From 02181a649562e5fb3da6da6af324235fcc76f9f0 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 13 Sep 2024 21:11:31 +0400 Subject: [PATCH 01/13] start extracting system-instruction crate --- Cargo.lock | 16 ++++++++ Cargo.toml | 2 + programs/sbf/Cargo.lock | 11 ++++++ sdk/program/Cargo.toml | 1 + sdk/program/src/lib.rs | 2 +- sdk/system-instruction/Cargo.toml | 38 +++++++++++++++++++ .../src/lib.rs} | 9 +++-- 7 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 sdk/system-instruction/Cargo.toml rename sdk/{program/src/system_instruction.rs => system-instruction/src/lib.rs} (99%) diff --git a/Cargo.lock b/Cargo.lock index 0d522ff3580112..00d931a7a2ad35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7476,6 +7476,7 @@ dependencies = [ "solana-slot-hashes", "solana-slot-history", "solana-stable-layout", + "solana-system-instruction", "solana-sysvar-id", "solana-transaction-error", "static_assertions", @@ -8460,6 +8461,21 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-system-instruction" +version = "2.2.0" +dependencies = [ + "num-derive", + "num-traits", + "solana-decode-error", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-instruction", + "solana-program", + "solana-pubkey", + "static_assertions", +] + [[package]] name = "solana-system-program" version = "2.2.0" diff --git a/Cargo.toml b/Cargo.toml index 51b9aa1c42fb09..9c01c93fc9bebd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,6 +143,7 @@ members = [ "sdk/slot-hashes", "sdk/slot-history", "sdk/stable-layout", + "sdk/system-instruction", "sdk/sysvar-id", "sdk/time-utils", "sdk/transaction-error", @@ -484,6 +485,7 @@ solana-sha256-hasher = { path = "sdk/sha256-hasher", version = "=2.2.0" } solana-signature = { path = "sdk/signature", version = "=2.2.0", default-features = false } solana-slot-hashes = { path = "sdk/slot-hashes", version = "=2.2.0" } solana-slot-history = { path = "sdk/slot-history", version = "=2.2.0" } +solana-system-instruction = { path = "sdk/system-instruction", version = "=2.2.0" } solana-time-utils = { path = "sdk/time-utils", version = "=2.2.0" } solana-timings = { path = "timings", version = "=2.2.0" } solana-unified-scheduler-logic = { path = "unified-scheduler-logic", version = "=2.2.0" } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 17ca6b9ee419b9..de40d4549a7ae5 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -5839,6 +5839,7 @@ dependencies = [ "solana-slot-hashes", "solana-slot-history", "solana-stable-layout", + "solana-system-instruction", "solana-sysvar-id", "solana-transaction-error", "thiserror", @@ -7080,6 +7081,16 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-system-instruction" +version = "2.2.0" +dependencies = [ + "num-derive", + "num-traits", + "solana-decode-error", + "solana-pubkey", +] + [[package]] name = "solana-system-program" version = "2.2.0" diff --git a/sdk/program/Cargo.toml b/sdk/program/Cargo.toml index 4252838b59c10f..7ce1aaeb11ae06 100644 --- a/sdk/program/Cargo.toml +++ b/sdk/program/Cargo.toml @@ -74,6 +74,7 @@ solana-short-vec = { workspace = true } solana-slot-hashes = { workspace = true, features = ["serde", "sysvar"] } solana-slot-history = { workspace = true, features = ["serde", "sysvar"] } solana-stable-layout = { workspace = true } +solana-system-instruction = { workspace = true } solana-sysvar-id = { workspace = true } thiserror = { workspace = true } diff --git a/sdk/program/src/lib.rs b/sdk/program/src/lib.rs index 8a757d72e7c87e..e6bcd2095cd173 100644 --- a/sdk/program/src/lib.rs +++ b/sdk/program/src/lib.rs @@ -504,7 +504,6 @@ pub mod slot_history; pub mod stake; pub mod stake_history; pub mod syscalls; -pub mod system_instruction; pub mod system_program; pub mod sysvar; pub mod vote; @@ -551,6 +550,7 @@ pub use { entrypoint_no_alloc, }, solana_program_option as program_option, solana_pubkey as pubkey, solana_rent as rent, + solana_system_instruction as system_instruction, }; /// The [config native program][np]. /// diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml new file mode 100644 index 00000000000000..8e2b4a26cfb595 --- /dev/null +++ b/sdk/system-instruction/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "solana-system-instruction" +description = "Instructions and constructors for the Solana system program." +documentation = "https://docs.rs/solana-system-instruction" +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +num-derive = { workspace = true } +num-traits = { workspace = true } +solana-decode-error = { workspace = true } +solana-pubkey = { workspace = true, default-features = false } +solana-frozen-abi = { workspace = true, optional = true } +solana-frozen-abi-macro = { workspace = true, optional = true } + +[dev-dependencies] +solana-instruction = { workspace = true } +solana-program = { path = "../program", default-features = false } +static_assertions = { workspace = true } + +[features] +default = ["std"] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "std" +] +std = [] + +[lints] +workspace = true diff --git a/sdk/program/src/system_instruction.rs b/sdk/system-instruction/src/lib.rs similarity index 99% rename from sdk/program/src/system_instruction.rs rename to sdk/system-instruction/src/lib.rs index bd0fcb0b37e0a6..add0fb8fac9851 100644 --- a/sdk/program/src/system_instruction.rs +++ b/sdk/system-instruction/src/lib.rs @@ -38,18 +38,19 @@ //! [`invoke`]: crate::program::invoke //! [`invoke_signed`]: crate::program::invoke_signed //! [`AccountInfo`]: crate::account_info::AccountInfo +#![cfg_attr(feature = "frozen-abi", feature(min_specialization))] #[allow(deprecated)] use { crate::{ - instruction::{AccountMeta, Instruction}, - nonce, - pubkey::Pubkey, - system_program, + nonce, system_program, sysvar::{recent_blockhashes, rent}, }, num_derive::{FromPrimitive, ToPrimitive}, solana_decode_error::DecodeError, + solana_frozen_abi_macro::{AbiEnumVisitor, AbiExample}, + solana_instruction::{AccountMeta, Instruction}, + solana_pubkey::Pubkey, thiserror::Error, }; From 855bdccd41402fbb6693825b1a34ea5589a8a741 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 27 Sep 2024 12:44:47 +0400 Subject: [PATCH 02/13] get system-instruction crate working --- Cargo.lock | 6 +++ programs/sbf/Cargo.lock | 5 ++ sdk/system-instruction/Cargo.toml | 13 +++-- sdk/system-instruction/src/lib.rs | 84 +++++++++++++++++++------------ 4 files changed, 71 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00d931a7a2ad35..baa152e8558548 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8465,15 +8465,21 @@ dependencies = [ name = "solana-system-instruction" version = "2.2.0" dependencies = [ + "anyhow", + "borsh 1.5.1", "num-derive", "num-traits", + "serde", + "serde_derive", "solana-decode-error", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-instruction", "solana-program", + "solana-program-error", "solana-pubkey", "static_assertions", + "thiserror", ] [[package]] diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index de40d4549a7ae5..93b9e3b28b5c83 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -7087,8 +7087,13 @@ version = "2.2.0" dependencies = [ "num-derive", "num-traits", + "serde", + "serde_derive", "solana-decode-error", + "solana-instruction", + "solana-program-error", "solana-pubkey", + "thiserror", ] [[package]] diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index 8e2b4a26cfb595..07c5e23bc69fa2 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -15,24 +15,29 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] num-derive = { workspace = true } num-traits = { workspace = true } +serde = { workspace = true } +serde_derive = { workspace = true } solana-decode-error = { workspace = true } -solana-pubkey = { workspace = true, default-features = false } +solana-instruction = { workspace = true, features = ["bincode", "std"] } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true, default-features = false, features = ["serde"] } solana-frozen-abi = { workspace = true, optional = true } solana-frozen-abi-macro = { workspace = true, optional = true } +thiserror = { workspace = true } [dev-dependencies] +anyhow = { workspace = true } +borsh = { workspace = true } solana-instruction = { workspace = true } solana-program = { path = "../program", default-features = false } +solana-program-error = { workspace = true, features = ["borsh"] } static_assertions = { workspace = true } [features] -default = ["std"] frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", - "std" ] -std = [] [lints] workspace = true diff --git a/sdk/system-instruction/src/lib.rs b/sdk/system-instruction/src/lib.rs index add0fb8fac9851..9c7c0c6e3c48d0 100644 --- a/sdk/system-instruction/src/lib.rs +++ b/sdk/system-instruction/src/lib.rs @@ -42,18 +42,23 @@ #[allow(deprecated)] use { - crate::{ - nonce, system_program, - sysvar::{recent_blockhashes, rent}, - }, num_derive::{FromPrimitive, ToPrimitive}, + serde_derive::{Deserialize, Serialize}, solana_decode_error::DecodeError, - solana_frozen_abi_macro::{AbiEnumVisitor, AbiExample}, solana_instruction::{AccountMeta, Instruction}, solana_pubkey::Pubkey, thiserror::Error, }; +// inline some constants to avoid dependencies +const RECENT_BLOCKHASHES_ID: Pubkey = + Pubkey::from_str_const("SysvarRecentB1ockHashes11111111111111111111"); +const RENT_ID: Pubkey = Pubkey::from_str_const("SysvarRent111111111111111111111111111111111"); +const SYSTEM_PROGRAM_ID: Pubkey = Pubkey::from_str_const("11111111111111111111111111111111"); +const NONCE_STATE_SIZE: usize = 80; +#[cfg(test)] +static_assertions::const_assert_eq!(solana_program::nonce::State::size(), NONCE_STATE_SIZE); + #[derive(Error, Debug, Serialize, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] pub enum SystemError { #[error("an account with the same address already exists")] @@ -105,7 +110,10 @@ static_assertions::const_assert_eq!(MAX_PERMITTED_DATA_LENGTH, 10_485_760); #[cfg_attr( feature = "frozen-abi", frozen_abi(digest = "2LnVTnJg7LxB1FawNZLoQEY8yiYx3MT3paTdx4s5kAXU"), - derive(AbiExample, AbiEnumVisitor) + derive( + solana_frozen_abi_macro::AbiExample, + solana_frozen_abi_macro::AbiEnumVisitor + ) )] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub enum SystemInstruction { @@ -451,7 +459,7 @@ pub fn create_account( AccountMeta::new(*to_pubkey, true), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::CreateAccount { lamports, space, @@ -479,7 +487,7 @@ pub fn create_account_with_seed( ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::CreateAccountWithSeed { base: *base, seed: seed.to_string(), @@ -675,7 +683,7 @@ pub fn create_account_with_seed( pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction { let account_metas = vec![AccountMeta::new(*pubkey, true)]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::Assign { owner: *owner }, account_metas, ) @@ -692,7 +700,7 @@ pub fn assign_with_seed( AccountMeta::new_readonly(*base, true), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::AssignWithSeed { base: *base, seed: seed.to_string(), @@ -889,7 +897,7 @@ pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Inst AccountMeta::new(*to_pubkey, false), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::Transfer { lamports }, account_metas, ) @@ -909,7 +917,7 @@ pub fn transfer_with_seed( AccountMeta::new(*to_pubkey, false), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::TransferWithSeed { lamports, from_seed, @@ -1106,7 +1114,7 @@ pub fn transfer_with_seed( pub fn allocate(pubkey: &Pubkey, space: u64) -> Instruction { let account_metas = vec![AccountMeta::new(*pubkey, true)]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::Allocate { space }, account_metas, ) @@ -1124,7 +1132,7 @@ pub fn allocate_with_seed( AccountMeta::new_readonly(*base, true), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::AllocateWithSeed { base: *base, seed: seed.to_string(), @@ -1298,17 +1306,17 @@ pub fn create_nonce_account_with_seed( base, seed, lamports, - nonce::State::size() as u64, - &system_program::id(), + NONCE_STATE_SIZE as u64, + &SYSTEM_PROGRAM_ID, ), Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::InitializeNonceAccount(*authority), vec![ AccountMeta::new(*nonce_pubkey, false), #[allow(deprecated)] - AccountMeta::new_readonly(recent_blockhashes::id(), false), - AccountMeta::new_readonly(rent::id(), false), + AccountMeta::new_readonly(RECENT_BLOCKHASHES_ID, false), + AccountMeta::new_readonly(RENT_ID, false), ], ), ] @@ -1436,17 +1444,17 @@ pub fn create_nonce_account( from_pubkey, nonce_pubkey, lamports, - nonce::State::size() as u64, - &system_program::id(), + NONCE_STATE_SIZE as u64, + &SYSTEM_PROGRAM_ID, ), Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::InitializeNonceAccount(*authority), vec![ AccountMeta::new(*nonce_pubkey, false), #[allow(deprecated)] - AccountMeta::new_readonly(recent_blockhashes::id(), false), - AccountMeta::new_readonly(rent::id(), false), + AccountMeta::new_readonly(RECENT_BLOCKHASHES_ID, false), + AccountMeta::new_readonly(RENT_ID, false), ], ), ] @@ -1579,11 +1587,11 @@ pub fn advance_nonce_account(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) let account_metas = vec![ AccountMeta::new(*nonce_pubkey, false), #[allow(deprecated)] - AccountMeta::new_readonly(recent_blockhashes::id(), false), + AccountMeta::new_readonly(RECENT_BLOCKHASHES_ID, false), AccountMeta::new_readonly(*authorized_pubkey, true), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::AdvanceNonceAccount, account_metas, ) @@ -1671,12 +1679,12 @@ pub fn withdraw_nonce_account( AccountMeta::new(*nonce_pubkey, false), AccountMeta::new(*to_pubkey, false), #[allow(deprecated)] - AccountMeta::new_readonly(recent_blockhashes::id(), false), - AccountMeta::new_readonly(rent::id(), false), + AccountMeta::new_readonly(RECENT_BLOCKHASHES_ID, false), + AccountMeta::new_readonly(RENT_ID, false), AccountMeta::new_readonly(*authorized_pubkey, true), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::WithdrawNonceAccount(lamports), account_metas, ) @@ -1753,7 +1761,7 @@ pub fn authorize_nonce_account( AccountMeta::new_readonly(*authorized_pubkey, true), ]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::AuthorizeNonceAccount(*new_authority), account_metas, ) @@ -1764,7 +1772,7 @@ pub fn authorize_nonce_account( pub fn upgrade_nonce_account(nonce_pubkey: Pubkey) -> Instruction { let account_metas = vec![AccountMeta::new(nonce_pubkey, /*is_signer:*/ false)]; Instruction::new_with_bincode( - system_program::id(), + SYSTEM_PROGRAM_ID, &SystemInstruction::UpgradeNonceAccount, account_metas, ) @@ -1772,7 +1780,7 @@ pub fn upgrade_nonce_account(nonce_pubkey: Pubkey) -> Instruction { #[cfg(test)] mod tests { - use {super::*, crate::instruction::Instruction}; + use super::*; fn get_keys(instruction: &Instruction) -> Vec { instruction.accounts.iter().map(|x| x.pubkey).collect() @@ -1799,9 +1807,19 @@ mod tests { let ixs = create_nonce_account(&from_pubkey, &nonce_pubkey, &authorized, 42); assert_eq!(ixs.len(), 2); let ix = &ixs[0]; - assert_eq!(ix.program_id, system_program::id()); + assert_eq!(ix.program_id, SYSTEM_PROGRAM_ID); let pubkeys: Vec<_> = ix.accounts.iter().map(|am| am.pubkey).collect(); assert!(pubkeys.contains(&from_pubkey)); assert!(pubkeys.contains(&nonce_pubkey)); } + + #[test] + fn test_inline_consts() { + assert_eq!( + solana_program::sysvar::recent_blockhashes::ID, + RECENT_BLOCKHASHES_ID + ); + assert_eq!(solana_program::sysvar::rent::ID, RENT_ID); + assert_eq!(solana_program::system_program::ID, SYSTEM_PROGRAM_ID); + } } From e050f9f098386c41630d9bfde68faaf1fd10f9d3 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 27 Sep 2024 13:05:31 +0400 Subject: [PATCH 03/13] remove thiserror --- Cargo.lock | 1 - programs/sbf/Cargo.lock | 1 - sdk/system-instruction/Cargo.toml | 1 - sdk/system-instruction/src/lib.rs | 49 ++++++++++++++++++++++++------- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index baa152e8558548..4ac82b7a21a67c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8479,7 +8479,6 @@ dependencies = [ "solana-program-error", "solana-pubkey", "static_assertions", - "thiserror", ] [[package]] diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 93b9e3b28b5c83..891e463ebbfbb4 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -7093,7 +7093,6 @@ dependencies = [ "solana-instruction", "solana-program-error", "solana-pubkey", - "thiserror", ] [[package]] diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index 07c5e23bc69fa2..0d3ac009b40595 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -23,7 +23,6 @@ solana-program-error = { workspace = true } solana-pubkey = { workspace = true, default-features = false, features = ["serde"] } solana-frozen-abi = { workspace = true, optional = true } solana-frozen-abi-macro = { workspace = true, optional = true } -thiserror = { workspace = true } [dev-dependencies] anyhow = { workspace = true } diff --git a/sdk/system-instruction/src/lib.rs b/sdk/system-instruction/src/lib.rs index 9c7c0c6e3c48d0..1480d0cf4a729f 100644 --- a/sdk/system-instruction/src/lib.rs +++ b/sdk/system-instruction/src/lib.rs @@ -42,12 +42,12 @@ #[allow(deprecated)] use { + core::fmt, num_derive::{FromPrimitive, ToPrimitive}, serde_derive::{Deserialize, Serialize}, solana_decode_error::DecodeError, solana_instruction::{AccountMeta, Instruction}, solana_pubkey::Pubkey, - thiserror::Error, }; // inline some constants to avoid dependencies @@ -59,28 +59,55 @@ const NONCE_STATE_SIZE: usize = 80; #[cfg(test)] static_assertions::const_assert_eq!(solana_program::nonce::State::size(), NONCE_STATE_SIZE); -#[derive(Error, Debug, Serialize, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] +#[derive(Debug, Serialize, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] pub enum SystemError { - #[error("an account with the same address already exists")] AccountAlreadyInUse, - #[error("account does not have enough SOL to perform the operation")] ResultWithNegativeLamports, - #[error("cannot assign account to this program id")] InvalidProgramId, - #[error("cannot allocate account data of this length")] InvalidAccountDataLength, - #[error("length of requested seed is too long")] MaxSeedLengthExceeded, - #[error("provided address does not match addressed derived from seed")] AddressWithSeedMismatch, - #[error("advancing stored nonce requires a populated RecentBlockhashes sysvar")] NonceNoRecentBlockhashes, - #[error("stored nonce is still in recent_blockhashes")] NonceBlockhashNotExpired, - #[error("specified nonce does not match stored nonce")] NonceUnexpectedBlockhashValue, } +impl std::error::Error for SystemError {} + +impl fmt::Display for SystemError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + SystemError::AccountAlreadyInUse => { + f.write_str("an account with the same address already exists") + } + SystemError::ResultWithNegativeLamports => { + f.write_str("account does not have enough SOL to perform the operation") + } + SystemError::InvalidProgramId => { + f.write_str("cannot assign account to this program id") + } + SystemError::InvalidAccountDataLength => { + f.write_str("cannot allocate account data of this length") + } + SystemError::MaxSeedLengthExceeded => { + f.write_str("length of requested seed is too long") + } + SystemError::AddressWithSeedMismatch => { + f.write_str("provided address does not match addressed derived from seed") + } + SystemError::NonceNoRecentBlockhashes => { + f.write_str("advancing stored nonce requires a populated RecentBlockhashes sysvar") + } + SystemError::NonceBlockhashNotExpired => { + f.write_str("stored nonce is still in recent_blockhashes") + } + SystemError::NonceUnexpectedBlockhashValue => { + f.write_str("specified nonce does not match stored nonce") + } + } + } +} + impl DecodeError for SystemError { fn type_of() -> &'static str { "SystemError" From 4f47a092c54fcbbba2d62a9da7630ff1a2516fa9 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 27 Sep 2024 13:07:28 +0400 Subject: [PATCH 04/13] remove unused dep --- programs/sbf/Cargo.lock | 1 - sdk/system-instruction/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 891e463ebbfbb4..18fcaa233f170b 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -7091,7 +7091,6 @@ dependencies = [ "serde_derive", "solana-decode-error", "solana-instruction", - "solana-program-error", "solana-pubkey", ] diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index 0d3ac009b40595..c527d25b7eac3c 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -19,7 +19,6 @@ serde = { workspace = true } serde_derive = { workspace = true } solana-decode-error = { workspace = true } solana-instruction = { workspace = true, features = ["bincode", "std"] } -solana-program-error = { workspace = true } solana-pubkey = { workspace = true, default-features = false, features = ["serde"] } solana-frozen-abi = { workspace = true, optional = true } solana-frozen-abi-macro = { workspace = true, optional = true } From c9375d6dd4e45a9951a9cac1165f20c41687f743 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 27 Sep 2024 17:47:27 +0400 Subject: [PATCH 05/13] remove num_derive --- Cargo.lock | 3 +- programs/sbf/Cargo.lock | 1 - sdk/system-instruction/Cargo.toml | 3 +- sdk/system-instruction/src/lib.rs | 73 +++++++++++++++++++++++++++++-- 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ac82b7a21a67c..9a3c8258ff046e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8467,7 +8467,6 @@ version = "2.2.0" dependencies = [ "anyhow", "borsh 1.5.1", - "num-derive", "num-traits", "serde", "serde_derive", @@ -8479,6 +8478,8 @@ dependencies = [ "solana-program-error", "solana-pubkey", "static_assertions", + "strum", + "strum_macros", ] [[package]] diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 18fcaa233f170b..6c0ceb6b3b7726 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -7085,7 +7085,6 @@ dependencies = [ name = "solana-system-instruction" version = "2.2.0" dependencies = [ - "num-derive", "num-traits", "serde", "serde_derive", diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index c527d25b7eac3c..a7456eb1091937 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -13,7 +13,6 @@ edition = { workspace = true } targets = ["x86_64-unknown-linux-gnu"] [dependencies] -num-derive = { workspace = true } num-traits = { workspace = true } serde = { workspace = true } serde_derive = { workspace = true } @@ -30,6 +29,8 @@ solana-instruction = { workspace = true } solana-program = { path = "../program", default-features = false } solana-program-error = { workspace = true, features = ["borsh"] } static_assertions = { workspace = true } +strum = { workspace = true } +strum_macros = { workspace = true } [features] frozen-abi = [ diff --git a/sdk/system-instruction/src/lib.rs b/sdk/system-instruction/src/lib.rs index 1480d0cf4a729f..7eae459cea798a 100644 --- a/sdk/system-instruction/src/lib.rs +++ b/sdk/system-instruction/src/lib.rs @@ -43,7 +43,7 @@ #[allow(deprecated)] use { core::fmt, - num_derive::{FromPrimitive, ToPrimitive}, + num_traits::{FromPrimitive, ToPrimitive}, serde_derive::{Deserialize, Serialize}, solana_decode_error::DecodeError, solana_instruction::{AccountMeta, Instruction}, @@ -59,7 +59,10 @@ const NONCE_STATE_SIZE: usize = 80; #[cfg(test)] static_assertions::const_assert_eq!(solana_program::nonce::State::size(), NONCE_STATE_SIZE); -#[derive(Debug, Serialize, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] +// Use strum when testing to ensure our FromPrimitive +// impl is exhaustive +#[cfg_attr(test, derive(strum_macros::FromRepr, strum_macros::EnumIter))] +#[derive(Debug, Serialize, Clone, PartialEq, Eq)] pub enum SystemError { AccountAlreadyInUse, ResultWithNegativeLamports, @@ -72,6 +75,58 @@ pub enum SystemError { NonceUnexpectedBlockhashValue, } +impl FromPrimitive for SystemError { + #[inline] + fn from_i64(n: i64) -> Option { + if n == Self::AccountAlreadyInUse as i64 { + Some(Self::AccountAlreadyInUse) + } else if n == Self::ResultWithNegativeLamports as i64 { + Some(Self::ResultWithNegativeLamports) + } else if n == Self::InvalidProgramId as i64 { + Some(Self::InvalidProgramId) + } else if n == Self::InvalidAccountDataLength as i64 { + Some(Self::InvalidAccountDataLength) + } else if n == Self::MaxSeedLengthExceeded as i64 { + Some(Self::MaxSeedLengthExceeded) + } else if n == Self::AddressWithSeedMismatch as i64 { + Some(Self::AddressWithSeedMismatch) + } else if n == Self::NonceNoRecentBlockhashes as i64 { + Some(Self::NonceNoRecentBlockhashes) + } else if n == Self::NonceBlockhashNotExpired as i64 { + Some(Self::NonceBlockhashNotExpired) + } else if n == Self::NonceUnexpectedBlockhashValue as i64 { + Some(Self::NonceUnexpectedBlockhashValue) + } else { + None + } + } + #[inline] + fn from_u64(n: u64) -> Option { + Self::from_i64(n as i64) + } +} + +impl ToPrimitive for SystemError { + #[inline] + fn to_i64(&self) -> Option { + Some(match *self { + Self::AccountAlreadyInUse => Self::AccountAlreadyInUse as i64, + Self::ResultWithNegativeLamports => Self::ResultWithNegativeLamports as i64, + Self::InvalidProgramId => Self::InvalidProgramId as i64, + Self::InvalidAccountDataLength => Self::InvalidAccountDataLength as i64, + Self::MaxSeedLengthExceeded => Self::MaxSeedLengthExceeded as i64, + Self::AddressWithSeedMismatch => Self::AddressWithSeedMismatch as i64, + Self::NonceNoRecentBlockhashes => Self::NonceNoRecentBlockhashes as i64, + Self::NonceBlockhashNotExpired => Self::NonceBlockhashNotExpired as i64, + Self::NonceUnexpectedBlockhashValue => Self::NonceUnexpectedBlockhashValue as i64, + }) + } + #[inline] + fn to_u64(&self) -> Option { + self.to_i64().map(|x| x as u64) + } +} + impl std::error::Error for SystemError {} impl fmt::Display for SystemError { @@ -1807,7 +1862,7 @@ pub fn upgrade_nonce_account(nonce_pubkey: Pubkey) -> Instruction { #[cfg(test)] mod tests { - use super::*; + use {super::*, strum::IntoEnumIterator}; fn get_keys(instruction: &Instruction) -> Vec { instruction.accounts.iter().map(|x| x.pubkey).collect() @@ -1849,4 +1904,16 @@ mod tests { assert_eq!(solana_program::sysvar::rent::ID, RENT_ID); assert_eq!(solana_program::system_program::ID, SYSTEM_PROGRAM_ID); } + + #[test] + fn test_system_error_from_primitive_exhaustive() { + for variant in SystemError::iter() { + let variant_i64 = variant.clone() as i64; + assert_eq!( + SystemError::from_repr(variant_i64 as usize), + SystemError::from_i64(variant_i64) + ); + assert_eq!(SystemError::from_i64(variant_i64).unwrap(), variant); + } + } } From 8f88d61d94bf5c0ea068c85c0fc10486c0137fb8 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 27 Sep 2024 18:59:16 +0400 Subject: [PATCH 06/13] fix doc links --- sdk/system-instruction/src/lib.rs | 61 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/sdk/system-instruction/src/lib.rs b/sdk/system-instruction/src/lib.rs index 7eae459cea798a..73d5618b40139e 100644 --- a/sdk/system-instruction/src/lib.rs +++ b/sdk/system-instruction/src/lib.rs @@ -19,7 +19,7 @@ //! or they can be [program derived addresses][pda], //! where write access to accounts is granted by an owning program. //! -//! [pda]: crate::pubkey::Pubkey::find_program_address +//! [pda]: https://docs.rs/solana-pubkey/latest/solana_pubkey/struct.Pubkey.html#method.find_program_address //! //! The system program ID is defined in [`system_program`]. //! @@ -34,10 +34,11 @@ //! and these variants are linked from the documentation for their constructors. //! //! [`RpcClient`]: https://docs.rs/solana-client/latest/solana_client/rpc_client/struct.RpcClient.html -//! [cpi]: crate::program -//! [`invoke`]: crate::program::invoke -//! [`invoke_signed`]: crate::program::invoke_signed -//! [`AccountInfo`]: crate::account_info::AccountInfo +//! [cpi]: https://docs.rs/solana-program/latest/solana_program/program/ +//! [`invoke`]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html +//! [`invoke_signed`]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke_signed.html +//! [`AccountInfo`]: https://docs.rs/solana-account-info/latest/solana_account_info/struct.AccountInfo.html +//! [`system_program`]: https://docs.rs/solana-program/latest/solana_program/system_program/index.html #![cfg_attr(feature = "frozen-abi", feature(min_specialization))] #[allow(deprecated)] @@ -377,7 +378,7 @@ pub enum SystemInstruction { /// [`SystemInstruction::CreateAccount`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// Account creation typically involves three steps: [`allocate`] space, /// [`transfer`] lamports for rent, [`assign`] to its owning program. The @@ -454,8 +455,8 @@ pub enum SystemInstruction { /// virtually by the program itself via [`invoke_signed`], `payer` being signed /// for by the client that submitted the transaction. /// -/// [pda]: Pubkey::find_program_address -/// [`invoke_signed`]: crate::program::invoke_signed +/// [pda]: https://docs.rs/solana-program/latest/solana_program/pubkey/struct.Pubkey.html#method.find_program_address +/// [`invoke_signed`]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke_signed.html /// /// ``` /// # use borsh::{BorshDeserialize, BorshSerialize}; @@ -588,7 +589,7 @@ pub fn create_account_with_seed( /// [`SystemInstruction::Assign`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// # Required signers /// @@ -671,8 +672,8 @@ pub fn create_account_with_seed( /// itself via [`invoke_signed`], `payer` being signed for by the client that /// submitted the transaction. /// -/// [pda]: Pubkey::find_program_address -/// [`invoke_signed`]: crate::program::invoke_signed +/// [pda]: https://docs.rs/solana-program/latest/solana_program/pubkey/struct.Pubkey.html#method.find_program_address +/// [`invoke_signed`]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke_signed.html /// /// ``` /// # use borsh::{BorshDeserialize, BorshSerialize}; @@ -799,7 +800,7 @@ pub fn assign_with_seed( /// [`SystemInstruction::Transfer`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// # Required signers /// @@ -882,8 +883,8 @@ pub fn assign_with_seed( /// itself via [`invoke_signed`], `payer` being signed for by the client that /// submitted the transaction. /// -/// [pda]: Pubkey::find_program_address -/// [`invoke_signed`]: crate::program::invoke_signed +/// [pda]: https://docs.rs/solana-program/latest/solana_program/pubkey/struct.Pubkey.html#method.find_program_address +/// [`invoke_signed`]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke_signed.html /// /// ``` /// # use borsh::{BorshDeserialize, BorshSerialize}; @@ -1016,7 +1017,7 @@ pub fn transfer_with_seed( /// [`SystemInstruction::Allocate`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// The transaction will fail if the account already has size greater than 0, /// or if the requested size is greater than [`MAX_PERMITTED_DATA_LENGTH`]. @@ -1102,8 +1103,8 @@ pub fn transfer_with_seed( /// itself via [`invoke_signed`], `payer` being signed for by the client that /// submitted the transaction. /// -/// [pda]: Pubkey::find_program_address -/// [`invoke_signed`]: crate::program::invoke_signed +/// [pda]: https://docs.rs/solana-program/latest/solana_program/pubkey/struct.Pubkey.html#method.find_program_address +/// [`invoke_signed`]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke_signed.html /// /// ``` /// # use borsh::{BorshDeserialize, BorshSerialize}; @@ -1232,7 +1233,7 @@ pub fn allocate_with_seed( /// [`SystemInstruction::Transfer`]s. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// # Required signers /// @@ -1297,8 +1298,8 @@ pub fn allocate_with_seed( /// [`invoke_signed`], `payer` being signed for by the client that submitted the /// transaction. /// -/// [pda]: Pubkey::find_program_address -/// [`invoke_signed`]: crate::program::invoke_signed +/// [pda]: https://docs.rs/solana-program/latest/solana_program/pubkey/struct.Pubkey.html#method.find_program_address +/// [`invoke_signed`]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke_signed.html /// /// ``` /// # use borsh::{BorshDeserialize, BorshSerialize}; @@ -1412,7 +1413,7 @@ pub fn create_nonce_account_with_seed( /// [`SystemInstruction::InitializeNonceAccount`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// A [durable transaction nonce][dtn] is a special account that enables /// execution of transactions that have been signed in the past. @@ -1426,7 +1427,7 @@ pub fn create_nonce_account_with_seed( /// minutes, then successfully execute that transaction. /// /// [dtn]: https://docs.solanalabs.com/implemented-proposals/durable-tx-nonces -/// [rbh]: crate::message::Message::recent_blockhash +/// [rbh]: https://docs.rs/solana-program/latest/solana_program/message/legacy/struct.Message.html#structfield.recent_blockhash /// [nonce]: https://en.wikipedia.org/wiki/Cryptographic_nonce /// /// Durable transaction nonces are an alternative to the standard recent @@ -1441,8 +1442,8 @@ pub fn create_nonce_account_with_seed( /// the [`blockhash`] field of [`nonce::state::Data`], which is deserialized /// from the nonce account data. /// -/// [`blockhash`]: crate::nonce::state::Data::blockhash -/// [`nonce::state::Data`]: crate::nonce::state::Data +/// [`blockhash`]: https://docs.rs/solana-program/latest/solana_program/nonce/state/struct.Data.html#method.blockhash +/// [`nonce::state::Data`]: https://docs.rs/solana-program/latest/solana_program/nonce/state/struct.Data.html /// /// The basic durable transaction nonce lifecycle is /// @@ -1549,7 +1550,7 @@ pub fn create_nonce_account( /// [`SystemInstruction::AdvanceNonceAccount`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// Every transaction that relies on a durable transaction nonce must contain a /// [`SystemInstruction::AdvanceNonceAccount`] instruction as the first @@ -1569,9 +1570,9 @@ pub fn create_nonce_account( /// For further description of durable transaction nonces see /// [`create_nonce_account`]. /// -/// [`Message`]: crate::message::Message -/// [`Message::new_with_nonce`]: crate::message::Message::new_with_nonce -/// [`recent_blockhash`]: crate::message::Message::recent_blockhash +/// [`Message`]: https://docs.rs/solana-program/latest/solana_program/message/legacy/struct.Message.html +/// [`Message::new_with_nonce`]: https://docs.rs/solana-program/latest/solana_program/message/legacy/struct.Message.html#method.new_with_nonce +/// [`recent_blockhash`]: https://docs.rs/solana-program/latest/solana_program/message/legacy/struct.Message.html#structfield.recent_blockhash /// [dfa]: https://docs.rs/solana-rpc-client-nonce-utils/latest/solana_rpc_client_nonce_utils/fn.data_from_account.html /// /// # Required signers @@ -1686,7 +1687,7 @@ pub fn advance_nonce_account(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) /// [`SystemInstruction::WithdrawNonceAccount`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// Withdrawing the entire balance of a nonce account will cause the runtime to /// destroy it upon successful completion of the transaction. @@ -1779,7 +1780,7 @@ pub fn withdraw_nonce_account( /// [`SystemInstruction::AuthorizeNonceAccount`]. /// /// [`Transaction`]: https://docs.rs/solana-sdk/latest/solana_sdk/transaction/struct.Transaction.html -/// [invoked]: crate::program::invoke +/// [invoked]: https://docs.rs/solana-program/latest/solana_program/program/fn.invoke.html /// /// This constructor creates a [`SystemInstruction::AuthorizeNonceAccount`] /// instruction. From c1d304f06d79066abaa247d3d37565ab7bb9a2b2 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 27 Sep 2024 19:21:29 +0400 Subject: [PATCH 07/13] fix path --- sdk/system-instruction/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/system-instruction/src/lib.rs b/sdk/system-instruction/src/lib.rs index 73d5618b40139e..9ea97150352a72 100644 --- a/sdk/system-instruction/src/lib.rs +++ b/sdk/system-instruction/src/lib.rs @@ -192,7 +192,7 @@ static_assertions::const_assert_eq!(MAX_PERMITTED_DATA_LENGTH, 10_485_760); /// An instruction to the system program. #[cfg_attr( feature = "frozen-abi", - frozen_abi(digest = "2LnVTnJg7LxB1FawNZLoQEY8yiYx3MT3paTdx4s5kAXU"), + solana_frozen_abi_macro::frozen_abi(digest = "2LnVTnJg7LxB1FawNZLoQEY8yiYx3MT3paTdx4s5kAXU"), derive( solana_frozen_abi_macro::AbiExample, solana_frozen_abi_macro::AbiEnumVisitor From e64edca2e0200a7d6014b751469744e1897faf5d Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Fri, 27 Sep 2024 20:01:20 +0400 Subject: [PATCH 08/13] missing dep for frozen-abi --- Cargo.lock | 1 + sdk/system-instruction/Cargo.toml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 9a3c8258ff046e..1ae1ee64e243ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8474,6 +8474,7 @@ dependencies = [ "solana-frozen-abi", "solana-frozen-abi-macro", "solana-instruction", + "solana-logger", "solana-program", "solana-program-error", "solana-pubkey", diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index a7456eb1091937..75181c55f71667 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -18,6 +18,7 @@ serde = { workspace = true } serde_derive = { workspace = true } solana-decode-error = { workspace = true } solana-instruction = { workspace = true, features = ["bincode", "std"] } +solana-logger = { workspace = true, optional = true } solana-pubkey = { workspace = true, default-features = false, features = ["serde"] } solana-frozen-abi = { workspace = true, optional = true } solana-frozen-abi-macro = { workspace = true, optional = true } @@ -36,6 +37,7 @@ strum_macros = { workspace = true } frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", + "dep:solana-logger", ] [lints] From eeb93057c008541d5ec55d7e17ba6ec6a52eb2e8 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sat, 28 Sep 2024 20:17:59 +0400 Subject: [PATCH 09/13] sort deps --- sdk/system-instruction/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index 75181c55f71667..6972db5ae5e332 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -17,11 +17,11 @@ num-traits = { workspace = true } serde = { workspace = true } serde_derive = { workspace = true } solana-decode-error = { workspace = true } +solana-frozen-abi = { workspace = true, optional = true } +solana-frozen-abi-macro = { workspace = true, optional = true } solana-instruction = { workspace = true, features = ["bincode", "std"] } solana-logger = { workspace = true, optional = true } solana-pubkey = { workspace = true, default-features = false, features = ["serde"] } -solana-frozen-abi = { workspace = true, optional = true } -solana-frozen-abi-macro = { workspace = true, optional = true } [dev-dependencies] anyhow = { workspace = true } @@ -37,7 +37,7 @@ strum_macros = { workspace = true } frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", - "dep:solana-logger", + "dep:solana-logger" ] [lints] From 9edd479613b74f5c7a8a54a742755b6dfcf9141e Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sat, 28 Sep 2024 23:59:09 +0400 Subject: [PATCH 10/13] missing feature activation --- sdk/program/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/program/Cargo.toml b/sdk/program/Cargo.toml index 7ce1aaeb11ae06..66da747edbb492 100644 --- a/sdk/program/Cargo.toml +++ b/sdk/program/Cargo.toml @@ -149,7 +149,8 @@ frozen-abi = [ "solana-instruction/frozen-abi", "solana-pubkey/frozen-abi", "solana-rent/frozen-abi", - "solana-short-vec/frozen-abi" + "solana-short-vec/frozen-abi", + "solana-system-instruction/frozen-abi" ] [lints] From 57acf84043123095eb78e8ec7cace5c288ca629b Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sat, 5 Oct 2024 12:49:23 +0400 Subject: [PATCH 11/13] move wasm impl for SystemInstruction to system-instruction crate --- Cargo.lock | 2 + programs/sbf/Cargo.lock | 2 + sdk/program/src/wasm/system_instruction.rs | 115 +------------------- sdk/system-instruction/Cargo.toml | 4 + sdk/system-instruction/src/lib.rs | 2 + sdk/system-instruction/src/wasm.rs | 117 +++++++++++++++++++++ 6 files changed, 130 insertions(+), 112 deletions(-) create mode 100644 sdk/system-instruction/src/wasm.rs diff --git a/Cargo.lock b/Cargo.lock index 1ae1ee64e243ed..b52669b747014e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8467,6 +8467,7 @@ version = "2.2.0" dependencies = [ "anyhow", "borsh 1.5.1", + "js-sys", "num-traits", "serde", "serde_derive", @@ -8481,6 +8482,7 @@ dependencies = [ "static_assertions", "strum", "strum_macros", + "wasm-bindgen", ] [[package]] diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 6c0ceb6b3b7726..5d8af314d8519d 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -7085,12 +7085,14 @@ dependencies = [ name = "solana-system-instruction" version = "2.2.0" dependencies = [ + "js-sys", "num-traits", "serde", "serde_derive", "solana-decode-error", "solana-instruction", "solana-pubkey", + "wasm-bindgen", ] [[package]] diff --git a/sdk/program/src/wasm/system_instruction.rs b/sdk/program/src/wasm/system_instruction.rs index 94dd636788092c..e320db37177a6f 100644 --- a/sdk/program/src/wasm/system_instruction.rs +++ b/sdk/program/src/wasm/system_instruction.rs @@ -1,112 +1,3 @@ -//! `SystemInstruction` Javascript interface -#![cfg(target_arch = "wasm32")] -#![allow(non_snake_case)] -use { - crate::{instruction::Instruction, pubkey::Pubkey, system_instruction::*}, - wasm_bindgen::prelude::*, -}; - -#[wasm_bindgen] -impl SystemInstruction { - pub fn createAccount( - from_pubkey: &Pubkey, - to_pubkey: &Pubkey, - lamports: u64, - space: u64, - owner: &Pubkey, - ) -> Instruction { - create_account(from_pubkey, to_pubkey, lamports, space, owner) - } - - pub fn createAccountWithSeed( - from_pubkey: &Pubkey, - to_pubkey: &Pubkey, - base: &Pubkey, - seed: &str, - lamports: u64, - space: u64, - owner: &Pubkey, - ) -> Instruction { - create_account_with_seed(from_pubkey, to_pubkey, base, seed, lamports, space, owner) - } - - pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction { - assign(pubkey, owner) - } - - pub fn assignWithSeed( - pubkey: &Pubkey, - base: &Pubkey, - seed: &str, - owner: &Pubkey, - ) -> Instruction { - assign_with_seed(pubkey, base, seed, owner) - } - - pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction { - transfer(from_pubkey, to_pubkey, lamports) - } - - pub fn transferWithSeed( - from_pubkey: &Pubkey, - from_base: &Pubkey, - from_seed: String, - from_owner: &Pubkey, - to_pubkey: &Pubkey, - lamports: u64, - ) -> Instruction { - transfer_with_seed( - from_pubkey, - from_base, - from_seed, - from_owner, - to_pubkey, - lamports, - ) - } - - pub fn allocate(pubkey: &Pubkey, space: u64) -> Instruction { - allocate(pubkey, space) - } - - pub fn allocateWithSeed( - address: &Pubkey, - base: &Pubkey, - seed: &str, - space: u64, - owner: &Pubkey, - ) -> Instruction { - allocate_with_seed(address, base, seed, space, owner) - } - - pub fn createNonceAccount( - from_pubkey: &Pubkey, - nonce_pubkey: &Pubkey, - authority: &Pubkey, - lamports: u64, - ) -> js_sys::Array { - let instructions = create_nonce_account(from_pubkey, nonce_pubkey, authority, lamports); - instructions.into_iter().map(JsValue::from).collect() - } - - pub fn advanceNonceAccount(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction { - advance_nonce_account(nonce_pubkey, authorized_pubkey) - } - - pub fn withdrawNonceAccount( - nonce_pubkey: &Pubkey, - authorized_pubkey: &Pubkey, - to_pubkey: &Pubkey, - lamports: u64, - ) -> Instruction { - withdraw_nonce_account(nonce_pubkey, authorized_pubkey, to_pubkey, lamports) - } - - pub fn authorizeNonceAccount( - nonce_pubkey: &Pubkey, - authorized_pubkey: &Pubkey, - new_authority: &Pubkey, - ) -> Instruction { - authorize_nonce_account(nonce_pubkey, authorized_pubkey, new_authority) - } -} +//! Left empty because deleting this module would technically be a breaking change, +//! but there was never anything you could import from here. +// TODO: delete this in next breaking change. diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index 6972db5ae5e332..33c8cfb188f707 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -23,6 +23,10 @@ solana-instruction = { workspace = true, features = ["bincode", "std"] } solana-logger = { workspace = true, optional = true } solana-pubkey = { workspace = true, default-features = false, features = ["serde"] } +[target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys = { workspace = true } +wasm-bindgen = { workspace = true } + [dev-dependencies] anyhow = { workspace = true } borsh = { workspace = true } diff --git a/sdk/system-instruction/src/lib.rs b/sdk/system-instruction/src/lib.rs index 9ea97150352a72..35d49aa2930b32 100644 --- a/sdk/system-instruction/src/lib.rs +++ b/sdk/system-instruction/src/lib.rs @@ -50,6 +50,8 @@ use { solana_instruction::{AccountMeta, Instruction}, solana_pubkey::Pubkey, }; +#[cfg(target_arch = "wasm32")] +mod wasm; // inline some constants to avoid dependencies const RECENT_BLOCKHASHES_ID: Pubkey = diff --git a/sdk/system-instruction/src/wasm.rs b/sdk/system-instruction/src/wasm.rs new file mode 100644 index 00000000000000..e9d4475a60b1d0 --- /dev/null +++ b/sdk/system-instruction/src/wasm.rs @@ -0,0 +1,117 @@ +//! `SystemInstruction` Javascript interface +#![allow(non_snake_case)] +use { + crate::{ + advance_nonce_account, allocate, allocate_with_seed, assign, assign_with_seed, + authorize_nonce_account, create_account, create_account_with_seed, create_nonce_account, + transfer, transfer_with_seed, withdraw_nonce_account, SystemInstruction, + }, + solana_instruction::Instruction, + solana_pubkey::Pubkey, + wasm_bindgen::prelude::*, +}; + +#[wasm_bindgen] +impl SystemInstruction { + pub fn createAccount( + from_pubkey: &Pubkey, + to_pubkey: &Pubkey, + lamports: u64, + space: u64, + owner: &Pubkey, + ) -> Instruction { + create_account(from_pubkey, to_pubkey, lamports, space, owner) + } + + pub fn createAccountWithSeed( + from_pubkey: &Pubkey, + to_pubkey: &Pubkey, + base: &Pubkey, + seed: &str, + lamports: u64, + space: u64, + owner: &Pubkey, + ) -> Instruction { + create_account_with_seed(from_pubkey, to_pubkey, base, seed, lamports, space, owner) + } + + pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction { + assign(pubkey, owner) + } + + pub fn assignWithSeed( + pubkey: &Pubkey, + base: &Pubkey, + seed: &str, + owner: &Pubkey, + ) -> Instruction { + assign_with_seed(pubkey, base, seed, owner) + } + + pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction { + transfer(from_pubkey, to_pubkey, lamports) + } + + pub fn transferWithSeed( + from_pubkey: &Pubkey, + from_base: &Pubkey, + from_seed: String, + from_owner: &Pubkey, + to_pubkey: &Pubkey, + lamports: u64, + ) -> Instruction { + transfer_with_seed( + from_pubkey, + from_base, + from_seed, + from_owner, + to_pubkey, + lamports, + ) + } + + pub fn allocate(pubkey: &Pubkey, space: u64) -> Instruction { + allocate(pubkey, space) + } + + pub fn allocateWithSeed( + address: &Pubkey, + base: &Pubkey, + seed: &str, + space: u64, + owner: &Pubkey, + ) -> Instruction { + allocate_with_seed(address, base, seed, space, owner) + } + + pub fn createNonceAccount( + from_pubkey: &Pubkey, + nonce_pubkey: &Pubkey, + authority: &Pubkey, + lamports: u64, + ) -> js_sys::Array { + let instructions = create_nonce_account(from_pubkey, nonce_pubkey, authority, lamports); + instructions.into_iter().map(JsValue::from).collect() + } + + pub fn advanceNonceAccount(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction { + advance_nonce_account(nonce_pubkey, authorized_pubkey) + } + + pub fn withdrawNonceAccount( + nonce_pubkey: &Pubkey, + authorized_pubkey: &Pubkey, + to_pubkey: &Pubkey, + lamports: u64, + ) -> Instruction { + withdraw_nonce_account(nonce_pubkey, authorized_pubkey, to_pubkey, lamports) + } + + pub fn authorizeNonceAccount( + nonce_pubkey: &Pubkey, + authorized_pubkey: &Pubkey, + new_authority: &Pubkey, + ) -> Instruction { + authorize_nonce_account(nonce_pubkey, authorized_pubkey, new_authority) + } +} From c07d7f38fc7c2e66f61225ddba8dc9b15432f82a Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sat, 12 Oct 2024 13:47:37 +0400 Subject: [PATCH 12/13] add doc_auto_cfg like in #3121 --- sdk/system-instruction/Cargo.toml | 2 ++ sdk/system-instruction/src/lib.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index 33c8cfb188f707..f039bc375e7749 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -11,6 +11,8 @@ edition = { workspace = true } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] [dependencies] num-traits = { workspace = true } diff --git a/sdk/system-instruction/src/lib.rs b/sdk/system-instruction/src/lib.rs index 35d49aa2930b32..915c86daf578b3 100644 --- a/sdk/system-instruction/src/lib.rs +++ b/sdk/system-instruction/src/lib.rs @@ -40,6 +40,7 @@ //! [`AccountInfo`]: https://docs.rs/solana-account-info/latest/solana_account_info/struct.AccountInfo.html //! [`system_program`]: https://docs.rs/solana-program/latest/solana_program/system_program/index.html #![cfg_attr(feature = "frozen-abi", feature(min_specialization))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #[allow(deprecated)] use { From ead7942cee469efe6a2aa64e33f8bf292f971b3d Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sat, 12 Oct 2024 14:01:13 +0400 Subject: [PATCH 13/13] include wasm32 build on docs.rs --- sdk/system-instruction/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/system-instruction/Cargo.toml b/sdk/system-instruction/Cargo.toml index f039bc375e7749..33c1526694dfdb 100644 --- a/sdk/system-instruction/Cargo.toml +++ b/sdk/system-instruction/Cargo.toml @@ -10,7 +10,7 @@ license = { workspace = true } edition = { workspace = true } [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] all-features = true rustdoc-args = ["--cfg=docsrs"]