* filters for recent contact-infos when checking for live stake (#19204)
Contact-infos are saved to disk:
https://github.com/solana-labs/solana/blob/9dfeee299/gossip/src/cluster_info.rs#L1678-L1683
and restored on validator start-up:
https://github.com/solana-labs/solana/blob/9dfeee299/core/src/validator.rs#L450
Staked nodes entries will not expire until an epoch after. So when the
validator checks for online stake it is erroneously picking up
contact-infos restored from disk, which breaks the entire
wait-for-supermajority logic:
https://github.com/solana-labs/solana/blob/9dfeee299/core/src/validator.rs#L1515-L1561
This commit adds an extra check for the age of contact-info entries and
filters out old ones.
(cherry picked from commit 7a789e0763
)
# Conflicts:
# core/src/validator.rs
* removes backport merge conflicts
Co-authored-by: behzad nouri <behzadnouri@gmail.com>
This commit is contained in:
@ -245,7 +245,7 @@ fn spy(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| x.0)
|
.map(|x| x.0)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
tvu_peers = spy_ref.all_tvu_peers().into_iter().collect::<Vec<_>>();
|
tvu_peers = spy_ref.all_tvu_peers();
|
||||||
|
|
||||||
let found_node_by_pubkey = if let Some(pubkey) = find_node_by_pubkey {
|
let found_node_by_pubkey = if let Some(pubkey) = find_node_by_pubkey {
|
||||||
all_peers.iter().any(|x| x.id == pubkey)
|
all_peers.iter().any(|x| x.id == pubkey)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! The `validator` module hosts all the validator microservices.
|
//! The `validator` module hosts all the validator microservices.
|
||||||
|
|
||||||
use crate::{
|
use {
|
||||||
|
crate::{
|
||||||
broadcast_stage::BroadcastStageType,
|
broadcast_stage::BroadcastStageType,
|
||||||
cache_block_meta_service::{CacheBlockMetaSender, CacheBlockMetaService},
|
cache_block_meta_service::{CacheBlockMetaSender, CacheBlockMetaService},
|
||||||
cluster_info::{
|
cluster_info::{
|
||||||
@ -11,6 +12,7 @@ use crate::{
|
|||||||
completed_data_sets_service::CompletedDataSetsService,
|
completed_data_sets_service::CompletedDataSetsService,
|
||||||
consensus::{reconcile_blockstore_roots_with_tower, Tower},
|
consensus::{reconcile_blockstore_roots_with_tower, Tower},
|
||||||
contact_info::ContactInfo,
|
contact_info::ContactInfo,
|
||||||
|
crds_gossip_pull::CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS,
|
||||||
gossip_service::GossipService,
|
gossip_service::GossipService,
|
||||||
max_slots::MaxSlots,
|
max_slots::MaxSlots,
|
||||||
optimistically_confirmed_bank_tracker::{
|
optimistically_confirmed_bank_tracker::{
|
||||||
@ -31,10 +33,10 @@ use crate::{
|
|||||||
tpu::{Tpu, DEFAULT_TPU_COALESCE_MS},
|
tpu::{Tpu, DEFAULT_TPU_COALESCE_MS},
|
||||||
transaction_status_service::TransactionStatusService,
|
transaction_status_service::TransactionStatusService,
|
||||||
tvu::{Sockets, Tvu, TvuConfig},
|
tvu::{Sockets, Tvu, TvuConfig},
|
||||||
};
|
},
|
||||||
use crossbeam_channel::{bounded, unbounded};
|
crossbeam_channel::{bounded, unbounded},
|
||||||
use rand::{thread_rng, Rng};
|
rand::{thread_rng, Rng},
|
||||||
use solana_ledger::{
|
solana_ledger::{
|
||||||
bank_forks_utils,
|
bank_forks_utils,
|
||||||
blockstore::{Blockstore, BlockstoreSignals, CompletedSlotsReceiver, PurgeType},
|
blockstore::{Blockstore, BlockstoreSignals, CompletedSlotsReceiver, PurgeType},
|
||||||
blockstore_db::BlockstoreRecoveryMode,
|
blockstore_db::BlockstoreRecoveryMode,
|
||||||
@ -42,17 +44,17 @@ use solana_ledger::{
|
|||||||
leader_schedule::FixedSchedule,
|
leader_schedule::FixedSchedule,
|
||||||
leader_schedule_cache::LeaderScheduleCache,
|
leader_schedule_cache::LeaderScheduleCache,
|
||||||
poh::compute_hash_time_ns,
|
poh::compute_hash_time_ns,
|
||||||
};
|
},
|
||||||
use solana_measure::measure::Measure;
|
solana_measure::measure::Measure,
|
||||||
use solana_metrics::datapoint_info;
|
solana_metrics::datapoint_info,
|
||||||
use solana_runtime::{
|
solana_runtime::{
|
||||||
accounts_index::AccountSecondaryIndexes,
|
accounts_index::AccountSecondaryIndexes,
|
||||||
bank::Bank,
|
bank::Bank,
|
||||||
bank_forks::{BankForks, SnapshotConfig},
|
bank_forks::{BankForks, SnapshotConfig},
|
||||||
commitment::BlockCommitmentCache,
|
commitment::BlockCommitmentCache,
|
||||||
hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE},
|
hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE},
|
||||||
};
|
},
|
||||||
use solana_sdk::{
|
solana_sdk::{
|
||||||
clock::Slot,
|
clock::Slot,
|
||||||
epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET,
|
epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET,
|
||||||
genesis_config::GenesisConfig,
|
genesis_config::GenesisConfig,
|
||||||
@ -61,20 +63,23 @@ use solana_sdk::{
|
|||||||
shred_version::compute_shred_version,
|
shred_version::compute_shred_version,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
timing::timestamp,
|
timing::timestamp,
|
||||||
};
|
},
|
||||||
use solana_vote_program::vote_state::VoteState;
|
solana_vote_program::vote_state::VoteState,
|
||||||
use std::time::Instant;
|
std::time::Instant,
|
||||||
use std::{
|
std::{
|
||||||
collections::HashSet,
|
collections::{HashMap, HashSet},
|
||||||
fmt,
|
fmt,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::atomic::{AtomicBool, AtomicU64, Ordering},
|
sync::{
|
||||||
sync::mpsc::Receiver,
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||||
sync::{Arc, Mutex, RwLock},
|
mpsc::Receiver,
|
||||||
|
Arc, Mutex, RwLock,
|
||||||
|
},
|
||||||
thread::{sleep, Builder},
|
thread::{sleep, Builder},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_COMPLETED_DATA_SETS_IN_CHANNEL: usize = 100_000;
|
const MAX_COMPLETED_DATA_SETS_IN_CHANNEL: usize = 100_000;
|
||||||
@ -1458,7 +1463,20 @@ fn get_stake_percent_in_gossip(bank: &Bank, cluster_info: &ClusterInfo, log: boo
|
|||||||
let mut offline_nodes = vec![];
|
let mut offline_nodes = vec![];
|
||||||
|
|
||||||
let mut total_activated_stake = 0;
|
let mut total_activated_stake = 0;
|
||||||
let all_tvu_peers = cluster_info.all_tvu_peers();
|
let now = timestamp();
|
||||||
|
// Nodes contact infos are saved to disk and restored on validator startup.
|
||||||
|
// Staked nodes entries will not expire until an epoch after. So it
|
||||||
|
// is necessary here to filter for recent entries to establish liveness.
|
||||||
|
let peers: HashMap<_, _> = cluster_info
|
||||||
|
.all_tvu_peers()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|node| {
|
||||||
|
let age = now.saturating_sub(node.wallclock);
|
||||||
|
// Contact infos are refreshed twice during this period.
|
||||||
|
age < CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS
|
||||||
|
})
|
||||||
|
.map(|node| (node.id, node))
|
||||||
|
.collect();
|
||||||
let my_shred_version = cluster_info.my_shred_version();
|
let my_shred_version = cluster_info.my_shred_version();
|
||||||
let my_id = cluster_info.id();
|
let my_id = cluster_info.id();
|
||||||
|
|
||||||
@ -1474,10 +1492,7 @@ fn get_stake_percent_in_gossip(bank: &Bank, cluster_info: &ClusterInfo, log: boo
|
|||||||
.map(|vote_state| vote_state.node_pubkey)
|
.map(|vote_state| vote_state.node_pubkey)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
if let Some(peer) = all_tvu_peers
|
if let Some(peer) = peers.get(&vote_state_node_pubkey) {
|
||||||
.iter()
|
|
||||||
.find(|peer| peer.id == vote_state_node_pubkey)
|
|
||||||
{
|
|
||||||
if peer.shred_version == my_shred_version {
|
if peer.shred_version == my_shred_version {
|
||||||
trace!(
|
trace!(
|
||||||
"observed {} in gossip, (activated_stake={})",
|
"observed {} in gossip, (activated_stake={})",
|
||||||
|
Reference in New Issue
Block a user