feat: use local checkpoint state for holesky-rescue - #7509
Merged
Merged
Conversation
Member
Author
|
was able to start from local checkpoint state in db |
twoeths
force-pushed
the
te/start_from_local_ws_state
branch
from
February 28, 2025 06:35
36b577e to
e189e52
Compare
Member
Author
|
was able to load local checkpoint state from file |
twoeths
force-pushed
the
te/start_from_local_ws_state
branch
from
February 28, 2025 09:17
6e939fb to
46543d5
Compare
This reverts commit 4d2bd7b.
twoeths
force-pushed
the
te/start_from_local_ws_state
branch
from
March 4, 2025 09:05
1afbddc to
e898a9b
Compare
twoeths
marked this pull request as ready for review
March 5, 2025 11:37
nflaig
reviewed
Mar 5, 2025
Member
Author
|
I deployed the latest commit to |
twoeths
commented
Mar 7, 2025
| startEpoch: Math.min(computeEpochAtSlot(local.headSlot), remote.finalizedEpoch), | ||
| // startEpoch: Math.min(computeEpochAtSlot(local.headSlot), remote.finalizedEpoch), | ||
| // for holesky-rescue, we don't want to sync from finalizedEpoch which is too far away (115967) | ||
| startEpoch: computeEpochAtSlot(local.headSlot), |
Member
Author
There was a problem hiding this comment.
this is not correct in case we sync from the last finalized checkpoint
once we got on a wrong fork, we cannot recover
for example this is the wrong fork
8527:Mar-06 17:56:30.653[chain] verbose: Block processed slot=3711858, root=0xb6b21a75a1587c3af9037946a564a58548edeac52d028b0abdd7ec9b0baeed04, delaySec=839094.6530001163
8558:Mar-06 17:56:31.076[chain] verbose: Block processed slot=3711860, root=0x7b0aeb3fd90bd78e2f70c38f64fc7d94abeda215581793c3d111fdac325ab26a, delaySec=839071.0759999752
9586:Mar-06 17:56:59.940[chain] verbose: Block processed slot=3711964, root=0xd0165ccec1ebba1a08c1c69a070acf9df638f7acca1922591f530683c541c945, delaySec=837851.9400000572
9634:Mar-06 17:57:02.911[chain] verbose: Block processed slot=3711974, root=0xfe1d75c5b393401b2dd01fe85fb103a1485055f47c7299089ec7da6aecf2fff1, delaySec=837734.9110000134
correct one should be
4291:Mar-06 17:56:00.593[chain] verbose: Block processed slot=3711858, root=0xb6b21a75a1587c3af9037946a564a58548edeac52d028b0abdd7ec9b0baeed04, delaySec=839064.5929999352
4326:Mar-06 17:56:01.020[chain] verbose: Block processed slot=3711860, root=0x7b0aeb3fd90bd78e2f70c38f64fc7d94abeda215581793c3d111fdac325ab26a, delaySec=839041.0199999809
4395:Mar-06 17:56:06.181[chain] verbose: Block processed slot=3711901, root=0xe372ed53b4badda9eb1f8db5549649a77886c88e91aa92f5ff3b0c934562bc1c, delaySec=838554.1809999943
4463:Mar-06 17:56:09.686[chain] verbose: Block processed slot=3711913, root=0xcd2f0403e62139d1e77440d66df9abacc2c706e45527e95cc51569c9d328de9a, delaySec=838413.6860001087
4509:Mar-06 17:56:10.090[chain] verbose: Block processed slot=3711917, root=0x69a749989af18cf9f77f433b4af321ee3d0f2ffaecde9c84c86cddd7fc13f2b8, delaySec=838366.0899999142
so need to distinguish 2 cases:
- if sync from finalized checkpoint state:
startEpoch: Math.min(computeEpochAtSlot(local.headSlot), remote.finalizedEpoch)(same logic) - if sync from unfinalized checkpoint state:
startEpoch: Math.min(computeEpochAtSlot(local.headSlot), Math.max(remote.finalizedEpoch, computeEpochAtSlot(trustedHead.slot)))
2 tasks
nflaig
added a commit
that referenced
this pull request
Mar 10, 2025
**Motivation** - implement an api to get a node synced asap **Description** - new api: `eth/v1/lodestar/persisted_checkpoint_state` to return a state based on an optional `rootHex:epoch` param - if not specified, return the latest safe checkpoint state - a node need to specify `--checkpointState` from the previous PR #7509 **Test** - [x] `curl -H "Accept: application/octet-stream" http://localhost:9596/eth/v1/lodestar/persisted_checkpoint_state -o latest_checkpoint_state.ssz` - [x] `curl -H "Accept: application/octet-stream" http://localhost:9596/eth/v1/lodestar/persisted_checkpoint_state?checkpoint_id=0x4f4d4c1b81141fe77a4a1c6a376dbe64ed9baa8f123664195e4f710c9fc4238d:118936 -o state_epoch_118936.ssz` --------- Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com> Co-authored-by: Nico Flaig <nflaig@protonmail.com>
nflaig
pushed a commit
that referenced
this pull request
Sep 30, 2025
**Motivation** - we already have local checkpoint states in either db or file, this PR use one of them to save syncing time the next time the node is restarted - see #7504 (comment) **Description** 2 new init unfinalized state options: - new `--lastPersistedCheckpointState`, true by default to load from the last safe persisted checkpoint state. And the last safe persisted checkpoint state is considered unfinalized - use `--checkpointState` option: this is old option and support finalized state only, this PR supports booting from unfinalized state similar to `--lastPersistedCheckpointState` ==> to quickly sync a new node, we can use this option. Then remove it and the next time node will use `--lastPersistedCheckpointState` option by default - we can configure one of our nodes with `chain.nHistoricalStatesFileDataStore = true` - then feed other nodes with a persisted "safe checkpoint state" from there in `~/checkpoint_states` folder - a persisted checkpoint state is consider to be safe to boot if - it should be the checkpoint state that's unique in its epoch - its last processed block slot should be at epoch boundary or last slot of previous epoch - state slot should be at epoch boundary - state slot should be equal to epoch * SLOTS_PER_EPOCH other options to boot from `stateArchived` or `checkpointSyncUrl` are considered finalized states including `wssCheckpoint`. It's not possible to use `wssCheckpoint` option with unfinalized state for now. **TODO** - this is for `holesky-rescue`, consider supporting this for `unstable` branch too - update document in that case --------- Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com>
nflaig
added a commit
that referenced
this pull request
Oct 1, 2025
**Motivation** - implement an api to get a node synced asap **Description** - new api: `eth/v1/lodestar/persisted_checkpoint_state` to return a state based on an optional `rootHex:epoch` param - if not specified, return the latest safe checkpoint state - a node need to specify `--checkpointState` from the previous PR #7509 **Test** - [x] `curl -H "Accept: application/octet-stream" http://localhost:9596/eth/v1/lodestar/persisted_checkpoint_state -o latest_checkpoint_state.ssz` - [x] `curl -H "Accept: application/octet-stream" http://localhost:9596/eth/v1/lodestar/persisted_checkpoint_state?checkpoint_id=0x4f4d4c1b81141fe77a4a1c6a376dbe64ed9baa8f123664195e4f710c9fc4238d:118936 -o state_epoch_118936.ssz` --------- Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com> Co-authored-by: Nico Flaig <nflaig@protonmail.com>
This was referenced Oct 17, 2025
nflaig
added a commit
that referenced
this pull request
Oct 17, 2025
wemeetagain
pushed a commit
that referenced
this pull request
Oct 22, 2025
**Motivation** This was a feature we developed for [rescuing Holesky](https://blog.chainsafe.io/lodestar-holesky-rescue-retrospective/) as part of #7501 to quickly sync nodes to head during a period of long non-finality (~3 weeks). While it's unlikely we will have such a long period of non-finality on mainnet, this feature is still useful to have for much shorter periods and testing purposes on devnets. It is now part of [Ethereum protocol hardening](https://github.com/eth-clients/diamond) mitigations described [here](https://github.com/eth-clients/diamond/blob/main/mitigations/nfin-checkpoint-001.md) > Ordinary checkpoint sync begins from the latest finalized checkpoint (block and/or state). As an escape hatch during non-finality, it is useful to have the ability to checkpoint sync from an unfinalized checkpoint. A client implementing this mitigation MUST support checkpoint sync from an arbitrary non-finalized checkpoint state. We will support this with the exception that our checkpoint state needs to be an epoch boundary checkpoint. **Description** The main feature of this PR is to allow initializing a node from an unfinalized checkpoint state either retrieved locally or from a remote source. This behavior is disabled by default but can be enabled by either adding - the `--lastPersistedCheckpointState` flag to load from the last safe persisted checkpoint state stored locally - or `--unsafeCheckpointState` to provide a file path or url to an unfinalized checkpoint state to start syncing from which can be used with new endpoint `GET /eth/v1/lodestar/persisted_checkpoint_state` to sync from a remote node or by sharing states from `checkpoint_states` folder Both of these options are not safe to use on a network that recently finalized an epoch and must only be considered if syncing from last finalized checkpoint state is unfeasible. An unfinalized checkpoint state persisted locally is only considered to be safe to boot if - it's the only checkpoint in it's epoch to avoid ambiguity from forks - its last processed block slot is at an epoch boundary or last slot of previous epoch - state slot is at an epoch boundary - state slot is equal to `epoch * SLOTS_PER_EPOCH` But even if these criteria are met, there is chance that the node will end up on a minority chain as it will not be able to pivot to another chain that conflicts with the checkpoint state it was initialized from. Other existing flags (like `--checkpointState`) are unchanged by this PR and will continue to expect a finalized checkpoint state. Previous PRs #7509, #7541, #7542 not merged to unstable are included. Closes #7963 cc @twoeths --------- Co-authored-by: twoeths <10568965+twoeths@users.noreply.github.com> Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Description
2 new init unfinalized state options:
new
--lastPersistedCheckpointState, true by default to load from the last safe persisted checkpoint state. And the last safe persisted checkpoint state is considered unfinalizeduse
--checkpointStateoption: this is old option and support finalized state only, this PR supports booting from unfinalized state similar to--lastPersistedCheckpointState==> to quickly sync a new node, we can use this option. Then remove it and the next time node will use--lastPersistedCheckpointStateoption by defaultwe can configure one of our nodes with
chain.nHistoricalStatesFileDataStore = truethen feed other nodes with a persisted "safe checkpoint state" from there in
~/checkpoint_statesfoldera persisted checkpoint state is consider to be safe to boot if
other options to boot from
stateArchivedorcheckpointSyncUrlare considered finalized states includingwssCheckpoint. It's not possible to usewssCheckpointoption with unfinalized state for now.TODO
holesky-rescue, consider supporting this forunstablebranch too