Only allow votes when root distance gets too high (#19917)
This commit is contained in:
parent
2762f6f96f
commit
dc69cc1ae4
|
@ -1065,6 +1065,7 @@ impl BankingStage {
|
|||
cost_tracker: &Arc<RwLock<CostTracker>>,
|
||||
banking_stage_stats: &BankingStageStats,
|
||||
demote_program_write_locks: bool,
|
||||
votes_only: bool,
|
||||
) -> (Vec<SanitizedTransaction>, Vec<usize>, Vec<usize>) {
|
||||
let mut retryable_transaction_packet_indexes: Vec<usize> = vec![];
|
||||
|
||||
|
@ -1079,6 +1080,9 @@ impl BankingStage {
|
|||
Err(TransactionError::UnsupportedVersion)
|
||||
})
|
||||
.ok()?;
|
||||
if votes_only && !solana_runtime::bank::is_simple_vote_transaction(&tx) {
|
||||
return None;
|
||||
}
|
||||
tx.verify_precompiles(feature_set).ok()?;
|
||||
Some((tx, *tx_index))
|
||||
})
|
||||
|
@ -1178,6 +1182,7 @@ impl BankingStage {
|
|||
cost_tracker,
|
||||
banking_stage_stats,
|
||||
bank.demote_program_write_locks(),
|
||||
bank.vote_only_bank(),
|
||||
);
|
||||
packet_conversion_time.stop();
|
||||
inc_new_counter_info!("banking_stage-packet_conversion", 1);
|
||||
|
@ -1284,6 +1289,7 @@ impl BankingStage {
|
|||
cost_tracker,
|
||||
banking_stage_stats,
|
||||
bank.demote_program_write_locks(),
|
||||
bank.vote_only_bank(),
|
||||
);
|
||||
unprocessed_packet_conversion_time.stop();
|
||||
|
||||
|
@ -2963,4 +2969,58 @@ mod tests {
|
|||
transaction.message_data()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transactions_from_packets() {
|
||||
use solana_sdk::feature_set::FeatureSet;
|
||||
use solana_vote_program::vote_state::Vote;
|
||||
solana_logger::setup();
|
||||
let mut vote_packet = Packet::default();
|
||||
let vote_instruction = solana_vote_program::vote_instruction::vote(
|
||||
&Pubkey::new_unique(),
|
||||
&Pubkey::new_unique(),
|
||||
Vote::default(),
|
||||
);
|
||||
let vote_transaction =
|
||||
Transaction::new_with_payer(&[vote_instruction], Some(&Pubkey::new_unique()));
|
||||
Packet::populate_packet(&mut vote_packet, None, &vote_transaction).unwrap();
|
||||
let mut non_vote = Packet::default();
|
||||
let tx = system_transaction::transfer(
|
||||
&Keypair::new(),
|
||||
&Pubkey::new_unique(),
|
||||
2,
|
||||
Hash::default(),
|
||||
);
|
||||
Packet::populate_packet(&mut non_vote, None, &tx).unwrap();
|
||||
let msgs = Packets::new(vec![non_vote, vote_packet]);
|
||||
let packet_indexes = [0, 1];
|
||||
let feature_set = Arc::new(FeatureSet::default());
|
||||
let cost_model = Arc::new(RwLock::new(CostModel::default()));
|
||||
let cost_tracker = Arc::new(RwLock::new(CostTracker::new(cost_model)));
|
||||
let banking_stage_stats = BankingStageStats::default();
|
||||
let (transactions, _transaction_to_packet_indexes, _retryable_packet_indexes) =
|
||||
BankingStage::transactions_from_packets(
|
||||
&msgs,
|
||||
&packet_indexes,
|
||||
&feature_set,
|
||||
&cost_tracker,
|
||||
&banking_stage_stats,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
assert_eq!(transactions.len(), 1);
|
||||
assert!(!transactions[0].signatures().is_empty());
|
||||
|
||||
let (transactions, _transaction_to_packet_indexes, _retryable_packet_indexes) =
|
||||
BankingStage::transactions_from_packets(
|
||||
&msgs,
|
||||
&packet_indexes,
|
||||
&feature_set,
|
||||
&cost_tracker,
|
||||
&banking_stage_stats,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
assert_eq!(transactions.len(), 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1453,12 +1453,22 @@ impl ReplayStage {
|
|||
poh_slot, parent_slot, root_slot
|
||||
);
|
||||
|
||||
let root_distance = poh_slot - root_slot;
|
||||
const MAX_ROOT_DISTANCE_FOR_VOTE_ONLY: Slot = 500;
|
||||
let vote_only_bank = if root_distance > MAX_ROOT_DISTANCE_FOR_VOTE_ONLY {
|
||||
datapoint_info!("vote-only-bank", ("slot", poh_slot, i64));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let tpu_bank = Self::new_bank_from_parent_with_notify(
|
||||
&parent,
|
||||
poh_slot,
|
||||
root_slot,
|
||||
my_pubkey,
|
||||
rpc_subscriptions,
|
||||
vote_only_bank,
|
||||
);
|
||||
|
||||
let tpu_bank = bank_forks.write().unwrap().insert(tpu_bank);
|
||||
|
@ -2784,6 +2794,7 @@ impl ReplayStage {
|
|||
forks.root(),
|
||||
&leader,
|
||||
rpc_subscriptions,
|
||||
false,
|
||||
);
|
||||
let empty: Vec<Pubkey> = vec![];
|
||||
Self::update_fork_propagated_threshold_from_votes(
|
||||
|
@ -2810,9 +2821,10 @@ impl ReplayStage {
|
|||
root_slot: u64,
|
||||
leader: &Pubkey,
|
||||
rpc_subscriptions: &Arc<RpcSubscriptions>,
|
||||
vote_only_bank: bool,
|
||||
) -> Bank {
|
||||
rpc_subscriptions.notify_slot(slot, parent.slot(), root_slot);
|
||||
Bank::new_from_parent(parent, leader, slot)
|
||||
Bank::new_from_parent_with_vote_only(parent, leader, slot, vote_only_bank)
|
||||
}
|
||||
|
||||
fn record_rewards(bank: &Bank, rewards_recorder_sender: &Option<RewardsRecorderSender>) {
|
||||
|
|
|
@ -984,6 +984,8 @@ pub struct Bank {
|
|||
pub drop_callback: RwLock<OptionalDropCallback>,
|
||||
|
||||
pub freeze_started: AtomicBool,
|
||||
|
||||
vote_only_bank: bool,
|
||||
}
|
||||
|
||||
impl Default for BlockhashQueue {
|
||||
|
@ -1109,6 +1111,7 @@ impl Bank {
|
|||
feature_set: Arc::<FeatureSet>::default(),
|
||||
drop_callback: RwLock::<OptionalDropCallback>::default(),
|
||||
freeze_started: AtomicBool::default(),
|
||||
vote_only_bank: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1219,7 +1222,22 @@ impl Bank {
|
|||
|
||||
/// Create a new bank that points to an immutable checkpoint of another bank.
|
||||
pub fn new_from_parent(parent: &Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
|
||||
Self::_new_from_parent(parent, collector_id, slot, &mut null_tracer())
|
||||
Self::_new_from_parent(parent, collector_id, slot, &mut null_tracer(), false)
|
||||
}
|
||||
|
||||
pub fn new_from_parent_with_vote_only(
|
||||
parent: &Arc<Bank>,
|
||||
collector_id: &Pubkey,
|
||||
slot: Slot,
|
||||
vote_only_bank: bool,
|
||||
) -> Self {
|
||||
Self::_new_from_parent(
|
||||
parent,
|
||||
collector_id,
|
||||
slot,
|
||||
&mut null_tracer(),
|
||||
vote_only_bank,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_from_parent_with_tracer(
|
||||
|
@ -1228,7 +1246,13 @@ impl Bank {
|
|||
slot: Slot,
|
||||
reward_calc_tracer: impl FnMut(&RewardCalculationEvent),
|
||||
) -> Self {
|
||||
Self::_new_from_parent(parent, collector_id, slot, &mut Some(reward_calc_tracer))
|
||||
Self::_new_from_parent(
|
||||
parent,
|
||||
collector_id,
|
||||
slot,
|
||||
&mut Some(reward_calc_tracer),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
fn _new_from_parent(
|
||||
|
@ -1236,6 +1260,7 @@ impl Bank {
|
|||
collector_id: &Pubkey,
|
||||
slot: Slot,
|
||||
reward_calc_tracer: &mut Option<impl FnMut(&RewardCalculationEvent)>,
|
||||
vote_only_bank: bool,
|
||||
) -> Self {
|
||||
parent.freeze();
|
||||
assert_ne!(slot, parent.slot());
|
||||
|
@ -1284,6 +1309,7 @@ impl Bank {
|
|||
fee_calculator: fee_rate_governor.create_fee_calculator(),
|
||||
fee_rate_governor,
|
||||
capitalization: AtomicU64::new(parent.capitalization()),
|
||||
vote_only_bank,
|
||||
inflation: parent.inflation.clone(),
|
||||
transaction_count: AtomicU64::new(parent.transaction_count()),
|
||||
transaction_error_count: AtomicU64::new(0),
|
||||
|
@ -1374,6 +1400,10 @@ impl Bank {
|
|||
*self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
|
||||
}
|
||||
|
||||
pub fn vote_only_bank(&self) -> bool {
|
||||
self.vote_only_bank
|
||||
}
|
||||
|
||||
/// Like `new_from_parent` but additionally:
|
||||
/// * Doesn't assume that the parent is anywhere near `slot`, parent could be millions of slots
|
||||
/// in the past
|
||||
|
@ -1469,6 +1499,7 @@ impl Bank {
|
|||
feature_set: new(),
|
||||
drop_callback: RwLock::new(OptionalDropCallback(None)),
|
||||
freeze_started: AtomicBool::new(fields.hash != Hash::default()),
|
||||
vote_only_bank: false,
|
||||
};
|
||||
bank.finish_init(
|
||||
genesis_config,
|
||||
|
@ -5698,7 +5729,7 @@ pub fn goto_end_of_slot(bank: &mut Bank) {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_simple_vote_transaction(transaction: &SanitizedTransaction) -> bool {
|
||||
pub fn is_simple_vote_transaction(transaction: &SanitizedTransaction) -> bool {
|
||||
if transaction.message().instructions().len() == 1 {
|
||||
let (program_pubkey, instruction) = transaction
|
||||
.message()
|
||||
|
|
Loading…
Reference in New Issue