# Lighthouse Beacon Node Startup To understand the Engine API flow for starting up a beacon node, I want to learn what happens behind the scenes when you launch Lighthouse with the beacon node command. I'll be focusing on the interactions with the execution layer. Including how is the EL node represented, which Engine API endpoints are called, etc. I will ignore a lot of functionality not related to the EL. You can check [Jimmy Chen](https://github.com/jimmygchen)'s [article](https://hackmd.io/@jimmygchen/Sk9oPHO8s) for a slightly different focus. Let's analyze what happens when you run this on your terminal: [1] ```bash lighthouse bn \ --network mainnet \ --execution-endpoint http://localhost:8551 \ --execution-jwt /secrets/jwt.hex \ --checkpoint-sync-url https://mainnet.checkpoint.sigp.io \ --disable-deposit-contract-sync ``` Here's a detailed version of the process: ![node-startup-detailed](https://hackmd.io/_uploads/SJc2vQvep.png) *You can find this diagram in higher quality [here.](https://github.com/danielrachi/diagrams/blob/main/rendered/lighthouse-startup.png)* This diagram goes deep into what function is called where, but here's a more general overview of the process: 1. Lighthouse is started, using the command I mentioned above. This runs the lighthouse main function. 2. In the lighthouse main function, the code relevant to the `bn` command (short for `beacon_node`) is run. 3. Everything after `bn` in the provided command are configuration flags. That config is parsed into a `ClientConfig` struct. - One of the fields of the `ClientConfig` is an `execution_layer::Config`. It contains info about the EL client that Lighthouse will communicate with to run the node. The info from the CLI is used to build this struct. E.g. the `--execution-endpoint` flag is parsed into `execution_endpoints: Vec<SensitiveUrl>`. 4. The `ClientConfig` built in the previous step is used to build a `ClientBuilder`. - One of the fields of the `ClientBuilder` is a `BeaconChainBuilder`. That one has an `execution_layer: Option<ExecutionLayer<T::EthSpec>>`. - To fill the `execution_layer` field of the `BeaconChainBuilder`, an `ExecutionLayer` struct is built from the `execution_layer::Config` field of the `ClientConfig`. 6. The `ClientBuilder` of the previous step is consumed to start all necessary processes and build a `Client`. - The first step to take is to consume the `BeaconChainBuilder`. Which up to this point was storing our representation of the EL client. The `ExecutionClient` gets transferred directly to the `BeaconChain` that is being built. - Other important services of the node are started. Specifically: the networking stack, notifier and Prometheus metrics. - With everything ready, the `ClientBuilder` is consumed. This does a lot of stuff, but what matters for the scope of this article is a call to `BeaconChain::update_execution_engine_forkchoice`. Note that this is a method of the `BeaconChain`, where our `ExecutionLayer` is currently stored. - `update_execution_engine_forkchoice` starts a series of function calls [2]. The bottom of these calls are Engine API endpoints! Specifically: - [`engine_exchangeCapabilities`](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md#engine_exchangecapabilities) - [`engine_forkchoiceUpdatedV2`](https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_forkchoiceupdatedv2) or [`engine_forkchoiceUpdatedV1`](https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_forkchoiceupdatedv1) ### Final thoughts In my [Flashbots article](https://hackmd.io/@danielrachi/HJxXjUwC2), I mentioned that there might be a minimal set of Engine API endpoints that can be implemented in a Portal Client just to start a CL client. Well, it looks like I found them! ~~I don't know how far can a CL client go only with those endpoints. I guess I'll figure that out as I learn more about the Engine API and make sequence diagrams to visualize the main flows of it.~~ [Here's the article with those diagrams.](https://hackmd.io/@danielrachi/engine_api) The CL client won't go very far with those endpoints, it'll eventually start calling `engine_newPayload`. But besides that, it should be able to perform validator tasks with only those endpoints and a builder client attached to it. ### Notes [1] This is the command that the [lighthouse book](https://lighthouse-book.sigmaprime.io/run_a_node.html#non-staking) suggests using to start a non-staker node. The startup process described in the article is the same for launching the node with the staker command. [2] You might be wondering what's the point of calling functions that just call other functions. Well: 1) I'm ignoring a lot of functionality, 2) There are a lot of parameters to prepare and other things to do before calling some of the functions, and 3) In rust the error handling gets quite extensive in programs this big, so wrapping a function just to prepare its arguments and handle its errors is not something crazy.