Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 83c1831

Browse files
authored
Fix replay stage test (#6406)
1 parent b859964 commit 83c1831

File tree

3 files changed

+34
-25
lines changed

3 files changed

+34
-25
lines changed

core/src/blocktree.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ impl Blocktree {
429429
&mut write_batch,
430430
&mut just_inserted_data_shreds,
431431
);
432-
} else {
432+
} else if shred.is_code() {
433433
self.check_insert_coding_shred(
434434
shred,
435435
&mut erasure_metas,
@@ -1033,7 +1033,14 @@ impl Blocktree {
10331033
if is_complete {
10341034
if let Ok(deshred_payload) = Shredder::deshred(&shred_chunk) {
10351035
debug!("{:?} shreds in last FEC set", shred_chunk.len(),);
1036-
let entries: Vec<Entry> = bincode::deserialize(&deshred_payload)?;
1036+
let entries: Vec<Entry> =
1037+
bincode::deserialize(&deshred_payload).map_err(|_| {
1038+
Error::BlocktreeError(BlocktreeError::InvalidShredData(Box::new(
1039+
bincode::ErrorKind::Custom(
1040+
"could not construct entries".to_string(),
1041+
),
1042+
)))
1043+
})?;
10371044
return Ok((entries, shred_chunk.len()));
10381045
} else {
10391046
debug!("Failed in deshredding shred payloads");

core/src/replay_stage.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -878,14 +878,15 @@ impl Service for ReplayStage {
878878
mod test {
879879
use super::*;
880880
use crate::blocktree::tests::make_slot_entries;
881-
use crate::blocktree::{entries_to_test_shreds, get_tmp_ledger_path};
881+
use crate::blocktree::{entries_to_test_shreds, get_tmp_ledger_path, BlocktreeError};
882882
use crate::confidence::BankConfidence;
883883
use crate::entry;
884884
use crate::genesis_utils::{create_genesis_block, create_genesis_block_with_leader};
885885
use crate::replay_stage::ReplayStage;
886-
use crate::shred::Shred;
886+
use crate::shred::{Shred, ShredHeader, DATA_COMPLETE_SHRED, SIZE_OF_SHRED_HEADER};
887887
use solana_runtime::genesis_utils::GenesisBlockInfo;
888888
use solana_sdk::hash::{hash, Hash};
889+
use solana_sdk::packet::PACKET_DATA_SIZE;
889890
use solana_sdk::signature::{Keypair, KeypairUtil};
890891
use solana_sdk::system_transaction;
891892
use solana_sdk::transaction::TransactionError;
@@ -1004,28 +1005,24 @@ mod test {
10041005
}
10051006

10061007
#[test]
1007-
fn test_dead_fork_blob_deserialize_failure() {
1008-
let keypair1 = Keypair::new();
1009-
let keypair2 = Keypair::new();
1010-
// Insert entry that causes blob deserialization failure
1011-
1012-
let res = check_dead_fork(|blockhash, slot| {
1013-
let entry = entry::next_entry(
1014-
&blockhash,
1015-
1,
1016-
vec![system_transaction::create_user_account(
1017-
&keypair1,
1018-
&keypair2.pubkey(),
1019-
2,
1020-
*blockhash,
1021-
)],
1008+
fn test_dead_fork_entry_deserialize_failure() {
1009+
// Insert entry that causes deserialization failure
1010+
let res = check_dead_fork(|_, _| {
1011+
let payload_len = PACKET_DATA_SIZE - *SIZE_OF_SHRED_HEADER;
1012+
let gibberish = [0xa5u8; PACKET_DATA_SIZE];
1013+
let mut header = ShredHeader::default();
1014+
header.data_header.flags = DATA_COMPLETE_SHRED;
1015+
let mut shred = Shred::new_empty_from_header(header);
1016+
let _ = bincode::serialize_into(
1017+
&mut shred.payload[*SIZE_OF_SHRED_HEADER..],
1018+
&gibberish[..payload_len],
10221019
);
1023-
entries_to_test_shreds(vec![entry], slot, slot.saturating_sub(1), false)
1020+
vec![shred]
10241021
});
10251022

10261023
assert_matches!(
10271024
res,
1028-
Err(Error::TransactionError(TransactionError::AccountNotFound))
1025+
Err(Error::BlocktreeError(BlocktreeError::InvalidShredData(_)))
10291026
);
10301027
}
10311028

core/src/shred.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ pub const MAX_DATA_SHREDS_PER_FEC_BLOCK: u32 = 16;
5252
pub const RECOMMENDED_FEC_RATE: f32 = 0.25;
5353

5454
const LAST_SHRED_IN_SLOT: u8 = 0b0000_0001;
55-
const DATA_COMPLETE_SHRED: u8 = 0b0000_0010;
55+
pub const DATA_COMPLETE_SHRED: u8 = 0b0000_0010;
5656

5757
#[derive(Serialize, Clone, Deserialize, PartialEq, Debug)]
58-
pub struct ShredType(u8);
58+
pub struct ShredType(pub u8);
5959

6060
/// A common header that is present in data and code shred headers
6161
#[derive(Serialize, Clone, Deserialize, Default, PartialEq, Debug)]
@@ -245,6 +245,9 @@ impl Shred {
245245
pub fn is_data(&self) -> bool {
246246
self.headers.shred_type == ShredType(DATA_SHRED)
247247
}
248+
pub fn is_code(&self) -> bool {
249+
self.headers.shred_type == ShredType(CODING_SHRED)
250+
}
248251

249252
pub fn last_in_slot(&self) -> bool {
250253
if self.is_data() {
@@ -271,7 +274,7 @@ impl Shred {
271274
}
272275

273276
pub fn coding_params(&self) -> Option<(u16, u16, u16)> {
274-
if !self.is_data() {
277+
if self.is_code() {
275278
let header = &self.headers.coding_header;
276279
Some((
277280
header.num_data_shreds,
@@ -286,8 +289,10 @@ impl Shred {
286289
pub fn verify(&self, pubkey: &Pubkey) -> bool {
287290
let signed_payload_offset = if self.is_data() {
288291
*SIZE_OF_CODING_SHRED_HEADER + *SIZE_OF_SHRED_TYPE
289-
} else {
292+
} else if self.is_code() {
290293
*SIZE_OF_SHRED_TYPE
294+
} else {
295+
return false;
291296
} + *SIZE_OF_SIGNATURE;
292297
self.signature()
293298
.verify(pubkey.as_ref(), &self.payload[signed_payload_offset..])

0 commit comments

Comments
 (0)