diff --git a/Cargo.lock b/Cargo.lock index 9c43ec7af1..dea5209683 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,7 +108,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -119,7 +119,7 @@ version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a265e3abeffdce30b2e26b7a11b222fe37c6067404001b434101457d0385eb92" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -220,9 +220,9 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "bincode" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" dependencies = [ "byteorder", "serde", @@ -244,7 +244,7 @@ dependencies = [ "lazycell", "log 0.4.8", "peeking_take_while", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "regex", "rustc-hash", @@ -415,24 +415,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "cbindgen" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "104ca409bbff8293739438c71820a2606111b5f8f81835536dc673dfd807369e" -dependencies = [ - "clap", - "heck", - "log 0.4.8", - "proc-macro2 1.0.18", - "quote 1.0.7", - "serde", - "serde_json", - "syn 1.0.33", - "tempfile", - "toml", -] - [[package]] name = "cc" version = "1.0.49" @@ -730,6 +712,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derivative" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" +dependencies = [ + "proc-macro2 1.0.19", + "quote 1.0.7", + "syn 1.0.33", +] + [[package]] name = "dialoguer" version = "0.6.2" @@ -887,7 +880,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -921,7 +914,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", "synstructure", @@ -1092,7 +1085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -1292,15 +1285,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "heck" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "hermit-abi" version = "0.1.14" @@ -1710,7 +1694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fadf6945e227246825a583514534d864554e9f23d80b3c77d034b10983db5ef" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -2119,7 +2103,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -2153,6 +2137,28 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066" +dependencies = [ + "derivative", + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e" +dependencies = [ + "proc-macro-crate", + "proc-macro2 1.0.19", + "quote 1.0.7", + "syn 1.0.33", +] + [[package]] name = "number_prefix" version = "0.3.0" @@ -2338,7 +2344,7 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -2437,9 +2443,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid 0.2.0", ] @@ -2462,7 +2468,7 @@ checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" dependencies = [ "anyhow", "itertools 0.8.2", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -2498,7 +2504,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", ] [[package]] @@ -2908,7 +2914,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9bdc5e856e51e685846fb6c13a1f5e5432946c2c90501bdc76a1319f19e29da" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -2971,7 +2977,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -3058,16 +3064,16 @@ version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] [[package]] name = "serde_json" -version = "1.0.55" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "itoa", "ryu", @@ -3115,7 +3121,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d08338d8024b227c62bd68a12c7c9883f5c66780abaef15c550dc56f46ee6515" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -3594,9 +3600,7 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610ba71932d0bf4abf88eabb081ee43fa1ee6bb5137c4fa6776ea9dd8630ca5c" +version = "1.2.27" dependencies = [ "backtrace", "bytes 0.4.12", @@ -3619,7 +3623,9 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.2.27" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60a268f63ce5ccc4e7283077cc5c867764759f00fa4241ca58deaa74a29bd01" dependencies = [ "backtrace", "bytes 0.4.12", @@ -3942,9 +3948,7 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc703cb2807e9d713f70df32ac8c3a7a9c8af437dd0d468b1b77cfd8e8b4cbc8" +version = "1.2.27" dependencies = [ "env_logger", "lazy_static", @@ -3953,7 +3957,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.2.27" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79e1cece7027026b97a1aa87aeddaefd3241aad5159d8b1a63c0bc11d33576d" dependencies = [ "env_logger", "lazy_static", @@ -4170,43 +4176,6 @@ dependencies = [ "serde", ] -[[package]] -name = "solana-sdk" -version = "1.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a556c1b456609b760ff47b933912f27563ea8a9a1692864cbc1014c02f5b981e" -dependencies = [ - "assert_matches", - "bincode", - "bs58", - "bv", - "byteorder", - "chrono", - "ed25519-dalek", - "generic-array 0.14.3", - "hex", - "hmac", - "itertools 0.9.0", - "log 0.4.8", - "memmap", - "num-derive 0.3.0", - "num-traits", - "pbkdf2", - "rand 0.7.3", - "rand_chacha 0.2.2", - "rustc_version", - "rustversion", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "sha2", - "solana-crate-features 1.2.17", - "solana-logger 1.2.17", - "solana-sdk-macro 1.2.17", - "thiserror", -] - [[package]] name = "solana-sdk" version = "1.2.27" @@ -4245,16 +4214,42 @@ dependencies = [ ] [[package]] -name = "solana-sdk-macro" -version = "1.2.17" +name = "solana-sdk" +version = "1.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc386020de692562a29c0696a71c14a3d94455a9a785a97c7b254c38d6a2c8" +checksum = "0cd7695b4a6ded0b3610a109dca3bd34f272fccf4f143864a30634658f5a7e68" dependencies = [ + "assert_matches", + "bincode", "bs58", - "proc-macro2 1.0.18", - "quote 1.0.7", + "bv", + "byteorder", + "chrono", + "curve25519-dalek", + "ed25519-dalek", + "generic-array 0.14.3", + "hex", + "hmac", + "itertools 0.9.0", + "log 0.4.8", + "memmap", + "num-derive 0.3.0", + "num-traits", + "pbkdf2", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rustc_version", "rustversion", - "syn 1.0.33", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2", + "solana-crate-features 1.3.5", + "solana-logger 1.3.5", + "solana-sdk-macro 1.3.5", + "solana-sdk-macro-frozen-abi", + "thiserror", ] [[package]] @@ -4262,12 +4257,38 @@ name = "solana-sdk-macro" version = "1.2.27" dependencies = [ "bs58", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "rustversion", "syn 1.0.33", ] +[[package]] +name = "solana-sdk-macro" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0d2d378b5563e04e56fc22f92164d1ba78a43d244b77ec054f564290ae8469" +dependencies = [ + "bs58", + "proc-macro2 1.0.19", + "quote 1.0.7", + "rustversion", + "syn 1.0.33", +] + +[[package]] +name = "solana-sdk-macro-frozen-abi" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9b012fab0634311c8b6176ee1d6874a39f7b0bad8b647fe2cf36f687151728" +dependencies = [ + "lazy_static", + "proc-macro2 1.0.19", + "quote 1.0.7", + "rustc_version", + "syn 1.0.33", +] + [[package]] name = "solana-stake-accounts" version = "1.2.27" @@ -4586,20 +4607,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b303bab17e0c696de6d7550ba6f05a5a6dbf5c5d1597e68a4592899072e1c07a" dependencies = [ - "solana-sdk 1.2.17", + "solana-sdk 1.3.5", ] [[package]] name = "spl-token" -version = "1.0.8" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8bee8b59279b46d0627490b544c3bc38e440ff4da9851a34a26ab0a24bfe7d" +checksum = "89ee48031d5b189a9da7295076ba07bf0ccd407e0fee1279281fb2c3258fa9fb" dependencies = [ - "cbindgen", + "arrayref", "num-derive 0.3.0", "num-traits", + "num_enum", "remove_dir_all", - "solana-sdk 1.2.17", + "solana-sdk 1.3.5", "thiserror", ] @@ -4632,7 +4654,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "serde", "serde_derive", @@ -4646,7 +4668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "serde", "serde_derive", @@ -4711,7 +4733,7 @@ version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "unicode-xid 0.2.0", ] @@ -4722,7 +4744,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", "unicode-xid 0.2.0", @@ -4844,7 +4866,7 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -4906,7 +4928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "standback", "syn 1.0.33", @@ -5052,7 +5074,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -5457,7 +5479,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", ] @@ -5576,12 +5598,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" - [[package]] name = "unicode-width" version = "0.1.7" @@ -5751,7 +5767,7 @@ dependencies = [ "bumpalo", "lazy_static", "log 0.4.8", - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", "wasm-bindgen-shared", @@ -5785,7 +5801,7 @@ version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", "wasm-bindgen-backend", @@ -5990,7 +6006,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" dependencies = [ - "proc-macro2 1.0.18", + "proc-macro2 1.0.19", "quote 1.0.7", "syn 1.0.33", "synstructure", diff --git a/account-decoder/Cargo.toml b/account-decoder/Cargo.toml index fd0c30c5fa..f9a9cc8220 100644 --- a/account-decoder/Cargo.toml +++ b/account-decoder/Cargo.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" base64 = "0.12.3" bs58 = "0.3.1" bv = "0.11.1" @@ -22,7 +22,7 @@ solana-config-program = { path = "../programs/config", version = "1.2.27" } solana-sdk = { path = "../sdk", version = "1.2.27" } solana-stake-program = { path = "../programs/stake", version = "1.2.27" } solana-vote-program = { path = "../programs/vote", version = "1.2.27" } -spl-token-v1-0 = { package = "spl-token", version = "1.0.8", features = ["skip-no-mangle"] } +spl-token-v2-0 = { package = "spl-token", version = "2.0.1", features = ["skip-no-mangle"] } thiserror = "1.0" [package.metadata.docs.rs] diff --git a/account-decoder/src/parse_account_data.rs b/account-decoder/src/parse_account_data.rs index 8f92cda547..a9f4aedf99 100644 --- a/account-decoder/src/parse_account_data.rs +++ b/account-decoder/src/parse_account_data.rs @@ -3,7 +3,7 @@ use crate::{ parse_nonce::parse_nonce, parse_stake::parse_stake, parse_sysvar::parse_sysvar, - parse_token::{parse_token, spl_token_id_v1_0}, + parse_token::{parse_token, spl_token_id_v2_0}, parse_vote::parse_vote, }; use inflector::Inflector; @@ -17,7 +17,7 @@ lazy_static! { static ref STAKE_PROGRAM_ID: Pubkey = solana_stake_program::id(); static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id(); static ref SYSVAR_PROGRAM_ID: Pubkey = sysvar::id(); - static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v1_0(); + static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v2_0(); static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id(); pub static ref PARSABLE_PROGRAM_IDS: HashMap = { let mut m = HashMap::new(); diff --git a/account-decoder/src/parse_token.rs b/account-decoder/src/parse_token.rs index 459846835d..e3f890470d 100644 --- a/account-decoder/src/parse_token.rs +++ b/account-decoder/src/parse_token.rs @@ -3,32 +3,32 @@ use crate::{ StringAmount, }; use solana_sdk::pubkey::Pubkey; -use spl_token_v1_0::{ +use spl_token_v2_0::{ option::COption, + pack::Pack, solana_sdk::pubkey::Pubkey as SplTokenPubkey, - state::{unpack, Account, Mint, Multisig}, + state::{Account, AccountState, Mint, Multisig}, }; use std::{mem::size_of, str::FromStr}; -// A helper function to convert spl_token_v1_0::id() as spl_sdk::pubkey::Pubkey to +// A helper function to convert spl_token_v2_0::id() as spl_sdk::pubkey::Pubkey to // solana_sdk::pubkey::Pubkey -pub fn spl_token_id_v1_0() -> Pubkey { - Pubkey::from_str(&spl_token_v1_0::id().to_string()).unwrap() +pub fn spl_token_id_v2_0() -> Pubkey { + Pubkey::from_str(&spl_token_v2_0::id().to_string()).unwrap() } -// A helper function to convert spl_token_v1_0::native_mint::id() as spl_sdk::pubkey::Pubkey to +// A helper function to convert spl_token_v2_0::native_mint::id() as spl_sdk::pubkey::Pubkey to // solana_sdk::pubkey::Pubkey -pub fn spl_token_v1_0_native_mint() -> Pubkey { - Pubkey::from_str(&spl_token_v1_0::native_mint::id().to_string()).unwrap() +pub fn spl_token_v2_0_native_mint() -> Pubkey { + Pubkey::from_str(&spl_token_v2_0::native_mint::id().to_string()).unwrap() } pub fn parse_token( data: &[u8], mint_decimals: Option, ) -> Result { - let mut data = data.to_vec(); if data.len() == size_of::() { - let account: Account = *unpack(&mut data) + let account = Account::unpack(data) .map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?; let decimals = mint_decimals.ok_or_else(|| { ParseAccountError::AdditionalDataMissing( @@ -43,8 +43,12 @@ pub fn parse_token( COption::Some(pubkey) => Some(pubkey.to_string()), COption::None => None, }, - is_initialized: account.is_initialized, - is_native: account.is_native, + state: account.state.into(), + is_native: account.is_native(), + rent_exempt_reserve: match account.is_native { + COption::Some(reserve) => Some(token_amount_to_ui_amount(reserve, decimals)), + COption::None => None, + }, delegated_amount: if account.delegate.is_none() { None } else { @@ -53,20 +57,29 @@ pub fn parse_token( decimals, )) }, - })) - } else if data.len() == size_of::() { - let mint: Mint = *unpack(&mut data) - .map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?; - Ok(TokenAccountType::Mint(UiMint { - owner: match mint.owner { + close_authority: match account.close_authority { COption::Some(pubkey) => Some(pubkey.to_string()), COption::None => None, }, + })) + } else if data.len() == size_of::() { + let mint = Mint::unpack(data) + .map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?; + Ok(TokenAccountType::Mint(UiMint { + mint_authority: match mint.mint_authority { + COption::Some(pubkey) => Some(pubkey.to_string()), + COption::None => None, + }, + supply: mint.supply.to_string(), decimals: mint.decimals, is_initialized: mint.is_initialized, + freeze_authority: match mint.freeze_authority { + COption::Some(pubkey) => Some(pubkey.to_string()), + COption::None => None, + }, })) } else if data.len() == size_of::() { - let multisig: Multisig = *unpack(&mut data) + let multisig = Multisig::unpack(data) .map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?; Ok(TokenAccountType::Multisig(UiMultisig { num_required_signers: multisig.m, @@ -107,10 +120,32 @@ pub struct UiTokenAccount { pub token_amount: UiTokenAmount, #[serde(skip_serializing_if = "Option::is_none")] pub delegate: Option, - pub is_initialized: bool, + pub state: UiAccountState, pub is_native: bool, #[serde(skip_serializing_if = "Option::is_none")] + pub rent_exempt_reserve: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub delegated_amount: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub close_authority: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] +pub enum UiAccountState { + Uninitialized, + Initialized, + Frozen, +} + +impl From for UiAccountState { + fn from(state: AccountState) -> Self { + match state { + AccountState::Uninitialized => UiAccountState::Uninitialized, + AccountState::Initialized => UiAccountState::Initialized, + AccountState::Frozen => UiAccountState::Frozen, + } + } } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] @@ -134,9 +169,11 @@ pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount { #[derive(Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct UiMint { - pub owner: Option, + pub mint_authority: Option, + pub supply: StringAmount, pub decimals: u8, pub is_initialized: bool, + pub freeze_authority: Option, } #[derive(Debug, Serialize, Deserialize, PartialEq)] @@ -159,18 +196,23 @@ pub fn get_token_account_mint(data: &[u8]) -> Option { #[cfg(test)] mod test { use super::*; - use spl_token_v1_0::state::unpack_unchecked; #[test] fn test_parse_token() { let mint_pubkey = SplTokenPubkey::new(&[2; 32]); let owner_pubkey = SplTokenPubkey::new(&[3; 32]); let mut account_data = [0; size_of::()]; - let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap(); - account.mint = mint_pubkey; - account.owner = owner_pubkey; - account.amount = 42; - account.is_initialized = true; + Account::unpack_unchecked_mut(&mut account_data, &mut |account: &mut Account| { + account.mint = mint_pubkey; + account.owner = owner_pubkey; + account.amount = 42; + account.state = AccountState::Initialized; + account.is_native = COption::None; + account.close_authority = COption::Some(owner_pubkey); + Ok(()) + }) + .unwrap(); + assert!(parse_token(&account_data, None).is_err()); assert_eq!( parse_token(&account_data, Some(2)).unwrap(), @@ -183,23 +225,33 @@ mod test { amount: "42".to_string() }, delegate: None, - is_initialized: true, + state: UiAccountState::Initialized, is_native: false, + rent_exempt_reserve: None, delegated_amount: None, + close_authority: Some(owner_pubkey.to_string()), }), ); let mut mint_data = [0; size_of::()]; - let mut mint: &mut Mint = unpack_unchecked(&mut mint_data).unwrap(); - mint.owner = COption::Some(owner_pubkey); - mint.decimals = 3; - mint.is_initialized = true; + Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| { + mint.mint_authority = COption::Some(owner_pubkey); + mint.supply = 42; + mint.decimals = 3; + mint.is_initialized = true; + mint.freeze_authority = COption::Some(owner_pubkey); + Ok(()) + }) + .unwrap(); + assert_eq!( parse_token(&mint_data, None).unwrap(), TokenAccountType::Mint(UiMint { - owner: Some(owner_pubkey.to_string()), + mint_authority: Some(owner_pubkey.to_string()), + supply: 42.to_string(), decimals: 3, is_initialized: true, + freeze_authority: Some(owner_pubkey.to_string()), }), ); @@ -207,15 +259,18 @@ mod test { let signer2 = SplTokenPubkey::new(&[2; 32]); let signer3 = SplTokenPubkey::new(&[3; 32]); let mut multisig_data = [0; size_of::()]; - let mut multisig: &mut Multisig = unpack_unchecked(&mut multisig_data).unwrap(); let mut signers = [SplTokenPubkey::default(); 11]; signers[0] = signer1; signers[1] = signer2; signers[2] = signer3; - multisig.m = 2; - multisig.n = 3; - multisig.is_initialized = true; - multisig.signers = signers; + Multisig::unpack_unchecked_mut(&mut multisig_data, &mut |multisig: &mut Multisig| { + multisig.m = 2; + multisig.n = 3; + multisig.is_initialized = true; + multisig.signers = signers; + Ok(()) + }) + .unwrap(); assert_eq!( parse_token(&multisig_data, None).unwrap(), TokenAccountType::Multisig(UiMultisig { @@ -238,8 +293,11 @@ mod test { fn test_get_token_account_mint() { let mint_pubkey = SplTokenPubkey::new(&[2; 32]); let mut account_data = [0; size_of::()]; - let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap(); - account.mint = mint_pubkey; + Account::unpack_unchecked_mut(&mut account_data, &mut |account: &mut Account| { + account.mint = mint_pubkey; + Ok(()) + }) + .unwrap(); let expected_mint_pubkey = Pubkey::new(&[2; 32]); assert_eq!( diff --git a/bench-tps/Cargo.toml b/bench-tps/Cargo.toml index d232db6c5d..8943afd43a 100644 --- a/bench-tps/Cargo.toml +++ b/bench-tps/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" homepage = "https://solana.com/" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" clap = "2.33.1" log = "0.4.8" rayon = "1.3.0" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 070fa64385..406b65b9f7 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" homepage = "https://solana.com/" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" bs58 = "0.3.1" chrono = { version = "0.4.11", features = ["serde"] } clap = "2.33.1" diff --git a/client/Cargo.toml b/client/Cargo.toml index dce1941d79..87f1e783a0 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" bs58 = "0.3.1" indicatif = "0.14.0" jsonrpc-core = "14.1.0" diff --git a/core/Cargo.toml b/core/Cargo.toml index 056b5aae66..cbae50f242 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" codecov = { repository = "solana-labs/solana", branch = "master", service = "github" } [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" bv = { version = "0.11.1", features = ["serde"] } bs58 = "0.3.1" byteorder = "1.3.4" @@ -67,7 +67,7 @@ solana-version = { path = "../version", version = "1.2.27" } solana-vote-program = { path = "../programs/vote", version = "1.2.27" } solana-vote-signer = { path = "../vote-signer", version = "1.2.27" } solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.27" } -spl-token-v1-0 = { package = "spl-token", version = "1.0.8", features = ["skip-no-mangle"] } +spl-token-v2-0 = { package = "spl-token", version = "2.0.1", features = ["skip-no-mangle"] } tempfile = "3.1.0" thiserror = "1.0" tokio = { version = "0.2.22", features = ["full"] } diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 1a78803e2b..d9dedd509b 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -10,13 +10,13 @@ use crate::{ send_transaction_service::SendTransactionService, validator::ValidatorExit, }; -use bincode::serialize; +use bincode::{config::Options, serialize}; use jsonrpc_core::{types::error, Error, Metadata, Result}; use jsonrpc_derive::rpc; use solana_account_decoder::{ parse_account_data::AccountAdditionalData, parse_token::{ - get_token_account_mint, spl_token_id_v1_0, spl_token_v1_0_native_mint, + get_token_account_mint, spl_token_id_v2_0, spl_token_v2_0_native_mint, token_amount_to_ui_amount, UiTokenAmount, }, UiAccount, UiAccountEncoding, @@ -59,7 +59,10 @@ use solana_transaction_status::{ ConfirmedBlock, ConfirmedTransaction, TransactionStatus, UiTransactionEncoding, }; use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY}; -use spl_token_v1_0::state::{Account as TokenAccount, Mint}; +use spl_token_v2_0::{ + pack::Pack, + state::{Account as TokenAccount, Mint}, +}; use std::{ cmp::{max, min}, collections::{HashMap, HashSet}, @@ -194,7 +197,7 @@ impl JsonRpcRequestProcessor { check_slice_and_encoding(&encoding, config.data_slice.is_some())?; let mut response = None; if let Some(account) = bank.get_account(pubkey) { - if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { + if account.owner == spl_token_id_v2_0() && encoding == UiAccountEncoding::JsonParsed { response = Some(get_parsed_token_account(bank.clone(), pubkey, account)); } else if (encoding == UiAccountEncoding::Binary || encoding == UiAccountEncoding::Base58) @@ -243,7 +246,7 @@ impl JsonRpcRequestProcessor { check_slice_and_encoding(&encoding, data_slice_config.is_some())?; let keyed_accounts = get_filtered_program_accounts(&bank, program_id, filters); let result = - if program_id == &spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { + if program_id == &spl_token_id_v2_0() && encoding == UiAccountEncoding::JsonParsed { get_parsed_token_accounts(bank, keyed_accounts).collect() } else { keyed_accounts @@ -975,16 +978,14 @@ impl JsonRpcRequestProcessor { Error::invalid_params("Invalid param: could not find account".to_string()) })?; - if account.owner != spl_token_id_v1_0() { + if account.owner != spl_token_id_v2_0() { return Err(Error::invalid_params( - "Invalid param: not a v1.0 Token account".to_string(), + "Invalid param: not a v2.0 Token account".to_string(), )); } - let mut data = account.data.to_vec(); - let token_account = - spl_token_v1_0::state::unpack::(&mut data).map_err(|_| { - Error::invalid_params("Invalid param: not a v1.0 Token account".to_string()) - })?; + let token_account = TokenAccount::unpack(&account.data).map_err(|_| { + Error::invalid_params("Invalid param: not a v2.0 Token account".to_string()) + })?; let mint = &Pubkey::from_str(&token_account.mint.to_string()) .expect("Token account mint should be convertible to Pubkey"); let (_, decimals) = get_mint_owner_and_decimals(&bank, &mint)?; @@ -998,32 +999,19 @@ impl JsonRpcRequestProcessor { commitment: Option, ) -> Result> { let bank = self.bank(commitment)?; - let (mint_owner, decimals) = get_mint_owner_and_decimals(&bank, mint)?; - if mint_owner != spl_token_id_v1_0() { + let mint_account = bank.get_account(mint).ok_or_else(|| { + Error::invalid_params("Invalid param: could not find account".to_string()) + })?; + if mint_account.owner != spl_token_id_v2_0() { return Err(Error::invalid_params( - "Invalid param: not a v1.0 Token mint".to_string(), + "Invalid param: not a v2.0 Token mint".to_string(), )); } + let mint = Mint::unpack(&mint_account.data).map_err(|_| { + Error::invalid_params("Invalid param: mint could not be unpacked".to_string()) + })?; - let filters = vec![ - // Filter on Mint address - RpcFilterType::Memcmp(Memcmp { - offset: 0, - bytes: MemcmpEncodedBytes::Binary(mint.to_string()), - encoding: None, - }), - // Filter on Token Account state - RpcFilterType::DataSize(size_of::() as u64), - ]; - let supply = get_filtered_program_accounts(&bank, &mint_owner, filters) - .map(|(_pubkey, account)| { - let mut data = account.data.to_vec(); - spl_token_v1_0::state::unpack(&mut data) - .map(|account: &mut TokenAccount| account.amount) - .unwrap_or(0) - }) - .sum(); - let supply = token_amount_to_ui_amount(supply, decimals); + let supply = token_amount_to_ui_amount(mint.supply, mint.decimals); new_response(&bank, supply) } @@ -1034,9 +1022,9 @@ impl JsonRpcRequestProcessor { ) -> Result>> { let bank = self.bank(commitment)?; let (mint_owner, decimals) = get_mint_owner_and_decimals(&bank, mint)?; - if mint_owner != spl_token_id_v1_0() { + if mint_owner != spl_token_id_v2_0() { return Err(Error::invalid_params( - "Invalid param: not a v1.0 Token mint".to_string(), + "Invalid param: not a v2.0 Token mint".to_string(), )); } let filters = vec![ @@ -1052,9 +1040,8 @@ impl JsonRpcRequestProcessor { let mut token_balances: Vec = get_filtered_program_accounts(&bank, &mint_owner, filters) .map(|(address, account)| { - let mut data = account.data.to_vec(); - let amount = spl_token_v1_0::state::unpack(&mut data) - .map(|account: &mut TokenAccount| account.amount) + let amount = TokenAccount::unpack(&account.data) + .map(|account| account.amount) .unwrap_or(0); let amount = token_amount_to_ui_amount(amount, decimals); RpcTokenAccountBalance { @@ -1341,15 +1328,15 @@ fn get_token_program_id_and_mint( match token_account_filter { TokenAccountsFilter::Mint(mint) => { let (mint_owner, _) = get_mint_owner_and_decimals(&bank, &mint)?; - if mint_owner != spl_token_id_v1_0() { + if mint_owner != spl_token_id_v2_0() { return Err(Error::invalid_params( - "Invalid param: not a v1.0 Token mint".to_string(), + "Invalid param: not a v2.0 Token mint".to_string(), )); } Ok((mint_owner, Some(mint))) } TokenAccountsFilter::ProgramId(program_id) => { - if program_id == spl_token_id_v1_0() { + if program_id == spl_token_id_v2_0() { Ok((program_id, None)) } else { Err(Error::invalid_params( @@ -1363,8 +1350,8 @@ fn get_token_program_id_and_mint( /// Analyze a mint Pubkey that may be the native_mint and get the mint-account owner (token /// program_id) and decimals fn get_mint_owner_and_decimals(bank: &Arc, mint: &Pubkey) -> Result<(Pubkey, u8)> { - if mint == &spl_token_v1_0_native_mint() { - Ok((spl_token_id_v1_0(), spl_token_v1_0::native_mint::DECIMALS)) + if mint == &spl_token_v2_0_native_mint() { + Ok((spl_token_id_v2_0(), spl_token_v2_0::native_mint::DECIMALS)) } else { let mint_account = bank.get_account(mint).ok_or_else(|| { Error::invalid_params("Invalid param: could not find mint".to_string()) @@ -1375,12 +1362,11 @@ fn get_mint_owner_and_decimals(bank: &Arc, mint: &Pubkey) -> Result<(Pubke } fn get_mint_decimals(data: &[u8]) -> Result { - let mut data = data.to_vec(); - spl_token_v1_0::state::unpack(&mut data) + Mint::unpack(data) .map_err(|_| { Error::invalid_params("Invalid param: Token mint could not be unpacked".to_string()) }) - .map(|mint: &mut Mint| mint.decimals) + .map(|mint| mint.decimals) } #[rpc] @@ -1665,7 +1651,7 @@ pub trait RpcSol { ) -> Result; // SPL Token-specific RPC endpoints - // See https://github.com/solana-labs/solana-program-library/releases/tag/token-v1.0.0 for + // See https://github.com/solana-labs/solana-program-library/releases/tag/token-v2.0.0 for // program details #[rpc(meta, name = "getTokenAccountBalance")] @@ -2420,9 +2406,11 @@ fn deserialize_bs58_transaction(bs58_transaction: String) -> Result<(Vec, Tr info!("{}", err); return Err(Error::invalid_params(&err)); } - bincode::config() - .limit(PACKET_DATA_SIZE as u64) - .deserialize(&wire_transaction) + bincode::options() + .with_limit(PACKET_DATA_SIZE as u64) + .with_fixint_encoding() + .allow_trailing_bytes() + .deserialize_from(&wire_transaction[..]) .map_err(|err| { info!("transaction deserialize error: {:?}", err); Error::invalid_params(&err.to_string()) @@ -2467,8 +2455,9 @@ pub mod tests { vote_instruction, vote_state::{Vote, VoteInit, MAX_LOCKOUT_HISTORY}, }; - use spl_token_v1_0::{ - option::COption, solana_sdk::pubkey::Pubkey as SplTokenPubkey, state::Mint, + use spl_token_v2_0::{ + option::COption, solana_sdk::pubkey::Pubkey as SplTokenPubkey, + state::AccountState as TokenAccountState, state::Mint, }; use std::{ collections::HashMap, @@ -4686,24 +4675,27 @@ pub mod tests { let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand()); let mut account_data = [0; size_of::()]; - let account: &mut TokenAccount = - spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap(); let mint = SplTokenPubkey::new(&[2; 32]); let owner = SplTokenPubkey::new(&[3; 32]); let delegate = SplTokenPubkey::new(&[4; 32]); - *account = TokenAccount { - mint, - owner, - delegate: COption::Some(delegate), - amount: 420, - is_initialized: true, - is_native: false, - delegated_amount: 30, - }; + TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| { + *account = TokenAccount { + mint, + owner, + delegate: COption::Some(delegate), + amount: 420, + state: TokenAccountState::Initialized, + is_native: COption::None, + delegated_amount: 30, + close_authority: COption::Some(owner), + }; + Ok(()) + }) + .unwrap(); let token_account = Account { lamports: 111, data: account_data.to_vec(), - owner: spl_token_id_v1_0(), + owner: spl_token_id_v2_0(), ..Account::default() }; let token_account_pubkey = Pubkey::new_rand(); @@ -4711,17 +4703,21 @@ pub mod tests { // Add the mint let mut mint_data = [0; size_of::()]; - let mint_state: &mut Mint = - spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap(); - *mint_state = Mint { - owner: COption::Some(owner), - decimals: 2, - is_initialized: true, - }; + Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| { + *mint = Mint { + mint_authority: COption::Some(owner), + supply: 500, + decimals: 2, + is_initialized: true, + freeze_authority: COption::Some(owner), + }; + Ok(()) + }) + .unwrap(); let mint_account = Account { lamports: 111, data: mint_data.to_vec(), - owner: spl_token_id_v1_0(), + owner: spl_token_id_v2_0(), ..Account::default() }; bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account); @@ -4750,10 +4746,7 @@ pub mod tests { .expect("actual response deserialization"); assert!(result.get("error").is_some()); - // Add another token account to ensure getTokenSupply sums all mint accounts - let other_token_account_pubkey = Pubkey::new_rand(); - bank.store_account(&other_token_account_pubkey, &token_account); - + // Test get token supply, pulls supply from mint let req = format!( r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{}"]}}"#, mint, @@ -4764,8 +4757,8 @@ pub mod tests { let supply: UiTokenAmount = serde_json::from_value(result["result"]["value"].clone()).unwrap(); let error = f64::EPSILON; - assert!((supply.ui_amount - 2.0 * 4.2).abs() < error); - assert_eq!(supply.amount, (2 * 420).to_string()); + assert!((supply.ui_amount - 5.0).abs() < error); + assert_eq!(supply.amount, 500.to_string()); assert_eq!(supply.decimals, 2); // Test non-existent mint address @@ -4778,24 +4771,31 @@ pub mod tests { .expect("actual response deserialization"); assert!(result.get("error").is_some()); + // Add another token account with the same owner, delegate, and mint + let other_token_account_pubkey = Pubkey::new_rand(); + bank.store_account(&other_token_account_pubkey, &token_account); + // Add another token account with the same owner and delegate but different mint let mut account_data = [0; size_of::()]; - let account: &mut TokenAccount = - spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap(); let new_mint = SplTokenPubkey::new(&[5; 32]); - *account = TokenAccount { - mint: new_mint, - owner, - delegate: COption::Some(delegate), - amount: 42, - is_initialized: true, - is_native: false, - delegated_amount: 30, - }; + TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| { + *account = TokenAccount { + mint: new_mint, + owner, + delegate: COption::Some(delegate), + amount: 42, + state: TokenAccountState::Initialized, + is_native: COption::None, + delegated_amount: 30, + close_authority: COption::Some(owner), + }; + Ok(()) + }) + .unwrap(); let token_account = Account { lamports: 111, data: account_data.to_vec(), - owner: spl_token_id_v1_0(), + owner: spl_token_id_v2_0(), ..Account::default() }; let token_with_different_mint_pubkey = Pubkey::new_rand(); @@ -4810,7 +4810,7 @@ pub mod tests { "params":["{}", {{"programId": "{}"}}] }}"#, owner, - spl_token_id_v1_0(), + spl_token_id_v2_0(), ); let res = io.handle_request_sync(&req, meta.clone()); let result: Value = serde_json::from_str(&res.expect("actual response")) @@ -4828,7 +4828,7 @@ pub mod tests { "params":["{}", {{"programId": "{}"}}, {{"encoding": "jsonParsed"}}] }}"#, owner, - spl_token_id_v1_0(), + spl_token_id_v2_0(), ); let res = io.handle_request_sync(&req, meta.clone()); let result: Value = serde_json::from_str(&res.expect("actual response")) @@ -4892,7 +4892,7 @@ pub mod tests { "params":["{}", {{"programId": "{}"}}] }}"#, Pubkey::new_rand(), - spl_token_id_v1_0(), + spl_token_id_v2_0(), ); let res = io.handle_request_sync(&req, meta.clone()); let result: Value = serde_json::from_str(&res.expect("actual response")) @@ -4910,7 +4910,7 @@ pub mod tests { "params":["{}", {{"programId": "{}"}}] }}"#, delegate, - spl_token_id_v1_0(), + spl_token_id_v2_0(), ); let res = io.handle_request_sync(&req, meta.clone()); let result: Value = serde_json::from_str(&res.expect("actual response")) @@ -4975,7 +4975,7 @@ pub mod tests { "params":["{}", {{"programId": "{}"}}] }}"#, Pubkey::new_rand(), - spl_token_id_v1_0(), + spl_token_id_v2_0(), ); let res = io.handle_request_sync(&req, meta.clone()); let result: Value = serde_json::from_str(&res.expect("actual response")) @@ -4986,17 +4986,21 @@ pub mod tests { // Add new_mint, and another token account on new_mint with different balance let mut mint_data = [0; size_of::()]; - let mint_state: &mut Mint = - spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap(); - *mint_state = Mint { - owner: COption::Some(owner), - decimals: 2, - is_initialized: true, - }; + Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| { + *mint = Mint { + mint_authority: COption::Some(owner), + supply: 500, + decimals: 2, + is_initialized: true, + freeze_authority: COption::Some(owner), + }; + Ok(()) + }) + .unwrap(); let mint_account = Account { lamports: 111, data: mint_data.to_vec(), - owner: spl_token_id_v1_0(), + owner: spl_token_id_v2_0(), ..Account::default() }; bank.store_account( @@ -5004,21 +5008,24 @@ pub mod tests { &mint_account, ); let mut account_data = [0; size_of::()]; - let account: &mut TokenAccount = - spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap(); - *account = TokenAccount { - mint: new_mint, - owner, - delegate: COption::Some(delegate), - amount: 10, - is_initialized: true, - is_native: false, - delegated_amount: 30, - }; + TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| { + *account = TokenAccount { + mint: new_mint, + owner, + delegate: COption::Some(delegate), + amount: 10, + state: TokenAccountState::Initialized, + is_native: COption::None, + delegated_amount: 30, + close_authority: COption::Some(owner), + }; + Ok(()) + }) + .unwrap(); let token_account = Account { lamports: 111, data: account_data.to_vec(), - owner: spl_token_id_v1_0(), + owner: spl_token_id_v2_0(), ..Account::default() }; let token_with_smaller_balance = Pubkey::new_rand(); @@ -5062,24 +5069,27 @@ pub mod tests { let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand()); let mut account_data = [0; size_of::()]; - let account: &mut TokenAccount = - spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap(); let mint = SplTokenPubkey::new(&[2; 32]); let owner = SplTokenPubkey::new(&[3; 32]); let delegate = SplTokenPubkey::new(&[4; 32]); - *account = TokenAccount { - mint, - owner, - delegate: COption::Some(delegate), - amount: 420, - is_initialized: true, - is_native: false, - delegated_amount: 30, - }; + TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| { + *account = TokenAccount { + mint, + owner, + delegate: COption::Some(delegate), + amount: 420, + state: TokenAccountState::Initialized, + is_native: COption::Some(10), + delegated_amount: 30, + close_authority: COption::Some(owner), + }; + Ok(()) + }) + .unwrap(); let token_account = Account { lamports: 111, data: account_data.to_vec(), - owner: spl_token_id_v1_0(), + owner: spl_token_id_v2_0(), ..Account::default() }; let token_account_pubkey = Pubkey::new_rand(); @@ -5087,17 +5097,21 @@ pub mod tests { // Add the mint let mut mint_data = [0; size_of::()]; - let mint_state: &mut Mint = - spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap(); - *mint_state = Mint { - owner: COption::Some(owner), - decimals: 2, - is_initialized: true, - }; + Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| { + *mint = Mint { + mint_authority: COption::Some(owner), + supply: 500, + decimals: 2, + is_initialized: true, + freeze_authority: COption::Some(owner), + }; + Ok(()) + }) + .unwrap(); let mint_account = Account { lamports: 111, data: mint_data.to_vec(), - owner: spl_token_id_v1_0(), + owner: spl_token_id_v2_0(), ..Account::default() }; bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account); @@ -5113,7 +5127,7 @@ pub mod tests { result["result"]["value"]["data"], json!({ "program": "spl-token", - "space": 120, + "space": 176, "parsed": { "type": "account", "info": { @@ -5125,13 +5139,19 @@ pub mod tests { "amount": "420", }, "delegate": delegate.to_string(), - "isInitialized": true, - "isNative": false, + "state": "initialized", + "isNative": true, + "rentExemptReserve": { + "uiAmount": 0.1, + "decimals": 2, + "amount": "10", + }, "delegatedAmount": { "uiAmount": 0.3, "decimals": 2, "amount": "30", }, + "closeAuthority": owner.to_string(), } } }) @@ -5149,13 +5169,15 @@ pub mod tests { result["result"]["value"]["data"], json!({ "program": "spl-token", - "space": 40, + "space": 88, "parsed": { "type": "mint", "info": { - "owner": owner.to_string(), + "mintAuthority": owner.to_string(), "decimals": 2, + "supply": "500".to_string(), "isInitialized": true, + "freezeAuthority": owner.to_string(), } } }) diff --git a/core/src/rpc_subscriptions.rs b/core/src/rpc_subscriptions.rs index 8a92836695..b1b248983b 100644 --- a/core/src/rpc_subscriptions.rs +++ b/core/src/rpc_subscriptions.rs @@ -11,7 +11,7 @@ use jsonrpc_pubsub::{ SubscriptionId, }; use serde::Serialize; -use solana_account_decoder::{parse_token::spl_token_id_v1_0, UiAccount, UiAccountEncoding}; +use solana_account_decoder::{parse_token::spl_token_id_v2_0, UiAccount, UiAccountEncoding}; use solana_client::{ rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}, rpc_filter::RpcFilterType, @@ -266,7 +266,7 @@ fn filter_account_result( // and should notify that the account state has been reverted. if fork != last_notified_slot { let encoding = encoding.unwrap_or(UiAccountEncoding::Binary); - if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { + if account.owner == spl_token_id_v2_0() && encoding == UiAccountEncoding::JsonParsed { let bank = bank.unwrap(); // If result.is_some(), bank must also be Some return ( Box::new(iter::once(get_parsed_token_account(bank, pubkey, account))), diff --git a/dos/Cargo.toml b/dos/Cargo.toml index 2eda54d50e..9ce64cd658 100644 --- a/dos/Cargo.toml +++ b/dos/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" homepage = "https://solana.com/" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" clap = "2.33.1" log = "0.4.8" rand = "0.7.0" diff --git a/faucet/Cargo.toml b/faucet/Cargo.toml index 07f6d4c2b2..59389cb1a7 100644 --- a/faucet/Cargo.toml +++ b/faucet/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" byteorder = "1.3.4" bytes = "0.4" clap = "2.33" diff --git a/install/Cargo.toml b/install/Cargo.toml index 30cf673130..4ff79c1f4d 100644 --- a/install/Cargo.toml +++ b/install/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://solana.com/" [dependencies] atty = "0.2.11" -bincode = "1.2.1" +bincode = "1.3.1" bzip2 = "0.3.3" chrono = { version = "0.4.11", features = ["serde"] } clap = { version = "2.33.1" } diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index e585c8cdb5..4bcf4c5781 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" byteorder = "1.3.4" bzip2 = "0.3.3" chrono = { version = "0.4.11", features = ["serde"] } diff --git a/ledger/src/shred.rs b/ledger/src/shred.rs index 8a658ee5d3..dce30aae57 100644 --- a/ledger/src/shred.rs +++ b/ledger/src/shred.rs @@ -3,6 +3,7 @@ use crate::{ entry::{create_ticks, Entry}, erasure::Session, }; +use bincode::config::Options; use core::cell::RefCell; use rayon::{ iter::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator}, @@ -137,8 +138,10 @@ impl Shred { where T: Deserialize<'de>, { - let ret = bincode::config() - .limit(PACKET_DATA_SIZE as u64) + let ret = bincode::options() + .with_limit(PACKET_DATA_SIZE as u64) + .with_fixint_encoding() + .allow_trailing_bytes() .deserialize(&buf[*index..*index + size])?; *index += size; Ok(ret) diff --git a/ledger/src/snapshot_utils.rs b/ledger/src/snapshot_utils.rs index 443bfc821a..3d06bfaac5 100644 --- a/ledger/src/snapshot_utils.rs +++ b/ledger/src/snapshot_utils.rs @@ -1,7 +1,9 @@ -use crate::bank_forks::CompressionType; -use crate::hardened_unpack::{unpack_snapshot, UnpackError}; -use crate::snapshot_package::AccountsPackage; -use bincode::serialize_into; +use crate::{ + bank_forks::CompressionType, + hardened_unpack::{unpack_snapshot, UnpackError}, + snapshot_package::AccountsPackage, +}; +use bincode::{config::Options, serialize_into}; use bzip2::bufread::BzDecoder; use flate2::read::GzDecoder; use fs_extra::dir::CopyOptions; @@ -721,8 +723,10 @@ where info!("Loading bank from {:?}", &root_paths.snapshot_file_path); let bank = deserialize_snapshot_data_file(&root_paths.snapshot_file_path, |mut stream| { - let mut bank: Bank = bincode::config() - .limit(MAX_SNAPSHOT_DATA_FILE_SIZE) + let mut bank: Bank = bincode::options() + .with_limit(MAX_SNAPSHOT_DATA_FILE_SIZE) + .with_fixint_encoding() + .allow_trailing_bytes() .deserialize_from(&mut stream)?; info!("Rebuilding accounts..."); @@ -757,8 +761,10 @@ where let status_cache_path = unpacked_snapshots_dir.join(SNAPSHOT_STATUS_CACHE_FILE_NAME); let slot_deltas = deserialize_snapshot_data_file(&status_cache_path, |stream| { info!("Rebuilding status cache..."); - let slot_deltas: Vec = bincode::config() - .limit(MAX_SNAPSHOT_DATA_FILE_SIZE) + let slot_deltas: Vec = bincode::options() + .with_limit(MAX_SNAPSHOT_DATA_FILE_SIZE) + .with_fixint_encoding() + .allow_trailing_bytes() .deserialize_from(stream)?; Ok(slot_deltas) })?; diff --git a/net-utils/Cargo.toml b/net-utils/Cargo.toml index 202a54308a..e907f3820b 100644 --- a/net-utils/Cargo.toml +++ b/net-utils/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" bytes = "0.4" clap = "2.33.1" log = "0.4.8" diff --git a/perf/Cargo.toml b/perf/Cargo.toml index 1b713c9c49..af7146e26a 100644 --- a/perf/Cargo.toml +++ b/perf/Cargo.toml @@ -11,7 +11,7 @@ edition = "2018" [dependencies] rand = "0.7.0" dlopen = "0.1.8" -bincode = "1.2.1" +bincode = "1.3.1" rayon = "1.3.0" serde = "1.0.110" dlopen_derive = "0.1.4" diff --git a/perf/src/packet.rs b/perf/src/packet.rs index d62e274782..981bb756f5 100644 --- a/perf/src/packet.rs +++ b/perf/src/packet.rs @@ -1,5 +1,6 @@ //! The `packet` module defines data structures and methods to pull data from the network. use crate::{cuda_runtime::PinnedVec, recycler::Recycler}; +use bincode::config::Options; use serde::Serialize; pub use solana_sdk::packet::{Meta, Packet, PACKET_DATA_SIZE}; use std::net::SocketAddr; @@ -100,9 +101,11 @@ pub fn limited_deserialize(data: &[u8]) -> bincode::Result where T: serde::de::DeserializeOwned, { - bincode::config() - .limit(PACKET_DATA_SIZE as u64) - .deserialize(data) + bincode::options() + .with_limit(PACKET_DATA_SIZE as u64) + .with_fixint_encoding() + .allow_trailing_bytes() + .deserialize_from(data) } #[cfg(test)] diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 3fbab17625..0e91c5460f 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -82,9 +82,9 @@ checksum = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67" [[package]] name = "bincode" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" dependencies = [ "byteorder 1.3.4", "serde", diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index 60ebef8508..fb784c1a27 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" byteorder = "1.3.4" jemalloc-sys = { version = "0.3.2", features = ["disable_initial_exec_tls"] } num-derive = { version = "0.3" } diff --git a/programs/btc_spv/Cargo.toml b/programs/btc_spv/Cargo.toml index 79c24ee2cc..b4709c514b 100644 --- a/programs/btc_spv/Cargo.toml +++ b/programs/btc_spv/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" log = "0.4.2" num-derive = "0.3" num-traits = "0.2" diff --git a/programs/budget/Cargo.toml b/programs/budget/Cargo.toml index 2a261ee63a..b482b71ceb 100644 --- a/programs/budget/Cargo.toml +++ b/programs/budget/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" chrono = { version = "0.4.11", features = ["serde"] } log = "0.4.8" num-derive = "0.3" diff --git a/programs/config/Cargo.toml b/programs/config/Cargo.toml index cfed2913f3..1240f45789 100644 --- a/programs/config/Cargo.toml +++ b/programs/config/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" chrono = { version = "0.4.11", features = ["serde"] } log = "0.4.8" serde = "1.0.110" diff --git a/programs/exchange/Cargo.toml b/programs/exchange/Cargo.toml index b3983e4564..8efdcbb882 100644 --- a/programs/exchange/Cargo.toml +++ b/programs/exchange/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" log = "0.4.8" num-derive = { version = "0.3" } num-traits = { version = "0.2" } diff --git a/programs/ownable/Cargo.toml b/programs/ownable/Cargo.toml index 7981c893b0..018754bde0 100644 --- a/programs/ownable/Cargo.toml +++ b/programs/ownable/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" solana-sdk = { path = "../../sdk", version = "1.2.27" } num-derive = "0.3" num-traits = "0.2" diff --git a/programs/stake/Cargo.toml b/programs/stake/Cargo.toml index 7c380106bd..1baf40b232 100644 --- a/programs/stake/Cargo.toml +++ b/programs/stake/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" log = "0.4.8" num-derive = "0.3" num-traits = "0.2" diff --git a/programs/vest/Cargo.toml b/programs/vest/Cargo.toml index aff5c49424..069fbd9d34 100644 --- a/programs/vest/Cargo.toml +++ b/programs/vest/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" chrono = { version = "0.4.11", features = ["serde"] } num-derive = "0.2" num-traits = "0.2" diff --git a/programs/vote/Cargo.toml b/programs/vote/Cargo.toml index 62b6d8b056..11b9349d4c 100644 --- a/programs/vote/Cargo.toml +++ b/programs/vote/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" log = "0.4.8" num-derive = "0.3" num-traits = "0.2" diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index b2a750dd38..fb08cc6ef9 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.2.1" +bincode = "1.3.1" bv = { version = "0.11.1", features = ["serde"] } byteorder = "1.3.4" fnv = "1.0.7" diff --git a/runtime/src/serde_snapshot/legacy.rs b/runtime/src/serde_snapshot/legacy.rs index 8277a078c6..0884455703 100644 --- a/runtime/src/serde_snapshot/legacy.rs +++ b/runtime/src/serde_snapshot/legacy.rs @@ -1,4 +1,4 @@ -use {super::*, solana_measure::measure::Measure, std::cell::RefCell}; +use {super::*, bincode::config::Options, solana_measure::measure::Measure, std::cell::RefCell}; // Serializable version of AccountStorageEntry for snapshot format #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] @@ -189,8 +189,10 @@ impl<'a> TypeContext<'a> for Context { ); // (1st of 3 elements) read in map of slots to account storage entries - let storage: HashMap> = bincode::config() - .limit(serialized_len) + let storage: HashMap> = bincode::options() + .with_limit(serialized_len) + .with_fixint_encoding() + .allow_trailing_bytes() .deserialize_from(&mut stream) .map_err(accountsdb_to_io_error)?; diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 13e9a3af89..ee46df5eca 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -31,7 +31,7 @@ default = [ [dependencies] assert_matches = { version = "1.3.0", optional = true } -bincode = "1.2.1" +bincode = "1.3.1" bs58 = "0.3.1" bv = { version = "0.11.1", features = ["serde"] } byteorder = { version = "1.3.4", optional = true } diff --git a/sdk/src/program_utils.rs b/sdk/src/program_utils.rs index 979a18beeb..cfe8033479 100644 --- a/sdk/src/program_utils.rs +++ b/sdk/src/program_utils.rs @@ -1,4 +1,5 @@ use crate::instruction::InstructionError; +use bincode::config::Options; /// Deserialize with a limit based the maximum amount of data a program can expect to get. /// This function should be used in place of direct deserialization to help prevent OOM errors @@ -7,8 +8,31 @@ where T: serde::de::DeserializeOwned, { let limit = crate::packet::PACKET_DATA_SIZE as u64; - bincode::config() - .limit(limit) - .deserialize(instruction_data) + bincode::options() + .with_limit(limit) + .with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed + .allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method + .deserialize_from(instruction_data) .map_err(|_| InstructionError::InvalidInstructionData) } + +#[cfg(test)] +pub mod tests { + use super::*; + + #[test] + fn test_limited_deserialize() { + #[derive(Deserialize, Serialize)] + enum Foo { + Bar(Vec), + } + + let item = Foo::Bar([1; crate::packet::PACKET_DATA_SIZE - 12].to_vec()); // crate::packet::PACKET_DATA_SIZE - 12: size limit, minus enum variant and vec len() serialized sizes + let serialized = bincode::serialize(&item).unwrap(); + assert!(limited_deserialize::(&serialized).is_ok()); + + let item = Foo::Bar([1; crate::packet::PACKET_DATA_SIZE - 11].to_vec()); // Extra byte should bump serialized size over the size limit + let serialized = bincode::serialize(&item).unwrap(); + assert!(limited_deserialize::(&serialized).is_err()); + } +} diff --git a/transaction-status/Cargo.toml b/transaction-status/Cargo.toml index 2819e4cdb9..ce30c8affd 100644 --- a/transaction-status/Cargo.toml +++ b/transaction-status/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" [dependencies] base64 = "0.12.3" -bincode = "1.2.1" +bincode = "1.3.1" bs58 = "0.3.1" Inflector = "0.11.4" lazy_static = "1.4.0" @@ -20,7 +20,7 @@ serde_json = "1.0.54" solana-account-decoder = { path = "../account-decoder", version = "1.2.27" } solana-sdk = { path = "../sdk", version = "1.2.27" } spl-memo-v1-0 = { package = "spl-memo", version = "1.0.7", features = ["skip-no-mangle"] } -spl-token-v1-0 = { package = "spl-token", version = "1.0.8", features = ["skip-no-mangle"] } +spl-token-v2-0 = { package = "spl-token", version = "2.0.1", features = ["skip-no-mangle"] } thiserror = "1.0" [package.metadata.docs.rs] diff --git a/transaction-status/src/parse_instruction.rs b/transaction-status/src/parse_instruction.rs index aaa6ac0616..ebaac0922a 100644 --- a/transaction-status/src/parse_instruction.rs +++ b/transaction-status/src/parse_instruction.rs @@ -1,7 +1,7 @@ use crate::parse_token::parse_token; use inflector::Inflector; use serde_json::Value; -use solana_account_decoder::parse_token::spl_token_id_v1_0; +use solana_account_decoder::parse_token::spl_token_id_v2_0; use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey}; use std::{ collections::HashMap, @@ -12,7 +12,7 @@ use thiserror::Error; lazy_static! { static ref MEMO_PROGRAM_ID: Pubkey = Pubkey::from_str(&spl_memo_v1_0::id().to_string()).unwrap(); - static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v1_0(); + static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v2_0(); static ref PARSABLE_PROGRAM_IDS: HashMap = { let mut m = HashMap::new(); m.insert(*MEMO_PROGRAM_ID, ParsableProgram::SplMemo); diff --git a/transaction-status/src/parse_token.rs b/transaction-status/src/parse_token.rs index 84db788b71..bd4b69d346 100644 --- a/transaction-status/src/parse_token.rs +++ b/transaction-status/src/parse_token.rs @@ -1,7 +1,10 @@ use crate::parse_instruction::{ParsableProgram, ParseInstructionError, ParsedInstructionEnum}; use serde_json::{json, Map, Value}; use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey}; -use spl_token_v1_0::instruction::TokenInstruction; +use spl_token_v2_0::{ + instruction::{AuthorityType, TokenInstruction}, + option::COption, +}; pub fn parse_token( instruction: &CompiledInstruction, @@ -16,7 +19,11 @@ pub fn parse_token( )); } match token_instruction { - TokenInstruction::InitializeMint { amount, decimals } => { + TokenInstruction::InitializeMint { + decimals, + mint_authority, + freeze_authority, + } => { if instruction.accounts.len() < 2 { return Err(ParseInstructionError::InstructionKeyMismatch( ParsableProgram::SplToken, @@ -24,26 +31,16 @@ pub fn parse_token( } let mut value = json!({ "mint": account_keys[instruction.accounts[0] as usize].to_string(), - "amount": amount, - "decimals":decimals, + "decimals": decimals, + "mintAuthority": mint_authority.to_string(), + "rentSysvar": account_keys[instruction.accounts[1] as usize].to_string(), }); let map = value.as_object_mut().unwrap(); - if amount == 0 { + if let COption::Some(freeze_authority) = freeze_authority { map.insert( - "owner".to_string(), - json!(account_keys[instruction.accounts[1] as usize].to_string()), + "freezeAuthority".to_string(), + json!(freeze_authority.to_string()), ); - } else { - map.insert( - "account".to_string(), - json!(account_keys[instruction.accounts[1] as usize].to_string()), - ); - if let Some(i) = instruction.accounts.get(2) { - map.insert( - "owner".to_string(), - json!(account_keys[*i as usize].to_string()), - ); - } } Ok(ParsedInstructionEnum { instruction_type: "initializeMint".to_string(), @@ -51,7 +48,7 @@ pub fn parse_token( }) } TokenInstruction::InitializeAccount => { - if instruction.accounts.len() < 3 { + if instruction.accounts.len() < 4 { return Err(ParseInstructionError::InstructionKeyMismatch( ParsableProgram::SplToken, )); @@ -62,23 +59,25 @@ pub fn parse_token( "account": account_keys[instruction.accounts[0] as usize].to_string(), "mint": account_keys[instruction.accounts[1] as usize].to_string(), "owner": account_keys[instruction.accounts[2] as usize].to_string(), + "rentSysvar": account_keys[instruction.accounts[3] as usize].to_string(), }), }) } TokenInstruction::InitializeMultisig { m } => { - if instruction.accounts.len() < 2 { + if instruction.accounts.len() < 3 { return Err(ParseInstructionError::InstructionKeyMismatch( ParsableProgram::SplToken, )); } let mut signers: Vec = vec![]; - for i in instruction.accounts[1..].iter() { + for i in instruction.accounts[2..].iter() { signers.push(account_keys[*i as usize].to_string()); } Ok(ParsedInstructionEnum { instruction_type: "initializeMultisig".to_string(), info: json!({ "multisig": account_keys[instruction.accounts[0] as usize].to_string(), + "rentSysvar": account_keys[instruction.accounts[1] as usize].to_string(), "signers": signers, "m": m, }), @@ -157,27 +156,38 @@ pub fn parse_token( info: value, }) } - TokenInstruction::SetOwner => { - if instruction.accounts.len() < 3 { + TokenInstruction::SetAuthority { + authority_type, + new_authority, + } => { + if instruction.accounts.len() < 2 { return Err(ParseInstructionError::InstructionKeyMismatch( ParsableProgram::SplToken, )); } + let owned = match authority_type { + AuthorityType::MintTokens | AuthorityType::FreezeAccount => "mint", + AuthorityType::AccountOwner | AuthorityType::CloseAccount => "account", + }; let mut value = json!({ - "owned": account_keys[instruction.accounts[0] as usize].to_string(), - "newOwner": account_keys[instruction.accounts[1] as usize].to_string(), + owned: account_keys[instruction.accounts[0] as usize].to_string(), + "authorityType": Into::::into(authority_type), + "newAuthority": match new_authority { + COption::Some(authority) => Some(authority.to_string()), + COption::None => None, + }, }); let mut map = value.as_object_mut().unwrap(); parse_signers( &mut map, - 2, + 1, account_keys, &instruction.accounts, - "owner", - "multisigOwner", + "authority", + "multisigAuthority", ); Ok(ParsedInstructionEnum { - instruction_type: "setOwner".to_string(), + instruction_type: "setAuthority".to_string(), info: value, }) } @@ -198,8 +208,8 @@ pub fn parse_token( 2, account_keys, &instruction.accounts, - "owner", - "multisigOwner", + "mintAuthority", + "multisigMintAuthority", ); Ok(ParsedInstructionEnum { instruction_type: "mintTo".to_string(), @@ -207,19 +217,20 @@ pub fn parse_token( }) } TokenInstruction::Burn { amount } => { - if instruction.accounts.len() < 2 { + if instruction.accounts.len() < 3 { return Err(ParseInstructionError::InstructionKeyMismatch( ParsableProgram::SplToken, )); } let mut value = json!({ "account": account_keys[instruction.accounts[0] as usize].to_string(), + "mint": account_keys[instruction.accounts[1] as usize].to_string(), "amount": amount, }); let mut map = value.as_object_mut().unwrap(); parse_signers( &mut map, - 1, + 2, account_keys, &instruction.accounts, "authority", @@ -254,6 +265,180 @@ pub fn parse_token( info: value, }) } + TokenInstruction::FreezeAccount => { + if instruction.accounts.len() < 3 { + return Err(ParseInstructionError::InstructionKeyMismatch( + ParsableProgram::SplToken, + )); + } + let mut value = json!({ + "account": account_keys[instruction.accounts[0] as usize].to_string(), + "mint": account_keys[instruction.accounts[1] as usize].to_string(), + }); + let mut map = value.as_object_mut().unwrap(); + parse_signers( + &mut map, + 2, + account_keys, + &instruction.accounts, + "freezeAuthority", + "multisigFreezeAuthority", + ); + Ok(ParsedInstructionEnum { + instruction_type: "freezeAccount".to_string(), + info: value, + }) + } + TokenInstruction::ThawAccount => { + if instruction.accounts.len() < 3 { + return Err(ParseInstructionError::InstructionKeyMismatch( + ParsableProgram::SplToken, + )); + } + let mut value = json!({ + "account": account_keys[instruction.accounts[0] as usize].to_string(), + "mint": account_keys[instruction.accounts[1] as usize].to_string(), + }); + let mut map = value.as_object_mut().unwrap(); + parse_signers( + &mut map, + 2, + account_keys, + &instruction.accounts, + "freezeAuthority", + "multisigFreezeAuthority", + ); + Ok(ParsedInstructionEnum { + instruction_type: "thawAccount".to_string(), + info: value, + }) + } + TokenInstruction::Transfer2 { amount, decimals } => { + if instruction.accounts.len() < 4 { + return Err(ParseInstructionError::InstructionKeyMismatch( + ParsableProgram::SplToken, + )); + } + let mut value = json!({ + "source": account_keys[instruction.accounts[0] as usize].to_string(), + "mint": account_keys[instruction.accounts[1] as usize].to_string(), + "destination": account_keys[instruction.accounts[2] as usize].to_string(), + "amount": amount, + "decimals": decimals, + }); + let mut map = value.as_object_mut().unwrap(); + parse_signers( + &mut map, + 3, + account_keys, + &instruction.accounts, + "authority", + "multisigAuthority", + ); + Ok(ParsedInstructionEnum { + instruction_type: "transfer2".to_string(), + info: value, + }) + } + TokenInstruction::Approve2 { amount, decimals } => { + if instruction.accounts.len() < 4 { + return Err(ParseInstructionError::InstructionKeyMismatch( + ParsableProgram::SplToken, + )); + } + let mut value = json!({ + "source": account_keys[instruction.accounts[0] as usize].to_string(), + "mint": account_keys[instruction.accounts[1] as usize].to_string(), + "delegate": account_keys[instruction.accounts[2] as usize].to_string(), + "amount": amount, + "decimals": decimals, + }); + let mut map = value.as_object_mut().unwrap(); + parse_signers( + &mut map, + 3, + account_keys, + &instruction.accounts, + "owner", + "multisigOwner", + ); + Ok(ParsedInstructionEnum { + instruction_type: "approve2".to_string(), + info: value, + }) + } + TokenInstruction::MintTo2 { amount, decimals } => { + if instruction.accounts.len() < 3 { + return Err(ParseInstructionError::InstructionKeyMismatch( + ParsableProgram::SplToken, + )); + } + let mut value = json!({ + "mint": account_keys[instruction.accounts[0] as usize].to_string(), + "account": account_keys[instruction.accounts[1] as usize].to_string(), + "amount": amount, + "decimals": decimals, + }); + let mut map = value.as_object_mut().unwrap(); + parse_signers( + &mut map, + 2, + account_keys, + &instruction.accounts, + "mintAuthority", + "multisigMintAuthority", + ); + Ok(ParsedInstructionEnum { + instruction_type: "mintTo2".to_string(), + info: value, + }) + } + TokenInstruction::Burn2 { amount, decimals } => { + if instruction.accounts.len() < 3 { + return Err(ParseInstructionError::InstructionKeyMismatch( + ParsableProgram::SplToken, + )); + } + let mut value = json!({ + "account": account_keys[instruction.accounts[0] as usize].to_string(), + "mint": account_keys[instruction.accounts[1] as usize].to_string(), + "amount": amount, + "decimals": decimals, + }); + let mut map = value.as_object_mut().unwrap(); + parse_signers( + &mut map, + 2, + account_keys, + &instruction.accounts, + "authority", + "multisigAuthority", + ); + Ok(ParsedInstructionEnum { + instruction_type: "burn2".to_string(), + info: value, + }) + } + } +} + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] +pub enum UiAuthorityType { + MintTokens, + FreezeAccount, + AccountOwner, + CloseAccount, +} + +impl From for UiAuthorityType { + fn from(authority_type: AuthorityType) -> Self { + match authority_type { + AuthorityType::MintTokens => UiAuthorityType::MintTokens, + AuthorityType::FreezeAccount => UiAuthorityType::FreezeAccount, + AuthorityType::AccountOwner => UiAuthorityType::AccountOwner, + AuthorityType::CloseAccount => UiAuthorityType::CloseAccount, + } } } @@ -287,7 +472,7 @@ fn parse_signers( mod test { use super::*; use solana_sdk::instruction::CompiledInstruction; - use spl_token_v1_0::{ + use spl_token_v2_0::{ instruction::*, solana_sdk::{ instruction::CompiledInstruction as SplTokenCompiledInstruction, message::Message, @@ -319,11 +504,10 @@ mod test { // Test InitializeMint variations let initialize_mint_ix = initialize_mint( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), - Some(&convert_pubkey(keys[1])), - Some(&convert_pubkey(keys[2])), - 42, + &convert_pubkey(keys[2]), + Some(&convert_pubkey(keys[3])), 2, ) .unwrap(); @@ -335,20 +519,19 @@ mod test { instruction_type: "initializeMint".to_string(), info: json!({ "mint": keys[0].to_string(), - "amount": 42, "decimals": 2, - "account": keys[1].to_string(), - "owner": keys[2].to_string(), + "mintAuthority": keys[2].to_string(), + "freezeAuthority": keys[3].to_string(), + "rentSysvar": keys[1].to_string(), }) } ); let initialize_mint_ix = initialize_mint( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), - Some(&convert_pubkey(keys[1])), + &convert_pubkey(keys[2]), None, - 42, 2, ) .unwrap(); @@ -360,40 +543,16 @@ mod test { instruction_type: "initializeMint".to_string(), info: json!({ "mint": keys[0].to_string(), - "amount": 42, "decimals": 2, - "account": keys[1].to_string(), - }) - } - ); - - let initialize_mint_ix = initialize_mint( - &spl_token_v1_0::id(), - &convert_pubkey(keys[0]), - None, - Some(&convert_pubkey(keys[1])), - 0, - 2, - ) - .unwrap(); - let message = Message::new(&[initialize_mint_ix], None); - let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); - assert_eq!( - parse_token(&compiled_instruction, &keys).unwrap(), - ParsedInstructionEnum { - instruction_type: "initializeMint".to_string(), - info: json!({ - "mint": keys[0].to_string(), - "amount": 0, - "decimals": 2, - "owner": keys[1].to_string(), + "mintAuthority": keys[2].to_string(), + "rentSysvar": keys[1].to_string(), }) } ); // Test InitializeAccount let initialize_account_ix = initialize_account( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), @@ -409,18 +568,19 @@ mod test { "account": keys[0].to_string(), "mint": keys[1].to_string(), "owner": keys[2].to_string(), + "rentSysvar": keys[3].to_string(), }) } ); // Test InitializeMultisig let initialize_multisig_ix = initialize_multisig( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), &[ - &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[3]), + &convert_pubkey(keys[4]), ], 2, ) @@ -434,14 +594,15 @@ mod test { info: json!({ "multisig": keys[0].to_string(), "m": 2, - "signers": keys[1..4].iter().map(|key| key.to_string()).collect::>(), + "rentSysvar": keys[1].to_string(), + "signers": keys[2..5].iter().map(|key| key.to_string()).collect::>(), }) } ); // Test Transfer, incl multisig let transfer_ix = transfer( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -465,7 +626,7 @@ mod test { ); let transfer_ix = transfer( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[2]), &convert_pubkey(keys[3]), &convert_pubkey(keys[4]), @@ -491,7 +652,7 @@ mod test { // Test Approve, incl multisig let approve_ix = approve( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -515,7 +676,7 @@ mod test { ); let approve_ix = approve( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[2]), &convert_pubkey(keys[3]), &convert_pubkey(keys[4]), @@ -541,7 +702,7 @@ mod test { // Test Revoke let revoke_ix = revoke( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[0]), &[], @@ -561,31 +722,58 @@ mod test { ); // Test SetOwner - let set_owner_ix = set_owner( - &spl_token_v1_0::id(), - &convert_pubkey(keys[1]), - &convert_pubkey(keys[2]), + let set_authority_ix = set_authority( + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), + Some(&convert_pubkey(keys[2])), + AuthorityType::FreezeAccount, + &convert_pubkey(keys[1]), &[], ) .unwrap(); - let message = Message::new(&[set_owner_ix], None); + let message = Message::new(&[set_authority_ix], None); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); assert_eq!( parse_token(&compiled_instruction, &keys).unwrap(), ParsedInstructionEnum { - instruction_type: "setOwner".to_string(), + instruction_type: "setAuthority".to_string(), info: json!({ - "owned": keys[1].to_string(), - "newOwner": keys[2].to_string(), - "owner": keys[0].to_string(), + "mint": keys[1].to_string(), + "newAuthority": keys[2].to_string(), + "authority": keys[0].to_string(), + "authorityType": "freezeAccount".to_string(), + }) + } + ); + + let set_authority_ix = set_authority( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + None, + AuthorityType::CloseAccount, + &convert_pubkey(keys[0]), + &[], + ) + .unwrap(); + let message = Message::new(&[set_authority_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + let new_authority: Option = None; + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "setAuthority".to_string(), + info: json!({ + "account": keys[1].to_string(), + "newAuthority": new_authority, + "authority": keys[0].to_string(), + "authorityType": "closeAccount".to_string(), }) } ); // Test MintTo let mint_to_ix = mint_to( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -602,7 +790,7 @@ mod test { info: json!({ "mint": keys[1].to_string(), "account": keys[2].to_string(), - "owner": keys[0].to_string(), + "mintAuthority": keys[0].to_string(), "amount": 42, }) } @@ -610,8 +798,9 @@ mod test { // Test Burn let burn_ix = burn( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), &[], 42, @@ -625,6 +814,7 @@ mod test { instruction_type: "burn".to_string(), info: json!({ "account": keys[1].to_string(), + "mint": keys[2].to_string(), "authority": keys[0].to_string(), "amount": 42, }) @@ -633,7 +823,7 @@ mod test { // Test CloseAccount let close_account_ix = close_account( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -653,6 +843,222 @@ mod test { }) } ); + + // Test FreezeAccount + let freeze_account_ix = freeze_account( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + ) + .unwrap(); + let message = Message::new(&[freeze_account_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "freezeAccount".to_string(), + info: json!({ + "account": keys[1].to_string(), + "mint": keys[2].to_string(), + "freezeAuthority": keys[0].to_string(), + }) + } + ); + + // Test ThawAccount + let thaw_account_ix = thaw_account( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + ) + .unwrap(); + let message = Message::new(&[thaw_account_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "thawAccount".to_string(), + info: json!({ + "account": keys[1].to_string(), + "mint": keys[2].to_string(), + "freezeAuthority": keys[0].to_string(), + }) + } + ); + + // Test Transfer2, incl multisig + let transfer_ix = transfer2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[0]), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[transfer_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "transfer2".to_string(), + info: json!({ + "source": keys[1].to_string(), + "destination": keys[2].to_string(), + "mint": keys[3].to_string(), + "authority": keys[0].to_string(), + "amount": 42, + "decimals": 2, + }) + } + ); + + let transfer_ix = transfer2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &convert_pubkey(keys[4]), + &convert_pubkey(keys[5]), + &[&convert_pubkey(keys[0]), &convert_pubkey(keys[1])], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[transfer_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "transfer2".to_string(), + info: json!({ + "source": keys[2].to_string(), + "destination": keys[3].to_string(), + "mint": keys[4].to_string(), + "multisigAuthority": keys[5].to_string(), + "signers": keys[0..2].iter().map(|key| key.to_string()).collect::>(), + "amount": 42, + "decimals": 2, + }) + } + ); + + // Test Approve2, incl multisig + let approve_ix = approve2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &convert_pubkey(keys[0]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[approve_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "approve2".to_string(), + info: json!({ + "source": keys[1].to_string(), + "mint": keys[2].to_string(), + "delegate": keys[3].to_string(), + "owner": keys[0].to_string(), + "amount": 42, + "decimals": 2, + }) + } + ); + + let approve_ix = approve2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &convert_pubkey(keys[4]), + &convert_pubkey(keys[5]), + &[&convert_pubkey(keys[0]), &convert_pubkey(keys[1])], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[approve_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "approve2".to_string(), + info: json!({ + "source": keys[2].to_string(), + "mint": keys[3].to_string(), + "delegate": keys[4].to_string(), + "multisigOwner": keys[5].to_string(), + "signers": keys[0..2].iter().map(|key| key.to_string()).collect::>(), + "amount": 42, + "decimals": 2, + }) + } + ); + + // Test MintTo2 + let mint_to_ix = mint_to2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[mint_to_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "mintTo2".to_string(), + info: json!({ + "mint": keys[1].to_string(), + "account": keys[2].to_string(), + "mintAuthority": keys[0].to_string(), + "amount": 42, + "decimals": 2, + }) + } + ); + + // Test Burn2 + let burn_ix = burn2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[burn_ix], None); + let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert_eq!( + parse_token(&compiled_instruction, &keys).unwrap(), + ParsedInstructionEnum { + instruction_type: "burn2".to_string(), + info: json!({ + "account": keys[1].to_string(), + "mint": keys[2].to_string(), + "authority": keys[0].to_string(), + "amount": 42, + "decimals": 2, + }) + } + ); } #[test] @@ -664,27 +1070,10 @@ mod test { // Test InitializeMint variations let initialize_mint_ix = initialize_mint( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), - Some(&convert_pubkey(keys[1])), + &convert_pubkey(keys[1]), Some(&convert_pubkey(keys[2])), - 42, - 2, - ) - .unwrap(); - let message = Message::new(&[initialize_mint_ix], None); - let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); - assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); - compiled_instruction.accounts = - compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 2].to_vec(); - assert!(parse_token(&compiled_instruction, &keys).is_err()); - - let initialize_mint_ix = initialize_mint( - &spl_token_v1_0::id(), - &convert_pubkey(keys[0]), - Some(&convert_pubkey(keys[1])), - None, - 42, 2, ) .unwrap(); @@ -696,11 +1085,10 @@ mod test { assert!(parse_token(&compiled_instruction, &keys).is_err()); let initialize_mint_ix = initialize_mint( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), + &convert_pubkey(keys[1]), None, - Some(&convert_pubkey(keys[1])), - 0, 2, ) .unwrap(); @@ -713,7 +1101,7 @@ mod test { // Test InitializeAccount let initialize_account_ix = initialize_account( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), @@ -721,14 +1109,14 @@ mod test { .unwrap(); let message = Message::new(&[initialize_account_ix], None); let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); - assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); + assert!(parse_token(&compiled_instruction, &keys[0..3]).is_err()); compiled_instruction.accounts = compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); assert!(parse_token(&compiled_instruction, &keys).is_err()); // Test InitializeMultisig let initialize_multisig_ix = initialize_multisig( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[0]), &[ &convert_pubkey(keys[1]), @@ -740,14 +1128,14 @@ mod test { .unwrap(); let message = Message::new(&[initialize_multisig_ix], None); let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); - assert!(parse_token(&compiled_instruction, &keys[0..3]).is_err()); + assert!(parse_token(&compiled_instruction, &keys[0..4]).is_err()); compiled_instruction.accounts = compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 3].to_vec(); assert!(parse_token(&compiled_instruction, &keys).is_err()); // Test Transfer, incl multisig let transfer_ix = transfer( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -763,7 +1151,7 @@ mod test { assert!(parse_token(&compiled_instruction, &keys).is_err()); let transfer_ix = transfer( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[2]), &convert_pubkey(keys[3]), &convert_pubkey(keys[4]), @@ -780,7 +1168,7 @@ mod test { // Test Approve, incl multisig let approve_ix = approve( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -796,7 +1184,7 @@ mod test { assert!(parse_token(&compiled_instruction, &keys).is_err()); let approve_ix = approve( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[2]), &convert_pubkey(keys[3]), &convert_pubkey(keys[4]), @@ -813,7 +1201,7 @@ mod test { // Test Revoke let revoke_ix = revoke( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[0]), &[], @@ -826,25 +1214,26 @@ mod test { compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); assert!(parse_token(&compiled_instruction, &keys).is_err()); - // Test SetOwner - let set_owner_ix = set_owner( - &spl_token_v1_0::id(), + // Test SetAuthority + let set_authority_ix = set_authority( + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), - &convert_pubkey(keys[2]), + Some(&convert_pubkey(keys[2])), + AuthorityType::FreezeAccount, &convert_pubkey(keys[0]), &[], ) .unwrap(); - let message = Message::new(&[set_owner_ix], None); + let message = Message::new(&[set_authority_ix], None); let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); - assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); + assert!(parse_token(&compiled_instruction, &keys[0..1]).is_err()); compiled_instruction.accounts = compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); assert!(parse_token(&compiled_instruction, &keys).is_err()); // Test MintTo let mint_to_ix = mint_to( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -861,8 +1250,9 @@ mod test { // Test Burn let burn_ix = burn( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), &[], 42, @@ -870,14 +1260,14 @@ mod test { .unwrap(); let message = Message::new(&[burn_ix], None); let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); - assert!(parse_token(&compiled_instruction, &keys[0..1]).is_err()); + assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); compiled_instruction.accounts = compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); assert!(parse_token(&compiled_instruction, &keys).is_err()); // Test CloseAccount let close_account_ix = close_account( - &spl_token_v1_0::id(), + &spl_token_v2_0::id(), &convert_pubkey(keys[1]), &convert_pubkey(keys[2]), &convert_pubkey(keys[0]), @@ -890,5 +1280,147 @@ mod test { compiled_instruction.accounts = compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); assert!(parse_token(&compiled_instruction, &keys).is_err()); + + // Test FreezeAccount + let freeze_account_ix = freeze_account( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + ) + .unwrap(); + let message = Message::new(&[freeze_account_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); + + // Test ThawAccount + let thaw_account_ix = thaw_account( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + ) + .unwrap(); + let message = Message::new(&[thaw_account_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); + + // Test Transfer2, incl multisig + let transfer_ix = transfer2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &convert_pubkey(keys[0]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[transfer_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..3]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); + + let transfer_ix = transfer2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &convert_pubkey(keys[4]), + &convert_pubkey(keys[5]), + &[&convert_pubkey(keys[0]), &convert_pubkey(keys[1])], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[transfer_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..5]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 3].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); + + // Test Approve2, incl multisig + let approve_ix = approve2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &convert_pubkey(keys[0]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[approve_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..3]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); + + let approve_ix = approve2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[3]), + &convert_pubkey(keys[4]), + &convert_pubkey(keys[5]), + &[&convert_pubkey(keys[0]), &convert_pubkey(keys[1])], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[approve_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..5]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 3].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); + + // Test MintTo2 + let mint_to_ix = mint_to2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[mint_to_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); + + // Test Burn2 + let burn_ix = burn2( + &spl_token_v2_0::id(), + &convert_pubkey(keys[1]), + &convert_pubkey(keys[2]), + &convert_pubkey(keys[0]), + &[], + 42, + 2, + ) + .unwrap(); + let message = Message::new(&[burn_ix], None); + let mut compiled_instruction = convert_compiled_instruction(&message.instructions[0]); + assert!(parse_token(&compiled_instruction, &keys[0..2]).is_err()); + compiled_instruction.accounts = + compiled_instruction.accounts[0..compiled_instruction.accounts.len() - 1].to_vec(); + assert!(parse_token(&compiled_instruction, &keys).is_err()); } }