diff --git a/clients/reth/Dockerfile b/clients/reth/Dockerfile new file mode 100644 index 0000000000..27c0789474 --- /dev/null +++ b/clients/reth/Dockerfile @@ -0,0 +1,28 @@ +ARG baseimage=paradigmxyz/reth +ARG tag=main + +FROM $baseimage:$tag as builder + +# Install script tools. +RUN apt-get update -y +RUN apt-get install -y bash curl jq + +# Add genesis mapper script. +ADD genesis.json /genesis.json +ADD mapper.jq /mapper.jq + +# Add the startup script. +ADD reth.sh /reth.sh +RUN chmod +x /reth.sh + +# Add the enode URL retriever script. +ADD enode.sh /hive-bin/enode.sh +RUN chmod +x /hive-bin/enode.sh + +# Create version.txt +RUN /usr/local/bin/reth --version | sed -e 's/reth \(.*\)/\1/' > /version.txt + +# Export the usual networking ports to allow outside access to the node. +EXPOSE 8545 8546 30303 30303/udp + +ENTRYPOINT ["/reth.sh"] diff --git a/clients/reth/enode.sh b/clients/reth/enode.sh new file mode 100644 index 0000000000..489756f280 --- /dev/null +++ b/clients/reth/enode.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +TARGET_RESPONSE=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"admin_nodeInfo","params":[],"id":1}' "127.0.0.1:8545" ) +TARGET_ENODE=$(echo ${TARGET_RESPONSE}| jq -r '.result.enode') + +echo "$TARGET_ENODE" diff --git a/clients/reth/genesis.json b/clients/reth/genesis.json new file mode 100644 index 0000000000..7ca6f39f73 --- /dev/null +++ b/clients/reth/genesis.json @@ -0,0 +1,15 @@ +{ + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x42", + "gasLimit" : "0x2fefd8", + "mixHash" : "0x2c85bcbce56429100b2108254bb56906257582aeafcbd682bc9af67a9f5aee46", + "nonce" : "0x78cc16f7b4f65485", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp" : "0x54c98c81", + "alloc" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance" : "0x09184e72a000" + } + } +} diff --git a/clients/reth/mapper.jq b/clients/reth/mapper.jq new file mode 100644 index 0000000000..858223a2af --- /dev/null +++ b/clients/reth/mapper.jq @@ -0,0 +1,59 @@ +# Removes all empty keys and values in input. +def remove_empty: + . | walk( + if type == "object" then + with_entries( + select( + .value != null and + .value != "" and + .value != [] and + .key != null and + .key != "" + ) + ) + else . + end + ) +; + +# Converts decimal string to number. +def to_int: + if . == null then . else .|tonumber end +; + +# Converts "1" / "0" to boolean. +def to_bool: + if . == null then . else + if . == "1" then true else false end + end +; + +# Replace config in input. +. + { + "config": { + "ethash": (if env.HIVE_CLIQUE_PERIOD then null else {} end), + "clique": (if env.HIVE_CLIQUE_PERIOD == null then null else { + "period": env.HIVE_CLIQUE_PERIOD|to_int, + } end), + "chainId": (if env.HIVE_CHAIN_ID == null then 1 else env.HIVE_CHAIN_ID|to_int end), + "homesteadBlock": env.HIVE_FORK_HOMESTEAD|to_int, + "daoForkBlock": env.HIVE_FORK_DAO_BLOCK|to_int, + "daoForkSupport": env.HIVE_FORK_DAO_VOTE|to_bool, + "eip150Block": env.HIVE_FORK_TANGERINE|to_int, + "eip150Hash": env.HIVE_FORK_TANGERINE_HASH, + "eip155Block": env.HIVE_FORK_SPURIOUS|to_int, + "eip158Block": env.HIVE_FORK_SPURIOUS|to_int, + "byzantiumBlock": env.HIVE_FORK_BYZANTIUM|to_int, + "constantinopleBlock": env.HIVE_FORK_CONSTANTINOPLE|to_int, + "petersburgBlock": env.HIVE_FORK_PETERSBURG|to_int, + "istanbulBlock": env.HIVE_FORK_ISTANBUL|to_int, + "muirGlacierBlock": env.HIVE_FORK_MUIR_GLACIER|to_int, + "berlinBlock": env.HIVE_FORK_BERLIN|to_int, + "londonBlock": env.HIVE_FORK_LONDON|to_int, + "arrowGlacierBlock": env.HIVE_FORK_ARROW_GLACIER|to_int, + "grayGlacierBlock": env.HIVE_FORK_GRAY_GLACIER|to_int, + "terminalTotalDifficulty": env.HIVE_TERMINAL_TOTAL_DIFFICULTY|to_int, + "terminalTotalDifficultyPassed": env.HIVE_TERMINAL_TOTAL_DIFFICULTY_PASSED|to_bool, + "shanghaiTime": env.HIVE_SHANGHAI_TIMESTAMP|to_int, + }|remove_empty +} diff --git a/clients/reth/reth.sh b/clients/reth/reth.sh new file mode 100644 index 0000000000..1a4d092205 --- /dev/null +++ b/clients/reth/reth.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +# Startup script to initialize and boot a reth instance. +# +# This script assumes the following files: +# - `reth` binary is located in the filesystem root +# - `genesis.json` file is located in the filesystem root (mandatory) +# - `chain.rlp` file is located in the filesystem root (optional) +# - `blocks` folder is located in the filesystem root (optional) +# +# This script can be configured using the following environment variables: +# +# - HIVE_BOOTNODE enode URL of the remote bootstrap node +# - HIVE_NETWORK_ID network ID number to use for the eth protocol +# - HIVE_FORK_HOMESTEAD block number of the homestead transition +# - HIVE_FORK_DAO_BLOCK block number of the DAO hard-fork transition +# - HIVE_FORK_TANGERINE block number of TangerineWhistle +# - HIVE_FORK_SPURIOUS block number of SpuriousDragon +# - HIVE_FORK_BYZANTIUM block number for Byzantium transition +# - HIVE_FORK_CONSTANTINOPLE block number for Constantinople transition +# - HIVE_FORK_PETERSBURG block number for ConstantinopleFix/Petersburg transition +# - HIVE_FORK_ISTANBUL block number for Istanbul transition +# - HIVE_FORK_MUIR_GLACIER block number for MuirGlacier transition +# - HIVE_LOGLEVEL client log level +# +# These flags are NOT supported by reth +# +# - HIVE_TESTNET whether testnet nonces (2^20) are needed +# - HIVE_GRAPHQL_ENABLED turns on GraphQL server +# - HIVE_CLIQUE_PRIVATEKEY private key for clique mining +# - HIVE_NODETYPE sync and pruning selector (archive, full, light) +# - HIVE_SKIP_POW If set, skip PoW verification during block import +# - HIVE_MINER address to credit with mining rewards +# - HIVE_MINER_EXTRA extra-data field to set for newly minted blocks + +# Immediately abort the script on any error encountered +set -ex + +# no ansi colors +export RUST_LOG_STYLE=never + +reth=/usr/local/bin/reth + +case "$HIVE_LOGLEVEL" in + 0|1) FLAGS="$FLAGS -v" ;; + 2) FLAGS="$FLAGS -vv" ;; + 3) FLAGS="$FLAGS -vvv" ;; + 4) FLAGS="$FLAGS -vvvv" ;; + 5) FLAGS="$FLAGS -vvvvv" ;; +esac + +# Create the data directory. +mkdir /reth-hive-datadir +FLAGS="$FLAGS --datadir /reth-hive-datadir" + +# TODO If a specific network ID is requested, use that +#if [ "$HIVE_NETWORK_ID" != "" ]; then +# FLAGS="$FLAGS --networkid $HIVE_NETWORK_ID" +#else +# FLAGS="$FLAGS --networkid 1337" +#fi + +# Configure the chain. +mv /genesis.json /genesis-input.json +jq -f /mapper.jq /genesis-input.json > /genesis.json + +# Dump genesis +echo "Supplied genesis state:" +cat /genesis.json + +echo "Command flags till now:" +echo $FLAGS + +# Initialize the local testchain with the genesis state +echo "Initializing database with genesis state..." +$reth init $FLAGS --chain /genesis.json + +# make sure we use the same genesis each time +FLAGS="$FLAGS --chain /genesis.json" + +# Don't immediately abort, some imports are meant to fail +set +ex + +# Load the test chain if present +echo "Loading initial blockchain..." +if [ -f /chain.rlp ]; then + RUST_LOG=info $reth import $FLAGS /chain.rlp +else + echo "Warning: chain.rlp not found." +fi + +# Load the remainder of the test chain +echo "Loading remaining individual blocks..." +if [ -d /blocks ]; then + echo "Loading remaining individual blocks..." + for file in $(ls /blocks | sort -n); do + echo "Importing " $file + $reth import $FLAGS /blocks/$file + done +else + echo "Warning: blocks folder not found." +fi + +# Only set boot nodes in online steps +# It doesn't make sense to dial out, use only a pre-set bootnode. +if [ "$HIVE_BOOTNODE" != "" ]; then + FLAGS="$FLAGS --bootnodes=$HIVE_BOOTNODE" +fi + +# Configure any mining operation +# TODO +#if [ "$HIVE_MINER" != "" ]; then +# FLAGS="$FLAGS --mine --miner.etherbase $HIVE_MINER" +#fi +#if [ "$HIVE_MINER_EXTRA" != "" ]; then +# FLAGS="$FLAGS --miner.extradata $HIVE_MINER_EXTRA" +#fi + +# Import clique signing key. +# TODO +#if [ "$HIVE_CLIQUE_PRIVATEKEY" != "" ]; then +# # Create password file. +# echo "Importing clique key..." +# echo "$HIVE_CLIQUE_PRIVATEKEY" > ./private_key.txt +# +# # Ensure password file is used when running geth in mining mode. +# if [ "$HIVE_MINER" != "" ]; then +# FLAGS="$FLAGS --miner.sigfile private_key.txt" +# fi +#fi + +# If clique is expected enable auto-mine +if [ -n "${HIVE_CLIQUE_PRIVATEKEY}" ] || [ -n "${HIVE_CLIQUE_PERIOD}" ]; then + FLAGS="$FLAGS --auto-mine" +fi + +# Configure RPC. +FLAGS="$FLAGS --http --http.addr=0.0.0.0 --http.api=admin,debug,eth,net,web3" +FLAGS="$FLAGS --ws --ws.addr=0.0.0.0 --ws.api=admin,debug,eth,net,web3" + +# Enable continuous sync if there is no CL (ttd == "") and mining is disabled +if [ -z "${HIVE_MINER}" ] && [ -z "${HIVE_CLIQUE_PRIVATEKEY}" ] && [ -z "${HIVE_TERMINAL_TOTAL_DIFFICULTY}" ]; then + # if there is no chain file then we need to sync with the continuous + # download mode + if [ ! -f /chain.rlp ]; then + FLAGS="$FLAGS --debug.continuous" + fi +fi + + +if [ "$HIVE_TERMINAL_TOTAL_DIFFICULTY" != "" ]; then + JWT_SECRET="7365637265747365637265747365637265747365637265747365637265747365" + echo -n $JWT_SECRET > /jwt.secret + FLAGS="$FLAGS --authrpc.addr=0.0.0.0 --authrpc.jwtsecret=/jwt.secret" +fi + +# Configure NAT +FLAGS="$FLAGS --nat none" + +# Launch the main client. +echo "Running reth with flags: $FLAGS" +RUST_LOG=info $reth node $FLAGS