Running Optimism Archive Node for TheGraph MIPs Program

Olga L
3 min readJun 7, 2023

Minimum Hardware requirements
- CPU: 4 Cores / 8 Threads
- RAM: 16 GiB
- Storage: 4 TiB NVMe SSD

You need two components running — DTL and L2 GETH

Pre-requisites

sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y

sudo apt install -y git make wget gcc pkg-config libusb-1.0-0-dev libudev-dev jq gcc g++ curl libssl-dev apache2-utils build-essential pkg-config

# Add to PATH
echo "export PATH="$PATH:/root/.foundry/bin:/usr/local/go/bin:/root/.local/bin"" >> /root/.bashrc

source /root/.bashrc

# Install go
wget https://go.dev/dl/go1.19.4.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go1.19.4.linux-amd64.tar.gz

# Install nvm
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash

# Download foundry
curl -L https://foundry.paradigm.xyz | bash

# Install foundry
foundryup

source /root/.bashrc

# Install node and yarn
nvm install 16 && npm install --global yarn && nvm use 16

source /root/.bashrc

# Check if go and npm are installed:
go version
nvm -v
npm -v
yarn -v

# Set symlinks for node and npm
sudo ln -s "$(which node)" /usr/bin/node
sudo ln -s "$(which npm)" /usr/bin/npm

Building Optimism DTL

cd /root/
git clone -b master https://github.com/ethereum-optimism/optimism.git
cd optimism
yarn
yarn build
mkdir -p /root/.local/share/optimism/dtl/datadir

Setting up the Systemd file for Optimism DTL

[Unit]
Description=Optimism DTL Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=200000
WorkingDirectory=/root/optimism/packages/data-transport-layer/
ExecStart=/root/.nvm/versions/node/v16.20.0/bin/yarn start
EnvironmentFile=/root/optimism/packages/data-transport-layer/.env

KillSignal=SIGHUP

[Install]
WantedBy=multi-user.target

Setting up the config file

# READ THIS CAREFULLY:

# You can either sync the DTL from ETH L1 or OP L2
# You need an Ethereum Mainnet RPC endpoint (can be full node or archive) if you want to sync from ETH L1
# You need an Alchemy Optimism endpoint if you want to sync from OP L2
# If you want to sync from L1, set DATA_TRANSPORT_LAYER__SYNC_FROM_L1=true and DATA_TRANSPORT_LAYER__SYNC_FROM_L2=false
# If you want to do it the other way, set them the other way around
# Same for ROLLUP_BACKEND=l1, if you're syncing from L2, change it to l2

# Syncing from L1 will always be 2000 blocks behind chainhead due to how rollups work.
# Recommended to sync from L2 via a free Alchemy account

echo "###### DTL ENV ######

DATA_TRANSPORT_LAYER__ADDRESS_MANAGER=0xdE1FCfB0851916CA5101820A69b13a4E276bd81F
DATA_TRANSPORT_LAYER__L1_START_HEIGHT=13596466
DATA_TRANSPORT_LAYER__CONFIRMATIONS=12
DATA_TRANSPORT_LAYER__DANGEROUSLY_CATCH_ALL_ERRORS=true
DATA_TRANSPORT_LAYER__DB_PATH=/root/.local/share/optimism/dtl/datadir
DATA_TRANSPORT_LAYER__ENABLE_METRICS=true
DATA_TRANSPORT_LAYER__ETH_NETWORK_NAME=mainnet
DATA_TRANSPORT_LAYER__L2_CHAIN_ID=10
DATA_TRANSPORT_LAYER__LOGS_PER_POLLING_INTERVAL=2000
DATA_TRANSPORT_LAYER__NODE_ENV=production
DATA_TRANSPORT_LAYER__POLLING_INTERVAL=500
DATA_TRANSPORT_LAYER__SENTRY_TRACE_RATE=0.05
DATA_TRANSPORT_LAYER__SERVER_HOSTNAME=0.0.0.0
DATA_TRANSPORT_LAYER__SERVER_PORT=7878
DATA_TRANSPORT_LAYER__TRANSACTIONS_PER_POLLING_INTERVAL=1000
DATA_TRANSPORT_LAYER__SYNC_FROM_L1=false
DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT=http://ip:port
DATA_TRANSPORT_LAYER__SYNC_FROM_L2=true
DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT=https://opt-mainnet.g.alchemy.com/v2/PROJECTID

###### L2 GETH OP ENV ######

NETWORK_NAME=mainnet
NODE_TYPE=archive
USING_OVM=true
SEQUENCER_CLIENT_HTTP=https://mainnet.optimism.io
BLOCK_SIGNER_ADDRESS=0x00000398232E2064F896018496b4b44b3D62751F
BLOCK_SIGNER_PRIVATE_KEY=6587ae678cf4fc9a33000cdbf9f35226b71dcc6a4684a31203241f9bcfd55d27
ETH1_CTC_DEPLOYMENT_HEIGHT=13596466
ETH1_SYNC_SERVICE_ENABLE=true
ROLLUP_CLIENT_HTTP=http://0.0.0.0:7878
ROLLUP_MAX_CALLDATA_SIZE=40000
ROLLUP_POLL_INTERVAL_FLAG=1s
ROLLUP_VERIFIER_ENABLE=true
ROLLUP_DISABLE_TRANSFERS=false
ROLLUP_ENABLE_L2_GAS_POLLING=false
ROLLUP_GAS_PRICE_ORACLE_OWNER_ADDRESS=0x648E3e8101BFaB7bf5997Bd007Fb473786019159
ROLLUP_BACKEND=l2


###### L2 GETH ENV ######

GCMODE=archive
CACHE=32768
DATADIR=/root/.local/share/optimism/l2geth/datadir
CHAIN_ID=10
NETWORK_ID=10
NO_DISCOVER=true
NO_USB=true
GASPRICE=0
TARGET_GAS_LIMIT=15000000
RPC_ADDR=0.0.0.0
RPC_API=eth,rollup,net,web3,debug
RPC_CORS_DOMAIN=*
RPC_ENABLE=true
RPC_PORT=9656
RPC_VHOSTS=*
WS_ADDR=0.0.0.0
WS_API=eth,rollup,net,web3,debug
WS_ORIGINS=*
WS=true

Run DTL

systemctl daemon-reload
systemctl restart dtl
# Viewing Logs
journalctl -fu dtl

Building and preparing L2 GETH

cd /root/optimism/l2geth
make geth
mkdir -p /root/.local/share/optimism/l2geth/genesis/
mkdir -p /root/.local/share/optimism/l2geth/datadir/

# Download the genesis file
wget -O /root/.local/share/optimism/l2geth/genesis/genesis.json https://storage.googleapis.com/optimism/mainnet/genesis-berlin.json

# Init L2 GETH - this takes a while depending on your machine's specs
set -o allexport; source /root/optimism/packages/data-transport-layer/.env; set +o allexport; /root/optimism/l2geth/build/bin/geth init --datadir=/root/.local/share/optimism/l2geth/datadir /root/.local/share/optimism/l2geth/genesis/genesis.json --no-usb

# Import the block signer account
touch $DATADIR/password
echo $BLOCK_SIGNER_PRIVATE_KEY > $DATADIR/block-signer-key

/root/optimism/l2geth/build/bin/geth account import --datadir=$DATADIR --password $DATADIR/password $DATADIR/block-signer-key

Setting up the Systemd file for Optimism L2 GETH

[Unit]
Description=Optimism L2 GETH Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=200000
WorkingDirectory=/root/optimism
EnvironmentFile=/root/optimism/packages/data-transport-layer/.env
ExecStart=/root/optimism/l2geth/build/bin/geth \
--datadir=/root/.local/share/optimism/l2geth/datadir \
--password=/root/.local/share/optimism/l2geth/datadir/password \
--allow-insecure-unlock \
--unlock=0x00000398232E2064F896018496b4b44b3D62751F \
--mine \
--miner.etherbase=0x00000398232E2064F896018496b4b44b3D62751F \
--vmodule=eth/*=5,miner=4,rpc=5,rollup=4,consensus/clique=1 \
--cache=32768

KillSignal=SIGHUP

[Install]
WantedBy=multi-user.target

Run l2geth

systemctl daemon-reload
systemctl restart l2geth
# journalctl -fu l2geth

Serve subgraphs

If you want to serve multiple chains, the recommended option is to use Graph Node’s toml file and add a new chain under [chains] section.

[chains.${CHAIN_0_NAME}]
shard = "primary"
provider = [ { label = "${CHAIN_0_NAME}", url = "${CHAIN_0_RPC}", features = ["archive", "traces"] } ]

# Read more about it with included examples
# https://github.com/graphprotocol/graph-node/blob/master/docs/config.md#configuring-ethereum-providers

Serve subgraphs on Goerli:
1. Sport Markets Optimism (MIPs) QmdC27G3EXQQhh3fx24zCuadJ4KN7zK47wWwxfHTr64Hv9
2. Velodrome Optimism (MIPs) Qmdo7tHRi6nBc4StvF5qn3secT7Ccms7tSc2Zfhx9PiK3b
3. Beethoven X Optimism (MIPs) Qmc4Z52rAHkFdhAXLHQLL68zFVAPK86K85BSNzQkUQQK2m

Adding a rule for subgraphs

graph indexer rules set <deploymentId> decisionBasis always allocationAmount <amount>

--

--