Skip to content

Commit c6a7130

Browse files
v2.1: Store epoch in MaxAge (backport of #3485) (#3502)
* Store epoch in MaxAge (#3485) (cherry picked from commit 5a6f518) # Conflicts: # core/src/banking_stage/scheduler_messages.rs # core/src/banking_stage/transaction_scheduler/transaction_state.rs # core/src/banking_stage/transaction_scheduler/transaction_state_container.rs * resolve conflicts --------- Co-authored-by: Andrew Fitzgerald <[email protected]>
1 parent c1bddce commit c6a7130

File tree

7 files changed

+56
-72
lines changed

7 files changed

+56
-72
lines changed

core/src/banking_stage/consume_worker.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,12 @@ mod tests {
783783
..
784784
} = create_slow_genesis_config(10_000);
785785
let (bank, bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
786-
let bank = Arc::new(Bank::new_from_parent(bank, &Pubkey::new_unique(), 1));
786+
// Warp to next epoch for MaxAge tests.
787+
let bank = Arc::new(Bank::new_from_parent(
788+
bank.clone(),
789+
&Pubkey::new_unique(),
790+
bank.get_epoch_info().slots_in_epoch,
791+
));
787792

788793
let ledger_path = get_tmp_ledger_path_auto_delete!();
789794
let blockstore = Blockstore::open(ledger_path.path())
@@ -863,7 +868,7 @@ mod tests {
863868
let bid = TransactionBatchId::new(0);
864869
let id = TransactionId::new(0);
865870
let max_age = MaxAge {
866-
epoch_invalidation_slot: bank.slot(),
871+
sanitized_epoch: bank.epoch(),
867872
alt_invalidation_slot: bank.slot(),
868873
};
869874
let work = ConsumeWork {
@@ -912,7 +917,7 @@ mod tests {
912917
let bid = TransactionBatchId::new(0);
913918
let id = TransactionId::new(0);
914919
let max_age = MaxAge {
915-
epoch_invalidation_slot: bank.slot(),
920+
sanitized_epoch: bank.epoch(),
916921
alt_invalidation_slot: bank.slot(),
917922
};
918923
let work = ConsumeWork {
@@ -962,7 +967,7 @@ mod tests {
962967
let id1 = TransactionId::new(1);
963968
let id2 = TransactionId::new(0);
964969
let max_age = MaxAge {
965-
epoch_invalidation_slot: bank.slot(),
970+
sanitized_epoch: bank.epoch(),
966971
alt_invalidation_slot: bank.slot(),
967972
};
968973
consume_sender
@@ -1023,7 +1028,7 @@ mod tests {
10231028
let id1 = TransactionId::new(1);
10241029
let id2 = TransactionId::new(0);
10251030
let max_age = MaxAge {
1026-
epoch_invalidation_slot: bank.slot(),
1031+
sanitized_epoch: bank.epoch(),
10271032
alt_invalidation_slot: bank.slot(),
10281033
};
10291034
consume_sender
@@ -1077,6 +1082,7 @@ mod tests {
10771082
.unwrap()
10781083
.set_bank_for_test(bank.clone());
10791084
assert!(bank.slot() > 0);
1085+
assert!(bank.epoch() > 0);
10801086

10811087
// No conflicts between transactions. Test 6 cases.
10821088
// 1. Epoch expiration, before slot => still succeeds due to resanitizing
@@ -1161,27 +1167,27 @@ mod tests {
11611167
transactions: txs,
11621168
max_ages: vec![
11631169
MaxAge {
1164-
epoch_invalidation_slot: bank.slot() - 1,
1170+
sanitized_epoch: bank.epoch() - 1,
11651171
alt_invalidation_slot: Slot::MAX,
11661172
},
11671173
MaxAge {
1168-
epoch_invalidation_slot: bank.slot(),
1174+
sanitized_epoch: bank.epoch(),
11691175
alt_invalidation_slot: Slot::MAX,
11701176
},
11711177
MaxAge {
1172-
epoch_invalidation_slot: bank.slot() + 1,
1178+
sanitized_epoch: bank.epoch() + 1,
11731179
alt_invalidation_slot: Slot::MAX,
11741180
},
11751181
MaxAge {
1176-
epoch_invalidation_slot: u64::MAX,
1182+
sanitized_epoch: bank.epoch(),
11771183
alt_invalidation_slot: bank.slot() - 1,
11781184
},
11791185
MaxAge {
1180-
epoch_invalidation_slot: u64::MAX,
1186+
sanitized_epoch: bank.epoch(),
11811187
alt_invalidation_slot: bank.slot(),
11821188
},
11831189
MaxAge {
1184-
epoch_invalidation_slot: u64::MAX,
1190+
sanitized_epoch: bank.epoch(),
11851191
alt_invalidation_slot: bank.slot() + 1,
11861192
},
11871193
],

core/src/banking_stage/consumer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,8 @@ impl Consumer {
442442
let pre_results = txs.iter().zip(max_ages).map(|(tx, max_age)| {
443443
// If the transaction was sanitized before this bank's epoch,
444444
// additional checks are necessary.
445-
if bank.slot() > max_age.epoch_invalidation_slot {
446-
// Reserved key set may have cahnged, so we must verify that
445+
if bank.epoch() != max_age.sanitized_epoch {
446+
// Reserved key set may have changed, so we must verify that
447447
// no writable keys are reserved.
448448
bank.check_reserved_keys(tx)?;
449449
}

core/src/banking_stage/scheduler_messages.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use {
2-
solana_sdk::{clock::Slot, transaction::SanitizedTransaction},
2+
solana_sdk::{
3+
clock::{Epoch, Slot},
4+
transaction::SanitizedTransaction,
5+
},
36
std::fmt::Display,
47
};
58

@@ -37,10 +40,17 @@ impl Display for TransactionId {
3740

3841
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3942
pub struct MaxAge {
40-
pub epoch_invalidation_slot: Slot,
43+
pub sanitized_epoch: Epoch,
4144
pub alt_invalidation_slot: Slot,
4245
}
4346

47+
impl MaxAge {
48+
pub const MAX: Self = Self {
49+
sanitized_epoch: Epoch::MAX,
50+
alt_invalidation_slot: Slot::MAX,
51+
};
52+
}
53+
4454
/// Message: [Scheduler -> Worker]
4555
/// Transactions to be consumed (i.e. executed, recorded, and committed)
4656
pub struct ConsumeWork {

core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,8 @@ mod tests {
618618
crossbeam_channel::{unbounded, Receiver},
619619
itertools::Itertools,
620620
solana_sdk::{
621-
clock::Slot, compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message,
622-
packet::Packet, pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction,
621+
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, packet::Packet,
622+
pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction,
623623
transaction::Transaction,
624624
},
625625
std::{borrow::Borrow, sync::Arc},
@@ -705,10 +705,7 @@ mod tests {
705705
);
706706
let transaction_ttl = SanitizedTransactionTTL {
707707
transaction,
708-
max_age: MaxAge {
709-
epoch_invalidation_slot: Slot::MAX,
710-
alt_invalidation_slot: Slot::MAX,
711-
},
708+
max_age: MaxAge::MAX,
712709
};
713710
const TEST_TRANSACTION_COST: u64 = 5000;
714711
container.insert_new_transaction(

core/src/banking_stage/transaction_scheduler/scheduler_controller.rs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use {
3232
solana_sdk::{
3333
self,
3434
address_lookup_table::state::estimate_last_valid_slot,
35-
clock::{Slot, FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE},
35+
clock::{Epoch, Slot, FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE},
3636
fee::FeeBudgetLimits,
3737
saturating_add_assign,
3838
transaction::SanitizedTransaction,
@@ -509,9 +509,7 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
509509
(root_bank, working_bank)
510510
};
511511
let alt_resolved_slot = root_bank.slot();
512-
let last_slot_in_epoch = working_bank
513-
.epoch_schedule()
514-
.get_last_slot_in_epoch(working_bank.epoch());
512+
let sanitized_epoch = root_bank.epoch();
515513
let transaction_account_lock_limit = working_bank.get_transaction_account_lock_limit();
516514
let vote_only = working_bank.vote_only_bank();
517515

@@ -533,7 +531,7 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
533531
.build_sanitized_transaction(
534532
vote_only,
535533
root_bank.as_ref(),
536-
working_bank.get_reserved_account_keys(),
534+
root_bank.get_reserved_account_keys(),
537535
)
538536
.map(|(tx, deactivation_slot)| (packet.clone(), tx, deactivation_slot))
539537
})
@@ -556,7 +554,7 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
556554
arc_packets.push(packet);
557555
transactions.push(tx);
558556
max_ages.push(calculate_max_age(
559-
last_slot_in_epoch,
557+
sanitized_epoch,
560558
deactivation_slot,
561559
alt_resolved_slot,
562560
));
@@ -683,11 +681,10 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
683681
}
684682
}
685683

686-
/// Given the last slot in the epoch, the minimum deactivation slot,
687-
/// and the current slot, return the `MaxAge` that should be used for
688-
/// the transaction. This is used to determine the maximum slot that a
689-
/// transaction will be considered valid for, without re-resolving addresses
690-
/// or resanitizing.
684+
/// Given the epoch, the minimum deactivation slot, and the current slot,
685+
/// return the `MaxAge` that should be used for the transaction. This is used
686+
/// to determine the maximum slot that a transaction will be considered valid
687+
/// for, without re-resolving addresses or resanitizing.
691688
///
692689
/// This function considers the deactivation period of Address Table
693690
/// accounts. If the deactivation period runs past the end of the epoch,
@@ -700,13 +697,13 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
700697
/// period, i.e. the transaction's address lookups are valid until
701698
/// AT LEAST this slot.
702699
fn calculate_max_age(
703-
last_slot_in_epoch: Slot,
700+
sanitized_epoch: Epoch,
704701
deactivation_slot: Slot,
705702
current_slot: Slot,
706703
) -> MaxAge {
707704
let alt_min_expire_slot = estimate_last_valid_slot(deactivation_slot.min(current_slot));
708705
MaxAge {
709-
epoch_invalidation_slot: last_slot_in_epoch,
706+
sanitized_epoch,
710707
alt_invalidation_slot: alt_min_expire_slot,
711708
}
712709
}
@@ -1218,23 +1215,23 @@ mod tests {
12181215
#[test]
12191216
fn test_calculate_max_age() {
12201217
let current_slot = 100;
1221-
let last_slot_in_epoch = 1000;
1218+
let sanitized_epoch = 10;
12221219

12231220
// ALT deactivation slot is delayed
12241221
assert_eq!(
1225-
calculate_max_age(last_slot_in_epoch, current_slot - 1, current_slot),
1222+
calculate_max_age(sanitized_epoch, current_slot - 1, current_slot),
12261223
MaxAge {
1227-
epoch_invalidation_slot: last_slot_in_epoch,
1224+
sanitized_epoch,
12281225
alt_invalidation_slot: current_slot - 1
12291226
+ solana_sdk::slot_hashes::get_entries() as u64,
12301227
}
12311228
);
12321229

12331230
// no deactivation slot
12341231
assert_eq!(
1235-
calculate_max_age(last_slot_in_epoch, u64::MAX, current_slot),
1232+
calculate_max_age(sanitized_epoch, u64::MAX, current_slot),
12361233
MaxAge {
1237-
epoch_invalidation_slot: last_slot_in_epoch,
1234+
sanitized_epoch,
12381235
alt_invalidation_slot: current_slot + solana_sdk::slot_hashes::get_entries() as u64,
12391236
}
12401237
);

core/src/banking_stage/transaction_scheduler/transaction_state.rs

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,8 @@ mod tests {
209209
use {
210210
super::*,
211211
solana_sdk::{
212-
clock::Slot, compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message,
213-
packet::Packet, signature::Keypair, signer::Signer, system_instruction,
214-
transaction::Transaction,
212+
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, packet::Packet,
213+
signature::Keypair, signer::Signer, system_instruction, transaction::Transaction,
215214
},
216215
};
217216

@@ -233,10 +232,7 @@ mod tests {
233232
);
234233
let transaction_ttl = SanitizedTransactionTTL {
235234
transaction: SanitizedTransaction::from_transaction_for_tests(tx),
236-
max_age: MaxAge {
237-
epoch_invalidation_slot: Slot::MAX,
238-
alt_invalidation_slot: Slot::MAX,
239-
},
235+
max_age: MaxAge::MAX,
240236
};
241237
const TEST_TRANSACTION_COST: u64 = 5000;
242238
TransactionState::new(
@@ -327,13 +323,7 @@ mod tests {
327323
transaction_state,
328324
TransactionState::Unprocessed { .. }
329325
));
330-
assert_eq!(
331-
transaction_ttl.max_age,
332-
MaxAge {
333-
epoch_invalidation_slot: Slot::MAX,
334-
alt_invalidation_slot: Slot::MAX,
335-
}
336-
);
326+
assert_eq!(transaction_ttl.max_age, MaxAge::MAX);
337327

338328
let _ = transaction_state.transition_to_pending();
339329
assert!(matches!(
@@ -351,13 +341,7 @@ mod tests {
351341
transaction_state,
352342
TransactionState::Unprocessed { .. }
353343
));
354-
assert_eq!(
355-
transaction_ttl.max_age,
356-
MaxAge {
357-
epoch_invalidation_slot: Slot::MAX,
358-
alt_invalidation_slot: Slot::MAX,
359-
}
360-
);
344+
assert_eq!(transaction_ttl.max_age, MaxAge::MAX);
361345

362346
// ensure transaction_ttl is not lost through state transitions
363347
let transaction_ttl = transaction_state.transition_to_pending();
@@ -372,12 +356,6 @@ mod tests {
372356
transaction_state,
373357
TransactionState::Unprocessed { .. }
374358
));
375-
assert_eq!(
376-
transaction_ttl.max_age,
377-
MaxAge {
378-
epoch_invalidation_slot: Slot::MAX,
379-
alt_invalidation_slot: Slot::MAX,
380-
}
381-
);
359+
assert_eq!(transaction_ttl.max_age, MaxAge::MAX);
382360
}
383361
}

core/src/banking_stage/transaction_scheduler/transaction_state_container.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ mod tests {
161161
packet::Packet,
162162
signature::Keypair,
163163
signer::Signer,
164-
slot_history::Slot,
165164
system_instruction,
166165
transaction::{SanitizedTransaction, Transaction},
167166
},
@@ -199,10 +198,7 @@ mod tests {
199198
);
200199
let transaction_ttl = SanitizedTransactionTTL {
201200
transaction: tx,
202-
max_age: MaxAge {
203-
epoch_invalidation_slot: Slot::MAX,
204-
alt_invalidation_slot: Slot::MAX,
205-
},
201+
max_age: MaxAge::MAX,
206202
};
207203
const TEST_TRANSACTION_COST: u64 = 5000;
208204
(transaction_ttl, packet, priority, TEST_TRANSACTION_COST)

0 commit comments

Comments
 (0)