# EPF6 - Week 16
## Overview
- Attended Lodestar Weekly Standups and [shared updates](https://github.com/ChainSafe/lodestar/wiki/Lodestar-Weekly-Standups-2025#epf-contributors-progress)
- Continued working on the `NodePair[]` recreation from Kurtosis, with the goal of achieving 1:1 assertion parity with the Docker-based flow.
- Continued refining and expanding the creation of **Beacon**, **Execution**, and **Validator** nodes to fully integrate into the new Kurtosis-based `NodePair[]`, ensuring 1:1 parity with Docker-based simulation flow.
- Investigated Engine API authentication via `SHARED_JWT_SECRET` and how to manage it in Kurtosis compared to Lodestar’s handling.
- Completed the removal of Docker-specific `Job` and `JobOptions` references, with related logic moved to utils/syncing.ts.
- Aligned the Kurtosis configuration to correctly manage shared JWT tokens between CL and EL clients.
## Main points
- **Node creation functions refinement**
- Implemented and reviewed:
- `createExecutionNodeFromKurtosis(service, executionType, nodeIndex, elExtraParams)`:
```typescript
private async createExecutionNodeFromKurtosis(
service: NodeService,
executionType: ExecutionClient,
nodeIndex: number,
elExtraParams: string[]
): Promise<ExecutionNode> {
// Ports for public and private URLs for the execution node (Kurtosis services)
const httpPort = this.getPort(service, "rpc", "http");
const engPort = this.getPort(service, "engine-rpc", "engine");
const ethRpcPublicUrl = httpPort ? `http://localhost:${httpPort}` : "";
const engineRpcPublicUrl = engPort ? `http://localhost:${engPort}` : "";
const provider = executionType === ExecutionClient.Mock ? null : new (await import("web3")).Web3(ethRpcPublicUrl);
if (provider) {
const {registerWeb3JsPlugins} = await import("../../web3js/plugins/index.js");
registerWeb3JsPlugins(provider);
}
if (elExtraParams.length > 0) {
this.logger.info(`EL ${service.id} extra params: ${elExtraParams.join(" ")}`);
}
return {
client: executionType,
id: `${service.id}-execution-${executionType}`,
ttd: BigInt(this.forkConfig.TERMINAL_TOTAL_DIFFICULTY),
engineRpcPublicUrl,
engineRpcPrivateUrl: engineRpcPublicUrl,
ethRpcPublicUrl,
ethRpcPrivateUrl: ethRpcPublicUrl,
jwtSecretHex: undefined, //Lodestar uses 'SHARED_JWT_SECRET', ethereum-package is hardcoded,
provider,
serviceContext: service.serviceContext,
};
}
→ Logs **elExtraParams** for traceability; keeps config minimal (URLs, jwt, provider, ttd).
- `createValidatorNodeFromKurtosis(service, validatorType, beacon, vcExtraParams)`
→ Logs **vcExtraParams**; builds KeyManager client using forkConfig.
- `createBeaconNodeFromKurtosis(service, beaconType)`
→ Builds API client from forkConfig
:::success
:bulb: These functions now aim to generate **assertion-ready node objects**, compatible with Lodestar’s existing test assertions.
:::
- **Validator client investigation**
- Found that in the current Kurtosis setup, VC services only exposed metrics and not HTTP endpoints.
- This conflicted with Lodestar’s KeyManager expectations (which typically live on the beacon REST).
- Patched configuration by enabling the **VC HTTP** interface through `keymanager_enabled: true` in the ethereum-package.
- After patching, VC services now expose both http-validator and metrics ports as expected.
- **Engine API and auth**
- Investigated how Lodestar handles the `SHARED_JWT_SECRET` for Engine API authentication.
- Aligned the Kurtosis configuration to correctly manage **shared JWT tokens** between CL and EL clients.
- Discussed with my mentor to confirm whether the `SHARED_JWT_SECRET` plays any active role in assertion management, since Lodestar and the ethereum-package each define their own hardcoded JWT secrets. I was concerned this mismatch could block a full migration.
- The mentor clarified that assertions use **public node APIs**, so the JWT is not involved in assertion logic. The JWT is only required for EL↔CL communication (execution node to beacon node), which Kurtosis handles internally. Therefore, **the difference in JWT handling does not affect the migration.**
## Learnings & Outcomes
- The Node creation logic now closely mirrors the Docker-based version and is in a draft state, pending end-to-end validation against `multiFork.test.ts`. Early checks suggest the structure aligns correctly, but full execution and assertion testing are still to come.
- `keymanager_enabled: true` was essential for proper validator client exposure.
- Kurtosis-based NodePair generation ensures that assertions (e.g., `nodeAssertion`, `accountBalanceAssertion`) can be reused without API modifications.
- **Next challenge**: confirm runtime **CL–EL wiring** in Kurtosis matches Docker behavior to ensure assertions reach all endpoints.
## Week 17 TODOs
- Commit the draft implementation of `NodePair[]` recreation to receive mentor feedback before proceeding with further testing.
- Verify assertion parity with **multiFork.test.ts**.
- Start outlining the final presentation for Devconnect on the migration work.
### Useful resources checked
[Lodestar JWT ethereum-package](https://github.com/ethpandaops/ethereum-package/blob/ae74385e68086c1984fcd4a4eba995d0cb09afa7/src/cl/lodestar/lodestar_launcher.star#L185)
[Lodestar GitHub JWT](https://github.com/ChainSafe/lodestar/blob/793f92c091c563a744a4cc4ec261e142d299853f/packages/cli/test/utils/crucible/constants.ts#L23)