v1.1: backport commitment max changes (#9775) (#9778)

automerge
This commit is contained in:
mergify[bot]
2020-04-28 16:42:08 -07:00
committed by GitHub
parent f65caa66bf
commit dbaff495c8
16 changed files with 503 additions and 140 deletions

View File

@ -246,7 +246,7 @@ fn main() {
poh_recorder.lock().unwrap().set_bank(&bank); poh_recorder.lock().unwrap().set_bank(&bank);
assert!(poh_recorder.lock().unwrap().bank().is_some()); assert!(poh_recorder.lock().unwrap().bank().is_some());
if bank.slot() > 32 { if bank.slot() > 32 {
bank_forks.set_root(root, &None); bank_forks.set_root(root, &None, None);
root += 1; root += 1;
} }
debug!( debug!(

View File

@ -1,4 +1,5 @@
use crate::consensus::VOTE_THRESHOLD_SIZE; use crate::consensus::VOTE_THRESHOLD_SIZE;
use solana_ledger::blockstore::Blockstore;
use solana_measure::measure::Measure; use solana_measure::measure::Measure;
use solana_metrics::inc_new_counter_info; use solana_metrics::inc_new_counter_info;
use solana_runtime::bank::Bank; use solana_runtime::bank::Bank;
@ -45,11 +46,12 @@ impl BlockCommitment {
} }
} }
#[derive(Default)]
pub struct BlockCommitmentCache { pub struct BlockCommitmentCache {
block_commitment: HashMap<Slot, BlockCommitment>, block_commitment: HashMap<Slot, BlockCommitment>,
largest_confirmed_root: Slot,
total_stake: u64, total_stake: u64,
bank: Arc<Bank>, bank: Arc<Bank>,
blockstore: Arc<Blockstore>,
root: Slot, root: Slot,
} }
@ -70,22 +72,41 @@ impl std::fmt::Debug for BlockCommitmentCache {
impl BlockCommitmentCache { impl BlockCommitmentCache {
pub fn new( pub fn new(
block_commitment: HashMap<Slot, BlockCommitment>, block_commitment: HashMap<Slot, BlockCommitment>,
largest_confirmed_root: Slot,
total_stake: u64, total_stake: u64,
bank: Arc<Bank>, bank: Arc<Bank>,
blockstore: Arc<Blockstore>,
root: Slot, root: Slot,
) -> Self { ) -> Self {
Self { Self {
block_commitment, block_commitment,
largest_confirmed_root,
total_stake, total_stake,
bank, bank,
blockstore,
root, root,
} }
} }
pub fn default_with_blockstore(blockstore: Arc<Blockstore>) -> Self {
Self {
block_commitment: HashMap::default(),
largest_confirmed_root: Slot::default(),
total_stake: u64::default(),
bank: Arc::new(Bank::default()),
blockstore,
root: Slot::default(),
}
}
pub fn get_block_commitment(&self, slot: Slot) -> Option<&BlockCommitment> { pub fn get_block_commitment(&self, slot: Slot) -> Option<&BlockCommitment> {
self.block_commitment.get(&slot) self.block_commitment.get(&slot)
} }
pub fn largest_confirmed_root(&self) -> Slot {
self.largest_confirmed_root
}
pub fn total_stake(&self) -> u64 { pub fn total_stake(&self) -> u64 {
self.total_stake self.total_stake
} }
@ -123,24 +144,28 @@ impl BlockCommitmentCache {
} }
pub fn is_confirmed_rooted(&self, slot: Slot) -> bool { pub fn is_confirmed_rooted(&self, slot: Slot) -> bool {
self.get_block_commitment(slot) slot <= self.largest_confirmed_root()
.map(|block_commitment| { && (self.blockstore.is_root(slot) || self.bank.status_cache_ancestors().contains(&slot))
(block_commitment.get_rooted_stake() as f64 / self.total_stake as f64)
> VOTE_THRESHOLD_SIZE
})
.unwrap_or(false)
} }
#[cfg(test)] #[cfg(test)]
pub fn new_for_tests() -> Self { pub fn new_for_tests_with_blockstore(blockstore: Arc<Blockstore>) -> Self {
let mut block_commitment: HashMap<Slot, BlockCommitment> = HashMap::new(); let mut block_commitment: HashMap<Slot, BlockCommitment> = HashMap::new();
block_commitment.insert(0, BlockCommitment::default()); block_commitment.insert(0, BlockCommitment::default());
Self { Self {
block_commitment, block_commitment,
blockstore,
total_stake: 42, total_stake: 42,
..Self::default() largest_confirmed_root: Slot::default(),
bank: Arc::new(Bank::default()),
root: Slot::default(),
} }
} }
#[cfg(test)]
pub(crate) fn set_get_largest_confirmed_root(&mut self, root: Slot) {
self.largest_confirmed_root = root;
}
} }
pub struct CommitmentAggregationData { pub struct CommitmentAggregationData {
@ -159,6 +184,18 @@ impl CommitmentAggregationData {
} }
} }
fn get_largest_confirmed_root(mut rooted_stake: Vec<(Slot, u64)>, total_stake: u64) -> Slot {
rooted_stake.sort_by(|a, b| a.0.cmp(&b.0).reverse());
let mut stake_sum = 0;
for (root, stake) in rooted_stake {
stake_sum += stake;
if (stake_sum as f64 / total_stake as f64) > VOTE_THRESHOLD_SIZE {
return root;
}
}
0
}
pub struct AggregateCommitmentService { pub struct AggregateCommitmentService {
t_commitment: JoinHandle<()>, t_commitment: JoinHandle<()>,
} }
@ -216,12 +253,18 @@ impl AggregateCommitmentService {
} }
let mut aggregate_commitment_time = Measure::start("aggregate-commitment-ms"); let mut aggregate_commitment_time = Measure::start("aggregate-commitment-ms");
let block_commitment = Self::aggregate_commitment(&ancestors, &aggregation_data.bank); let (block_commitment, rooted_stake) =
Self::aggregate_commitment(&ancestors, &aggregation_data.bank);
let largest_confirmed_root =
get_largest_confirmed_root(rooted_stake, aggregation_data.total_staked);
let mut new_block_commitment = BlockCommitmentCache::new( let mut new_block_commitment = BlockCommitmentCache::new(
block_commitment, block_commitment,
largest_confirmed_root,
aggregation_data.total_staked, aggregation_data.total_staked,
aggregation_data.bank, aggregation_data.bank,
block_commitment_cache.read().unwrap().blockstore.clone(),
aggregation_data.root, aggregation_data.root,
); );
@ -236,7 +279,10 @@ impl AggregateCommitmentService {
} }
} }
pub fn aggregate_commitment(ancestors: &[Slot], bank: &Bank) -> HashMap<Slot, BlockCommitment> { pub fn aggregate_commitment(
ancestors: &[Slot],
bank: &Bank,
) -> (HashMap<Slot, BlockCommitment>, Vec<(Slot, u64)>) {
assert!(!ancestors.is_empty()); assert!(!ancestors.is_empty());
// Check ancestors is sorted // Check ancestors is sorted
@ -245,6 +291,7 @@ impl AggregateCommitmentService {
} }
let mut commitment = HashMap::new(); let mut commitment = HashMap::new();
let mut rooted_stake: Vec<(Slot, u64)> = Vec::new();
for (_, (lamports, account)) in bank.vote_accounts().into_iter() { for (_, (lamports, account)) in bank.vote_accounts().into_iter() {
if lamports == 0 { if lamports == 0 {
continue; continue;
@ -257,17 +304,19 @@ impl AggregateCommitmentService {
let vote_state = vote_state.unwrap(); let vote_state = vote_state.unwrap();
Self::aggregate_commitment_for_vote_account( Self::aggregate_commitment_for_vote_account(
&mut commitment, &mut commitment,
&mut rooted_stake,
&vote_state, &vote_state,
ancestors, ancestors,
lamports, lamports,
); );
} }
commitment (commitment, rooted_stake)
} }
fn aggregate_commitment_for_vote_account( fn aggregate_commitment_for_vote_account(
commitment: &mut HashMap<Slot, BlockCommitment>, commitment: &mut HashMap<Slot, BlockCommitment>,
rooted_stake: &mut Vec<(Slot, u64)>,
vote_state: &VoteState, vote_state: &VoteState,
ancestors: &[Slot], ancestors: &[Slot],
lamports: u64, lamports: u64,
@ -286,6 +335,7 @@ impl AggregateCommitmentService {
break; break;
} }
} }
rooted_stake.push((root, lamports));
} }
for vote in &vote_state.votes { for vote in &vote_state.votes {
@ -312,6 +362,7 @@ impl AggregateCommitmentService {
mod tests { mod tests {
use super::*; use super::*;
use crate::genesis_utils::{create_genesis_config, GenesisConfigInfo}; use crate::genesis_utils::{create_genesis_config, GenesisConfigInfo};
use solana_ledger::get_tmp_ledger_path;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use solana_stake_program::stake_state; use solana_stake_program::stake_state;
use solana_vote_program::vote_state::{self, VoteStateVersions}; use solana_vote_program::vote_state::{self, VoteStateVersions};
@ -329,6 +380,8 @@ mod tests {
#[test] #[test]
fn test_get_confirmations() { fn test_get_confirmations() {
let bank = Arc::new(Bank::default()); let bank = Arc::new(Bank::default());
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
// Build BlockCommitmentCache with votes at depths 0 and 1 for 2 slots // Build BlockCommitmentCache with votes at depths 0 and 1 for 2 slots
let mut cache0 = BlockCommitment::default(); let mut cache0 = BlockCommitment::default();
cache0.increase_confirmation_stake(1, 5); cache0.increase_confirmation_stake(1, 5);
@ -346,7 +399,8 @@ mod tests {
block_commitment.entry(0).or_insert(cache0.clone()); block_commitment.entry(0).or_insert(cache0.clone());
block_commitment.entry(1).or_insert(cache1.clone()); block_commitment.entry(1).or_insert(cache1.clone());
block_commitment.entry(2).or_insert(cache2.clone()); block_commitment.entry(2).or_insert(cache2.clone());
let block_commitment_cache = BlockCommitmentCache::new(block_commitment, 50, bank, 0); let block_commitment_cache =
BlockCommitmentCache::new(block_commitment, 0, 50, bank, blockstore, 0);
assert_eq!(block_commitment_cache.get_confirmation_count(0), Some(2)); assert_eq!(block_commitment_cache.get_confirmation_count(0), Some(2));
assert_eq!(block_commitment_cache.get_confirmation_count(1), Some(1)); assert_eq!(block_commitment_cache.get_confirmation_count(1), Some(1));
@ -354,17 +408,68 @@ mod tests {
assert_eq!(block_commitment_cache.get_confirmation_count(3), None,); assert_eq!(block_commitment_cache.get_confirmation_count(3), None,);
} }
#[test]
fn test_is_confirmed_rooted() {
let bank = Arc::new(Bank::default());
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
blockstore.set_roots(&[0, 1]).unwrap();
// Build BlockCommitmentCache with rooted slots
let mut cache0 = BlockCommitment::default();
cache0.increase_rooted_stake(50);
let mut cache1 = BlockCommitment::default();
cache1.increase_rooted_stake(40);
let mut cache2 = BlockCommitment::default();
cache2.increase_rooted_stake(20);
let mut block_commitment = HashMap::new();
block_commitment.entry(1).or_insert(cache0.clone());
block_commitment.entry(2).or_insert(cache1.clone());
block_commitment.entry(3).or_insert(cache2.clone());
let largest_confirmed_root = 1;
let block_commitment_cache = BlockCommitmentCache::new(
block_commitment,
largest_confirmed_root,
50,
bank,
blockstore,
0,
);
assert!(block_commitment_cache.is_confirmed_rooted(0));
assert!(block_commitment_cache.is_confirmed_rooted(1));
assert!(!block_commitment_cache.is_confirmed_rooted(2));
assert!(!block_commitment_cache.is_confirmed_rooted(3));
}
#[test]
fn test_get_largest_confirmed_root() {
assert_eq!(get_largest_confirmed_root(vec![], 10), 0);
let mut rooted_stake = vec![];
rooted_stake.push((0, 5));
rooted_stake.push((1, 5));
assert_eq!(get_largest_confirmed_root(rooted_stake, 10), 0);
let mut rooted_stake = vec![];
rooted_stake.push((1, 5));
rooted_stake.push((0, 10));
rooted_stake.push((2, 5));
rooted_stake.push((1, 4));
assert_eq!(get_largest_confirmed_root(rooted_stake, 10), 1);
}
#[test] #[test]
fn test_aggregate_commitment_for_vote_account_1() { fn test_aggregate_commitment_for_vote_account_1() {
let ancestors = vec![3, 4, 5, 7, 9, 11]; let ancestors = vec![3, 4, 5, 7, 9, 11];
let mut commitment = HashMap::new(); let mut commitment = HashMap::new();
let mut rooted_stake = vec![];
let lamports = 5; let lamports = 5;
let mut vote_state = VoteState::default(); let mut vote_state = VoteState::default();
let root = ancestors.last().unwrap(); let root = ancestors.last().unwrap().clone();
vote_state.root_slot = Some(*root); vote_state.root_slot = Some(root);
AggregateCommitmentService::aggregate_commitment_for_vote_account( AggregateCommitmentService::aggregate_commitment_for_vote_account(
&mut commitment, &mut commitment,
&mut rooted_stake,
&vote_state, &vote_state,
&ancestors, &ancestors,
lamports, lamports,
@ -375,12 +480,14 @@ mod tests {
expected.increase_rooted_stake(lamports); expected.increase_rooted_stake(lamports);
assert_eq!(*commitment.get(&a).unwrap(), expected); assert_eq!(*commitment.get(&a).unwrap(), expected);
} }
assert_eq!(rooted_stake[0], (root, lamports));
} }
#[test] #[test]
fn test_aggregate_commitment_for_vote_account_2() { fn test_aggregate_commitment_for_vote_account_2() {
let ancestors = vec![3, 4, 5, 7, 9, 11]; let ancestors = vec![3, 4, 5, 7, 9, 11];
let mut commitment = HashMap::new(); let mut commitment = HashMap::new();
let mut rooted_stake = vec![];
let lamports = 5; let lamports = 5;
let mut vote_state = VoteState::default(); let mut vote_state = VoteState::default();
@ -389,6 +496,7 @@ mod tests {
vote_state.process_slot_vote_unchecked(*ancestors.last().unwrap()); vote_state.process_slot_vote_unchecked(*ancestors.last().unwrap());
AggregateCommitmentService::aggregate_commitment_for_vote_account( AggregateCommitmentService::aggregate_commitment_for_vote_account(
&mut commitment, &mut commitment,
&mut rooted_stake,
&vote_state, &vote_state,
&ancestors, &ancestors,
lamports, lamports,
@ -405,12 +513,14 @@ mod tests {
assert_eq!(*commitment.get(&a).unwrap(), expected); assert_eq!(*commitment.get(&a).unwrap(), expected);
} }
} }
assert_eq!(rooted_stake[0], (root, lamports));
} }
#[test] #[test]
fn test_aggregate_commitment_for_vote_account_3() { fn test_aggregate_commitment_for_vote_account_3() {
let ancestors = vec![3, 4, 5, 7, 9, 10, 11]; let ancestors = vec![3, 4, 5, 7, 9, 10, 11];
let mut commitment = HashMap::new(); let mut commitment = HashMap::new();
let mut rooted_stake = vec![];
let lamports = 5; let lamports = 5;
let mut vote_state = VoteState::default(); let mut vote_state = VoteState::default();
@ -421,6 +531,7 @@ mod tests {
vote_state.process_slot_vote_unchecked(ancestors[6]); vote_state.process_slot_vote_unchecked(ancestors[6]);
AggregateCommitmentService::aggregate_commitment_for_vote_account( AggregateCommitmentService::aggregate_commitment_for_vote_account(
&mut commitment, &mut commitment,
&mut rooted_stake,
&vote_state, &vote_state,
&ancestors, &ancestors,
lamports, lamports,
@ -441,6 +552,7 @@ mod tests {
assert_eq!(*commitment.get(&a).unwrap(), expected); assert_eq!(*commitment.get(&a).unwrap(), expected);
} }
} }
assert_eq!(rooted_stake[0], (root, lamports));
} }
#[test] #[test]
@ -450,6 +562,8 @@ mod tests {
mut genesis_config, .. mut genesis_config, ..
} = create_genesis_config(10_000); } = create_genesis_config(10_000);
let rooted_stake_amount = 40;
let sk1 = Pubkey::new_rand(); let sk1 = Pubkey::new_rand();
let pk1 = Pubkey::new_rand(); let pk1 = Pubkey::new_rand();
let mut vote_account1 = vote_state::create_account(&pk1, &Pubkey::new_rand(), 0, 100); let mut vote_account1 = vote_state::create_account(&pk1, &Pubkey::new_rand(), 0, 100);
@ -460,12 +574,36 @@ mod tests {
let mut vote_account2 = vote_state::create_account(&pk2, &Pubkey::new_rand(), 0, 50); let mut vote_account2 = vote_state::create_account(&pk2, &Pubkey::new_rand(), 0, 50);
let stake_account2 = let stake_account2 =
stake_state::create_account(&sk2, &pk2, &vote_account2, &genesis_config.rent, 50); stake_state::create_account(&sk2, &pk2, &vote_account2, &genesis_config.rent, 50);
let sk3 = Pubkey::new_rand();
let pk3 = Pubkey::new_rand();
let mut vote_account3 = vote_state::create_account(&pk3, &Pubkey::new_rand(), 0, 1);
let stake_account3 = stake_state::create_account(
&sk3,
&pk3,
&vote_account3,
&genesis_config.rent,
rooted_stake_amount,
);
let sk4 = Pubkey::new_rand();
let pk4 = Pubkey::new_rand();
let mut vote_account4 = vote_state::create_account(&pk4, &Pubkey::new_rand(), 0, 1);
let stake_account4 = stake_state::create_account(
&sk4,
&pk4,
&vote_account4,
&genesis_config.rent,
rooted_stake_amount,
);
genesis_config.accounts.extend(vec![ genesis_config.accounts.extend(vec![
(pk1, vote_account1.clone()), (pk1, vote_account1.clone()),
(sk1, stake_account1), (sk1, stake_account1),
(pk2, vote_account2.clone()), (pk2, vote_account2.clone()),
(sk2, stake_account2), (sk2, stake_account2),
(pk3, vote_account3.clone()),
(sk3, stake_account3),
(pk4, vote_account4.clone()),
(sk4, stake_account4),
]); ]);
// Create bank // Create bank
@ -485,7 +623,20 @@ mod tests {
VoteState::to(&versioned, &mut vote_account2).unwrap(); VoteState::to(&versioned, &mut vote_account2).unwrap();
bank.store_account(&pk2, &vote_account2); bank.store_account(&pk2, &vote_account2);
let commitment = AggregateCommitmentService::aggregate_commitment(&ancestors, &bank); let mut vote_state3 = VoteState::from(&vote_account3).unwrap();
vote_state3.root_slot = Some(1);
let versioned = VoteStateVersions::Current(Box::new(vote_state3));
VoteState::to(&versioned, &mut vote_account3).unwrap();
bank.store_account(&pk3, &vote_account3);
let mut vote_state4 = VoteState::from(&vote_account4).unwrap();
vote_state4.root_slot = Some(2);
let versioned = VoteStateVersions::Current(Box::new(vote_state4));
VoteState::to(&versioned, &mut vote_account4).unwrap();
bank.store_account(&pk4, &vote_account4);
let (commitment, rooted_stake) =
AggregateCommitmentService::aggregate_commitment(&ancestors, &bank);
for a in ancestors { for a in ancestors {
if a <= 3 { if a <= 3 {
@ -509,5 +660,7 @@ mod tests {
assert!(commitment.get(&a).is_none()); assert!(commitment.get(&a).is_none());
} }
} }
assert_eq!(rooted_stake.len(), 2);
assert_eq!(get_largest_confirmed_root(rooted_stake, 100), 1)
} }
} }

View File

@ -621,7 +621,7 @@ pub mod test {
} }
let vote = tower.new_vote_from_bank(&bank, &my_vote_pubkey).0; let vote = tower.new_vote_from_bank(&bank, &my_vote_pubkey).0;
if let Some(new_root) = tower.record_bank_vote(vote) { if let Some(new_root) = tower.record_bank_vote(vote) {
ReplayStage::handle_new_root(new_root, bank_forks, progress, &None); ReplayStage::handle_new_root(new_root, bank_forks, progress, &None, None);
} }
// Mark the vote for this bank under this node's pubkey so it will be // Mark the vote for this bank under this node's pubkey so it will be

View File

@ -67,7 +67,6 @@ impl Drop for Finalizer {
} }
} }
#[derive(Default)]
pub struct ReplayStageConfig { pub struct ReplayStageConfig {
pub my_pubkey: Pubkey, pub my_pubkey: Pubkey,
pub vote_account: Pubkey, pub vote_account: Pubkey,
@ -257,13 +256,15 @@ impl ReplayStage {
); );
let ancestors = Arc::new(bank_forks.read().unwrap().ancestors()); let ancestors = Arc::new(bank_forks.read().unwrap().ancestors());
let forks_root = bank_forks.read().unwrap().root();
let start = allocated.get(); let start = allocated.get();
let mut frozen_banks: Vec<_> = bank_forks let mut frozen_banks: Vec<_> = bank_forks
.read() .read()
.unwrap() .unwrap()
.frozen_banks() .frozen_banks()
.values() .into_iter()
.cloned() .filter(|(slot, _)| *slot >= forks_root)
.map(|(_, bank)| bank)
.collect(); .collect();
let newly_computed_slot_stats = Self::compute_bank_stats( let newly_computed_slot_stats = Self::compute_bank_stats(
&my_pubkey, &my_pubkey,
@ -344,6 +345,7 @@ impl ReplayStage {
&accounts_hash_sender, &accounts_hash_sender,
&latest_root_senders, &latest_root_senders,
&subscriptions, &subscriptions,
&block_commitment_cache,
)?; )?;
} }
datapoint_debug!( datapoint_debug!(
@ -618,6 +620,7 @@ impl ReplayStage {
accounts_hash_sender: &Option<SnapshotPackageSender>, accounts_hash_sender: &Option<SnapshotPackageSender>,
latest_root_senders: &[Sender<Slot>], latest_root_senders: &[Sender<Slot>],
subscriptions: &Arc<RpcSubscriptions>, subscriptions: &Arc<RpcSubscriptions>,
block_commitment_cache: &Arc<RwLock<BlockCommitmentCache>>,
) -> Result<()> { ) -> Result<()> {
if bank.is_empty() { if bank.is_empty() {
inc_new_counter_info!("replay_stage-voted_empty_bank", 1); inc_new_counter_info!("replay_stage-voted_empty_bank", 1);
@ -643,7 +646,20 @@ impl ReplayStage {
blockstore blockstore
.set_roots(&rooted_slots) .set_roots(&rooted_slots)
.expect("Ledger set roots failed"); .expect("Ledger set roots failed");
Self::handle_new_root(new_root, &bank_forks, progress, accounts_hash_sender); let largest_confirmed_root = Some(
block_commitment_cache
.read()
.unwrap()
.largest_confirmed_root(),
);
Self::handle_new_root(
new_root,
&bank_forks,
progress,
accounts_hash_sender,
largest_confirmed_root,
);
subscriptions.notify_roots(rooted_slots); subscriptions.notify_roots(rooted_slots);
latest_root_senders.iter().for_each(|s| { latest_root_senders.iter().for_each(|s| {
if let Err(e) = s.send(new_root) { if let Err(e) = s.send(new_root) {
@ -979,15 +995,17 @@ impl ReplayStage {
} }
pub(crate) fn handle_new_root( pub(crate) fn handle_new_root(
new_root: u64, new_root: Slot,
bank_forks: &RwLock<BankForks>, bank_forks: &RwLock<BankForks>,
progress: &mut HashMap<u64, ForkProgress>, progress: &mut HashMap<u64, ForkProgress>,
accounts_hash_sender: &Option<SnapshotPackageSender>, accounts_hash_sender: &Option<SnapshotPackageSender>,
largest_confirmed_root: Option<Slot>,
) { ) {
bank_forks bank_forks.write().unwrap().set_root(
.write() new_root,
.unwrap() accounts_hash_sender,
.set_root(new_root, accounts_hash_sender); largest_confirmed_root,
);
let r_bank_forks = bank_forks.read().unwrap(); let r_bank_forks = bank_forks.read().unwrap();
progress.retain(|k, _| r_bank_forks.get(*k).is_some()); progress.retain(|k, _| r_bank_forks.get(*k).is_some());
} }
@ -1016,7 +1034,11 @@ impl ReplayStage {
// Find the next slot that chains to the old slot // Find the next slot that chains to the old slot
let forks = forks_lock.read().unwrap(); let forks = forks_lock.read().unwrap();
let frozen_banks = forks.frozen_banks(); let frozen_banks = forks.frozen_banks();
let frozen_bank_slots: Vec<u64> = frozen_banks.keys().cloned().collect(); let frozen_bank_slots: Vec<u64> = frozen_banks
.keys()
.cloned()
.filter(|s| *s >= forks.root())
.collect();
let next_slots = blockstore let next_slots = blockstore
.get_slots_since(&frozen_bank_slots) .get_slots_since(&frozen_bank_slots)
.expect("Db error"); .expect("Db error");
@ -1419,7 +1441,9 @@ pub(crate) mod tests {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let subscriptions = Arc::new(RpcSubscriptions::new( let subscriptions = Arc::new(RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::default())), Arc::new(RwLock::new(BlockCommitmentCache::default_with_blockstore(
blockstore.clone(),
))),
)); ));
let bank_forks = BankForks::new(0, bank0); let bank_forks = BankForks::new(0, bank0);
bank_forks.working_bank().freeze(); bank_forks.working_bank().freeze();
@ -1472,12 +1496,58 @@ pub(crate) mod tests {
for i in 0..=root { for i in 0..=root {
progress.insert(i, ForkProgress::new(Hash::default())); progress.insert(i, ForkProgress::new(Hash::default()));
} }
ReplayStage::handle_new_root(root, &bank_forks, &mut progress, &None); ReplayStage::handle_new_root(root, &bank_forks, &mut progress, &None, None);
assert_eq!(bank_forks.read().unwrap().root(), root); assert_eq!(bank_forks.read().unwrap().root(), root);
assert_eq!(progress.len(), 1); assert_eq!(progress.len(), 1);
assert!(progress.get(&root).is_some()); assert!(progress.get(&root).is_some());
} }
#[test]
fn test_handle_new_root_ahead_of_largest_confirmed_root() {
let genesis_config = create_genesis_config(10_000).genesis_config;
let bank0 = Bank::new(&genesis_config);
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank0)));
let confirmed_root = 1;
let fork = 2;
let bank1 = Bank::new_from_parent(
bank_forks.read().unwrap().get(0).unwrap(),
&Pubkey::default(),
confirmed_root,
);
bank_forks.write().unwrap().insert(bank1);
let bank2 = Bank::new_from_parent(
bank_forks.read().unwrap().get(confirmed_root).unwrap(),
&Pubkey::default(),
fork,
);
bank_forks.write().unwrap().insert(bank2);
let root = 3;
let root_bank = Bank::new_from_parent(
bank_forks.read().unwrap().get(confirmed_root).unwrap(),
&Pubkey::default(),
root,
);
bank_forks.write().unwrap().insert(root_bank);
let mut progress = HashMap::new();
for i in 0..=root {
progress.insert(i, ForkProgress::new(Hash::default()));
}
ReplayStage::handle_new_root(
root,
&bank_forks,
&mut progress,
&None,
Some(confirmed_root),
);
assert_eq!(bank_forks.read().unwrap().root(), root);
assert!(bank_forks.read().unwrap().get(confirmed_root).is_some());
assert!(bank_forks.read().unwrap().get(fork).is_none());
assert_eq!(progress.len(), 2);
assert!(progress.get(&root).is_some());
assert!(progress.get(&confirmed_root).is_some());
assert!(progress.get(&fork).is_none());
}
#[test] #[test]
fn test_dead_fork_transaction_error() { fn test_dead_fork_transaction_error() {
let keypair1 = Keypair::new(); let keypair1 = Keypair::new();
@ -1745,7 +1815,11 @@ pub(crate) mod tests {
bank.store_account(&pubkey, &leader_vote_account); bank.store_account(&pubkey, &leader_vote_account);
} }
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default())); let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let (lockouts_sender, _) = AggregateCommitmentService::new( let (lockouts_sender, _) = AggregateCommitmentService::new(
&Arc::new(AtomicBool::new(false)), &Arc::new(AtomicBool::new(false)),
block_commitment_cache.clone(), block_commitment_cache.clone(),

View File

@ -9,7 +9,7 @@ use crate::{
validator::ValidatorExit, validator::ValidatorExit,
}; };
use bincode::serialize; use bincode::serialize;
use jsonrpc_core::{Error, Metadata, Result}; use jsonrpc_core::{Error, ErrorCode, Metadata, Result};
use jsonrpc_derive::rpc; use jsonrpc_derive::rpc;
use solana_client::rpc_response::*; use solana_client::rpc_response::*;
use solana_faucet::faucet::request_airdrop_transaction; use solana_faucet::faucet::request_airdrop_transaction;
@ -40,6 +40,7 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
const JSON_RPC_SERVER_ERROR_0: i64 = -32000;
const MAX_QUERY_ITEMS: usize = 256; const MAX_QUERY_ITEMS: usize = 256;
const MAX_SLOT_RANGE: u64 = 10_000; const MAX_SLOT_RANGE: u64 = 10_000;
@ -79,17 +80,32 @@ pub struct JsonRpcRequestProcessor {
} }
impl JsonRpcRequestProcessor { impl JsonRpcRequestProcessor {
fn bank(&self, commitment: Option<CommitmentConfig>) -> Arc<Bank> { fn bank(&self, commitment: Option<CommitmentConfig>) -> Result<Arc<Bank>> {
debug!("RPC commitment_config: {:?}", commitment); debug!("RPC commitment_config: {:?}", commitment);
let r_bank_forks = self.bank_forks.read().unwrap(); let r_bank_forks = self.bank_forks.read().unwrap();
if commitment.is_some() && commitment.unwrap().commitment == CommitmentLevel::Recent { if commitment.is_some() && commitment.unwrap().commitment == CommitmentLevel::Recent {
let bank = r_bank_forks.working_bank(); let bank = r_bank_forks.working_bank();
debug!("RPC using working_bank: {:?}", bank.slot()); debug!("RPC using working_bank: {:?}", bank.slot());
bank Ok(bank)
} else { } else {
let slot = r_bank_forks.root(); let cluster_root = self
debug!("RPC using block: {:?}", slot); .block_commitment_cache
r_bank_forks.get(slot).cloned().unwrap() .read()
.unwrap()
.largest_confirmed_root();
debug!("RPC using block: {:?}", cluster_root);
r_bank_forks
.get(cluster_root)
.cloned()
.ok_or_else(|| Error {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_0),
message: format!(
"Cluster largest_confirmed_root {} does not exist on node. Node root: {}",
cluster_root,
r_bank_forks.root(),
),
data: None,
})
} }
} }
@ -116,7 +132,7 @@ impl JsonRpcRequestProcessor {
pubkey: Result<Pubkey>, pubkey: Result<Pubkey>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<Option<RpcAccount>> { ) -> RpcResponse<Option<RpcAccount>> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
pubkey.and_then(|key| new_response(bank, bank.get_account(&key).map(RpcAccount::encode))) pubkey.and_then(|key| new_response(bank, bank.get_account(&key).map(RpcAccount::encode)))
} }
@ -126,7 +142,7 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<u64> { ) -> Result<u64> {
Ok(self Ok(self
.bank(commitment) .bank(commitment)?
.get_minimum_balance_for_rent_exemption(data_len)) .get_minimum_balance_for_rent_exemption(data_len))
} }
@ -136,7 +152,7 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<Vec<RpcKeyedAccount>> { ) -> Result<Vec<RpcKeyedAccount>> {
Ok(self Ok(self
.bank(commitment) .bank(commitment)?
.get_program_accounts(Some(&program_id)) .get_program_accounts(Some(&program_id))
.into_iter() .into_iter()
.map(|(pubkey, account)| RpcKeyedAccount { .map(|(pubkey, account)| RpcKeyedAccount {
@ -147,13 +163,13 @@ impl JsonRpcRequestProcessor {
} }
pub fn get_inflation(&self, commitment: Option<CommitmentConfig>) -> Result<Inflation> { pub fn get_inflation(&self, commitment: Option<CommitmentConfig>) -> Result<Inflation> {
Ok(self.bank(commitment).inflation()) Ok(self.bank(commitment)?.inflation())
} }
pub fn get_epoch_schedule(&self) -> Result<EpochSchedule> { pub fn get_epoch_schedule(&self) -> Result<EpochSchedule> {
// Since epoch schedule data comes from the genesis config, any commitment level should be // Since epoch schedule data comes from the genesis config, any commitment level should be
// fine // fine
Ok(*self.bank(None).epoch_schedule()) Ok(*self.bank(None)?.epoch_schedule())
} }
pub fn get_balance( pub fn get_balance(
@ -161,7 +177,7 @@ impl JsonRpcRequestProcessor {
pubkey: Result<Pubkey>, pubkey: Result<Pubkey>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<u64> { ) -> RpcResponse<u64> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
pubkey.and_then(|key| new_response(bank, bank.get_balance(&key))) pubkey.and_then(|key| new_response(bank, bank.get_balance(&key)))
} }
@ -169,7 +185,7 @@ impl JsonRpcRequestProcessor {
&self, &self,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhashFeeCalculator> { ) -> RpcResponse<RpcBlockhashFeeCalculator> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash(); let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
new_response( new_response(
bank, bank,
@ -184,7 +200,7 @@ impl JsonRpcRequestProcessor {
&self, &self,
blockhash: &Hash, blockhash: &Hash,
) -> RpcResponse<Option<RpcFeeCalculator>> { ) -> RpcResponse<Option<RpcFeeCalculator>> {
let bank = &*self.bank(None); let bank = &*self.bank(None)?;
let fee_calculator = bank.get_fee_calculator(blockhash); let fee_calculator = bank.get_fee_calculator(blockhash);
new_response( new_response(
bank, bank,
@ -193,7 +209,7 @@ impl JsonRpcRequestProcessor {
} }
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> { fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
let bank = &*self.bank(None); let bank = &*self.bank(None)?;
let fee_rate_governor = bank.get_fee_rate_governor(); let fee_rate_governor = bank.get_fee_rate_governor();
new_response( new_response(
bank, bank,
@ -208,7 +224,7 @@ impl JsonRpcRequestProcessor {
signature: Result<Signature>, signature: Result<Signature>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<bool> { ) -> RpcResponse<bool> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
match signature { match signature {
Err(e) => Err(e), Err(e) => Err(e),
Ok(sig) => { Ok(sig) => {
@ -232,11 +248,11 @@ impl JsonRpcRequestProcessor {
} }
fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).slot()) Ok(self.bank(commitment)?.slot())
} }
fn get_slot_leader(&self, commitment: Option<CommitmentConfig>) -> Result<String> { fn get_slot_leader(&self, commitment: Option<CommitmentConfig>) -> Result<String> {
Ok(self.bank(commitment).collector_id().to_string()) Ok(self.bank(commitment)?.collector_id().to_string())
} }
fn minimum_ledger_slot(&self) -> Result<Slot> { fn minimum_ledger_slot(&self) -> Result<Slot> {
@ -253,18 +269,18 @@ impl JsonRpcRequestProcessor {
} }
fn get_transaction_count(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_transaction_count(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).transaction_count() as u64) Ok(self.bank(commitment)?.transaction_count() as u64)
} }
fn get_total_supply(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_total_supply(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).capitalization()) Ok(self.bank(commitment)?.capitalization())
} }
fn get_vote_accounts( fn get_vote_accounts(
&self, &self,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<RpcVoteAccountStatus> { ) -> Result<RpcVoteAccountStatus> {
let bank = self.bank(commitment); let bank = self.bank(commitment)?;
let vote_accounts = bank.vote_accounts(); let vote_accounts = bank.vote_accounts();
let epoch_vote_accounts = bank let epoch_vote_accounts = bank
.epoch_vote_accounts(bank.get_epoch_and_slot_index(bank.slot()).0) .epoch_vote_accounts(bank.get_epoch_and_slot_index(bank.slot()).0)
@ -326,7 +342,7 @@ impl JsonRpcRequestProcessor {
} }
fn get_slots_per_segment(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_slots_per_segment(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).slots_per_segment()) Ok(self.bank(commitment)?.slots_per_segment())
} }
fn get_storage_pubkeys_for_slot(&self, slot: Slot) -> Result<Vec<String>> { fn get_storage_pubkeys_for_slot(&self, slot: Slot) -> Result<Vec<String>> {
@ -376,7 +392,11 @@ impl JsonRpcRequestProcessor {
start_slot: Slot, start_slot: Slot,
end_slot: Option<Slot>, end_slot: Option<Slot>,
) -> Result<Vec<Slot>> { ) -> Result<Vec<Slot>> {
let end_slot = end_slot.unwrap_or_else(|| self.bank(None).slot()); let end_slot = if let Some(end_slot) = end_slot {
end_slot
} else {
self.bank(None)?.slot()
};
if end_slot < start_slot { if end_slot < start_slot {
return Ok(vec![]); return Ok(vec![]);
} }
@ -394,7 +414,7 @@ impl JsonRpcRequestProcessor {
// queried). If these values will be variable in the future, those timing parameters will // queried). If these values will be variable in the future, those timing parameters will
// need to be stored persistently, and the slot_duration calculation will likely need to be // need to be stored persistently, and the slot_duration calculation will likely need to be
// moved upstream into blockstore. Also, an explicit commitment level will need to be set. // moved upstream into blockstore. Also, an explicit commitment level will need to be set.
let bank = self.bank(None); let bank = self.bank(None)?;
let slot_duration = slot_duration_from_slots_per_year(bank.slots_per_year()); let slot_duration = slot_duration_from_slots_per_year(bank.slots_per_year());
let epoch = bank.epoch_schedule().get_epoch(slot); let epoch = bank.epoch_schedule().get_epoch(slot);
let stakes = HashMap::new(); let stakes = HashMap::new();
@ -412,7 +432,7 @@ impl JsonRpcRequestProcessor {
signature: Signature, signature: Signature,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Option<RpcSignatureConfirmation> { ) -> Option<RpcSignatureConfirmation> {
self.get_transaction_status(signature, &self.bank(commitment)) self.get_transaction_status(signature, &self.bank(commitment).ok()?)
.map( .map(
|TransactionStatus { |TransactionStatus {
status, status,
@ -430,7 +450,7 @@ impl JsonRpcRequestProcessor {
signature: Signature, signature: Signature,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Option<transaction::Result<()>> { ) -> Option<transaction::Result<()>> {
self.bank(commitment).get_signature_status(&signature) self.bank(commitment).ok()?.get_signature_status(&signature)
} }
pub fn get_signature_statuses( pub fn get_signature_statuses(
@ -449,7 +469,7 @@ impl JsonRpcRequestProcessor {
let search_transaction_history = config let search_transaction_history = config
.and_then(|x| x.search_transaction_history) .and_then(|x| x.search_transaction_history)
.unwrap_or(false); .unwrap_or(false);
let bank = self.bank(commitment); let bank = self.bank(commitment)?;
for signature in signatures { for signature in signatures {
let status = if let Some(status) = self.get_transaction_status(signature, &bank) { let status = if let Some(status) = self.get_transaction_status(signature, &bank) {
@ -944,7 +964,7 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata, meta: Self::Metadata,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<RpcEpochInfo> { ) -> Result<RpcEpochInfo> {
let bank = meta.request_processor.read().unwrap().bank(commitment); let bank = meta.request_processor.read().unwrap().bank(commitment)?;
let epoch_schedule = bank.epoch_schedule(); let epoch_schedule = bank.epoch_schedule();
let slot = bank.slot(); let slot = bank.slot();
@ -980,7 +1000,7 @@ impl RpcSol for RpcSolImpl {
slot: Option<Slot>, slot: Option<Slot>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<Option<RpcLeaderSchedule>> { ) -> Result<Option<RpcLeaderSchedule>> {
let bank = meta.request_processor.read().unwrap().bank(commitment); let bank = meta.request_processor.read().unwrap().bank(commitment)?;
let slot = slot.unwrap_or_else(|| bank.slot()); let slot = slot.unwrap_or_else(|| bank.slot());
let epoch = bank.epoch_schedule().get_epoch(slot); let epoch = bank.epoch_schedule().get_epoch(slot);
@ -1144,7 +1164,7 @@ impl RpcSol for RpcSolImpl {
.request_processor .request_processor
.read() .read()
.unwrap() .unwrap()
.bank(commitment.clone()) .bank(commitment.clone())?
.confirmed_last_blockhash() .confirmed_last_blockhash()
.0; .0;
let transaction = request_airdrop_transaction(&faucet_addr, &pubkey, lamports, blockhash) let transaction = request_airdrop_transaction(&faucet_addr, &pubkey, lamports, blockhash)
@ -1491,8 +1511,10 @@ pub mod tests {
.or_insert(commitment_slot1.clone()); .or_insert(commitment_slot1.clone());
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::new( let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::new(
block_commitment, block_commitment,
0,
10, 10,
bank.clone(), bank.clone(),
blockstore.clone(),
0, 0,
))); )));
@ -1524,15 +1546,13 @@ pub mod tests {
let mut roots = blockstore_roots.clone(); let mut roots = blockstore_roots.clone();
if !roots.is_empty() { if !roots.is_empty() {
roots.retain(|&x| x > 1); roots.retain(|&x| x > 0);
let mut parent_bank = bank; let mut parent_bank = bank;
for (i, root) in roots.iter().enumerate() { for (i, root) in roots.iter().enumerate() {
let new_bank = let new_bank =
Bank::new_from_parent(&parent_bank, parent_bank.collector_id(), *root); Bank::new_from_parent(&parent_bank, parent_bank.collector_id(), *root);
parent_bank = bank_forks.write().unwrap().insert(new_bank); parent_bank = bank_forks.write().unwrap().insert(new_bank);
parent_bank.squash(); let parent = if i > 0 { roots[i - 1] } else { 0 };
bank_forks.write().unwrap().set_root(*root, &None);
let parent = if i > 0 { roots[i - 1] } else { 1 };
fill_blockstore_slot_with_ticks(&blockstore, 5, *root, parent, Hash::default()); fill_blockstore_slot_with_ticks(&blockstore, 5, *root, parent, Hash::default());
} }
blockstore.set_roots(&roots).unwrap(); blockstore.set_roots(&roots).unwrap();
@ -1542,6 +1562,10 @@ pub mod tests {
roots.iter().max().unwrap() + 1, roots.iter().max().unwrap() + 1,
); );
bank_forks.write().unwrap().insert(new_bank); bank_forks.write().unwrap().insert(new_bank);
for root in roots.iter() {
bank_forks.write().unwrap().set_root(*root, &None, Some(0));
}
} }
let bank = bank_forks.read().unwrap().working_bank(); let bank = bank_forks.read().unwrap().working_bank();
@ -1610,14 +1634,16 @@ pub mod tests {
let validator_exit = create_validator_exit(&exit); let validator_exit = create_validator_exit(&exit);
let (bank_forks, alice, _) = new_bank_forks(); let (bank_forks, alice, _) = new_bank_forks();
let bank = bank_forks.read().unwrap().working_bank(); let bank = bank_forks.read().unwrap().working_bank();
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&ledger_path).unwrap(); let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let request_processor = JsonRpcRequestProcessor::new( let request_processor = JsonRpcRequestProcessor::new(
JsonRpcConfig::default(), JsonRpcConfig::default(),
bank_forks, bank_forks,
block_commitment_cache, block_commitment_cache,
Arc::new(blockstore), blockstore,
StorageState::default(), StorageState::default(),
validator_exit, validator_exit,
); );
@ -2089,7 +2115,7 @@ pub mod tests {
.expect("actual response deserialization"); .expect("actual response deserialization");
let result = result.as_ref().unwrap(); let result = result.as_ref().unwrap();
assert_eq!(expected_res, result.status); assert_eq!(expected_res, result.status);
assert_eq!(Some(2), result.confirmations); assert_eq!(None, result.confirmations);
// Test getSignatureStatus request on unprocessed tx // Test getSignatureStatus request on unprocessed tx
let tx = system_transaction::transfer(&alice, &bob_pubkey, 10, blockhash); let tx = system_transaction::transfer(&alice, &bob_pubkey, 10, blockhash);
@ -2253,9 +2279,11 @@ pub mod tests {
fn test_rpc_send_bad_tx() { fn test_rpc_send_bad_tx() {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let validator_exit = create_validator_exit(&exit); let validator_exit = create_validator_exit(&exit);
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&ledger_path).unwrap(); let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let mut io = MetaIoHandler::default(); let mut io = MetaIoHandler::default();
let rpc = RpcSolImpl; let rpc = RpcSolImpl;
@ -2266,7 +2294,7 @@ pub mod tests {
JsonRpcConfig::default(), JsonRpcConfig::default(),
new_bank_forks().0, new_bank_forks().0,
block_commitment_cache, block_commitment_cache,
Arc::new(blockstore), blockstore,
StorageState::default(), StorageState::default(),
validator_exit, validator_exit,
); );
@ -2356,14 +2384,16 @@ pub mod tests {
fn test_rpc_request_processor_config_default_trait_validator_exit_fails() { fn test_rpc_request_processor_config_default_trait_validator_exit_fails() {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let validator_exit = create_validator_exit(&exit); let validator_exit = create_validator_exit(&exit);
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&ledger_path).unwrap(); let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let request_processor = JsonRpcRequestProcessor::new( let request_processor = JsonRpcRequestProcessor::new(
JsonRpcConfig::default(), JsonRpcConfig::default(),
new_bank_forks().0, new_bank_forks().0,
block_commitment_cache, block_commitment_cache,
Arc::new(blockstore), blockstore,
StorageState::default(), StorageState::default(),
validator_exit, validator_exit,
); );
@ -2375,16 +2405,18 @@ pub mod tests {
fn test_rpc_request_processor_allow_validator_exit_config() { fn test_rpc_request_processor_allow_validator_exit_config() {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let validator_exit = create_validator_exit(&exit); let validator_exit = create_validator_exit(&exit);
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&ledger_path).unwrap(); let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let mut config = JsonRpcConfig::default(); let mut config = JsonRpcConfig::default();
config.enable_validator_exit = true; config.enable_validator_exit = true;
let request_processor = JsonRpcRequestProcessor::new( let request_processor = JsonRpcRequestProcessor::new(
config, config,
new_bank_forks().0, new_bank_forks().0,
block_commitment_cache, block_commitment_cache,
Arc::new(blockstore), blockstore,
StorageState::default(), StorageState::default(),
validator_exit, validator_exit,
); );
@ -2439,6 +2471,8 @@ pub mod tests {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let validator_exit = create_validator_exit(&exit); let validator_exit = create_validator_exit(&exit);
let bank_forks = new_bank_forks().0; let bank_forks = new_bank_forks().0;
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let commitment_slot0 = BlockCommitment::new([8; MAX_LOCKOUT_HISTORY + 1]); let commitment_slot0 = BlockCommitment::new([8; MAX_LOCKOUT_HISTORY + 1]);
let commitment_slot1 = BlockCommitment::new([9; MAX_LOCKOUT_HISTORY + 1]); let commitment_slot1 = BlockCommitment::new([9; MAX_LOCKOUT_HISTORY + 1]);
@ -2451,12 +2485,12 @@ pub mod tests {
.or_insert(commitment_slot1.clone()); .or_insert(commitment_slot1.clone());
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::new( let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::new(
block_commitment, block_commitment,
0,
42, 42,
bank_forks.read().unwrap().working_bank(), bank_forks.read().unwrap().working_bank(),
blockstore.clone(),
0, 0,
))); )));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&ledger_path).unwrap();
let mut config = JsonRpcConfig::default(); let mut config = JsonRpcConfig::default();
config.enable_validator_exit = true; config.enable_validator_exit = true;
@ -2464,7 +2498,7 @@ pub mod tests {
config, config,
bank_forks, bank_forks,
block_commitment_cache, block_commitment_cache,
Arc::new(blockstore), blockstore,
StorageState::default(), StorageState::default(),
validator_exit, validator_exit,
); );
@ -2648,8 +2682,16 @@ pub mod tests {
fn test_get_confirmed_blocks() { fn test_get_confirmed_blocks() {
let bob_pubkey = Pubkey::new_rand(); let bob_pubkey = Pubkey::new_rand();
let roots = vec![0, 1, 3, 4, 8]; let roots = vec![0, 1, 3, 4, 8];
let RpcHandler { io, meta, .. } = let RpcHandler {
start_rpc_handler_with_tx_and_blockstore(&bob_pubkey, roots.clone(), 0); io,
meta,
block_commitment_cache,
..
} = start_rpc_handler_with_tx_and_blockstore(&bob_pubkey, roots.clone(), 0);
block_commitment_cache
.write()
.unwrap()
.set_get_largest_confirmed_root(8);
let req = let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0]}}"#); format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0]}}"#);

View File

@ -7,8 +7,13 @@ use jsonrpc_pubsub::{typed::Subscriber, Session, SubscriptionId};
use solana_client::rpc_response::{ use solana_client::rpc_response::{
Response as RpcResponse, RpcAccount, RpcKeyedAccount, RpcSignatureResult, Response as RpcResponse, RpcAccount, RpcKeyedAccount, RpcSignatureResult,
}; };
#[cfg(test)]
use solana_ledger::blockstore::Blockstore;
use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature}; use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature};
use std::sync::{atomic, Arc}; use std::{
str::FromStr,
sync::{atomic, Arc},
};
// Suppress needless_return due to // Suppress needless_return due to
// https://github.com/paritytech/jsonrpc/blob/2d38e6424d8461cdf72e78425ce67d51af9c6586/derive/src/lib.rs#L204 // https://github.com/paritytech/jsonrpc/blob/2d38e6424d8461cdf72e78425ce67d51af9c6586/derive/src/lib.rs#L204
@ -118,7 +123,6 @@ pub trait RpcSolPubSub {
fn root_unsubscribe(&self, meta: Option<Self::Metadata>, id: SubscriptionId) -> Result<bool>; fn root_unsubscribe(&self, meta: Option<Self::Metadata>, id: SubscriptionId) -> Result<bool>;
} }
#[derive(Default)]
pub struct RpcSolPubSubImpl { pub struct RpcSolPubSubImpl {
uid: Arc<atomic::AtomicUsize>, uid: Arc<atomic::AtomicUsize>,
subscriptions: Arc<RpcSubscriptions>, subscriptions: Arc<RpcSubscriptions>,
@ -129,9 +133,14 @@ impl RpcSolPubSubImpl {
let uid = Arc::new(atomic::AtomicUsize::default()); let uid = Arc::new(atomic::AtomicUsize::default());
Self { uid, subscriptions } Self { uid, subscriptions }
} }
}
use std::str::FromStr; #[cfg(test)]
fn default_with_blockstore(blockstore: Arc<Blockstore>) -> Self {
let uid = Arc::new(atomic::AtomicUsize::default());
let subscriptions = Arc::new(RpcSubscriptions::default_with_blockstore(blockstore));
Self { uid, subscriptions }
}
}
fn param<T: FromStr>(param_str: &str, thing: &str) -> Result<T> { fn param<T: FromStr>(param_str: &str, thing: &str) -> Result<T> {
param_str.parse::<T>().map_err(|_e| Error { param_str.parse::<T>().map_err(|_e| Error {
@ -323,7 +332,7 @@ mod tests {
use jsonrpc_pubsub::{PubSubHandler, Session}; use jsonrpc_pubsub::{PubSubHandler, Session};
use serial_test_derive::serial; use serial_test_derive::serial;
use solana_budget_program::{self, budget_instruction}; use solana_budget_program::{self, budget_instruction};
use solana_ledger::bank_forks::BankForks; use solana_ledger::{bank_forks::BankForks, get_tmp_ledger_path};
use solana_runtime::bank::Bank; use solana_runtime::bank::Bank;
use solana_sdk::{ use solana_sdk::{
pubkey::Pubkey, pubkey::Pubkey,
@ -370,12 +379,16 @@ mod tests {
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash(); let blockhash = bank.last_blockhash();
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank))); let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let rpc = RpcSolPubSubImpl { let rpc = RpcSolPubSubImpl {
subscriptions: Arc::new(RpcSubscriptions::new( subscriptions: Arc::new(RpcSubscriptions::new(
&Arc::new(AtomicBool::new(false)), &Arc::new(AtomicBool::new(false)),
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)), )),
..RpcSolPubSubImpl::default() )),
uid: Arc::new(atomic::AtomicUsize::default()),
}; };
// Test signature subscriptions // Test signature subscriptions
@ -416,11 +429,13 @@ mod tests {
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let arc_bank = Arc::new(bank); let arc_bank = Arc::new(bank);
let blockhash = arc_bank.last_blockhash(); let blockhash = arc_bank.last_blockhash();
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let session = create_session(); let session = create_session();
let mut io = PubSubHandler::default(); let mut io = PubSubHandler::default();
let rpc = RpcSolPubSubImpl::default(); let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
io.extend_with(rpc.to_delegate()); io.extend_with(rpc.to_delegate());
let tx = system_transaction::transfer(&alice, &bob_pubkey, 20, blockhash); let tx = system_transaction::transfer(&alice, &bob_pubkey, 20, blockhash);
@ -475,13 +490,17 @@ mod tests {
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash(); let blockhash = bank.last_blockhash();
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank))); let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let rpc = RpcSolPubSubImpl { let rpc = RpcSolPubSubImpl {
subscriptions: Arc::new(RpcSubscriptions::new( subscriptions: Arc::new(RpcSubscriptions::new(
&Arc::new(AtomicBool::new(false)), &Arc::new(AtomicBool::new(false)),
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)), )),
..RpcSolPubSubImpl::default() )),
uid: Arc::new(atomic::AtomicUsize::default()),
}; };
let session = create_session(); let session = create_session();
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("accountNotification"); let (subscriber, _id_receiver, receiver) = Subscriber::new_test("accountNotification");
@ -569,9 +588,11 @@ mod tests {
fn test_account_unsubscribe() { fn test_account_unsubscribe() {
let bob_pubkey = Pubkey::new_rand(); let bob_pubkey = Pubkey::new_rand();
let session = create_session(); let session = create_session();
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let mut io = PubSubHandler::default(); let mut io = PubSubHandler::default();
let rpc = RpcSolPubSubImpl::default(); let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
io.extend_with(rpc.to_delegate()); io.extend_with(rpc.to_delegate());
@ -615,13 +636,17 @@ mod tests {
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash(); let blockhash = bank.last_blockhash();
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank))); let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let bob = Keypair::new(); let bob = Keypair::new();
let mut rpc = RpcSolPubSubImpl::default(); let mut rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore.clone());
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let subscriptions = RpcSubscriptions::new( let subscriptions = RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)),
); );
rpc.subscriptions = Arc::new(subscriptions); rpc.subscriptions = Arc::new(subscriptions);
let session = create_session(); let session = create_session();
@ -652,11 +677,15 @@ mod tests {
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash(); let blockhash = bank.last_blockhash();
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank))); let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let bob = Keypair::new(); let bob = Keypair::new();
let mut rpc = RpcSolPubSubImpl::default(); let mut rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore.clone());
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())); let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore.clone()),
));
let subscriptions = RpcSubscriptions::new(&exit, block_commitment_cache.clone()); let subscriptions = RpcSubscriptions::new(&exit, block_commitment_cache.clone());
rpc.subscriptions = Arc::new(subscriptions); rpc.subscriptions = Arc::new(subscriptions);
@ -683,8 +712,14 @@ mod tests {
cache0.increase_confirmation_stake(1, 10); cache0.increase_confirmation_stake(1, 10);
let mut block_commitment = HashMap::new(); let mut block_commitment = HashMap::new();
block_commitment.entry(0).or_insert(cache0.clone()); block_commitment.entry(0).or_insert(cache0.clone());
let mut new_block_commitment = let mut new_block_commitment = BlockCommitmentCache::new(
BlockCommitmentCache::new(block_commitment, 10, bank1.clone(), 0); block_commitment,
0,
10,
bank1.clone(),
blockstore.clone(),
0,
);
let mut w_block_commitment_cache = block_commitment_cache.write().unwrap(); let mut w_block_commitment_cache = block_commitment_cache.write().unwrap();
std::mem::swap(&mut *w_block_commitment_cache, &mut new_block_commitment); std::mem::swap(&mut *w_block_commitment_cache, &mut new_block_commitment);
drop(w_block_commitment_cache); drop(w_block_commitment_cache);
@ -698,7 +733,8 @@ mod tests {
cache0.increase_confirmation_stake(2, 10); cache0.increase_confirmation_stake(2, 10);
let mut block_commitment = HashMap::new(); let mut block_commitment = HashMap::new();
block_commitment.entry(0).or_insert(cache0.clone()); block_commitment.entry(0).or_insert(cache0.clone());
let mut new_block_commitment = BlockCommitmentCache::new(block_commitment, 10, bank2, 0); let mut new_block_commitment =
BlockCommitmentCache::new(block_commitment, 0, 10, bank2, blockstore.clone(), 0);
let mut w_block_commitment_cache = block_commitment_cache.write().unwrap(); let mut w_block_commitment_cache = block_commitment_cache.write().unwrap();
std::mem::swap(&mut *w_block_commitment_cache, &mut new_block_commitment); std::mem::swap(&mut *w_block_commitment_cache, &mut new_block_commitment);
drop(w_block_commitment_cache); drop(w_block_commitment_cache);
@ -728,7 +764,9 @@ mod tests {
#[test] #[test]
#[serial] #[serial]
fn test_slot_subscribe() { fn test_slot_subscribe() {
let rpc = RpcSolPubSubImpl::default(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
let session = create_session(); let session = create_session();
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("slotNotification"); let (subscriber, _id_receiver, receiver) = Subscriber::new_test("slotNotification");
rpc.slot_subscribe(session, subscriber); rpc.slot_subscribe(session, subscriber);
@ -753,7 +791,9 @@ mod tests {
#[test] #[test]
#[serial] #[serial]
fn test_slot_unsubscribe() { fn test_slot_unsubscribe() {
let rpc = RpcSolPubSubImpl::default(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
let session = create_session(); let session = create_session();
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("slotNotification"); let (subscriber, _id_receiver, receiver) = Subscriber::new_test("slotNotification");
rpc.slot_subscribe(session, subscriber); rpc.slot_subscribe(session, subscriber);

View File

@ -73,6 +73,7 @@ impl PubSubService {
mod tests { mod tests {
use super::*; use super::*;
use crate::commitment::BlockCommitmentCache; use crate::commitment::BlockCommitmentCache;
use solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path};
use std::{ use std::{
net::{IpAddr, Ipv4Addr}, net::{IpAddr, Ipv4Addr},
sync::RwLock, sync::RwLock,
@ -82,9 +83,13 @@ mod tests {
fn test_pubsub_new() { fn test_pubsub_new() {
let pubsub_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); let pubsub_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let subscriptions = Arc::new(RpcSubscriptions::new( let subscriptions = Arc::new(RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)),
)); ));
let pubsub_service = PubSubService::new(&subscriptions, pubsub_addr, &exit); let pubsub_service = PubSubService::new(&subscriptions, pubsub_addr, &exit);
let thread = pubsub_service.thread_hdl.thread(); let thread = pubsub_service.thread_hdl.thread();

View File

@ -361,16 +361,18 @@ mod tests {
solana_net_utils::find_available_port_in_range(ip_addr, (10000, 65535)).unwrap(), solana_net_utils::find_available_port_in_range(ip_addr, (10000, 65535)).unwrap(),
); );
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank.slot(), bank))); let bank_forks = Arc::new(RwLock::new(BankForks::new(bank.slot(), bank)));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&ledger_path).unwrap(); let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let mut rpc_service = JsonRpcService::new( let mut rpc_service = JsonRpcService::new(
rpc_addr, rpc_addr,
JsonRpcConfig::default(), JsonRpcConfig::default(),
None, None,
bank_forks, bank_forks,
block_commitment_cache, block_commitment_cache,
Arc::new(blockstore), blockstore,
cluster_info, cluster_info,
Hash::default(), Hash::default(),
&PathBuf::from("farf"), &PathBuf::from("farf"),

View File

@ -11,7 +11,7 @@ use serde::Serialize;
use solana_client::rpc_response::{ use solana_client::rpc_response::{
Response, RpcAccount, RpcKeyedAccount, RpcResponseContext, RpcSignatureResult, Response, RpcAccount, RpcKeyedAccount, RpcResponseContext, RpcSignatureResult,
}; };
use solana_ledger::bank_forks::BankForks; use solana_ledger::{bank_forks::BankForks, blockstore::Blockstore};
use solana_runtime::bank::Bank; use solana_runtime::bank::Bank;
use solana_sdk::{ use solana_sdk::{
account::Account, clock::Slot, pubkey::Pubkey, signature::Signature, transaction, account::Account, clock::Slot, pubkey::Pubkey, signature::Signature, transaction,
@ -246,15 +246,6 @@ pub struct RpcSubscriptions {
exit: Arc<AtomicBool>, exit: Arc<AtomicBool>,
} }
impl Default for RpcSubscriptions {
fn default() -> Self {
Self::new(
&Arc::new(AtomicBool::new(false)),
Arc::new(RwLock::new(BlockCommitmentCache::default())),
)
}
}
impl Drop for RpcSubscriptions { impl Drop for RpcSubscriptions {
fn drop(&mut self) { fn drop(&mut self) {
self.shutdown().unwrap_or_else(|err| { self.shutdown().unwrap_or_else(|err| {
@ -324,6 +315,15 @@ impl RpcSubscriptions {
} }
} }
pub fn default_with_blockstore(blockstore: Arc<Blockstore>) -> Self {
Self::new(
&Arc::new(AtomicBool::new(false)),
Arc::new(RwLock::new(BlockCommitmentCache::default_with_blockstore(
blockstore,
))),
)
}
fn check_account( fn check_account(
pubkey: &Pubkey, pubkey: &Pubkey,
bank_forks: &Arc<RwLock<BankForks>>, bank_forks: &Arc<RwLock<BankForks>>,
@ -624,6 +624,7 @@ pub(crate) mod tests {
use jsonrpc_pubsub::typed::Subscriber; use jsonrpc_pubsub::typed::Subscriber;
use serial_test_derive::serial; use serial_test_derive::serial;
use solana_budget_program; use solana_budget_program;
use solana_ledger::get_tmp_ledger_path;
use solana_sdk::{ use solana_sdk::{
signature::{Keypair, Signer}, signature::{Keypair, Signer},
system_transaction, system_transaction,
@ -664,6 +665,8 @@ pub(crate) mod tests {
mint_keypair, mint_keypair,
.. ..
} = create_genesis_config(100); } = create_genesis_config(100);
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash(); let blockhash = bank.last_blockhash();
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank))); let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
@ -690,7 +693,9 @@ pub(crate) mod tests {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let subscriptions = RpcSubscriptions::new( let subscriptions = RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)),
); );
subscriptions.add_account_subscription(alice.pubkey(), None, sub_id.clone(), subscriber); subscriptions.add_account_subscription(alice.pubkey(), None, sub_id.clone(), subscriber);
@ -737,6 +742,8 @@ pub(crate) mod tests {
mint_keypair, mint_keypair,
.. ..
} = create_genesis_config(100); } = create_genesis_config(100);
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash(); let blockhash = bank.last_blockhash();
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank))); let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
@ -763,7 +770,9 @@ pub(crate) mod tests {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let subscriptions = RpcSubscriptions::new( let subscriptions = RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)),
); );
subscriptions.add_program_subscription( subscriptions.add_program_subscription(
solana_budget_program::id(), solana_budget_program::id(),
@ -818,6 +827,8 @@ pub(crate) mod tests {
mint_keypair, mint_keypair,
.. ..
} = create_genesis_config(100); } = create_genesis_config(100);
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let bank = Bank::new(&genesis_config); let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash(); let blockhash = bank.last_blockhash();
let mut bank_forks = BankForks::new(0, bank); let mut bank_forks = BankForks::new(0, bank);
@ -856,7 +867,8 @@ pub(crate) mod tests {
let mut block_commitment = HashMap::new(); let mut block_commitment = HashMap::new();
block_commitment.entry(0).or_insert(cache0.clone()); block_commitment.entry(0).or_insert(cache0.clone());
block_commitment.entry(1).or_insert(cache1.clone()); block_commitment.entry(1).or_insert(cache1.clone());
let block_commitment_cache = BlockCommitmentCache::new(block_commitment, 10, bank1, 0); let block_commitment_cache =
BlockCommitmentCache::new(block_commitment, 0, 10, bank1, blockstore, 0);
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let subscriptions = let subscriptions =
@ -959,9 +971,13 @@ pub(crate) mod tests {
Subscriber::new_test("slotNotification"); Subscriber::new_test("slotNotification");
let sub_id = SubscriptionId::Number(0 as u64); let sub_id = SubscriptionId::Number(0 as u64);
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let subscriptions = RpcSubscriptions::new( let subscriptions = RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)),
); );
subscriptions.add_slot_subscription(sub_id.clone(), subscriber); subscriptions.add_slot_subscription(sub_id.clone(), subscriber);
@ -1001,9 +1017,13 @@ pub(crate) mod tests {
Subscriber::new_test("rootNotification"); Subscriber::new_test("rootNotification");
let sub_id = SubscriptionId::Number(0 as u64); let sub_id = SubscriptionId::Number(0 as u64);
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let subscriptions = RpcSubscriptions::new( let subscriptions = RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
)),
); );
subscriptions.add_root_subscription(sub_id.clone(), subscriber); subscriptions.add_root_subscription(sub_id.clone(), subscriber);

View File

@ -663,6 +663,7 @@ mod tests {
use super::*; use super::*;
use crate::genesis_utils::{create_genesis_config, GenesisConfigInfo}; use crate::genesis_utils::{create_genesis_config, GenesisConfigInfo};
use rayon::prelude::*; use rayon::prelude::*;
use solana_ledger::get_tmp_ledger_path;
use solana_runtime::bank::Bank; use solana_runtime::bank::Bank;
use solana_sdk::{ use solana_sdk::{
hash::Hasher, hash::Hasher,
@ -690,7 +691,11 @@ mod tests {
&[bank.clone()], &[bank.clone()],
vec![0], vec![0],
))); )));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default())); let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore),
));
let (_slot_sender, slot_receiver) = channel(); let (_slot_sender, slot_receiver) = channel();
let storage_state = StorageState::new( let storage_state = StorageState::new(
&bank.last_blockhash(), &bank.last_blockhash(),

View File

@ -301,7 +301,9 @@ pub mod tests {
let voting_keypair = Keypair::new(); let voting_keypair = Keypair::new();
let storage_keypair = Arc::new(Keypair::new()); let storage_keypair = Arc::new(Keypair::new());
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank)); let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default())); let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let tvu = Tvu::new( let tvu = Tvu::new(
&voting_keypair.pubkey(), &voting_keypair.pubkey(),
Some(Arc::new(voting_keypair)), Some(Arc::new(voting_keypair)),
@ -320,10 +322,7 @@ pub mod tests {
&StorageState::default(), &StorageState::default(),
None, None,
l_receiver, l_receiver,
&Arc::new(RpcSubscriptions::new( &Arc::new(RpcSubscriptions::new(&exit, block_commitment_cache.clone())),
&exit,
Arc::new(RwLock::new(BlockCommitmentCache::default())),
)),
&poh_recorder, &poh_recorder,
&leader_schedule_cache, &leader_schedule_cache,
&exit, &exit,

View File

@ -202,7 +202,6 @@ impl Validator {
} }
let bank_forks = Arc::new(RwLock::new(bank_forks)); let bank_forks = Arc::new(RwLock::new(bank_forks));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
let mut validator_exit = ValidatorExit::default(); let mut validator_exit = ValidatorExit::default();
let exit_ = exit.clone(); let exit_ = exit.clone();
@ -238,6 +237,9 @@ impl Validator {
); );
let blockstore = Arc::new(blockstore); let blockstore = Arc::new(blockstore);
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let subscriptions = Arc::new(RpcSubscriptions::new(&exit, block_commitment_cache.clone())); let subscriptions = Arc::new(RpcSubscriptions::new(&exit, block_commitment_cache.clone()));

View File

@ -137,7 +137,7 @@ mod tests {
// and to allow snapshotting of bank and the purging logic on status_cache to // and to allow snapshotting of bank and the purging logic on status_cache to
// kick in // kick in
if slot % set_root_interval == 0 || slot == last_slot - 1 { if slot % set_root_interval == 0 || slot == last_slot - 1 {
bank_forks.set_root(bank.slot(), &sender); bank_forks.set_root(bank.slot(), &sender, None);
} }
} }
// Generate a snapshot package for last bank // Generate a snapshot package for last bank
@ -377,9 +377,11 @@ mod tests {
snapshot_test_config.bank_forks.insert(new_bank); snapshot_test_config.bank_forks.insert(new_bank);
current_bank = snapshot_test_config.bank_forks[new_slot].clone(); current_bank = snapshot_test_config.bank_forks[new_slot].clone();
} }
snapshot_test_config snapshot_test_config.bank_forks.set_root(
.bank_forks current_bank.slot(),
.set_root(current_bank.slot(), &snapshot_sender); &snapshot_sender,
None,
);
} }
let num_old_slots = num_set_roots * *add_root_interval - MAX_CACHE_ENTRIES + 1; let num_old_slots = num_set_roots * *add_root_interval - MAX_CACHE_ENTRIES + 1;

View File

@ -6,6 +6,7 @@ use solana_core::{
commitment::BlockCommitmentCache, rpc_pubsub_service::PubSubService, commitment::BlockCommitmentCache, rpc_pubsub_service::PubSubService,
rpc_subscriptions::RpcSubscriptions, validator::TestValidator, rpc_subscriptions::RpcSubscriptions, validator::TestValidator,
}; };
use solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path};
use solana_sdk::{ use solana_sdk::{
commitment_config::CommitmentConfig, pubkey::Pubkey, rpc_port, signature::Signer, commitment_config::CommitmentConfig, pubkey::Pubkey, rpc_port, signature::Signer,
system_transaction, system_transaction,
@ -85,9 +86,13 @@ fn test_slot_subscription() {
rpc_port::DEFAULT_RPC_PUBSUB_PORT, rpc_port::DEFAULT_RPC_PUBSUB_PORT,
); );
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let ledger_path = get_tmp_ledger_path!();
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let subscriptions = Arc::new(RpcSubscriptions::new( let subscriptions = Arc::new(RpcSubscriptions::new(
&exit, &exit,
Arc::new(RwLock::new(BlockCommitmentCache::default())), Arc::new(RwLock::new(BlockCommitmentCache::default_with_blockstore(
blockstore,
))),
)); ));
let pubsub_service = PubSubService::new(&subscriptions, pubsub_addr, &exit); let pubsub_service = PubSubService::new(&subscriptions, pubsub_addr, &exit);
std::thread::sleep(Duration::from_millis(400)); std::thread::sleep(Duration::from_millis(400));

View File

@ -59,7 +59,9 @@ mod tests {
&[bank.clone()], &[bank.clone()],
vec![0], vec![0],
))); )));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default())); let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let cluster_info = test_cluster_info(&keypair.pubkey()); let cluster_info = test_cluster_info(&keypair.pubkey());
let (bank_sender, bank_receiver) = channel(); let (bank_sender, bank_receiver) = channel();
@ -180,7 +182,9 @@ mod tests {
&[bank.clone()], &[bank.clone()],
vec![0], vec![0],
))); )));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default())); let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let cluster_info = test_cluster_info(&keypair.pubkey()); let cluster_info = test_cluster_info(&keypair.pubkey());
let (bank_sender, bank_receiver) = channel(); let (bank_sender, bank_receiver) = channel();

View File

@ -165,6 +165,7 @@ impl BankForks {
&mut self, &mut self,
root: Slot, root: Slot,
snapshot_package_sender: &Option<SnapshotPackageSender>, snapshot_package_sender: &Option<SnapshotPackageSender>,
largest_confirmed_root: Option<Slot>,
) { ) {
self.root = root; self.root = root;
let set_root_start = Instant::now(); let set_root_start = Instant::now();
@ -205,7 +206,7 @@ impl BankForks {
} }
} }
self.prune_non_root(root); self.prune_non_root(root, largest_confirmed_root);
inc_new_counter_info!( inc_new_counter_info!(
"bank-forks_set_root_ms", "bank-forks_set_root_ms",
@ -276,10 +277,19 @@ impl BankForks {
Ok(()) Ok(())
} }
fn prune_non_root(&mut self, root: Slot) { fn prune_non_root(&mut self, root: Slot, largest_confirmed_root: Option<Slot>) {
let descendants = self.descendants(); let descendants = self.descendants();
self.banks self.banks.retain(|slot, _| {
.retain(|slot, _| slot == &root || descendants[&root].contains(slot)); *slot == root
|| descendants[&root].contains(slot)
|| (*slot < root
&& *slot >= largest_confirmed_root.unwrap_or(root)
&& descendants[slot].contains(&root))
});
datapoint_debug!(
"bank_forks_purge_non_root",
("num_banks_retained", self.banks.len(), i64),
);
} }
pub fn set_snapshot_config(&mut self, snapshot_config: Option<SnapshotConfig>) { pub fn set_snapshot_config(&mut self, snapshot_config: Option<SnapshotConfig>) {