From 750f367343f1405fbabc57d0adf82a863c388628 Mon Sep 17 00:00:00 2001 From: Jon C Date: Fri, 1 Nov 2024 22:26:45 +0100 Subject: [PATCH] record: Remove dependency on solana-program #### Problem It's possible to write programs without solana-program, but spl-record still has a dependency on it. #### Summary of changes Mostly straightforward, replacing the crates with their components. I also removed a dependency on spl-pod, because that brings in solana-zk-sdk, which does require solana-program currently. --- Cargo.lock | 11 ++++++-- record/program/Cargo.toml | 11 ++++++-- record/program/Xargo.toml | 2 -- record/program/src/entrypoint.rs | 6 +++-- record/program/src/error.rs | 5 ++-- record/program/src/instruction.rs | 10 +++---- record/program/src/lib.rs | 7 +++-- record/program/src/processor.rs | 42 ++++++++++++++++-------------- record/program/src/state.rs | 17 ++++++------ record/program/tests/functional.rs | 40 ++++++++++++++-------------- 10 files changed, 84 insertions(+), 67 deletions(-) delete mode 100644 record/program/Xargo.toml diff --git a/Cargo.lock b/Cargo.lock index d10c0822a1f..8bd3b48bfac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8292,10 +8292,17 @@ dependencies = [ "bytemuck", "num-derive", "num-traits", - "solana-program", + "solana-account-info", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-pack", "solana-program-test", + "solana-pubkey", + "solana-rent", "solana-sdk", - "spl-pod 0.5.0", "thiserror", ] diff --git a/record/program/Cargo.toml b/record/program/Cargo.toml index 988a35b675f..ba03c64bf8b 100644 --- a/record/program/Cargo.toml +++ b/record/program/Cargo.toml @@ -15,9 +15,16 @@ test-sbf = [] bytemuck = { version = "1.19.0", features = ["derive"] } num-derive = "0.4" num-traits = "0.2" -solana-program = "2.1.0" +solana-account-info = "2.1.0" +solana-decode-error = "2.1.0" +solana-instruction = { version = "2.1.0", features = ["std"] } +solana-msg = "2.1.0" +solana-program-entrypoint = "2.1.0" +solana-program-error = "2.1.0" +solana-program-pack = "2.1.0" +solana-pubkey = { version = "2.1.0", features = ["bytemuck"] } +solana-rent = "2.1.0" thiserror = "1.0" -spl-pod = { version = "0.5.0", path = "../../libraries/pod" } [dev-dependencies] solana-program-test = "2.1.0" diff --git a/record/program/Xargo.toml b/record/program/Xargo.toml deleted file mode 100644 index 1744f098ae1..00000000000 --- a/record/program/Xargo.toml +++ /dev/null @@ -1,2 +0,0 @@ -[target.bpfel-unknown-unknown.dependencies.std] -features = [] \ No newline at end of file diff --git a/record/program/src/entrypoint.rs b/record/program/src/entrypoint.rs index 62a02f2a465..f52b183fb1c 100644 --- a/record/program/src/entrypoint.rs +++ b/record/program/src/entrypoint.rs @@ -2,9 +2,11 @@ #![cfg(all(target_os = "solana", not(feature = "no-entrypoint")))] -use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey}; +use { + solana_account_info::AccountInfo, solana_program_error::ProgramResult, solana_pubkey::Pubkey, +}; -solana_program::entrypoint!(process_instruction); +solana_program_entrypoint::entrypoint!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/record/program/src/error.rs b/record/program/src/error.rs index d52354a89ff..f8780435836 100644 --- a/record/program/src/error.rs +++ b/record/program/src/error.rs @@ -1,9 +1,8 @@ //! Error types use { - num_derive::FromPrimitive, - solana_program::{decode_error::DecodeError, program_error::ProgramError}, - thiserror::Error, + num_derive::FromPrimitive, solana_decode_error::DecodeError, + solana_program_error::ProgramError, thiserror::Error, }; /// Errors that may be returned by the program. diff --git a/record/program/src/instruction.rs b/record/program/src/instruction.rs index 93d4f3ea946..a8de8c82a76 100644 --- a/record/program/src/instruction.rs +++ b/record/program/src/instruction.rs @@ -2,11 +2,9 @@ use { crate::id, - solana_program::{ - instruction::{AccountMeta, Instruction}, - program_error::ProgramError, - pubkey::Pubkey, - }, + solana_instruction::{AccountMeta, Instruction}, + solana_program_error::ProgramError, + solana_pubkey::Pubkey, std::mem::size_of, }; @@ -203,7 +201,7 @@ pub fn reallocate(record_account: &Pubkey, signer: &Pubkey, data_length: u64) -> #[cfg(test)] mod tests { - use {super::*, crate::state::tests::TEST_BYTES, solana_program::program_error::ProgramError}; + use {super::*, crate::state::tests::TEST_BYTES, solana_program_error::ProgramError}; #[test] fn serialize_initialize() { diff --git a/record/program/src/lib.rs b/record/program/src/lib.rs index 72a77a70a90..7646e07c210 100644 --- a/record/program/src/lib.rs +++ b/record/program/src/lib.rs @@ -9,6 +9,9 @@ pub mod state; // Export current SDK types for downstream users building with a different SDK // version -pub use solana_program; +pub use { + solana_account_info, solana_decode_error, solana_instruction, solana_msg, + solana_program_entrypoint, solana_program_error, solana_program_pack, solana_pubkey, +}; -solana_program::declare_id!("recr1L3PCGKLbckBqMNcJhuuyU1zgo8nBhfLVsJNwr5"); +solana_pubkey::declare_id!("recr1L3PCGKLbckBqMNcJhuuyU1zgo8nBhfLVsJNwr5"); diff --git a/record/program/src/processor.rs b/record/program/src/processor.rs index 4d626cc7b96..2def5c1e960 100644 --- a/record/program/src/processor.rs +++ b/record/program/src/processor.rs @@ -2,15 +2,11 @@ use { crate::{error::RecordError, instruction::RecordInstruction, state::RecordData}, - solana_program::{ - account_info::{next_account_info, AccountInfo}, - entrypoint::ProgramResult, - msg, - program_error::ProgramError, - program_pack::IsInitialized, - pubkey::Pubkey, - }, - spl_pod::bytemuck::{pod_from_bytes, pod_from_bytes_mut, pod_get_packed_len}, + solana_account_info::{next_account_info, AccountInfo}, + solana_msg::msg, + solana_program_error::{ProgramError, ProgramResult}, + solana_program_pack::IsInitialized, + solana_pubkey::Pubkey, }; fn check_authority(authority_info: &AccountInfo, expected_authority: &Pubkey) -> ProgramResult { @@ -46,9 +42,10 @@ pub fn process_instruction( return Err(ProgramError::InvalidAccountData); } - let account_data = pod_from_bytes_mut::( + let account_data = bytemuck::try_from_bytes_mut::( &mut raw_data[..RecordData::WRITABLE_START_INDEX], - )?; + ) + .map_err(|_| ProgramError::InvalidArgument)?; if account_data.is_initialized() { msg!("Record account already initialized"); return Err(ProgramError::AccountAlreadyInitialized); @@ -68,8 +65,10 @@ pub fn process_instruction( if raw_data.len() < RecordData::WRITABLE_START_INDEX { return Err(ProgramError::InvalidAccountData); } - let account_data = - pod_from_bytes::(&raw_data[..RecordData::WRITABLE_START_INDEX])?; + let account_data = bytemuck::try_from_bytes::( + &raw_data[..RecordData::WRITABLE_START_INDEX], + ) + .map_err(|_| ProgramError::InvalidArgument)?; if !account_data.is_initialized() { msg!("Record account not initialized"); return Err(ProgramError::UninitializedAccount); @@ -95,9 +94,10 @@ pub fn process_instruction( if raw_data.len() < RecordData::WRITABLE_START_INDEX { return Err(ProgramError::InvalidAccountData); } - let account_data = pod_from_bytes_mut::( + let account_data = bytemuck::try_from_bytes_mut::( &mut raw_data[..RecordData::WRITABLE_START_INDEX], - )?; + ) + .map_err(|_| ProgramError::InvalidArgument)?; if !account_data.is_initialized() { msg!("Record account not initialized"); return Err(ProgramError::UninitializedAccount); @@ -116,9 +116,10 @@ pub fn process_instruction( if raw_data.len() < RecordData::WRITABLE_START_INDEX { return Err(ProgramError::InvalidAccountData); } - let account_data = pod_from_bytes_mut::( + let account_data = bytemuck::try_from_bytes_mut::( &mut raw_data[..RecordData::WRITABLE_START_INDEX], - )?; + ) + .map_err(|_| ProgramError::InvalidArgument)?; if !account_data.is_initialized() { msg!("Record not initialized"); return Err(ProgramError::UninitializedAccount); @@ -143,9 +144,10 @@ pub fn process_instruction( if raw_data.len() < RecordData::WRITABLE_START_INDEX { return Err(ProgramError::InvalidAccountData); } - let account_data = pod_from_bytes_mut::( + let account_data = bytemuck::try_from_bytes_mut::( &mut raw_data[..RecordData::WRITABLE_START_INDEX], - )?; + ) + .map_err(|_| ProgramError::InvalidArgument)?; if !account_data.is_initialized() { msg!("Record not initialized"); return Err(ProgramError::UninitializedAccount); @@ -155,7 +157,7 @@ pub fn process_instruction( // needed account length is the sum of the meta data length and the specified // data length - let needed_account_length = pod_get_packed_len::() + let needed_account_length = std::mem::size_of::() .checked_add( usize::try_from(data_length).map_err(|_| ProgramError::InvalidArgument)?, ) diff --git a/record/program/src/state.rs b/record/program/src/state.rs index c809ec0a98d..0f8e78849a0 100644 --- a/record/program/src/state.rs +++ b/record/program/src/state.rs @@ -1,7 +1,8 @@ //! Program state use { bytemuck::{Pod, Zeroable}, - solana_program::{program_pack::IsInitialized, pubkey::Pubkey}, + solana_program_pack::IsInitialized, + solana_pubkey::Pubkey, }; /// Header type for recorded account data @@ -32,11 +33,7 @@ impl IsInitialized for RecordData { #[cfg(test)] pub mod tests { - use { - super::*, - solana_program::program_error::ProgramError, - spl_pod::bytemuck::{pod_bytes_of, pod_from_bytes}, - }; + use {super::*, solana_program_error::ProgramError}; /// Version for tests pub const TEST_VERSION: u8 = 1; @@ -54,9 +51,9 @@ pub mod tests { fn serialize_data() { let mut expected = vec![TEST_VERSION]; expected.extend_from_slice(&TEST_PUBKEY.to_bytes()); - assert_eq!(pod_bytes_of(&TEST_RECORD_DATA), expected); + assert_eq!(bytemuck::bytes_of(&TEST_RECORD_DATA), expected); assert_eq!( - *pod_from_bytes::(&expected).unwrap(), + *bytemuck::try_from_bytes::(&expected).unwrap(), TEST_RECORD_DATA, ); } @@ -66,7 +63,9 @@ pub mod tests { let mut expected = vec![TEST_VERSION]; expected.extend_from_slice(&TEST_PUBKEY.to_bytes()); expected.extend_from_slice(&TEST_BYTES); - let err: ProgramError = pod_from_bytes::(&expected).unwrap_err(); + let err = bytemuck::try_from_bytes::(&expected) + .map_err(|_| ProgramError::InvalidArgument) + .unwrap_err(); assert_eq!(err, ProgramError::InvalidArgument); } } diff --git a/record/program/tests/functional.rs b/record/program/tests/functional.rs index 948894c0788..3fe0ef9de43 100644 --- a/record/program/tests/functional.rs +++ b/record/program/tests/functional.rs @@ -1,18 +1,15 @@ #![cfg(feature = "test-sbf")] use { - solana_program::{ - instruction::{AccountMeta, Instruction, InstructionError}, - pubkey::Pubkey, - rent::Rent, - system_instruction, - }, + solana_instruction::{error::InstructionError, AccountMeta, Instruction}, solana_program_test::*, + solana_pubkey::Pubkey, + solana_rent::Rent, solana_sdk::{ signature::{Keypair, Signer}, + system_instruction, transaction::{Transaction, TransactionError}, }, - spl_pod::bytemuck::{pod_from_bytes, pod_get_packed_len}, spl_record::{ error::RecordError, id, instruction, processor::process_instruction, state::RecordData, }, @@ -28,7 +25,7 @@ async fn initialize_storage_account( account: &Keypair, data: &[u8], ) { - let account_length = pod_get_packed_len::() + let account_length = std::mem::size_of::() .checked_add(data.len()) .unwrap(); let transaction = Transaction::new_signed_with_payer( @@ -70,7 +67,8 @@ async fn initialize_success() { .unwrap() .unwrap(); let account_data = - pod_from_bytes::(&account.data[..RecordData::WRITABLE_START_INDEX]).unwrap(); + bytemuck::try_from_bytes::(&account.data[..RecordData::WRITABLE_START_INDEX]) + .unwrap(); assert_eq!(account_data.authority, authority.pubkey()); assert_eq!(account_data.version, RecordData::CURRENT_VERSION); assert_eq!(&account.data[RecordData::WRITABLE_START_INDEX..], data); @@ -84,7 +82,7 @@ async fn initialize_with_seed_success() { let seed = "storage"; let account = Pubkey::create_with_seed(&authority.pubkey(), seed, &id()).unwrap(); let data = &[111u8; 8]; - let account_length = pod_get_packed_len::() + let account_length = std::mem::size_of::() .checked_add(data.len()) .unwrap(); let transaction = Transaction::new_signed_with_payer( @@ -117,7 +115,8 @@ async fn initialize_with_seed_success() { .unwrap() .unwrap(); let account_data = - pod_from_bytes::(&account.data[..RecordData::WRITABLE_START_INDEX]).unwrap(); + bytemuck::try_from_bytes::(&account.data[..RecordData::WRITABLE_START_INDEX]) + .unwrap(); assert_eq!(account_data.authority, authority.pubkey()); assert_eq!(account_data.version, RecordData::CURRENT_VERSION); assert_eq!(&account.data[RecordData::WRITABLE_START_INDEX..], data); @@ -185,7 +184,8 @@ async fn write_success() { .unwrap() .unwrap(); let account_data = - pod_from_bytes::(&account.data[..RecordData::WRITABLE_START_INDEX]).unwrap(); + bytemuck::try_from_bytes::(&account.data[..RecordData::WRITABLE_START_INDEX]) + .unwrap(); assert_eq!(account_data.authority, authority.pubkey()); assert_eq!(account_data.version, RecordData::CURRENT_VERSION); assert_eq!(&account.data[RecordData::WRITABLE_START_INDEX..], new_data); @@ -269,7 +269,7 @@ async fn close_account_success() { let authority = Keypair::new(); let account = Keypair::new(); let data = &[222u8; 8]; - let account_length = pod_get_packed_len::() + let account_length = std::mem::size_of::() .checked_add(data.len()) .unwrap(); initialize_storage_account(&mut context, &authority, &account, data).await; @@ -407,9 +407,10 @@ async fn set_authority_success() { .await .unwrap() .unwrap(); - let account_data = - pod_from_bytes::(&account_handle.data[..RecordData::WRITABLE_START_INDEX]) - .unwrap(); + let account_data = bytemuck::try_from_bytes::( + &account_handle.data[..RecordData::WRITABLE_START_INDEX], + ) + .unwrap(); assert_eq!(account_data.authority, new_authority.pubkey()); let new_data = &[200u8; 8]; @@ -436,9 +437,10 @@ async fn set_authority_success() { .await .unwrap() .unwrap(); - let account_data = - pod_from_bytes::(&account_handle.data[..RecordData::WRITABLE_START_INDEX]) - .unwrap(); + let account_data = bytemuck::try_from_bytes::( + &account_handle.data[..RecordData::WRITABLE_START_INDEX], + ) + .unwrap(); assert_eq!(account_data.authority, new_authority.pubkey()); assert_eq!(account_data.version, RecordData::CURRENT_VERSION); assert_eq!(