forked from ethereum/hive
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from 0xcary/sync
add sync
- Loading branch information
Showing
7 changed files
with
665 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Build the simulator. | ||
FROM golang:1-alpine AS builder | ||
RUN apk --no-cache add gcc musl-dev linux-headers | ||
ADD . /sync | ||
WORKDIR /sync | ||
RUN go build . | ||
|
||
# Build the runner container. | ||
FROM alpine:latest | ||
ADD . / | ||
COPY --from=builder /sync/sync /sync | ||
ENTRYPOINT ["./sync"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module github.com/ethereum/hive/simulators/ethereum/sync | ||
|
||
go 1.17 | ||
|
||
require ( | ||
github.com/ethereum/go-ethereum v1.10.26 | ||
github.com/ethereum/hive v0.0.0-20230302111537-d7cb48a5d324 | ||
) | ||
|
||
require ( | ||
github.com/btcsuite/btcd v0.22.0-beta // indirect | ||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect | ||
github.com/deckarep/golang-set v1.8.0 // indirect | ||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect | ||
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect | ||
github.com/go-ole/go-ole v1.2.6 // indirect | ||
github.com/go-stack/stack v1.8.1 // indirect | ||
github.com/golang/snappy v0.0.4 // indirect | ||
github.com/gorilla/websocket v1.5.0 // indirect | ||
github.com/shirou/gopsutil v3.21.11+incompatible // indirect | ||
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect | ||
github.com/tklauser/go-sysconf v0.3.11 // indirect | ||
github.com/tklauser/numcpus v0.6.0 // indirect | ||
github.com/yusufpapurcu/wmi v1.2.2 // indirect | ||
golang.org/x/crypto v0.4.0 // indirect | ||
golang.org/x/sys v0.5.0 // indirect | ||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect | ||
) |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/ethclient" | ||
"github.com/ethereum/hive/hivesim" | ||
) | ||
|
||
var ( | ||
// the number of seconds before a sync is considered stalled or failed | ||
syncTimeout = 65 * time.Second | ||
params = hivesim.Params{ | ||
"HIVE_CLIQUE_PRIVATEKEY": "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c", | ||
"HIVE_MINER": "658bdf435d810c91414ec09147daa6db62406379", | ||
"HIVE_NETWORK_ID": "321", | ||
"HIVE_CHAIN_ID": "321", | ||
|
||
"HIVE_NODETYPE": "", | ||
// block interval: 1s | ||
"HIVE_KCC_POSA_BLOCK_INTERVAL": "1", | ||
// epoch : 5 | ||
"HIVE_KCC_POSA_EPOCH": "10", | ||
// initial valiators | ||
"HIVE_KCC_POSA_ISHIKARI_INIT_VALIDATORS": "0x658bdf435d810c91414ec09147daa6db62406379", | ||
// admin | ||
"HIVE_KCC_POSA_ADMIN": "0x658bdf435d810c91414ec09147daa6db62406379", | ||
// KCC Ishikari fork number | ||
"HIVE_FORK_KCC_ISHIKARI": "9", | ||
// KCC Ishikari Patch001 fork number | ||
"HIVE_FORK_KCC_ISHIKARI_PATCH001": "10", | ||
// KCC Ishikari Patch002 fork number | ||
"HIVE_FORK_KCC_ISHIKARI_PATCH002": "11", | ||
} | ||
sourceFiles = map[string]string{ | ||
"genesis.json": "./simplechain/genesis.json", | ||
"chain.rlp": "./simplechain/chain.rlp", | ||
"geth.sh": "./simplechain/geth.sh", | ||
} | ||
sinkFiles = map[string]string{ | ||
"genesis.json": "./simplechain/genesis.json", | ||
"geth.sh": "./simplechain/geth.sh", | ||
} | ||
) | ||
|
||
var ( | ||
testchainHeadNumber = uint64(8591) | ||
testchainHeadHash = common.HexToHash("0x0520a5c756a2b225ac8e35fbd027f82c3fb21082a1f53c178540df5e94000013") | ||
) | ||
|
||
func main() { | ||
var suite = hivesim.Suite{ | ||
Name: "sync with other clients", | ||
Description: `This suite of tests verifies that clients can sync from each other in different modes. | ||
For each client, we test if it can serve as a sync source for all other clients (including itself).`, | ||
} | ||
suite.Add(hivesim.ClientTestSpec{ | ||
Role: "eth1", | ||
Name: "CLIENT as sync source", | ||
Description: "This loads the test chain into the client and verifies whether it was imported correctly.", | ||
Parameters: params, | ||
Files: sourceFiles, | ||
Run: runSourceTest, | ||
}) | ||
hivesim.MustRunSuite(hivesim.New(), suite) | ||
} | ||
|
||
func runSourceTest(t *hivesim.T, c *hivesim.Client) { | ||
t.Logf("Notice: Versions before KCC 1.2.1 cannot used for this case.") | ||
|
||
if c.Type == "kcc_v1.2.0" || c.Type == "kcc_v1.2.1" { | ||
t.Logf("Versions before KCC 1.2.1 cannot used for this case.") | ||
return | ||
} | ||
|
||
// Check whether the source has imported its chain.rlp correctly. | ||
source := &node{c} | ||
if err := source.checkHead(testchainHeadNumber, testchainHeadHash); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Configure sink to connect to the source node. | ||
enode, err := source.EnodeURL() | ||
if err != nil { | ||
t.Fatal("can't get node peer-to-peer endpoint:", enode) | ||
} | ||
t.Logf("enode: %s\n", enode) | ||
sinkParams := params.Set("HIVE_BOOTNODE", enode) | ||
|
||
// Sync all sink nodes against the source. | ||
t.RunAllClients(hivesim.ClientTestSpec{ | ||
Role: "eth1", | ||
Name: fmt.Sprintf("sync %s -> CLIENT", source.Type), | ||
Description: fmt.Sprintf("This test attempts to sync the chain from a %s node.", source.Type), | ||
Parameters: sinkParams, | ||
Files: sinkFiles, | ||
Run: runSyncTest, | ||
}) | ||
} | ||
|
||
func runSyncTest(t *hivesim.T, c *hivesim.Client) { | ||
node := &node{c} | ||
err := node.checkSync(t, testchainHeadNumber, testchainHeadHash) | ||
if err != nil { | ||
t.Fatal("sync failed:", err) | ||
} | ||
} | ||
|
||
type node struct { | ||
*hivesim.Client | ||
} | ||
|
||
// checkSync waits for the node to reach the head of the chain. | ||
func (n *node) checkSync(t *hivesim.T, wantNumber uint64, wantHash common.Hash) error { | ||
var ( | ||
timeout = time.After(syncTimeout) | ||
current = uint64(0) | ||
) | ||
for { | ||
select { | ||
case <-timeout: | ||
return fmt.Errorf("timeout (%v elapsed, current head is %d)", syncTimeout, current) | ||
default: | ||
block, err := n.head() | ||
if err != nil { | ||
t.Logf("error getting block from %s (%s): %v", n.Type, n.Container, err) | ||
return err | ||
} | ||
blockNumber := block.Number.Uint64() | ||
if blockNumber != current { | ||
t.Logf("%s has new head %d\n", n.Type, blockNumber) | ||
} | ||
if current == wantNumber { | ||
if block.Hash() != wantHash { | ||
return fmt.Errorf("wrong head hash %x, want %x", block.Hash(), wantHash) | ||
} | ||
return nil // success | ||
} | ||
// check in a little while.... | ||
current = blockNumber | ||
time.Sleep(1000 * time.Millisecond) | ||
} | ||
} | ||
} | ||
|
||
// head returns the node's chain head. | ||
func (n *node) head() (*types.Header, error) { | ||
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) | ||
return ethclient.NewClient(n.RPC()).HeaderByNumber(ctx, nil) | ||
} | ||
|
||
// checkHead checks whether the remote chain head matches the given values. | ||
func (n *node) checkHead(num uint64, hash common.Hash) error { | ||
head, err := n.head() | ||
if err != nil { | ||
return fmt.Errorf("can't query chain head: %v", err) | ||
} | ||
if head.Hash() != hash { | ||
fmt.Printf("info: wrong chain head %d (%s), want %d (%s)\n", head.Number, head.Hash().String(), num, hash.String()) | ||
|
||
return fmt.Errorf("wrong chain head %d (%s), want %d (%s)", head.Number, head.Hash().TerminalString(), num, hash.TerminalString()) | ||
} else { | ||
fmt.Printf("have the same header!\n") | ||
} | ||
return nil | ||
} |
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
#!/bin/bash | ||
|
||
# Startup script to initialize and boot a go-ethereum instance. | ||
# | ||
# This script assumes the following files: | ||
# - `geth` 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) | ||
# - `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 | ||
# - HIVE_FORK_KCC_ISHIKARI block number for Ishikari | ||
# | ||
# 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 | ||
|
||
geth=/usr/local/bin/geth | ||
FLAGS="--pcscdpath=\"\"" | ||
|
||
if [ "$HIVE_LOGLEVEL" != "" ]; then | ||
FLAGS="$FLAGS --verbosity=$HIVE_LOGLEVEL" | ||
fi | ||
|
||
# It doesn't make sense to dial out, use only a pre-set bootnode. | ||
FLAGS="$FLAGS --bootnodes=$HIVE_BOOTNODE" | ||
|
||
|
||
# If a specific network ID is requested, use that | ||
if [ "$HIVE_NETWORK_ID" != "" ]; then | ||
FLAGS="$FLAGS --networkid $HIVE_NETWORK_ID" | ||
else | ||
FLAGS="$FLAGS --networkid 322" # use networkid of testnet | ||
fi | ||
|
||
# If the client is to be run in testnet mode, flag it as such | ||
if [ "$HIVE_TESTNET" == "1" ]; then | ||
FLAGS="$FLAGS --testnet" | ||
fi | ||
|
||
# Handle any client mode or operation requests | ||
if [ "$HIVE_NODETYPE" == "archive" ]; then | ||
FLAGS="$FLAGS --syncmode full --gcmode archive" | ||
fi | ||
if [ "$HIVE_NODETYPE" == "full" ]; then | ||
FLAGS="$FLAGS --syncmode full" | ||
fi | ||
if [ "$HIVE_NODETYPE" == "light" ]; then | ||
FLAGS="$FLAGS --syncmode light" | ||
fi | ||
if [ "$HIVE_NODETYPE" == "snap" ]; then | ||
FLAGS="$FLAGS --syncmode snap" | ||
fi | ||
if [ "$HIVE_NODETYPE" == "" ]; then | ||
FLAGS="$FLAGS --syncmode snap" | ||
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 | ||
|
||
# Initialize the local testchain with the genesis state | ||
echo "Initializing database with genesis state..." | ||
$geth $FLAGS init /genesis.json | ||
|
||
# Don't immediately abort, some imports are meant to fail | ||
set +e | ||
|
||
# Load the test chain if present | ||
echo "Loading initial blockchain..." | ||
if [ -f /chain.rlp ]; then | ||
$geth $FLAGS --gcmode=archive import /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 | ||
(cd /blocks && $geth $FLAGS --gcmode=archive --verbosity=$HIVE_LOGLEVEL --nocompaction import `ls | sort -n`) | ||
else | ||
echo "Warning: blocks folder not found." | ||
fi | ||
|
||
set -e | ||
|
||
# Import clique signing key. | ||
if [ "$HIVE_CLIQUE_PRIVATEKEY" != "" ]; then | ||
# Create password file. | ||
echo "Importing clique key..." | ||
echo "the private key is $HIVE_CLIQUE_PRIVATEKEY" | ||
echo "secret" > /geth-password-file.txt | ||
$geth --nousb account import --password /geth-password-file.txt <(echo "$HIVE_CLIQUE_PRIVATEKEY") | ||
|
||
# Ensure password file is used when running geth in mining mode. | ||
if [ "$HIVE_MINER" != "" ]; then | ||
FLAGS="$FLAGS --password /geth-password-file.txt --unlock $HIVE_MINER --allow-insecure-unlock" | ||
fi | ||
fi | ||
|
||
# Configure any mining operation | ||
#if [ "$HIVE_MINER" != "" ] && [ "$HIVE_NODETYPE" != "light" ]; then | ||
# FLAGS="$FLAGS --mine --miner.threads 1 --miner.etherbase $HIVE_MINER" | ||
#fi | ||
|
||
FLAGS="$FLAGS --miner.gasprice 1000000000" # 1gwei | ||
|
||
|
||
# Add Gas Block Limit Configuration | ||
if [ "$HIVE_GAS_TARGET" != "" ]; then | ||
FLAGS="$FLAGS --miner.gastarget $HIVE_GAS_TARGET" | ||
fi | ||
if [ "$HIVE_GAS_LIMIT" != "" ]; then | ||
FLAGS="$FLAGS --miner.gaslimit $HIVE_GAS_LIMIT" | ||
fi | ||
|
||
# Configure LES. | ||
if [ "$HIVE_LES_SERVER" == "1" ]; then | ||
FLAGS="$FLAGS --light.serve 50 --light.nosyncserve" | ||
fi | ||
|
||
# Configure RPC. | ||
FLAGS="$FLAGS --http --http.addr=0.0.0.0 --http.port=8545 --http.api=admin,debug,eth,miner,net,personal,txpool,web3" | ||
FLAGS="$FLAGS --ws --ws.addr=0.0.0.0 --ws.origins \"*\" --ws.api=admin,debug,eth,miner,net,personal,txpool,web3" | ||
if [ "$HIVE_GRAPHQL_ENABLED" != "" ]; then | ||
FLAGS="$FLAGS --graphql" | ||
fi | ||
# used for the graphql to allow submission of unprotected tx | ||
if [ "$HIVE_ALLOW_UNPROTECTED_TX" != "" ]; then | ||
FLAGS="$FLAGS --rpc.allow-unprotected-txs" | ||
fi | ||
|
||
# Run the go-ethereum implementation with the requested flags. | ||
FLAGS="$FLAGS --nat=none" | ||
echo "Running go-ethereum with flags $FLAGS" | ||
$geth $FLAGS |