Skip to content

Commit 79efca9

Browse files
committed
feat: add replace_account_source method to manage account source updates
1 parent 6a0d73b commit 79efca9

2 files changed

Lines changed: 66 additions & 20 deletions

File tree

crates/hpsvm/src/accounts_db.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ impl AccountsDb {
196196
self.source = source;
197197
}
198198

199+
pub(crate) fn replace_account_source(
200+
&mut self,
201+
source: Arc<dyn AccountSource>,
202+
) -> Arc<dyn AccountSource> {
203+
std::mem::replace(&mut self.source, source)
204+
}
205+
199206
pub fn get_account_ref(&self, pubkey: &Address) -> Option<&AccountSharedData> {
200207
self.inner.get(pubkey)
201208
}

crates/hpsvm/src/lib.rs

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ use utils::{
345345
#[cfg(feature = "register-tracing")]
346346
use crate::register_tracing::DefaultRegisterTracingCallback;
347347
use crate::{
348+
account_source::EmptyAccountSource,
348349
accounts_db::AccountsDb,
349350
batch::{TransactionBatchError, TransactionBatchExecutionResult, TransactionBatchPlan},
350351
error::HPSVMError,
@@ -622,6 +623,20 @@ impl HPSVM {
622623
}
623624
}
624625

626+
fn with_temporary_account_source<T>(
627+
&mut self,
628+
source: Arc<dyn AccountSource>,
629+
op: impl FnOnce(&mut Self) -> T,
630+
) -> T {
631+
let previous_source = self.accounts.replace_account_source(source);
632+
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| op(self)));
633+
self.accounts.set_account_source(previous_source);
634+
match result {
635+
Ok(result) => result,
636+
Err(payload) => std::panic::resume_unwind(payload),
637+
}
638+
}
639+
625640
#[cfg(feature = "register-tracing")]
626641
/// Create a test environment with debugging features.
627642
///
@@ -856,6 +871,7 @@ impl HPSVM {
856871
let previous_feature_set = self.cfg.feature_set.clone();
857872
let previous_accounts = self.accounts.clone();
858873
let previous_reserved_account_keys = self.reserved_account_keys.clone();
874+
let previous_state_version = self.state_version;
859875

860876
self.cfg.feature_set = feature_set;
861877
self.reserved_account_keys =
@@ -864,6 +880,7 @@ impl HPSVM {
864880
self.cfg.feature_set = previous_feature_set;
865881
self.reserved_account_keys = previous_reserved_account_keys;
866882
self.accounts = previous_accounts;
883+
self.state_version = previous_state_version;
867884
return Err(error);
868885
}
869886

@@ -1164,8 +1181,10 @@ impl HPSVM {
11641181
)
11651182
.expect("failed to create airdrop transaction");
11661183

1167-
self.with_transaction_origin(TransactionOrigin::InternalAirdrop, |svm| {
1168-
svm.send_transaction(tx)
1184+
self.with_temporary_account_source(Arc::new(EmptyAccountSource), |svm| {
1185+
svm.with_transaction_origin(TransactionOrigin::InternalAirdrop, |svm| {
1186+
svm.send_transaction(tx)
1187+
})
11691188
})
11701189
}
11711190

@@ -1381,6 +1400,7 @@ impl HPSVM {
13811400
where
13821401
'a: 'b,
13831402
{
1403+
let mut account_source_failures = Vec::new();
13841404
let compute_budget = hotpath_block!("hpsvm::process_transaction::compute_budget", {
13851405
self.runtime_env.compute_budget.unwrap_or_else(|| ComputeBudget {
13861406
compute_unit_limit: u64::from(compute_budget_limits.compute_unit_limit),
@@ -1534,13 +1554,11 @@ impl HPSVM {
15341554
});
15351555
}
15361556
Err(error) => {
1537-
return Err(execution_result_with_account_source_error(
1538-
*owner_id,
1539-
error,
1540-
TransactionError::ProgramAccountNotFound,
1541-
fee,
1542-
"failed to load owner account from source",
1543-
));
1557+
account_source_failures.push(AccountSourceFailure {
1558+
pubkey: *owner_id,
1559+
error: error.to_string(),
1560+
});
1561+
AccountSharedData::default()
15441562
}
15451563
};
15461564
if !native_loader::check_id(owner_account.owner()) {
@@ -1551,6 +1569,7 @@ impl HPSVM {
15511569
tx_result: Err(TransactionError::InvalidProgramForExecution),
15521570
compute_units_consumed: accumulated_consume_units,
15531571
fee,
1572+
account_source_failures: account_source_failures.clone(),
15541573
..Default::default()
15551574
});
15561575
}
@@ -1560,6 +1579,7 @@ impl HPSVM {
15601579
tx_result: Err(TransactionError::InvalidProgramForExecution),
15611580
compute_units_consumed: accumulated_consume_units,
15621581
fee,
1582+
account_source_failures: account_source_failures.clone(),
15631583
..Default::default()
15641584
});
15651585
}
@@ -1580,11 +1600,12 @@ impl HPSVM {
15801600

15811601
let rent_check = hotpath_block!(
15821602
"hpsvm::process_transaction::check_accounts_rent",
1583-
self.check_accounts_rent(tx, &context, &rent)
1603+
self.check_accounts_rent(tx, &context, &rent, &mut account_source_failures)
15841604
);
15851605
if let Err(mut error) = rent_check {
15861606
error.compute_units_consumed = accumulated_consume_units;
15871607
error.fee = fee;
1608+
error.account_source_failures = account_source_failures;
15881609
return Err(error);
15891610
}
15901611

@@ -1647,6 +1668,7 @@ impl HPSVM {
16471668
},
16481669
fee,
16491670
payer_key,
1671+
account_source_failures,
16501672
})
16511673
}
16521674

@@ -1655,6 +1677,7 @@ impl HPSVM {
16551677
tx: &SanitizedTransaction,
16561678
context: &TransactionContext<'_>,
16571679
rent: &Rent,
1680+
account_source_failures: &mut Vec<AccountSourceFailure>,
16581681
) -> Result<(), ExecutionResult> {
16591682
let message = tx.message();
16601683
for index in 0..message.account_keys().len() {
@@ -1680,13 +1703,11 @@ impl HPSVM {
16801703
Ok(Some(acc)) => get_account_rent_state(rent, acc.lamports(), acc.data().len()),
16811704
Ok(None) => RentState::Uninitialized,
16821705
Err(error) => {
1683-
return Err(execution_result_with_account_source_error(
1684-
*pubkey,
1685-
error,
1686-
TransactionError::AccountNotFound,
1687-
0,
1688-
"failed to load rent pre-state from source",
1689-
));
1706+
account_source_failures.push(AccountSourceFailure {
1707+
pubkey: *pubkey,
1708+
error: error.to_string(),
1709+
});
1710+
RentState::Uninitialized
16901711
}
16911712
};
16921713

@@ -1731,6 +1752,7 @@ impl HPSVM {
17311752
core: CheckAndProcessTransactionSuccessCore { result, compute_units_consumed, context },
17321753
fee,
17331754
payer_key,
1755+
account_source_failures,
17341756
} = match self.check_and_process_transaction(sanitized_tx, log_collector) {
17351757
Ok(value) => value,
17361758
Err(value) => return value,
@@ -1743,9 +1765,16 @@ impl HPSVM {
17431765
compute_units_consumed,
17441766
fee,
17451767
payer_key,
1768+
account_source_failures,
17461769
)
17471770
} else {
1748-
ExecutionResult { tx_result: result, compute_units_consumed, fee, ..Default::default() }
1771+
ExecutionResult {
1772+
tx_result: result,
1773+
compute_units_consumed,
1774+
fee,
1775+
account_source_failures,
1776+
..Default::default()
1777+
}
17491778
}
17501779
}
17511780

@@ -1758,6 +1787,7 @@ impl HPSVM {
17581787
core: CheckAndProcessTransactionSuccessCore { result, compute_units_consumed, context },
17591788
fee,
17601789
payer_key,
1790+
account_source_failures,
17611791
} = match self.check_and_process_transaction(sanitized_tx, log_collector) {
17621792
Ok(value) => value,
17631793
Err(value) => return value,
@@ -1770,9 +1800,16 @@ impl HPSVM {
17701800
compute_units_consumed,
17711801
fee,
17721802
payer_key,
1803+
account_source_failures,
17731804
)
17741805
} else {
1775-
ExecutionResult { tx_result: result, compute_units_consumed, fee, ..Default::default() }
1806+
ExecutionResult {
1807+
tx_result: result,
1808+
compute_units_consumed,
1809+
fee,
1810+
account_source_failures,
1811+
..Default::default()
1812+
}
17761813
}
17771814
}
17781815

@@ -2232,6 +2269,7 @@ struct CheckAndProcessTransactionSuccess<'ix_data> {
22322269
core: CheckAndProcessTransactionSuccessCore<'ix_data>,
22332270
fee: u64,
22342271
payer_key: Option<Address>,
2272+
account_source_failures: Vec<AccountSourceFailure>,
22352273
}
22362274

22372275
fn execution_result_if_context(
@@ -2241,6 +2279,7 @@ fn execution_result_if_context(
22412279
compute_units_consumed: u64,
22422280
fee: u64,
22432281
fee_payer: Option<Address>,
2282+
account_source_failures: Vec<AccountSourceFailure>,
22442283
) -> ExecutionResult {
22452284
let (signature, return_data, inner_instructions, execution_trace, post_accounts) =
22462285
execute_tx_helper(sanitized_tx, ctx);
@@ -2256,7 +2295,7 @@ fn execution_result_if_context(
22562295
included: true,
22572296
fee,
22582297
fee_payer,
2259-
account_source_failures: Vec::new(),
2298+
account_source_failures,
22602299
fatal_error: None,
22612300
}
22622301
}

0 commit comments

Comments
 (0)