# Running a Facet Node

## Introduction

To run a Facet node you will need two pieces of software: [facet-node](https://github.com/0xFacet/facet-node) and [facet-geth](https://github.com/0xFacet/facet-geth). This architecture follows the Consensus/Execution split on the Ethereum L1, with `facet-node` acting as the consensus client and `facet-geth` as the execution layer.

facet-geth is a fork of Optimism's op-geth. facet-node is modeled after op-node, though it isn't a fork.

#### How it works

1. `facet-node` connects to an L1 Ethereum RPC server and monitors each L1 block for Facet transactions—i.e., transactions whose "to: address is `address(0xface7)` or event logs whose first topic is `bytes32(uint256(0xface7))`.
2. `facet-node` extracts the Facet transaction information and combines it with other data to form a transaction payload that `facet-geth` can understand (this is called a "Deposit Transaction").
3. `facet-node` constructs a Facet block with these Deposit transactions and sends the block to `facet-geth` using the [engine API](https://github.com/ethereum/execution-apis/tree/main/src/engine). This is the same API Ethereum consensus clients use to tell the execution layer about new blocks.

`facet-node` is stateless. All data required to operate `facet-node` is stored in `facet-geth.`

### Facet Genesis State

Facet's genesis block includes state from its initial pre-EVM implementation, \[legacy] Facet. This state is deterministically generated by executing the latest Facet logic against historical \[legacy] Facet transactions. From the perspective of running a Facet node all you need is the final genesis.json file which is included in the `facet-geth` repository.

### Run a Node with Docker Compose

Ensure you have Docker or [Docker Desktop](https://www.docker.com/products/docker-desktop/) installed.

Clone `facet-node`:

```
git clone https://github.com/0xFacet/facet-node
cd facet-node/docker-compose
mv .env.sample .env
```

Now edit `.env`. The defaults should be fine but you need to add your own `L1_RPC_URL`.

Finally, start the node:

```
docker compose up
```

And that's it!

### Run a Node without Docker

* Clone `facet-node`:

  ```
  git clone https://github.com/0xFacet/facet-node
  ```

  and `facet-geth`:

  ```
  git clone https://github.com/0xFacet/facet-geth
  ```
* Now `cd facet-node`
* Install Ruby Version Manager (RVM) if not already installed:

  ```
  \curl -sSL https://get.rvm.io | bash -s stable
  ```

  If you encounter GPG issues, run:

  ```
  gpg2 --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDBd
  ```
* Install Ruby 3.3.4:

  ```
  rvm install 3.3.4
  ```

  On macOS, if you encounter OpenSSL issues:

  ```
  rvm install 3.3.4 --with-openssl-dir=$(brew --prefix openssl@1.1)
  ```
* Run `rvm use 3.3.4`
* Run `bundle install`
* Set up Foundry (make sure you install it first):

  ```
  cd contracts && forge soldeer install --recursive-deps && forge build && cd ..
  ```
* Set up environment variables. First copy the .sample.env files to .env.

  ```
  cp .sample.env .env 
  ```

  Now edit the files. Here's what the variables are for:

<table><thead><tr><th width="290">Variable</th><th>Description</th><th width="164">Default/Example</th><th>Purpose</th></tr></thead><tbody><tr><td>L1_NETWORK</td><td>Ethereum network to derive blocks from</td><td>"sepolia" or "mainnet"</td><td>Determines which Ethereum network Facet will sync from</td></tr><tr><td>L1_GENESIS_BLOCK</td><td>Starting L1 block number</td><td>21373000</td><td>Block number to start syncing from. Mainnet genesis: 21373000, Sepolia genesis: 7201200</td></tr><tr><td>LOCAL_GETH_DIR</td><td>Path to local geth directory</td><td>"/path/to/geth_dir"</td><td>Location where facet-geth is cloned</td></tr><tr><td>GETH_RPC_URL</td><td>Authenticated RPC endpoint</td><td>"http://127.0.0.1:8551"</td><td>Used for authenticated connections to facet-geth</td></tr><tr><td>NON_AUTH_GETH_RPC_URL</td><td>Non-authenticated RPC endpoint</td><td>"http://127.0.0.1:8545"</td><td>Used for non-authenticated connections to facet-geth</td></tr><tr><td>GETH_DISCOVERY_PORT</td><td>P2P discovery port</td><td>"30303"</td><td>Port used by facet-geth for peer discovery</td></tr><tr><td>BLOCK_IMPORT_BATCH_SIZE</td><td>Number of blocks per batch</td><td>"5"</td><td>Controls how many simultaneous RPC requests are made</td></tr><tr><td>L1_RPC_URL</td><td>Ethereum RPC endpoint</td><td>"https://eth_rpc_url"</td><td>Source of L1 block data</td></tr><tr><td>JWT_SECRET</td><td>Authentication secret</td><td>"0x0101..."</td><td>Must match value in /tmp/jwtsecret for auth</td></tr><tr><td>MIGRATION_MODE</td><td>Enable migration features</td><td>"false"</td><td>Only needed when creating genesis file</td></tr><tr><td>FACET_V1_VM_DATABASE_URL</td><td>Legacy database connection</td><td>""</td><td>Only needed when creating genesis file</td></tr></tbody></table>

* Put a JWT\_SECRET in `/tmp/jwtsecret` on your local machine:

  ```
  openssl rand -hex 32 | awk '{print "0x"$1}' > /tmp/jwtsecret
  ```
* Run the tests to ensure everything works.

  ```
  rspec && cd contracts && forge test -vv && cd ..
  ```

### Using `facet-geth`

To use `facet-geth` to process blocks instead of just in a test:

1. From the `facet-node` directory, generate the geth initialization command.

   <pre><code><strong>bundle exec rake geth:init_command
   </strong></code></pre>
2. Copy the command, cd back into `facet-geth`, and run it. Note, this command will restart the chain from genesis, deleting any blocks you've already derived. If you want to just restart geth without doing this you should only run the /build/bin/geth command.
3. Finally, cd back into `facet-node` and start deriving Facet blocks from L1 blocks:

   ```
   bundle exec clockwork config/derive_facet_blocks.rb
   ```

You should now have `facet-node` and `facet-geth` set up and running!

### Accessing Facet Data

You can use the geth's normal RPC API to get information about Facet blocks and transactions. For example `eth_getBlockByNumber`. You can also query the chain directly from the geth console which the above command launches. For example `eth.getBlock(1)`.

From the perspective of querying data, Facet will behave identically to any other EVM chain.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.facet.org/guides/running-a-facet-node.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
