Skip to content

Commit 4e08fe2

Browse files
bomanapsArtiomTr
authored andcommitted
Gate attestations until justified checkpoint advances from anchor
1 parent a638435 commit 4e08fe2

3 files changed

Lines changed: 23 additions & 2 deletions

File tree

lean_client/fork_choice/src/handlers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ fn process_block_internal(
502502
"Store justified checkpoint updated!"
503503
);
504504
store.latest_justified = new_state.latest_justified.clone();
505+
store.justified_ever_updated = true;
505506
METRICS.get().map(|metrics| {
506507
let Some(slot) = new_state.latest_justified.slot.0.try_into().ok() else {
507508
warn!("unable to set latest_justified slot in metrics");

lean_client/fork_choice/src/store.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ pub struct Store {
3333

3434
pub latest_finalized: Checkpoint,
3535

36+
/// Set to `true` the first time `on_block` drives a justified checkpoint
37+
/// update beyond the initial anchor value. Validator duties (attestation,
38+
/// block proposal) must not run while this is `false` — the store's
39+
/// `latest_justified` is still the placeholder anchor checkpoint and using
40+
/// it as an attestation source would produce wrong source checkpoints.
41+
pub justified_ever_updated: bool,
42+
3643
pub blocks: HashMap<H256, Block>,
3744

3845
pub states: HashMap<H256, State>,
@@ -209,6 +216,7 @@ pub fn get_forkchoice_store(
209216
safe_target: block_root,
210217
latest_justified,
211218
latest_finalized,
219+
justified_ever_updated: false,
212220
blocks: [(block_root, block)].into(),
213221
states: [(block_root, anchor_state)].into(),
214222
latest_known_attestations: HashMap::new(),

lean_client/src/main.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -997,8 +997,20 @@ async fn main() -> Result<()> {
997997
let _ = sender.send(result);
998998
}
999999
ValidatorChainMessage::BuildAttestationData { slot, sender } => {
1000-
let result = store.read().produce_attestation_data(slot);
1001-
let _ = sender.send(result);
1000+
let store_read = store.read();
1001+
if !store_read.justified_ever_updated {
1002+
warn!(
1003+
slot = slot.0,
1004+
"Skipping attestation: justified checkpoint has not yet \
1005+
advanced from anchor — node is not ready to attest"
1006+
);
1007+
let _ = sender.send(Err(anyhow::anyhow!(
1008+
"not ready: justified checkpoint has not advanced from anchor value"
1009+
)));
1010+
} else {
1011+
let result = store_read.produce_attestation_data(slot);
1012+
let _ = sender.send(result);
1013+
}
10021014
}
10031015
}
10041016
}

0 commit comments

Comments
 (0)