Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions programs/sbf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 1 addition & 10 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5673,20 +5673,11 @@ impl InvokeContextCallback for Bank {
}

impl TransactionProcessingCallback for Bank {
fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
self.rc
.accounts
.accounts_db
.account_matches_owners(&self.ancestors, account, owners)
.ok()
}

fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
self.rc
.accounts
.accounts_db
.load_with_fixed_root(&self.ancestors, pubkey)
.map(|(acc, _)| acc)
}

// NOTE: must hold idempotent for the same set of arguments
Expand Down
1 change: 1 addition & 0 deletions svm-callback/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ readme = false

[dependencies]
solana-account = { workspace = true }
solana-clock = { workspace = true }
solana-precompile-error = { workspace = true }
solana-pubkey = { workspace = true }

Expand Down
8 changes: 3 additions & 5 deletions svm-callback/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
solana_account::AccountSharedData, solana_precompile_error::PrecompileError,
solana_pubkey::Pubkey,
solana_account::AccountSharedData, solana_clock::Slot,
solana_precompile_error::PrecompileError, solana_pubkey::Pubkey,
};

/// Callback used by InvokeContext in SVM
Expand Down Expand Up @@ -33,9 +33,7 @@ pub trait InvokeContextCallback {

/// Runtime callbacks for transaction processing.
pub trait TransactionProcessingCallback: InvokeContextCallback {
fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize>;

fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData>;
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)>;

fn add_builtin_account(&self, _name: &str, _program_id: &Pubkey) {}

Expand Down
4 changes: 1 addition & 3 deletions svm/doc/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,7 @@ information.

```rust
pub trait TransactionProcessingCallback {
fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize>;

fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData>;
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)>;

fn add_builtin_account(&self, _name: &str, _program_id: &Pubkey) {}

Expand Down
33 changes: 16 additions & 17 deletions svm/src/account_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use {
state_traits::StateMut, Account, AccountSharedData, ReadableAccount, WritableAccount,
PROGRAM_OWNERS,
},
solana_clock::Slot,
solana_fee_structure::FeeDetails,
solana_instruction::{BorrowedAccountMeta, BorrowedInstruction},
solana_instructions_sysvar::construct_instructions_data,
Expand Down Expand Up @@ -258,7 +259,7 @@ impl<'a, CB: TransactionProcessingCallback> AccountLoader<'a, CB> {
};

(option_account, false)
} else if let Some(account) = self.callbacks.get_account_shared_data(account_key) {
} else if let Some((account, _slot)) = self.callbacks.get_account_shared_data(account_key) {
(Some(account), true)
} else {
(None, false)
Expand Down Expand Up @@ -318,14 +319,8 @@ impl<'a, CB: TransactionProcessingCallback> AccountLoader<'a, CB> {
// In general, most accounts we load this way should already be in our accounts store.
// Once SIMD-0186 is implemented, 100% of accounts will be.
impl<CB: TransactionProcessingCallback> TransactionProcessingCallback for AccountLoader<'_, CB> {
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
self.do_load(pubkey).0
}

fn account_matches_owners(&self, pubkey: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
self.do_load(pubkey)
.0
.and_then(|account| owners.iter().position(|entry| entry == account.owner()))
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
self.do_load(pubkey).0.map(|account| (account, 0))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a path used in production. Would you mind explaining here why the slot does not matter?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explaining = adding a comment in the code.

Copy link
Author

@Lichtso Lichtso Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will matter, but not in this PR. It is only to get the interface changes at the v3.0 version bump. So for now, the slot is a dummy. I did add a comment in the last commit.

}
}

Expand Down Expand Up @@ -890,12 +885,10 @@ mod tests {
impl InvokeContextCallback for TestCallbacks {}

impl TransactionProcessingCallback for TestCallbacks {
fn account_matches_owners(&self, _account: &Pubkey, _owners: &[Pubkey]) -> Option<usize> {
None
}

fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
self.accounts_map.get(pubkey).cloned()
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
self.accounts_map
.get(pubkey)
.map(|account| (account.clone(), 0))
}

fn inspect_account(
Expand Down Expand Up @@ -2758,7 +2751,10 @@ mod tests {

let account_loader: AccountLoader<_> = (&mock_bank).into();
assert_eq!(
account_loader.get_account_shared_data(&fee_payer).unwrap(),
account_loader
.get_account_shared_data(&fee_payer)
.unwrap()
.0,
fee_payer_account
);

Expand All @@ -2785,7 +2781,10 @@ mod tests {
fee_payer_account
);
assert_eq!(
account_loader.get_account_shared_data(&fee_payer).unwrap(),
account_loader
.get_account_shared_data(&fee_payer)
.unwrap()
.0,
fee_payer_account
);

Expand Down
29 changes: 11 additions & 18 deletions svm/src/program_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub(crate) fn load_program_accounts<CB: TransactionProcessingCallback>(
callbacks: &CB,
pubkey: &Pubkey,
) -> Option<ProgramAccountLoadResult> {
let program_account = callbacks.get_account_shared_data(pubkey)?;
let (program_account, _slot) = callbacks.get_account_shared_data(pubkey)?;

if loader_v4::check_id(program_account.owner()) {
return Some(
Expand Down Expand Up @@ -92,7 +92,9 @@ pub(crate) fn load_program_accounts<CB: TransactionProcessingCallback>(
programdata_address,
}) = program_account.state()
{
if let Some(programdata_account) = callbacks.get_account_shared_data(&programdata_address) {
if let Some((programdata_account, _slot)) =
callbacks.get_account_shared_data(&programdata_address)
{
if let Ok(UpgradeableLoaderState::ProgramData {
slot,
upgrade_authority_address: _,
Expand Down Expand Up @@ -217,15 +219,15 @@ pub(crate) fn get_program_modification_slot<CB: TransactionProcessingCallback>(
callbacks: &CB,
pubkey: &Pubkey,
) -> TransactionResult<Slot> {
let program = callbacks
let (program, _slot) = callbacks
.get_account_shared_data(pubkey)
.ok_or(TransactionError::ProgramAccountNotFound)?;
if bpf_loader_upgradeable::check_id(program.owner()) {
if let Ok(UpgradeableLoaderState::Program {
programdata_address,
}) = program.state()
{
let programdata = callbacks
let (programdata, _slot) = callbacks
.get_account_shared_data(&programdata_address)
.ok_or(TransactionError::ProgramAccountNotFound)?;
if let Ok(UpgradeableLoaderState::ProgramData {
Expand Down Expand Up @@ -283,20 +285,11 @@ mod tests {
impl InvokeContextCallback for MockBankCallback {}

impl TransactionProcessingCallback for MockBankCallback {
fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
if let Some(data) = self.account_shared_data.borrow().get(account) {
if data.lamports() == 0 {
None
} else {
owners.iter().position(|entry| data.owner() == entry)
}
} else {
None
}
}

fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
self.account_shared_data.borrow().get(pubkey).cloned()
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
self.account_shared_data
.borrow()
.get(pubkey)
.map(|account| (account.clone(), 0))
}

fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
Expand Down
24 changes: 6 additions & 18 deletions svm/src/transaction_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,13 +712,13 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
if let Some(cache_entry) = program_cache_for_tx_batch.find(account_key) {
cache_entry.tx_usage_counter.fetch_add(1, Ordering::Relaxed);
} else if account_loader
.account_matches_owners(account_key, PROGRAM_OWNERS)
.is_some()
.get_account_shared_data(account_key)
.map(|(account, _slot)| PROGRAM_OWNERS.contains(account.owner()))
.unwrap_or(false)
{
program_accounts_set.insert(*account_key);
}
}

program_accounts_set
}

Expand Down Expand Up @@ -1040,7 +1040,7 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
) {
let mut sysvar_cache = self.sysvar_cache.write().unwrap();
sysvar_cache.fill_missing_entries(|pubkey, set_sysvar| {
if let Some(account) = callbacks.get_account_shared_data(pubkey) {
if let Some((account, _slot)) = callbacks.get_account_shared_data(pubkey) {
set_sysvar(account.data());
}
});
Expand Down Expand Up @@ -1160,24 +1160,12 @@ mod tests {
impl InvokeContextCallback for MockBankCallback {}

impl TransactionProcessingCallback for MockBankCallback {
fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
if let Some(data) = self.account_shared_data.read().unwrap().get(account) {
if data.lamports() == 0 {
None
} else {
owners.iter().position(|entry| data.owner() == entry)
}
} else {
None
}
}

fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
self.account_shared_data
.read()
.unwrap()
.get(pubkey)
.cloned()
.map(|account| (account.clone(), 0))
}

fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
Expand Down
16 changes: 2 additions & 14 deletions svm/tests/mock_bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,12 @@ pub struct MockBankCallback {
impl InvokeContextCallback for MockBankCallback {}

impl TransactionProcessingCallback for MockBankCallback {
fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
if let Some(data) = self.account_shared_data.read().unwrap().get(account) {
if data.lamports() == 0 {
None
} else {
owners.iter().position(|entry| data.owner() == entry)
}
} else {
None
}
}

fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
self.account_shared_data
.read()
.unwrap()
.get(pubkey)
.cloned()
.map(|account| (account.clone(), 0))
}

fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
Expand Down
Loading