Fix replay stage test (#6406)

This commit is contained in:
Pankaj Garg 2019-10-16 15:41:43 -07:00 committed by GitHub
parent b85996494b
commit 83c1831a01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 25 deletions

View File

@ -429,7 +429,7 @@ impl Blocktree {
&mut write_batch, &mut write_batch,
&mut just_inserted_data_shreds, &mut just_inserted_data_shreds,
); );
} else { } else if shred.is_code() {
self.check_insert_coding_shred( self.check_insert_coding_shred(
shred, shred,
&mut erasure_metas, &mut erasure_metas,
@ -1033,7 +1033,14 @@ impl Blocktree {
if is_complete { if is_complete {
if let Ok(deshred_payload) = Shredder::deshred(&shred_chunk) { if let Ok(deshred_payload) = Shredder::deshred(&shred_chunk) {
debug!("{:?} shreds in last FEC set", shred_chunk.len(),); debug!("{:?} shreds in last FEC set", shred_chunk.len(),);
let entries: Vec<Entry> = bincode::deserialize(&deshred_payload)?; let entries: Vec<Entry> =
bincode::deserialize(&deshred_payload).map_err(|_| {
Error::BlocktreeError(BlocktreeError::InvalidShredData(Box::new(
bincode::ErrorKind::Custom(
"could not construct entries".to_string(),
),
)))
})?;
return Ok((entries, shred_chunk.len())); return Ok((entries, shred_chunk.len()));
} else { } else {
debug!("Failed in deshredding shred payloads"); debug!("Failed in deshredding shred payloads");

View File

@ -878,14 +878,15 @@ impl Service for ReplayStage {
mod test { mod test {
use super::*; use super::*;
use crate::blocktree::tests::make_slot_entries; use crate::blocktree::tests::make_slot_entries;
use crate::blocktree::{entries_to_test_shreds, get_tmp_ledger_path}; use crate::blocktree::{entries_to_test_shreds, get_tmp_ledger_path, BlocktreeError};
use crate::confidence::BankConfidence; use crate::confidence::BankConfidence;
use crate::entry; use crate::entry;
use crate::genesis_utils::{create_genesis_block, create_genesis_block_with_leader}; use crate::genesis_utils::{create_genesis_block, create_genesis_block_with_leader};
use crate::replay_stage::ReplayStage; use crate::replay_stage::ReplayStage;
use crate::shred::Shred; use crate::shred::{Shred, ShredHeader, DATA_COMPLETE_SHRED, SIZE_OF_SHRED_HEADER};
use solana_runtime::genesis_utils::GenesisBlockInfo; use solana_runtime::genesis_utils::GenesisBlockInfo;
use solana_sdk::hash::{hash, Hash}; use solana_sdk::hash::{hash, Hash};
use solana_sdk::packet::PACKET_DATA_SIZE;
use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction; use solana_sdk::system_transaction;
use solana_sdk::transaction::TransactionError; use solana_sdk::transaction::TransactionError;
@ -1004,28 +1005,24 @@ mod test {
} }
#[test] #[test]
fn test_dead_fork_blob_deserialize_failure() { fn test_dead_fork_entry_deserialize_failure() {
let keypair1 = Keypair::new(); // Insert entry that causes deserialization failure
let keypair2 = Keypair::new(); let res = check_dead_fork(|_, _| {
// Insert entry that causes blob deserialization failure let payload_len = PACKET_DATA_SIZE - *SIZE_OF_SHRED_HEADER;
let gibberish = [0xa5u8; PACKET_DATA_SIZE];
let res = check_dead_fork(|blockhash, slot| { let mut header = ShredHeader::default();
let entry = entry::next_entry( header.data_header.flags = DATA_COMPLETE_SHRED;
&blockhash, let mut shred = Shred::new_empty_from_header(header);
1, let _ = bincode::serialize_into(
vec![system_transaction::create_user_account( &mut shred.payload[*SIZE_OF_SHRED_HEADER..],
&keypair1, &gibberish[..payload_len],
&keypair2.pubkey(),
2,
*blockhash,
)],
); );
entries_to_test_shreds(vec![entry], slot, slot.saturating_sub(1), false) vec![shred]
}); });
assert_matches!( assert_matches!(
res, res,
Err(Error::TransactionError(TransactionError::AccountNotFound)) Err(Error::BlocktreeError(BlocktreeError::InvalidShredData(_)))
); );
} }

View File

@ -52,10 +52,10 @@ pub const MAX_DATA_SHREDS_PER_FEC_BLOCK: u32 = 16;
pub const RECOMMENDED_FEC_RATE: f32 = 0.25; pub const RECOMMENDED_FEC_RATE: f32 = 0.25;
const LAST_SHRED_IN_SLOT: u8 = 0b0000_0001; const LAST_SHRED_IN_SLOT: u8 = 0b0000_0001;
const DATA_COMPLETE_SHRED: u8 = 0b0000_0010; pub const DATA_COMPLETE_SHRED: u8 = 0b0000_0010;
#[derive(Serialize, Clone, Deserialize, PartialEq, Debug)] #[derive(Serialize, Clone, Deserialize, PartialEq, Debug)]
pub struct ShredType(u8); pub struct ShredType(pub u8);
/// A common header that is present in data and code shred headers /// A common header that is present in data and code shred headers
#[derive(Serialize, Clone, Deserialize, Default, PartialEq, Debug)] #[derive(Serialize, Clone, Deserialize, Default, PartialEq, Debug)]
@ -245,6 +245,9 @@ impl Shred {
pub fn is_data(&self) -> bool { pub fn is_data(&self) -> bool {
self.headers.shred_type == ShredType(DATA_SHRED) self.headers.shred_type == ShredType(DATA_SHRED)
} }
pub fn is_code(&self) -> bool {
self.headers.shred_type == ShredType(CODING_SHRED)
}
pub fn last_in_slot(&self) -> bool { pub fn last_in_slot(&self) -> bool {
if self.is_data() { if self.is_data() {
@ -271,7 +274,7 @@ impl Shred {
} }
pub fn coding_params(&self) -> Option<(u16, u16, u16)> { pub fn coding_params(&self) -> Option<(u16, u16, u16)> {
if !self.is_data() { if self.is_code() {
let header = &self.headers.coding_header; let header = &self.headers.coding_header;
Some(( Some((
header.num_data_shreds, header.num_data_shreds,
@ -286,8 +289,10 @@ impl Shred {
pub fn verify(&self, pubkey: &Pubkey) -> bool { pub fn verify(&self, pubkey: &Pubkey) -> bool {
let signed_payload_offset = if self.is_data() { let signed_payload_offset = if self.is_data() {
*SIZE_OF_CODING_SHRED_HEADER + *SIZE_OF_SHRED_TYPE *SIZE_OF_CODING_SHRED_HEADER + *SIZE_OF_SHRED_TYPE
} else { } else if self.is_code() {
*SIZE_OF_SHRED_TYPE *SIZE_OF_SHRED_TYPE
} else {
return false;
} + *SIZE_OF_SIGNATURE; } + *SIZE_OF_SIGNATURE;
self.signature() self.signature()
.verify(pubkey.as_ref(), &self.payload[signed_payload_offset..]) .verify(pubkey.as_ref(), &self.payload[signed_payload_offset..])