diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index 04f42e667..fc7a349d4 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -1019,11 +1019,19 @@ impl ReplayStage { // that comes after the root, so we should not see any // errors related to the slot being purged let slot = bank.slot(); - warn!("Fatal replay error in slot: {}, err: {:?}", slot, err); - let is_serious = matches!( + + // Block producer can abandon the block if it detects a better one + // while producing. Somewhat common and expected in a + // network with variable network/machine configuration. + let is_serious = !matches!( err, - BlockstoreProcessorError::InvalidBlock(BlockError::InvalidTickCount) + BlockstoreProcessorError::InvalidBlock(BlockError::TooFewTicks) ); + if is_serious { + warn!("Fatal replay error in slot: {}, err: {:?}", slot, err); + } else { + info!("Slot had too few ticks: {}", slot); + } Self::mark_dead_slot(blockstore, bank_progress, slot, &err, is_serious); err })?; @@ -2397,6 +2405,7 @@ pub(crate) mod tests { #[test] fn test_dead_fork_invalid_slot_tick_count() { + solana_logger::setup(); // Too many ticks per slot let res = check_dead_fork(|_keypair, bank| { let blockhash = bank.last_blockhash(); @@ -2412,7 +2421,7 @@ pub(crate) mod tests { }); if let Err(BlockstoreProcessorError::InvalidBlock(block_error)) = res { - assert_eq!(block_error, BlockError::InvalidTickCount); + assert_eq!(block_error, BlockError::TooManyTicks); } else { panic!(); } @@ -2432,7 +2441,7 @@ pub(crate) mod tests { }); if let Err(BlockstoreProcessorError::InvalidBlock(block_error)) = res { - assert_eq!(block_error, BlockError::InvalidTickCount); + assert_eq!(block_error, BlockError::TooFewTicks); } else { panic!(); } diff --git a/ledger/src/block_error.rs b/ledger/src/block_error.rs index 523d0ac83..d5b871afc 100644 --- a/ledger/src/block_error.rs +++ b/ledger/src/block_error.rs @@ -2,7 +2,8 @@ use thiserror::Error; #[derive(Error, Debug, PartialEq)] pub enum BlockError { - /// Block did not have enough ticks or was not marked full + /// Block did not have enough ticks was not marked full + /// and no shred with is_last was seen. #[error("incomplete block")] Incomplete, @@ -14,9 +15,16 @@ pub enum BlockError { #[error("invalid last tick")] InvalidLastTick, - /// Blocks can not have extra ticks or missing ticks - #[error("invalid tick count")] - InvalidTickCount, + /// Blocks can not have missing ticks + /// Usually indicates that the node was interruppted with a more valuable block during + /// production and abandoned it for that more-favorable block. Leader sent data to indicate + /// the end of the block. + #[error("too few ticks")] + TooFewTicks, + + /// Blocks can not have extra ticks + #[error("too many ticks")] + TooManyTicks, /// All ticks must contain the same number of hashes within a block #[error("invalid tick hash count")] diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 0d0b2ef75..4919dab03 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -545,12 +545,12 @@ pub fn verify_ticks( if next_bank_tick_height > max_bank_tick_height { warn!("Too many entry ticks found in slot: {}", bank.slot()); - return Err(BlockError::InvalidTickCount); + return Err(BlockError::TooManyTicks); } if next_bank_tick_height < max_bank_tick_height && slot_full { - warn!("Too few entry ticks found in slot: {}", bank.slot()); - return Err(BlockError::InvalidTickCount); + info!("Too few entry ticks found in slot: {}", bank.slot()); + return Err(BlockError::TooFewTicks); } if next_bank_tick_height == max_bank_tick_height {