patches crds vote-index assignment bug (#14438)
If tower is full, old votes are evicted from the front of the deque: https://github.com/solana-labs/solana/blob/2074e407c/programs/vote/src/vote_state/mod.rs#L367-L373 whereas recent votes if expire are evicted from the back: https://github.com/solana-labs/solana/blob/2074e407c/programs/vote/src/vote_state/mod.rs#L529-L537 As a result, from a single tower_index scalar, we cannot infer which crds-vote should be overwritten: https://github.com/solana-labs/solana/blob/2074e407c/core/src/crds_value.rs#L576 In addition there is an off by one bug in the existing code. tower_index is bounded by MAX_LOCKOUT_HISTORY - 1: https://github.com/solana-labs/solana/blob/2074e407c/core/src/consensus.rs#L382 So, it is at most 30, whereas MAX_VOTES is 32: https://github.com/solana-labs/solana/blob/2074e407c/core/src/crds_value.rs#L29 Which means that this branch is never taken: https://github.com/solana-labs/solana/blob/2074e407c/core/src/crds_value.rs#L590-L593 so crds table alwasys keeps 29 **oldest** votes by wallclock, and then only overrides the 30st one each time. (i.e a tally of only two most recent votes).
This commit is contained in:
@ -7,8 +7,14 @@ use solana_core::gossip_service::GossipService;
|
||||
use solana_runtime::bank_forks::BankForks;
|
||||
|
||||
use solana_perf::packet::Packet;
|
||||
use solana_sdk::signature::{Keypair, Signer};
|
||||
use solana_sdk::timing::timestamp;
|
||||
use solana_sdk::{
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
timing::timestamp,
|
||||
transaction::Transaction,
|
||||
};
|
||||
use solana_vote_program::{vote_instruction, vote_state::Vote};
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, RwLock};
|
||||
@ -269,7 +275,21 @@ pub fn cluster_info_scale() {
|
||||
let mut time = Measure::start("votes");
|
||||
let tx = test_tx();
|
||||
warn!("tx.message.account_keys: {:?}", tx.message.account_keys);
|
||||
nodes[0].0.push_vote(0, tx.clone());
|
||||
let vote = Vote::new(
|
||||
vec![1, 3, num_votes + 5], // slots
|
||||
Hash::default(),
|
||||
);
|
||||
let ix = vote_instruction::vote(
|
||||
&Pubkey::new_unique(), // vote_pubkey
|
||||
&Pubkey::new_unique(), // authorized_voter_pubkey
|
||||
vote,
|
||||
);
|
||||
let tx = Transaction::new_with_payer(
|
||||
&[ix], // instructions
|
||||
None, // payer
|
||||
);
|
||||
let tower = vec![num_votes + 5];
|
||||
nodes[0].0.push_vote(&tower, tx.clone());
|
||||
let mut success = false;
|
||||
for _ in 0..(30 * 5) {
|
||||
let mut not_done = 0;
|
||||
|
Reference in New Issue
Block a user