Skip to content

Commit bf99100

Browse files
committed
fix(blockchain): adapt the heartbeat tier to main's rejection taxonomy
Main replaced `InvalidValidatorIndex` with index-specific variants, made `is_slot_justified` fallible, added a genesis field this branch also extends, and made `rejection_reason` exhaustive so a new `StoreError` forces a classification decision. The heartbeat variants report as unclassified for now: leanSpec names no rejection reason for the tier yet, so a placeholder mapping would assert a reason no fixture agrees with. Revisit when the spec covers heartbeat vote validation. The two projection-window assertions read an untracked slot as "not justified yet", matching how the packer's pre-filter treats its own window.
1 parent e74ab5d commit bf99100

4 files changed

Lines changed: 24 additions & 7 deletions

File tree

bin/ethlambda/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,7 @@ async fn fetch_initial_state(
773773
mod tests {
774774
use super::*;
775775
use ethlambda_storage::backend::InMemoryBackend;
776+
use ethlambda_types::constants::DEFAULT_HEARTBEAT_COMMITTEE_SIZE;
776777
use ethlambda_types::genesis::GenesisValidatorEntry;
777778

778779
/// Validator-config snippet matching `lean-quickstart`'s ansible-devnet
@@ -898,6 +899,7 @@ validators:
898899
fn test_genesis(genesis_time: u64) -> GenesisConfig {
899900
GenesisConfig {
900901
genesis_time,
902+
heartbeat_committee_size: DEFAULT_HEARTBEAT_COMMITTEE_SIZE,
901903
genesis_validators: vec![GenesisValidatorEntry {
902904
attestation_pubkey: [1u8; 52],
903905
proposal_pubkey: [2u8; 52],

crates/blockchain/src/block_builder.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,10 @@ mod tests {
13251325
&advanced.justified_slots,
13261326
advanced.finalized_slot,
13271327
data.target.slot,
1328-
),
1328+
)
1329+
// Same reading as the packer's pre-filter: a slot the projection
1330+
// window does not track is not justified yet.
1331+
.unwrap_or(false),
13291332
"a heartbeat entry must not justify its target on tier alone"
13301333
);
13311334

@@ -1334,11 +1337,14 @@ mod tests {
13341337
// `advance` being inert.
13351338
let mut justified = empty_projection();
13361339
justified.advance(EntryEffect::Justifies, &data, HashSet::from([7]));
1337-
assert!(justified_slots_ops::is_slot_justified(
1338-
&justified.justified_slots,
1339-
justified.finalized_slot,
1340-
data.target.slot,
1341-
));
1340+
assert!(
1341+
justified_slots_ops::is_slot_justified(
1342+
&justified.justified_slots,
1343+
justified.finalized_slot,
1344+
data.target.slot,
1345+
)
1346+
.unwrap_or(false)
1347+
);
13421348
}
13431349

13441350
/// Under cap pressure the surviving heartbeat entries must be the

crates/blockchain/src/spec_test_runner.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ pub fn rejection_reason(err: &StoreError) -> Option<RejectionReason> {
9898
| StoreError::SignatureAggregationFailed(_)
9999
| StoreError::MissingTargetState(_)
100100
| StoreError::SlotOutOfRange(_) => return None,
101+
102+
// Placeholder: leanSpec names no rejection reason for the heartbeat tier
103+
// yet, so these report as unclassified until it does. Revisit once the
104+
// spec fixtures cover heartbeat vote validation.
105+
StoreError::HeartbeatVoteOutOfSlot { .. }
106+
| StoreError::NotHeartbeatCommitteeMember { .. } => return None,
101107
};
102108
Some(reason)
103109
}

crates/blockchain/src/store.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,10 @@ pub fn on_gossip_heartbeat_attestation(
710710
.ok_or(StoreError::MissingTargetState(data.target.root))?;
711711
let num_validators = target_state.validators.len() as u64;
712712
if validator_id >= num_validators {
713-
return Err(StoreError::InvalidValidatorIndex);
713+
return Err(StoreError::AttesterIndexOutOfRange {
714+
validator_index: validator_id,
715+
num_validators,
716+
});
714717
}
715718

716719
if !is_heartbeat_committee_member(

0 commit comments

Comments
 (0)