Flow Gateway Node setup

Prerequisites

Generate Node Information

# get the binary
curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/boot-tools.tar
# untar it
tar -xvf boot-tools.tar
# verify sha256sum: a06e3e9b2443c6755214150e9e101b70dd48ae30ffcfcbbcc471ba430cb104bf
sha256sum ./boot-tools/bootstrap
# create a directory
mkdir ./bootstrap
# Use a fully qualified domain name for YOUR_NODE_ADDRESS_GOES_HERE. Please also include the port number in the network address e.g. flowaccess.mycompany.com:3569
./boot-tools/bootstrap key --address "<YOUR_NODE_ADDRESS_GOES_HERE>:3569" --role access -o ./bootstrap
Bash

Get you node id

cat ./bootstrap/public-root-information/node-id && echo ""
Bash

All your private keys should be in the bootstrap folder created earlier. Please take a back up of the entire folder.

Stake 100 FLOW

The minimum 100 is required to prevent certain vulnerabilities in the smart contract that are a result of having a zero minimum stake requirement. Follow this guide to stake using Flow Port

All fields required are generated here:

cat ./bootstrap/public-root-information/node-info.pub.* | jq
Bash
{
  "Role": "access",
  "Address": "flowaccess.mycompany.com:3569",
  "NodeID": "e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5",
  "Weight": 0,
  "NetworkPubKey": "f493a74704f6961ae7903e062ecd58d990672858eff99aece7bfbccf3aa02de8f1a624ecbf21a01e8b2f4a5854c231fbe218edd7762a34fea881f3958a215305",
  "StakingPubKey": "ae8dcf81f3a70d72036b7ba2c586ed37ed0eb82b9c0a4aab998a8420f98894f94c14f84fa716e93654d3940fc0c8ff4d19b504c90a5b4918b28f421e9d3659dc2b7e246025ebeffea0d83cceefe315d7ed346dbe412fdac51b64997d97d29f7e"
}
JSON

Create an address to use with the faucet here on testnet

Verify That Your Node ID Was Selected

On Wednesday at around 12:00 UTC, the staking auction for the current epoch will end and five nodes from candidate list of nodes will be chosen at random by the staking contract to be part of the next epoch. If all 5 slots have been taken from the previous epoch, then no new access nodes will be chosen

There are several ways to verify whether your node was chosen as explained below When you stake the node, the tokens will show up under the tokensCommitted bucket. After the staking auction ends, if the node is selected, the tokens remain in the tokensCommitted bucket and are moved to the tokensStaked bucket at the end of the epoch. If the node is not selected, the tokens are moved to the tokensUnstaked bucket.

# install flow cli
sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)"
echo 'export PATH="$PATH:/root/.local/bin"' >> ~/.profile
source ~/.profile
Bash

You can check via Flow Port or using flow accounts staking-info

# You can check the balance using Flow Cli. Once you have downloaded and installed Flow Cli, you can query the account balance using the command
flow accounts staking-info your_account_address -n mainnet
Bash
# You can check the balance using Flow Cli. Once you have downloaded and installed Flow Cli, you can query the account balance using the command
flow accounts staking-info your_account_address -n testnet
Bash

Look for the Tokens Staked field in the response of the above command to verify

Get binaries

curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/binary/access/app
chmod +x app
mv app /usr/bin/access-node
Bash

Create services

Use systemctl to set up services for Access Node, Gateway

Access Node

# Define the variables
NODE_ID=$(cat ./bootstrap/public-root-information/node-info.pub.* | jq -r .NodeID)
DYNAMIC_ACCESS_ADDRESS="secure.mainnet.nodes.onflow.org:9001"
DYNAMIC_ACCESS_PUBLICKEY="28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae"
Bash
# Define the variables
NODE_ID=$(cat ./bootstrap/public-root-information/node-info.pub.* | jq -r .NodeID)
DYNAMIC_ACCESS_ADDRESS="secure.testnet.nodes.onflow.org:9001"
DYNAMIC_ACCESS_PUBLICKEY="ba69f7d2e82b9edf25b103c195cd371cf0cc047ef8884a9bbe331e62982d46daeebf836f7445a2ac16741013b192959d8ad26998aff12f2adc67a99e1eb2988d"

Bash
sudo tee <<EOF >/dev/null /etc/systemd/system/access-node.service
[Unit]
Description=Access Node daemon
After=network-online.target

[Service]
User=$USER
ExecStart=/usr/bin/access-node \
--nodeid=$NODE_ID \
--bootstrapdir=$PWD/bootstrap \
--datadir=$PWD/data/protocol \
--secretsdir=$PWD/data/secrets \
--execution-data-dir=$PWD/data/execution_data \
--rpc-addr=0.0.0.0:9000 \
--state-stream-addr=0.0.0.0:9000 \
--secure-rpc-addr=0.0.0.0:9001 \
--http-addr=0.0.0.0:8000 \
--rest-addr=0.0.0.0:8070 \
--admin-addr=localhost:9002 \
--bind=0.0.0.0:3569 \
--dht-enabled=false \
--grpc-compressor=gzip \
--profiler-dir=$PWD/data/profiler \
--dynamic-startup-access-address=$DYNAMIC_ACCESS_ADDRESS \
--dynamic-startup-access-publickey=$DYNAMIC_ACCESS_PUBLICKEY \
--dynamic-startup-epoch-phase=EpochPhaseStaking
Restart=always
RestartSec=3
LimitNOFILE=4096

[Install]
WantedBy=multi-user.target
EOF

cat /etc/systemd/system/access-node.service
sudo systemctl enable access-node
Bash

Build gateway

git clone https://github.com/onflow/flow-evm-gateway.git
cd flow-evm-gateway
go build -o evm-gateway cmd/main/main.go
mv evm-gateway /usr/bin/
Bash

EVM Gateway

Each EVM Gateway operator needs to create an account on Flow as well as an account on EVM. The first one will be used to pay for fees on Flow, which means it needs to be sufficiently funded and monitored for balance (it shouldn’t fall to 0 without refunding it, as of now the node doesn’t monitor these, but will be added in the future, however, the funding won’t so it should be done manually). The second EVM account will be used to get refunded fees on EVM. That account shouldn’t have to be monitored for balance as the balance will always grow.

flow keys generate
Bash

It will generate an output like this

🔴️ Store private key safely and don't share with anyone!
Private Key              5438b13e290b257f0c41e3b23fbf3b5f5f6d4e9b2d3797430d2d2d5484db9b37
Public Key               9b85626369efe380ebd701f7189f2746fda26d09e1b63cb003bd84a5d33b662685c56427a0526a670efa88b0cb8da371cf9dc1de5ac6bbffb56e327a5c16e708
Mnemonic                 sustain limb elbow awkward onion crouch truth trial until poverty famous feel
Derivation Path          m/44'/539'/0'/0/0
Signature Algorithm      ECDSA_P256
Bash

Visit https://faucet.flow.com, and use the generated Public Key, to create and fund your Flow account. Make sure to use the Flow address and the Private Key for the —coa-address & —coa-key flags.

ACCESS_NODE_GRPC_HOST="your_domian:9000"
FLOW_NETWORK_ID="flow-mainnet"
INIT_CADENCE_HEIGHT="211176670" # to be confirmed
COINBASE="your_evm_address_without_0x"
COA_ADDRESS="your_flow_address"
COA_KEY="your_private_key"
GAS_PRICE="100" # feel free to experiment with different values
Bash
ACCESS_NODE_GRPC_HOST="your_domian:9000"
FLOW_NETWORK_ID="flow-testnet"
INIT_CADENCE_HEIGHT="211176670"
COINBASE="your_evm_address_without_0x"
COA_ADDRESS="your_flow_address"
COA_KEY="your_private_key"
GAS_PRICE="100" # feel free to experiment with different values
Bash
sudo tee <<EOF >/dev/null /etc/systemd/system/gateway.service
[Unit]
Description=Gateway daemon
After=network-online.target

[Service]
User=$USER
ExecStart=/usr/bin/evm-gateway \
--access-node-grpc-host=$ACCESS_NODE_GRPC_HOST \
--flow-network-id=$FLOW_NETWORK_ID \
--init-cadence-height=$INIT_CADENCE_HEIGHT \
--ws-enabled=true \
--coa-resource-create=true \
--coinbase=$COINBASE \
--coa-address=$COA_ADDRESS \
--coa-key=$COA_KEY \
--gas-price=$GAS_PRICE
Restart=always
RestartSec=3
LimitNOFILE=4096

[Install]
WantedBy=multi-user.target
EOF

cat /etc/systemd/system/gateway.service
sudo systemctl enable gateway
Bash

Start all services

Order of operations:

  1. access-node: ensure it’s fully synced before proceeding
  2. gateway
sudo systemctl daemon-reload
sudo systemctl restart access-node
sudo systemctl restart gateway
Bash

For access node, Compare the flow height explorer mainnet testnet

flow blocks get latest --host localhost:9000
Bash

For gateway

curl -s -XPOST 'localhost:8545' --header 'Content-Type: application/json' --data-raw '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' | jq
Bash

Check logs

# change log settings to persistent if not already
sed -i 's/#Storage=auto/Storage=persistent/g' /etc/systemd/journald.conf
sudo systemctl restart systemd-journald

journalctl -u access-node.service -f -n 100
journalctl -u gateway.service -f -n 100
Bash

Logs should look like

{"level":"info","component":"ingestion","cadence-height":211179523,"cadence-event-length":1,"time":"2024-09-07T15:35:08Z","message":"received new cadence evm events"}
{"level":"info","component":"ingestion","hash":"0xa3e86dbe8a454d7f84908fc3af5ea3e335f4ab33bce8127f43243eb987505020","evm-height":2853,"cadence-height":211179523,"cadence-id":"872cda9894505a8357daa493d45fa99d2632b8a36a556e013df01506c5f893da","parent-hash":"0xa9b37ac67550b5b96490270b49b78fca35ff701b92bf37a6b7f6193050681bf4","tx-hashes-root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","time":"2024-09-07T15:35:08Z","message":"new evm block executed event"}
{"level":"info","component":"ingestion","cadence-height":211179524,"cadence-event-length":1,"time":"2024-09-07T15:35:08Z","message":"received new cadence evm events"}
{"level":"info","component":"ingestion","hash":"0x0c7706407fd79496a845c2a337ecbf551fb670ba5ff864e42d94b6897d71474b","evm-height":2854,"cadence-height":211179524,"cadence-id":"5bd1d53fe3e3125d980dee8d9a75b8998d64d1710acacc1f4df0ad52ab4140f6","parent-hash":"0xa3e86dbe8a454d7f84908fc3af5ea3e335f4ab33bce8127f43243eb987505020","tx-hashes-root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","time":"2024-09-07T15:35:08Z","message":"new evm block executed event"}
{"level":"info","component":"ingestion","cadence-height":211179525,"cadence-event-length":1,"time":"2024-09-07T15:35:08Z","message":"received new cadence evm events"}
{"level":"info","component":"ingestion","hash":"0x42d7665cc17c04170eb77e2b14f7adbfbf30a5ac65d5b36a98a2857798a7a33f","evm-height":2855,"cadence-height":211179525,"cadence-id":"df6a5ddbd669f56c44dc1f4c6701e00c323eedc6a6cd0a14593aeeed9000ea25","parent-hash":"0x0c7706407fd79496a845c2a337ecbf551fb670ba5ff864e42d94b6897d71474b","tx-hashes-root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","time":"2024-09-07T15:35:08Z","message":"new evm block executed event"}
{"level":"info","component":"ingestion","cadence-height":211179526,"cadence-event-length":1,"time":"2024-09-07T15:35:08Z","message":"received new cadence evm events"}
{"level":"info","component":"ingestion","hash":"0x7e248dd506b721faeece565382d1f310665c2faa5a0882b49f039b73eddb0b34","evm-height":2856,"cadence-height":211179526,"cadence-id":"d34dc88006ebd8ce3e82af11d9668f864c7a9a274e4583c392fe367fc210294c","parent-hash":"0x42d7665cc17c04170eb77e2b14f7adbfbf30a5ac65d5b36a98a2857798a7a33f","tx-hashes-root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","time":"2024-09-07T15:35:08Z","message":"new evm block executed event"}
{"level":"info","component":"ingestion","cadence-height":211179527,"cadence-event-length":1,"time":"2024-09-07T15:35:08Z","message":"received new cadence evm events"}
{"level":"info","component":"ingestion","hash":"0x133702b182bdff543bfccd0bf380b28a6b4a9de2c1d2123b14601b522bd49a33","evm-height":2857,"cadence-height":211179527,"cadence-id":"e886a98d565f11119f6f38950145c7c86ebf438dbd6c296d88bfac8d72857ccc","parent-hash":"0x7e248dd506b721faeece565382d1f310665c2faa5a0882b49f039b73eddb0b34","tx-hashes-root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","time":"2024-09-07T15:35:08Z","message":"new evm block executed event"}
Bash
Edit this page