diff --git a/Cargo.lock b/Cargo.lock index 40a271eb1a6c78..cb555b8e6a64ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5625,6 +5625,22 @@ dependencies = [ "sha-1 0.9.8", ] +[[package]] +name = "solana-account" +version = "2.1.0" +dependencies = [ + "bincode", + "qualifier_attr", + "serde", + "serde_bytes", + "serde_derive", + "solana-account", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-logger", + "solana-program", +] + [[package]] name = "solana-account-decoder" version = "2.1.0" @@ -7814,6 +7830,7 @@ dependencies = [ "sha2 0.10.8", "sha3", "siphasher", + "solana-account", "solana-bn254", "solana-decode-error", "solana-derivation-path", diff --git a/Cargo.toml b/Cargo.toml index a61b7aacad85fc..31ccbcc3186d59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ members = [ "runtime-transaction", "sanitize", "sdk", + "sdk/account", "sdk/account-info", "sdk/atomic-u64", "sdk/cargo-build-sbf", @@ -364,6 +365,7 @@ smallvec = "1.13.2" smpl_jwt = "0.7.1" socket2 = "0.5.7" soketto = "0.7" +solana-account = { path = "sdk/account", version = "=2.1.0" } solana-account-decoder = { path = "account-decoder", version = "=2.1.0" } solana-account-info = { path = "sdk/account-info", version = "=2.1.0" } solana-accounts-db = { path = "accounts-db", version = "=2.1.0" } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index bb2021ea6c2477..e88e06245b7c41 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -4688,6 +4688,18 @@ dependencies = [ "sha-1", ] +[[package]] +name = "solana-account" +version = "2.1.0" +dependencies = [ + "bincode", + "qualifier_attr", + "serde", + "serde_bytes", + "serde_derive", + "solana-program", +] + [[package]] name = "solana-account-decoder" version = "2.1.0" @@ -6596,6 +6608,7 @@ dependencies = [ "sha2 0.10.8", "sha3", "siphasher", + "solana-account", "solana-bn254", "solana-decode-error", "solana-derivation-path", diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 8793f1e58bd1ab..e0e7f132ffec20 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -35,11 +35,12 @@ full = [ "digest", ] borsh = ["dep:borsh", "solana-program/borsh", "solana-secp256k1-recover/borsh"] -dev-context-only-utils = ["qualifier_attr"] +dev-context-only-utils = ["qualifier_attr", "solana-account/dev-context-only-utils"] frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", "solana-feature-set/frozen-abi", + "solana-account/frozen-abi", "solana-program/frozen-abi", "solana-short-vec/frozen-abi", "solana-signature/frozen-abi" @@ -83,6 +84,7 @@ serde_with = { workspace = true, features = ["macros"] } sha2 = { workspace = true } sha3 = { workspace = true, optional = true } siphasher = { workspace = true } +solana-account = { workspace = true, features = ["bincode"] } solana-bn254 = { workspace = true } solana-decode-error = { workspace = true } solana-derivation-path = { workspace = true } diff --git a/sdk/account/Cargo.toml b/sdk/account/Cargo.toml new file mode 100644 index 00000000000000..33d210778f08e5 --- /dev/null +++ b/sdk/account/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "solana-account" +description = "Solana Account type" +documentation = "https://docs.rs/solana-account" +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[dependencies] +bincode = { workspace = true, optional = true } +qualifier_attr = { workspace = true, optional = true } +serde = { workspace = true, optional = true } +serde_bytes = { workspace = true, optional = true } +serde_derive = { workspace = true, optional = true } +solana-frozen-abi = { workspace = true, optional = true } +solana-frozen-abi-macro = { workspace = true, optional = true } +solana-logger = { workspace = true, optional = true } +solana-program = { workspace = true } + +[dev-dependencies] +solana-account = { path = ".", features = ["dev-context-only-utils"] } + +[features] +bincode = ["dep:bincode", "serde"] +dev-context-only-utils = ["bincode", "dep:qualifier_attr"] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "dep:solana-logger", + "solana-program/frozen-abi", +] +serde = ["dep:serde", "dep:serde_bytes", "dep:serde_derive"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/sdk/src/account.rs b/sdk/account/src/lib.rs similarity index 95% rename from sdk/src/account.rs rename to sdk/account/src/lib.rs index cb7dfbc9638c3e..c2bcbbfd02c916 100644 --- a/sdk/src/account.rs +++ b/sdk/account/src/lib.rs @@ -1,20 +1,24 @@ +#![cfg_attr(feature = "frozen-abi", feature(min_specialization))] //! The Solana [`Account`] type. #[cfg(feature = "dev-context-only-utils")] use qualifier_attr::qualifiers; +#[cfg(feature = "serde")] +use serde::ser::{Serialize, Serializer}; +#[cfg(feature = "frozen-abi")] +use solana_frozen_abi_macro::{frozen_abi, AbiExample}; +#[cfg(feature = "bincode")] +use solana_program::sysvar::Sysvar; use { - crate::{ + solana_program::{ + account_info::AccountInfo, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock::{Epoch, INITIAL_RENT_EPOCH}, + debug_account_data::*, lamports::LamportsError, loader_v4, pubkey::Pubkey, }, - serde::{ - ser::{Serialize, Serializer}, - Deserialize, - }, - solana_program::{account_info::AccountInfo, debug_account_data::*, sysvar::Sysvar}, std::{ cell::{Ref, RefCell}, fmt, @@ -32,13 +36,17 @@ use { derive(AbiExample), frozen_abi(digest = "2SUJNHbXMPWrsSXmDTFc4VHx2XQ85fT5Leabefh5Nwe7") )] -#[derive(Deserialize, PartialEq, Eq, Clone, Default)] -#[serde(rename_all = "camelCase")] +#[cfg_attr( + feature = "serde", + derive(serde_derive::Deserialize), + serde(rename_all = "camelCase") +)] +#[derive(PartialEq, Eq, Clone, Default)] pub struct Account { /// lamports in the account pub lamports: u64, /// data held in this account - #[serde(with = "serde_bytes")] + #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))] pub data: Vec, /// the program that owns this account. If executable, the program that loads this account. pub owner: Pubkey, @@ -49,10 +57,14 @@ pub struct Account { } // mod because we need 'Account' below to have the name 'Account' to match expected serialization +#[cfg(feature = "serde")] mod account_serialize { + #[cfg(feature = "frozen-abi")] + use solana_frozen_abi_macro::{frozen_abi, AbiExample}; use { - crate::{account::ReadableAccount, clock::Epoch, pubkey::Pubkey}, + crate::ReadableAccount, serde::{ser::Serializer, Serialize}, + solana_program::{clock::Epoch, pubkey::Pubkey}, }; #[repr(C)] #[cfg_attr( @@ -60,7 +72,7 @@ mod account_serialize { derive(AbiExample), frozen_abi(digest = "2SUJNHbXMPWrsSXmDTFc4VHx2XQ85fT5Leabefh5Nwe7") )] - #[derive(Serialize)] + #[derive(serde_derive::Serialize)] #[serde(rename_all = "camelCase")] struct Account<'a> { lamports: u64, @@ -91,21 +103,23 @@ mod account_serialize { } } +#[cfg(feature = "serde")] impl Serialize for Account { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - crate::account::account_serialize::serialize_account(self, serializer) + crate::account_serialize::serialize_account(self, serializer) } } +#[cfg(feature = "serde")] impl Serialize for AccountSharedData { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - crate::account::account_serialize::serialize_account(self, serializer) + crate::account_serialize::serialize_account(self, serializer) } } @@ -113,8 +127,12 @@ impl Serialize for AccountSharedData { /// This will be the in-memory representation of the 'Account' struct data. /// The existing 'Account' structure cannot easily change due to downstream projects. #[cfg_attr(feature = "frozen-abi", derive(AbiExample))] -#[derive(PartialEq, Eq, Clone, Default, Deserialize)] -#[serde(from = "Account")] +#[cfg_attr( + feature = "serde", + derive(serde_derive::Deserialize), + serde(from = "Account") +)] +#[derive(PartialEq, Eq, Clone, Default)] pub struct AccountSharedData { /// lamports in the account lamports: u64, @@ -435,6 +453,7 @@ fn shared_new_ref( Rc::new(RefCell::new(shared_new::(lamports, space, owner))) } +#[cfg(feature = "bincode")] fn shared_new_data( lamports: u64, state: &T, @@ -449,6 +468,8 @@ fn shared_new_data( Epoch::default(), )) } + +#[cfg(feature = "bincode")] fn shared_new_ref_data( lamports: u64, state: &T, @@ -459,6 +480,7 @@ fn shared_new_ref_data( )?)) } +#[cfg(feature = "bincode")] fn shared_new_data_with_space( lamports: u64, state: &T, @@ -471,6 +493,8 @@ fn shared_new_data_with_space( Ok(account) } + +#[cfg(feature = "bincode")] fn shared_new_ref_data_with_space( lamports: u64, state: &T, @@ -482,12 +506,14 @@ fn shared_new_ref_data_with_space( )?)) } +#[cfg(feature = "bincode")] fn shared_deserialize_data( account: &U, ) -> Result { bincode::deserialize(account.data()) } +#[cfg(feature = "bincode")] fn shared_serialize_data( account: &mut U, state: &T, @@ -505,6 +531,7 @@ impl Account { pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc> { shared_new_ref(lamports, space, owner) } + #[cfg(feature = "bincode")] pub fn new_data( lamports: u64, state: &T, @@ -512,6 +539,7 @@ impl Account { ) -> Result { shared_new_data(lamports, state, owner) } + #[cfg(feature = "bincode")] pub fn new_ref_data( lamports: u64, state: &T, @@ -519,6 +547,7 @@ impl Account { ) -> Result, bincode::Error> { shared_new_ref_data(lamports, state, owner) } + #[cfg(feature = "bincode")] pub fn new_data_with_space( lamports: u64, state: &T, @@ -527,6 +556,7 @@ impl Account { ) -> Result { shared_new_data_with_space(lamports, state, space, owner) } + #[cfg(feature = "bincode")] pub fn new_ref_data_with_space( lamports: u64, state: &T, @@ -538,9 +568,11 @@ impl Account { pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self { shared_new_rent_epoch(lamports, space, owner, rent_epoch) } + #[cfg(feature = "bincode")] pub fn deserialize_data(&self) -> Result { shared_deserialize_data(self) } + #[cfg(feature = "bincode")] pub fn serialize_data(&mut self, state: &T) -> Result<(), bincode::Error> { shared_serialize_data(self, state) } @@ -631,6 +663,7 @@ impl AccountSharedData { pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc> { shared_new_ref(lamports, space, owner) } + #[cfg(feature = "bincode")] pub fn new_data( lamports: u64, state: &T, @@ -638,6 +671,7 @@ impl AccountSharedData { ) -> Result { shared_new_data(lamports, state, owner) } + #[cfg(feature = "bincode")] pub fn new_ref_data( lamports: u64, state: &T, @@ -645,6 +679,7 @@ impl AccountSharedData { ) -> Result, bincode::Error> { shared_new_ref_data(lamports, state, owner) } + #[cfg(feature = "bincode")] pub fn new_data_with_space( lamports: u64, state: &T, @@ -653,6 +688,7 @@ impl AccountSharedData { ) -> Result { shared_new_data_with_space(lamports, state, space, owner) } + #[cfg(feature = "bincode")] pub fn new_ref_data_with_space( lamports: u64, state: &T, @@ -664,9 +700,11 @@ impl AccountSharedData { pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self { shared_new_rent_epoch(lamports, space, owner, rent_epoch) } + #[cfg(feature = "bincode")] pub fn deserialize_data(&self) -> Result { shared_deserialize_data(self) } + #[cfg(feature = "bincode")] pub fn serialize_data(&mut self, state: &T) -> Result<(), bincode::Error> { shared_serialize_data(self, state) } @@ -675,6 +713,7 @@ impl AccountSharedData { pub type InheritableAccountFields = (u64, Epoch); pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH); +#[cfg(feature = "bincode")] pub fn create_account_with_fields( sysvar: &S, (lamports, rent_epoch): InheritableAccountFields, @@ -686,10 +725,12 @@ pub fn create_account_with_fields( account } +#[cfg(feature = "bincode")] pub fn create_account_for_test(sysvar: &S) -> Account { create_account_with_fields(sysvar, DUMMY_INHERITABLE_ACCOUNT_FIELDS) } +#[cfg(feature = "bincode")] /// Create an `Account` from a `Sysvar`. pub fn create_account_shared_data_with_fields( sysvar: &S, @@ -698,6 +739,7 @@ pub fn create_account_shared_data_with_fields( AccountSharedData::from(create_account_with_fields(sysvar, fields)) } +#[cfg(feature = "bincode")] pub fn create_account_shared_data_for_test(sysvar: &S) -> AccountSharedData { AccountSharedData::from(create_account_with_fields( sysvar, @@ -705,11 +747,13 @@ pub fn create_account_shared_data_for_test(sysvar: &S) -> AccountShar )) } +#[cfg(feature = "bincode")] /// Create a `Sysvar` from an `Account`'s data. pub fn from_account(account: &T) -> Option { bincode::deserialize(account.data()).ok() } +#[cfg(feature = "bincode")] /// Serialize a `Sysvar` into an `Account`'s data. pub fn to_account(sysvar: &S, account: &mut T) -> Option<()> { bincode::serialize_into(account.data_as_mut_slice(), sysvar).ok() diff --git a/sdk/src/account_utils.rs b/sdk/src/account_utils.rs index e6e6a7bccd1b2b..7338d64cc33498 100644 --- a/sdk/src/account_utils.rs +++ b/sdk/src/account_utils.rs @@ -1,11 +1,9 @@ //! Useful extras for `Account` state. use { - crate::{ - account::{Account, AccountSharedData}, - instruction::InstructionError, - }, + crate::instruction::InstructionError, bincode::ErrorKind, + solana_account::{Account, AccountSharedData}, std::cell::Ref, }; @@ -66,10 +64,7 @@ where #[cfg(test)] mod tests { - use { - super::*, - crate::{account::AccountSharedData, pubkey::Pubkey}, - }; + use {super::*, crate::pubkey::Pubkey, solana_account::AccountSharedData}; #[test] fn test_account_state() { diff --git a/sdk/src/client.rs b/sdk/src/client.rs index 185b9aeeb0d40b..f33f31d478f6af 100644 --- a/sdk/src/client.rs +++ b/sdk/src/client.rs @@ -9,21 +9,23 @@ #![cfg(feature = "full")] -use crate::{ - account::Account, - clock::Slot, - commitment_config::CommitmentConfig, - epoch_info::EpochInfo, - hash::Hash, - instruction::Instruction, - message::Message, - pubkey::Pubkey, - signature::{Keypair, Signature}, - signer::Signer, - signers::Signers, - system_instruction, - transaction::{self, Transaction, VersionedTransaction}, - transport::Result, +use { + crate::{ + clock::Slot, + commitment_config::CommitmentConfig, + epoch_info::EpochInfo, + hash::Hash, + instruction::Instruction, + message::Message, + pubkey::Pubkey, + signature::{Keypair, Signature}, + signer::Signer, + signers::Signers, + system_instruction, + transaction::{self, Transaction, VersionedTransaction}, + transport::Result, + }, + solana_account::Account, }; pub trait Client: SyncClient + AsyncClient { diff --git a/sdk/src/feature.rs b/sdk/src/feature.rs index bca42e7bb6d327..a59e38ff0d252f 100644 --- a/sdk/src/feature.rs +++ b/sdk/src/feature.rs @@ -1,6 +1,6 @@ //! Methods for working with `Feature` accounts. -use crate::account::{AccountSharedData, ReadableAccount, WritableAccount}; +use solana_account::{AccountSharedData, ReadableAccount, WritableAccount}; pub use solana_program::feature::*; pub fn from_account(account: &T) -> Option { diff --git a/sdk/src/genesis_config.rs b/sdk/src/genesis_config.rs index 8e3f89f254830e..24208a76363dbf 100644 --- a/sdk/src/genesis_config.rs +++ b/sdk/src/genesis_config.rs @@ -4,7 +4,6 @@ use { crate::{ - account::{Account, AccountSharedData}, clock::{UnixTimestamp, DEFAULT_TICKS_PER_SLOT}, epoch_schedule::EpochSchedule, fee_calculator::FeeRateGovernor, @@ -22,6 +21,7 @@ use { bincode::{deserialize, serialize}, chrono::{TimeZone, Utc}, memmap2::Mmap, + solana_account::{Account, AccountSharedData}, std::{ collections::BTreeMap, fmt, @@ -87,7 +87,7 @@ impl FromStr for ClusterType { #[cfg_attr( feature = "frozen-abi", derive(AbiExample), - frozen_abi(digest = "GDkrvVXezJYuGHcKSK19wvPBUMfKsifKQtoBxH1RpriL") + frozen_abi(digest = "2eGYc5mpKqDsS8sZfNS4mVq4qPptXYa9hSid2Hpv4DkQ") )] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct GenesisConfig { diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 07c92473cbb46a..11f65d40eedaec 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -58,7 +58,6 @@ pub use solana_program::{ }; #[cfg(feature = "borsh")] pub use solana_program::{borsh, borsh0_10, borsh1}; -pub mod account; pub mod account_utils; pub mod client; pub mod commitment_config; @@ -107,6 +106,8 @@ pub mod transaction_context; pub mod transport; pub mod wasm; +#[deprecated(since = "2.1.0", note = "Use `solana-account` crate instead")] +pub use solana_account as account; #[deprecated(since = "2.1.0", note = "Use `solana-bn254` crate instead")] pub use solana_bn254 as alt_bn128; #[deprecated(since = "2.1.0", note = "Use `solana-decode-error` crate instead")] diff --git a/sdk/src/native_loader.rs b/sdk/src/native_loader.rs index 53a7ded4b61f54..1f32d3988fcf58 100644 --- a/sdk/src/native_loader.rs +++ b/sdk/src/native_loader.rs @@ -1,6 +1,6 @@ //! The native loader native program. -use crate::account::{ +use solana_account::{ Account, AccountSharedData, InheritableAccountFields, DUMMY_INHERITABLE_ACCOUNT_FIELDS, }; diff --git a/sdk/src/nonce_account.rs b/sdk/src/nonce_account.rs index 255011a7bb6402..f2127790345b92 100644 --- a/sdk/src/nonce_account.rs +++ b/sdk/src/nonce_account.rs @@ -2,7 +2,6 @@ use { crate::{ - account::{AccountSharedData, ReadableAccount}, account_utils::StateMut, hash::Hash, nonce::{ @@ -10,6 +9,7 @@ use { State, }, }, + solana_account::{AccountSharedData, ReadableAccount}, std::cell::RefCell, }; diff --git a/sdk/src/rent_collector.rs b/sdk/src/rent_collector.rs index 96a7e479db76a6..4be46786a1de12 100644 --- a/sdk/src/rent_collector.rs +++ b/sdk/src/rent_collector.rs @@ -1,14 +1,16 @@ #![cfg(feature = "full")] //! calculate and collect rent from Accounts -use solana_sdk::{ - account::{AccountSharedData, ReadableAccount, WritableAccount}, - clock::Epoch, - epoch_schedule::EpochSchedule, - genesis_config::GenesisConfig, - incinerator, - pubkey::Pubkey, - rent::{Rent, RentDue}, +use { + solana_account::{AccountSharedData, ReadableAccount, WritableAccount}, + solana_sdk::{ + clock::Epoch, + epoch_schedule::EpochSchedule, + genesis_config::GenesisConfig, + incinerator, + pubkey::Pubkey, + rent::{Rent, RentDue}, + }, }; #[cfg_attr(feature = "frozen-abi", derive(AbiExample))] @@ -213,11 +215,7 @@ impl std::ops::AddAssign for CollectedInfo { #[cfg(test)] mod tests { - use { - super::*, - assert_matches::assert_matches, - solana_sdk::{account::Account, sysvar}, - }; + use {super::*, assert_matches::assert_matches, solana_account::Account, solana_sdk::sysvar}; fn default_rent_collector_clone_with_epoch(epoch: Epoch) -> RentCollector { RentCollector::default().clone_with_epoch(epoch) diff --git a/sdk/src/transaction_context.rs b/sdk/src/transaction_context.rs index 0bb2f0ec983659..95f65c3af55fe0 100644 --- a/sdk/src/transaction_context.rs +++ b/sdk/src/transaction_context.rs @@ -3,31 +3,28 @@ #[cfg(all(not(target_os = "solana"), feature = "full", debug_assertions))] use crate::signature::Signature; +use { + crate::{instruction::InstructionError, pubkey::Pubkey}, + solana_account::{AccountSharedData, ReadableAccount}, + std::{ + cell::{Ref, RefCell, RefMut}, + collections::HashSet, + pin::Pin, + rc::Rc, + }, +}; #[cfg(not(target_os = "solana"))] use { crate::{ - account::WritableAccount, rent::Rent, system_instruction::{ MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION, MAX_PERMITTED_DATA_LENGTH, }, }, + solana_account::WritableAccount, solana_program::entrypoint::MAX_PERMITTED_DATA_INCREASE, std::mem::MaybeUninit, }; -use { - crate::{ - account::{AccountSharedData, ReadableAccount}, - instruction::InstructionError, - pubkey::Pubkey, - }, - std::{ - cell::{Ref, RefCell, RefMut}, - collections::HashSet, - pin::Pin, - rc::Rc, - }, -}; /// Index of an account inside of the TransactionContext or an InstructionContext. pub type IndexOfAccount = u16;