Replace get_tmp_ledger_path!() with self cleaning version (#33702)
This macro is used a lot for tests to create a ledger path in order to open a Blockstore. Files will be left on disk unless the test remembers to call Blockstore::destroy() on the directory. So, instead of requiring this, use the get_tmp_ledger_path_auto_delete!() macro that creates a TempDir (which automatically deletes itself when it goes out of scope).
This commit is contained in:
parent
5a963529a8
commit
56ccffdaa5
|
@ -14,7 +14,7 @@ use {
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
blockstore::Blockstore,
|
blockstore::Blockstore,
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
leader_schedule_cache::LeaderScheduleCache,
|
leader_schedule_cache::LeaderScheduleCache,
|
||||||
},
|
},
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
|
@ -410,216 +410,212 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Arc::new(
|
||||||
let blockstore = Arc::new(
|
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger"),
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
);
|
||||||
);
|
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
||||||
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
let (exit, poh_recorder, poh_service, signal_receiver) = create_test_recorder(
|
||||||
let (exit, poh_recorder, poh_service, signal_receiver) = create_test_recorder(
|
bank.clone(),
|
||||||
bank.clone(),
|
blockstore.clone(),
|
||||||
blockstore.clone(),
|
None,
|
||||||
None,
|
Some(leader_schedule_cache),
|
||||||
Some(leader_schedule_cache),
|
);
|
||||||
);
|
let (banking_tracer, tracer_thread) =
|
||||||
let (banking_tracer, tracer_thread) =
|
BankingTracer::new(matches.is_present("trace_banking").then_some((
|
||||||
BankingTracer::new(matches.is_present("trace_banking").then_some((
|
&blockstore.banking_trace_path(),
|
||||||
&blockstore.banking_trace_path(),
|
exit.clone(),
|
||||||
exit.clone(),
|
BANKING_TRACE_DIR_DEFAULT_BYTE_LIMIT,
|
||||||
BANKING_TRACE_DIR_DEFAULT_BYTE_LIMIT,
|
)))
|
||||||
)))
|
.unwrap();
|
||||||
.unwrap();
|
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
|
||||||
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
|
let (tpu_vote_sender, tpu_vote_receiver) = banking_tracer.create_channel_tpu_vote();
|
||||||
let (tpu_vote_sender, tpu_vote_receiver) = banking_tracer.create_channel_tpu_vote();
|
let (gossip_vote_sender, gossip_vote_receiver) = banking_tracer.create_channel_gossip_vote();
|
||||||
let (gossip_vote_sender, gossip_vote_receiver) =
|
let cluster_info = {
|
||||||
banking_tracer.create_channel_gossip_vote();
|
let keypair = Arc::new(Keypair::new());
|
||||||
let cluster_info = {
|
let node = Node::new_localhost_with_pubkey(&keypair.pubkey());
|
||||||
let keypair = Arc::new(Keypair::new());
|
ClusterInfo::new(node.info, keypair, SocketAddrSpace::Unspecified)
|
||||||
let node = Node::new_localhost_with_pubkey(&keypair.pubkey());
|
};
|
||||||
ClusterInfo::new(node.info, keypair, SocketAddrSpace::Unspecified)
|
let cluster_info = Arc::new(cluster_info);
|
||||||
};
|
let tpu_disable_quic = matches.is_present("tpu_disable_quic");
|
||||||
let cluster_info = Arc::new(cluster_info);
|
let connection_cache = match tpu_disable_quic {
|
||||||
let tpu_disable_quic = matches.is_present("tpu_disable_quic");
|
false => ConnectionCache::new_quic(
|
||||||
let connection_cache = match tpu_disable_quic {
|
"connection_cache_banking_bench_quic",
|
||||||
false => ConnectionCache::new_quic(
|
DEFAULT_TPU_CONNECTION_POOL_SIZE,
|
||||||
"connection_cache_banking_bench_quic",
|
),
|
||||||
DEFAULT_TPU_CONNECTION_POOL_SIZE,
|
true => ConnectionCache::with_udp(
|
||||||
),
|
"connection_cache_banking_bench_udp",
|
||||||
true => ConnectionCache::with_udp(
|
DEFAULT_TPU_CONNECTION_POOL_SIZE,
|
||||||
"connection_cache_banking_bench_udp",
|
),
|
||||||
DEFAULT_TPU_CONNECTION_POOL_SIZE,
|
};
|
||||||
),
|
let banking_stage = BankingStage::new_thread_local_multi_iterator(
|
||||||
};
|
&cluster_info,
|
||||||
let banking_stage = BankingStage::new_thread_local_multi_iterator(
|
&poh_recorder,
|
||||||
&cluster_info,
|
non_vote_receiver,
|
||||||
&poh_recorder,
|
tpu_vote_receiver,
|
||||||
non_vote_receiver,
|
gossip_vote_receiver,
|
||||||
tpu_vote_receiver,
|
num_banking_threads,
|
||||||
gossip_vote_receiver,
|
None,
|
||||||
num_banking_threads,
|
replay_vote_sender,
|
||||||
None,
|
None,
|
||||||
replay_vote_sender,
|
Arc::new(connection_cache),
|
||||||
None,
|
bank_forks.clone(),
|
||||||
Arc::new(connection_cache),
|
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
||||||
bank_forks.clone(),
|
);
|
||||||
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
|
||||||
);
|
|
||||||
|
|
||||||
// This is so that the signal_receiver does not go out of scope after the closure.
|
// This is so that the signal_receiver does not go out of scope after the closure.
|
||||||
// If it is dropped before poh_service, then poh_service will error when
|
// If it is dropped before poh_service, then poh_service will error when
|
||||||
// calling send() on the channel.
|
// calling send() on the channel.
|
||||||
let signal_receiver = Arc::new(signal_receiver);
|
let signal_receiver = Arc::new(signal_receiver);
|
||||||
let mut total_us = 0;
|
let mut total_us = 0;
|
||||||
let mut tx_total_us = 0;
|
let mut tx_total_us = 0;
|
||||||
let base_tx_count = bank.transaction_count();
|
let base_tx_count = bank.transaction_count();
|
||||||
let mut txs_processed = 0;
|
let mut txs_processed = 0;
|
||||||
let collector = solana_sdk::pubkey::new_rand();
|
let collector = solana_sdk::pubkey::new_rand();
|
||||||
let mut total_sent = 0;
|
let mut total_sent = 0;
|
||||||
for current_iteration_index in 0..iterations {
|
for current_iteration_index in 0..iterations {
|
||||||
trace!("RUNNING ITERATION {}", current_iteration_index);
|
trace!("RUNNING ITERATION {}", current_iteration_index);
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let mut sent = 0;
|
let mut sent = 0;
|
||||||
|
|
||||||
let packets_for_this_iteration = &all_packets[current_iteration_index % num_chunks];
|
let packets_for_this_iteration = &all_packets[current_iteration_index % num_chunks];
|
||||||
for (packet_batch_index, packet_batch) in
|
for (packet_batch_index, packet_batch) in
|
||||||
packets_for_this_iteration.packet_batches.iter().enumerate()
|
packets_for_this_iteration.packet_batches.iter().enumerate()
|
||||||
{
|
{
|
||||||
sent += packet_batch.len();
|
sent += packet_batch.len();
|
||||||
trace!(
|
trace!(
|
||||||
"Sending PacketBatch index {}, {}",
|
"Sending PacketBatch index {}, {}",
|
||||||
packet_batch_index,
|
packet_batch_index,
|
||||||
timestamp(),
|
timestamp(),
|
||||||
);
|
);
|
||||||
non_vote_sender
|
non_vote_sender
|
||||||
.send(BankingPacketBatch::new((vec![packet_batch.clone()], None)))
|
.send(BankingPacketBatch::new((vec![packet_batch.clone()], None)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for tx in &packets_for_this_iteration.transactions {
|
for tx in &packets_for_this_iteration.transactions {
|
||||||
loop {
|
loop {
|
||||||
if bank.get_signature_status(&tx.signatures[0]).is_some() {
|
if bank.get_signature_status(&tx.signatures[0]).is_some() {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if poh_recorder.read().unwrap().bank().is_none() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sleep(Duration::from_millis(5));
|
|
||||||
}
|
}
|
||||||
}
|
if poh_recorder.read().unwrap().bank().is_none() {
|
||||||
|
break;
|
||||||
// check if txs had been processed by bank. Returns when all transactions are
|
|
||||||
// processed, with `FALSE` indicate there is still bank. or returns TRUE indicate a
|
|
||||||
// bank has expired before receiving all txs.
|
|
||||||
if check_txs(
|
|
||||||
&signal_receiver,
|
|
||||||
packets_for_this_iteration.transactions.len(),
|
|
||||||
&poh_recorder,
|
|
||||||
) {
|
|
||||||
eprintln!(
|
|
||||||
"[iteration {}, tx sent {}, slot {} expired, bank tx count {}]",
|
|
||||||
current_iteration_index,
|
|
||||||
sent,
|
|
||||||
bank.slot(),
|
|
||||||
bank.transaction_count(),
|
|
||||||
);
|
|
||||||
tx_total_us += duration_as_us(&now.elapsed());
|
|
||||||
|
|
||||||
let mut poh_time = Measure::start("poh_time");
|
|
||||||
poh_recorder
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.reset(bank.clone(), Some((bank.slot(), bank.slot() + 1)));
|
|
||||||
poh_time.stop();
|
|
||||||
|
|
||||||
let mut new_bank_time = Measure::start("new_bank");
|
|
||||||
let new_slot = bank.slot() + 1;
|
|
||||||
let new_bank = Bank::new_from_parent(bank, &collector, new_slot);
|
|
||||||
new_bank_time.stop();
|
|
||||||
|
|
||||||
let mut insert_time = Measure::start("insert_time");
|
|
||||||
bank_forks.write().unwrap().insert(new_bank);
|
|
||||||
bank = bank_forks.read().unwrap().working_bank();
|
|
||||||
insert_time.stop();
|
|
||||||
|
|
||||||
// set cost tracker limits to MAX so it will not filter out TXs
|
|
||||||
bank.write_cost_tracker().unwrap().set_limits(
|
|
||||||
std::u64::MAX,
|
|
||||||
std::u64::MAX,
|
|
||||||
std::u64::MAX,
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(poh_recorder.read().unwrap().bank().is_none());
|
|
||||||
poh_recorder
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.set_bank_for_test(bank.clone());
|
|
||||||
assert!(poh_recorder.read().unwrap().bank().is_some());
|
|
||||||
debug!(
|
|
||||||
"new_bank_time: {}us insert_time: {}us poh_time: {}us",
|
|
||||||
new_bank_time.as_us(),
|
|
||||||
insert_time.as_us(),
|
|
||||||
poh_time.as_us(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
eprintln!(
|
|
||||||
"[iteration {}, tx sent {}, slot {} active, bank tx count {}]",
|
|
||||||
current_iteration_index,
|
|
||||||
sent,
|
|
||||||
bank.slot(),
|
|
||||||
bank.transaction_count(),
|
|
||||||
);
|
|
||||||
tx_total_us += duration_as_us(&now.elapsed());
|
|
||||||
}
|
|
||||||
|
|
||||||
// This signature clear may not actually clear the signatures
|
|
||||||
// in this chunk, but since we rotate between CHUNKS then
|
|
||||||
// we should clear them by the time we come around again to re-use that chunk.
|
|
||||||
bank.clear_signatures();
|
|
||||||
total_us += duration_as_us(&now.elapsed());
|
|
||||||
total_sent += sent;
|
|
||||||
|
|
||||||
if current_iteration_index % num_chunks == 0 {
|
|
||||||
let last_blockhash = bank.last_blockhash();
|
|
||||||
for packets_for_single_iteration in all_packets.iter_mut() {
|
|
||||||
packets_for_single_iteration.refresh_blockhash(last_blockhash);
|
|
||||||
}
|
}
|
||||||
|
sleep(Duration::from_millis(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
txs_processed += bank_forks
|
|
||||||
.read()
|
|
||||||
.unwrap()
|
|
||||||
.working_bank()
|
|
||||||
.transaction_count();
|
|
||||||
debug!("processed: {} base: {}", txs_processed, base_tx_count);
|
|
||||||
|
|
||||||
eprintln!("[total_sent: {}, base_tx_count: {}, txs_processed: {}, txs_landed: {}, total_us: {}, tx_total_us: {}]",
|
// check if txs had been processed by bank. Returns when all transactions are
|
||||||
total_sent, base_tx_count, txs_processed, (txs_processed - base_tx_count), total_us, tx_total_us);
|
// processed, with `FALSE` indicate there is still bank. or returns TRUE indicate a
|
||||||
|
// bank has expired before receiving all txs.
|
||||||
|
if check_txs(
|
||||||
|
&signal_receiver,
|
||||||
|
packets_for_this_iteration.transactions.len(),
|
||||||
|
&poh_recorder,
|
||||||
|
) {
|
||||||
|
eprintln!(
|
||||||
|
"[iteration {}, tx sent {}, slot {} expired, bank tx count {}]",
|
||||||
|
current_iteration_index,
|
||||||
|
sent,
|
||||||
|
bank.slot(),
|
||||||
|
bank.transaction_count(),
|
||||||
|
);
|
||||||
|
tx_total_us += duration_as_us(&now.elapsed());
|
||||||
|
|
||||||
eprintln!(
|
let mut poh_time = Measure::start("poh_time");
|
||||||
"{{'name': 'banking_bench_total', 'median': '{:.2}'}}",
|
poh_recorder
|
||||||
(1000.0 * 1000.0 * total_sent as f64) / (total_us as f64),
|
.write()
|
||||||
);
|
.unwrap()
|
||||||
eprintln!(
|
.reset(bank.clone(), Some((bank.slot(), bank.slot() + 1)));
|
||||||
"{{'name': 'banking_bench_tx_total', 'median': '{:.2}'}}",
|
poh_time.stop();
|
||||||
(1000.0 * 1000.0 * total_sent as f64) / (tx_total_us as f64),
|
|
||||||
);
|
|
||||||
eprintln!(
|
|
||||||
"{{'name': 'banking_bench_success_tx_total', 'median': '{:.2}'}}",
|
|
||||||
(1000.0 * 1000.0 * (txs_processed - base_tx_count) as f64) / (total_us as f64),
|
|
||||||
);
|
|
||||||
|
|
||||||
drop(non_vote_sender);
|
let mut new_bank_time = Measure::start("new_bank");
|
||||||
drop(tpu_vote_sender);
|
let new_slot = bank.slot() + 1;
|
||||||
drop(gossip_vote_sender);
|
let new_bank = Bank::new_from_parent(bank, &collector, new_slot);
|
||||||
exit.store(true, Ordering::Relaxed);
|
new_bank_time.stop();
|
||||||
banking_stage.join().unwrap();
|
|
||||||
debug!("waited for banking_stage");
|
let mut insert_time = Measure::start("insert_time");
|
||||||
poh_service.join().unwrap();
|
bank_forks.write().unwrap().insert(new_bank);
|
||||||
sleep(Duration::from_secs(1));
|
bank = bank_forks.read().unwrap().working_bank();
|
||||||
debug!("waited for poh_service");
|
insert_time.stop();
|
||||||
if let Some(tracer_thread) = tracer_thread {
|
|
||||||
tracer_thread.join().unwrap().unwrap();
|
// set cost tracker limits to MAX so it will not filter out TXs
|
||||||
|
bank.write_cost_tracker().unwrap().set_limits(
|
||||||
|
std::u64::MAX,
|
||||||
|
std::u64::MAX,
|
||||||
|
std::u64::MAX,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(poh_recorder.read().unwrap().bank().is_none());
|
||||||
|
poh_recorder
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.set_bank_for_test(bank.clone());
|
||||||
|
assert!(poh_recorder.read().unwrap().bank().is_some());
|
||||||
|
debug!(
|
||||||
|
"new_bank_time: {}us insert_time: {}us poh_time: {}us",
|
||||||
|
new_bank_time.as_us(),
|
||||||
|
insert_time.as_us(),
|
||||||
|
poh_time.as_us(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"[iteration {}, tx sent {}, slot {} active, bank tx count {}]",
|
||||||
|
current_iteration_index,
|
||||||
|
sent,
|
||||||
|
bank.slot(),
|
||||||
|
bank.transaction_count(),
|
||||||
|
);
|
||||||
|
tx_total_us += duration_as_us(&now.elapsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This signature clear may not actually clear the signatures
|
||||||
|
// in this chunk, but since we rotate between CHUNKS then
|
||||||
|
// we should clear them by the time we come around again to re-use that chunk.
|
||||||
|
bank.clear_signatures();
|
||||||
|
total_us += duration_as_us(&now.elapsed());
|
||||||
|
total_sent += sent;
|
||||||
|
|
||||||
|
if current_iteration_index % num_chunks == 0 {
|
||||||
|
let last_blockhash = bank.last_blockhash();
|
||||||
|
for packets_for_single_iteration in all_packets.iter_mut() {
|
||||||
|
packets_for_single_iteration.refresh_blockhash(last_blockhash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _unused = Blockstore::destroy(&ledger_path);
|
txs_processed += bank_forks
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.working_bank()
|
||||||
|
.transaction_count();
|
||||||
|
debug!("processed: {} base: {}", txs_processed, base_tx_count);
|
||||||
|
|
||||||
|
eprintln!("[total_sent: {}, base_tx_count: {}, txs_processed: {}, txs_landed: {}, total_us: {}, tx_total_us: {}]",
|
||||||
|
total_sent, base_tx_count, txs_processed, (txs_processed - base_tx_count), total_us, tx_total_us);
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"{{'name': 'banking_bench_total', 'median': '{:.2}'}}",
|
||||||
|
(1000.0 * 1000.0 * total_sent as f64) / (total_us as f64),
|
||||||
|
);
|
||||||
|
eprintln!(
|
||||||
|
"{{'name': 'banking_bench_tx_total', 'median': '{:.2}'}}",
|
||||||
|
(1000.0 * 1000.0 * total_sent as f64) / (tx_total_us as f64),
|
||||||
|
);
|
||||||
|
eprintln!(
|
||||||
|
"{{'name': 'banking_bench_success_tx_total', 'median': '{:.2}'}}",
|
||||||
|
(1000.0 * 1000.0 * (txs_processed - base_tx_count) as f64) / (total_us as f64),
|
||||||
|
);
|
||||||
|
|
||||||
|
drop(non_vote_sender);
|
||||||
|
drop(tpu_vote_sender);
|
||||||
|
drop(gossip_vote_sender);
|
||||||
|
exit.store(true, Ordering::Relaxed);
|
||||||
|
banking_stage.join().unwrap();
|
||||||
|
debug!("waited for banking_stage");
|
||||||
|
poh_service.join().unwrap();
|
||||||
|
sleep(Duration::from_secs(1));
|
||||||
|
debug!("waited for poh_service");
|
||||||
|
if let Some(tracer_thread) = tracer_thread {
|
||||||
|
tracer_thread.join().unwrap().unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use {
|
||||||
futures_util::StreamExt,
|
futures_util::StreamExt,
|
||||||
rand::Rng,
|
rand::Rng,
|
||||||
serde_json::{json, Value},
|
serde_json::{json, Value},
|
||||||
solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path},
|
solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path_auto_delete},
|
||||||
solana_pubsub_client::{nonblocking, pubsub_client::PubsubClient},
|
solana_pubsub_client::{nonblocking, pubsub_client::PubsubClient},
|
||||||
solana_rpc::{
|
solana_rpc::{
|
||||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||||
|
@ -233,8 +233,8 @@ fn test_block_subscription() {
|
||||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||||
|
|
||||||
// setup Blockstore
|
// setup Blockstore
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Blockstore::open(&ledger_path).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Arc::new(blockstore);
|
let blockstore = Arc::new(blockstore);
|
||||||
|
|
||||||
// populate ledger with test txs
|
// populate ledger with test txs
|
||||||
|
|
|
@ -29,7 +29,7 @@ use {
|
||||||
blockstore::Blockstore,
|
blockstore::Blockstore,
|
||||||
blockstore_processor::process_entries_for_tests,
|
blockstore_processor::process_entries_for_tests,
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
},
|
},
|
||||||
solana_perf::{
|
solana_perf::{
|
||||||
packet::{to_packet_batches, Packet},
|
packet::{to_packet_batches, Packet},
|
||||||
|
@ -83,49 +83,46 @@ fn check_txs(receiver: &Arc<Receiver<WorkingBankEntry>>, ref_tx_count: usize) {
|
||||||
fn bench_consume_buffered(bencher: &mut Bencher) {
|
fn bench_consume_buffered(bencher: &mut Bencher) {
|
||||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100_000);
|
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100_000);
|
||||||
let bank = Arc::new(Bank::new_for_benches(&genesis_config));
|
let bank = Arc::new(Bank::new_for_benches(&genesis_config));
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Arc::new(
|
||||||
let blockstore = Arc::new(
|
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger"),
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
);
|
||||||
|
let (exit, poh_recorder, poh_service, _signal_receiver) =
|
||||||
|
create_test_recorder(bank, blockstore, None, None);
|
||||||
|
|
||||||
|
let recorder = poh_recorder.read().unwrap().new_recorder();
|
||||||
|
let bank_start = poh_recorder.read().unwrap().bank_start().unwrap();
|
||||||
|
|
||||||
|
let tx = test_tx();
|
||||||
|
let transactions = vec![tx; 4194304];
|
||||||
|
let batches = transactions
|
||||||
|
.iter()
|
||||||
|
.filter_map(|transaction| {
|
||||||
|
let packet = Packet::from_data(None, transaction).ok().unwrap();
|
||||||
|
DeserializedPacket::new(packet).ok()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let batches_len = batches.len();
|
||||||
|
let mut transaction_buffer = UnprocessedTransactionStorage::new_transaction_storage(
|
||||||
|
UnprocessedPacketBatches::from_iter(batches, 2 * batches_len),
|
||||||
|
ThreadType::Transactions,
|
||||||
|
);
|
||||||
|
let (s, _r) = unbounded();
|
||||||
|
let committer = Committer::new(None, s, Arc::new(PrioritizationFeeCache::new(0u64)));
|
||||||
|
let consumer = Consumer::new(committer, recorder, QosService::new(1), None);
|
||||||
|
// This tests the performance of buffering packets.
|
||||||
|
// If the packet buffers are copied, performance will be poor.
|
||||||
|
bencher.iter(move || {
|
||||||
|
consumer.consume_buffered_packets(
|
||||||
|
&bank_start,
|
||||||
|
&mut transaction_buffer,
|
||||||
|
&BankingStageStats::default(),
|
||||||
|
&mut LeaderSlotMetricsTracker::new(0),
|
||||||
);
|
);
|
||||||
let (exit, poh_recorder, poh_service, _signal_receiver) =
|
});
|
||||||
create_test_recorder(bank, blockstore, None, None);
|
|
||||||
|
|
||||||
let recorder = poh_recorder.read().unwrap().new_recorder();
|
exit.store(true, Ordering::Relaxed);
|
||||||
let bank_start = poh_recorder.read().unwrap().bank_start().unwrap();
|
poh_service.join().unwrap();
|
||||||
|
|
||||||
let tx = test_tx();
|
|
||||||
let transactions = vec![tx; 4194304];
|
|
||||||
let batches = transactions
|
|
||||||
.iter()
|
|
||||||
.filter_map(|transaction| {
|
|
||||||
let packet = Packet::from_data(None, transaction).ok().unwrap();
|
|
||||||
DeserializedPacket::new(packet).ok()
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let batches_len = batches.len();
|
|
||||||
let mut transaction_buffer = UnprocessedTransactionStorage::new_transaction_storage(
|
|
||||||
UnprocessedPacketBatches::from_iter(batches, 2 * batches_len),
|
|
||||||
ThreadType::Transactions,
|
|
||||||
);
|
|
||||||
let (s, _r) = unbounded();
|
|
||||||
let committer = Committer::new(None, s, Arc::new(PrioritizationFeeCache::new(0u64)));
|
|
||||||
let consumer = Consumer::new(committer, recorder, QosService::new(1), None);
|
|
||||||
// This tests the performance of buffering packets.
|
|
||||||
// If the packet buffers are copied, performance will be poor.
|
|
||||||
bencher.iter(move || {
|
|
||||||
consumer.consume_buffered_packets(
|
|
||||||
&bank_start,
|
|
||||||
&mut transaction_buffer,
|
|
||||||
&BankingStageStats::default(),
|
|
||||||
&mut LeaderSlotMetricsTracker::new(0),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
exit.store(true, Ordering::Relaxed);
|
|
||||||
poh_service.join().unwrap();
|
|
||||||
}
|
|
||||||
let _unused = Blockstore::destroy(&ledger_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec<Transaction> {
|
fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec<Transaction> {
|
||||||
|
@ -279,95 +276,92 @@ fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) {
|
||||||
packet_batches
|
packet_batches
|
||||||
});
|
});
|
||||||
|
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Arc::new(
|
||||||
let blockstore = Arc::new(
|
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger"),
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
);
|
||||||
);
|
let (exit, poh_recorder, poh_service, signal_receiver) =
|
||||||
let (exit, poh_recorder, poh_service, signal_receiver) =
|
create_test_recorder(bank.clone(), blockstore, None, None);
|
||||||
create_test_recorder(bank.clone(), blockstore, None, None);
|
let cluster_info = {
|
||||||
let cluster_info = {
|
let keypair = Arc::new(Keypair::new());
|
||||||
let keypair = Arc::new(Keypair::new());
|
let node = Node::new_localhost_with_pubkey(&keypair.pubkey());
|
||||||
let node = Node::new_localhost_with_pubkey(&keypair.pubkey());
|
ClusterInfo::new(node.info, keypair, SocketAddrSpace::Unspecified)
|
||||||
ClusterInfo::new(node.info, keypair, SocketAddrSpace::Unspecified)
|
};
|
||||||
};
|
let cluster_info = Arc::new(cluster_info);
|
||||||
let cluster_info = Arc::new(cluster_info);
|
let (s, _r) = unbounded();
|
||||||
let (s, _r) = unbounded();
|
let _banking_stage = BankingStage::new(
|
||||||
let _banking_stage = BankingStage::new(
|
BlockProductionMethod::ThreadLocalMultiIterator,
|
||||||
BlockProductionMethod::ThreadLocalMultiIterator,
|
&cluster_info,
|
||||||
&cluster_info,
|
&poh_recorder,
|
||||||
&poh_recorder,
|
non_vote_receiver,
|
||||||
non_vote_receiver,
|
tpu_vote_receiver,
|
||||||
tpu_vote_receiver,
|
gossip_vote_receiver,
|
||||||
gossip_vote_receiver,
|
None,
|
||||||
None,
|
s,
|
||||||
s,
|
None,
|
||||||
None,
|
Arc::new(ConnectionCache::new("connection_cache_test")),
|
||||||
Arc::new(ConnectionCache::new("connection_cache_test")),
|
bank_forks,
|
||||||
bank_forks,
|
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
||||||
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
let chunk_len = verified.len() / CHUNKS;
|
let chunk_len = verified.len() / CHUNKS;
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
|
|
||||||
// This is so that the signal_receiver does not go out of scope after the closure.
|
// This is so that the signal_receiver does not go out of scope after the closure.
|
||||||
// If it is dropped before poh_service, then poh_service will error when
|
// If it is dropped before poh_service, then poh_service will error when
|
||||||
// calling send() on the channel.
|
// calling send() on the channel.
|
||||||
let signal_receiver = Arc::new(signal_receiver);
|
let signal_receiver = Arc::new(signal_receiver);
|
||||||
let signal_receiver2 = signal_receiver;
|
let signal_receiver2 = signal_receiver;
|
||||||
bencher.iter(move || {
|
bencher.iter(move || {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let mut sent = 0;
|
let mut sent = 0;
|
||||||
if let Some(vote_packets) = &vote_packets {
|
if let Some(vote_packets) = &vote_packets {
|
||||||
tpu_vote_sender
|
tpu_vote_sender
|
||||||
.send(BankingPacketBatch::new((
|
.send(BankingPacketBatch::new((
|
||||||
vote_packets[start..start + chunk_len].to_vec(),
|
vote_packets[start..start + chunk_len].to_vec(),
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
gossip_vote_sender
|
gossip_vote_sender
|
||||||
.send(BankingPacketBatch::new((
|
.send(BankingPacketBatch::new((
|
||||||
vote_packets[start..start + chunk_len].to_vec(),
|
vote_packets[start..start + chunk_len].to_vec(),
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
for v in verified[start..start + chunk_len].chunks(chunk_len / num_threads) {
|
for v in verified[start..start + chunk_len].chunks(chunk_len / num_threads) {
|
||||||
debug!(
|
debug!(
|
||||||
"sending... {}..{} {} v.len: {}",
|
"sending... {}..{} {} v.len: {}",
|
||||||
start,
|
start,
|
||||||
start + chunk_len,
|
start + chunk_len,
|
||||||
timestamp(),
|
timestamp(),
|
||||||
v.len(),
|
v.len(),
|
||||||
);
|
|
||||||
for xv in v {
|
|
||||||
sent += xv.len();
|
|
||||||
}
|
|
||||||
non_vote_sender
|
|
||||||
.send(BankingPacketBatch::new((v.to_vec(), None)))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
check_txs(&signal_receiver2, txes / CHUNKS);
|
|
||||||
|
|
||||||
// This signature clear may not actually clear the signatures
|
|
||||||
// in this chunk, but since we rotate between CHUNKS then
|
|
||||||
// we should clear them by the time we come around again to re-use that chunk.
|
|
||||||
bank.clear_signatures();
|
|
||||||
trace!(
|
|
||||||
"time: {} checked: {} sent: {}",
|
|
||||||
duration_as_us(&now.elapsed()),
|
|
||||||
txes / CHUNKS,
|
|
||||||
sent,
|
|
||||||
);
|
);
|
||||||
start += chunk_len;
|
for xv in v {
|
||||||
start %= verified.len();
|
sent += xv.len();
|
||||||
});
|
}
|
||||||
exit.store(true, Ordering::Relaxed);
|
non_vote_sender
|
||||||
poh_service.join().unwrap();
|
.send(BankingPacketBatch::new((v.to_vec(), None)))
|
||||||
}
|
.unwrap();
|
||||||
let _unused = Blockstore::destroy(&ledger_path);
|
}
|
||||||
|
|
||||||
|
check_txs(&signal_receiver2, txes / CHUNKS);
|
||||||
|
|
||||||
|
// This signature clear may not actually clear the signatures
|
||||||
|
// in this chunk, but since we rotate between CHUNKS then
|
||||||
|
// we should clear them by the time we come around again to re-use that chunk.
|
||||||
|
bank.clear_signatures();
|
||||||
|
trace!(
|
||||||
|
"time: {} checked: {} sent: {}",
|
||||||
|
duration_as_us(&now.elapsed()),
|
||||||
|
txes / CHUNKS,
|
||||||
|
sent,
|
||||||
|
);
|
||||||
|
start += chunk_len;
|
||||||
|
start %= verified.len();
|
||||||
|
});
|
||||||
|
exit.store(true, Ordering::Relaxed);
|
||||||
|
poh_service.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
|
|
|
@ -1518,7 +1518,7 @@ pub mod test {
|
||||||
vote_simulator::VoteSimulator,
|
vote_simulator::VoteSimulator,
|
||||||
},
|
},
|
||||||
itertools::Itertools,
|
itertools::Itertools,
|
||||||
solana_ledger::{blockstore::make_slot_entries, get_tmp_ledger_path},
|
solana_ledger::{blockstore::make_slot_entries, get_tmp_ledger_path_auto_delete},
|
||||||
solana_runtime::bank::Bank,
|
solana_runtime::bank::Bank,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
|
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
|
||||||
|
@ -2928,36 +2928,33 @@ pub mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reconcile_blockstore_roots_with_tower_normal() {
|
fn test_reconcile_blockstore_roots_with_tower_normal() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let (shreds, _) = make_slot_entries(1, 0, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(1, 0, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
let (shreds, _) = make_slot_entries(3, 1, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(3, 1, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
let (shreds, _) = make_slot_entries(4, 1, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(4, 1, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
assert!(!blockstore.is_root(0));
|
assert!(!blockstore.is_root(0));
|
||||||
assert!(!blockstore.is_root(1));
|
assert!(!blockstore.is_root(1));
|
||||||
assert!(!blockstore.is_root(3));
|
assert!(!blockstore.is_root(3));
|
||||||
assert!(!blockstore.is_root(4));
|
assert!(!blockstore.is_root(4));
|
||||||
|
|
||||||
let mut tower = Tower::default();
|
let mut tower = Tower::default();
|
||||||
tower.vote_state.root_slot = Some(4);
|
tower.vote_state.root_slot = Some(4);
|
||||||
reconcile_blockstore_roots_with_external_source(
|
reconcile_blockstore_roots_with_external_source(
|
||||||
ExternalRootSource::Tower(tower.root()),
|
ExternalRootSource::Tower(tower.root()),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
&mut blockstore.last_root(),
|
&mut blockstore.last_root(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(!blockstore.is_root(0));
|
assert!(!blockstore.is_root(0));
|
||||||
assert!(blockstore.is_root(1));
|
assert!(blockstore.is_root(1));
|
||||||
assert!(!blockstore.is_root(3));
|
assert!(!blockstore.is_root(3));
|
||||||
assert!(blockstore.is_root(4));
|
assert!(blockstore.is_root(4));
|
||||||
}
|
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2966,61 +2963,55 @@ pub mod test {
|
||||||
external root (Tower(4))!?")]
|
external root (Tower(4))!?")]
|
||||||
fn test_reconcile_blockstore_roots_with_tower_panic_no_common_root() {
|
fn test_reconcile_blockstore_roots_with_tower_panic_no_common_root() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let (shreds, _) = make_slot_entries(1, 0, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(1, 0, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
let (shreds, _) = make_slot_entries(3, 1, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(3, 1, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
let (shreds, _) = make_slot_entries(4, 1, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(4, 1, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
blockstore.set_roots(std::iter::once(&3)).unwrap();
|
blockstore.set_roots(std::iter::once(&3)).unwrap();
|
||||||
assert!(!blockstore.is_root(0));
|
assert!(!blockstore.is_root(0));
|
||||||
assert!(!blockstore.is_root(1));
|
assert!(!blockstore.is_root(1));
|
||||||
assert!(blockstore.is_root(3));
|
assert!(blockstore.is_root(3));
|
||||||
assert!(!blockstore.is_root(4));
|
assert!(!blockstore.is_root(4));
|
||||||
|
|
||||||
let mut tower = Tower::default();
|
let mut tower = Tower::default();
|
||||||
tower.vote_state.root_slot = Some(4);
|
tower.vote_state.root_slot = Some(4);
|
||||||
reconcile_blockstore_roots_with_external_source(
|
reconcile_blockstore_roots_with_external_source(
|
||||||
ExternalRootSource::Tower(tower.root()),
|
ExternalRootSource::Tower(tower.root()),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
&mut blockstore.last_root(),
|
&mut blockstore.last_root(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reconcile_blockstore_roots_with_tower_nop_no_parent() {
|
fn test_reconcile_blockstore_roots_with_tower_nop_no_parent() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let (shreds, _) = make_slot_entries(1, 0, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(1, 0, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
let (shreds, _) = make_slot_entries(3, 1, 42, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(3, 1, 42, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
assert!(!blockstore.is_root(0));
|
assert!(!blockstore.is_root(0));
|
||||||
assert!(!blockstore.is_root(1));
|
assert!(!blockstore.is_root(1));
|
||||||
assert!(!blockstore.is_root(3));
|
assert!(!blockstore.is_root(3));
|
||||||
|
|
||||||
let mut tower = Tower::default();
|
let mut tower = Tower::default();
|
||||||
tower.vote_state.root_slot = Some(4);
|
tower.vote_state.root_slot = Some(4);
|
||||||
assert_eq!(blockstore.last_root(), 0);
|
assert_eq!(blockstore.last_root(), 0);
|
||||||
reconcile_blockstore_roots_with_external_source(
|
reconcile_blockstore_roots_with_external_source(
|
||||||
ExternalRootSource::Tower(tower.root()),
|
ExternalRootSource::Tower(tower.root()),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
&mut blockstore.last_root(),
|
&mut blockstore.last_root(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(blockstore.last_root(), 0);
|
assert_eq!(blockstore.last_root(), 0);
|
||||||
}
|
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -918,7 +918,10 @@ mod test {
|
||||||
cluster_info::{ClusterInfo, Node},
|
cluster_info::{ClusterInfo, Node},
|
||||||
contact_info::{ContactInfo, Protocol},
|
contact_info::{ContactInfo, Protocol},
|
||||||
},
|
},
|
||||||
solana_ledger::{blockstore::make_many_slot_entries, get_tmp_ledger_path, shred::Nonce},
|
solana_ledger::{
|
||||||
|
blockstore::make_many_slot_entries, get_tmp_ledger_path,
|
||||||
|
get_tmp_ledger_path_auto_delete, shred::Nonce,
|
||||||
|
},
|
||||||
solana_runtime::{accounts_background_service::AbsRequestSender, bank_forks::BankForks},
|
solana_runtime::{accounts_background_service::AbsRequestSender, bank_forks::BankForks},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
@ -1938,8 +1941,8 @@ mod test {
|
||||||
..
|
..
|
||||||
} = ManageAncestorHashesState::new(bank_forks);
|
} = ManageAncestorHashesState::new(bank_forks);
|
||||||
|
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Blockstore::open(&ledger_path).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
|
|
||||||
// Create invalid packet with fewer bytes than the size of the nonce
|
// Create invalid packet with fewer bytes than the size of the nonce
|
||||||
let mut packet = Packet::default();
|
let mut packet = Packet::default();
|
||||||
|
|
|
@ -864,7 +864,7 @@ mod test {
|
||||||
make_chaining_slot_entries, make_many_slot_entries, make_slot_entries, Blockstore,
|
make_chaining_slot_entries, make_many_slot_entries, make_slot_entries, Blockstore,
|
||||||
},
|
},
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
shred::max_ticks_per_n_shreds,
|
shred::max_ticks_per_n_shreds,
|
||||||
},
|
},
|
||||||
solana_runtime::bank::Bank,
|
solana_runtime::bank::Bank,
|
||||||
|
@ -884,289 +884,270 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_repair_orphan() {
|
pub fn test_repair_orphan() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
// Create some orphan slots
|
// Create some orphan slots
|
||||||
let (mut shreds, _) = make_slot_entries(1, 0, 1, /*merkle_variant:*/ true);
|
let (mut shreds, _) = make_slot_entries(1, 0, 1, /*merkle_variant:*/ true);
|
||||||
let (shreds2, _) = make_slot_entries(5, 2, 1, /*merkle_variant:*/ true);
|
let (shreds2, _) = make_slot_entries(5, 2, 1, /*merkle_variant:*/ true);
|
||||||
shreds.extend(shreds2);
|
shreds.extend(shreds2);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
let mut repair_weight = RepairWeight::new(0);
|
let mut repair_weight = RepairWeight::new(0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
repair_weight.get_best_weighted_repairs(
|
repair_weight.get_best_weighted_repairs(
|
||||||
&blockstore,
|
&blockstore,
|
||||||
&HashMap::new(),
|
&HashMap::new(),
|
||||||
&EpochSchedule::default(),
|
&EpochSchedule::default(),
|
||||||
MAX_ORPHANS,
|
MAX_ORPHANS,
|
||||||
MAX_REPAIR_LENGTH,
|
MAX_REPAIR_LENGTH,
|
||||||
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
||||||
MAX_CLOSEST_COMPLETION_REPAIRS,
|
MAX_CLOSEST_COMPLETION_REPAIRS,
|
||||||
&mut RepairTiming::default(),
|
&mut RepairTiming::default(),
|
||||||
&mut BestRepairsStats::default(),
|
&mut BestRepairsStats::default(),
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
ShredRepairType::Orphan(2),
|
ShredRepairType::Orphan(2),
|
||||||
ShredRepairType::HighestShred(0, 0)
|
ShredRepairType::HighestShred(0, 0)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_repair_empty_slot() {
|
pub fn test_repair_empty_slot() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let (shreds, _) = make_slot_entries(2, 0, 1, /*merkle_variant:*/ true);
|
let (shreds, _) = make_slot_entries(2, 0, 1, /*merkle_variant:*/ true);
|
||||||
|
|
||||||
// Write this shred to slot 2, should chain to slot 0, which we haven't received
|
// Write this shred to slot 2, should chain to slot 0, which we haven't received
|
||||||
// any shreds for
|
// any shreds for
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
let mut repair_weight = RepairWeight::new(0);
|
let mut repair_weight = RepairWeight::new(0);
|
||||||
|
|
||||||
// Check that repair tries to patch the empty slot
|
// Check that repair tries to patch the empty slot
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
repair_weight.get_best_weighted_repairs(
|
repair_weight.get_best_weighted_repairs(
|
||||||
&blockstore,
|
&blockstore,
|
||||||
&HashMap::new(),
|
&HashMap::new(),
|
||||||
&EpochSchedule::default(),
|
&EpochSchedule::default(),
|
||||||
MAX_ORPHANS,
|
MAX_ORPHANS,
|
||||||
MAX_REPAIR_LENGTH,
|
MAX_REPAIR_LENGTH,
|
||||||
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
||||||
MAX_CLOSEST_COMPLETION_REPAIRS,
|
MAX_CLOSEST_COMPLETION_REPAIRS,
|
||||||
&mut RepairTiming::default(),
|
&mut RepairTiming::default(),
|
||||||
&mut BestRepairsStats::default(),
|
&mut BestRepairsStats::default(),
|
||||||
),
|
),
|
||||||
vec![ShredRepairType::HighestShred(0, 0)]
|
vec![ShredRepairType::HighestShred(0, 0)]
|
||||||
);
|
);
|
||||||
}
|
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_generate_repairs() {
|
pub fn test_generate_repairs() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let nth = 3;
|
let nth = 3;
|
||||||
let num_slots = 2;
|
let num_slots = 2;
|
||||||
|
|
||||||
// Create some shreds
|
// Create some shreds
|
||||||
let (mut shreds, _) = make_many_slot_entries(0, num_slots, 150);
|
let (mut shreds, _) = make_many_slot_entries(0, num_slots, 150);
|
||||||
let num_shreds = shreds.len() as u64;
|
let num_shreds = shreds.len() as u64;
|
||||||
let num_shreds_per_slot = num_shreds / num_slots;
|
let num_shreds_per_slot = num_shreds / num_slots;
|
||||||
|
|
||||||
// write every nth shred
|
// write every nth shred
|
||||||
let mut shreds_to_write = vec![];
|
let mut shreds_to_write = vec![];
|
||||||
let mut missing_indexes_per_slot = vec![];
|
let mut missing_indexes_per_slot = vec![];
|
||||||
for i in (0..num_shreds).rev() {
|
for i in (0..num_shreds).rev() {
|
||||||
let index = i % num_shreds_per_slot;
|
let index = i % num_shreds_per_slot;
|
||||||
// get_best_repair_shreds only returns missing shreds in
|
// get_best_repair_shreds only returns missing shreds in
|
||||||
// between shreds received; So this should either insert the
|
// between shreds received; So this should either insert the
|
||||||
// last shred in each slot, or exclude missing shreds after the
|
// last shred in each slot, or exclude missing shreds after the
|
||||||
// last inserted shred from expected repairs.
|
// last inserted shred from expected repairs.
|
||||||
if index % nth == 0 || index + 1 == num_shreds_per_slot {
|
if index % nth == 0 || index + 1 == num_shreds_per_slot {
|
||||||
shreds_to_write.insert(0, shreds.remove(i as usize));
|
shreds_to_write.insert(0, shreds.remove(i as usize));
|
||||||
} else if i < num_shreds_per_slot {
|
} else if i < num_shreds_per_slot {
|
||||||
missing_indexes_per_slot.insert(0, index);
|
missing_indexes_per_slot.insert(0, index);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
blockstore
|
|
||||||
.insert_shreds(shreds_to_write, None, false)
|
|
||||||
.unwrap();
|
|
||||||
let expected: Vec<ShredRepairType> = (0..num_slots)
|
|
||||||
.flat_map(|slot| {
|
|
||||||
missing_indexes_per_slot
|
|
||||||
.iter()
|
|
||||||
.map(move |shred_index| ShredRepairType::Shred(slot, *shred_index))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut repair_weight = RepairWeight::new(0);
|
|
||||||
sleep_shred_deferment_period();
|
|
||||||
assert_eq!(
|
|
||||||
repair_weight.get_best_weighted_repairs(
|
|
||||||
&blockstore,
|
|
||||||
&HashMap::new(),
|
|
||||||
&EpochSchedule::default(),
|
|
||||||
MAX_ORPHANS,
|
|
||||||
MAX_REPAIR_LENGTH,
|
|
||||||
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
|
||||||
MAX_CLOSEST_COMPLETION_REPAIRS,
|
|
||||||
&mut RepairTiming::default(),
|
|
||||||
&mut BestRepairsStats::default(),
|
|
||||||
),
|
|
||||||
expected
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
repair_weight.get_best_weighted_repairs(
|
|
||||||
&blockstore,
|
|
||||||
&HashMap::new(),
|
|
||||||
&EpochSchedule::default(),
|
|
||||||
MAX_ORPHANS,
|
|
||||||
expected.len() - 2,
|
|
||||||
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
|
||||||
MAX_CLOSEST_COMPLETION_REPAIRS,
|
|
||||||
&mut RepairTiming::default(),
|
|
||||||
&mut BestRepairsStats::default(),
|
|
||||||
)[..],
|
|
||||||
expected[0..expected.len() - 2]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
blockstore
|
||||||
|
.insert_shreds(shreds_to_write, None, false)
|
||||||
|
.unwrap();
|
||||||
|
let expected: Vec<ShredRepairType> = (0..num_slots)
|
||||||
|
.flat_map(|slot| {
|
||||||
|
missing_indexes_per_slot
|
||||||
|
.iter()
|
||||||
|
.map(move |shred_index| ShredRepairType::Shred(slot, *shred_index))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut repair_weight = RepairWeight::new(0);
|
||||||
|
sleep_shred_deferment_period();
|
||||||
|
assert_eq!(
|
||||||
|
repair_weight.get_best_weighted_repairs(
|
||||||
|
&blockstore,
|
||||||
|
&HashMap::new(),
|
||||||
|
&EpochSchedule::default(),
|
||||||
|
MAX_ORPHANS,
|
||||||
|
MAX_REPAIR_LENGTH,
|
||||||
|
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
||||||
|
MAX_CLOSEST_COMPLETION_REPAIRS,
|
||||||
|
&mut RepairTiming::default(),
|
||||||
|
&mut BestRepairsStats::default(),
|
||||||
|
),
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
repair_weight.get_best_weighted_repairs(
|
||||||
|
&blockstore,
|
||||||
|
&HashMap::new(),
|
||||||
|
&EpochSchedule::default(),
|
||||||
|
MAX_ORPHANS,
|
||||||
|
expected.len() - 2,
|
||||||
|
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
||||||
|
MAX_CLOSEST_COMPLETION_REPAIRS,
|
||||||
|
&mut RepairTiming::default(),
|
||||||
|
&mut BestRepairsStats::default(),
|
||||||
|
)[..],
|
||||||
|
expected[0..expected.len() - 2]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_generate_highest_repair() {
|
pub fn test_generate_highest_repair() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let num_entries_per_slot = 100;
|
let num_entries_per_slot = 100;
|
||||||
|
|
||||||
// Create some shreds
|
// Create some shreds
|
||||||
let (mut shreds, _) = make_slot_entries(
|
let (mut shreds, _) = make_slot_entries(
|
||||||
0, // slot
|
0, // slot
|
||||||
0, // parent_slot
|
0, // parent_slot
|
||||||
num_entries_per_slot as u64,
|
num_entries_per_slot as u64,
|
||||||
true, // merkle_variant
|
true, // merkle_variant
|
||||||
);
|
);
|
||||||
let num_shreds_per_slot = shreds.len() as u64;
|
let num_shreds_per_slot = shreds.len() as u64;
|
||||||
|
|
||||||
// Remove last shred (which is also last in slot) so that slot is not complete
|
// Remove last shred (which is also last in slot) so that slot is not complete
|
||||||
shreds.pop();
|
shreds.pop();
|
||||||
|
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
|
|
||||||
// We didn't get the last shred for this slot, so ask for the highest shred for that slot
|
// We didn't get the last shred for this slot, so ask for the highest shred for that slot
|
||||||
let expected: Vec<ShredRepairType> =
|
let expected: Vec<ShredRepairType> =
|
||||||
vec![ShredRepairType::HighestShred(0, num_shreds_per_slot - 1)];
|
vec![ShredRepairType::HighestShred(0, num_shreds_per_slot - 1)];
|
||||||
|
|
||||||
sleep_shred_deferment_period();
|
sleep_shred_deferment_period();
|
||||||
let mut repair_weight = RepairWeight::new(0);
|
let mut repair_weight = RepairWeight::new(0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
repair_weight.get_best_weighted_repairs(
|
repair_weight.get_best_weighted_repairs(
|
||||||
&blockstore,
|
&blockstore,
|
||||||
&HashMap::new(),
|
&HashMap::new(),
|
||||||
&EpochSchedule::default(),
|
&EpochSchedule::default(),
|
||||||
MAX_ORPHANS,
|
MAX_ORPHANS,
|
||||||
MAX_REPAIR_LENGTH,
|
MAX_REPAIR_LENGTH,
|
||||||
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
MAX_UNKNOWN_LAST_INDEX_REPAIRS,
|
||||||
MAX_CLOSEST_COMPLETION_REPAIRS,
|
MAX_CLOSEST_COMPLETION_REPAIRS,
|
||||||
&mut RepairTiming::default(),
|
&mut RepairTiming::default(),
|
||||||
&mut BestRepairsStats::default(),
|
&mut BestRepairsStats::default(),
|
||||||
),
|
),
|
||||||
expected
|
expected
|
||||||
);
|
);
|
||||||
}
|
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_repair_range() {
|
pub fn test_repair_range() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let slots: Vec<u64> = vec![1, 3, 5, 7, 8];
|
let slots: Vec<u64> = vec![1, 3, 5, 7, 8];
|
||||||
let num_entries_per_slot = max_ticks_per_n_shreds(1, None) + 1;
|
let num_entries_per_slot = max_ticks_per_n_shreds(1, None) + 1;
|
||||||
|
|
||||||
let shreds = make_chaining_slot_entries(&slots, num_entries_per_slot);
|
let shreds = make_chaining_slot_entries(&slots, num_entries_per_slot);
|
||||||
for (mut slot_shreds, _) in shreds.into_iter() {
|
for (mut slot_shreds, _) in shreds.into_iter() {
|
||||||
slot_shreds.remove(0);
|
slot_shreds.remove(0);
|
||||||
blockstore.insert_shreds(slot_shreds, None, false).unwrap();
|
blockstore.insert_shreds(slot_shreds, None, false).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through all possible combinations of start..end (inclusive on both
|
// Iterate through all possible combinations of start..end (inclusive on both
|
||||||
// sides of the range)
|
// sides of the range)
|
||||||
for start in 0..slots.len() {
|
for start in 0..slots.len() {
|
||||||
for end in start..slots.len() {
|
for end in start..slots.len() {
|
||||||
let repair_slot_range = RepairSlotRange {
|
let repair_slot_range = RepairSlotRange {
|
||||||
start: slots[start],
|
start: slots[start],
|
||||||
end: slots[end],
|
end: slots[end],
|
||||||
};
|
};
|
||||||
let expected: Vec<ShredRepairType> = (repair_slot_range.start
|
let expected: Vec<ShredRepairType> = (repair_slot_range.start
|
||||||
..=repair_slot_range.end)
|
..=repair_slot_range.end)
|
||||||
.map(|slot_index| {
|
.map(|slot_index| {
|
||||||
if slots.contains(&slot_index) {
|
if slots.contains(&slot_index) {
|
||||||
ShredRepairType::Shred(slot_index, 0)
|
ShredRepairType::Shred(slot_index, 0)
|
||||||
} else {
|
} else {
|
||||||
ShredRepairType::HighestShred(slot_index, 0)
|
ShredRepairType::HighestShred(slot_index, 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
sleep_shred_deferment_period();
|
sleep_shred_deferment_period();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RepairService::generate_repairs_in_range(
|
RepairService::generate_repairs_in_range(
|
||||||
&blockstore,
|
&blockstore,
|
||||||
std::usize::MAX,
|
std::usize::MAX,
|
||||||
&repair_slot_range,
|
&repair_slot_range,
|
||||||
),
|
),
|
||||||
expected
|
expected
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_repair_range_highest() {
|
pub fn test_repair_range_highest() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
|
||||||
|
|
||||||
let num_entries_per_slot = 10;
|
let num_entries_per_slot = 10;
|
||||||
|
|
||||||
let num_slots = 1;
|
let num_slots = 1;
|
||||||
let start = 5;
|
let start = 5;
|
||||||
|
|
||||||
// Create some shreds in slots 0..num_slots
|
// Create some shreds in slots 0..num_slots
|
||||||
for i in start..start + num_slots {
|
for i in start..start + num_slots {
|
||||||
let parent = if i > 0 { i - 1 } else { 0 };
|
let parent = if i > 0 { i - 1 } else { 0 };
|
||||||
let (shreds, _) = make_slot_entries(
|
let (shreds, _) = make_slot_entries(
|
||||||
i, // slot
|
i, // slot
|
||||||
parent,
|
parent,
|
||||||
num_entries_per_slot as u64,
|
num_entries_per_slot as u64,
|
||||||
true, // merkle_variant
|
true, // merkle_variant
|
||||||
);
|
|
||||||
|
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let end = 4;
|
|
||||||
let expected: Vec<ShredRepairType> = vec![
|
|
||||||
ShredRepairType::HighestShred(end - 2, 0),
|
|
||||||
ShredRepairType::HighestShred(end - 1, 0),
|
|
||||||
ShredRepairType::HighestShred(end, 0),
|
|
||||||
];
|
|
||||||
|
|
||||||
let repair_slot_range = RepairSlotRange { start: 2, end };
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
RepairService::generate_repairs_in_range(
|
|
||||||
&blockstore,
|
|
||||||
std::usize::MAX,
|
|
||||||
&repair_slot_range,
|
|
||||||
),
|
|
||||||
expected
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
}
|
}
|
||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
|
||||||
|
let end = 4;
|
||||||
|
let expected: Vec<ShredRepairType> = vec![
|
||||||
|
ShredRepairType::HighestShred(end - 2, 0),
|
||||||
|
ShredRepairType::HighestShred(end - 1, 0),
|
||||||
|
ShredRepairType::HighestShred(end, 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
let repair_slot_range = RepairSlotRange { start: 2, end };
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
RepairService::generate_repairs_in_range(
|
||||||
|
&blockstore,
|
||||||
|
std::usize::MAX,
|
||||||
|
&repair_slot_range,
|
||||||
|
),
|
||||||
|
expected
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_generate_duplicate_repairs_for_slot() {
|
pub fn test_generate_duplicate_repairs_for_slot() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let dead_slot = 9;
|
let dead_slot = 9;
|
||||||
|
|
||||||
// SlotMeta doesn't exist, should make no repairs
|
// SlotMeta doesn't exist, should make no repairs
|
||||||
|
@ -1203,8 +1184,8 @@ mod test {
|
||||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||||
let bank = Bank::new_for_tests(&genesis_config);
|
let bank = Bank::new_for_tests(&genesis_config);
|
||||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let cluster_slots = ClusterSlots::default();
|
let cluster_slots = ClusterSlots::default();
|
||||||
let cluster_info = Arc::new(new_test_cluster_info());
|
let cluster_info = Arc::new(new_test_cluster_info());
|
||||||
let identity_keypair = cluster_info.keypair().clone();
|
let identity_keypair = cluster_info.keypair().clone();
|
||||||
|
|
|
@ -1423,7 +1423,7 @@ mod tests {
|
||||||
blockstore::make_many_slot_entries,
|
blockstore::make_many_slot_entries,
|
||||||
blockstore_processor::fill_blockstore_slot_with_ticks,
|
blockstore_processor::fill_blockstore_slot_with_ticks,
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
shred::{max_ticks_per_n_shreds, Shred, ShredFlags},
|
shred::{max_ticks_per_n_shreds, Shred, ShredFlags},
|
||||||
},
|
},
|
||||||
solana_perf::packet::{deserialize_from_with_limit, Packet},
|
solana_perf::packet::{deserialize_from_with_limit, Packet},
|
||||||
|
@ -1853,64 +1853,60 @@ mod tests {
|
||||||
fn run_highest_window_request(slot: Slot, num_slots: u64, nonce: Nonce) {
|
fn run_highest_window_request(slot: Slot, num_slots: u64, nonce: Nonce) {
|
||||||
let recycler = PacketBatchRecycler::default();
|
let recycler = PacketBatchRecycler::default();
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let rv = ServeRepair::run_highest_window_request(
|
||||||
let rv = ServeRepair::run_highest_window_request(
|
&recycler,
|
||||||
&recycler,
|
&socketaddr_any!(),
|
||||||
&socketaddr_any!(),
|
&blockstore,
|
||||||
&blockstore,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
nonce,
|
||||||
nonce,
|
);
|
||||||
);
|
assert!(rv.is_none());
|
||||||
assert!(rv.is_none());
|
|
||||||
|
|
||||||
let _ = fill_blockstore_slot_with_ticks(
|
let _ = fill_blockstore_slot_with_ticks(
|
||||||
&blockstore,
|
&blockstore,
|
||||||
max_ticks_per_n_shreds(1, None) + 1,
|
max_ticks_per_n_shreds(1, None) + 1,
|
||||||
slot,
|
slot,
|
||||||
slot - num_slots + 1,
|
slot - num_slots + 1,
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let index = 1;
|
let index = 1;
|
||||||
let rv = ServeRepair::run_highest_window_request(
|
let rv = ServeRepair::run_highest_window_request(
|
||||||
&recycler,
|
&recycler,
|
||||||
&socketaddr_any!(),
|
&socketaddr_any!(),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
slot,
|
slot,
|
||||||
index,
|
index,
|
||||||
nonce,
|
nonce,
|
||||||
)
|
)
|
||||||
.expect("packets");
|
.expect("packets");
|
||||||
let request = ShredRepairType::HighestShred(slot, index);
|
let request = ShredRepairType::HighestShred(slot, index);
|
||||||
verify_responses(&request, rv.iter());
|
verify_responses(&request, rv.iter());
|
||||||
|
|
||||||
let rv: Vec<Shred> = rv
|
let rv: Vec<Shred> = rv
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
assert_eq!(repair_response::nonce(p).unwrap(), nonce);
|
assert_eq!(repair_response::nonce(p).unwrap(), nonce);
|
||||||
Shred::new_from_serialized_shred(p.data(..).unwrap().to_vec()).ok()
|
Shred::new_from_serialized_shred(p.data(..).unwrap().to_vec()).ok()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
assert!(!rv.is_empty());
|
assert!(!rv.is_empty());
|
||||||
let index = blockstore.meta(slot).unwrap().unwrap().received - 1;
|
let index = blockstore.meta(slot).unwrap().unwrap().received - 1;
|
||||||
assert_eq!(rv[0].index(), index as u32);
|
assert_eq!(rv[0].index(), index as u32);
|
||||||
assert_eq!(rv[0].slot(), slot);
|
assert_eq!(rv[0].slot(), slot);
|
||||||
|
|
||||||
let rv = ServeRepair::run_highest_window_request(
|
let rv = ServeRepair::run_highest_window_request(
|
||||||
&recycler,
|
&recycler,
|
||||||
&socketaddr_any!(),
|
&socketaddr_any!(),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
slot,
|
slot,
|
||||||
index + 1,
|
index + 1,
|
||||||
nonce,
|
nonce,
|
||||||
);
|
);
|
||||||
assert!(rv.is_none());
|
assert!(rv.is_none());
|
||||||
}
|
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1922,48 +1918,44 @@ mod tests {
|
||||||
fn run_window_request(slot: Slot, nonce: Nonce) {
|
fn run_window_request(slot: Slot, nonce: Nonce) {
|
||||||
let recycler = PacketBatchRecycler::default();
|
let recycler = PacketBatchRecycler::default();
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let rv = ServeRepair::run_window_request(
|
||||||
let rv = ServeRepair::run_window_request(
|
&recycler,
|
||||||
&recycler,
|
&socketaddr_any!(),
|
||||||
&socketaddr_any!(),
|
&blockstore,
|
||||||
&blockstore,
|
slot,
|
||||||
slot,
|
0,
|
||||||
0,
|
nonce,
|
||||||
nonce,
|
);
|
||||||
);
|
assert!(rv.is_none());
|
||||||
assert!(rv.is_none());
|
let shred = Shred::new_from_data(slot, 1, 1, &[], ShredFlags::empty(), 0, 2, 0);
|
||||||
let shred = Shred::new_from_data(slot, 1, 1, &[], ShredFlags::empty(), 0, 2, 0);
|
|
||||||
|
|
||||||
blockstore
|
blockstore
|
||||||
.insert_shreds(vec![shred], None, false)
|
.insert_shreds(vec![shred], None, false)
|
||||||
.expect("Expect successful ledger write");
|
.expect("Expect successful ledger write");
|
||||||
|
|
||||||
let index = 1;
|
let index = 1;
|
||||||
let rv = ServeRepair::run_window_request(
|
let rv = ServeRepair::run_window_request(
|
||||||
&recycler,
|
&recycler,
|
||||||
&socketaddr_any!(),
|
&socketaddr_any!(),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
slot,
|
slot,
|
||||||
index,
|
index,
|
||||||
nonce,
|
nonce,
|
||||||
)
|
)
|
||||||
.expect("packets");
|
.expect("packets");
|
||||||
let request = ShredRepairType::Shred(slot, index);
|
let request = ShredRepairType::Shred(slot, index);
|
||||||
verify_responses(&request, rv.iter());
|
verify_responses(&request, rv.iter());
|
||||||
let rv: Vec<Shred> = rv
|
let rv: Vec<Shred> = rv
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
assert_eq!(repair_response::nonce(p).unwrap(), nonce);
|
assert_eq!(repair_response::nonce(p).unwrap(), nonce);
|
||||||
Shred::new_from_serialized_shred(p.data(..).unwrap().to_vec()).ok()
|
Shred::new_from_serialized_shred(p.data(..).unwrap().to_vec()).ok()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
assert_eq!(rv[0].index(), 1);
|
assert_eq!(rv[0].index(), 1);
|
||||||
assert_eq!(rv[0].slot(), slot);
|
assert_eq!(rv[0].slot(), slot);
|
||||||
}
|
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_test_cluster_info() -> ClusterInfo {
|
fn new_test_cluster_info() -> ClusterInfo {
|
||||||
|
@ -2095,122 +2087,114 @@ mod tests {
|
||||||
fn run_orphan(slot: Slot, num_slots: u64, nonce: Nonce) {
|
fn run_orphan(slot: Slot, num_slots: u64, nonce: Nonce) {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let recycler = PacketBatchRecycler::default();
|
let recycler = PacketBatchRecycler::default();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let rv =
|
||||||
let rv =
|
ServeRepair::run_orphan(&recycler, &socketaddr_any!(), &blockstore, slot, 0, nonce);
|
||||||
ServeRepair::run_orphan(&recycler, &socketaddr_any!(), &blockstore, slot, 0, nonce);
|
assert!(rv.is_none());
|
||||||
assert!(rv.is_none());
|
|
||||||
|
|
||||||
// Create slots [slot, slot + num_slots) with 5 shreds apiece
|
// Create slots [slot, slot + num_slots) with 5 shreds apiece
|
||||||
let (shreds, _) = make_many_slot_entries(slot, num_slots, 5);
|
let (shreds, _) = make_many_slot_entries(slot, num_slots, 5);
|
||||||
|
|
||||||
blockstore
|
blockstore
|
||||||
.insert_shreds(shreds, None, false)
|
.insert_shreds(shreds, None, false)
|
||||||
.expect("Expect successful ledger write");
|
.expect("Expect successful ledger write");
|
||||||
|
|
||||||
// We don't have slot `slot + num_slots`, so we don't know how to service this request
|
// We don't have slot `slot + num_slots`, so we don't know how to service this request
|
||||||
let rv = ServeRepair::run_orphan(
|
let rv = ServeRepair::run_orphan(
|
||||||
&recycler,
|
&recycler,
|
||||||
&socketaddr_any!(),
|
&socketaddr_any!(),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
slot + num_slots,
|
slot + num_slots,
|
||||||
5,
|
5,
|
||||||
nonce,
|
nonce,
|
||||||
);
|
);
|
||||||
assert!(rv.is_none());
|
assert!(rv.is_none());
|
||||||
|
|
||||||
// For a orphan request for `slot + num_slots - 1`, we should return the highest shreds
|
// For a orphan request for `slot + num_slots - 1`, we should return the highest shreds
|
||||||
// from slots in the range [slot, slot + num_slots - 1]
|
// from slots in the range [slot, slot + num_slots - 1]
|
||||||
let rv: Vec<_> = ServeRepair::run_orphan(
|
let rv: Vec<_> = ServeRepair::run_orphan(
|
||||||
&recycler,
|
&recycler,
|
||||||
&socketaddr_any!(),
|
&socketaddr_any!(),
|
||||||
&blockstore,
|
&blockstore,
|
||||||
slot + num_slots - 1,
|
slot + num_slots - 1,
|
||||||
5,
|
5,
|
||||||
nonce,
|
nonce,
|
||||||
)
|
)
|
||||||
.expect("run_orphan packets")
|
.expect("run_orphan packets")
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Verify responses
|
||||||
|
let request = ShredRepairType::Orphan(slot);
|
||||||
|
verify_responses(&request, rv.iter());
|
||||||
|
|
||||||
|
let expected: Vec<_> = (slot..slot + num_slots)
|
||||||
|
.rev()
|
||||||
|
.filter_map(|slot| {
|
||||||
|
let index = blockstore.meta(slot).unwrap().unwrap().received - 1;
|
||||||
|
repair_response::repair_response_packet(
|
||||||
|
&blockstore,
|
||||||
|
slot,
|
||||||
|
index,
|
||||||
|
&socketaddr_any!(),
|
||||||
|
nonce,
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
assert_eq!(rv, expected);
|
||||||
// Verify responses
|
|
||||||
let request = ShredRepairType::Orphan(slot);
|
|
||||||
verify_responses(&request, rv.iter());
|
|
||||||
|
|
||||||
let expected: Vec<_> = (slot..slot + num_slots)
|
|
||||||
.rev()
|
|
||||||
.filter_map(|slot| {
|
|
||||||
let index = blockstore.meta(slot).unwrap().unwrap().received - 1;
|
|
||||||
repair_response::repair_response_packet(
|
|
||||||
&blockstore,
|
|
||||||
slot,
|
|
||||||
index,
|
|
||||||
&socketaddr_any!(),
|
|
||||||
nonce,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
assert_eq!(rv, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn run_orphan_corrupted_shred_size() {
|
fn run_orphan_corrupted_shred_size() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let recycler = PacketBatchRecycler::default();
|
let recycler = PacketBatchRecycler::default();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
// Create slots [1, 2] with 1 shred apiece
|
||||||
// Create slots [1, 2] with 1 shred apiece
|
let (mut shreds, _) = make_many_slot_entries(1, 2, 1);
|
||||||
let (mut shreds, _) = make_many_slot_entries(1, 2, 1);
|
|
||||||
|
|
||||||
assert_eq!(shreds[0].slot(), 1);
|
assert_eq!(shreds[0].slot(), 1);
|
||||||
assert_eq!(shreds[0].index(), 0);
|
assert_eq!(shreds[0].index(), 0);
|
||||||
// TODO: The test previously relied on corrupting shred payload
|
// TODO: The test previously relied on corrupting shred payload
|
||||||
// size which we no longer want to expose. Current test no longer
|
// size which we no longer want to expose. Current test no longer
|
||||||
// covers packet size check in repair_response_packet_from_bytes.
|
// covers packet size check in repair_response_packet_from_bytes.
|
||||||
shreds.remove(0);
|
shreds.remove(0);
|
||||||
blockstore
|
blockstore
|
||||||
.insert_shreds(shreds, None, false)
|
.insert_shreds(shreds, None, false)
|
||||||
.expect("Expect successful ledger write");
|
.expect("Expect successful ledger write");
|
||||||
let nonce = 42;
|
let nonce = 42;
|
||||||
// Make sure repair response is corrupted
|
// Make sure repair response is corrupted
|
||||||
assert!(repair_response::repair_response_packet(
|
assert!(repair_response::repair_response_packet(
|
||||||
&blockstore,
|
&blockstore,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
&socketaddr_any!(),
|
&socketaddr_any!(),
|
||||||
nonce,
|
nonce,
|
||||||
)
|
)
|
||||||
.is_none());
|
.is_none());
|
||||||
|
|
||||||
// Orphan request for slot 2 should only return slot 1 since
|
// Orphan request for slot 2 should only return slot 1 since
|
||||||
// calling `repair_response_packet` on slot 1's shred will
|
// calling `repair_response_packet` on slot 1's shred will
|
||||||
// be corrupted
|
// be corrupted
|
||||||
let rv: Vec<_> =
|
let rv: Vec<_> =
|
||||||
ServeRepair::run_orphan(&recycler, &socketaddr_any!(), &blockstore, 2, 5, nonce)
|
ServeRepair::run_orphan(&recycler, &socketaddr_any!(), &blockstore, 2, 5, nonce)
|
||||||
.expect("run_orphan packets")
|
.expect("run_orphan packets")
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Verify responses
|
// Verify responses
|
||||||
let expected = vec![repair_response::repair_response_packet(
|
let expected = vec![repair_response::repair_response_packet(
|
||||||
&blockstore,
|
&blockstore,
|
||||||
2,
|
2,
|
||||||
0,
|
0,
|
||||||
&socketaddr_any!(),
|
&socketaddr_any!(),
|
||||||
nonce,
|
nonce,
|
||||||
)
|
)
|
||||||
.unwrap()];
|
.unwrap()];
|
||||||
assert_eq!(rv, expected);
|
assert_eq!(rv, expected);
|
||||||
}
|
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2223,95 +2207,92 @@ mod tests {
|
||||||
|
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let recycler = PacketBatchRecycler::default();
|
let recycler = PacketBatchRecycler::default();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
|
||||||
let slot = 0;
|
|
||||||
let num_slots = MAX_ANCESTOR_RESPONSES as u64;
|
|
||||||
let nonce = 10;
|
|
||||||
|
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let slot = 0;
|
||||||
|
let num_slots = MAX_ANCESTOR_RESPONSES as u64;
|
||||||
|
let nonce = 10;
|
||||||
|
|
||||||
// Create slots [slot, slot + num_slots) with 5 shreds apiece
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let (shreds, _) = make_many_slot_entries(slot, num_slots, 5);
|
|
||||||
|
|
||||||
blockstore
|
// Create slots [slot, slot + num_slots) with 5 shreds apiece
|
||||||
.insert_shreds(shreds, None, false)
|
let (shreds, _) = make_many_slot_entries(slot, num_slots, 5);
|
||||||
.expect("Expect successful ledger write");
|
|
||||||
|
|
||||||
// We don't have slot `slot + num_slots`, so we return empty
|
blockstore
|
||||||
let rv = ServeRepair::run_ancestor_hashes(
|
.insert_shreds(shreds, None, false)
|
||||||
&recycler,
|
.expect("Expect successful ledger write");
|
||||||
&socketaddr_any!(),
|
|
||||||
&blockstore,
|
// We don't have slot `slot + num_slots`, so we return empty
|
||||||
slot + num_slots,
|
let rv = ServeRepair::run_ancestor_hashes(
|
||||||
nonce,
|
&recycler,
|
||||||
)
|
&socketaddr_any!(),
|
||||||
.expect("run_ancestor_hashes packets");
|
&blockstore,
|
||||||
assert_eq!(rv.len(), 1);
|
slot + num_slots,
|
||||||
let packet = &rv[0];
|
nonce,
|
||||||
let ancestor_hashes_response = deserialize_ancestor_hashes_response(packet);
|
)
|
||||||
match ancestor_hashes_response {
|
.expect("run_ancestor_hashes packets");
|
||||||
AncestorHashesResponse::Hashes(hashes) => {
|
assert_eq!(rv.len(), 1);
|
||||||
assert!(hashes.is_empty());
|
let packet = &rv[0];
|
||||||
}
|
let ancestor_hashes_response = deserialize_ancestor_hashes_response(packet);
|
||||||
_ => {
|
match ancestor_hashes_response {
|
||||||
panic!("unexpected response: {:?}", &ancestor_hashes_response);
|
AncestorHashesResponse::Hashes(hashes) => {
|
||||||
}
|
assert!(hashes.is_empty());
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
// `slot + num_slots - 1` is not marked duplicate confirmed so nothing should return
|
panic!("unexpected response: {:?}", &ancestor_hashes_response);
|
||||||
// empty
|
|
||||||
let rv = ServeRepair::run_ancestor_hashes(
|
|
||||||
&recycler,
|
|
||||||
&socketaddr_any!(),
|
|
||||||
&blockstore,
|
|
||||||
slot + num_slots - 1,
|
|
||||||
nonce,
|
|
||||||
)
|
|
||||||
.expect("run_ancestor_hashes packets");
|
|
||||||
assert_eq!(rv.len(), 1);
|
|
||||||
let packet = &rv[0];
|
|
||||||
let ancestor_hashes_response = deserialize_ancestor_hashes_response(packet);
|
|
||||||
match ancestor_hashes_response {
|
|
||||||
AncestorHashesResponse::Hashes(hashes) => {
|
|
||||||
assert!(hashes.is_empty());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
panic!("unexpected response: {:?}", &ancestor_hashes_response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set duplicate confirmed
|
|
||||||
let mut expected_ancestors = Vec::with_capacity(num_slots as usize);
|
|
||||||
expected_ancestors.resize(num_slots as usize, (0, Hash::default()));
|
|
||||||
for (i, duplicate_confirmed_slot) in (slot..slot + num_slots).enumerate() {
|
|
||||||
let frozen_hash = Hash::new_unique();
|
|
||||||
expected_ancestors[num_slots as usize - i - 1] =
|
|
||||||
(duplicate_confirmed_slot, frozen_hash);
|
|
||||||
blockstore.insert_bank_hash(duplicate_confirmed_slot, frozen_hash, true);
|
|
||||||
}
|
|
||||||
let rv = ServeRepair::run_ancestor_hashes(
|
|
||||||
&recycler,
|
|
||||||
&socketaddr_any!(),
|
|
||||||
&blockstore,
|
|
||||||
slot + num_slots - 1,
|
|
||||||
nonce,
|
|
||||||
)
|
|
||||||
.expect("run_ancestor_hashes packets");
|
|
||||||
assert_eq!(rv.len(), 1);
|
|
||||||
let packet = &rv[0];
|
|
||||||
let ancestor_hashes_response = deserialize_ancestor_hashes_response(packet);
|
|
||||||
match ancestor_hashes_response {
|
|
||||||
AncestorHashesResponse::Hashes(hashes) => {
|
|
||||||
assert_eq!(hashes, expected_ancestors);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
panic!("unexpected response: {:?}", &ancestor_hashes_response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
// `slot + num_slots - 1` is not marked duplicate confirmed so nothing should return
|
||||||
|
// empty
|
||||||
|
let rv = ServeRepair::run_ancestor_hashes(
|
||||||
|
&recycler,
|
||||||
|
&socketaddr_any!(),
|
||||||
|
&blockstore,
|
||||||
|
slot + num_slots - 1,
|
||||||
|
nonce,
|
||||||
|
)
|
||||||
|
.expect("run_ancestor_hashes packets");
|
||||||
|
assert_eq!(rv.len(), 1);
|
||||||
|
let packet = &rv[0];
|
||||||
|
let ancestor_hashes_response = deserialize_ancestor_hashes_response(packet);
|
||||||
|
match ancestor_hashes_response {
|
||||||
|
AncestorHashesResponse::Hashes(hashes) => {
|
||||||
|
assert!(hashes.is_empty());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("unexpected response: {:?}", &ancestor_hashes_response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set duplicate confirmed
|
||||||
|
let mut expected_ancestors = Vec::with_capacity(num_slots as usize);
|
||||||
|
expected_ancestors.resize(num_slots as usize, (0, Hash::default()));
|
||||||
|
for (i, duplicate_confirmed_slot) in (slot..slot + num_slots).enumerate() {
|
||||||
|
let frozen_hash = Hash::new_unique();
|
||||||
|
expected_ancestors[num_slots as usize - i - 1] =
|
||||||
|
(duplicate_confirmed_slot, frozen_hash);
|
||||||
|
blockstore.insert_bank_hash(duplicate_confirmed_slot, frozen_hash, true);
|
||||||
|
}
|
||||||
|
let rv = ServeRepair::run_ancestor_hashes(
|
||||||
|
&recycler,
|
||||||
|
&socketaddr_any!(),
|
||||||
|
&blockstore,
|
||||||
|
slot + num_slots - 1,
|
||||||
|
nonce,
|
||||||
|
)
|
||||||
|
.expect("run_ancestor_hashes packets");
|
||||||
|
assert_eq!(rv.len(), 1);
|
||||||
|
let packet = &rv[0];
|
||||||
|
let ancestor_hashes_response = deserialize_ancestor_hashes_response(packet);
|
||||||
|
match ancestor_hashes_response {
|
||||||
|
AncestorHashesResponse::Hashes(hashes) => {
|
||||||
|
assert_eq!(hashes, expected_ancestors);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("unexpected response: {:?}", &ancestor_hashes_response);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -4078,7 +4078,7 @@ pub(crate) mod tests {
|
||||||
blockstore::{entries_to_test_shreds, make_slot_entries, BlockstoreError},
|
blockstore::{entries_to_test_shreds, make_slot_entries, BlockstoreError},
|
||||||
create_new_tmp_ledger,
|
create_new_tmp_ledger,
|
||||||
genesis_utils::{create_genesis_config, create_genesis_config_with_leader},
|
genesis_utils::{create_genesis_config, create_genesis_config_with_leader},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path, get_tmp_ledger_path_auto_delete,
|
||||||
shred::{Shred, ShredFlags, LEGACY_SHRED_DATA_CAPACITY},
|
shred::{Shred, ShredFlags, LEGACY_SHRED_DATA_CAPACITY},
|
||||||
},
|
},
|
||||||
solana_rpc::{
|
solana_rpc::{
|
||||||
|
@ -6405,9 +6405,10 @@ pub(crate) mod tests {
|
||||||
let mut vote_simulator = VoteSimulator::new(1);
|
let mut vote_simulator = VoteSimulator::new(1);
|
||||||
vote_simulator.fill_bank_forks(forks, &HashMap::<Pubkey, Vec<u64>>::new(), true);
|
vote_simulator.fill_bank_forks(forks, &HashMap::<Pubkey, Vec<u64>>::new(), true);
|
||||||
let (bank_forks, mut progress) = (vote_simulator.bank_forks, vote_simulator.progress);
|
let (bank_forks, mut progress) = (vote_simulator.bank_forks, vote_simulator.progress);
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Arc::new(
|
let blockstore = Arc::new(
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
Blockstore::open(ledger_path.path())
|
||||||
|
.expect("Expected to be able to open database ledger"),
|
||||||
);
|
);
|
||||||
let mut tower = Tower::new_for_tests(8, 2.0 / 3.0);
|
let mut tower = Tower::new_for_tests(8, 2.0 / 3.0);
|
||||||
|
|
||||||
|
@ -6552,9 +6553,10 @@ pub(crate) mod tests {
|
||||||
vote_simulator.fill_bank_forks(forks, &validator_votes, true);
|
vote_simulator.fill_bank_forks(forks, &validator_votes, true);
|
||||||
|
|
||||||
let (bank_forks, mut progress) = (vote_simulator.bank_forks, vote_simulator.progress);
|
let (bank_forks, mut progress) = (vote_simulator.bank_forks, vote_simulator.progress);
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Arc::new(
|
let blockstore = Arc::new(
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
Blockstore::open(ledger_path.path())
|
||||||
|
.expect("Expected to be able to open database ledger"),
|
||||||
);
|
);
|
||||||
let mut tower = Tower::new_for_tests(8, 0.67);
|
let mut tower = Tower::new_for_tests(8, 0.67);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use {
|
||||||
solana_entry::entry::{create_ticks, Entry},
|
solana_entry::entry::{create_ticks, Entry},
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
blockstore::{entries_to_test_shreds, Blockstore},
|
blockstore::{entries_to_test_shreds, Blockstore},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
},
|
},
|
||||||
solana_sdk::{clock::Slot, hash::Hash},
|
solana_sdk::{clock::Slot, hash::Hash},
|
||||||
std::path::Path,
|
std::path::Path,
|
||||||
|
@ -23,8 +23,6 @@ fn bench_write_shreds(bench: &mut Bencher, entries: Vec<Entry>, ledger_path: &Pa
|
||||||
let shreds = entries_to_test_shreds(&entries, 0, 0, true, 0, /*merkle_variant:*/ true);
|
let shreds = entries_to_test_shreds(&entries, 0, 0, true, 0, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
Blockstore::destroy(ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert some shreds into the ledger in preparation for read benchmarks
|
// Insert some shreds into the ledger in preparation for read benchmarks
|
||||||
|
@ -59,28 +57,28 @@ fn setup_read_bench(
|
||||||
#[bench]
|
#[bench]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn bench_write_small(bench: &mut Bencher) {
|
fn bench_write_small(bench: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let num_entries = 32 * 1024;
|
let num_entries = 32 * 1024;
|
||||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||||
bench_write_shreds(bench, entries, &ledger_path);
|
bench_write_shreds(bench, entries, ledger_path.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write big shreds to the ledger
|
// Write big shreds to the ledger
|
||||||
#[bench]
|
#[bench]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn bench_write_big(bench: &mut Bencher) {
|
fn bench_write_big(bench: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let num_entries = 32 * 1024;
|
let num_entries = 32 * 1024;
|
||||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||||
bench_write_shreds(bench, entries, &ledger_path);
|
bench_write_shreds(bench, entries, ledger_path.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn bench_read_sequential(bench: &mut Bencher) {
|
fn bench_read_sequential(bench: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore =
|
let blockstore =
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger");
|
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger");
|
||||||
|
|
||||||
// Insert some big and small shreds into the ledger
|
// Insert some big and small shreds into the ledger
|
||||||
let num_small_shreds = 32 * 1024;
|
let num_small_shreds = 32 * 1024;
|
||||||
|
@ -98,16 +96,14 @@ fn bench_read_sequential(bench: &mut Bencher) {
|
||||||
let _ = blockstore.get_data_shred(slot, i % total_shreds);
|
let _ = blockstore.get_data_shred(slot, i % total_shreds);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn bench_read_random(bench: &mut Bencher) {
|
fn bench_read_random(bench: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore =
|
let blockstore =
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger");
|
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger");
|
||||||
|
|
||||||
// Insert some big and small shreds into the ledger
|
// Insert some big and small shreds into the ledger
|
||||||
let num_small_shreds = 32 * 1024;
|
let num_small_shreds = 32 * 1024;
|
||||||
|
@ -129,36 +125,32 @@ fn bench_read_random(bench: &mut Bencher) {
|
||||||
let _ = blockstore.get_data_shred(slot, *i as u64);
|
let _ = blockstore.get_data_shred(slot, *i as u64);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn bench_insert_data_shred_small(bench: &mut Bencher) {
|
fn bench_insert_data_shred_small(bench: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore =
|
let blockstore =
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger");
|
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger");
|
||||||
let num_entries = 32 * 1024;
|
let num_entries = 32 * 1024;
|
||||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||||
bench.iter(move || {
|
bench.iter(move || {
|
||||||
let shreds = entries_to_test_shreds(&entries, 0, 0, true, 0, /*merkle_variant:*/ true);
|
let shreds = entries_to_test_shreds(&entries, 0, 0, true, 0, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
});
|
});
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn bench_insert_data_shred_big(bench: &mut Bencher) {
|
fn bench_insert_data_shred_big(bench: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore =
|
let blockstore =
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger");
|
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger");
|
||||||
let num_entries = 32 * 1024;
|
let num_entries = 32 * 1024;
|
||||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||||
bench.iter(move || {
|
bench.iter(move || {
|
||||||
let shreds = entries_to_test_shreds(&entries, 0, 0, true, 0, /*merkle_variant:*/ true);
|
let shreds = entries_to_test_shreds(&entries, 0, 0, true, 0, /*merkle_variant:*/ true);
|
||||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||||
});
|
});
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use {
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
blockstore::Blockstore,
|
blockstore::Blockstore,
|
||||||
blockstore_db::{columns as cf, LedgerColumn},
|
blockstore_db::{columns as cf, LedgerColumn},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
},
|
},
|
||||||
solana_runtime::bank::RewardType,
|
solana_runtime::bank::RewardType,
|
||||||
solana_sdk::{clock::Slot, pubkey},
|
solana_sdk::{clock::Slot, pubkey},
|
||||||
|
@ -86,22 +86,22 @@ fn bench_read_rewards<F, G>(
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_serialize_write_bincode(bencher: &mut Bencher) {
|
fn bench_serialize_write_bincode(bencher: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
bench_write_rewards(bencher, &ledger_path, write_bincode_rewards);
|
bench_write_rewards(bencher, ledger_path.path(), write_bincode_rewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_serialize_write_protobuf(bencher: &mut Bencher) {
|
fn bench_serialize_write_protobuf(bencher: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
bench_write_rewards(bencher, &ledger_path, write_protobuf_rewards);
|
bench_write_rewards(bencher, ledger_path.path(), write_protobuf_rewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_read_bincode(bencher: &mut Bencher) {
|
fn bench_read_bincode(bencher: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
bench_read_rewards(
|
bench_read_rewards(
|
||||||
bencher,
|
bencher,
|
||||||
&ledger_path,
|
ledger_path.path(),
|
||||||
write_bincode_rewards,
|
write_bincode_rewards,
|
||||||
read_bincode_rewards,
|
read_bincode_rewards,
|
||||||
);
|
);
|
||||||
|
@ -109,10 +109,10 @@ fn bench_read_bincode(bencher: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_read_protobuf(bencher: &mut Bencher) {
|
fn bench_read_protobuf(bencher: &mut Bencher) {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
bench_read_rewards(
|
bench_read_rewards(
|
||||||
bencher,
|
bencher,
|
||||||
&ledger_path,
|
ledger_path.path(),
|
||||||
write_protobuf_rewards,
|
write_protobuf_rewards,
|
||||||
read_protobuf_rewards,
|
read_protobuf_rewards,
|
||||||
);
|
);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -385,7 +385,7 @@ mod tests {
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
blockstore::Blockstore,
|
blockstore::Blockstore,
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
leader_schedule_cache::LeaderScheduleCache,
|
leader_schedule_cache::LeaderScheduleCache,
|
||||||
},
|
},
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
|
@ -404,171 +404,168 @@ mod tests {
|
||||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2);
|
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2);
|
||||||
let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config));
|
let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config));
|
||||||
let prev_hash = bank.last_blockhash();
|
let prev_hash = bank.last_blockhash();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path())
|
||||||
let blockstore = Blockstore::open(&ledger_path)
|
.expect("Expected to be able to open database ledger");
|
||||||
.expect("Expected to be able to open database ledger");
|
|
||||||
|
|
||||||
let default_target_tick_duration =
|
let default_target_tick_duration =
|
||||||
timing::duration_as_us(&PohConfig::default().target_tick_duration);
|
timing::duration_as_us(&PohConfig::default().target_tick_duration);
|
||||||
let target_tick_duration = Duration::from_micros(default_target_tick_duration);
|
let target_tick_duration = Duration::from_micros(default_target_tick_duration);
|
||||||
let poh_config = PohConfig {
|
let poh_config = PohConfig {
|
||||||
hashes_per_tick: Some(clock::DEFAULT_HASHES_PER_TICK),
|
hashes_per_tick: Some(clock::DEFAULT_HASHES_PER_TICK),
|
||||||
target_tick_duration,
|
target_tick_duration,
|
||||||
target_tick_count: None,
|
target_tick_count: None,
|
||||||
};
|
};
|
||||||
let exit = Arc::new(AtomicBool::new(false));
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
let ticks_per_slot = bank.ticks_per_slot();
|
let ticks_per_slot = bank.ticks_per_slot();
|
||||||
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
||||||
let blockstore = Arc::new(blockstore);
|
let blockstore = Arc::new(blockstore);
|
||||||
let (poh_recorder, entry_receiver, record_receiver) = PohRecorder::new(
|
let (poh_recorder, entry_receiver, record_receiver) = PohRecorder::new(
|
||||||
bank.tick_height(),
|
bank.tick_height(),
|
||||||
prev_hash,
|
prev_hash,
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
Some((4, 4)),
|
Some((4, 4)),
|
||||||
ticks_per_slot,
|
ticks_per_slot,
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
blockstore,
|
blockstore,
|
||||||
&leader_schedule_cache,
|
&leader_schedule_cache,
|
||||||
&poh_config,
|
&poh_config,
|
||||||
exit.clone(),
|
exit.clone(),
|
||||||
);
|
);
|
||||||
let poh_recorder = Arc::new(RwLock::new(poh_recorder));
|
let poh_recorder = Arc::new(RwLock::new(poh_recorder));
|
||||||
let ticks_per_slot = bank.ticks_per_slot();
|
let ticks_per_slot = bank.ticks_per_slot();
|
||||||
let bank_slot = bank.slot();
|
let bank_slot = bank.slot();
|
||||||
|
|
||||||
// specify RUN_TIME to run in a benchmark-like mode
|
// specify RUN_TIME to run in a benchmark-like mode
|
||||||
// to calibrate batch size
|
// to calibrate batch size
|
||||||
let run_time = std::env::var("RUN_TIME")
|
let run_time = std::env::var("RUN_TIME")
|
||||||
.map(|x| x.parse().unwrap())
|
.map(|x| x.parse().unwrap())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let is_test_run = run_time == 0;
|
let is_test_run = run_time == 0;
|
||||||
|
|
||||||
let entry_producer = {
|
let entry_producer = {
|
||||||
let poh_recorder = poh_recorder.clone();
|
let poh_recorder = poh_recorder.clone();
|
||||||
let exit = exit.clone();
|
let exit = exit.clone();
|
||||||
|
|
||||||
Builder::new()
|
Builder::new()
|
||||||
.name("solPohEntryProd".to_string())
|
.name("solPohEntryProd".to_string())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let mut total_us = 0;
|
let mut total_us = 0;
|
||||||
let mut total_times = 0;
|
let mut total_times = 0;
|
||||||
let h1 = hash(b"hello world!");
|
let h1 = hash(b"hello world!");
|
||||||
let tx = VersionedTransaction::from(test_tx());
|
let tx = VersionedTransaction::from(test_tx());
|
||||||
loop {
|
loop {
|
||||||
// send some data
|
// send some data
|
||||||
let mut time = Measure::start("record");
|
let mut time = Measure::start("record");
|
||||||
let _ = poh_recorder.write().unwrap().record(
|
let _ =
|
||||||
bank_slot,
|
poh_recorder
|
||||||
h1,
|
.write()
|
||||||
vec![tx.clone()],
|
.unwrap()
|
||||||
);
|
.record(bank_slot, h1, vec![tx.clone()]);
|
||||||
time.stop();
|
time.stop();
|
||||||
total_us += time.as_us();
|
total_us += time.as_us();
|
||||||
total_times += 1;
|
total_times += 1;
|
||||||
if is_test_run && thread_rng().gen_ratio(1, 4) {
|
if is_test_run && thread_rng().gen_ratio(1, 4) {
|
||||||
sleep(Duration::from_millis(200));
|
sleep(Duration::from_millis(200));
|
||||||
}
|
|
||||||
|
|
||||||
if exit.load(Ordering::Relaxed) {
|
|
||||||
info!(
|
|
||||||
"spent:{}ms record: {}ms entries recorded: {}",
|
|
||||||
now.elapsed().as_millis(),
|
|
||||||
total_us / 1000,
|
|
||||||
total_times,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let hashes_per_batch = std::env::var("HASHES_PER_BATCH")
|
if exit.load(Ordering::Relaxed) {
|
||||||
.map(|x| x.parse().unwrap())
|
info!(
|
||||||
.unwrap_or(DEFAULT_HASHES_PER_BATCH);
|
"spent:{}ms record: {}ms entries recorded: {}",
|
||||||
let poh_service = PohService::new(
|
now.elapsed().as_millis(),
|
||||||
poh_recorder.clone(),
|
total_us / 1000,
|
||||||
&poh_config,
|
total_times,
|
||||||
exit.clone(),
|
);
|
||||||
0,
|
break;
|
||||||
DEFAULT_PINNED_CPU_CORE,
|
}
|
||||||
hashes_per_batch,
|
|
||||||
record_receiver,
|
|
||||||
);
|
|
||||||
poh_recorder.write().unwrap().set_bank_for_test(bank);
|
|
||||||
|
|
||||||
// get some events
|
|
||||||
let mut hashes = 0;
|
|
||||||
let mut need_tick = true;
|
|
||||||
let mut need_entry = true;
|
|
||||||
let mut need_partial = true;
|
|
||||||
let mut num_ticks = 0;
|
|
||||||
|
|
||||||
let time = Instant::now();
|
|
||||||
while run_time != 0 || need_tick || need_entry || need_partial {
|
|
||||||
let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap();
|
|
||||||
|
|
||||||
if entry.is_tick() {
|
|
||||||
num_ticks += 1;
|
|
||||||
assert!(
|
|
||||||
entry.num_hashes <= poh_config.hashes_per_tick.unwrap(),
|
|
||||||
"{} <= {}",
|
|
||||||
entry.num_hashes,
|
|
||||||
poh_config.hashes_per_tick.unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
if entry.num_hashes == poh_config.hashes_per_tick.unwrap() {
|
|
||||||
need_tick = false;
|
|
||||||
} else {
|
|
||||||
need_partial = false;
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
hashes += entry.num_hashes;
|
let hashes_per_batch = std::env::var("HASHES_PER_BATCH")
|
||||||
|
.map(|x| x.parse().unwrap())
|
||||||
|
.unwrap_or(DEFAULT_HASHES_PER_BATCH);
|
||||||
|
let poh_service = PohService::new(
|
||||||
|
poh_recorder.clone(),
|
||||||
|
&poh_config,
|
||||||
|
exit.clone(),
|
||||||
|
0,
|
||||||
|
DEFAULT_PINNED_CPU_CORE,
|
||||||
|
hashes_per_batch,
|
||||||
|
record_receiver,
|
||||||
|
);
|
||||||
|
poh_recorder.write().unwrap().set_bank_for_test(bank);
|
||||||
|
|
||||||
assert_eq!(hashes, poh_config.hashes_per_tick.unwrap());
|
// get some events
|
||||||
|
let mut hashes = 0;
|
||||||
|
let mut need_tick = true;
|
||||||
|
let mut need_entry = true;
|
||||||
|
let mut need_partial = true;
|
||||||
|
let mut num_ticks = 0;
|
||||||
|
|
||||||
hashes = 0;
|
let time = Instant::now();
|
||||||
|
while run_time != 0 || need_tick || need_entry || need_partial {
|
||||||
|
let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap();
|
||||||
|
|
||||||
|
if entry.is_tick() {
|
||||||
|
num_ticks += 1;
|
||||||
|
assert!(
|
||||||
|
entry.num_hashes <= poh_config.hashes_per_tick.unwrap(),
|
||||||
|
"{} <= {}",
|
||||||
|
entry.num_hashes,
|
||||||
|
poh_config.hashes_per_tick.unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
if entry.num_hashes == poh_config.hashes_per_tick.unwrap() {
|
||||||
|
need_tick = false;
|
||||||
} else {
|
} else {
|
||||||
assert!(entry.num_hashes >= 1);
|
need_partial = false;
|
||||||
need_entry = false;
|
|
||||||
hashes += entry.num_hashes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if run_time != 0 {
|
hashes += entry.num_hashes;
|
||||||
if time.elapsed().as_millis() > run_time {
|
|
||||||
break;
|
assert_eq!(hashes, poh_config.hashes_per_tick.unwrap());
|
||||||
}
|
|
||||||
} else {
|
hashes = 0;
|
||||||
assert!(
|
} else {
|
||||||
time.elapsed().as_secs() < 60,
|
assert!(entry.num_hashes >= 1);
|
||||||
"Test should not run for this long! {}s tick {} entry {} partial {}",
|
need_entry = false;
|
||||||
time.elapsed().as_secs(),
|
hashes += entry.num_hashes;
|
||||||
need_tick,
|
|
||||||
need_entry,
|
|
||||||
need_partial,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
info!(
|
|
||||||
"target_tick_duration: {} ticks_per_slot: {}",
|
|
||||||
poh_config.target_tick_duration.as_nanos(),
|
|
||||||
ticks_per_slot
|
|
||||||
);
|
|
||||||
let elapsed = time.elapsed();
|
|
||||||
info!(
|
|
||||||
"{} ticks in {}ms {}us/tick",
|
|
||||||
num_ticks,
|
|
||||||
elapsed.as_millis(),
|
|
||||||
elapsed.as_micros() / num_ticks
|
|
||||||
);
|
|
||||||
|
|
||||||
exit.store(true, Ordering::Relaxed);
|
if run_time != 0 {
|
||||||
poh_service.join().unwrap();
|
if time.elapsed().as_millis() > run_time {
|
||||||
entry_producer.join().unwrap();
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert!(
|
||||||
|
time.elapsed().as_secs() < 60,
|
||||||
|
"Test should not run for this long! {}s tick {} entry {} partial {}",
|
||||||
|
time.elapsed().as_secs(),
|
||||||
|
need_tick,
|
||||||
|
need_entry,
|
||||||
|
need_partial,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Blockstore::destroy(&ledger_path).unwrap();
|
info!(
|
||||||
|
"target_tick_duration: {} ticks_per_slot: {}",
|
||||||
|
poh_config.target_tick_duration.as_nanos(),
|
||||||
|
ticks_per_slot
|
||||||
|
);
|
||||||
|
let elapsed = time.elapsed();
|
||||||
|
info!(
|
||||||
|
"{} ticks in {}ms {}us/tick",
|
||||||
|
num_ticks,
|
||||||
|
elapsed.as_millis(),
|
||||||
|
elapsed.as_micros() / num_ticks
|
||||||
|
);
|
||||||
|
|
||||||
|
exit.store(true, Ordering::Relaxed);
|
||||||
|
poh_service.join().unwrap();
|
||||||
|
entry_producer.join().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,8 @@ mod test {
|
||||||
super::*,
|
super::*,
|
||||||
solana_gossip::contact_info::ContactInfo,
|
solana_gossip::contact_info::ContactInfo,
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
blockstore::Blockstore, get_tmp_ledger_path, leader_schedule_cache::LeaderScheduleCache,
|
blockstore::Blockstore, get_tmp_ledger_path_auto_delete,
|
||||||
|
leader_schedule_cache::LeaderScheduleCache,
|
||||||
},
|
},
|
||||||
solana_runtime::{
|
solana_runtime::{
|
||||||
bank::Bank,
|
bank::Bank,
|
||||||
|
@ -128,123 +129,120 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_leader_tpus() {
|
fn test_get_leader_tpus() {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
{
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Blockstore::open(&ledger_path).unwrap();
|
|
||||||
|
|
||||||
let validator_vote_keypairs0 = ValidatorVoteKeypairs::new_rand();
|
let validator_vote_keypairs0 = ValidatorVoteKeypairs::new_rand();
|
||||||
let validator_vote_keypairs1 = ValidatorVoteKeypairs::new_rand();
|
let validator_vote_keypairs1 = ValidatorVoteKeypairs::new_rand();
|
||||||
let validator_vote_keypairs2 = ValidatorVoteKeypairs::new_rand();
|
let validator_vote_keypairs2 = ValidatorVoteKeypairs::new_rand();
|
||||||
let validator_keypairs = vec![
|
let validator_keypairs = vec![
|
||||||
&validator_vote_keypairs0,
|
&validator_vote_keypairs0,
|
||||||
&validator_vote_keypairs1,
|
&validator_vote_keypairs1,
|
||||||
&validator_vote_keypairs2,
|
&validator_vote_keypairs2,
|
||||||
];
|
];
|
||||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config_with_vote_accounts(
|
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config_with_vote_accounts(
|
||||||
1_000_000_000,
|
1_000_000_000,
|
||||||
&validator_keypairs,
|
&validator_keypairs,
|
||||||
vec![10_000; 3],
|
vec![10_000; 3],
|
||||||
);
|
);
|
||||||
let bank = Arc::new(Bank::new_for_tests(&genesis_config));
|
let bank = Arc::new(Bank::new_for_tests(&genesis_config));
|
||||||
|
|
||||||
let (poh_recorder, _entry_receiver, _record_receiver) = PohRecorder::new(
|
let (poh_recorder, _entry_receiver, _record_receiver) = PohRecorder::new(
|
||||||
0,
|
0,
|
||||||
bank.last_blockhash(),
|
bank.last_blockhash(),
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
Some((2, 2)),
|
Some((2, 2)),
|
||||||
bank.ticks_per_slot(),
|
bank.ticks_per_slot(),
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
Arc::new(blockstore),
|
Arc::new(blockstore),
|
||||||
&Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
|
&Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
|
||||||
&PohConfig::default(),
|
&PohConfig::default(),
|
||||||
Arc::new(AtomicBool::default()),
|
Arc::new(AtomicBool::default()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let node_keypair = Arc::new(Keypair::new());
|
let node_keypair = Arc::new(Keypair::new());
|
||||||
let cluster_info = Arc::new(ClusterInfo::new(
|
let cluster_info = Arc::new(ClusterInfo::new(
|
||||||
ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
|
ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
|
||||||
node_keypair,
|
node_keypair,
|
||||||
SocketAddrSpace::Unspecified,
|
SocketAddrSpace::Unspecified,
|
||||||
));
|
));
|
||||||
|
|
||||||
let validator0_socket = (
|
let validator0_socket = (
|
||||||
SocketAddr::from((Ipv4Addr::LOCALHOST, 1111)),
|
SocketAddr::from((Ipv4Addr::LOCALHOST, 1111)),
|
||||||
SocketAddr::from((Ipv4Addr::LOCALHOST, 1111 + QUIC_PORT_OFFSET)),
|
SocketAddr::from((Ipv4Addr::LOCALHOST, 1111 + QUIC_PORT_OFFSET)),
|
||||||
);
|
);
|
||||||
let validator1_socket = (
|
let validator1_socket = (
|
||||||
SocketAddr::from((Ipv4Addr::LOCALHOST, 2222)),
|
SocketAddr::from((Ipv4Addr::LOCALHOST, 2222)),
|
||||||
SocketAddr::from((Ipv4Addr::LOCALHOST, 2222 + QUIC_PORT_OFFSET)),
|
SocketAddr::from((Ipv4Addr::LOCALHOST, 2222 + QUIC_PORT_OFFSET)),
|
||||||
);
|
);
|
||||||
let validator2_socket = (
|
let validator2_socket = (
|
||||||
SocketAddr::from((Ipv4Addr::LOCALHOST, 3333)),
|
SocketAddr::from((Ipv4Addr::LOCALHOST, 3333)),
|
||||||
SocketAddr::from((Ipv4Addr::LOCALHOST, 3333 + QUIC_PORT_OFFSET)),
|
SocketAddr::from((Ipv4Addr::LOCALHOST, 3333 + QUIC_PORT_OFFSET)),
|
||||||
);
|
);
|
||||||
let recent_peers: HashMap<_, _> = vec![
|
let recent_peers: HashMap<_, _> = vec![
|
||||||
(
|
(
|
||||||
validator_vote_keypairs0.node_keypair.pubkey(),
|
validator_vote_keypairs0.node_keypair.pubkey(),
|
||||||
validator0_socket,
|
validator0_socket,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
validator_vote_keypairs1.node_keypair.pubkey(),
|
validator_vote_keypairs1.node_keypair.pubkey(),
|
||||||
validator1_socket,
|
validator1_socket,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
validator_vote_keypairs2.node_keypair.pubkey(),
|
validator_vote_keypairs2.node_keypair.pubkey(),
|
||||||
validator2_socket,
|
validator2_socket,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
let leader_info = ClusterTpuInfo {
|
let leader_info = ClusterTpuInfo {
|
||||||
cluster_info,
|
cluster_info,
|
||||||
poh_recorder: Arc::new(RwLock::new(poh_recorder)),
|
poh_recorder: Arc::new(RwLock::new(poh_recorder)),
|
||||||
recent_peers: recent_peers.clone(),
|
recent_peers: recent_peers.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let slot = bank.slot();
|
let slot = bank.slot();
|
||||||
let first_leader =
|
let first_leader =
|
||||||
solana_ledger::leader_schedule_utils::slot_leader_at(slot, &bank).unwrap();
|
solana_ledger::leader_schedule_utils::slot_leader_at(slot, &bank).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
leader_info.get_leader_tpus(1, Protocol::UDP),
|
leader_info.get_leader_tpus(1, Protocol::UDP),
|
||||||
vec![&recent_peers.get(&first_leader).unwrap().0]
|
vec![&recent_peers.get(&first_leader).unwrap().0]
|
||||||
);
|
);
|
||||||
|
|
||||||
let second_leader = solana_ledger::leader_schedule_utils::slot_leader_at(
|
let second_leader = solana_ledger::leader_schedule_utils::slot_leader_at(
|
||||||
slot + NUM_CONSECUTIVE_LEADER_SLOTS,
|
slot + NUM_CONSECUTIVE_LEADER_SLOTS,
|
||||||
&bank,
|
&bank,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut expected_leader_sockets = vec![
|
let mut expected_leader_sockets = vec![
|
||||||
&recent_peers.get(&first_leader).unwrap().0,
|
&recent_peers.get(&first_leader).unwrap().0,
|
||||||
&recent_peers.get(&second_leader).unwrap().0,
|
&recent_peers.get(&second_leader).unwrap().0,
|
||||||
];
|
];
|
||||||
expected_leader_sockets.dedup();
|
expected_leader_sockets.dedup();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
leader_info.get_leader_tpus(2, Protocol::UDP),
|
leader_info.get_leader_tpus(2, Protocol::UDP),
|
||||||
expected_leader_sockets
|
expected_leader_sockets
|
||||||
);
|
);
|
||||||
|
|
||||||
let third_leader = solana_ledger::leader_schedule_utils::slot_leader_at(
|
let third_leader = solana_ledger::leader_schedule_utils::slot_leader_at(
|
||||||
slot + (2 * NUM_CONSECUTIVE_LEADER_SLOTS),
|
slot + (2 * NUM_CONSECUTIVE_LEADER_SLOTS),
|
||||||
&bank,
|
&bank,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut expected_leader_sockets = vec![
|
let mut expected_leader_sockets = vec![
|
||||||
&recent_peers.get(&first_leader).unwrap().0,
|
&recent_peers.get(&first_leader).unwrap().0,
|
||||||
&recent_peers.get(&second_leader).unwrap().0,
|
&recent_peers.get(&second_leader).unwrap().0,
|
||||||
&recent_peers.get(&third_leader).unwrap().0,
|
&recent_peers.get(&third_leader).unwrap().0,
|
||||||
];
|
];
|
||||||
expected_leader_sockets.dedup();
|
expected_leader_sockets.dedup();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
leader_info.get_leader_tpus(3, Protocol::UDP),
|
leader_info.get_leader_tpus(3, Protocol::UDP),
|
||||||
expected_leader_sockets
|
expected_leader_sockets
|
||||||
);
|
);
|
||||||
|
|
||||||
for x in 4..8 {
|
for x in 4..8 {
|
||||||
assert!(leader_info.get_leader_tpus(x, Protocol::UDP).len() <= recent_peers.len());
|
assert!(leader_info.get_leader_tpus(x, Protocol::UDP).len() <= recent_peers.len());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Blockstore::destroy(&ledger_path).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -586,7 +586,7 @@ mod tests {
|
||||||
crate::rpc::{create_validator_exit, tests::new_test_cluster_info},
|
crate::rpc::{create_validator_exit, tests::new_test_cluster_info},
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
},
|
},
|
||||||
solana_rpc_client_api::config::RpcContextConfig,
|
solana_rpc_client_api::config::RpcContextConfig,
|
||||||
solana_runtime::bank::Bank,
|
solana_runtime::bank::Bank,
|
||||||
|
@ -618,8 +618,8 @@ 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)));
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
||||||
let optimistically_confirmed_bank =
|
let optimistically_confirmed_bank =
|
||||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||||
|
@ -719,8 +719,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_file_get_path() {
|
fn test_is_file_get_path() {
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let bank_forks = create_bank_forks();
|
let bank_forks = create_bank_forks();
|
||||||
let optimistically_confirmed_bank =
|
let optimistically_confirmed_bank =
|
||||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||||
|
@ -728,13 +728,13 @@ mod tests {
|
||||||
|
|
||||||
let bank_forks = create_bank_forks();
|
let bank_forks = create_bank_forks();
|
||||||
let rrm = RpcRequestMiddleware::new(
|
let rrm = RpcRequestMiddleware::new(
|
||||||
ledger_path.clone(),
|
ledger_path.path().to_path_buf(),
|
||||||
None,
|
None,
|
||||||
bank_forks.clone(),
|
bank_forks.clone(),
|
||||||
health.clone(),
|
health.clone(),
|
||||||
);
|
);
|
||||||
let rrm_with_snapshot_config = RpcRequestMiddleware::new(
|
let rrm_with_snapshot_config = RpcRequestMiddleware::new(
|
||||||
ledger_path.clone(),
|
ledger_path.path().to_path_buf(),
|
||||||
Some(SnapshotConfig::default()),
|
Some(SnapshotConfig::default()),
|
||||||
bank_forks,
|
bank_forks,
|
||||||
health,
|
health,
|
||||||
|
@ -829,15 +829,14 @@ mod tests {
|
||||||
fn test_process_file_get() {
|
fn test_process_file_get() {
|
||||||
let runtime = Runtime::new().unwrap();
|
let runtime = Runtime::new().unwrap();
|
||||||
|
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let genesis_path = ledger_path.join(DEFAULT_GENESIS_ARCHIVE);
|
let genesis_path = ledger_path.path().join(DEFAULT_GENESIS_ARCHIVE);
|
||||||
let bank_forks = create_bank_forks();
|
let bank_forks = create_bank_forks();
|
||||||
let optimistically_confirmed_bank =
|
let optimistically_confirmed_bank =
|
||||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||||
|
|
||||||
let rrm = RpcRequestMiddleware::new(
|
let rrm = RpcRequestMiddleware::new(
|
||||||
ledger_path.clone(),
|
ledger_path.path().to_path_buf(),
|
||||||
None,
|
None,
|
||||||
bank_forks,
|
bank_forks,
|
||||||
RpcHealth::stub(optimistically_confirmed_bank, blockstore),
|
RpcHealth::stub(optimistically_confirmed_bank, blockstore),
|
||||||
|
@ -872,7 +871,7 @@ mod tests {
|
||||||
{
|
{
|
||||||
std::fs::remove_file(&genesis_path).unwrap();
|
std::fs::remove_file(&genesis_path).unwrap();
|
||||||
{
|
{
|
||||||
let mut file = std::fs::File::create(ledger_path.join("wrong")).unwrap();
|
let mut file = std::fs::File::create(ledger_path.path().join("wrong")).unwrap();
|
||||||
file.write_all(b"wrong file").unwrap();
|
file.write_all(b"wrong file").unwrap();
|
||||||
}
|
}
|
||||||
symlink::symlink_file("wrong", &genesis_path).unwrap();
|
symlink::symlink_file("wrong", &genesis_path).unwrap();
|
||||||
|
|
|
@ -1259,6 +1259,7 @@ pub(crate) mod tests {
|
||||||
rpc_pubsub_service,
|
rpc_pubsub_service,
|
||||||
},
|
},
|
||||||
serial_test::serial,
|
serial_test::serial,
|
||||||
|
solana_ledger::get_tmp_ledger_path_auto_delete,
|
||||||
solana_rpc_client_api::config::{
|
solana_rpc_client_api::config::{
|
||||||
RpcAccountInfoConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter,
|
RpcAccountInfoConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter,
|
||||||
RpcProgramAccountsConfig, RpcSignatureSubscribeConfig, RpcTransactionLogsConfig,
|
RpcProgramAccountsConfig, RpcSignatureSubscribeConfig, RpcTransactionLogsConfig,
|
||||||
|
@ -1473,8 +1474,8 @@ pub(crate) mod tests {
|
||||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||||
let optimistically_confirmed_bank =
|
let optimistically_confirmed_bank =
|
||||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Blockstore::open(&ledger_path).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Arc::new(blockstore);
|
let blockstore = Arc::new(blockstore);
|
||||||
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
||||||
let max_complete_rewards_slot = Arc::new(AtomicU64::default());
|
let max_complete_rewards_slot = Arc::new(AtomicU64::default());
|
||||||
|
@ -1593,8 +1594,8 @@ pub(crate) mod tests {
|
||||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||||
let optimistically_confirmed_bank =
|
let optimistically_confirmed_bank =
|
||||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Blockstore::open(&ledger_path).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Arc::new(blockstore);
|
let blockstore = Arc::new(blockstore);
|
||||||
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
||||||
let max_complete_rewards_slot = Arc::new(AtomicU64::default());
|
let max_complete_rewards_slot = Arc::new(AtomicU64::default());
|
||||||
|
@ -1711,8 +1712,8 @@ pub(crate) mod tests {
|
||||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||||
let optimistically_confirmed_bank =
|
let optimistically_confirmed_bank =
|
||||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Blockstore::open(&ledger_path).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
let blockstore = Arc::new(blockstore);
|
let blockstore = Arc::new(blockstore);
|
||||||
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
||||||
let max_complete_rewards_slot = Arc::new(AtomicU64::default());
|
let max_complete_rewards_slot = Arc::new(AtomicU64::default());
|
||||||
|
|
|
@ -230,7 +230,7 @@ pub(crate) mod tests {
|
||||||
nonce_info::{NonceFull, NoncePartial},
|
nonce_info::{NonceFull, NoncePartial},
|
||||||
rent_debits::RentDebits,
|
rent_debits::RentDebits,
|
||||||
},
|
},
|
||||||
solana_ledger::{genesis_utils::create_genesis_config, get_tmp_ledger_path},
|
solana_ledger::{genesis_utils::create_genesis_config, get_tmp_ledger_path_auto_delete},
|
||||||
solana_runtime::bank::{Bank, TransactionBalancesSet},
|
solana_runtime::bank::{Bank, TransactionBalancesSet},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
|
@ -339,9 +339,9 @@ pub(crate) mod tests {
|
||||||
let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config));
|
let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config));
|
||||||
|
|
||||||
let (transaction_status_sender, transaction_status_receiver) = unbounded();
|
let (transaction_status_sender, transaction_status_receiver) = unbounded();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore =
|
let blockstore = Blockstore::open(ledger_path.path())
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger");
|
.expect("Expected to be able to open database ledger");
|
||||||
let blockstore = Arc::new(blockstore);
|
let blockstore = Arc::new(blockstore);
|
||||||
|
|
||||||
let transaction = build_test_transaction_legacy();
|
let transaction = build_test_transaction_legacy();
|
||||||
|
|
|
@ -505,7 +505,7 @@ pub mod test {
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
blockstore::Blockstore,
|
blockstore::Blockstore,
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path_auto_delete,
|
||||||
shred::{max_ticks_per_n_shreds, ProcessShredsStats, ReedSolomonCache, Shredder},
|
shred::{max_ticks_per_n_shreds, ProcessShredsStats, ReedSolomonCache, Shredder},
|
||||||
},
|
},
|
||||||
solana_runtime::bank::Bank,
|
solana_runtime::bank::Bank,
|
||||||
|
@ -590,8 +590,8 @@ pub mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_duplicate_retransmit_signal() {
|
fn test_duplicate_retransmit_signal() {
|
||||||
// Setup
|
// Setup
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
|
||||||
let (transmit_sender, transmit_receiver) = unbounded();
|
let (transmit_sender, transmit_receiver) = unbounded();
|
||||||
let (retransmit_slots_sender, retransmit_slots_receiver) = unbounded();
|
let (retransmit_slots_sender, retransmit_slots_receiver) = unbounded();
|
||||||
|
|
||||||
|
@ -694,66 +694,62 @@ pub mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_broadcast_ledger() {
|
fn test_broadcast_ledger() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
|
|
||||||
|
// Create the leader scheduler
|
||||||
|
let leader_keypair = Arc::new(Keypair::new());
|
||||||
|
|
||||||
|
let (entry_sender, entry_receiver) = unbounded();
|
||||||
|
let (retransmit_slots_sender, retransmit_slots_receiver) = unbounded();
|
||||||
|
let broadcast_service = setup_dummy_broadcast_service(
|
||||||
|
leader_keypair,
|
||||||
|
ledger_path.path(),
|
||||||
|
entry_receiver,
|
||||||
|
retransmit_slots_receiver,
|
||||||
|
);
|
||||||
|
let start_tick_height;
|
||||||
|
let max_tick_height;
|
||||||
|
let ticks_per_slot;
|
||||||
|
let slot;
|
||||||
{
|
{
|
||||||
// Create the leader scheduler
|
let bank = broadcast_service.bank;
|
||||||
let leader_keypair = Arc::new(Keypair::new());
|
start_tick_height = bank.tick_height();
|
||||||
|
max_tick_height = bank.max_tick_height();
|
||||||
let (entry_sender, entry_receiver) = unbounded();
|
ticks_per_slot = bank.ticks_per_slot();
|
||||||
let (retransmit_slots_sender, retransmit_slots_receiver) = unbounded();
|
slot = bank.slot();
|
||||||
let broadcast_service = setup_dummy_broadcast_service(
|
let ticks = create_ticks(max_tick_height - start_tick_height, 0, Hash::default());
|
||||||
leader_keypair,
|
for (i, tick) in ticks.into_iter().enumerate() {
|
||||||
&ledger_path,
|
entry_sender
|
||||||
entry_receiver,
|
.send((bank.clone(), (tick, i as u64 + 1)))
|
||||||
retransmit_slots_receiver,
|
.expect("Expect successful send to broadcast service");
|
||||||
);
|
|
||||||
let start_tick_height;
|
|
||||||
let max_tick_height;
|
|
||||||
let ticks_per_slot;
|
|
||||||
let slot;
|
|
||||||
{
|
|
||||||
let bank = broadcast_service.bank;
|
|
||||||
start_tick_height = bank.tick_height();
|
|
||||||
max_tick_height = bank.max_tick_height();
|
|
||||||
ticks_per_slot = bank.ticks_per_slot();
|
|
||||||
slot = bank.slot();
|
|
||||||
let ticks = create_ticks(max_tick_height - start_tick_height, 0, Hash::default());
|
|
||||||
for (i, tick) in ticks.into_iter().enumerate() {
|
|
||||||
entry_sender
|
|
||||||
.send((bank.clone(), (tick, i as u64 + 1)))
|
|
||||||
.expect("Expect successful send to broadcast service");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(
|
|
||||||
"[broadcast_ledger] max_tick_height: {}, start_tick_height: {}, ticks_per_slot: {}",
|
|
||||||
max_tick_height,
|
|
||||||
start_tick_height,
|
|
||||||
ticks_per_slot,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut entries = vec![];
|
|
||||||
for _ in 0..10 {
|
|
||||||
entries = broadcast_service
|
|
||||||
.blockstore
|
|
||||||
.get_slot_entries(slot, 0)
|
|
||||||
.expect("Expect entries to be present");
|
|
||||||
if entries.len() >= max_tick_height as usize {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sleep(Duration::from_millis(1000));
|
|
||||||
}
|
|
||||||
assert_eq!(entries.len(), max_tick_height as usize);
|
|
||||||
|
|
||||||
drop(entry_sender);
|
|
||||||
drop(retransmit_slots_sender);
|
|
||||||
broadcast_service
|
|
||||||
.broadcast_service
|
|
||||||
.join()
|
|
||||||
.expect("Expect successful join of broadcast service");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
|
trace!(
|
||||||
|
"[broadcast_ledger] max_tick_height: {}, start_tick_height: {}, ticks_per_slot: {}",
|
||||||
|
max_tick_height,
|
||||||
|
start_tick_height,
|
||||||
|
ticks_per_slot,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut entries = vec![];
|
||||||
|
for _ in 0..10 {
|
||||||
|
entries = broadcast_service
|
||||||
|
.blockstore
|
||||||
|
.get_slot_entries(slot, 0)
|
||||||
|
.expect("Expect entries to be present");
|
||||||
|
if entries.len() >= max_tick_height as usize {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(1000));
|
||||||
|
}
|
||||||
|
assert_eq!(entries.len(), max_tick_height as usize);
|
||||||
|
|
||||||
|
drop(entry_sender);
|
||||||
|
drop(retransmit_slots_sender);
|
||||||
|
broadcast_service
|
||||||
|
.broadcast_service
|
||||||
|
.join()
|
||||||
|
.expect("Expect successful join of broadcast service");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,7 +503,7 @@ mod test {
|
||||||
solana_gossip::cluster_info::{ClusterInfo, Node},
|
solana_gossip::cluster_info::{ClusterInfo, Node},
|
||||||
solana_ledger::{
|
solana_ledger::{
|
||||||
blockstore::Blockstore, genesis_utils::create_genesis_config, get_tmp_ledger_path,
|
blockstore::Blockstore, genesis_utils::create_genesis_config, get_tmp_ledger_path,
|
||||||
shred::max_ticks_per_n_shreds,
|
get_tmp_ledger_path_auto_delete, shred::max_ticks_per_n_shreds,
|
||||||
},
|
},
|
||||||
solana_runtime::bank::Bank,
|
solana_runtime::bank::Bank,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -815,9 +815,10 @@ mod test {
|
||||||
bs.current_slot_and_parent = Some((1, 0));
|
bs.current_slot_and_parent = Some((1, 0));
|
||||||
let entries = create_ticks(10_000, 1, solana_sdk::hash::Hash::default());
|
let entries = create_ticks(10_000, 1, solana_sdk::hash::Hash::default());
|
||||||
|
|
||||||
let ledger_path = get_tmp_ledger_path!();
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||||
let blockstore = Arc::new(
|
let blockstore = Arc::new(
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
Blockstore::open(ledger_path.path())
|
||||||
|
.expect("Expected to be able to open database ledger"),
|
||||||
);
|
);
|
||||||
let mut stats = ProcessShredsStats::default();
|
let mut stats = ProcessShredsStats::default();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue