diff --git a/Cargo.lock b/Cargo.lock index bd42ecaea07eeb..778727cf8d35e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8338,6 +8338,7 @@ dependencies = [ "solana-signature", "solana-signer", "solana-time-utils", + "solana-transaction-context", "solana-transaction-error", "static_assertions", "thiserror", @@ -8947,6 +8948,24 @@ dependencies = [ "tokio-util 0.7.12", ] +[[package]] +name = "solana-transaction-context" +version = "2.2.0" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-account-info", + "solana-instruction", + "solana-program", + "solana-pubkey", + "solana-rent", + "solana-signature", + "solana-transaction-context", + "static_assertions", +] + [[package]] name = "solana-transaction-dos" version = "2.2.0" diff --git a/Cargo.toml b/Cargo.toml index 09dde285183abd..94e69fae610373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -157,6 +157,7 @@ members = [ "sdk/stable-layout", "sdk/sysvar-id", "sdk/time-utils", + "sdk/transaction-context", "sdk/transaction-error", "send-transaction-service", "stake-accounts", @@ -540,6 +541,7 @@ solana-thin-client = { path = "thin-client", version = "=2.2.0" } solana-transaction-error = { path = "sdk/transaction-error", version = "=2.2.0" } solana-tpu-client = { path = "tpu-client", version = "=2.2.0", default-features = false } solana-tpu-client-next = { path = "tpu-client-next", version = "=2.2.0" } +solana-transaction-context = { path = "sdk/transaction-context", version = "=2.2.0" } solana-transaction-status = { path = "transaction-status", version = "=2.2.0" } solana-transaction-status-client-types = { path = "transaction-status-client-types", version = "=2.2.0" } solana-transaction-metrics-tracker = { path = "transaction-metrics-tracker", version = "=2.2.0" } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 1bfe03cc6ab922..9fffc9889b17a3 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -7070,6 +7070,7 @@ dependencies = [ "solana-signature", "solana-signer", "solana-time-utils", + "solana-transaction-context", "solana-transaction-error", "thiserror", "wasm-bindgen", @@ -7465,6 +7466,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "solana-transaction-context" +version = "2.2.0" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-instruction", + "solana-pubkey", + "solana-rent", + "solana-signature", +] + [[package]] name = "solana-transaction-error" version = "2.2.0" diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index cfef796073044f..1da283e37644e2 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -28,6 +28,7 @@ full = [ "rand0-7", "serde_json", "solana-signature", + "solana-transaction-context/debug-signature", "ed25519-dalek", "libsecp256k1", "sha3", @@ -43,7 +44,11 @@ full = [ "dep:solana-transaction-error" ] borsh = ["dep:borsh", "solana-program/borsh", "solana-secp256k1-recover/borsh"] -dev-context-only-utils = ["qualifier_attr", "solana-account/dev-context-only-utils"] +dev-context-only-utils = [ + "qualifier_attr", + "solana-account/dev-context-only-utils", + "solana-transaction-context/dev-context-only-utils", +] frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", @@ -134,6 +139,9 @@ solana-signature = { workspace = true, features = [ ], optional = true } solana-signer = { workspace = true, optional = true } solana-time-utils = { workspace = true } +solana-transaction-context = { workspace = true, features = [ + "bincode", +] } solana-transaction-error = { workspace = true, features = ["serde"], optional = true } thiserror = { workspace = true } diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 8b52dfa8704d8c..b41f0a4ef7b836 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -104,7 +104,6 @@ pub mod signer; pub mod simple_vote_transaction_checker; pub mod system_transaction; pub mod transaction; -pub mod transaction_context; pub mod transport; pub mod wasm; @@ -190,6 +189,11 @@ pub use solana_serde_varint as serde_varint; pub use solana_short_vec as short_vec; #[deprecated(since = "2.2.0", note = "Use `solana-time-utils` crate instead")] pub use solana_time_utils as timing; +#[deprecated( + since = "2.2.0", + note = "Use `solana-transaction-context` crate instead" +)] +pub use solana_transaction_context as transaction_context; /// Convenience macro for `AddAssign` with saturating arithmetic. /// Replace by `std::num::Saturating` once stable diff --git a/sdk/transaction-context/Cargo.toml b/sdk/transaction-context/Cargo.toml new file mode 100644 index 00000000000000..0ef668c7f357f7 --- /dev/null +++ b/sdk/transaction-context/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "solana-transaction-context" +description = "Solana data shared between program runtime and built-in programs as well as SBF programs." +documentation = "https://docs.rs/solana-transaction-context" +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[dependencies] +serde = { workspace = true, optional = true } +serde_derive = { workspace = true, optional = true } +solana-account = { workspace = true } +solana-instruction = { workspace = true, features = ["std"] } +solana-pubkey = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + +[target.'cfg(not(target_os = "solana"))'.dependencies] +bincode = { workspace = true, optional = true } +solana-rent = { workspace = true } +solana-signature = { workspace = true, optional = true } + +[dev-dependencies] +solana-account-info = { workspace = true } +solana-program = { workspace = true } +solana-transaction-context = { path = ".", features = [ + "dev-context-only-utils", +] } +static_assertions = { workspace = true } + +[features] +bincode = ["dep:bincode", "serde", "solana-account/bincode"] +debug-signature = ["dep:solana-signature"] +dev-context-only-utils = [ + "bincode", + "debug-signature", + "solana-account/dev-context-only-utils" +] +serde = ["dep:serde", "dep:serde_derive"] + +[lints] +workspace = true diff --git a/sdk/src/transaction_context.rs b/sdk/transaction-context/src/lib.rs similarity index 95% rename from sdk/src/transaction_context.rs rename to sdk/transaction-context/src/lib.rs index 6cb9513a127537..33bd6bc986e9bd 100644 --- a/sdk/src/transaction_context.rs +++ b/sdk/transaction-context/src/lib.rs @@ -1,11 +1,19 @@ //! Data shared between program runtime and built-in programs as well as SBF programs. #![deny(clippy::indexing_slicing)] - -#[cfg(all(not(target_os = "solana"), feature = "full", debug_assertions))] -use crate::signature::Signature; +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +#[cfg(all( + not(target_os = "solana"), + feature = "debug-signature", + debug_assertions +))] +use solana_signature::Signature; +#[cfg(not(target_os = "solana"))] +use {solana_account::WritableAccount, solana_rent::Rent, std::mem::MaybeUninit}; use { - crate::{instruction::InstructionError, pubkey::Pubkey}, solana_account::{AccountSharedData, ReadableAccount}, + solana_instruction::error::InstructionError, + solana_pubkey::Pubkey, std::{ cell::{Ref, RefCell, RefMut}, collections::HashSet, @@ -13,18 +21,34 @@ use { rc::Rc, }, }; + +// Inlined to avoid solana_program dep #[cfg(not(target_os = "solana"))] -use { - crate::{ - 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, -}; +const MAX_PERMITTED_DATA_LENGTH: u64 = 10 * 1024 * 1024; +#[cfg(test)] +static_assertions::const_assert_eq!( + MAX_PERMITTED_DATA_LENGTH, + solana_program::system_instruction::MAX_PERMITTED_DATA_LENGTH +); + +// Inlined to avoid solana_program dep +#[cfg(not(target_os = "solana"))] +const MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION: i64 = + MAX_PERMITTED_DATA_LENGTH as i64 * 2; +#[cfg(test)] +static_assertions::const_assert_eq!( + MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION, + solana_program::system_instruction::MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION +); + +// Inlined to avoid solana_account_info dep +#[cfg(not(target_os = "solana"))] +const MAX_PERMITTED_DATA_INCREASE: usize = 1_024 * 10; +#[cfg(test)] +static_assertions::const_assert_eq!( + MAX_PERMITTED_DATA_INCREASE, + solana_account_info::MAX_PERMITTED_DATA_INCREASE +); /// Index of an account inside of the TransactionContext or an InstructionContext. pub type IndexOfAccount = u16; @@ -144,7 +168,11 @@ pub struct TransactionContext { #[cfg(not(target_os = "solana"))] rent: Rent, /// Useful for debugging to filter by or to look it up on the explorer - #[cfg(all(not(target_os = "solana"), feature = "full", debug_assertions))] + #[cfg(all( + not(target_os = "solana"), + feature = "debug-signature", + debug_assertions + ))] signature: Signature, } @@ -172,7 +200,11 @@ impl TransactionContext { accounts_resize_delta: RefCell::new(0), remove_accounts_executable_flag_checks: true, rent, - #[cfg(all(not(target_os = "solana"), feature = "full", debug_assertions))] + #[cfg(all( + not(target_os = "solana"), + feature = "debug-signature", + debug_assertions + ))] signature: Signature::default(), } } @@ -200,13 +232,21 @@ impl TransactionContext { } /// Stores the signature of the current transaction - #[cfg(all(not(target_os = "solana"), feature = "full", debug_assertions))] + #[cfg(all( + not(target_os = "solana"), + feature = "debug-signature", + debug_assertions + ))] pub fn set_signature(&mut self, signature: &Signature) { self.signature = *signature; } /// Returns the signature of the current transaction - #[cfg(all(not(target_os = "solana"), feature = "full", debug_assertions))] + #[cfg(all( + not(target_os = "solana"), + feature = "debug-signature", + debug_assertions + ))] pub fn get_signature(&self) -> &Signature { &self.signature } @@ -445,7 +485,11 @@ impl TransactionContext { } /// Return data at the end of a transaction -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] +#[cfg_attr( + feature = "serde", + derive(serde_derive::Deserialize, serde_derive::Serialize) +)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct TransactionReturnData { pub program_id: Pubkey, pub data: Vec, @@ -969,7 +1013,7 @@ impl<'a> BorrowedAccount<'a> { } /// Deserializes the account data into a state - #[cfg(not(target_os = "solana"))] + #[cfg(all(not(target_os = "solana"), feature = "bincode"))] pub fn get_state(&self) -> Result { self.account .deserialize_data() @@ -977,7 +1021,7 @@ impl<'a> BorrowedAccount<'a> { } /// Serializes a state into the account data - #[cfg(not(target_os = "solana"))] + #[cfg(all(not(target_os = "solana"), feature = "bincode"))] pub fn set_state(&mut self, state: &T) -> Result<(), InstructionError> { let data = self.get_data_mut()?; let serialized_size =