Skip to content

Commit

Permalink
Merge pull request #29 from 0xcary/sync
Browse files Browse the repository at this point in the history
add sync
  • Loading branch information
junnmm authored Mar 17, 2023
2 parents f8d8fe3 + 4e57126 commit ccd1e85
Show file tree
Hide file tree
Showing 7 changed files with 665 additions and 0 deletions.
12 changes: 12 additions & 0 deletions simulators/kcc/sync/Dockerfile
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"]
28 changes: 28 additions & 0 deletions simulators/kcc/sync/go.mod
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
)
214 changes: 214 additions & 0 deletions simulators/kcc/sync/go.sum

Large diffs are not rendered by default.

170 changes: 170 additions & 0 deletions simulators/kcc/sync/main.go
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 added simulators/kcc/sync/simplechain/chain.rlp
Binary file not shown.
67 changes: 67 additions & 0 deletions simulators/kcc/sync/simplechain/genesis.json

Large diffs are not rendered by default.

174 changes: 174 additions & 0 deletions simulators/kcc/sync/simplechain/geth.sh
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

0 comments on commit ccd1e85

Please sign in to comment.