diff --git a/clients/ethereumjs/Dockerfile b/clients/ethereumjs/Dockerfile new file mode 100644 index 0000000000..09307bfd9e --- /dev/null +++ b/clients/ethereumjs/Dockerfile @@ -0,0 +1,28 @@ +FROM node:16-alpine as build +RUN apk update && apk add --no-cache bash git jq curl && rm -rf /var/cache/apk/* +RUN git clone --depth 1 https://github.com/ethereumjs/ethereumjs-monorepo.git && \ + (cd ethereumjs-monorepo && npm i) + +RUN cd ethereumjs-monorepo/packages/client && npx ethereumjs --version > /version.txt + +ADD ethereumjs.sh /ethereumjs.sh +ADD mapper.jq /mapper.jq +ADD jwtsecret /jwtsecret +RUN chmod +x /ethereumjs.sh + +# Inject the enode id retriever script +RUN mkdir /hive-bin +ADD enode.sh /hive-bin/enode.sh +RUN chmod +x /hive-bin/enode.sh + +ADD genesis.json /genesis.json + +# Export the usual networking ports to allow outside access to the node +EXPOSE 8545 8546 8550 8547 30303 30303/udp + +# NodeJS applications have a default memory limit of 2.5GB. +# This limit is bit tight, it is recommended to raise the limit +# since memory may spike during certain network conditions. +ENV NODE_OPTIONS=--max_old_space_size=6144 + +ENTRYPOINT ["/ethereumjs.sh"] \ No newline at end of file diff --git a/clients/ethereumjs/enode.sh b/clients/ethereumjs/enode.sh new file mode 100755 index 0000000000..332614c374 --- /dev/null +++ b/clients/ethereumjs/enode.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Script to retrieve the enode +# +# This is copied into the validator container by Hive +# and used to provide a client-specific enode id retriever +# + +# Immediately abort the script on any error encountered +set -e + +data='{"jsonrpc":"2.0","method":"admin_nodeInfo","params":[],"id":1}' +TARGET_RESPONSE=$(curl -s -X POST -H "Content-Type: application/json" --data $data "localhost:8545" ) +TARGET_ENODE=$(echo ${TARGET_RESPONSE}| jq -r '.result.enode') +echo "$TARGET_ENODE" \ No newline at end of file diff --git a/clients/ethereumjs/ethereumjs.sh b/clients/ethereumjs/ethereumjs.sh new file mode 100644 index 0000000000..09ed02a487 --- /dev/null +++ b/clients/ethereumjs/ethereumjs.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# Startup script to initialize and boot a ethereum-js instance. +# +# This script assumes the following files: +# - `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) +# - `keys` folder is located in the filesystem root (optional) +# +# This script assumes 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_TESTNET whether testnet nonces (2^20) are needed +# - HIVE_NODETYPE sync and pruning selector (archive, full, light) +# +# Forks: +# +# - HIVE_FORK_HOMESTEAD block number of the homestead hard-fork transition +# - HIVE_FORK_DAO_BLOCK block number of the DAO hard-fork transition +# - HIVE_FORK_DAO_VOTE whether the node support (or opposes) the DAO fork +# - HIVE_FORK_TANGERINE block number of Tangerine Whistle transition +# - HIVE_FORK_SPURIOUS block number of Spurious Dragon transition +# - 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_MUIRGLACIER block number for Muir Glacier transition +# - HIVE_FORK_BERLIN block number for Berlin transition +# - HIVE_FORK_LONDON block number for London +# +# Clique PoA: +# +# - HIVE_CLIQUE_PERIOD enables clique support. value is block time in seconds. +# - HIVE_CLIQUE_PRIVATEKEY private key for clique mining +# +# Other: +# +# - HIVE_MINER enable mining. value is coinbase address. +# - HIVE_MINER_EXTRA extra-data field to set for newly minted blocks +# - HIVE_SKIP_POW if set, skip PoW verification during block import +# - HIVE_LOGLEVEL client loglevel (0-5) +# - HIVE_GRAPHQL_ENABLED enables graphql on port 8545 +# - HIVE_LES_SERVER set to '1' to enable LES server + + +# Immediately abort the script on any error encountered +set -e + +ethereumjs="node /ethereumjs-monorepo/packages/client/dist/bin/cli.js" +FLAGS="--gethGenesis ./genesis.json --rpc --rpcEngine --saveReceipts --rpcEnginePort 8551 --ws --loglevel debug" + + +# 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 + +# Import clique signing key. +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 ethereumjs in mining mode. + if [ "$HIVE_MINER" != "" ]; then + FLAGS="$FLAGS --mine --unlock ./private_key.txt --minerCoinbase $HIVE_MINER" + fi +fi + +if [ "$HIVE_TERMINAL_TOTAL_DIFFICULTY" != "" ]; then + FLAGS="$FLAGS --jwt-secret ./jwtsecret" +fi + +FLAGS="$FLAGS --bootnodes=$HIVE_BOOTNODE" +echo "Running ethereumjs with flags $FLAGS" +$ethereumjs $FLAGS \ No newline at end of file diff --git a/clients/ethereumjs/genesis.json b/clients/ethereumjs/genesis.json new file mode 100644 index 0000000000..ed3dc4e3eb --- /dev/null +++ b/clients/ethereumjs/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/ethereumjs/jwtsecret b/clients/ethereumjs/jwtsecret new file mode 100644 index 0000000000..7daae6cf23 --- /dev/null +++ b/clients/ethereumjs/jwtsecret @@ -0,0 +1 @@ +0x7365637265747365637265747365637265747365637265747365637265747365 \ No newline at end of file diff --git a/clients/ethereumjs/mapper.jq b/clients/ethereumjs/mapper.jq new file mode 100644 index 0000000000..690421cd13 --- /dev/null +++ b/clients/ethereumjs/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, + "epoch": 30000 + } end), + "chainId": env.HIVE_CHAIN_ID|to_int, + "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, + "yolov2Block": env.HIVE_FORK_BERLIN|to_int, + "yolov3Block": env.HIVE_FORK_BERLIN|to_int, + "londonBlock": env.HIVE_FORK_LONDON|to_int, + "mergeForkBlock": env.HIVE_MERGE_BLOCK_ID|to_int, + "terminalTotalDifficulty": env.HIVE_TERMINAL_TOTAL_DIFFICULTY|to_int, + }|remove_empty +}