Skip to content

Commit 9557d87

Browse files
authored
v2.0: Fix setting an account override for fee payer (backport of #2375) (#2451)
1 parent e86b3cd commit 9557d87

File tree

1 file changed

+73
-2
lines changed

1 file changed

+73
-2
lines changed

svm/src/transaction_processor.rs

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
235235

236236
let (validation_results, validate_fees_time) = measure!(self.validate_fees(
237237
callbacks,
238+
config.account_overrides,
238239
sanitized_txs,
239240
check_results,
240241
&environment.feature_set,
@@ -380,6 +381,7 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
380381
fn validate_fees<CB: TransactionProcessingCallback>(
381382
&self,
382383
callbacks: &CB,
384+
account_overrides: Option<&AccountOverrides>,
383385
sanitized_txs: &[impl core::borrow::Borrow<SanitizedTransaction>],
384386
check_results: Vec<TransactionCheckResult>,
385387
feature_set: &FeatureSet,
@@ -395,6 +397,7 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
395397
let message = sanitized_tx.borrow().message();
396398
self.validate_transaction_fee_payer(
397399
callbacks,
400+
account_overrides,
398401
message,
399402
checked_details,
400403
feature_set,
@@ -413,6 +416,7 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
413416
fn validate_transaction_fee_payer<CB: TransactionProcessingCallback>(
414417
&self,
415418
callbacks: &CB,
419+
account_overrides: Option<&AccountOverrides>,
416420
message: &SanitizedMessage,
417421
checked_details: CheckedTransactionDetails,
418422
feature_set: &FeatureSet,
@@ -429,8 +433,12 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
429433
})?;
430434

431435
let fee_payer_address = message.fee_payer();
432-
let Some(mut fee_payer_account) = callbacks.get_account_shared_data(fee_payer_address)
433-
else {
436+
437+
let fee_payer_account = account_overrides
438+
.and_then(|overrides| overrides.get(fee_payer_address).cloned())
439+
.or_else(|| callbacks.get_account_shared_data(fee_payer_address));
440+
441+
let Some(mut fee_payer_account) = fee_payer_account else {
434442
error_counters.account_not_found += 1;
435443
return Err(TransactionError::AccountNotFound);
436444
};
@@ -2001,6 +2009,7 @@ mod tests {
20012009
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
20022010
let result = batch_processor.validate_transaction_fee_payer(
20032011
&mock_bank,
2012+
None,
20042013
&message,
20052014
CheckedTransactionDetails {
20062015
nonce: None,
@@ -2073,6 +2082,7 @@ mod tests {
20732082
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
20742083
let result = batch_processor.validate_transaction_fee_payer(
20752084
&mock_bank,
2085+
None,
20762086
&message,
20772087
CheckedTransactionDetails {
20782088
nonce: None,
@@ -2120,6 +2130,7 @@ mod tests {
21202130
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
21212131
let result = batch_processor.validate_transaction_fee_payer(
21222132
&mock_bank,
2133+
None,
21232134
&message,
21242135
CheckedTransactionDetails {
21252136
nonce: None,
@@ -2152,6 +2163,7 @@ mod tests {
21522163
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
21532164
let result = batch_processor.validate_transaction_fee_payer(
21542165
&mock_bank,
2166+
None,
21552167
&message,
21562168
CheckedTransactionDetails {
21572169
nonce: None,
@@ -2188,6 +2200,7 @@ mod tests {
21882200
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
21892201
let result = batch_processor.validate_transaction_fee_payer(
21902202
&mock_bank,
2203+
None,
21912204
&message,
21922205
CheckedTransactionDetails {
21932206
nonce: None,
@@ -2222,6 +2235,7 @@ mod tests {
22222235
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
22232236
let result = batch_processor.validate_transaction_fee_payer(
22242237
&mock_bank,
2238+
None,
22252239
&message,
22262240
CheckedTransactionDetails {
22272241
nonce: None,
@@ -2253,6 +2267,7 @@ mod tests {
22532267
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
22542268
let result = batch_processor.validate_transaction_fee_payer(
22552269
&mock_bank,
2270+
None,
22562271
&message,
22572272
CheckedTransactionDetails {
22582273
nonce: None,
@@ -2314,6 +2329,7 @@ mod tests {
23142329
));
23152330
let result = batch_processor.validate_transaction_fee_payer(
23162331
&mock_bank,
2332+
None,
23172333
&message,
23182334
CheckedTransactionDetails {
23192335
nonce: nonce.clone(),
@@ -2371,6 +2387,7 @@ mod tests {
23712387
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
23722388
let result = batch_processor.validate_transaction_fee_payer(
23732389
&mock_bank,
2390+
None,
23742391
&message,
23752392
CheckedTransactionDetails {
23762393
nonce: None,
@@ -2386,4 +2403,58 @@ mod tests {
23862403
assert_eq!(result, Err(TransactionError::InsufficientFundsForFee));
23872404
}
23882405
}
2406+
2407+
#[test]
2408+
fn test_validate_account_override_usage_on_validate_fee() {
2409+
/*
2410+
The test setups an account override with enough lamport to pass validate fee.
2411+
The account_db has the account with minimum rent amount thus would fail the validate_free.
2412+
The test verify that the override is used with a passing test of validate fee.
2413+
*/
2414+
let lamports_per_signature = 5000;
2415+
2416+
let message =
2417+
new_unchecked_sanitized_message(Message::new(&[], Some(&Pubkey::new_unique())));
2418+
2419+
let fee_payer_address = message.fee_payer();
2420+
let transaction_fee = lamports_per_signature;
2421+
let rent_collector = RentCollector::default();
2422+
let min_balance = rent_collector.rent.minimum_balance(0);
2423+
2424+
let fee_payer_account = AccountSharedData::new(min_balance, 0, &Pubkey::default());
2425+
let mut mock_accounts = HashMap::new();
2426+
mock_accounts.insert(*fee_payer_address, fee_payer_account.clone());
2427+
2428+
let necessary_balance = min_balance + transaction_fee;
2429+
let mut account_overrides = AccountOverrides::default();
2430+
let fee_payer_account_override =
2431+
AccountSharedData::new(necessary_balance, 0, &Pubkey::default());
2432+
account_overrides.set_account(fee_payer_address, Some(fee_payer_account_override));
2433+
2434+
let mock_bank = MockBankCallback {
2435+
account_shared_data: Arc::new(RwLock::new(mock_accounts)),
2436+
};
2437+
2438+
let mut error_counters = TransactionErrorMetrics::default();
2439+
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
2440+
2441+
let result = batch_processor.validate_transaction_fee_payer(
2442+
&mock_bank,
2443+
Some(&account_overrides),
2444+
&message,
2445+
CheckedTransactionDetails {
2446+
nonce: None,
2447+
lamports_per_signature,
2448+
},
2449+
&FeatureSet::default(),
2450+
&FeeStructure::default(),
2451+
&rent_collector,
2452+
&mut error_counters,
2453+
);
2454+
assert!(
2455+
result.is_ok(),
2456+
"test_account_override_used: {:?}",
2457+
result.err()
2458+
);
2459+
}
23892460
}

0 commit comments

Comments
 (0)