Only allow votes when root distance gets too high (#19933)
This commit is contained in:
@ -978,12 +978,18 @@ impl BankingStage {
|
|||||||
msgs: &Packets,
|
msgs: &Packets,
|
||||||
transaction_indexes: &[usize],
|
transaction_indexes: &[usize],
|
||||||
libsecp256k1_0_5_upgrade_enabled: bool,
|
libsecp256k1_0_5_upgrade_enabled: bool,
|
||||||
|
votes_only: bool,
|
||||||
) -> (Vec<HashedTransaction<'static>>, Vec<usize>) {
|
) -> (Vec<HashedTransaction<'static>>, Vec<usize>) {
|
||||||
transaction_indexes
|
transaction_indexes
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|tx_index| {
|
.filter_map(|tx_index| {
|
||||||
let p = &msgs.packets[*tx_index];
|
let p = &msgs.packets[*tx_index];
|
||||||
let tx: Transaction = limited_deserialize(&p.data[0..p.meta.size]).ok()?;
|
let tx: Transaction = limited_deserialize(&p.data[0..p.meta.size]).ok()?;
|
||||||
|
|
||||||
|
if votes_only && !solana_runtime::bank::is_simple_vote_transaction(&tx) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
tx.verify_precompiles(libsecp256k1_0_5_upgrade_enabled)
|
tx.verify_precompiles(libsecp256k1_0_5_upgrade_enabled)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
let message_bytes = Self::packet_message(p)?;
|
let message_bytes = Self::packet_message(p)?;
|
||||||
@ -1050,6 +1056,7 @@ impl BankingStage {
|
|||||||
msgs,
|
msgs,
|
||||||
&packet_indexes,
|
&packet_indexes,
|
||||||
bank.libsecp256k1_0_5_upgrade_enabled(),
|
bank.libsecp256k1_0_5_upgrade_enabled(),
|
||||||
|
bank.vote_only_bank(),
|
||||||
);
|
);
|
||||||
packet_conversion_time.stop();
|
packet_conversion_time.stop();
|
||||||
|
|
||||||
@ -1121,6 +1128,7 @@ impl BankingStage {
|
|||||||
msgs,
|
msgs,
|
||||||
&transaction_indexes,
|
&transaction_indexes,
|
||||||
bank.libsecp256k1_0_5_upgrade_enabled(),
|
bank.libsecp256k1_0_5_upgrade_enabled(),
|
||||||
|
bank.vote_only_bank(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let tx_count = transaction_to_packet_indexes.len();
|
let tx_count = transaction_to_packet_indexes.len();
|
||||||
@ -2786,4 +2794,37 @@ mod tests {
|
|||||||
transaction.message_data()
|
transaction.message_data()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_transactions_from_packets() {
|
||||||
|
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 (transactions, _transaction_to_packet_indexes) =
|
||||||
|
BankingStage::transactions_from_packets(&msgs, &packet_indexes, false, true);
|
||||||
|
assert_eq!(transactions.len(), 1);
|
||||||
|
assert!(!transactions[0].transaction().signatures.is_empty());
|
||||||
|
|
||||||
|
let (transactions, _transaction_to_packet_indexes) =
|
||||||
|
BankingStage::transactions_from_packets(&msgs, &packet_indexes, false, false);
|
||||||
|
assert_eq!(transactions.len(), 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1181,12 +1181,22 @@ impl ReplayStage {
|
|||||||
poh_slot, parent_slot, root_slot
|
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(
|
let tpu_bank = Self::new_bank_from_parent_with_notify(
|
||||||
&parent,
|
&parent,
|
||||||
poh_slot,
|
poh_slot,
|
||||||
root_slot,
|
root_slot,
|
||||||
my_pubkey,
|
my_pubkey,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
|
vote_only_bank,
|
||||||
);
|
);
|
||||||
|
|
||||||
let tpu_bank = bank_forks.write().unwrap().insert(tpu_bank);
|
let tpu_bank = bank_forks.write().unwrap().insert(tpu_bank);
|
||||||
@ -2442,6 +2452,7 @@ impl ReplayStage {
|
|||||||
forks.root(),
|
forks.root(),
|
||||||
&leader,
|
&leader,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
let empty: Vec<Pubkey> = vec![];
|
let empty: Vec<Pubkey> = vec![];
|
||||||
Self::update_fork_propagated_threshold_from_votes(
|
Self::update_fork_propagated_threshold_from_votes(
|
||||||
@ -2468,9 +2479,10 @@ impl ReplayStage {
|
|||||||
root_slot: u64,
|
root_slot: u64,
|
||||||
leader: &Pubkey,
|
leader: &Pubkey,
|
||||||
subscriptions: &Arc<RpcSubscriptions>,
|
subscriptions: &Arc<RpcSubscriptions>,
|
||||||
|
vote_only_bank: bool,
|
||||||
) -> Bank {
|
) -> Bank {
|
||||||
subscriptions.notify_slot(slot, parent.slot(), root_slot);
|
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>) {
|
fn record_rewards(bank: &Bank, rewards_recorder_sender: &Option<RewardsRecorderSender>) {
|
||||||
|
@ -1005,6 +1005,8 @@ pub struct Bank {
|
|||||||
pub drop_callback: RwLock<OptionalDropCallback>,
|
pub drop_callback: RwLock<OptionalDropCallback>,
|
||||||
|
|
||||||
pub freeze_started: AtomicBool,
|
pub freeze_started: AtomicBool,
|
||||||
|
|
||||||
|
vote_only_bank: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BlockhashQueue {
|
impl Default for BlockhashQueue {
|
||||||
@ -1119,7 +1121,22 @@ impl Bank {
|
|||||||
|
|
||||||
/// Create a new bank that points to an immutable checkpoint of another 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 {
|
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(
|
pub fn new_from_parent_with_tracer(
|
||||||
@ -1128,7 +1145,13 @@ impl Bank {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
reward_calc_tracer: impl FnMut(&RewardCalculationEvent),
|
reward_calc_tracer: impl FnMut(&RewardCalculationEvent),
|
||||||
) -> Self {
|
) -> 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(
|
fn _new_from_parent(
|
||||||
@ -1136,6 +1159,7 @@ impl Bank {
|
|||||||
collector_id: &Pubkey,
|
collector_id: &Pubkey,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
reward_calc_tracer: &mut Option<impl FnMut(&RewardCalculationEvent)>,
|
reward_calc_tracer: &mut Option<impl FnMut(&RewardCalculationEvent)>,
|
||||||
|
vote_only_bank: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
parent.freeze();
|
parent.freeze();
|
||||||
assert_ne!(slot, parent.slot());
|
assert_ne!(slot, parent.slot());
|
||||||
@ -1184,6 +1208,7 @@ impl Bank {
|
|||||||
fee_calculator: fee_rate_governor.create_fee_calculator(),
|
fee_calculator: fee_rate_governor.create_fee_calculator(),
|
||||||
fee_rate_governor,
|
fee_rate_governor,
|
||||||
capitalization: AtomicU64::new(parent.capitalization()),
|
capitalization: AtomicU64::new(parent.capitalization()),
|
||||||
|
vote_only_bank,
|
||||||
inflation: parent.inflation.clone(),
|
inflation: parent.inflation.clone(),
|
||||||
transaction_count: AtomicU64::new(parent.transaction_count()),
|
transaction_count: AtomicU64::new(parent.transaction_count()),
|
||||||
transaction_error_count: AtomicU64::new(0),
|
transaction_error_count: AtomicU64::new(0),
|
||||||
@ -1278,6 +1303,10 @@ impl Bank {
|
|||||||
*self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
|
*self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn vote_only_bank(&self) -> bool {
|
||||||
|
self.vote_only_bank
|
||||||
|
}
|
||||||
|
|
||||||
/// Like `new_from_parent` but additionally:
|
/// Like `new_from_parent` but additionally:
|
||||||
/// * Doesn't assume that the parent is anywhere near `slot`, parent could be millions of slots
|
/// * Doesn't assume that the parent is anywhere near `slot`, parent could be millions of slots
|
||||||
/// in the past
|
/// in the past
|
||||||
@ -1373,6 +1402,7 @@ impl Bank {
|
|||||||
feature_set: new(),
|
feature_set: new(),
|
||||||
drop_callback: RwLock::new(OptionalDropCallback(None)),
|
drop_callback: RwLock::new(OptionalDropCallback(None)),
|
||||||
freeze_started: AtomicBool::new(fields.hash != Hash::default()),
|
freeze_started: AtomicBool::new(fields.hash != Hash::default()),
|
||||||
|
vote_only_bank: false,
|
||||||
};
|
};
|
||||||
bank.finish_init(
|
bank.finish_init(
|
||||||
genesis_config,
|
genesis_config,
|
||||||
@ -5412,7 +5442,7 @@ pub fn goto_end_of_slot(bank: &mut Bank) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_simple_vote_transaction(transaction: &Transaction) -> bool {
|
pub fn is_simple_vote_transaction(transaction: &Transaction) -> bool {
|
||||||
if transaction.message.instructions.len() == 1 {
|
if transaction.message.instructions.len() == 1 {
|
||||||
let instruction = &transaction.message.instructions[0];
|
let instruction = &transaction.message.instructions[0];
|
||||||
let program_pubkey =
|
let program_pubkey =
|
||||||
|
Reference in New Issue
Block a user