**Motiviation**
All networks have completed the merge transition and most execution
clients no longer support pre-merge so it's not even possible anymore to
run a network from a genesis before bellatrix, unless you keep it to
phase0/altair only, which still works after this PR is merged.
This code is effectively tech debt, no longer exercised and just gets in
the way when doing refactors.
**Description**
Removes all code related to performing the merge transition. Running the
node pre-merge (CL only mode) is still possible and syncing still works.
Also removed a few CLI flags we added for the merge specifically, those
shouldn't be used anymore. Spec constants like
`TERMINAL_TOTAL_DIFFICULTY` are kept for spec compliance and ssz types
(like `PowBlock`) as well. I had to disable a few spec tests related to
handling the merge block since those code paths are removed.
Closes https://github.com/ChainSafe/lodestar/issues/8661
**Motivation**
- once we have `state-transition-z`, we're not able to get
`index2pubkey` from a light view of BeaconState in beacon-node
**Description**
- in `beacon-node`, use `index2pubkey` of BeaconChain instead as a
preparation for working with `state-transition-z`
- it's ok to use `state.epochCtx.index2pubkey` in `state-transition`
since it can access the full state there
part of #8652
---------
Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com>
**Motivation**
Provide npm provenance for published packages.
https://docs.npmjs.com/generating-provenance-statements
**Description**
- Use github runners for publish workflows to cover the error.
```
Error verifying sigstore provenance bundle: Unsupported GitHub Actions runner environment: "self-hosted". Only "github-hosted" runners are supported when publishing with provenance.
```
**Motivation**
Replace deprecated Holesky network support with Hoodi testnet
configuration. Hoodi is a new Ethereum testnet that will serve as a
replacement testnet, and this change updates Lodestar to support the new
network configuration.
**Description**
This PR removes Holesky network configuration and replaces all
references with Hoodi testnet support. Changes include:
- Removed `packages/cli/src/networks/holesky.ts` network file
- Removed `packages/config/src/chainConfig/networks/holesky.ts` chain
config
- Updated all network references from "holesky" to "hoodi" across CLI,
config, and test files
- Added Hoodi network configuration with proper chain parameters,
genesis data, and bootnodes
- Updated default environment configuration
- Updated unit tests to reflect the network change
<!-- Link to issues: https://github.com/ChainSafe/lodestar/issues/8595
-->
Closes #https://github.com/ChainSafe/lodestar/pull/8615
**AI Assistance Disclosure**
- [ ] External Contributors: I have read the [contributor
guidelines](https://github.com/ChainSafe/lodestar/blob/unstable/CONTRIBUTING.md#ai-assistance-notice)
and disclosed my usage of AI below.
<!-- Insert any AI assistance disclosure here -->
-PR content was developed using Cursor for code updates and
explanations; I reviewed and verified all changes manually.
Implement epbs state transition function.
Passes all operations, epoch_transition and rewards spec tests on v1.6.1
Part of #8439
---------
Co-authored-by: Nico Flaig <nflaig@protonmail.com>
**Motivation**
When requesting a future slot the node tries to dial the state from head
which allows to quite easily DoS the node as it's unbounded amount of
work if the slot is very far away from head.
We should not allow to request states that are in the future (> clock
slot) and return a 404 instead.
**Description**
In case state is request by slot, check if it's a slot from the future
based on clock slot and return 404 state not found error.
I didn't use `forkChoice.getHead().slot` because we should still be able
to serve the state if all slots between the requested slot and the head
slot are skipped.
Related [discord
discussion](https://discord.com/channels/593655374469660673/1387128551962050751/1445514034592878755),
thanks to @guha-rahul for catching and reporting this.
**Motivation**
- PR https://github.com/ChainSafe/lodestar/pull/4502 introduced a dev
testcontainers since @dadepo was having issues with docker
I really want to start decreasing our dependencies exposure, not
increasing it unless required. We have rolled our docker runners in the
past and should continue to do so.
**Description**
- Use adhoc docker
@dadepo I've removed the use of --network=host. If you have to run this
tests locally try to understand the incompatibilities and fix them
together without 3rd party libraries
---------
Co-authored-by: Cayman <caymannava@gmail.com>
Co-authored-by: Nico Flaig <nflaig@protonmail.com>
**Motivation**
- https://github.com/ChainSafe/lodestar/issues/8625
**Description**
Store indexed attestations for each block during block/signature
verification to avoid recomputing them during import
- compute `indexedAttestationsByBlock` once during verification
- enhance `FullyVerifiedBlock` to include indexed attestations for block
import
Closes https://github.com/ChainSafe/lodestar/issues/8625
Bumps
[mdast-util-to-hast](https://github.com/syntax-tree/mdast-util-to-hast)
from 13.1.0 to 13.2.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/syntax-tree/mdast-util-to-hast/releases">mdast-util-to-hast's
releases</a>.</em></p>
<blockquote>
<h2>13.2.1</h2>
<h4>Fix</h4>
<ul>
<li>ab3a795 Fix support for spaces in class names</li>
</ul>
<h4>Types</h4>
<ul>
<li>efb5312 Refactor to use <code>@import</code>s</li>
<li>a5bc210 Add declaration maps</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syntax-tree/mdast-util-to-hast/compare/13.2.0...13.2.1">https://github.com/syntax-tree/mdast-util-to-hast/compare/13.2.0...13.2.1</a></p>
<h2>13.2.0</h2>
<h4>Types</h4>
<ul>
<li>24f4576 Add type for <code>data.meta</code> on elements to hast</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syntax-tree/mdast-util-to-hast/compare/13.1.0...13.2.0">https://github.com/syntax-tree/mdast-util-to-hast/compare/13.1.0...13.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="174795b21f"><code>174795b</code></a>
13.2.1</li>
<li><a
href="3d05b3a715"><code>3d05b3a</code></a>
Update Node in Actions</li>
<li><a
href="ab3a79570a"><code>ab3a795</code></a>
Fix support for spaces in class names</li>
<li><a
href="efb5312310"><code>efb5312</code></a>
Refactor to use <code>@import</code>s</li>
<li><a
href="a5bc210f1a"><code>a5bc210</code></a>
Add declaration maps</li>
<li><a
href="b54955d4e1"><code>b54955d</code></a>
Add <code>.tsbuildinfo</code> to <code>.gitignore</code></li>
<li><a
href="f511a93817"><code>f511a93</code></a>
13.2.0</li>
<li><a
href="24f4576508"><code>24f4576</code></a>
Add type for <code>data.meta</code> on elements to hast</li>
<li><a
href="feeec02562"><code>feeec02</code></a>
Update dev-dependencies</li>
<li>See full diff in <a
href="https://github.com/syntax-tree/mdast-util-to-hast/compare/13.1.0...13.2.1">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/ChainSafe/lodestar/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
**Motivation**
- The era package was not mentioned in the readme.
**Description**
<!-- A clear and concise general description of the changes of this pull
request. -->
<!-- If applicable, add screenshots to help explain your solution -->
<!-- Link to issues: Resolves#111, Resolves#222 -->
**AI Assistance Disclosure**
- [x] External Contributors: I have read the [contributor
guidelines](https://github.com/ChainSafe/lodestar/blob/unstable/CONTRIBUTING.md#ai-assistance-notice)
and disclosed my usage of AI below.
<!-- Insert any AI assistance disclosure here -->
**Motivation**
- Era validation lacked genesis slot signature verification skip
**Description**
- Adds a check for genesis slot and skips signature verification for
slot 0 in ERA validation
**AI Assistance Disclosure**
- [x] External Contributors: I have read the [contributor
guidelines](https://github.com/ChainSafe/lodestar/blob/unstable/CONTRIBUTING.md#ai-assistance-notice)
and disclosed my usage of AI below.
No AI is used.
<!-- Insert any AI assistance disclosure here -->
**Motivation**
There is a concept documented in the specs called
[safe-block](https://github.com/ethereum/consensus-specs/blob/master/fork_choice/safe-block.md).
Wanted to introduce that concept in our codebase so upcoming feature of
`fcr` have less invasive changes.
**Description**
- Expose functions `getSafeBeaconBlockRoot` and
`getSafeExecutionBlockHash` from `fork-choice` package.
- Update the usage of `safeBlock` to use those functions
---------
Co-authored-by: Nico Flaig <nflaig@protonmail.com>
**Motivation**
We don't wanna skip slots if slot processing takes longer than slot
duration in a distributed setup as delays might get caused by hanging
HTTP requests due to DVT middleware not reaching the signature
threshold.
**Description**
Adds new flag `--clock.skipSlots` (default: `true`) to validator client
to allow disabling skipping slots by setting it to `false`.
**Note:** it will always be set to `false` if `--distributed` flag is
set as the behavior is not desired in a DVT cluster as assumptions about
beacon node change and skipping slots does more harm than good.
Related issue https://github.com/ChainSafe/lodestar/issues/5314
**Motivation**
- https://github.com/ChainSafe/lodestar/issues/8624
**Description**
- Cache serialized data column sidecars (from gossip and reqresp)
- Use serialized data column sidecars (if available) when persisting to
db (for engine, ~10 per slot, they will not be available, so they will
still be reserialized)
**Motivation**
- I found we verify proposer signatures multiple times per slot. On
hoodi it takes 20ms to 40ms, if we receive all DataColumnSidecars by
gossip it would be a lot of time
<img width="1594" height="294" alt="Screenshot 2025-11-20 at 15 15 01"
src="https://github.com/user-attachments/assets/6797bb8b-e4a6-4b10-a939-30fc45658f45"
/>
proposer signatures are verified when we receive gossip block,
BlobSidecar or DataColumnSidecar
**Description**
- enhance `SeenBlockInput` with a map to cache verified proposer
signature by slot + root hex
- verify Block/Blob/DataColumnSidecar proposer signature on main thread
and cache. It will takes ~30ms to do that, and we only have to do it
once per slot
part of #8619
**Testing**
- [x] deployed to feat4
- [x] monitor result
---------
Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com>
**Motivation**
We have been seeing too much AI slop from external contributors to this
repository. This PR aims to establish a norm of disclosure when any AI
assistance is used in a PR.
**Description**
This PR modifies the pull request template. This also removes an unused
section of the PR template which lists how to reproduce the solution.
This pull request closes #issue_number
**AI Assistance Disclosure**
- [x] External Contributors: I have read the [contributor
guidelines](https://github.com/ChainSafe/lodestar/blob/unstable/CONTRIBUTING.md#ai-assistance-notice)
and disclosed my usage of AI below.
I did not use any to create this PR.
---------
Co-authored-by: Nico Flaig <nflaig@protonmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
**Motivation**
After discussion we decided to stick with `napi` bindings instead of
`bun:ffi` to reduce the risk of vendor lock-in.
**Description**
- Remove all usages of `@lodestar/bun`
- Remove all conditional `imports` for packages related to `bun:ffi`
**Steps to test or reproduce**
- Run all tests
**Motivation**
- tracks #7048
-
[era](https://github.com/eth-clients/e2store-format-specs/blob/main/formats/era.md)
specs.
**Description**
- Adds functionality to read/write to
[e2s](613f4a9a50/docs/e2store.md (era-files))
files
```ts
import {open} from "node:fs/promises";
import {e2s} from "@lodestar/era";
const fh = await open("mainnet-xxxxxx-xxxxxxxx.era");
const entry = await e2s.readEntry(fh, 0);
entry.type == e2s.EntryType.Version
```
- Adds functionality to read/write era files
```ts
import {era} from "@lodestar/era";
import {config} from "@lodestar/config/default";
// open reader
const reader = await era.EraReader.open(config, "mainnet-xxxxx-xxxxxxxx.era");
// check number of groups
reader.groups.length === 1;
// read blocks
const slot = reader.groups[0].startSlot;
// return snappy-frame compressed, ssz-serialized block at slot or null if a skip slot
// throws if out of range
await reader.readCompressedBlock(slot);
// same, but for ssz-serialized block
await reader.readSerializedBlock(slot);
// same but for deserialized block
await reader.readBlock(slot);
// read state(s), one per group
// similar api to blocks, but with an _optional_ eraNumber param for specifying which group's state to read
await reader.readCompressedState();
await reader.readSerializedState();
await reader.readState();
// write era files
const writer = await era.EraWriter.create(config, "path/to/era");
// similar api to reader, can write compressed, serialized, or deserialized items
// first write all blocks for the era
await writer.writeBlock(block);
// ...
// then write the state
await writer.writeState(state);
// if applicable, continue writing eras of blocks and state (an era file can contain multiple eras, or "groups" as the spec states)
// when finished, must call `finish`, which will close the file handler and _rename_ the file to the spec-compliant name
await writer.finish();
```
- e2e test reads an era file, does all validation, writes an era fila,
does validation on that freshly created file
- requires the era file fixture to be downloaded (`cd packages/era/test
&& ./download_era_file.sh`)
- e2e test is skipped (`test:e2e` is not defined for the era package)
---------
Co-authored-by: Cayman <caymannava@gmail.com>
**Motivation**
Improve type check performance.
**Description**
- Improve the type check performance which was degraded in recent
changes. From `100s` to `8s` for `beacon-node` package.
```
time yarn check-types
yarn run v1.22.22
$ tsc
✨ Done in 105.85s.
yarn check-types 108.35s user 2.59s system 104% cpu 1:46.08 total
```
vs
```
time yarn check-types
yarn run v1.22.22
$ tsc
✨ Done in 8.46s.
yarn check-types 14.60s user 0.86s system 178% cpu 8.661 total
```
**Steps to test or reproduce**
- Run all jobs
**Motivation**
Update the vitest to avoid using third party test pool.
**Description**
- Use latest vitest
- Remove custom process pool which we developed to run our tests in Bun
runtime
- Migrate test configs to latest version
- Update types
- Switch to playwright from webdriverio for browser tests performance,
which was due for long.
**Steps to test or reproduce**
- Run all tests
Adds proposer duties v2 endpoint which works the same as v1 but uses
previous epoch to determine dependent root to account for deterministic
proposer lookahead changes in fulu.
https://github.com/ethereum/beacon-APIs/pull/563
We are already including the version (eg. `lodestar/v1.36.0`), there
doesn't seem to be much of a benefit in terms of security to not include
the commit hash as well and it helps debugging especially in early
testnets or release candidates as there the version number is the same
while it might run a different commit.
We do have the `--private` flag to avoid including any information about
the client on p2p.
**Motivation**
A bug was found on hoodi that needs to be rectified.
1) 1st column arrives via gossip
2) trigger getBlobsV2
3) many more columns (but not all) come via gossip
4) gossip block arrives
5) reqresp triggered via block arrival
6) get remaining data via reqresp
7) process blockInput
8) delete cached blockInput
9) remaining columns arrive via gossip and get added to a new BlockInput
10) getBlobsV2 finishes and gossips "missing" columns not found on new
BlockInput
11) reqresp gets triggered again after timeout (from second batch of
gossip columns on second BlockInput)
12) second batch of columns and second block get reqresp downloaded and
second block Input goes for processing
---------
Co-authored-by: Nico Flaig <nflaig@protonmail.com>
**Motivation**
Client teams have been instructed to increase default gas limits to 60M
for Fusaka.
**Description**
This will ensure that validators signal 60M by default and updates
docs/tests to work with the new 60M configuration.
---------
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>