Add a version field to shreds (#7023)
* Add a version field to shreds * Clippy * Fix Chacha Golden * Fix shredder bench compile * Fix blocktree bench compile
This commit is contained in:
parent
bfa2535ea1
commit
6bfe0fca1f
|
@ -21,7 +21,7 @@ fn bench_write_shreds(bench: &mut Bencher, entries: Vec<Entry>, ledger_path: &Pa
|
|||
let blocktree =
|
||||
Blocktree::open(ledger_path).expect("Expected to be able to open database ledger");
|
||||
bench.iter(move || {
|
||||
let shreds = entries_to_test_shreds(entries.clone(), 0, 0, true);
|
||||
let shreds = entries_to_test_shreds(entries.clone(), 0, 0, true, 0);
|
||||
blocktree.insert_shreds(shreds, None, false).unwrap();
|
||||
});
|
||||
|
||||
|
@ -43,7 +43,7 @@ fn setup_read_bench(
|
|||
);
|
||||
|
||||
// Convert the entries to shreds, write the shreds to the ledger
|
||||
let shreds = entries_to_test_shreds(entries, slot, slot.saturating_sub(1), true);
|
||||
let shreds = entries_to_test_shreds(entries, slot, slot.saturating_sub(1), true, 0);
|
||||
blocktree
|
||||
.insert_shreds(shreds, None, false)
|
||||
.expect("Expectd successful insertion of shreds into ledger");
|
||||
|
@ -136,7 +136,7 @@ fn bench_insert_data_shred_small(bench: &mut Bencher) {
|
|||
let num_entries = 32 * 1024;
|
||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||
bench.iter(move || {
|
||||
let shreds = entries_to_test_shreds(entries.clone(), 0, 0, true);
|
||||
let shreds = entries_to_test_shreds(entries.clone(), 0, 0, true, 0);
|
||||
blocktree.insert_shreds(shreds, None, false).unwrap();
|
||||
});
|
||||
Blocktree::destroy(&ledger_path).expect("Expected successful database destruction");
|
||||
|
@ -151,7 +151,7 @@ fn bench_insert_data_shred_big(bench: &mut Bencher) {
|
|||
let num_entries = 32 * 1024;
|
||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||
bench.iter(move || {
|
||||
let shreds = entries_to_test_shreds(entries.clone(), 0, 0, true);
|
||||
let shreds = entries_to_test_shreds(entries.clone(), 0, 0, true, 0);
|
||||
blocktree.insert_shreds(shreds, None, false).unwrap();
|
||||
});
|
||||
Blocktree::destroy(&ledger_path).expect("Expected successful database destruction");
|
||||
|
|
|
@ -35,7 +35,7 @@ fn bench_shredder_ticks(bencher: &mut Bencher) {
|
|||
let num_ticks = max_ticks_per_n_shreds(1) * num_shreds as u64;
|
||||
let entries = create_ticks(num_ticks, 0, Hash::default());
|
||||
bencher.iter(|| {
|
||||
let shredder = Shredder::new(1, 0, RECOMMENDED_FEC_RATE, kp.clone(), 0).unwrap();
|
||||
let shredder = Shredder::new(1, 0, RECOMMENDED_FEC_RATE, kp.clone(), 0, 0).unwrap();
|
||||
shredder.entries_to_shreds(&entries, true, 0);
|
||||
})
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ fn bench_shredder_large_entries(bencher: &mut Bencher) {
|
|||
let entries = make_large_unchained_entries(txs_per_entry, num_entries);
|
||||
// 1Mb
|
||||
bencher.iter(|| {
|
||||
let shredder = Shredder::new(1, 0, RECOMMENDED_FEC_RATE, kp.clone(), 0).unwrap();
|
||||
let shredder = Shredder::new(1, 0, RECOMMENDED_FEC_RATE, kp.clone(), 0, 0).unwrap();
|
||||
shredder.entries_to_shreds(&entries, true, 0);
|
||||
})
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ fn bench_deshredder(bencher: &mut Bencher) {
|
|||
let num_shreds = ((10000 * 1000) + (shred_size - 1)) / shred_size;
|
||||
let num_ticks = max_ticks_per_n_shreds(1) * num_shreds as u64;
|
||||
let entries = create_ticks(num_ticks, 0, Hash::default());
|
||||
let shredder = Shredder::new(1, 0, RECOMMENDED_FEC_RATE, kp, 0).unwrap();
|
||||
let shredder = Shredder::new(1, 0, RECOMMENDED_FEC_RATE, kp, 0, 0).unwrap();
|
||||
let data_shreds = shredder.entries_to_shreds(&entries, true, 0).0;
|
||||
bencher.iter(|| {
|
||||
let raw = &mut Shredder::deshred(&data_shreds).unwrap();
|
||||
|
@ -75,7 +75,7 @@ fn bench_deshredder(bencher: &mut Bencher) {
|
|||
fn bench_deserialize_hdr(bencher: &mut Bencher) {
|
||||
let data = vec![0; SIZE_OF_DATA_SHRED_PAYLOAD];
|
||||
|
||||
let shred = Shred::new_from_data(2, 1, 1, Some(&data), true, true, 0);
|
||||
let shred = Shred::new_from_data(2, 1, 1, Some(&data), true, true, 0, 0);
|
||||
|
||||
bencher.iter(|| {
|
||||
let payload = shred.payload.clone();
|
||||
|
|
|
@ -153,6 +153,7 @@ mod test {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ impl BroadcastStageType {
|
|||
receiver: Receiver<WorkingBankEntry>,
|
||||
exit_sender: &Arc<AtomicBool>,
|
||||
blocktree: &Arc<Blocktree>,
|
||||
shred_version: u16,
|
||||
) -> BroadcastStage {
|
||||
match self {
|
||||
BroadcastStageType::Standard => {
|
||||
|
@ -52,7 +53,7 @@ impl BroadcastStageType {
|
|||
receiver,
|
||||
exit_sender,
|
||||
blocktree,
|
||||
StandardBroadcastRun::new(keypair),
|
||||
StandardBroadcastRun::new(keypair, shred_version),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ impl BroadcastStageType {
|
|||
receiver,
|
||||
exit_sender,
|
||||
blocktree,
|
||||
FailEntryVerificationBroadcastRun::new(),
|
||||
FailEntryVerificationBroadcastRun::new(shred_version),
|
||||
),
|
||||
|
||||
BroadcastStageType::BroadcastFakeShreds => BroadcastStage::new(
|
||||
|
@ -71,7 +72,7 @@ impl BroadcastStageType {
|
|||
receiver,
|
||||
exit_sender,
|
||||
blocktree,
|
||||
BroadcastFakeShredsRun::new(0),
|
||||
BroadcastFakeShredsRun::new(0, shred_version),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +241,7 @@ mod test {
|
|||
entry_receiver,
|
||||
&exit_sender,
|
||||
&blocktree,
|
||||
StandardBroadcastRun::new(leader_keypair),
|
||||
StandardBroadcastRun::new(leader_keypair, 0),
|
||||
);
|
||||
|
||||
MockBroadcastStage {
|
||||
|
|
|
@ -6,13 +6,15 @@ use solana_sdk::hash::Hash;
|
|||
pub(super) struct BroadcastFakeShredsRun {
|
||||
last_blockhash: Hash,
|
||||
partition: usize,
|
||||
shred_version: u16,
|
||||
}
|
||||
|
||||
impl BroadcastFakeShredsRun {
|
||||
pub(super) fn new(partition: usize) -> Self {
|
||||
pub(super) fn new(partition: usize, shred_version: u16) -> Self {
|
||||
Self {
|
||||
last_blockhash: Hash::default(),
|
||||
partition,
|
||||
shred_version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +47,7 @@ impl BroadcastRun for BroadcastFakeShredsRun {
|
|||
RECOMMENDED_FEC_RATE,
|
||||
keypair.clone(),
|
||||
(bank.tick_height() % bank.ticks_per_slot()) as u8,
|
||||
self.shred_version,
|
||||
)
|
||||
.expect("Expected to create a new shredder");
|
||||
|
||||
|
|
|
@ -2,11 +2,13 @@ use super::*;
|
|||
use solana_ledger::shred::{Shredder, RECOMMENDED_FEC_RATE};
|
||||
use solana_sdk::hash::Hash;
|
||||
|
||||
pub(super) struct FailEntryVerificationBroadcastRun {}
|
||||
pub(super) struct FailEntryVerificationBroadcastRun {
|
||||
shred_version: u16,
|
||||
}
|
||||
|
||||
impl FailEntryVerificationBroadcastRun {
|
||||
pub(super) fn new() -> Self {
|
||||
Self {}
|
||||
pub(super) fn new(shred_version: u16) -> Self {
|
||||
Self { shred_version }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +45,7 @@ impl BroadcastRun for FailEntryVerificationBroadcastRun {
|
|||
RECOMMENDED_FEC_RATE,
|
||||
keypair.clone(),
|
||||
(bank.tick_height() % bank.ticks_per_slot()) as u8,
|
||||
self.shred_version,
|
||||
)
|
||||
.expect("Expected to create a new shredder");
|
||||
|
||||
|
|
|
@ -35,16 +35,18 @@ pub(super) struct StandardBroadcastRun {
|
|||
current_slot_and_parent: Option<(u64, u64)>,
|
||||
slot_broadcast_start: Option<Instant>,
|
||||
keypair: Arc<Keypair>,
|
||||
shred_version: u16,
|
||||
}
|
||||
|
||||
impl StandardBroadcastRun {
|
||||
pub(super) fn new(keypair: Arc<Keypair>) -> Self {
|
||||
pub(super) fn new(keypair: Arc<Keypair>, shred_version: u16) -> Self {
|
||||
Self {
|
||||
stats: BroadcastStats::default(),
|
||||
unfinished_slot: None,
|
||||
current_slot_and_parent: None,
|
||||
slot_broadcast_start: None,
|
||||
keypair,
|
||||
shred_version,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,6 +65,7 @@ impl StandardBroadcastRun {
|
|||
true,
|
||||
true,
|
||||
max_ticks_in_slot & SHRED_TICK_REFERENCE_MASK,
|
||||
self.shred_version,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
@ -93,6 +96,7 @@ impl StandardBroadcastRun {
|
|||
RECOMMENDED_FEC_RATE,
|
||||
self.keypair.clone(),
|
||||
reference_tick,
|
||||
self.shred_version,
|
||||
)
|
||||
.expect("Expected to create a new shredder");
|
||||
|
||||
|
@ -350,7 +354,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_interrupted_slot_last_shred() {
|
||||
let keypair = Arc::new(Keypair::new());
|
||||
let mut run = StandardBroadcastRun::new(keypair.clone());
|
||||
let mut run = StandardBroadcastRun::new(keypair.clone(), 0);
|
||||
|
||||
// Set up the slot to be interrupted
|
||||
let next_shred_index = 10;
|
||||
|
@ -396,7 +400,7 @@ mod test {
|
|||
};
|
||||
|
||||
// Step 1: Make an incomplete transmission for slot 0
|
||||
let mut standard_broadcast_run = StandardBroadcastRun::new(leader_keypair.clone());
|
||||
let mut standard_broadcast_run = StandardBroadcastRun::new(leader_keypair.clone(), 0);
|
||||
standard_broadcast_run
|
||||
.process_receive_results(&cluster_info, &socket, &blocktree, receive_results)
|
||||
.unwrap();
|
||||
|
@ -472,7 +476,7 @@ mod test {
|
|||
last_tick_height: ticks.len() as u64,
|
||||
};
|
||||
|
||||
let mut standard_broadcast_run = StandardBroadcastRun::new(leader_keypair);
|
||||
let mut standard_broadcast_run = StandardBroadcastRun::new(leader_keypair, 0);
|
||||
standard_broadcast_run
|
||||
.process_receive_results(&cluster_info, &socket, &blocktree, receive_results)
|
||||
.unwrap();
|
||||
|
|
|
@ -149,6 +149,7 @@ mod tests {
|
|||
true,
|
||||
&Arc::new(keypair),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -165,7 +166,7 @@ mod tests {
|
|||
hasher.hash(&buf[..size]);
|
||||
|
||||
// golden needs to be updated if shred structure changes....
|
||||
let golden: Hash = "HLzH7Nrh4q2K5WTh3e9vPNFZ1QVYhVDRMN9u5v51GqpJ"
|
||||
let golden: Hash = "9K6NR4cazo7Jzk2CpyXmNaZMGqvfXG83JzyJipkoHare"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -146,6 +146,7 @@ mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -206,6 +207,7 @@ mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -1151,7 +1151,7 @@ mod test {
|
|||
), // should cause AccountNotFound error
|
||||
],
|
||||
);
|
||||
entries_to_test_shreds(vec![entry], slot, slot.saturating_sub(1), false)
|
||||
entries_to_test_shreds(vec![entry], slot, slot.saturating_sub(1), false, 0)
|
||||
});
|
||||
|
||||
assert_matches!(
|
||||
|
@ -1179,7 +1179,7 @@ mod test {
|
|||
blockhash,
|
||||
)],
|
||||
);
|
||||
entries_to_test_shreds(vec![entry], slot, slot.saturating_sub(1), false)
|
||||
entries_to_test_shreds(vec![entry], slot, slot.saturating_sub(1), false, 0)
|
||||
});
|
||||
|
||||
if let Err(Error::BlockError(block_error)) = res {
|
||||
|
@ -1203,6 +1203,7 @@ mod test {
|
|||
slot,
|
||||
slot.saturating_sub(1),
|
||||
false,
|
||||
0,
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -1225,6 +1226,7 @@ mod test {
|
|||
slot,
|
||||
slot.saturating_sub(1),
|
||||
false,
|
||||
0,
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -1244,6 +1246,7 @@ mod test {
|
|||
slot,
|
||||
slot.saturating_sub(1),
|
||||
true,
|
||||
0,
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -1265,6 +1268,7 @@ mod test {
|
|||
slot,
|
||||
slot.saturating_sub(1),
|
||||
false,
|
||||
0,
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -1289,7 +1293,7 @@ mod test {
|
|||
system_transaction::transfer(&genesis_keypair, &keypair.pubkey(), 2, blockhash);
|
||||
let trailing_entry = entry::next_entry(&last_entry_hash, 1, vec![tx]);
|
||||
entries.push(trailing_entry);
|
||||
entries_to_test_shreds(entries, slot, slot.saturating_sub(1), true)
|
||||
entries_to_test_shreds(entries, slot, slot.saturating_sub(1), true, 0)
|
||||
});
|
||||
|
||||
if let Err(Error::BlockError(block_error)) = res {
|
||||
|
|
|
@ -213,6 +213,7 @@ impl RetransmitStage {
|
|||
completed_slots_receiver: CompletedSlotsReceiver,
|
||||
epoch_schedule: EpochSchedule,
|
||||
cfg: Option<PartitionCfg>,
|
||||
shred_version: u16,
|
||||
) -> Self {
|
||||
let (retransmit_sender, retransmit_receiver) = channel();
|
||||
|
||||
|
@ -251,6 +252,7 @@ impl RetransmitStage {
|
|||
&leader_schedule_cache,
|
||||
id,
|
||||
last_root,
|
||||
shred_version,
|
||||
);
|
||||
rv && is_connected
|
||||
},
|
||||
|
|
|
@ -91,6 +91,7 @@ pub mod tests {
|
|||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
let mut batch = [Packets::default(), Packets::default()];
|
||||
|
||||
|
@ -108,6 +109,7 @@ pub mod tests {
|
|||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
Shredder::sign_shred(&keypair, &mut shred);
|
||||
batch[1].packets.resize(1, Packet::default());
|
||||
|
@ -131,12 +133,14 @@ pub mod tests {
|
|||
let mut batch = vec![Packets::default()];
|
||||
batch[0].packets.resize(2, Packet::default());
|
||||
|
||||
let mut shred = Shred::new_from_data(0, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0);
|
||||
let mut shred =
|
||||
Shred::new_from_data(0, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0, 0);
|
||||
Shredder::sign_shred(&leader_keypair, &mut shred);
|
||||
batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
|
||||
batch[0].packets[0].meta.size = shred.payload.len();
|
||||
|
||||
let mut shred = Shred::new_from_data(0, 0xbeef, 0xc0de, Some(&[1, 2, 3, 4]), true, true, 0);
|
||||
let mut shred =
|
||||
Shred::new_from_data(0, 0xbeef, 0xc0de, Some(&[1, 2, 3, 4]), true, true, 0, 0);
|
||||
let wrong_keypair = Keypair::new();
|
||||
Shredder::sign_shred(&wrong_keypair, &mut shred);
|
||||
batch[0].packets[1].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
|
||||
|
|
|
@ -38,6 +38,7 @@ impl Tpu {
|
|||
blocktree: &Arc<Blocktree>,
|
||||
broadcast_type: &BroadcastStageType,
|
||||
exit: &Arc<AtomicBool>,
|
||||
shred_version: u16,
|
||||
) -> Self {
|
||||
let (packet_sender, packet_receiver) = channel();
|
||||
let fetch_stage = FetchStage::new_with_sender(
|
||||
|
@ -79,6 +80,7 @@ impl Tpu {
|
|||
entry_receiver,
|
||||
&exit,
|
||||
blocktree,
|
||||
shred_version,
|
||||
);
|
||||
|
||||
Self {
|
||||
|
|
|
@ -74,6 +74,7 @@ impl Tvu {
|
|||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||
sigverify_disabled: bool,
|
||||
cfg: Option<PartitionCfg>,
|
||||
shred_version: u16,
|
||||
) -> Self
|
||||
where
|
||||
T: 'static + KeypairUtil + Sync + Send,
|
||||
|
@ -132,6 +133,7 @@ impl Tvu {
|
|||
completed_slots_receiver,
|
||||
*bank_forks.read().unwrap().working_bank().epoch_schedule(),
|
||||
cfg,
|
||||
shred_version,
|
||||
);
|
||||
|
||||
let (blockstream_slot_sender, blockstream_slot_receiver) = channel();
|
||||
|
@ -294,6 +296,7 @@ pub mod tests {
|
|||
block_commitment_cache,
|
||||
false,
|
||||
None,
|
||||
0,
|
||||
);
|
||||
exit.store(true, Ordering::Relaxed);
|
||||
tvu.join().unwrap();
|
||||
|
|
|
@ -37,6 +37,7 @@ use solana_sdk::{
|
|||
timing::timestamp,
|
||||
};
|
||||
|
||||
use solana_ledger::shred::Shred;
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||
path::{Path, PathBuf},
|
||||
|
@ -184,6 +185,8 @@ impl Validator {
|
|||
let bank = bank_forks[bank_info.bank_slot].clone();
|
||||
let bank_forks = Arc::new(RwLock::new(bank_forks));
|
||||
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
||||
// The version used by shreds, derived from genesis
|
||||
let shred_version = Shred::version_from_hash(&genesis_hash);
|
||||
|
||||
let mut validator_exit = ValidatorExit::default();
|
||||
let exit_ = exit.clone();
|
||||
|
@ -346,6 +349,7 @@ impl Validator {
|
|||
block_commitment_cache,
|
||||
config.dev_sigverify_disabled,
|
||||
config.partition_cfg.clone(),
|
||||
shred_version,
|
||||
);
|
||||
|
||||
if config.dev_sigverify_disabled {
|
||||
|
@ -363,6 +367,7 @@ impl Validator {
|
|||
&blocktree,
|
||||
&config.broadcast_stage_type,
|
||||
&exit,
|
||||
shred_version,
|
||||
);
|
||||
|
||||
datapoint_info!("validator-new", ("id", id.to_string(), String));
|
||||
|
|
|
@ -42,6 +42,7 @@ pub fn should_retransmit_and_persist(
|
|||
leader_schedule_cache: &Arc<LeaderScheduleCache>,
|
||||
my_pubkey: &Pubkey,
|
||||
root: u64,
|
||||
shred_version: u16,
|
||||
) -> bool {
|
||||
let slot_leader_pubkey = match bank {
|
||||
None => leader_schedule_cache.slot_leader_at(shred.slot(), None),
|
||||
|
@ -54,6 +55,9 @@ pub fn should_retransmit_and_persist(
|
|||
} else if !verify_shred_slot(shred, root) {
|
||||
inc_new_counter_debug!("streamer-recv_window-outdated_transmission", 1);
|
||||
false
|
||||
} else if shred.version() != shred_version {
|
||||
inc_new_counter_debug!("streamer-recv_window-incorrect_shred_version", 1);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -309,7 +313,7 @@ mod test {
|
|||
parent: Slot,
|
||||
keypair: &Arc<Keypair>,
|
||||
) -> Vec<Shred> {
|
||||
let shredder = Shredder::new(slot, parent, 0.0, keypair.clone(), 0)
|
||||
let shredder = Shredder::new(slot, parent, 0.0, keypair.clone(), 0, 0)
|
||||
.expect("Failed to create entry shredder");
|
||||
shredder.entries_to_shreds(&entries, true, 0).0
|
||||
}
|
||||
|
@ -349,32 +353,37 @@ mod test {
|
|||
|
||||
// with a Bank for slot 0, shred continues
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, 0,),
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, 0, 0),
|
||||
true
|
||||
);
|
||||
// with the wrong shred_version, shred gets thrown out
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, 0, 1),
|
||||
false
|
||||
);
|
||||
|
||||
// If it's a coding shred, test that slot >= root
|
||||
let (common, coding) = Shredder::new_coding_shred_header(5, 5, 6, 6, 0);
|
||||
let (common, coding) = Shredder::new_coding_shred_header(5, 5, 6, 6, 0, 0);
|
||||
let mut coding_shred =
|
||||
Shred::new_empty_from_header(common, DataShredHeader::default(), coding);
|
||||
Shredder::sign_shred(&leader_keypair, &mut coding_shred);
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&coding_shred, Some(bank.clone()), &cache, &me_id, 0),
|
||||
should_retransmit_and_persist(&coding_shred, Some(bank.clone()), &cache, &me_id, 0, 0),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&coding_shred, Some(bank.clone()), &cache, &me_id, 5),
|
||||
should_retransmit_and_persist(&coding_shred, Some(bank.clone()), &cache, &me_id, 5, 0),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&coding_shred, Some(bank.clone()), &cache, &me_id, 6),
|
||||
should_retransmit_and_persist(&coding_shred, Some(bank.clone()), &cache, &me_id, 6, 0),
|
||||
false
|
||||
);
|
||||
|
||||
// with a Bank and no idea who leader is, shred gets thrown out
|
||||
shreds[0].set_slot(MINIMUM_SLOTS_PER_EPOCH as u64 * 3);
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, 0),
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, 0, 0),
|
||||
false
|
||||
);
|
||||
|
||||
|
@ -382,7 +391,7 @@ mod test {
|
|||
let slot = MINIMUM_SLOTS_PER_EPOCH as u64 * 3;
|
||||
let shreds = local_entries_to_shred(&[Entry::default()], slot, slot - 1, &leader_keypair);
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, slot),
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, slot, 0),
|
||||
false
|
||||
);
|
||||
|
||||
|
@ -391,13 +400,13 @@ mod test {
|
|||
let shreds =
|
||||
local_entries_to_shred(&[Entry::default()], slot + 1, slot - 1, &leader_keypair);
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, slot),
|
||||
should_retransmit_and_persist(&shreds[0], Some(bank.clone()), &cache, &me_id, slot, 0),
|
||||
false
|
||||
);
|
||||
|
||||
// if the shred came back from me, it doesn't continue, whether or not I have a bank
|
||||
assert_eq!(
|
||||
should_retransmit_and_persist(&shreds[0], None, &cache, &me_id, 0),
|
||||
should_retransmit_and_persist(&shreds[0], None, &cache, &me_id, 0, 0),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
|
|
@ -941,6 +941,8 @@ impl Blocktree {
|
|||
self.code_shred_cf.get_bytes((slot, index))
|
||||
}
|
||||
|
||||
// Only used by tests
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn write_entries(
|
||||
&self,
|
||||
start_slot: Slot,
|
||||
|
@ -951,6 +953,7 @@ impl Blocktree {
|
|||
is_full_slot: bool,
|
||||
keypair: &Arc<Keypair>,
|
||||
entries: Vec<Entry>,
|
||||
version: u16,
|
||||
) -> Result<usize> {
|
||||
let mut parent_slot = parent.map_or(start_slot.saturating_sub(1), |v| v);
|
||||
let num_slots = (start_slot - parent_slot).max(1); // Note: slot 0 has parent slot 0
|
||||
|
@ -958,8 +961,9 @@ impl Blocktree {
|
|||
let mut remaining_ticks_in_slot = num_slots * ticks_per_slot - num_ticks_in_start_slot;
|
||||
|
||||
let mut current_slot = start_slot;
|
||||
let mut shredder = Shredder::new(current_slot, parent_slot, 0.0, keypair.clone(), 0)
|
||||
.expect("Failed to create entry shredder");
|
||||
let mut shredder =
|
||||
Shredder::new(current_slot, parent_slot, 0.0, keypair.clone(), 0, version)
|
||||
.expect("Failed to create entry shredder");
|
||||
let mut all_shreds = vec![];
|
||||
let mut slot_entries = vec![];
|
||||
// Find all the entries for start_slot
|
||||
|
@ -987,6 +991,7 @@ impl Blocktree {
|
|||
0.0,
|
||||
keypair.clone(),
|
||||
(ticks_per_slot - remaining_ticks_in_slot) as u8,
|
||||
version,
|
||||
)
|
||||
.expect("Failed to create entry shredder");
|
||||
}
|
||||
|
@ -1833,8 +1838,9 @@ pub fn create_new_ledger(ledger_path: &Path, genesis_config: &GenesisConfig) ->
|
|||
let hashes_per_tick = genesis_config.poh_config.hashes_per_tick.unwrap_or(0);
|
||||
let entries = create_ticks(ticks_per_slot, hashes_per_tick, genesis_config.hash());
|
||||
let last_hash = entries.last().unwrap().hash;
|
||||
let version = Shred::version_from_hash(&last_hash);
|
||||
|
||||
let shredder = Shredder::new(0, 0, 0.0, Arc::new(Keypair::new()), 0)
|
||||
let shredder = Shredder::new(0, 0, 0.0, Arc::new(Keypair::new()), 0, version)
|
||||
.expect("Failed to create entry shredder");
|
||||
let shreds = shredder.entries_to_shreds(&entries, true, 0).0;
|
||||
assert!(shreds.last().unwrap().last_in_slot());
|
||||
|
@ -1918,8 +1924,9 @@ pub fn entries_to_test_shreds(
|
|||
slot: Slot,
|
||||
parent_slot: Slot,
|
||||
is_full_slot: bool,
|
||||
version: u16,
|
||||
) -> Vec<Shred> {
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, Arc::new(Keypair::new()), 0)
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, Arc::new(Keypair::new()), 0, version)
|
||||
.expect("Failed to create entry shredder");
|
||||
|
||||
shredder.entries_to_shreds(&entries, is_full_slot, 0).0
|
||||
|
@ -1932,7 +1939,7 @@ pub fn make_slot_entries(
|
|||
num_entries: u64,
|
||||
) -> (Vec<Shred>, Vec<Entry>) {
|
||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||
let shreds = entries_to_test_shreds(entries.clone(), slot, parent_slot, true);
|
||||
let shreds = entries_to_test_shreds(entries.clone(), slot, parent_slot, true, 0);
|
||||
(shreds, entries)
|
||||
}
|
||||
|
||||
|
@ -2056,7 +2063,7 @@ pub mod tests {
|
|||
let mut tick = create_ticks(1, 0, Hash::default());
|
||||
entries.append(&mut tick);
|
||||
}
|
||||
let shreds = entries_to_test_shreds(entries.clone(), slot, parent_slot, true);
|
||||
let shreds = entries_to_test_shreds(entries.clone(), slot, parent_slot, true, 0);
|
||||
(shreds, entries)
|
||||
}
|
||||
|
||||
|
@ -2132,6 +2139,7 @@ pub mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
new_ticks.clone(),
|
||||
0,
|
||||
)
|
||||
.unwrap() as u64;
|
||||
shreds_per_slot.push(num_shreds);
|
||||
|
@ -2452,12 +2460,12 @@ pub mod tests {
|
|||
{
|
||||
let blocktree = Blocktree::open(&blocktree_path).unwrap();
|
||||
let entries = create_ticks(8, 0, Hash::default());
|
||||
let shreds = entries_to_test_shreds(entries[0..4].to_vec(), 1, 0, false);
|
||||
let shreds = entries_to_test_shreds(entries[0..4].to_vec(), 1, 0, false, 0);
|
||||
blocktree
|
||||
.insert_shreds(shreds, None, false)
|
||||
.expect("Expected successful write of shreds");
|
||||
|
||||
let mut shreds1 = entries_to_test_shreds(entries[4..].to_vec(), 1, 0, false);
|
||||
let mut shreds1 = entries_to_test_shreds(entries[4..].to_vec(), 1, 0, false, 0);
|
||||
for (i, b) in shreds1.iter_mut().enumerate() {
|
||||
b.set_index(8 + i as u32);
|
||||
}
|
||||
|
@ -2489,7 +2497,7 @@ pub mod tests {
|
|||
let entries = create_ticks(slot + 1, 0, Hash::default());
|
||||
let last_entry = entries.last().unwrap().clone();
|
||||
let mut shreds =
|
||||
entries_to_test_shreds(entries, slot, slot.saturating_sub(1), false);
|
||||
entries_to_test_shreds(entries, slot, slot.saturating_sub(1), false, 0);
|
||||
for b in shreds.iter_mut() {
|
||||
b.set_index(index);
|
||||
b.set_slot(slot as u64);
|
||||
|
@ -2526,7 +2534,7 @@ pub mod tests {
|
|||
for slot in 0..num_slots {
|
||||
let entries = create_ticks(entries_per_slot, 0, Hash::default());
|
||||
let shreds =
|
||||
entries_to_test_shreds(entries.clone(), slot, slot.saturating_sub(1), false);
|
||||
entries_to_test_shreds(entries.clone(), slot, slot.saturating_sub(1), false, 0);
|
||||
assert!(shreds.len() as u64 >= shreds_per_slot);
|
||||
blocktree
|
||||
.insert_shreds(shreds, None, false)
|
||||
|
@ -2621,7 +2629,7 @@ pub mod tests {
|
|||
|
||||
assert_eq!(blocktree.get_slot_entries(0, 0, None).unwrap(), vec![]);
|
||||
|
||||
let duplicate_shreds = entries_to_test_shreds(original_entries.clone(), 0, 0, true);
|
||||
let duplicate_shreds = entries_to_test_shreds(original_entries.clone(), 0, 0, true, 0);
|
||||
let num_shreds = duplicate_shreds.len() as u64;
|
||||
blocktree
|
||||
.insert_shreds(duplicate_shreds, None, false)
|
||||
|
@ -3328,7 +3336,7 @@ pub mod tests {
|
|||
// Create enough entries to ensure there are at least two shreds created
|
||||
let num_entries = max_ticks_per_n_shreds(1) + 1;
|
||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||
let mut shreds = entries_to_test_shreds(entries, slot, 0, true);
|
||||
let mut shreds = entries_to_test_shreds(entries, slot, 0, true, 0);
|
||||
let num_shreds = shreds.len();
|
||||
assert!(num_shreds > 1);
|
||||
for (i, s) in shreds.iter_mut().enumerate() {
|
||||
|
@ -3415,7 +3423,9 @@ pub mod tests {
|
|||
// Write entries
|
||||
let gap: u64 = 10;
|
||||
let shreds: Vec<_> = (0..64)
|
||||
.map(|i| Shred::new_from_data(slot, (i * gap) as u32, 0, None, false, false, i as u8))
|
||||
.map(|i| {
|
||||
Shred::new_from_data(slot, (i * gap) as u32, 0, None, false, false, i as u8, 0)
|
||||
})
|
||||
.collect();
|
||||
blocktree.insert_shreds(shreds, None, false).unwrap();
|
||||
|
||||
|
@ -3449,7 +3459,7 @@ pub mod tests {
|
|||
assert_eq!(blocktree.find_missing_data_indexes(slot, 0, 1, 2, 0), empty);
|
||||
|
||||
let entries = create_ticks(100, 0, Hash::default());
|
||||
let mut shreds = entries_to_test_shreds(entries, slot, 0, true);
|
||||
let mut shreds = entries_to_test_shreds(entries, slot, 0, true, 0);
|
||||
assert!(shreds.len() > 2);
|
||||
shreds.drain(2..);
|
||||
|
||||
|
@ -3491,7 +3501,7 @@ pub mod tests {
|
|||
// Write entries
|
||||
let num_entries = 10;
|
||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||
let shreds = entries_to_test_shreds(entries, slot, 0, true);
|
||||
let shreds = entries_to_test_shreds(entries, slot, 0, true, 0);
|
||||
let num_shreds = shreds.len();
|
||||
|
||||
blocktree.insert_shreds(shreds, None, false).unwrap();
|
||||
|
@ -3605,7 +3615,7 @@ pub mod tests {
|
|||
let last_root = RwLock::new(0);
|
||||
|
||||
let slot = 1;
|
||||
let (mut shred, coding) = Shredder::new_coding_shred_header(slot, 11, 11, 11, 10);
|
||||
let (mut shred, coding) = Shredder::new_coding_shred_header(slot, 11, 11, 11, 10, 0);
|
||||
let coding_shred = Shred::new_empty_from_header(
|
||||
shred.clone(),
|
||||
DataShredHeader::default(),
|
||||
|
@ -4008,7 +4018,7 @@ pub mod tests {
|
|||
let num_ticks = 8;
|
||||
let entries = create_ticks(num_ticks, 0, Hash::default());
|
||||
let slot = 1;
|
||||
let shreds = entries_to_test_shreds(entries, slot, 0, false);
|
||||
let shreds = entries_to_test_shreds(entries, slot, 0, false, 0);
|
||||
let next_shred_index = shreds.len();
|
||||
blocktree
|
||||
.insert_shreds(shreds, None, false)
|
||||
|
@ -4027,6 +4037,7 @@ pub mod tests {
|
|||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
)];
|
||||
|
||||
// With the corruption, nothing should be returned, even though an
|
||||
|
|
|
@ -532,6 +532,7 @@ pub fn fill_blocktree_slot_with_ticks(
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -587,6 +588,7 @@ pub mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.expect("Expected to write shredded entries to blocktree");
|
||||
|
||||
|
@ -627,6 +629,7 @@ pub mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.expect("Expected to write shredded entries to blocktree");
|
||||
|
||||
|
@ -678,6 +681,7 @@ pub mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.expect("Expected to write shredded entries to blocktree");
|
||||
|
||||
|
@ -740,6 +744,7 @@ pub mod tests {
|
|||
false,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.expect("Expected to write shredded entries to blocktree");
|
||||
}
|
||||
|
@ -1151,6 +1156,7 @@ pub mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
let opts = ProcessOptions {
|
||||
|
@ -1261,6 +1267,7 @@ pub mod tests {
|
|||
true,
|
||||
&Arc::new(Keypair::new()),
|
||||
entries,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ use std::{sync::Arc, time::Instant};
|
|||
/// The following constants are computed by hand, and hardcoded.
|
||||
/// `test_shred_constants` ensures that the values are correct.
|
||||
/// Constants are used over lazy_static for performance reasons.
|
||||
pub const SIZE_OF_COMMON_SHRED_HEADER: usize = 77;
|
||||
pub const SIZE_OF_COMMON_SHRED_HEADER: usize = 79;
|
||||
pub const SIZE_OF_DATA_SHRED_HEADER: usize = 3;
|
||||
pub const SIZE_OF_CODING_SHRED_HEADER: usize = 6;
|
||||
pub const SIZE_OF_SIGNATURE: usize = 64;
|
||||
|
@ -83,6 +83,7 @@ pub struct ShredCommonHeader {
|
|||
pub shred_type: ShredType,
|
||||
pub slot: Slot,
|
||||
pub index: u32,
|
||||
pub version: u16,
|
||||
}
|
||||
|
||||
/// The data shred header has parent offset and flags
|
||||
|
@ -142,15 +143,20 @@ impl Shred {
|
|||
is_last_data: bool,
|
||||
is_last_in_slot: bool,
|
||||
reference_tick: u8,
|
||||
version: u16,
|
||||
) -> Self {
|
||||
let mut payload = vec![0; PACKET_DATA_SIZE];
|
||||
let mut common_header = ShredCommonHeader::default();
|
||||
common_header.slot = slot;
|
||||
common_header.index = index;
|
||||
let common_header = ShredCommonHeader {
|
||||
slot,
|
||||
index,
|
||||
version,
|
||||
..ShredCommonHeader::default()
|
||||
};
|
||||
|
||||
let mut data_header = DataShredHeader::default();
|
||||
data_header.parent_offset = parent_offset;
|
||||
data_header.flags = reference_tick.min(SHRED_TICK_REFERENCE_MASK);
|
||||
let mut data_header = DataShredHeader {
|
||||
parent_offset,
|
||||
flags: reference_tick.min(SHRED_TICK_REFERENCE_MASK),
|
||||
};
|
||||
|
||||
if is_last_data {
|
||||
data_header.flags |= DATA_COMPLETE_SHRED
|
||||
|
@ -281,6 +287,10 @@ impl Shred {
|
|||
self.common_header.index
|
||||
}
|
||||
|
||||
pub fn version(&self) -> u16 {
|
||||
self.common_header.version
|
||||
}
|
||||
|
||||
pub fn set_index(&mut self, index: u32) {
|
||||
self.common_header.index = index;
|
||||
Self::serialize_obj_into(
|
||||
|
@ -363,12 +373,26 @@ impl Shred {
|
|||
self.signature()
|
||||
.verify(pubkey.as_ref(), &self.payload[SIZE_OF_SIGNATURE..])
|
||||
}
|
||||
|
||||
pub fn version_from_hash(hash: &Hash) -> u16 {
|
||||
let hash = hash.as_ref();
|
||||
let mut accum = [0u8; 2];
|
||||
hash.chunks(2).for_each(|seed| {
|
||||
accum
|
||||
.iter_mut()
|
||||
.zip(seed)
|
||||
.for_each(|(accum, seed)| *accum ^= *seed)
|
||||
});
|
||||
// convert accum into a u16
|
||||
((accum[0] as u16) << 8) | accum[1] as u16
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Shredder {
|
||||
slot: Slot,
|
||||
parent_slot: Slot,
|
||||
version: u16,
|
||||
fec_rate: f32,
|
||||
keypair: Arc<Keypair>,
|
||||
pub signing_coding_time: u128,
|
||||
|
@ -382,6 +406,7 @@ impl Shredder {
|
|||
fec_rate: f32,
|
||||
keypair: Arc<Keypair>,
|
||||
reference_tick: u8,
|
||||
version: u16,
|
||||
) -> Result<Self> {
|
||||
if fec_rate > 1.0 || fec_rate < 0.0 {
|
||||
Err(ShredError::InvalidFecRate(fec_rate))
|
||||
|
@ -395,6 +420,7 @@ impl Shredder {
|
|||
keypair,
|
||||
signing_coding_time: 0,
|
||||
reference_tick,
|
||||
version,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -441,6 +467,7 @@ impl Shredder {
|
|||
is_last_data,
|
||||
is_last_in_slot,
|
||||
self.reference_tick,
|
||||
self.version,
|
||||
);
|
||||
|
||||
Shredder::sign_shred(&self.keypair, &mut shred);
|
||||
|
@ -458,7 +485,12 @@ impl Shredder {
|
|||
data_shreds
|
||||
.par_chunks(MAX_DATA_SHREDS_PER_FEC_BLOCK as usize)
|
||||
.flat_map(|shred_data_batch| {
|
||||
Shredder::generate_coding_shreds(self.slot, self.fec_rate, shred_data_batch)
|
||||
Shredder::generate_coding_shreds(
|
||||
self.slot,
|
||||
self.fec_rate,
|
||||
shred_data_batch,
|
||||
self.version,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
|
@ -503,11 +535,15 @@ impl Shredder {
|
|||
num_data: usize,
|
||||
num_code: usize,
|
||||
position: usize,
|
||||
version: u16,
|
||||
) -> (ShredCommonHeader, CodingShredHeader) {
|
||||
let mut header = ShredCommonHeader::default();
|
||||
header.shred_type = ShredType(CODING_SHRED);
|
||||
header.index = index;
|
||||
header.slot = slot;
|
||||
let header = ShredCommonHeader {
|
||||
shred_type: ShredType(CODING_SHRED),
|
||||
index,
|
||||
slot,
|
||||
version,
|
||||
..ShredCommonHeader::default()
|
||||
};
|
||||
(
|
||||
header,
|
||||
CodingShredHeader {
|
||||
|
@ -523,6 +559,7 @@ impl Shredder {
|
|||
slot: Slot,
|
||||
fec_rate: f32,
|
||||
data_shred_batch: &[Shred],
|
||||
version: u16,
|
||||
) -> Vec<Shred> {
|
||||
assert!(!data_shred_batch.is_empty());
|
||||
if fec_rate != 0.0 {
|
||||
|
@ -549,6 +586,7 @@ impl Shredder {
|
|||
num_data,
|
||||
num_coding,
|
||||
i,
|
||||
version,
|
||||
);
|
||||
let shred =
|
||||
Shred::new_empty_from_header(header, DataShredHeader::default(), coding_header);
|
||||
|
@ -578,6 +616,7 @@ impl Shredder {
|
|||
num_data,
|
||||
num_coding,
|
||||
i,
|
||||
version,
|
||||
);
|
||||
Shred {
|
||||
common_header,
|
||||
|
@ -781,6 +820,7 @@ pub mod tests {
|
|||
use super::*;
|
||||
use bincode::serialized_size;
|
||||
use matches::assert_matches;
|
||||
use solana_sdk::hash::hash;
|
||||
use solana_sdk::system_transaction;
|
||||
use std::collections::HashSet;
|
||||
use std::convert::TryInto;
|
||||
|
@ -848,7 +888,7 @@ pub mod tests {
|
|||
|
||||
// Test that parent cannot be > current slot
|
||||
assert_matches!(
|
||||
Shredder::new(slot, slot + 1, 1.00, keypair.clone(), 0),
|
||||
Shredder::new(slot, slot + 1, 1.00, keypair.clone(), 0, 0),
|
||||
Err(ShredError::SlotTooLow {
|
||||
slot: _,
|
||||
parent_slot: _,
|
||||
|
@ -856,7 +896,7 @@ pub mod tests {
|
|||
);
|
||||
// Test that slot - parent cannot be > u16 MAX
|
||||
assert_matches!(
|
||||
Shredder::new(slot, slot - 1 - 0xffff, 1.00, keypair.clone(), 0),
|
||||
Shredder::new(slot, slot - 1 - 0xffff, 1.00, keypair.clone(), 0, 0),
|
||||
Err(ShredError::SlotTooLow {
|
||||
slot: _,
|
||||
parent_slot: _,
|
||||
|
@ -865,7 +905,7 @@ pub mod tests {
|
|||
|
||||
let fec_rate = 0.25;
|
||||
let parent_slot = slot - 5;
|
||||
let shredder = Shredder::new(slot, parent_slot, fec_rate, keypair.clone(), 0)
|
||||
let shredder = Shredder::new(slot, parent_slot, fec_rate, keypair.clone(), 0, 0)
|
||||
.expect("Failed in creating shredder");
|
||||
|
||||
let entries: Vec<_> = (0..5)
|
||||
|
@ -940,7 +980,7 @@ pub mod tests {
|
|||
let slot = 1;
|
||||
|
||||
let parent_slot = 0;
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, keypair.clone(), 0)
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, keypair.clone(), 0, 0)
|
||||
.expect("Failed in creating shredder");
|
||||
|
||||
let entries: Vec<_> = (0..5)
|
||||
|
@ -966,7 +1006,7 @@ pub mod tests {
|
|||
let slot = 1;
|
||||
|
||||
let parent_slot = 0;
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, keypair.clone(), 5)
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, keypair.clone(), 5, 0)
|
||||
.expect("Failed in creating shredder");
|
||||
|
||||
let entries: Vec<_> = (0..5)
|
||||
|
@ -996,7 +1036,7 @@ pub mod tests {
|
|||
let slot = 1;
|
||||
|
||||
let parent_slot = 0;
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, keypair.clone(), u8::max_value())
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, keypair.clone(), u8::max_value(), 0)
|
||||
.expect("Failed in creating shredder");
|
||||
|
||||
let entries: Vec<_> = (0..5)
|
||||
|
@ -1033,11 +1073,11 @@ pub mod tests {
|
|||
let slot = 0x123456789abcdef0;
|
||||
// Test that FEC rate cannot be > 1.0
|
||||
assert_matches!(
|
||||
Shredder::new(slot, slot - 5, 1.001, keypair.clone(), 0),
|
||||
Shredder::new(slot, slot - 5, 1.001, keypair.clone(), 0, 0),
|
||||
Err(ShredError::InvalidFecRate(_))
|
||||
);
|
||||
|
||||
let shredder = Shredder::new(0x123456789abcdef0, slot - 5, 1.0, keypair.clone(), 0)
|
||||
let shredder = Shredder::new(0x123456789abcdef0, slot - 5, 1.0, keypair.clone(), 0, 0)
|
||||
.expect("Failed in creating shredder");
|
||||
|
||||
// Create enough entries to make > 1 shred
|
||||
|
@ -1079,7 +1119,7 @@ pub mod tests {
|
|||
fn test_recovery_and_reassembly() {
|
||||
let keypair = Arc::new(Keypair::new());
|
||||
let slot = 0x123456789abcdef0;
|
||||
let shredder = Shredder::new(slot, slot - 5, 1.0, keypair.clone(), 0)
|
||||
let shredder = Shredder::new(slot, slot - 5, 1.0, keypair.clone(), 0, 0)
|
||||
.expect("Failed in creating shredder");
|
||||
|
||||
let keypair0 = Keypair::new();
|
||||
|
@ -1325,7 +1365,7 @@ pub mod tests {
|
|||
fn test_multi_fec_block_coding() {
|
||||
let keypair = Arc::new(Keypair::new());
|
||||
let slot = 0x123456789abcdef0;
|
||||
let shredder = Shredder::new(slot, slot - 5, 1.0, keypair.clone(), 0)
|
||||
let shredder = Shredder::new(slot, slot - 5, 1.0, keypair.clone(), 0, 0)
|
||||
.expect("Failed in creating shredder");
|
||||
|
||||
let num_fec_sets = 100;
|
||||
|
@ -1408,4 +1448,54 @@ pub mod tests {
|
|||
let result = Shredder::deshred(&all_shreds[..]).unwrap();
|
||||
assert_eq!(serialized_entries[..], result[..serialized_entries.len()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shred_version() {
|
||||
let keypair = Arc::new(Keypair::new());
|
||||
let hash = hash(Hash::default().as_ref());
|
||||
let version = Shred::version_from_hash(&hash);
|
||||
assert_ne!(version, 0);
|
||||
let shredder =
|
||||
Shredder::new(0, 0, 1.0, keypair, 0, version).expect("Failed in creating shredder");
|
||||
|
||||
let entries: Vec<_> = (0..5)
|
||||
.map(|_| {
|
||||
let keypair0 = Keypair::new();
|
||||
let keypair1 = Keypair::new();
|
||||
let tx0 =
|
||||
system_transaction::transfer(&keypair0, &keypair1.pubkey(), 1, Hash::default());
|
||||
Entry::new(&Hash::default(), 1, vec![tx0])
|
||||
})
|
||||
.collect();
|
||||
|
||||
let (data_shreds, coding_shreds, _next_index) =
|
||||
shredder.entries_to_shreds(&entries, true, 0);
|
||||
assert!(!data_shreds
|
||||
.iter()
|
||||
.chain(coding_shreds.iter())
|
||||
.any(|s| s.version() != version));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version_from_hash() {
|
||||
let hash = [
|
||||
0xa5u8, 0xa5, 0x5a, 0x5a, 0xa5, 0xa5, 0x5a, 0x5a, 0xa5, 0xa5, 0x5a, 0x5a, 0xa5, 0xa5,
|
||||
0x5a, 0x5a, 0xa5, 0xa5, 0x5a, 0x5a, 0xa5, 0xa5, 0x5a, 0x5a, 0xa5, 0xa5, 0x5a, 0x5a,
|
||||
0xa5, 0xa5, 0x5a, 0x5a,
|
||||
];
|
||||
let version = Shred::version_from_hash(&Hash::new(&hash));
|
||||
assert_eq!(version, 0);
|
||||
let hash = [
|
||||
0xa5u8, 0xa5, 0x5a, 0x5a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
];
|
||||
let version = Shred::version_from_hash(&Hash::new(&hash));
|
||||
assert_eq!(version, 0xffff);
|
||||
let hash = [
|
||||
0xa5u8, 0xa5, 0x5a, 0x5a, 0xa5, 0xa5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
];
|
||||
let version = Shred::version_from_hash(&Hash::new(&hash));
|
||||
assert_eq!(version, 0x5a5a);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -486,7 +486,7 @@ pub mod tests {
|
|||
let mut packet = Packet::default();
|
||||
let slot = 0xdeadc0de;
|
||||
let mut shred =
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0);
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0, 0);
|
||||
assert_eq!(shred.slot(), slot);
|
||||
let keypair = Keypair::new();
|
||||
Shredder::sign_shred(&keypair, &mut shred);
|
||||
|
@ -520,7 +520,7 @@ pub mod tests {
|
|||
let mut batch = [Packets::default()];
|
||||
let slot = 0xdeadc0de;
|
||||
let mut shred =
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0);
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0, 0);
|
||||
let keypair = Keypair::new();
|
||||
Shredder::sign_shred(&keypair, &mut shred);
|
||||
batch[0].packets.resize(1, Packet::default());
|
||||
|
@ -563,7 +563,7 @@ pub mod tests {
|
|||
let mut batch = [Packets::default()];
|
||||
let slot = 0xdeadc0de;
|
||||
let mut shred =
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0);
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0, 0);
|
||||
let keypair = Keypair::new();
|
||||
Shredder::sign_shred(&keypair, &mut shred);
|
||||
batch[0].packets.resize(1, Packet::default());
|
||||
|
@ -615,7 +615,8 @@ pub mod tests {
|
|||
let mut batch = [Packets::default()];
|
||||
let slot = 0xdeadc0de;
|
||||
let keypair = Keypair::new();
|
||||
let shred = Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0);
|
||||
let shred =
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0, 0);
|
||||
batch[0].packets.resize(1, Packet::default());
|
||||
batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
|
||||
batch[0].packets[0].meta.size = shred.payload.len();
|
||||
|
@ -652,7 +653,8 @@ pub mod tests {
|
|||
let mut batch = [Packets::default()];
|
||||
let slot = 0xdeadc0de;
|
||||
let keypair = Keypair::new();
|
||||
let shred = Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0);
|
||||
let shred =
|
||||
Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true, 0, 0);
|
||||
batch[0].packets.resize(1, Packet::default());
|
||||
batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
|
||||
batch[0].packets[0].meta.size = shred.payload.len();
|
||||
|
|
|
@ -20,7 +20,7 @@ fn test_multiple_threads_insert_shred() {
|
|||
let threads: Vec<_> = (0..num_threads)
|
||||
.map(|i| {
|
||||
let entries = entry::create_ticks(1, 0, Hash::default());
|
||||
let shreds = blocktree::entries_to_test_shreds(entries, i + 1, 0, false);
|
||||
let shreds = blocktree::entries_to_test_shreds(entries, i + 1, 0, false, 0);
|
||||
let blocktree_ = blocktree.clone();
|
||||
Builder::new()
|
||||
.name("blocktree-writer".to_string())
|
||||
|
|
Loading…
Reference in New Issue