replaces Shred::new_empty_coding with Shred::new_from_parity_shard (#24749)
Removing implementation details of shreds and payload offsets from shredder, so that shredder does not need to mutate payload: https://github.com/solana-labs/solana/blob/71ad12128/ledger/src/shred.rs#L968-L977 Also, Shred::new_from_data can simply obtain a slice as opposed to Option<&[u8]>: https://github.com/solana-labs/solana/blob/71ad12128/ledger/src/shred.rs#L268-L278
This commit is contained in:
parent
cdce19be29
commit
0f60665100
|
@ -51,7 +51,7 @@ fn broadcast_shreds_bench(bencher: &mut Bencher) {
|
||||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||||
|
|
||||||
const NUM_SHREDS: usize = 32;
|
const NUM_SHREDS: usize = 32;
|
||||||
let shred = Shred::new_from_data(0, 0, 0, None, false, false, 0, 0, 0);
|
let shred = Shred::new_from_data(0, 0, 0, &[], false, false, 0, 0, 0);
|
||||||
let shreds = vec![shred; NUM_SHREDS];
|
let shreds = vec![shred; NUM_SHREDS];
|
||||||
let mut stakes = HashMap::new();
|
let mut stakes = HashMap::new();
|
||||||
const NUM_PEERS: usize = 200;
|
const NUM_PEERS: usize = 200;
|
||||||
|
|
|
@ -39,7 +39,7 @@ fn get_retransmit_peers_deterministic(
|
||||||
let parent_offset = if slot == 0 { 0 } else { 1 };
|
let parent_offset = if slot == 0 { 0 } else { 1 };
|
||||||
for i in 0..num_simulated_shreds {
|
for i in 0..num_simulated_shreds {
|
||||||
let index = i as u32;
|
let index = i as u32;
|
||||||
let shred = Shred::new_from_data(slot, index, parent_offset, None, false, false, 0, 0, 0);
|
let shred = Shred::new_from_data(slot, index, parent_offset, &[], false, false, 0, 0, 0);
|
||||||
let (_neighbors, _children) = cluster_nodes.get_retransmit_peers(
|
let (_neighbors, _children) = cluster_nodes.get_retransmit_peers(
|
||||||
*slot_leader,
|
*slot_leader,
|
||||||
&shred,
|
&shred,
|
||||||
|
|
|
@ -123,7 +123,7 @@ fn bench_deshredder(bencher: &mut Bencher) {
|
||||||
fn bench_deserialize_hdr(bencher: &mut Bencher) {
|
fn bench_deserialize_hdr(bencher: &mut Bencher) {
|
||||||
let data = vec![0; SIZE_OF_DATA_SHRED_PAYLOAD];
|
let data = vec![0; SIZE_OF_DATA_SHRED_PAYLOAD];
|
||||||
|
|
||||||
let shred = Shred::new_from_data(2, 1, 1, Some(&data), true, true, 0, 0, 1);
|
let shred = Shred::new_from_data(2, 1, 1, &data, true, true, 0, 0, 1);
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
let payload = shred.payload().clone();
|
let payload = shred.payload().clone();
|
||||||
|
|
|
@ -76,7 +76,7 @@ impl StandardBroadcastRun {
|
||||||
state.slot,
|
state.slot,
|
||||||
state.next_shred_index,
|
state.next_shred_index,
|
||||||
parent_offset as u16,
|
parent_offset as u16,
|
||||||
None, // data
|
&[], // data
|
||||||
true, // is_last_in_fec_set
|
true, // is_last_in_fec_set
|
||||||
true, // is_last_in_slot
|
true, // is_last_in_slot
|
||||||
reference_tick,
|
reference_tick,
|
||||||
|
|
|
@ -107,7 +107,7 @@ pub(crate) mod tests {
|
||||||
let repair_type = ShredRepairType::Orphan(9);
|
let repair_type = ShredRepairType::Orphan(9);
|
||||||
let mut outstanding_requests = OutstandingRequests::default();
|
let mut outstanding_requests = OutstandingRequests::default();
|
||||||
let nonce = outstanding_requests.add_request(repair_type, timestamp());
|
let nonce = outstanding_requests.add_request(repair_type, timestamp());
|
||||||
let shred = Shred::new_from_data(0, 0, 0, None, false, false, 0, 0, 0);
|
let shred = Shred::new_from_data(0, 0, 0, &[], false, false, 0, 0, 0);
|
||||||
|
|
||||||
let expire_timestamp = outstanding_requests
|
let expire_timestamp = outstanding_requests
|
||||||
.requests
|
.requests
|
||||||
|
@ -127,7 +127,7 @@ pub(crate) mod tests {
|
||||||
let mut outstanding_requests = OutstandingRequests::default();
|
let mut outstanding_requests = OutstandingRequests::default();
|
||||||
let nonce = outstanding_requests.add_request(repair_type, timestamp());
|
let nonce = outstanding_requests.add_request(repair_type, timestamp());
|
||||||
|
|
||||||
let shred = Shred::new_from_data(0, 0, 0, None, false, false, 0, 0, 0);
|
let shred = Shred::new_from_data(0, 0, 0, &[], false, false, 0, 0, 0);
|
||||||
let mut expire_timestamp = outstanding_requests
|
let mut expire_timestamp = outstanding_requests
|
||||||
.requests
|
.requests
|
||||||
.get(&nonce)
|
.get(&nonce)
|
||||||
|
|
|
@ -69,7 +69,7 @@ mod test {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[1, 2, 3, 4]),
|
&[1, 2, 3, 4],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -3749,7 +3749,7 @@ pub mod tests {
|
||||||
bank.slot(),
|
bank.slot(),
|
||||||
0, // index,
|
0, // index,
|
||||||
parent_offset as u16,
|
parent_offset as u16,
|
||||||
Some(&gibberish),
|
&gibberish,
|
||||||
true, // is_last_data
|
true, // is_last_data
|
||||||
false, // is_last_in_slot
|
false, // is_last_in_slot
|
||||||
0, // reference_tick
|
0, // reference_tick
|
||||||
|
|
|
@ -535,37 +535,37 @@ mod tests {
|
||||||
let slot = 1;
|
let slot = 1;
|
||||||
let index = 5;
|
let index = 5;
|
||||||
let version = 0x40;
|
let version = 0x40;
|
||||||
let shred = Shred::new_from_data(slot, index, 0, None, true, true, 0, version, 0);
|
let shred = Shred::new_from_data(slot, index, 0, &[], true, true, 0, version, 0);
|
||||||
let shreds_received = Arc::new(Mutex::new((LruCache::new(100), PacketHasher::default())));
|
let shreds_received = Arc::new(Mutex::new((LruCache::new(100), PacketHasher::default())));
|
||||||
// unique shred for (1, 5) should pass
|
// unique shred for (1, 5) should pass
|
||||||
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
||||||
// duplicate shred for (1, 5) blocked
|
// duplicate shred for (1, 5) blocked
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
|
|
||||||
let shred = Shred::new_from_data(slot, index, 2, None, true, true, 0, version, 0);
|
let shred = Shred::new_from_data(slot, index, 2, &[], true, true, 0, version, 0);
|
||||||
// first duplicate shred for (1, 5) passed
|
// first duplicate shred for (1, 5) passed
|
||||||
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
||||||
// then blocked
|
// then blocked
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
|
|
||||||
let shred = Shred::new_from_data(slot, index, 8, None, true, true, 0, version, 0);
|
let shred = Shred::new_from_data(slot, index, 8, &[], true, true, 0, version, 0);
|
||||||
// 2nd duplicate shred for (1, 5) blocked
|
// 2nd duplicate shred for (1, 5) blocked
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
|
|
||||||
let shred = Shred::new_empty_coding(slot, index, 0, 1, 1, 0, version);
|
let shred = Shred::new_from_parity_shard(slot, index, &[], 0, 1, 1, 0, version);
|
||||||
// Coding at (1, 5) passes
|
// Coding at (1, 5) passes
|
||||||
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
||||||
// then blocked
|
// then blocked
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
|
|
||||||
let shred = Shred::new_empty_coding(slot, index, 2, 1, 1, 0, version);
|
let shred = Shred::new_from_parity_shard(slot, index, &[], 2, 1, 1, 0, version);
|
||||||
// 2nd unique coding at (1, 5) passes
|
// 2nd unique coding at (1, 5) passes
|
||||||
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
assert!(!should_skip_retransmit(&shred, &shreds_received));
|
||||||
// same again is blocked
|
// same again is blocked
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
|
|
||||||
let shred = Shred::new_empty_coding(slot, index, 3, 1, 1, 0, version);
|
let shred = Shred::new_from_parity_shard(slot, index, &[], 3, 1, 1, 0, version);
|
||||||
// Another unique coding at (1, 5) always blocked
|
// Another unique coding at (1, 5) always blocked
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
assert!(should_skip_retransmit(&shred, &shreds_received));
|
assert!(should_skip_retransmit(&shred, &shreds_received));
|
||||||
|
|
|
@ -876,7 +876,7 @@ mod tests {
|
||||||
nonce,
|
nonce,
|
||||||
);
|
);
|
||||||
assert!(rv.is_none());
|
assert!(rv.is_none());
|
||||||
let shred = Shred::new_from_data(slot, 1, 1, None, false, false, 0, 2, 0);
|
let shred = Shred::new_from_data(slot, 1, 1, &[], false, false, 0, 2, 0);
|
||||||
|
|
||||||
blockstore
|
blockstore
|
||||||
.insert_shreds(vec![shred], None, false)
|
.insert_shreds(vec![shred], None, false)
|
||||||
|
@ -1306,7 +1306,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_shred_response() {
|
fn test_verify_shred_response() {
|
||||||
fn new_test_data_shred(slot: Slot, index: u32) -> Shred {
|
fn new_test_data_shred(slot: Slot, index: u32) -> Shred {
|
||||||
Shred::new_from_data(slot, index, 1, None, false, false, 0, 0, 0)
|
Shred::new_from_data(slot, index, 1, &[], false, false, 0, 0, 0)
|
||||||
}
|
}
|
||||||
let repair = ShredRepairType::Orphan(9);
|
let repair = ShredRepairType::Orphan(9);
|
||||||
// Ensure new options are addded to this test
|
// Ensure new options are addded to this test
|
||||||
|
|
|
@ -228,9 +228,10 @@ mod tests {
|
||||||
|
|
||||||
let slot = 1;
|
let slot = 1;
|
||||||
let shred = Shred::new_from_data(
|
let shred = Shred::new_from_data(
|
||||||
slot, 3, // shred index
|
slot,
|
||||||
|
3, // shred index
|
||||||
0, // parent offset
|
0, // parent offset
|
||||||
None, // data
|
&[], // data
|
||||||
true, // is_last_in_fec_set
|
true, // is_last_in_fec_set
|
||||||
true, // is_last_in_slot
|
true, // is_last_in_slot
|
||||||
0, // reference_tick
|
0, // reference_tick
|
||||||
|
@ -299,7 +300,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(stats.index_overrun, 1);
|
assert_eq!(stats.index_overrun, 1);
|
||||||
assert!(packet.meta.discard());
|
assert!(packet.meta.discard());
|
||||||
let shred = Shred::new_from_data(1, 3, 0, None, true, true, 0, 0, 0);
|
let shred = Shred::new_from_data(1, 3, 0, &[], true, true, 0, 0, 0);
|
||||||
shred.copy_to_packet(&mut packet);
|
shred.copy_to_packet(&mut packet);
|
||||||
|
|
||||||
// rejected slot is 1, root is 3
|
// rejected slot is 1, root is 3
|
||||||
|
@ -341,7 +342,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert!(packet.meta.discard());
|
assert!(packet.meta.discard());
|
||||||
|
|
||||||
let shred = Shred::new_from_data(1_000_000, 3, 0, None, true, true, 0, 0, 0);
|
let shred = Shred::new_from_data(1_000_000, 3, 0, &[], true, true, 0, 0, 0);
|
||||||
shred.copy_to_packet(&mut packet);
|
shred.copy_to_packet(&mut packet);
|
||||||
|
|
||||||
// Slot 1 million is too high
|
// Slot 1 million is too high
|
||||||
|
@ -358,7 +359,7 @@ mod tests {
|
||||||
assert!(packet.meta.discard());
|
assert!(packet.meta.discard());
|
||||||
|
|
||||||
let index = MAX_DATA_SHREDS_PER_SLOT as u32;
|
let index = MAX_DATA_SHREDS_PER_SLOT as u32;
|
||||||
let shred = Shred::new_from_data(5, index, 0, None, true, true, 0, 0, 0);
|
let shred = Shred::new_from_data(5, index, 0, &[], true, true, 0, 0, 0);
|
||||||
shred.copy_to_packet(&mut packet);
|
shred.copy_to_packet(&mut packet);
|
||||||
ShredFetchStage::process_packet(
|
ShredFetchStage::process_packet(
|
||||||
&mut packet,
|
&mut packet,
|
||||||
|
|
|
@ -82,7 +82,7 @@ pub mod tests {
|
||||||
0xdead_c0de,
|
0xdead_c0de,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[1, 2, 3, 4]),
|
&[1, 2, 3, 4],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
@ -101,7 +101,7 @@ pub mod tests {
|
||||||
0xc0de_dead,
|
0xc0de_dead,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[1, 2, 3, 4]),
|
&[1, 2, 3, 4],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
@ -131,32 +131,14 @@ pub mod tests {
|
||||||
let mut batches = vec![PacketBatch::default()];
|
let mut batches = vec![PacketBatch::default()];
|
||||||
batches[0].packets.resize(2, Packet::default());
|
batches[0].packets.resize(2, Packet::default());
|
||||||
|
|
||||||
let mut shred = Shred::new_from_data(
|
let mut shred =
|
||||||
0,
|
Shred::new_from_data(0, 0xc0de, 0xdead, &[1, 2, 3, 4], true, true, 0, 0, 0xc0de);
|
||||||
0xc0de,
|
|
||||||
0xdead,
|
|
||||||
Some(&[1, 2, 3, 4]),
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0xc0de,
|
|
||||||
);
|
|
||||||
shred.sign(&leader_keypair);
|
shred.sign(&leader_keypair);
|
||||||
batches[0].packets[0].data[0..shred.payload().len()].copy_from_slice(shred.payload());
|
batches[0].packets[0].data[0..shred.payload().len()].copy_from_slice(shred.payload());
|
||||||
batches[0].packets[0].meta.size = shred.payload().len();
|
batches[0].packets[0].meta.size = shred.payload().len();
|
||||||
|
|
||||||
let mut shred = Shred::new_from_data(
|
let mut shred =
|
||||||
0,
|
Shred::new_from_data(0, 0xbeef, 0xc0de, &[1, 2, 3, 4], true, true, 0, 0, 0xc0de);
|
||||||
0xbeef,
|
|
||||||
0xc0de,
|
|
||||||
Some(&[1, 2, 3, 4]),
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0xc0de,
|
|
||||||
);
|
|
||||||
let wrong_keypair = Keypair::new();
|
let wrong_keypair = Keypair::new();
|
||||||
shred.sign(&wrong_keypair);
|
shred.sign(&wrong_keypair);
|
||||||
batches[0].packets[1].data[0..shred.payload().len()].copy_from_slice(shred.payload());
|
batches[0].packets[1].data[0..shred.payload().len()].copy_from_slice(shred.payload());
|
||||||
|
|
|
@ -863,14 +863,15 @@ mod test {
|
||||||
));
|
));
|
||||||
|
|
||||||
// coding shreds don't contain parent slot information, test that slot >= root
|
// coding shreds don't contain parent slot information, test that slot >= root
|
||||||
let mut coding_shred = Shred::new_empty_coding(
|
let mut coding_shred = Shred::new_from_parity_shard(
|
||||||
5, // slot
|
5, // slot
|
||||||
5, // index
|
5, // index
|
||||||
5, // fec_set_index
|
&[], // parity_shard
|
||||||
6, // num_data_shreds
|
5, // fec_set_index
|
||||||
6, // num_coding_shreds
|
6, // num_data_shreds
|
||||||
3, // position
|
6, // num_coding_shreds
|
||||||
0, // version
|
3, // position
|
||||||
|
0, // version
|
||||||
);
|
);
|
||||||
coding_shred.sign(&leader_keypair);
|
coding_shred.sign(&leader_keypair);
|
||||||
// shred.slot() > root, shred continues
|
// shred.slot() > root, shred continues
|
||||||
|
@ -945,14 +946,15 @@ mod test {
|
||||||
std::net::{IpAddr, Ipv4Addr},
|
std::net::{IpAddr, Ipv4Addr},
|
||||||
};
|
};
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let shred = Shred::new_empty_coding(
|
let shred = Shred::new_from_parity_shard(
|
||||||
5, // slot
|
5, // slot
|
||||||
5, // index
|
5, // index
|
||||||
5, // fec_set_index
|
&[], // parity_shard
|
||||||
6, // num_data_shreds
|
5, // fec_set_index
|
||||||
6, // num_coding_shreds
|
6, // num_data_shreds
|
||||||
4, // position
|
6, // num_coding_shreds
|
||||||
0, // version
|
4, // position
|
||||||
|
0, // version
|
||||||
);
|
);
|
||||||
let mut shreds = vec![shred.clone(), shred.clone(), shred];
|
let mut shreds = vec![shred.clone(), shred.clone(), shred];
|
||||||
let _from_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
let _from_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||||
|
|
|
@ -32,7 +32,7 @@ fn bench_sigverify_shreds_sign_gpu(bencher: &mut Bencher) {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[5; SIZE_OF_DATA_SHRED_PAYLOAD]),
|
&[5; SIZE_OF_DATA_SHRED_PAYLOAD],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
1,
|
1,
|
||||||
|
@ -64,7 +64,7 @@ fn bench_sigverify_shreds_sign_cpu(bencher: &mut Bencher) {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[5; SIZE_OF_DATA_SHRED_PAYLOAD]),
|
&[5; SIZE_OF_DATA_SHRED_PAYLOAD],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -5705,7 +5705,7 @@ pub mod tests {
|
||||||
slot,
|
slot,
|
||||||
(i * gap) as u32,
|
(i * gap) as u32,
|
||||||
0,
|
0,
|
||||||
None,
|
&[],
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
i as u8,
|
i as u8,
|
||||||
|
@ -5837,7 +5837,7 @@ pub mod tests {
|
||||||
let parent_offset = shred5.slot() - shred5.parent().unwrap();
|
let parent_offset = shred5.slot() - shred5.parent().unwrap();
|
||||||
parent_offset as u16
|
parent_offset as u16
|
||||||
},
|
},
|
||||||
None, // data
|
&[], // data
|
||||||
true, // is_last_data
|
true, // is_last_data
|
||||||
true, // is_last_in_slot
|
true, // is_last_in_slot
|
||||||
0, // reference_tick
|
0, // reference_tick
|
||||||
|
@ -5938,13 +5938,15 @@ pub mod tests {
|
||||||
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
|
|
||||||
let slot = 1;
|
let slot = 1;
|
||||||
let coding_shred = Shred::new_empty_coding(
|
let coding_shred = Shred::new_from_parity_shard(
|
||||||
slot, 11, // index
|
slot,
|
||||||
11, // fec_set_index
|
11, // index
|
||||||
11, // num_data_shreds
|
&[], // parity_shard
|
||||||
11, // num_coding_shreds
|
11, // fec_set_index
|
||||||
8, // position
|
11, // num_data_shreds
|
||||||
0, // version
|
11, // num_coding_shreds
|
||||||
|
8, // position
|
||||||
|
0, // version
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut erasure_metas = HashMap::new();
|
let mut erasure_metas = HashMap::new();
|
||||||
|
@ -5994,13 +5996,15 @@ pub mod tests {
|
||||||
let last_root = RwLock::new(0);
|
let last_root = RwLock::new(0);
|
||||||
|
|
||||||
let slot = 1;
|
let slot = 1;
|
||||||
let mut coding_shred = Shred::new_empty_coding(
|
let mut coding_shred = Shred::new_from_parity_shard(
|
||||||
slot, 11, // index
|
slot,
|
||||||
11, // fec_set_index
|
11, // index
|
||||||
11, // num_data_shreds
|
&[], // parity_shard
|
||||||
11, // num_coding_shreds
|
11, // fec_set_index
|
||||||
8, // position
|
11, // num_data_shreds
|
||||||
0, // version
|
11, // num_coding_shreds
|
||||||
|
8, // position
|
||||||
|
0, // version
|
||||||
);
|
);
|
||||||
|
|
||||||
// Insert a good coding shred
|
// Insert a good coding shred
|
||||||
|
@ -6237,7 +6241,7 @@ pub mod tests {
|
||||||
slot,
|
slot,
|
||||||
next_shred_index as u32,
|
next_shred_index as u32,
|
||||||
1,
|
1,
|
||||||
Some(&[1, 1, 1]),
|
&[1, 1, 1],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -269,15 +269,14 @@ impl Shred {
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
index: u32,
|
index: u32,
|
||||||
parent_offset: u16,
|
parent_offset: u16,
|
||||||
data: Option<&[u8]>,
|
data: &[u8],
|
||||||
is_last_data: bool,
|
is_last_data: bool,
|
||||||
is_last_in_slot: bool,
|
is_last_in_slot: bool,
|
||||||
reference_tick: u8,
|
reference_tick: u8,
|
||||||
version: u16,
|
version: u16,
|
||||||
fec_set_index: u32,
|
fec_set_index: u32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let payload_size = SHRED_PAYLOAD_SIZE;
|
let mut payload = vec![0; SHRED_PAYLOAD_SIZE];
|
||||||
let mut payload = vec![0; payload_size];
|
|
||||||
let common_header = ShredCommonHeader {
|
let common_header = ShredCommonHeader {
|
||||||
slot,
|
slot,
|
||||||
index,
|
index,
|
||||||
|
@ -286,9 +285,7 @@ impl Shred {
|
||||||
..ShredCommonHeader::default()
|
..ShredCommonHeader::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = (data.map(|d| d.len()).unwrap_or(0)
|
let size = (data.len() + SIZE_OF_DATA_SHRED_HEADER + SIZE_OF_COMMON_SHRED_HEADER) as u16;
|
||||||
+ SIZE_OF_DATA_SHRED_HEADER
|
|
||||||
+ SIZE_OF_COMMON_SHRED_HEADER) as u16;
|
|
||||||
let mut data_header = DataShredHeader {
|
let mut data_header = DataShredHeader {
|
||||||
parent_offset,
|
parent_offset,
|
||||||
flags: reference_tick.min(SHRED_TICK_REFERENCE_MASK),
|
flags: reference_tick.min(SHRED_TICK_REFERENCE_MASK),
|
||||||
|
@ -320,10 +317,7 @@ impl Shred {
|
||||||
)
|
)
|
||||||
.expect("Failed to write data header into shred buffer");
|
.expect("Failed to write data header into shred buffer");
|
||||||
// TODO: Need to check if data is too large!
|
// TODO: Need to check if data is too large!
|
||||||
if let Some(data) = data {
|
payload[start..start + data.len()].copy_from_slice(data);
|
||||||
payload[start..start + data.len()].clone_from_slice(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
common_header,
|
common_header,
|
||||||
data_header,
|
data_header,
|
||||||
|
@ -362,9 +356,10 @@ impl Shred {
|
||||||
shred.sanitize().map(|_| shred)
|
shred.sanitize().map(|_| shred)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_empty_coding(
|
pub fn new_from_parity_shard(
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
index: u32,
|
index: u32,
|
||||||
|
parity_shard: &[u8],
|
||||||
fec_set_index: u32,
|
fec_set_index: u32,
|
||||||
num_data_shreds: u16,
|
num_data_shreds: u16,
|
||||||
num_coding_shreds: u16,
|
num_coding_shreds: u16,
|
||||||
|
@ -400,6 +395,10 @@ impl Shred {
|
||||||
&coding_header,
|
&coding_header,
|
||||||
)
|
)
|
||||||
.expect("Failed to write coding header into shred buffer");
|
.expect("Failed to write coding header into shred buffer");
|
||||||
|
// Tests may have an empty parity_shard.
|
||||||
|
if !parity_shard.is_empty() {
|
||||||
|
payload[SIZE_OF_CODING_SHRED_HEADERS..].copy_from_slice(parity_shard);
|
||||||
|
}
|
||||||
Shred {
|
Shred {
|
||||||
common_header,
|
common_header,
|
||||||
data_header: DataShredHeader::default(),
|
data_header: DataShredHeader::default(),
|
||||||
|
@ -835,7 +834,7 @@ impl Shredder {
|
||||||
self.slot,
|
self.slot,
|
||||||
shred_index,
|
shred_index,
|
||||||
parent_offset as u16,
|
parent_offset as u16,
|
||||||
Some(data),
|
data,
|
||||||
is_last_data,
|
is_last_data,
|
||||||
is_last_in_slot,
|
is_last_in_slot,
|
||||||
self.reference_tick,
|
self.reference_tick,
|
||||||
|
@ -965,17 +964,16 @@ impl Shredder {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, parity)| {
|
.map(|(i, parity)| {
|
||||||
let index = next_code_index + u32::try_from(i).unwrap();
|
let index = next_code_index + u32::try_from(i).unwrap();
|
||||||
let mut shred = Shred::new_empty_coding(
|
Shred::new_from_parity_shard(
|
||||||
slot,
|
slot,
|
||||||
index,
|
index,
|
||||||
|
parity,
|
||||||
fec_set_index,
|
fec_set_index,
|
||||||
num_data,
|
num_data,
|
||||||
num_coding,
|
num_coding,
|
||||||
u16::try_from(i).unwrap(), // position
|
u16::try_from(i).unwrap(), // position
|
||||||
version,
|
version,
|
||||||
);
|
)
|
||||||
shred.payload[SIZE_OF_CODING_SHRED_HEADERS..].copy_from_slice(parity);
|
|
||||||
shred
|
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -1947,7 +1945,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_parent_offset() {
|
fn test_invalid_parent_offset() {
|
||||||
let shred = Shred::new_from_data(10, 0, 1000, Some(&[1, 2, 3]), false, false, 0, 1, 0);
|
let shred = Shred::new_from_data(10, 0, 1000, &[1, 2, 3], false, false, 0, 1, 0);
|
||||||
let mut packet = Packet::default();
|
let mut packet = Packet::default();
|
||||||
shred.copy_to_packet(&mut packet);
|
shred.copy_to_packet(&mut packet);
|
||||||
let shred_res = Shred::new_from_serialized_shred(packet.data.to_vec());
|
let shred_res = Shred::new_from_serialized_shred(packet.data.to_vec());
|
||||||
|
@ -1971,7 +1969,7 @@ mod tests {
|
||||||
fn test_shred_offsets() {
|
fn test_shred_offsets() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let mut packet = Packet::default();
|
let mut packet = Packet::default();
|
||||||
let shred = Shred::new_from_data(1, 3, 0, None, true, true, 0, 0, 0);
|
let shred = Shred::new_from_data(1, 3, 0, &[], true, true, 0, 0, 0);
|
||||||
shred.copy_to_packet(&mut packet);
|
shred.copy_to_packet(&mut packet);
|
||||||
let mut stats = ShredFetchStats::default();
|
let mut stats = ShredFetchStats::default();
|
||||||
let ret = get_shred_slot_index_type(&packet, &mut stats);
|
let ret = get_shred_slot_index_type(&packet, &mut stats);
|
||||||
|
@ -2001,9 +1999,10 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(stats.index_overrun, 4);
|
assert_eq!(stats.index_overrun, 4);
|
||||||
|
|
||||||
let shred = Shred::new_empty_coding(
|
let shred = Shred::new_from_parity_shard(
|
||||||
8, // slot
|
8, // slot
|
||||||
2, // index
|
2, // index
|
||||||
|
&[], // parity_shard
|
||||||
10, // fec_set_index
|
10, // fec_set_index
|
||||||
30, // num_data
|
30, // num_data
|
||||||
4, // num_code
|
4, // num_code
|
||||||
|
@ -2016,14 +2015,15 @@ mod tests {
|
||||||
get_shred_slot_index_type(&packet, &mut stats)
|
get_shred_slot_index_type(&packet, &mut stats)
|
||||||
);
|
);
|
||||||
|
|
||||||
let shred = Shred::new_from_data(1, std::u32::MAX - 10, 0, None, true, true, 0, 0, 0);
|
let shred = Shred::new_from_data(1, std::u32::MAX - 10, 0, &[], true, true, 0, 0, 0);
|
||||||
shred.copy_to_packet(&mut packet);
|
shred.copy_to_packet(&mut packet);
|
||||||
assert_eq!(None, get_shred_slot_index_type(&packet, &mut stats));
|
assert_eq!(None, get_shred_slot_index_type(&packet, &mut stats));
|
||||||
assert_eq!(1, stats.index_out_of_bounds);
|
assert_eq!(1, stats.index_out_of_bounds);
|
||||||
|
|
||||||
let shred = Shred::new_empty_coding(
|
let shred = Shred::new_from_parity_shard(
|
||||||
8, // slot
|
8, // slot
|
||||||
2, // index
|
2, // index
|
||||||
|
&[], // parity_shard
|
||||||
10, // fec_set_index
|
10, // fec_set_index
|
||||||
30, // num_data_shreds
|
30, // num_data_shreds
|
||||||
4, // num_coding_shreds
|
4, // num_coding_shreds
|
||||||
|
@ -2072,8 +2072,7 @@ mod tests {
|
||||||
420, // slot
|
420, // slot
|
||||||
19, // index
|
19, // index
|
||||||
5, // parent_offset
|
5, // parent_offset
|
||||||
Some(&data),
|
&data, true, // is_last_data
|
||||||
true, // is_last_data
|
|
||||||
false, // is_last_in_slot
|
false, // is_last_in_slot
|
||||||
3, // reference_tick
|
3, // reference_tick
|
||||||
1, // version
|
1, // version
|
||||||
|
@ -2133,14 +2132,15 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sanitize_coding_shred() {
|
fn test_sanitize_coding_shred() {
|
||||||
let mut shred = Shred::new_empty_coding(
|
let mut shred = Shred::new_from_parity_shard(
|
||||||
1, // slot
|
1, // slot
|
||||||
12, // index
|
12, // index
|
||||||
11, // fec_set_index
|
&[], // parity_shard
|
||||||
11, // num_data_shreds
|
11, // fec_set_index
|
||||||
11, // num_coding_shreds
|
11, // num_data_shreds
|
||||||
8, // position
|
11, // num_coding_shreds
|
||||||
0, // version
|
8, // position
|
||||||
|
0, // version
|
||||||
);
|
);
|
||||||
assert_matches!(shred.sanitize(), Ok(()));
|
assert_matches!(shred.sanitize(), Ok(()));
|
||||||
// index < position is invalid.
|
// index < position is invalid.
|
||||||
|
|
|
@ -470,7 +470,7 @@ pub mod tests {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[1, 2, 3, 4]),
|
&[1, 2, 3, 4],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
@ -516,7 +516,7 @@ pub mod tests {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[1, 2, 3, 4]),
|
&[1, 2, 3, 4],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
@ -571,7 +571,7 @@ pub mod tests {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[1, 2, 3, 4]),
|
&[1, 2, 3, 4],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
@ -639,7 +639,7 @@ pub mod tests {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
i as u16,
|
i as u16,
|
||||||
Some(&[5; SIZE_OF_DATA_SHRED_PAYLOAD]),
|
&[5; SIZE_OF_DATA_SHRED_PAYLOAD],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
1,
|
1,
|
||||||
|
@ -685,7 +685,7 @@ pub mod tests {
|
||||||
slot,
|
slot,
|
||||||
0xc0de,
|
0xc0de,
|
||||||
0xdead,
|
0xdead,
|
||||||
Some(&[1, 2, 3, 4]),
|
&[1, 2, 3, 4],
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
|
|
Loading…
Reference in New Issue