Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions src/chain_sync/chain_follower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@ async fn chain_follower(
if let Err(reason) = GossipBlockValidator::new(&b).validate_pre_fetch(
&genesis,
cfg.block_delay_secs,
cfg.policy.chain_finality,
cs.heaviest_tipset().epoch(),
cs.ec_calculator_finalized_epoch(), // Not using F3 finalized epoch as it could go above the chain head during catchup
bad_block_cache.as_ref(),
&seen_block_cache,
) {
Expand Down Expand Up @@ -713,11 +712,9 @@ impl SyncStateMachine {
return;
}

// Check if tipset is outside the chain_finality window
let heaviest = self.cs.heaviest_tipset();
let epoch_diff = heaviest.epoch() - tipset.epoch();

if epoch_diff > self.cs.chain_config().policy.chain_finality {
// Check if tipset is outside the chain finality window.
// Not using F3 finalized epoch as it could go above the chain head during catchup
if tipset.epoch() < self.cs.ec_calculator_finalized_epoch() {
self.mark_bad_tipset(tipset);
return;
}
Expand Down
56 changes: 28 additions & 28 deletions src/chain_sync/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,11 @@ impl TipsetValidator<'_> {
pub enum GossipBlockRejectReason {
#[error("block epoch {0} is too far in the future")]
EpochTooFarAhead(ChainEpoch),
#[error("block epoch {0} is beyond finality (heaviest: {1})")]
EpochBeyondFinality(ChainEpoch, ChainEpoch),
#[error("block epoch {epoch} is beyond finality (finalized: {finalized_epoch})")]
EpochBeyondFinality {
epoch: ChainEpoch,
finalized_epoch: ChainEpoch,
},
#[error("block epoch {0} is negative")]
NegativeEpoch(ChainEpoch),
#[error("block timestamp {timestamp} inconsistent with epoch {epoch} (expected {expected})")]
Expand All @@ -197,7 +200,7 @@ impl GossipBlockRejectReason {
pub fn label(&self) -> &'static str {
match self {
Self::EpochTooFarAhead(_) => "epoch_too_far_ahead",
Self::EpochBeyondFinality(_, _) => "epoch_beyond_finality",
Self::EpochBeyondFinality { .. } => "epoch_beyond_finality",
Self::NegativeEpoch(_) => "negative_epoch",
Self::TimestampMismatch { .. } => "timestamp_mismatch",
Self::MissingSignature => "missing_signature",
Expand Down Expand Up @@ -228,14 +231,13 @@ impl<'a> GossipBlockValidator<'a> {
&self,
genesis_tipset: &Tipset,
block_delay: u32,
chain_finality: ChainEpoch,
heaviest_epoch: ChainEpoch,
finalized_epoch: ChainEpoch,
bad_block_cache: Option<&BadBlockCache>,
seen_block_cache: &SeenBlockCache,
) -> Result<(), GossipBlockRejectReason> {
let cid = *self.block.header.cid();
Self::check_bad_block_cache(cid, bad_block_cache)?;
self.validate_epoch_range(genesis_tipset, block_delay, chain_finality, heaviest_epoch)?;
self.validate_epoch_range(genesis_tipset, block_delay, finalized_epoch)?;
self.validate_timestamp(genesis_tipset, block_delay)?;
self.validate_election_proof()?;
self.validate_signature_present()?;
Expand Down Expand Up @@ -272,8 +274,7 @@ impl<'a> GossipBlockValidator<'a> {
&self,
genesis_tipset: &Tipset,
block_delay: u32,
chain_finality: ChainEpoch,
heaviest_epoch: ChainEpoch,
finalized_epoch: ChainEpoch,
) -> Result<(), GossipBlockRejectReason> {
let epoch = self.block.header.epoch;
if epoch < 0 {
Expand All @@ -284,11 +285,11 @@ impl<'a> GossipBlockValidator<'a> {
if epoch > max {
return Err(GossipBlockRejectReason::EpochTooFarAhead(epoch));
}
if heaviest_epoch.saturating_sub(epoch) > chain_finality {
return Err(GossipBlockRejectReason::EpochBeyondFinality(
if epoch < finalized_epoch {
return Err(GossipBlockRejectReason::EpochBeyondFinality {
epoch,
heaviest_epoch,
));
finalized_epoch,
});
}
Ok(())
}
Expand Down Expand Up @@ -450,8 +451,7 @@ mod tests {

let result = GossipBlockValidator::new(&block).validate_pre_fetch(
&genesis, 30, // block_delay
900, // chain_finality
0, // heaviest_epoch (same as block epoch)
0, // finalized_epoch
None, // no bad block cache
&seen,
);
Expand All @@ -466,12 +466,12 @@ mod tests {

assert!(
GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.is_ok()
);

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::DuplicateBlock(_)));
}
Expand All @@ -485,7 +485,7 @@ mod tests {
bad_cache.push(*block.header.cid());

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, Some(&bad_cache), &seen)
.validate_pre_fetch(&genesis, 30, 0, Some(&bad_cache), &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::BadBlock(_)));
}
Expand All @@ -497,7 +497,7 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::EpochTooFarAhead(_)));
}
Expand All @@ -509,11 +509,11 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 1000, None, &seen)
.validate_pre_fetch(&genesis, 30, 100, None, &seen)
.unwrap_err();
assert!(matches!(
err,
GossipBlockRejectReason::EpochBeyondFinality(_, _)
GossipBlockRejectReason::EpochBeyondFinality { .. }
));
}

Expand All @@ -524,7 +524,7 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::MissingElectionProof));
}
Expand All @@ -541,7 +541,7 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::InvalidWinCount(0)));
}
Expand All @@ -553,7 +553,7 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::MissingSignature));
}
Expand All @@ -566,7 +566,7 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::TooManyMessages(_)));
}
Expand All @@ -578,7 +578,7 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::NegativeEpoch(-1)));
}
Expand All @@ -592,7 +592,7 @@ mod tests {
let seen = SeenBlockCache::default();

let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(
err,
Expand All @@ -612,13 +612,13 @@ mod tests {

// First attempt: rejected as too far ahead
let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::EpochTooFarAhead(_)));

// Second attempt: must still be EpochTooFarAhead, NOT DuplicateBlock
let err = GossipBlockValidator::new(&block)
.validate_pre_fetch(&genesis, 30, 900, 0, None, &seen)
.validate_pre_fetch(&genesis, 30, 0, None, &seen)
.unwrap_err();
assert!(matches!(err, GossipBlockRejectReason::EpochTooFarAhead(_)));
}
Expand Down
Loading