Skip to content

Commit

Permalink
Store epoch in MaxAge (#3485)
Browse files Browse the repository at this point in the history
(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
  • Loading branch information
apfitzge authored and mergify[bot] committed Nov 6, 2024
1 parent 95ee9c1 commit a7cefc5
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 66 deletions.
28 changes: 17 additions & 11 deletions core/src/banking_stage/consume_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,12 @@ mod tests {
..
} = create_slow_genesis_config(10_000);
let (bank, bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
let bank = Arc::new(Bank::new_from_parent(bank, &Pubkey::new_unique(), 1));
// Warp to next epoch for MaxAge tests.
let bank = Arc::new(Bank::new_from_parent(
bank.clone(),
&Pubkey::new_unique(),
bank.get_epoch_info().slots_in_epoch,
));

let ledger_path = get_tmp_ledger_path_auto_delete!();
let blockstore = Blockstore::open(ledger_path.path())
Expand Down Expand Up @@ -863,7 +868,7 @@ mod tests {
let bid = TransactionBatchId::new(0);
let id = TransactionId::new(0);
let max_age = MaxAge {
epoch_invalidation_slot: bank.slot(),
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: bank.slot(),
};
let work = ConsumeWork {
Expand Down Expand Up @@ -912,7 +917,7 @@ mod tests {
let bid = TransactionBatchId::new(0);
let id = TransactionId::new(0);
let max_age = MaxAge {
epoch_invalidation_slot: bank.slot(),
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: bank.slot(),
};
let work = ConsumeWork {
Expand Down Expand Up @@ -962,7 +967,7 @@ mod tests {
let id1 = TransactionId::new(1);
let id2 = TransactionId::new(0);
let max_age = MaxAge {
epoch_invalidation_slot: bank.slot(),
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: bank.slot(),
};
consume_sender
Expand Down Expand Up @@ -1023,7 +1028,7 @@ mod tests {
let id1 = TransactionId::new(1);
let id2 = TransactionId::new(0);
let max_age = MaxAge {
epoch_invalidation_slot: bank.slot(),
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: bank.slot(),
};
consume_sender
Expand Down Expand Up @@ -1077,6 +1082,7 @@ mod tests {
.unwrap()
.set_bank_for_test(bank.clone());
assert!(bank.slot() > 0);
assert!(bank.epoch() > 0);

// No conflicts between transactions. Test 6 cases.
// 1. Epoch expiration, before slot => still succeeds due to resanitizing
Expand Down Expand Up @@ -1161,27 +1167,27 @@ mod tests {
transactions: txs,
max_ages: vec![
MaxAge {
epoch_invalidation_slot: bank.slot() - 1,
sanitized_epoch: bank.epoch() - 1,
alt_invalidation_slot: Slot::MAX,
},
MaxAge {
epoch_invalidation_slot: bank.slot(),
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: Slot::MAX,
},
MaxAge {
epoch_invalidation_slot: bank.slot() + 1,
sanitized_epoch: bank.epoch() + 1,
alt_invalidation_slot: Slot::MAX,
},
MaxAge {
epoch_invalidation_slot: u64::MAX,
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: bank.slot() - 1,
},
MaxAge {
epoch_invalidation_slot: u64::MAX,
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: bank.slot(),
},
MaxAge {
epoch_invalidation_slot: u64::MAX,
sanitized_epoch: bank.epoch(),
alt_invalidation_slot: bank.slot() + 1,
},
],
Expand Down
4 changes: 2 additions & 2 deletions core/src/banking_stage/consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,8 @@ impl Consumer {
let pre_results = txs.iter().zip(max_ages).map(|(tx, max_age)| {
// If the transaction was sanitized before this bank's epoch,
// additional checks are necessary.
if bank.slot() > max_age.epoch_invalidation_slot {
// Reserved key set may have cahnged, so we must verify that
if bank.epoch() != max_age.sanitized_epoch {
// Reserved key set may have changed, so we must verify that
// no writable keys are reserved.
bank.check_reserved_keys(tx)?;
}
Expand Down
17 changes: 16 additions & 1 deletion core/src/banking_stage/scheduler_messages.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
use {
<<<<<<< HEAD
solana_sdk::{clock::Slot, transaction::SanitizedTransaction},
=======
solana_runtime_transaction::runtime_transaction::RuntimeTransaction,
solana_sdk::{
clock::{Epoch, Slot},
transaction::SanitizedTransaction,
},
>>>>>>> 5a6f518c60 (Store epoch in MaxAge (#3485))
std::fmt::Display,
};

Expand Down Expand Up @@ -37,10 +45,17 @@ impl Display for TransactionId {

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MaxAge {
pub epoch_invalidation_slot: Slot,
pub sanitized_epoch: Epoch,
pub alt_invalidation_slot: Slot,
}

impl MaxAge {
pub const MAX: Self = Self {
sanitized_epoch: Epoch::MAX,
alt_invalidation_slot: Slot::MAX,
};
}

/// Message: [Scheduler -> Worker]
/// Transactions to be consumed (i.e. executed, recorded, and committed)
pub struct ConsumeWork {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,8 @@ mod tests {
crossbeam_channel::{unbounded, Receiver},
itertools::Itertools,
solana_sdk::{
clock::Slot, compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message,
packet::Packet, pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction,
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, packet::Packet,
pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction,
transaction::Transaction,
},
std::{borrow::Borrow, sync::Arc},
Expand Down Expand Up @@ -705,10 +705,7 @@ mod tests {
);
let transaction_ttl = SanitizedTransactionTTL {
transaction,
max_age: MaxAge {
epoch_invalidation_slot: Slot::MAX,
alt_invalidation_slot: Slot::MAX,
},
max_age: MaxAge::MAX,
};
const TEST_TRANSACTION_COST: u64 = 5000;
container.insert_new_transaction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use {
solana_sdk::{
self,
address_lookup_table::state::estimate_last_valid_slot,
clock::{Slot, FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE},
clock::{Epoch, Slot, FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE},
fee::FeeBudgetLimits,
saturating_add_assign,
transaction::SanitizedTransaction,
Expand Down Expand Up @@ -509,9 +509,7 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
(root_bank, working_bank)
};
let alt_resolved_slot = root_bank.slot();
let last_slot_in_epoch = working_bank
.epoch_schedule()
.get_last_slot_in_epoch(working_bank.epoch());
let sanitized_epoch = root_bank.epoch();
let transaction_account_lock_limit = working_bank.get_transaction_account_lock_limit();
let vote_only = working_bank.vote_only_bank();

Expand All @@ -533,7 +531,7 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
.build_sanitized_transaction(
vote_only,
root_bank.as_ref(),
working_bank.get_reserved_account_keys(),
root_bank.get_reserved_account_keys(),
)
.map(|(tx, deactivation_slot)| (packet.clone(), tx, deactivation_slot))
})
Expand All @@ -556,7 +554,7 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
arc_packets.push(packet);
transactions.push(tx);
max_ages.push(calculate_max_age(
last_slot_in_epoch,
sanitized_epoch,
deactivation_slot,
alt_resolved_slot,
));
Expand Down Expand Up @@ -683,11 +681,10 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
}
}

/// Given the last slot in the epoch, the minimum deactivation slot,
/// and the current slot, return the `MaxAge` that should be used for
/// the transaction. This is used to determine the maximum slot that a
/// transaction will be considered valid for, without re-resolving addresses
/// or resanitizing.
/// Given the epoch, the minimum deactivation slot, and the current slot,
/// return the `MaxAge` that should be used for the transaction. This is used
/// to determine the maximum slot that a transaction will be considered valid
/// for, without re-resolving addresses or resanitizing.
///
/// This function considers the deactivation period of Address Table
/// accounts. If the deactivation period runs past the end of the epoch,
Expand All @@ -700,13 +697,13 @@ impl<T: LikeClusterInfo> SchedulerController<T> {
/// period, i.e. the transaction's address lookups are valid until
/// AT LEAST this slot.
fn calculate_max_age(
last_slot_in_epoch: Slot,
sanitized_epoch: Epoch,
deactivation_slot: Slot,
current_slot: Slot,
) -> MaxAge {
let alt_min_expire_slot = estimate_last_valid_slot(deactivation_slot.min(current_slot));
MaxAge {
epoch_invalidation_slot: last_slot_in_epoch,
sanitized_epoch,
alt_invalidation_slot: alt_min_expire_slot,
}
}
Expand Down Expand Up @@ -1218,23 +1215,23 @@ mod tests {
#[test]
fn test_calculate_max_age() {
let current_slot = 100;
let last_slot_in_epoch = 1000;
let sanitized_epoch = 10;

// ALT deactivation slot is delayed
assert_eq!(
calculate_max_age(last_slot_in_epoch, current_slot - 1, current_slot),
calculate_max_age(sanitized_epoch, current_slot - 1, current_slot),
MaxAge {
epoch_invalidation_slot: last_slot_in_epoch,
sanitized_epoch,
alt_invalidation_slot: current_slot - 1
+ solana_sdk::slot_hashes::get_entries() as u64,
}
);

// no deactivation slot
assert_eq!(
calculate_max_age(last_slot_in_epoch, u64::MAX, current_slot),
calculate_max_age(sanitized_epoch, u64::MAX, current_slot),
MaxAge {
epoch_invalidation_slot: last_slot_in_epoch,
sanitized_epoch,
alt_invalidation_slot: current_slot + solana_sdk::slot_hashes::get_entries() as u64,
}
);
Expand Down
34 changes: 10 additions & 24 deletions core/src/banking_stage/transaction_scheduler/transaction_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,8 @@ mod tests {
use {
super::*,
solana_sdk::{
clock::Slot, compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message,
packet::Packet, signature::Keypair, signer::Signer, system_instruction,
transaction::Transaction,
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, packet::Packet,
signature::Keypair, signer::Signer, system_instruction, transaction::Transaction,
},
};

Expand All @@ -232,11 +231,16 @@ mod tests {
ImmutableDeserializedPacket::new(Packet::from_data(None, tx.clone()).unwrap()).unwrap(),
);
let transaction_ttl = SanitizedTransactionTTL {
<<<<<<< HEAD
transaction: SanitizedTransaction::from_transaction_for_tests(tx),
max_age: MaxAge {
epoch_invalidation_slot: Slot::MAX,
alt_invalidation_slot: Slot::MAX,
},
=======
transaction: RuntimeTransaction::from_transaction_for_tests(tx),
max_age: MaxAge::MAX,
>>>>>>> 5a6f518c60 (Store epoch in MaxAge (#3485))
};
const TEST_TRANSACTION_COST: u64 = 5000;
TransactionState::new(
Expand Down Expand Up @@ -327,13 +331,7 @@ mod tests {
transaction_state,
TransactionState::Unprocessed { .. }
));
assert_eq!(
transaction_ttl.max_age,
MaxAge {
epoch_invalidation_slot: Slot::MAX,
alt_invalidation_slot: Slot::MAX,
}
);
assert_eq!(transaction_ttl.max_age, MaxAge::MAX);

let _ = transaction_state.transition_to_pending();
assert!(matches!(
Expand All @@ -351,13 +349,7 @@ mod tests {
transaction_state,
TransactionState::Unprocessed { .. }
));
assert_eq!(
transaction_ttl.max_age,
MaxAge {
epoch_invalidation_slot: Slot::MAX,
alt_invalidation_slot: Slot::MAX,
}
);
assert_eq!(transaction_ttl.max_age, MaxAge::MAX);

// ensure transaction_ttl is not lost through state transitions
let transaction_ttl = transaction_state.transition_to_pending();
Expand All @@ -372,12 +364,6 @@ mod tests {
transaction_state,
TransactionState::Unprocessed { .. }
));
assert_eq!(
transaction_ttl.max_age,
MaxAge {
epoch_invalidation_slot: Slot::MAX,
alt_invalidation_slot: Slot::MAX,
}
);
assert_eq!(transaction_ttl.max_age, MaxAge::MAX);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ mod tests {
super::*,
crate::banking_stage::scheduler_messages::MaxAge,
solana_sdk::{
<<<<<<< HEAD
compute_budget::ComputeBudgetInstruction,
hash::Hash,
message::Message,
Expand All @@ -164,6 +165,10 @@ mod tests {
slot_history::Slot,
system_instruction,
transaction::{SanitizedTransaction, Transaction},
=======
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, packet::Packet,
signature::Keypair, signer::Signer, system_instruction, transaction::Transaction,
>>>>>>> 5a6f518c60 (Store epoch in MaxAge (#3485))
},
};

Expand Down Expand Up @@ -199,10 +204,7 @@ mod tests {
);
let transaction_ttl = SanitizedTransactionTTL {
transaction: tx,
max_age: MaxAge {
epoch_invalidation_slot: Slot::MAX,
alt_invalidation_slot: Slot::MAX,
},
max_age: MaxAge::MAX,
};
const TEST_TRANSACTION_COST: u64 = 5000;
(transaction_ttl, packet, priority, TEST_TRANSACTION_COST)
Expand Down

0 comments on commit a7cefc5

Please sign in to comment.