diff --git a/.github/matic-cli-config.yml b/.github/matic-cli-config.yml
new file mode 100644
index 0000000000..f643f4b192
--- /dev/null
+++ b/.github/matic-cli-config.yml
@@ -0,0 +1,11 @@
+defaultStake: 10000
+defaultFee: 2000
+borChainId: "15001"
+heimdallChainId: heimdall-15001
+contractsBranch: jc/v0.3.1-backport
+numOfValidators: 3
+numOfNonValidators: 0
+ethURL: http://ganache:9545
+devnetType: docker
+borDockerBuildContext: "../../bor"
+heimdallDockerBuildContext: "https://github.com/maticnetwork/heimdall.git#v0.3.0-dev"
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 727d3a2e22..336b2fea56 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,28 +1,183 @@
name: CI
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - "master"
+ - "qa"
+ - "develop"
+ pull_request:
+ branches:
+ - "**"
+ types: [opened, synchronize, edited]
+
+concurrency:
+ group: build-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
jobs:
- build:
- runs-on: ubuntu-latest
+ tests:
+ if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
+ strategy:
+ matrix:
+ os: [ ubuntu-20.04, macos-11 ] # list of os: https://github.com/actions/virtual-environments
+ runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - name: Install Go
- uses: actions/setup-go@v2
- with:
- go-version: 1.17
- - name: "Build binaries"
- run: make all
- - name: "Run tests"
- run: make test
- - name: Upload coverage to Codecov
- uses: codecov/codecov-action@v1
- with:
- file: ./cover.out
- - name: Reproducible build test
- run: |
- make geth
- shasum -a256 ./build/bin/geth > bor1.sha256
- make geth
- shasum -a256 ./build/bin/geth > bor2.sha256
- if ! cmp -s bor1.sha256 bor2.sha256; then
- echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1
- fi
+ - uses: actions/checkout@v3
+ - run: |
+ git submodule update --init --recursive --force
+ git fetch --no-tags --prune --depth=1 origin +refs/heads/master:refs/remotes/origin/master
+
+ - uses: actions/setup-go@v3
+ with:
+ go-version: 1.18.x
+
+ - name: Install dependencies on Linux
+ if: runner.os == 'Linux'
+ run: sudo apt update && sudo apt install build-essential
+
+ - name: Golang-ci install
+ if: runner.os == 'Linux'
+ run: make lintci-deps
+
+ - uses: actions/cache@v3
+ with:
+ path: |
+ ~/.cache/go-build
+ ~/Library/Caches/go-build
+ ~/go/pkg/mod
+ key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+ restore-keys: ${{ runner.os }}-go-
+
+ - name: Build
+ run: make all
+
+ - name: Lint
+ if: runner.os == 'Linux'
+ run: make lint
+
+ - name: Test
+ run: make test
+
+ #- name: Data race tests
+ # run: make test-race
+
+ - name: test-integration
+ run: make test-integration
+
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v1
+ with:
+ file: ./cover.out
+
+ # # TODO: make it work
+ # - name: Reproducible build test
+ # run: |
+ # make geth
+ # shasum -a256 ./build/bin/geth > bor1.sha256
+ # make geth
+ # shasum -a256 ./build/bin/geth > bor2.sha256
+ # if ! cmp -s bor1.sha256 bor2.sha256; then
+ # echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1
+ # fi
+
+ integration-tests:
+ if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
+ strategy:
+ matrix:
+ os: [ ubuntu-20.04 ] # list of os: https://github.com/actions/virtual-environments
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ path: bor
+ - name: Checkout submodules
+ run: |
+ cd bor
+ git submodule update --init --recursive --force
+ git fetch --no-tags --prune --depth=1 origin +refs/heads/master:refs/remotes/origin/master
+
+ - uses: actions/setup-go@v3
+ with:
+ go-version: 1.18.x
+
+ - name: Checkout matic-cli
+ uses: actions/checkout@v3
+ with:
+ repository: maticnetwork/matic-cli
+ ref: v0.3.0-dev
+ path: matic-cli
+
+ - name: Install dependencies on Linux
+ if: runner.os == 'Linux'
+ run: |
+ sudo apt update
+ sudo apt install build-essential
+ curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
+ sudo snap install solc
+ sudo apt install python2 jq curl
+ sudo ln -sf /usr/bin/python2 /usr/bin/python
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '10.17.0'
+ cache: 'npm'
+ cache-dependency-path: |
+ matic-cli/package-lock.json
+ matic-cli/devnet/code/contracts/package-lock.json
+ matic-cli/devnet/code/genesis-contracts/package-lock.json
+ matic-cli/devnet/code/genesis-contracts/matic-contracts/package-lock.json
+
+ - name: Bootstrap devnet
+ run: |
+ cd matic-cli
+ npm install --prefer-offline --no-audit --progress=false
+ mkdir devnet
+ cd devnet
+ ../bin/matic-cli setup devnet -c ../../bor/.github/matic-cli-config.yml
+
+ - name: Launch devnet
+ run: |
+ cd matic-cli/devnet
+ bash docker-ganache-start.sh
+ bash docker-heimdall-start-all.sh
+ bash docker-bor-setup.sh
+ bash docker-bor-start-all.sh
+ sleep 120 && bash ganache-deployment-bor.sh
+ sleep 120 && bash ganache-deployment-sync.sh
+ sleep 120
+ docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'admin.peers'"
+ docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'eth.blockNumber'"
+
+ - name: Run smoke tests
+ run: |
+ echo "Deposit 100 matic for each account to bor network"
+ cd matic-cli/devnet/code/contracts
+ npm run truffle exec scripts/deposit.js -- --network development $(jq -r .root.tokens.MaticToken contractAddresses.json) 100000000000000000000
+ cd -
+ bash bor/integration-tests/smoke_test.sh
+
+ - name: Upload logs
+ if: always()
+ uses: actions/upload-artifact@v3
+ with:
+ name: logs_${{ github.run_id }}
+ path: |
+ matic-cli/devnet/logs
+
+ - name: Package code and chain data
+ if: always()
+ run: |
+ cd matic-cli/devnet
+ docker compose down
+ cd -
+ mkdir -p ${{ github.run_id }}/matic-cli
+ sudo mv bor ${{ github.run_id }}
+ sudo mv matic-cli/devnet ${{ github.run_id }}/matic-cli
+ sudo tar czf code.tar.gz ${{ github.run_id }}
+
+ - name: Upload code and chain data
+ if: always()
+ uses: actions/upload-artifact@v3
+ with:
+ name: code_${{ github.run_id }}
+ path: code.tar.gz
diff --git a/.github/workflows/dockerimage.yml b/.github/workflows/dockerimage.yml
deleted file mode 100644
index a8dc11949f..0000000000
--- a/.github/workflows/dockerimage.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-name: Bor Docker Image CI
-
-on:
- push:
- branches-ignore:
- - '**'
- tags:
- - 'v*.*.*'
- # to be used by fork patch-releases ^^
- - 'v*.*.*-*'
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Build the Bor Docker image
- env:
- DOCKERHUB: ${{ secrets.DOCKERHUB }}
- DOCKERHUB_KEY: ${{ secrets.DOCKERHUB_KEY }}
- run: |
- ls -l
- echo "Docker login"
- docker login -u $DOCKERHUB -p $DOCKERHUB_KEY
- echo "running build"
- docker build -f Dockerfile.classic -t maticnetwork/bor:${GITHUB_REF/refs\/tags\//} .
- echo "pushing image"
- docker push maticnetwork/bor:${GITHUB_REF/refs\/tags\//}
- echo "DONE!"
diff --git a/.gitignore b/.gitignore
index ad4242c519..50328c8121 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,8 @@
*/**/*dapps*
build/_vendor/pkg
+cover.out
+
#*
.#*
*#
diff --git a/.golangci.yml b/.golangci.yml
index 4950b98c21..89a9e328b8 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,6 +1,7 @@
# This file configures github.com/golangci/golangci-lint.
run:
+ go: '1.18'
timeout: 20m
tests: true
# default is true. Enables skipping of directories:
@@ -8,28 +9,139 @@ run:
skip-dirs-use-default: true
skip-files:
- core/genesis_alloc.go
+ - gen_.*.go
+ - .*_gen.go
linters:
- disable-all: true
enable:
- - deadcode
- goconst
- goimports
- - gosimple
- - govet
- - ineffassign
- misspell
- # - staticcheck
- unconvert
- # - unused
- - varcheck
+ - bodyclose
+ - containedctx
+ - contextcheck
+ - decorder
+ - durationcheck
+ - errchkjson
+ - errname
+ - exhaustive
+ - exportloopref
+ - gocognit
+ - gofmt
+ # - gomnd
+ - gomoddirectives
+ - gosec
+ - makezero
+ - nestif
+ - nilerr
+ - nilnil
+ - noctx
+ #- nosprintfhostport # TODO: do we use IPv6?
+ - paralleltest
+ - prealloc
+ - predeclared
+ #- promlinter
+ #- revive
+ # - tagliatelle
+ - tenv
+ - thelper
+ - tparallel
+ - unconvert
+ - unparam
+ - wsl
+ #- errorlint causes stack overflow. TODO: recheck after each golangci update
linters-settings:
gofmt:
simplify: true
+ auto-fix: false
+
goconst:
min-len: 3 # minimum length of string constant
- min-occurrences: 6 # minimum number of occurrences
+ min-occurrences: 2 # minimum number of occurrences
+ numbers: true
+
+ goimports:
+ local-prefixes: github.com/ethereum/go-ethereum
+
+ nestif:
+ min-complexity: 5
+
+ prealloc:
+ for-loops: true
+
+ gocritic:
+ # Which checks should be enabled; can't be combined with 'disabled-checks';
+ # See https://go-critic.github.io/overview#checks-overview
+ # To check which checks are enabled run `GL_DEBUG=gocritic ./build/bin/golangci-lint run`
+ # By default list of stable checks is used.
+ enabled-checks:
+ - badLock
+ - filepathJoin
+ - sortSlice
+ - sprintfQuotedString
+ - syncMapLoadAndDelete
+ - weakCond
+ - boolExprSimplify
+ - httpNoBody
+ - ioutilDeprecated
+ - nestingReduce
+ - preferFilepathJoin
+ - redundantSprint
+ - stringConcatSimplify
+ - timeExprSimplify
+ - typeAssertChain
+ - yodaStyleExpr
+ - truncateCmp
+ - equalFold
+ - preferDecodeRune
+ - preferFprint
+ - preferStringWriter
+ - preferWriteByte
+ - sliceClear
+ #- ruleguard
+
+ # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
+ disabled-checks:
+ - regexpMust
+ - exitAfterDefer
+ - dupBranchBody
+ - singleCaseSwitch
+ - unlambda
+ - captLocal
+ - commentFormatting
+ - ifElseChain
+ - importShadow
+ - builtinShadow
+
+ # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
+ # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
+ enabled-tags:
+ - performance
+ - diagnostic
+ - opinionated
+ - style
+ disabled-tags:
+ - experimental
+ govet:
+ disable:
+ - deepequalerrors
+ - fieldalignment
+ - shadow
+ - unsafeptr
+ check-shadowing: true
+ enable-all: true
+ settings:
+ printf:
+ # Run `go tool vet help printf` to see available settings for `printf` analyzer.
+ funcs:
+ - (github.com/ethereum/go-ethereum/log.Logger).Trace
+ - (github.com/ethereum/go-ethereum/log.Logger).Debug
+ - (github.com/ethereum/go-ethereum/log.Logger).Info
+ - (github.com/ethereum/go-ethereum/log.Logger).Warn
+ - (github.com/ethereum/go-ethereum/log.Logger).Error
+ - (github.com/ethereum/go-ethereum/log.Logger).Crit
issues:
exclude-rules:
@@ -48,3 +160,28 @@ issues:
- path: cmd/faucet/
linters:
- deadcode
+ # Exclude some linters from running on tests files.
+ - path: test\.go
+ linters:
+ - gosec
+ - unused
+ - deadcode
+ - gocritic
+ - path: cmd/devp2p
+ linters:
+ - gosec
+ - unused
+ - deadcode
+ - gocritic
+ - path: metrics/sample\.go
+ linters:
+ - gosec
+ - gocritic
+ - path: p2p/simulations
+ linters:
+ - gosec
+ - gocritic
+ max-issues-per-linter: 0
+ max-same-issues: 0
+ #new: true
+ new-from-rev: origin/master
\ No newline at end of file
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 331d8de6b5..d09cc43206 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -7,7 +7,7 @@ release:
builds:
- id: darwin-amd64
- main: ./cmd/geth
+ main: ./cmd/cli
binary: bor
goos:
- darwin
@@ -22,7 +22,7 @@ builds:
-s -w
- id: darwin-arm64
- main: ./cmd/geth
+ main: ./cmd/cli
binary: bor
goos:
- darwin
@@ -37,7 +37,7 @@ builds:
-s -w
- id: linux-amd64
- main: ./cmd/geth
+ main: ./cmd/cli
binary: bor
goos:
- linux
@@ -53,7 +53,7 @@ builds:
-s -w -extldflags "-static"
- id: linux-arm64
- main: ./cmd/geth
+ main: ./cmd/cli
binary: bor
goos:
- linux
diff --git a/Dockerfile b/Dockerfile
index 8af791ab3f..7a2770ce9a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,7 +9,9 @@ RUN apt-get update -y && apt-get upgrade -y \
WORKDIR ${BOR_DIR}
COPY . .
-RUN make bor-all
+RUN make bor
+
+RUN cp build/bin/bor /usr/local/bin/
ENV SHELL /bin/bash
EXPOSE 8545 8546 8547 30303 30303/udp
diff --git a/Dockerfile.classic b/Dockerfile.classic
deleted file mode 100644
index 2fa38f08f9..0000000000
--- a/Dockerfile.classic
+++ /dev/null
@@ -1,18 +0,0 @@
-# Build Geth in a stock Go builder container
-FROM golang:1.18.1-alpine as builder
-
-RUN apk add --no-cache make gcc musl-dev linux-headers git bash
-
-ADD . /bor
-RUN cd /bor && make bor-all
-
-CMD ["/bin/bash"]
-
-# Pull Bor into a second stage deploy alpine container
-FROM alpine:latest
-
-RUN apk add --no-cache ca-certificates
-COPY --from=builder /bor/build/bin/bor /usr/local/bin/
-COPY --from=builder /bor/build/bin/bootnode /usr/local/bin/
-
-EXPOSE 8545 8546 8547 30303 30303/udp
diff --git a/Makefile b/Makefile
index b283928b81..46ecdec886 100644
--- a/Makefile
+++ b/Makefile
@@ -2,27 +2,35 @@
# with Go source code. If you know what GOPATH is then you probably
# don't need to bother with make.
-.PHONY: geth android ios evm all test clean
+.PHONY: geth android ios geth-cross evm all test clean docs
+.PHONY: geth-linux geth-linux-386 geth-linux-amd64 geth-linux-mips64 geth-linux-mips64le
+.PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64
+.PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64
+.PHONY: geth-windows geth-windows-386 geth-windows-amd64
-GOBIN = ./build/bin
GO ?= latest
+GOBIN = $(CURDIR)/build/bin
GORUN = env GO111MODULE=on go run
GOPATH = $(shell go env GOPATH)
-bor:
- $(GORUN) build/ci.go install ./cmd/geth
- mkdir -p $(GOPATH)/bin/
- cp $(GOBIN)/geth $(GOBIN)/bor
- cp $(GOBIN)/* $(GOPATH)/bin/
+GIT_COMMIT ?= $(shell git rev-list -1 HEAD)
+GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
+GIT_TAG ?= $(shell git describe --tags `git rev-list --tags="v*" --max-count=1`)
-bor-all:
- $(GORUN) build/ci.go install
+PACKAGE = github.com/ethereum/go-ethereum
+GO_FLAGS += -buildvcs=false
+GO_FLAGS += -ldflags "-X ${PACKAGE}/params.GitCommit=${GIT_COMMIT} -X ${PACKAGE}/params.GitBranch=${GIT_BRANCH} -X ${PACKAGE}/params.GitTag=${GIT_TAG}"
+
+TESTALL = $$(go list ./... | grep -v go-ethereum/cmd/)
+TESTE2E = ./tests/...
+GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) -p 1
+
+bor:
mkdir -p $(GOPATH)/bin/
- cp $(GOBIN)/geth $(GOBIN)/bor
- cp $(GOBIN)/* $(GOPATH)/bin/
+ go build -o $(GOBIN)/bor ./cmd/cli/main.go
protoc:
- protoc --go_out=. --go-grpc_out=. ./command/server/proto/*.proto
+ protoc --go_out=. --go-grpc_out=. ./internal/cli/server/proto/*.proto
geth:
$(GORUN) build/ci.go install ./cmd/geth
@@ -45,11 +53,29 @@ ios:
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
test:
- # Skip mobile and cmd tests since they are being deprecated
- go test -v $$(go list ./... | grep -v go-ethereum/cmd/) -cover -coverprofile=cover.out
+ $(GOTEST) --timeout 5m -shuffle=on -cover -coverprofile=cover.out $(TESTALL)
-lint: ## Run linters.
- $(GORUN) build/ci.go lint
+test-race:
+ $(GOTEST) --timeout 15m -race -shuffle=on $(TESTALL)
+
+test-integration:
+ $(GOTEST) --timeout 30m -tags integration $(TESTE2E)
+
+escape:
+ cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out
+
+lint:
+ @./build/bin/golangci-lint run --config ./.golangci.yml
+
+lintci-deps:
+ rm -f ./build/bin/golangci-lint
+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./build/bin v1.46.0
+
+goimports:
+ goimports -local "$(PACKAGE)" -w .
+
+docs:
+ $(GORUN) cmd/clidoc/main.go -d ./docs/cli
clean:
env GO111MODULE=on go clean -cache
@@ -59,11 +85,13 @@ clean:
# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'.
devtools:
- env GOBIN= go install golang.org/x/tools/cmd/stringer@latest
- env GOBIN= go install github.com/kevinburke/go-bindata/go-bindata@latest
- env GOBIN= go install github.com/fjl/gencodec@latest
- env GOBIN= go install github.com/golang/protobuf/protoc-gen-go@latest
- env GOBIN= go install ./cmd/abigen
+ # Notice! If you adding new binary - add it also to tests/deps/fake.go file
+ $(GOBUILD) -o $(GOBIN)/stringer github.com/golang.org/x/tools/cmd/stringer
+ $(GOBUILD) -o $(GOBIN)/go-bindata github.com/kevinburke/go-bindata/go-bindata
+ $(GOBUILD) -o $(GOBIN)/codecgen github.com/ugorji/go/codec/codecgen
+ $(GOBUILD) -o $(GOBIN)/abigen ./cmd/abigen
+ $(GOBUILD) -o $(GOBIN)/mockgen github.com/golang/mock/mockgen
+ $(GOBUILD) -o $(GOBIN)/protoc-gen-go github.com/golang/protobuf/protoc-gen-go
PATH=$(GOBIN):$(PATH) go generate ./common
PATH=$(GOBIN):$(PATH) go generate ./core/types
PATH=$(GOBIN):$(PATH) go generate ./consensus/bor
@@ -71,7 +99,6 @@ devtools:
@type "protoc" 2> /dev/null || echo 'Please install protoc'
# Cross Compilation Targets (xgo)
-
geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios
@echo "Full cross compilation done:"
@ls -ld $(GOBIN)/geth-*
diff --git a/README.md b/README.md
index 1dacae0219..4e33a551d0 100644
--- a/README.md
+++ b/README.md
@@ -63,12 +63,6 @@ them using your favourite package manager. Once the dependencies are installed,
$ make bor
```
-- or, to build the full suite of utilities:
-
- ```shell
- $ make bor-all
- ```
-
### Make awesome changes!
1. Create new branch for your changes
@@ -113,12 +107,6 @@ them using your favourite package manager. Once the dependencies are installed,
-Build the beta client:
-
-```shell
-go build -o bor-beta command/*.go
-```
-
## License
The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the
diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go
index 8a0cbe3357..7df1a823ec 100644
--- a/accounts/abi/bind/backends/simulated_test.go
+++ b/accounts/abi/bind/backends/simulated_test.go
@@ -27,10 +27,13 @@ import (
"testing"
"time"
+ "go.uber.org/goleak"
+
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/leak"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@@ -38,6 +41,8 @@ import (
)
func TestSimulatedBackend(t *testing.T) {
+ defer goleak.VerifyNone(t, leak.IgnoreList()...)
+
var gasLimit uint64 = 8000029
key, _ := crypto.GenerateKey() // nolint: gosec
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
diff --git a/builder/files/bor.service b/builder/files/bor.service
index fa84320a6c..28fda79814 100644
--- a/builder/files/bor.service
+++ b/builder/files/bor.service
@@ -6,21 +6,25 @@
[Service]
Restart=on-failure
RestartSec=5s
- ExecStart=/usr/local/bin/bor \
- --bor-mumbai \
- # --bor-mainnet \
- --datadir /var/lib/bor/data \
- --bootnodes "enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303,enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303"
+ ExecStart=/usr/local/bin/bor server \
+ -chain=mumbai \
+ # -chain=mainnet \
+ -datadir /var/lib/bor/data \
+ -metrics \
+ -metrics.prometheus-addr="127.0.0.1:7071" \
+ -bootnodes "enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303,enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303"
# Validator params
- # Uncomment and configure the following lines in case you run a validator
- # --keystore /var/lib/bor/keystore \
- # --unlock [VALIDATOR ADDRESS] \
- # --password /var/lib/bor/password.txt \
- # --allow-insecure-unlock \
- # --nodiscover --maxpeers 1 \
- # --mine
+ # Uncomment and configure the following lines in case you run a validator. Don't forget to add backslash (\)
+ # to previous command line.
+ # -keystore /var/lib/bor/keystore \
+ # -unlock [VALIDATOR ADDRESS] \
+ # -password /var/lib/bor/password.txt \
+ # -allow-insecure-unlock \
+ # -nodiscover -maxpeers 1 \
+ # -miner.etherbase [VALIDATOR ADDRESS] \
+ # -mine
Type=simple
- User=root
+ User=ubuntu
KillSignal=SIGINT
TimeoutStopSec=120
diff --git a/cmd/clidoc/main.go b/cmd/clidoc/main.go
new file mode 100644
index 0000000000..07efc04556
--- /dev/null
+++ b/cmd/clidoc/main.go
@@ -0,0 +1,77 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/internal/cli"
+)
+
+const (
+ DefaultDir string = "./docs/cli"
+ DefaultMainPage string = "README.md"
+)
+
+func main() {
+ commands := cli.Commands()
+
+ dest := flag.String("d", DefaultDir, "Destination directory where the docs will be generated")
+ flag.Parse()
+
+ dirPath := filepath.Join(".", *dest)
+ if err := os.MkdirAll(dirPath, os.ModePerm); err != nil {
+ log.Fatalln("Failed to create directory.", err)
+ }
+
+ mainPage := []string{
+ "# Bor command line interface",
+ "## Commands",
+ }
+
+ keys := make([]string, len(commands))
+ i := 0
+
+ for k := range commands {
+ keys[i] = k
+ i++
+ }
+
+ sort.Strings(keys)
+
+ for _, name := range keys {
+ cmd, err := commands[name]()
+ if err != nil {
+ log.Fatalf("Error occurred when inspecting bor command %s: %s", name, err)
+ }
+
+ fileName := strings.ReplaceAll(name, " ", "_") + ".md"
+
+ overwriteFile(filepath.Join(dirPath, fileName), cmd.MarkDown())
+ mainPage = append(mainPage, "- [```"+name+"```](./"+fileName+")")
+ }
+
+ overwriteFile(filepath.Join(dirPath, DefaultMainPage), strings.Join(mainPage, "\n\n"))
+
+ os.Exit(0)
+}
+
+func overwriteFile(filePath string, text string) {
+ log.Printf("Writing to page: %s\n", filePath)
+
+ f, err := os.Create(filePath)
+ if err != nil {
+ log.Fatalln(err)
+ }
+
+ if _, err = f.WriteString(text); err != nil {
+ log.Fatalln(err)
+ }
+
+ if err = f.Close(); err != nil {
+ log.Fatalln(err)
+ }
+}
diff --git a/common/debug/debug.go b/common/debug/debug.go
new file mode 100644
index 0000000000..6a677e495d
--- /dev/null
+++ b/common/debug/debug.go
@@ -0,0 +1,28 @@
+package debug
+
+import (
+ "runtime"
+)
+
+// Callers returns given number of callers with packages
+func Callers(show int) []string {
+ fpcs := make([]uintptr, show)
+
+ n := runtime.Callers(2, fpcs)
+ if n == 0 {
+ return nil
+ }
+
+ callers := make([]string, 0, len(fpcs))
+
+ for _, p := range fpcs {
+ caller := runtime.FuncForPC(p - 1)
+ if caller == nil {
+ continue
+ }
+
+ callers = append(callers, caller.Name())
+ }
+
+ return callers
+}
diff --git a/common/leak/ignore_list.go b/common/leak/ignore_list.go
new file mode 100644
index 0000000000..56134dcabc
--- /dev/null
+++ b/common/leak/ignore_list.go
@@ -0,0 +1,23 @@
+package leak
+
+import "go.uber.org/goleak"
+
+func IgnoreList() []goleak.Option {
+ return []goleak.Option{
+ // a list of goroutne leaks that hard to fix due to external dependencies or too big refactoring needed
+ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache"),
+ goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).dispatch"),
+ goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).internal"),
+ goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*nonrecursiveTree).dispatch"),
+ goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*nonrecursiveTree).internal"),
+ goleak.IgnoreTopFunction("github.com/rjeczalik/notify._Cfunc_CFRunLoopRun"),
+
+ // todo: this leaks should be fixed
+ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/metrics.(*meterArbiter).tick"),
+ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/consensus/ethash.(*remoteSealer).loop"),
+ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*BlockChain).updateFutureBlocks"),
+ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core/state/snapshot.(*diskLayer).generate"),
+ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/accounts/abi/bind/backends.nullSubscription.func1"),
+ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/eth/filters.(*EventSystem).eventLoop"),
+ }
+}
diff --git a/common/set/slice.go b/common/set/slice.go
new file mode 100644
index 0000000000..36f11e67fe
--- /dev/null
+++ b/common/set/slice.go
@@ -0,0 +1,11 @@
+package set
+
+func New[T comparable](slice []T) map[T]struct{} {
+ m := make(map[T]struct{}, len(slice))
+
+ for _, el := range slice {
+ m[el] = struct{}{}
+ }
+
+ return m
+}
diff --git a/consensus/bor/abi/interface.go b/consensus/bor/abi/interface.go
new file mode 100644
index 0000000000..bb05bf0b23
--- /dev/null
+++ b/consensus/bor/abi/interface.go
@@ -0,0 +1,6 @@
+package abi
+
+type ABI interface {
+ Pack(name string, args ...interface{}) ([]byte, error)
+ UnpackIntoInterface(v interface{}, name string, data []byte) error
+}
diff --git a/consensus/bor/api.go b/consensus/bor/api.go
index 12841290af..26d1efdaf1 100644
--- a/consensus/bor/api.go
+++ b/consensus/bor/api.go
@@ -4,14 +4,17 @@ import (
"encoding/hex"
"math"
"math/big"
+ "sort"
"strconv"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rpc"
+
lru "github.com/hashicorp/golang-lru"
"github.com/xsleonard/go-merkle"
"golang.org/x/crypto/sha3"
@@ -43,9 +46,88 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
if header == nil {
return nil, errUnknownBlock
}
+
return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
}
+type BlockSigners struct {
+ Signers []difficultiesKV
+ Diff int
+ Author common.Address
+}
+
+type difficultiesKV struct {
+ Signer common.Address
+ Difficulty uint64
+}
+
+func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV {
+ ss := make([]difficultiesKV, 0, len(values))
+ for k, v := range values {
+ ss = append(ss, difficultiesKV{k, v})
+ }
+
+ sort.Slice(ss, func(i, j int) bool {
+ return ss[i].Difficulty > ss[j].Difficulty
+ })
+
+ return ss
+}
+
+// GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span
+func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) {
+ snapNumber := *number - 1
+
+ var difficulties = make(map[common.Address]uint64)
+
+ snap, err := api.GetSnapshot(&snapNumber)
+
+ if err != nil {
+ return BlockSigners{}, err
+ }
+
+ proposer := snap.ValidatorSet.GetProposer().Address
+ proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer)
+
+ signers := snap.signers()
+ for i := 0; i < len(signers); i++ {
+ tempIndex := i
+ if tempIndex < proposerIndex {
+ tempIndex = tempIndex + len(signers)
+ }
+
+ difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex))
+ }
+
+ rankedDifficulties := rankMapDifficulties(difficulties)
+
+ author, err := api.GetAuthor(number)
+ if err != nil {
+ return BlockSigners{}, err
+ }
+
+ diff := int(difficulties[*author])
+ blockSigners := &BlockSigners{
+ Signers: rankedDifficulties,
+ Diff: diff,
+ Author: *author,
+ }
+
+ return *blockSigners, nil
+}
+
+// GetSnapshotProposer retrieves the in-turn signer at a given block.
+func (api *API) GetSnapshotProposer(number *rpc.BlockNumber) (common.Address, error) {
+ *number -= 1
+ snap, err := api.GetSnapshot(number)
+
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ return snap.ValidatorSet.GetProposer().Address, nil
+}
+
// GetAuthor retrieves the author a block.
func (api *API) GetAuthor(number *rpc.BlockNumber) (*common.Address, error) {
// Retrieve the requested block number (or current if none requested)
@@ -59,7 +141,9 @@ func (api *API) GetAuthor(number *rpc.BlockNumber) (*common.Address, error) {
if header == nil {
return nil, errUnknownBlock
}
+
author, err := api.bor.Author(header)
+
return &author, err
}
@@ -69,6 +153,7 @@ func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
if header == nil {
return nil, errUnknownBlock
}
+
return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
}
@@ -85,10 +170,13 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) {
if header == nil {
return nil, errUnknownBlock
}
+
snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
+
if err != nil {
return nil, err
}
+
return snap.signers(), nil
}
@@ -98,10 +186,13 @@ func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) {
if header == nil {
return nil, errUnknownBlock
}
+
snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
+
if err != nil {
return nil, err
}
+
return snap.signers(), nil
}
@@ -111,15 +202,17 @@ func (api *API) GetCurrentProposer() (common.Address, error) {
if err != nil {
return common.Address{}, err
}
+
return snap.ValidatorSet.GetProposer().Address, nil
}
// GetCurrentValidators gets the current validators
-func (api *API) GetCurrentValidators() ([]*Validator, error) {
+func (api *API) GetCurrentValidators() ([]*valset.Validator, error) {
snap, err := api.GetSnapshot(nil)
if err != nil {
- return make([]*Validator, 0), err
+ return make([]*valset.Validator, 0), err
}
+
return snap.ValidatorSet.Validators, nil
}
@@ -128,26 +221,36 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
if err := api.initializeRootHashCache(); err != nil {
return "", err
}
+
key := getRootHashKey(start, end)
+
if root, known := api.rootHashCache.Get(key); known {
return root.(string), nil
}
- length := uint64(end - start + 1)
+
+ length := end - start + 1
+
if length > MaxCheckpointLength {
return "", &MaxCheckpointLengthExceededError{start, end}
}
+
currentHeaderNumber := api.chain.CurrentHeader().Number.Uint64()
+
if start > end || end > currentHeaderNumber {
- return "", &InvalidStartEndBlockError{start, end, currentHeaderNumber}
+ return "", &valset.InvalidStartEndBlockError{Start: start, End: end, CurrentHeader: currentHeaderNumber}
}
+
blockHeaders := make([]*types.Header, end-start+1)
wg := new(sync.WaitGroup)
concurrent := make(chan bool, 20)
+
for i := start; i <= end; i++ {
wg.Add(1)
concurrent <- true
+
go func(number uint64) {
- blockHeaders[number-start] = api.chain.GetHeaderByNumber(uint64(number))
+ blockHeaders[number-start] = api.chain.GetHeaderByNumber(number)
+
<-concurrent
wg.Done()
}(i)
@@ -156,6 +259,7 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
close(concurrent)
headers := make([][32]byte, nextPowerOfTwo(length))
+
for i := 0; i < len(blockHeaders); i++ {
blockHeader := blockHeaders[i]
header := crypto.Keccak256(appendBytes32(
@@ -166,6 +270,7 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
))
var arr [32]byte
+
copy(arr[:], header)
headers[i] = arr
}
@@ -174,8 +279,10 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
if err := tree.Generate(convert(headers), sha3.NewLegacyKeccak256()); err != nil {
return "", err
}
+
root := hex.EncodeToString(tree.Root().Hash)
api.rootHashCache.Add(key, root)
+
return root, nil
}
@@ -184,6 +291,7 @@ func (api *API) initializeRootHashCache() error {
if api.rootHashCache == nil {
api.rootHashCache, err = lru.NewARC(10)
}
+
return err
}
diff --git a/consensus/bor/api/caller.go b/consensus/bor/api/caller.go
new file mode 100644
index 0000000000..d5fe259c97
--- /dev/null
+++ b/consensus/bor/api/caller.go
@@ -0,0 +1,14 @@
+package api
+
+import (
+ "context"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+//go:generate mockgen -destination=./caller_mock.go -package=api . Caller
+type Caller interface {
+ Call(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *ethapi.StateOverride) (hexutil.Bytes, error)
+}
diff --git a/consensus/bor/api/caller_mock.go b/consensus/bor/api/caller_mock.go
new file mode 100644
index 0000000000..940c99d178
--- /dev/null
+++ b/consensus/bor/api/caller_mock.go
@@ -0,0 +1,53 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/ethereum/go-ethereum/consensus/bor/api (interfaces: Caller)
+
+// Package api is a generated GoMock package.
+package api
+
+import (
+ context "context"
+ reflect "reflect"
+
+ hexutil "github.com/ethereum/go-ethereum/common/hexutil"
+ ethapi "github.com/ethereum/go-ethereum/internal/ethapi"
+ rpc "github.com/ethereum/go-ethereum/rpc"
+ gomock "github.com/golang/mock/gomock"
+)
+
+// MockCaller is a mock of Caller interface.
+type MockCaller struct {
+ ctrl *gomock.Controller
+ recorder *MockCallerMockRecorder
+}
+
+// MockCallerMockRecorder is the mock recorder for MockCaller.
+type MockCallerMockRecorder struct {
+ mock *MockCaller
+}
+
+// NewMockCaller creates a new mock instance.
+func NewMockCaller(ctrl *gomock.Controller) *MockCaller {
+ mock := &MockCaller{ctrl: ctrl}
+ mock.recorder = &MockCallerMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockCaller) EXPECT() *MockCallerMockRecorder {
+ return m.recorder
+}
+
+// Call mocks base method.
+func (m *MockCaller) Call(arg0 context.Context, arg1 ethapi.TransactionArgs, arg2 rpc.BlockNumberOrHash, arg3 *ethapi.StateOverride) (hexutil.Bytes, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Call", arg0, arg1, arg2, arg3)
+ ret0, _ := ret[0].(hexutil.Bytes)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// Call indicates an expected call of Call.
+func (mr *MockCallerMockRecorder) Call(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockCaller)(nil).Call), arg0, arg1, arg2, arg3)
+}
diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go
index 2eb2645f18..826a45dae2 100644
--- a/consensus/bor/bor.go
+++ b/consensus/bor/bor.go
@@ -2,38 +2,34 @@ package bor
import (
"bytes"
- "context"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
- "math"
"math/big"
"sort"
"strconv"
- "strings"
"sync"
"time"
lru "github.com/hashicorp/golang-lru"
"golang.org/x/crypto/sha3"
- ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/bor/api"
+ "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
+ "github.com/ethereum/go-ethereum/consensus/bor/statefull"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
@@ -56,11 +52,7 @@ var (
uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
- diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
- diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures
-
validatorHeaderBytesLength = common.AddressLength + 20 // address + power
- systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
)
// Various error messages to mark blocks invalid. These should be private to
@@ -72,18 +64,6 @@ var (
// that is not part of the local blockchain.
errUnknownBlock = errors.New("unknown block")
- // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition
- // block has a beneficiary set to non-zeroes.
- errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero")
-
- // errInvalidVote is returned if a nonce value is something else that the two
- // allowed constants of 0x00..0 or 0xff..f.
- errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f")
-
- // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block
- // has a vote nonce set to non-zeroes.
- errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero")
-
// errMissingVanity is returned if a block's extra-data section is shorter than
// 32 bytes, which is required to store the signer vanity.
errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
@@ -116,9 +96,6 @@ var (
// errOutOfRangeChain is returned if an authorization list is attempted to
// be modified via out-of-range or non-contiguous headers.
errOutOfRangeChain = errors.New("out of range or non-contiguous chain")
-
- // errShutdownDetected is returned if a shutdown was detected
- errShutdownDetected = errors.New("shutdown detected")
)
// SignerFn is a signer callback function to request a header to be signed by a
@@ -136,6 +113,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache, c *params.BorConfig
if len(header.Extra) < extraSeal {
return common.Address{}, errMissingSignature
}
+
signature := header.Extra[len(header.Extra)-extraSeal:]
// Recover the public key and the Ethereum address
@@ -143,10 +121,13 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache, c *params.BorConfig
if err != nil {
return common.Address{}, err
}
+
var signer common.Address
+
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
sigcache.Add(hash, signer)
+
return signer, nil
}
@@ -155,6 +136,7 @@ func SealHash(header *types.Header, c *params.BorConfig) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
encodeSigHeader(hasher, header, c)
hasher.Sum(hash[:0])
+
return hash
}
@@ -176,11 +158,13 @@ func encodeSigHeader(w io.Writer, header *types.Header, c *params.BorConfig) {
header.MixDigest,
header.Nonce,
}
+
if c.IsJaipur(header.Number.Uint64()) {
if header.BaseFee != nil {
enc = append(enc, header.BaseFee)
}
}
+
if err := rlp.Encode(w, enc); err != nil {
panic("can't encode: " + err.Error())
}
@@ -194,9 +178,11 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6
if number%c.Sprint == 0 {
delay = c.ProducerDelay
}
+
if succession > 0 {
delay += uint64(succession) * c.CalculateBackupMultiplier(number)
}
+
return delay
}
@@ -210,6 +196,7 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6
func BorRLP(header *types.Header, c *params.BorConfig) []byte {
b := new(bytes.Buffer)
encodeSigHeader(b, header, c)
+
return b.Bytes()
}
@@ -226,25 +213,25 @@ type Bor struct {
signFn SignerFn // Signer function to authorize hashes with
lock sync.RWMutex // Protects the signer fields
- ethAPI *ethapi.PublicBlockChainAPI
- GenesisContractsClient *GenesisContractsClient
- validatorSetABI abi.ABI
- stateReceiverABI abi.ABI
+ ethAPI api.Caller
+ spanner Spanner
+ GenesisContractsClient GenesisContract
HeimdallClient IHeimdallClient
- WithoutHeimdall bool
- scope event.SubscriptionScope
// The fields below are for testing only
fakeDiff bool // Skip difficulty verifications
+
+ closeOnce sync.Once
}
// New creates a Matic Bor consensus engine.
func New(
chainConfig *params.ChainConfig,
db ethdb.Database,
- ethAPI *ethapi.PublicBlockChainAPI,
- heimdallURL string,
- withoutHeimdall bool,
+ ethAPI api.Caller,
+ spanner Spanner,
+ heimdallClient IHeimdallClient,
+ genesisContracts GenesisContract,
) *Bor {
// get bor config
borConfig := chainConfig.Bor
@@ -253,14 +240,10 @@ func New(
if borConfig != nil && borConfig.Sprint == 0 {
borConfig.Sprint = defaultSprintLength
}
-
// Allocate the snapshot caches and create the engine
recents, _ := lru.NewARC(inmemorySnapshots)
signatures, _ := lru.NewARC(inmemorySignatures)
- vABI, _ := abi.JSON(strings.NewReader(validatorsetABI))
- sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI))
- heimdallClient, _ := NewHeimdallClient(heimdallURL)
- genesisContractsClient := NewGenesisContractsClient(chainConfig, borConfig.ValidatorContract, borConfig.StateReceiverContract, ethAPI)
+
c := &Bor{
chainConfig: chainConfig,
config: borConfig,
@@ -268,11 +251,9 @@ func New(
ethAPI: ethAPI,
recents: recents,
signatures: signatures,
- validatorSetABI: vABI,
- stateReceiverABI: sABI,
- GenesisContractsClient: genesisContractsClient,
+ spanner: spanner,
+ GenesisContractsClient: genesisContracts,
HeimdallClient: heimdallClient,
- WithoutHeimdall: withoutHeimdall,
}
// make sure we can decode all the GenesisAlloc in the BorConfig.
@@ -314,6 +295,7 @@ func (c *Bor) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.
}
}
}()
+
return abort, results
}
@@ -325,6 +307,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
if header.Number == nil {
return errUnknownBlock
}
+
number := header.Number.Uint64()
// Don't waste time checking blocks from the future
@@ -337,39 +320,47 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
}
// check extr adata
- isSprintEnd := (number+1)%c.config.Sprint == 0
+ isSprintEnd := IsSprintStart(number+1, c.config.Sprint)
// Ensure that the extra-data contains a signer list on checkpoint, but none otherwise
signersBytes := len(header.Extra) - extraVanity - extraSeal
if !isSprintEnd && signersBytes != 0 {
return errExtraValidators
}
+
if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 {
return errInvalidSpanValidators
}
+
// Ensure that the mix digest is zero as we don't have fork protection currently
if header.MixDigest != (common.Hash{}) {
return errInvalidMixDigest
}
+
// Ensure that the block doesn't contain any uncles which are meaningless in PoA
if header.UncleHash != uncleHash {
return errInvalidUncleHash
}
+
// Ensure that the block's difficulty is meaningful (may not be correct at this point)
if number > 0 {
if header.Difficulty == nil {
return errInvalidDifficulty
}
}
+
// Verify that the gas limit is <= 2^63-1
- cap := uint64(0x7fffffffffffffff)
- if header.GasLimit > cap {
- return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
+ gasCap := uint64(0x7fffffffffffffff)
+
+ if header.GasLimit > gasCap {
+ return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, gasCap)
}
+
// If all checks passed, validate any special fields for hard forks
if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil {
return err
}
+
// All basic checks passed, verify cascading fields
return c.verifyCascadingFields(chain, header, parents)
}
@@ -380,9 +371,11 @@ func validateHeaderExtraField(extraBytes []byte) error {
if len(extraBytes) < extraVanity {
return errMissingVanity
}
+
if len(extraBytes) < extraVanity+extraSeal {
return errMissingSignature
}
+
return nil
}
@@ -393,12 +386,14 @@ func validateHeaderExtraField(extraBytes []byte) error {
func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error {
// The genesis block is the always valid dead-end
number := header.Number.Uint64()
+
if number == 0 {
return nil
}
// Ensure that the block's timestamp isn't too close to it's parent
var parent *types.Header
+
if len(parents) > 0 {
parent = parents[len(parents)-1]
} else {
@@ -413,11 +408,13 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
+
if !chain.Config().IsLondon(header.Number) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, want ", header.BaseFee)
}
+
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
}
@@ -437,13 +434,14 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
}
// verify the validator list in the last sprint block
- if isSprintStart(number, c.config.Sprint) {
+ if IsSprintStart(number, c.config.Sprint) {
parentValidatorBytes := parent.Extra[extraVanity : len(parent.Extra)-extraSeal]
validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength)
currentValidators := snap.ValidatorSet.Copy().Validators
// sort validator by address
- sort.Sort(ValidatorsByAddress(currentValidators))
+ sort.Sort(valset.ValidatorsByAddress(currentValidators))
+
for i, validator := range currentValidators {
copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes())
}
@@ -458,25 +456,29 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
}
// snapshot retrieves the authorization snapshot at a given point in time.
+// nolint: gocognit
func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) {
// Search for a snapshot in memory or on disk for checkpoints
- var (
- headers []*types.Header
- snap *Snapshot
- )
+ var snap *Snapshot
+ headers := make([]*types.Header, 0, 16)
+
+ //nolint:govet
for snap == nil {
// If an in-memory snapshot was found, use that
if s, ok := c.recents.Get(hash); ok {
snap = s.(*Snapshot)
+
break
}
// If an on-disk checkpoint snapshot can be found, use that
if number%checkpointInterval == 0 {
- if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil {
+ if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil {
log.Trace("Loaded snapshot from disk", "number", number, "hash", hash)
+
snap = s
+
break
}
}
@@ -486,6 +488,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
// up more headers than allowed to be reorged (chain reinit from a freezer),
// consider the checkpoint trusted and snapshot it.
// TODO fix this
+ // nolint:nestif
if number == 0 {
checkpoint := chain.GetHeaderByNumber(number)
if checkpoint != nil {
@@ -493,17 +496,19 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
hash := checkpoint.Hash()
// get validators and current span
- validators, err := c.GetCurrentValidators(hash, number+1)
+ validators, err := c.spanner.GetCurrentValidators(hash, number+1)
if err != nil {
return nil, err
}
// new snap shot
- snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI)
+ snap = newSnapshot(c.config, c.signatures, number, hash, validators)
if err := snap.store(c.db); err != nil {
return nil, err
}
+
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
+
break
}
}
@@ -516,6 +521,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
if header.Hash() != hash || header.Number.Uint64() != number {
return nil, consensus.ErrUnknownAncestor
}
+
parents = parents[:len(parents)-1]
} else {
// No explicit parents (or no more left), reach out to the database
@@ -524,10 +530,13 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
return nil, consensus.ErrUnknownAncestor
}
}
+
headers = append(headers, header)
number, hash = number-1, header.ParentHash
}
+ log.Info("Snapshot has been found in", "headers depth", len(headers))
+
// check if snapshot is nil
if snap == nil {
return nil, fmt.Errorf("Unknown error while retrieving snapshot at block number %v", number)
@@ -542,6 +551,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
if err != nil {
return nil, err
}
+
c.recents.Add(snap.Hash, snap)
// If we've generated a new checkpoint snapshot, save to disk
@@ -549,8 +559,10 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
if err = snap.store(c.db); err != nil {
return nil, err
}
+
log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash)
}
+
return snap, err
}
@@ -560,6 +572,7 @@ func (c *Bor) VerifyUncles(chain consensus.ChainReader, block *types.Block) erro
if len(block.Uncles()) > 0 {
return errors.New("uncles not allowed")
}
+
return nil
}
@@ -590,6 +603,7 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header
if err != nil {
return err
}
+
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
// Check the UnauthorizedSignerError.Error() msg to see why we pass number-1
return &UnauthorizedSignerError{number - 1, signer.Bytes()}
@@ -643,17 +657,19 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
if len(header.Extra) < extraVanity {
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
}
+
header.Extra = header.Extra[:extraVanity]
// get validator set if number
- if (number+1)%c.config.Sprint == 0 {
- newValidators, err := c.GetCurrentValidators(header.ParentHash, number+1)
+ if IsSprintStart(number+1, c.config.Sprint) {
+ newValidators, err := c.spanner.GetCurrentValidators(header.ParentHash, number+1)
if err != nil {
return errors.New("unknown validators")
}
// sort validator by address
- sort.Sort(ValidatorsByAddress(newValidators))
+ sort.Sort(valset.ValidatorsByAddress(newValidators))
+
for _, validator := range newValidators {
header.Extra = append(header.Extra, validator.HeaderBytes()...)
}
@@ -673,7 +689,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
var succession int
// if signer is not empty
- if bytes.Compare(c.signer.Bytes(), common.Address{}.Bytes()) != 0 {
+ if c.signer != (common.Address{}) {
succession, err = snap.GetSignerSuccessionNumber(c.signer)
if err != nil {
return err
@@ -684,6 +700,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
if header.Time < uint64(time.Now().Unix()) {
header.Time = uint64(time.Now().Unix())
}
+
return nil
}
@@ -693,16 +710,18 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
stateSyncData := []*types.StateSyncData{}
var err error
+
headerNumber := header.Number.Uint64()
+
if headerNumber%c.config.Sprint == 0 {
- cx := chainContext{Chain: chain, Bor: c}
+ cx := statefull.ChainContext{Chain: chain, Bor: c}
// check and commit span
if err := c.checkAndCommitSpan(state, header, cx); err != nil {
log.Error("Error while committing span", "error", err)
return
}
- if !c.WithoutHeimdall {
+ if c.HeimdallClient != nil {
// commit statees
stateSyncData, err = c.CommitStates(state, header, cx)
if err != nil {
@@ -728,13 +747,16 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
func decodeGenesisAlloc(i interface{}) (core.GenesisAlloc, error) {
var alloc core.GenesisAlloc
+
b, err := json.Marshal(i)
if err != nil {
return nil, err
}
+
if err := json.Unmarshal(b, &alloc); err != nil {
return nil, err
}
+
return alloc, nil
}
@@ -745,12 +767,14 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.State
if err != nil {
return fmt.Errorf("failed to decode genesis alloc: %v", err)
}
+
for addr, account := range allocs {
log.Info("change contract code", "address", addr)
state.SetCode(addr, account.Code)
}
}
}
+
return nil
}
@@ -762,7 +786,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
headerNumber := header.Number.Uint64()
if headerNumber%c.config.Sprint == 0 {
- cx := chainContext{Chain: chain, Bor: c}
+ cx := statefull.ChainContext{Chain: chain, Bor: c}
// check and commit span
err := c.checkAndCommitSpan(state, header, cx)
@@ -771,7 +795,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
return nil, err
}
- if !c.WithoutHeimdall {
+ if c.HeimdallClient != nil {
// commit states
stateSyncData, err = c.CommitStates(state, header, cx)
if err != nil {
@@ -794,7 +818,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
block := types.NewBlock(header, txs, nil, receipts, new(trie.Trie))
// set state sync
- bc := chain.(*core.BlockChain)
+ bc := chain.(core.BorStateSyncer)
bc.SetStateSync(stateSyncData)
// return the final block for sealing
@@ -852,14 +876,14 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result
wiggle := time.Duration(successionNumber) * time.Duration(c.config.CalculateBackupMultiplier(number)) * time.Second
// Sign all the things!
- sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header, c.config))
+ err = Sign(signFn, signer, header, c.config)
if err != nil {
return err
}
- copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
// Wait until sealing is terminated or delay timeout.
- log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
+ log.Info("Waiting for slot to sign and propagate", "number", number, "hash", header.Hash, "delay-in-sec", uint(delay), "delay", common.PrettyDuration(delay))
+
go func() {
select {
case <-stop:
@@ -870,10 +894,13 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result
log.Info(
"Sealing out-of-turn",
"number", number,
+ "hash", header.Hash,
+ "wiggle-in-sec", uint(wiggle),
"wiggle", common.PrettyDuration(wiggle),
"in-turn-signer", snap.ValidatorSet.GetProposer().Address.Hex(),
)
}
+
log.Info(
"Sealing successful",
"number", number,
@@ -887,6 +914,18 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result
log.Warn("Sealing result was not read by miner", "number", number, "sealhash", SealHash(header, c.config))
}
}()
+
+ return nil
+}
+
+func Sign(signFn SignerFn, signer common.Address, header *types.Header, c *params.BorConfig) error {
+ sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header, c))
+ if err != nil {
+ return err
+ }
+
+ copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
+
return nil
}
@@ -898,6 +937,7 @@ func (c *Bor) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, par
if err != nil {
return nil
}
+
return new(big.Int).SetUint64(snap.Difficulty(c.signer))
}
@@ -919,112 +959,13 @@ func (c *Bor) APIs(chain consensus.ChainHeaderReader) []rpc.API {
// Close implements consensus.Engine. It's a noop for bor as there are no background threads.
func (c *Bor) Close() error {
- c.HeimdallClient.Close()
- return nil
-}
-
-// GetCurrentSpan get current span from contract
-func (c *Bor) GetCurrentSpan(headerHash common.Hash) (*Span, error) {
- // block
- blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false)
-
- // method
- method := "getCurrentSpan"
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- data, err := c.validatorSetABI.Pack(method)
- if err != nil {
- log.Error("Unable to pack tx for getCurrentSpan", "error", err)
- return nil, err
- }
-
- msgData := (hexutil.Bytes)(data)
- toAddress := common.HexToAddress(c.config.ValidatorContract)
- gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
- result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
- Gas: &gas,
- To: &toAddress,
- Data: &msgData,
- }, blockNr, nil)
- if err != nil {
- return nil, err
- }
-
- // span result
- ret := new(struct {
- Number *big.Int
- StartBlock *big.Int
- EndBlock *big.Int
- })
- if err := c.validatorSetABI.UnpackIntoInterface(ret, method, result); err != nil {
- return nil, err
- }
-
- // create new span
- span := Span{
- ID: ret.Number.Uint64(),
- StartBlock: ret.StartBlock.Uint64(),
- EndBlock: ret.EndBlock.Uint64(),
- }
-
- return &span, nil
-}
-
-// GetCurrentValidators get current validators
-func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*Validator, error) {
- // block
- blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false)
-
- // method
- method := "getBorValidators"
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- data, err := c.validatorSetABI.Pack(method, big.NewInt(0).SetUint64(blockNumber))
- if err != nil {
- log.Error("Unable to pack tx for getValidator", "error", err)
- return nil, err
- }
-
- // call
- msgData := (hexutil.Bytes)(data)
- toAddress := common.HexToAddress(c.config.ValidatorContract)
- gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
- result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
- Gas: &gas,
- To: &toAddress,
- Data: &msgData,
- }, blockNr, nil)
- if err != nil {
- panic(err)
- // return nil, err
- }
-
- var (
- ret0 = new([]common.Address)
- ret1 = new([]*big.Int)
- )
- out := &[]interface{}{
- ret0,
- ret1,
- }
-
- if err := c.validatorSetABI.UnpackIntoInterface(out, method, result); err != nil {
- return nil, err
- }
-
- valz := make([]*Validator, len(*ret0))
- for i, a := range *ret0 {
- valz[i] = &Validator{
- Address: a,
- VotingPower: (*ret1)[i].Int64(),
+ c.closeOnce.Do(func() {
+ if c.HeimdallClient != nil {
+ c.HeimdallClient.Close()
}
- }
+ })
- return valz, nil
+ return nil
}
func (c *Bor) checkAndCommitSpan(
@@ -1033,18 +974,20 @@ func (c *Bor) checkAndCommitSpan(
chain core.ChainContext,
) error {
headerNumber := header.Number.Uint64()
- span, err := c.GetCurrentSpan(header.ParentHash)
+
+ span, err := c.spanner.GetCurrentSpan(header.ParentHash)
if err != nil {
return err
}
+
if c.needToCommitSpan(span, headerNumber) {
- err := c.fetchAndCommitSpan(span.ID+1, state, header, chain)
- return err
+ return c.FetchAndCommitSpan(span.ID+1, state, header, chain)
}
+
return nil
}
-func (c *Bor) needToCommitSpan(span *Span, headerNumber uint64) bool {
+func (c *Bor) needToCommitSpan(span *span.Span, headerNumber uint64) bool {
// if span is nil
if span == nil {
return false
@@ -1063,99 +1006,52 @@ func (c *Bor) needToCommitSpan(span *Span, headerNumber uint64) bool {
return false
}
-func (c *Bor) fetchAndCommitSpan(
+func (c *Bor) FetchAndCommitSpan(
newSpanID uint64,
state *state.StateDB,
header *types.Header,
chain core.ChainContext,
) error {
- var heimdallSpan HeimdallSpan
+ var heimdallSpan span.HeimdallSpan
- if c.WithoutHeimdall {
- s, err := c.getNextHeimdallSpanForTest(newSpanID, state, header, chain)
+ if c.HeimdallClient == nil {
+ // fixme: move to a new mock or fake and remove c.HeimdallClient completely
+ s, err := c.getNextHeimdallSpanForTest(newSpanID, header, chain)
if err != nil {
return err
}
+
heimdallSpan = *s
} else {
- response, err := c.HeimdallClient.FetchWithRetry(fmt.Sprintf("bor/span/%d", newSpanID), "")
+ response, err := c.HeimdallClient.Span(newSpanID)
if err != nil {
return err
}
- if err := json.Unmarshal(response.Result, &heimdallSpan); err != nil {
- return err
- }
+ heimdallSpan = *response
}
- // check if chain id matches with heimdall span
+ // check if chain id matches with Heimdall span
if heimdallSpan.ChainID != c.chainConfig.ChainID.String() {
return fmt.Errorf(
- "Chain id proposed span, %s, and bor chain id, %s, doesn't match",
+ "chain id proposed span, %s, and bor chain id, %s, doesn't match",
heimdallSpan.ChainID,
c.chainConfig.ChainID,
)
}
- // get validators bytes
- var validators []MinimalVal
- for _, val := range heimdallSpan.ValidatorSet.Validators {
- validators = append(validators, val.MinimalVal())
- }
- validatorBytes, err := rlp.EncodeToBytes(validators)
- if err != nil {
- return err
- }
-
- // get producers bytes
- var producers []MinimalVal
- for _, val := range heimdallSpan.SelectedProducers {
- producers = append(producers, val.MinimalVal())
- }
- producerBytes, err := rlp.EncodeToBytes(producers)
- if err != nil {
- return err
- }
-
- // method
- method := "commitSpan"
- log.Info("✅ Committing new span",
- "id", heimdallSpan.ID,
- "startBlock", heimdallSpan.StartBlock,
- "endBlock", heimdallSpan.EndBlock,
- "validatorBytes", hex.EncodeToString(validatorBytes),
- "producerBytes", hex.EncodeToString(producerBytes),
- )
-
- // get packed data
- data, err := c.validatorSetABI.Pack(method,
- big.NewInt(0).SetUint64(heimdallSpan.ID),
- big.NewInt(0).SetUint64(heimdallSpan.StartBlock),
- big.NewInt(0).SetUint64(heimdallSpan.EndBlock),
- validatorBytes,
- producerBytes,
- )
- if err != nil {
- log.Error("Unable to pack tx for commitSpan", "error", err)
- return err
- }
-
- // get system message
- msg := getSystemMessage(common.HexToAddress(c.config.ValidatorContract), data)
-
- // apply message
- _, err = applyMessage(msg, state, header, c.chainConfig, chain)
- return err
+ return c.spanner.CommitSpan(heimdallSpan, state, header, chain)
}
// CommitStates commit states
func (c *Bor) CommitStates(
state *state.StateDB,
header *types.Header,
- chain chainContext,
+ chain statefull.ChainContext,
) ([]*types.StateSyncData, error) {
stateSyncs := make([]*types.StateSyncData, 0)
number := header.Number.Uint64()
+
_lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1)
if err != nil {
return nil, err
@@ -1163,11 +1059,17 @@ func (c *Bor) CommitStates(
to := time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.Sprint).Time), 0)
lastStateID := _lastStateID.Uint64()
+
log.Info(
"Fetching state updates from Heimdall",
"fromID", lastStateID+1,
"to", to.Format(time.RFC3339))
- eventRecords, err := c.HeimdallClient.FetchStateSyncEvents(lastStateID+1, to.Unix())
+
+ eventRecords, err := c.HeimdallClient.StateSyncEvents(lastStateID+1, to.Unix())
+ if err != nil {
+ log.Error("Error occurred when fetching state sync events", "stateID", lastStateID+1, "error", err)
+ }
+
if c.config.OverrideStateSyncRecords != nil {
if val, ok := c.config.OverrideStateSyncRecords[strconv.FormatUint(number, 10)]; ok {
eventRecords = eventRecords[0:val]
@@ -1177,12 +1079,14 @@ func (c *Bor) CommitStates(
totalGas := 0 /// limit on gas for state sync per block
chainID := c.chainConfig.ChainID.String()
+
for _, eventRecord := range eventRecords {
if eventRecord.ID <= lastStateID {
continue
}
+
if err := validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil {
- log.Error(err.Error())
+ log.Error("while validating event record", "block", number, "to", to, "stateID", lastStateID, "error", err.Error())
break
}
@@ -1192,25 +1096,30 @@ func (c *Bor) CommitStates(
Data: hex.EncodeToString(eventRecord.Data),
TxHash: eventRecord.TxHash,
}
+
stateSyncs = append(stateSyncs, &stateData)
gasUsed, err := c.GenesisContractsClient.CommitState(eventRecord, state, header, chain)
if err != nil {
return nil, err
}
+
totalGas += int(gasUsed)
lastStateID++
}
+
log.Info("StateSyncData", "Gas", totalGas, "Block-number", number, "LastStateID", lastStateID, "TotalRecords", len(eventRecords))
+
return stateSyncs, nil
}
-func validateEventRecord(eventRecord *EventRecordWithTime, number uint64, to time.Time, lastStateID uint64, chainID string) error {
+func validateEventRecord(eventRecord *clerk.EventRecordWithTime, number uint64, to time.Time, lastStateID uint64, chainID string) error {
// event id should be sequential and event.Time should lie in the range [from, to)
if lastStateID+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) {
return &InvalidStateReceivedError{number, lastStateID, &to, eventRecord}
}
+
return nil
}
@@ -1218,24 +1127,28 @@ func (c *Bor) SetHeimdallClient(h IHeimdallClient) {
c.HeimdallClient = h
}
+func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) {
+ return c.spanner.GetCurrentValidators(headerHash, blockNumber)
+}
+
//
// Private methods
//
func (c *Bor) getNextHeimdallSpanForTest(
newSpanID uint64,
- state *state.StateDB,
header *types.Header,
chain core.ChainContext,
-) (*HeimdallSpan, error) {
+) (*span.HeimdallSpan, error) {
headerNumber := header.Number.Uint64()
- span, err := c.GetCurrentSpan(header.ParentHash)
+
+ spanBor, err := c.spanner.GetCurrentSpan(header.ParentHash)
if err != nil {
return nil, err
}
// get local chain context object
- localContext := chain.(chainContext)
+ localContext := chain.(statefull.ChainContext)
// Retrieve the snapshot needed to verify this header and cache it
snap, err := c.snapshot(localContext.Chain, headerNumber-1, header.ParentHash, nil)
if err != nil {
@@ -1243,20 +1156,22 @@ func (c *Bor) getNextHeimdallSpanForTest(
}
// new span
- span.ID = newSpanID
- if span.EndBlock == 0 {
- span.StartBlock = 256
+ spanBor.ID = newSpanID
+ if spanBor.EndBlock == 0 {
+ spanBor.StartBlock = 256
} else {
- span.StartBlock = span.EndBlock + 1
+ spanBor.StartBlock = spanBor.EndBlock + 1
}
- span.EndBlock = span.StartBlock + (100 * c.config.Sprint) - 1
- selectedProducers := make([]Validator, len(snap.ValidatorSet.Validators))
+ spanBor.EndBlock = spanBor.StartBlock + (100 * c.config.Sprint) - 1
+
+ selectedProducers := make([]valset.Validator, len(snap.ValidatorSet.Validators))
for i, v := range snap.ValidatorSet.Validators {
selectedProducers[i] = *v
}
- heimdallSpan := &HeimdallSpan{
- Span: *span,
+
+ heimdallSpan := &span.HeimdallSpan{
+ Span: *spanBor,
ValidatorSet: *snap.ValidatorSet,
SelectedProducers: selectedProducers,
ChainID: c.chainConfig.ChainID.String(),
@@ -1265,98 +1180,22 @@ func (c *Bor) getNextHeimdallSpanForTest(
return heimdallSpan, nil
}
-//
-// Chain context
-//
-
-// chain context
-type chainContext struct {
- Chain consensus.ChainHeaderReader
- Bor consensus.Engine
-}
-
-func (c chainContext) Engine() consensus.Engine {
- return c.Bor
-}
-
-func (c chainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
- return c.Chain.GetHeader(hash, number)
-}
-
-// callmsg implements core.Message to allow passing it as a transaction simulator.
-type callmsg struct {
- ethereum.CallMsg
-}
-
-func (m callmsg) From() common.Address { return m.CallMsg.From }
-func (m callmsg) Nonce() uint64 { return 0 }
-func (m callmsg) CheckNonce() bool { return false }
-func (m callmsg) To() *common.Address { return m.CallMsg.To }
-func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
-func (m callmsg) Gas() uint64 { return m.CallMsg.Gas }
-func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
-func (m callmsg) Data() []byte { return m.CallMsg.Data }
-
-// get system message
-func getSystemMessage(toAddress common.Address, data []byte) callmsg {
- return callmsg{
- ethereum.CallMsg{
- From: systemAddress,
- Gas: math.MaxUint64 / 2,
- GasPrice: big.NewInt(0),
- Value: big.NewInt(0),
- To: &toAddress,
- Data: data,
- },
- }
-}
-
-// apply message
-func applyMessage(
- msg callmsg,
- state *state.StateDB,
- header *types.Header,
- chainConfig *params.ChainConfig,
- chainContext core.ChainContext,
-) (uint64, error) {
- initialGas := msg.Gas()
-
- // Create a new context to be used in the EVM environment
- blockContext := core.NewEVMBlockContext(header, chainContext, &header.Coinbase)
- // Create a new environment which holds all relevant information
- // about the transaction and calling mechanisms.
- vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{})
- // Apply the transaction to the current state (included in the env)
- _, gasLeft, err := vmenv.Call(
- vm.AccountRef(msg.From()),
- *msg.To(),
- msg.Data(),
- msg.Gas(),
- msg.Value(),
- )
- // Update the state with pending changes
- if err != nil {
- state.Finalise(true)
- }
-
- gasUsed := initialGas - gasLeft
- return gasUsed, nil
-}
-
-func validatorContains(a []*Validator, x *Validator) (*Validator, bool) {
+func validatorContains(a []*valset.Validator, x *valset.Validator) (*valset.Validator, bool) {
for _, n := range a {
- if bytes.Compare(n.Address.Bytes(), x.Address.Bytes()) == 0 {
+ if n.Address == x.Address {
return n, true
}
}
+
return nil, false
}
-func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) *ValidatorSet {
+func getUpdatedValidatorSet(oldValidatorSet *valset.ValidatorSet, newVals []*valset.Validator) *valset.ValidatorSet {
v := oldValidatorSet
oldVals := v.Validators
- var changes []*Validator
+ changes := make([]*valset.Validator, 0, len(oldVals))
+
for _, ov := range oldVals {
if f, ok := validatorContains(newVals, ov); ok {
ov.VotingPower = f.VotingPower
@@ -1373,10 +1212,13 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator)
}
}
- v.UpdateWithChangeSet(changes)
+ if err := v.UpdateWithChangeSet(changes); err != nil {
+ log.Error("Error while updating change set", "error", err)
+ }
+
return v
}
-func isSprintStart(number, sprint uint64) bool {
+func IsSprintStart(number, sprint uint64) bool {
return number%sprint == 0
}
diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go
index b0ebc96861..6225532ca9 100644
--- a/consensus/bor/bor_test.go
+++ b/consensus/bor/bor_test.go
@@ -4,6 +4,8 @@ import (
"math/big"
"testing"
+ "github.com/stretchr/testify/assert"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
@@ -12,10 +14,11 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
- "github.com/stretchr/testify/assert"
)
func TestGenesisContractChange(t *testing.T) {
+ t.Parallel()
+
addr0 := common.Address{0x1}
b := &Bor{
@@ -101,6 +104,8 @@ func TestGenesisContractChange(t *testing.T) {
}
func TestEncodeSigHeaderJaipur(t *testing.T) {
+ t.Parallel()
+
// As part of the EIP-1559 fork in mumbai, an incorrect seal hash
// was used for Bor that did not included the BaseFee. The Jaipur
// block is a hard fork to fix that.
diff --git a/consensus/bor/clerk.go b/consensus/bor/clerk/clerk.go
similarity index 98%
rename from consensus/bor/clerk.go
rename to consensus/bor/clerk/clerk.go
index 5524e249f2..fedca3df16 100644
--- a/consensus/bor/clerk.go
+++ b/consensus/bor/clerk/clerk.go
@@ -1,4 +1,4 @@
-package bor
+package clerk
import (
"fmt"
diff --git a/consensus/bor/contract/client.go b/consensus/bor/contract/client.go
new file mode 100644
index 0000000000..d65fb5bb15
--- /dev/null
+++ b/consensus/bor/contract/client.go
@@ -0,0 +1,133 @@
+package contract
+
+import (
+ "context"
+ "math"
+ "math/big"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/consensus/bor/api"
+ "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ "github.com/ethereum/go-ethereum/consensus/bor/statefull"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+var (
+ vABI, _ = abi.JSON(strings.NewReader(validatorsetABI))
+ sABI, _ = abi.JSON(strings.NewReader(stateReceiverABI))
+)
+
+func ValidatorSet() abi.ABI {
+ return vABI
+}
+
+func StateReceiver() abi.ABI {
+ return sABI
+}
+
+type GenesisContractsClient struct {
+ validatorSetABI abi.ABI
+ stateReceiverABI abi.ABI
+ ValidatorContract string
+ StateReceiverContract string
+ chainConfig *params.ChainConfig
+ ethAPI api.Caller
+}
+
+const (
+ validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]`
+ stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
+)
+
+func NewGenesisContractsClient(
+ chainConfig *params.ChainConfig,
+ validatorContract,
+ stateReceiverContract string,
+ ethAPI api.Caller,
+) *GenesisContractsClient {
+ return &GenesisContractsClient{
+ validatorSetABI: ValidatorSet(),
+ stateReceiverABI: StateReceiver(),
+ ValidatorContract: validatorContract,
+ StateReceiverContract: stateReceiverContract,
+ chainConfig: chainConfig,
+ ethAPI: ethAPI,
+ }
+}
+
+func (gc *GenesisContractsClient) CommitState(
+ event *clerk.EventRecordWithTime,
+ state *state.StateDB,
+ header *types.Header,
+ chCtx statefull.ChainContext,
+) (uint64, error) {
+ eventRecord := event.BuildEventRecord()
+
+ recordBytes, err := rlp.EncodeToBytes(eventRecord)
+ if err != nil {
+ return 0, err
+ }
+
+ const method = "commitState"
+
+ t := event.Time.Unix()
+
+ data, err := gc.stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(t), recordBytes)
+ if err != nil {
+ log.Error("Unable to pack tx for commitState", "error", err)
+ return 0, err
+ }
+
+ msg := statefull.GetSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
+ gasUsed, err := statefull.ApplyMessage(msg, state, header, gc.chainConfig, chCtx)
+
+ // Logging event log with time and individual gasUsed
+ log.Info("→ committing new state", "eventRecord", event.String(gasUsed))
+
+ if err != nil {
+ return 0, err
+ }
+
+ return gasUsed, nil
+}
+
+func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, error) {
+ blockNr := rpc.BlockNumber(snapshotNumber)
+ method := "lastStateId"
+
+ data, err := gc.stateReceiverABI.Pack(method)
+ if err != nil {
+ log.Error("Unable to pack tx for LastStateId", "error", err)
+
+ return nil, err
+ }
+
+ msgData := (hexutil.Bytes)(data)
+ toAddress := common.HexToAddress(gc.StateReceiverContract)
+ gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+
+ result, err := gc.ethAPI.Call(context.Background(), ethapi.TransactionArgs{
+ Gas: &gas,
+ To: &toAddress,
+ Data: &msgData,
+ }, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ ret := new(*big.Int)
+ if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil {
+ return nil, err
+ }
+
+ return *ret, nil
+}
diff --git a/consensus/bor/errors.go b/consensus/bor/errors.go
index df01b405b6..67f7ef53f3 100644
--- a/consensus/bor/errors.go
+++ b/consensus/bor/errors.go
@@ -3,37 +3,10 @@ package bor
import (
"fmt"
"time"
+
+ "github.com/ethereum/go-ethereum/consensus/bor/clerk"
)
-// TotalVotingPowerExceededError is returned when the maximum allowed total voting power is exceeded
-type TotalVotingPowerExceededError struct {
- Sum int64
- Validators []*Validator
-}
-
-func (e *TotalVotingPowerExceededError) Error() string {
- return fmt.Sprintf(
- "Total voting power should be guarded to not exceed %v; got: %v; for validator set: %v",
- MaxTotalVotingPower,
- e.Sum,
- e.Validators,
- )
-}
-
-type InvalidStartEndBlockError struct {
- Start uint64
- End uint64
- CurrentHeader uint64
-}
-
-func (e *InvalidStartEndBlockError) Error() string {
- return fmt.Sprintf(
- "Invalid parameters start: %d and end block: %d params",
- e.Start,
- e.End,
- )
-}
-
type MaxCheckpointLengthExceededError struct {
Start uint64
End uint64
@@ -129,7 +102,7 @@ type InvalidStateReceivedError struct {
Number uint64
LastStateID uint64
To *time.Time
- Event *EventRecordWithTime
+ Event *clerk.EventRecordWithTime
}
func (e *InvalidStateReceivedError) Error() string {
diff --git a/consensus/bor/genesis.go b/consensus/bor/genesis.go
new file mode 100644
index 0000000000..33de53f9ba
--- /dev/null
+++ b/consensus/bor/genesis.go
@@ -0,0 +1,16 @@
+package bor
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ "github.com/ethereum/go-ethereum/consensus/bor/statefull"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+)
+
+//go:generate mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract
+type GenesisContract interface {
+ CommitState(event *clerk.EventRecordWithTime, state *state.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error)
+ LastStateId(snapshotNumber uint64) (*big.Int, error)
+}
diff --git a/consensus/bor/genesis_contract_mock.go b/consensus/bor/genesis_contract_mock.go
new file mode 100644
index 0000000000..dfe9390509
--- /dev/null
+++ b/consensus/bor/genesis_contract_mock.go
@@ -0,0 +1,69 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: GenesisContract)
+
+// Package bor is a generated GoMock package.
+package bor
+
+import (
+ big "math/big"
+ reflect "reflect"
+
+ clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ statefull "github.com/ethereum/go-ethereum/consensus/bor/statefull"
+ state "github.com/ethereum/go-ethereum/core/state"
+ types "github.com/ethereum/go-ethereum/core/types"
+ gomock "github.com/golang/mock/gomock"
+)
+
+// MockGenesisContract is a mock of GenesisContract interface.
+type MockGenesisContract struct {
+ ctrl *gomock.Controller
+ recorder *MockGenesisContractMockRecorder
+}
+
+// MockGenesisContractMockRecorder is the mock recorder for MockGenesisContract.
+type MockGenesisContractMockRecorder struct {
+ mock *MockGenesisContract
+}
+
+// NewMockGenesisContract creates a new mock instance.
+func NewMockGenesisContract(ctrl *gomock.Controller) *MockGenesisContract {
+ mock := &MockGenesisContract{ctrl: ctrl}
+ mock.recorder = &MockGenesisContractMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockGenesisContract) EXPECT() *MockGenesisContractMockRecorder {
+ return m.recorder
+}
+
+// CommitState mocks base method.
+func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 *state.StateDB, arg2 *types.Header, arg3 statefull.ChainContext) (uint64, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "CommitState", arg0, arg1, arg2, arg3)
+ ret0, _ := ret[0].(uint64)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// CommitState indicates an expected call of CommitState.
+func (mr *MockGenesisContractMockRecorder) CommitState(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitState", reflect.TypeOf((*MockGenesisContract)(nil).CommitState), arg0, arg1, arg2, arg3)
+}
+
+// LastStateId mocks base method.
+func (m *MockGenesisContract) LastStateId(arg0 uint64) (*big.Int, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "LastStateId", arg0)
+ ret0, _ := ret[0].(*big.Int)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// LastStateId indicates an expected call of LastStateId.
+func (mr *MockGenesisContractMockRecorder) LastStateId(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastStateId", reflect.TypeOf((*MockGenesisContract)(nil).LastStateId), arg0)
+}
diff --git a/consensus/bor/genesis_contracts_client.go b/consensus/bor/genesis_contracts_client.go
deleted file mode 100644
index 79a2a254c4..0000000000
--- a/consensus/bor/genesis_contracts_client.go
+++ /dev/null
@@ -1,105 +0,0 @@
-package bor
-
-import (
- "context"
- "math"
- "math/big"
- "strings"
-
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/internal/ethapi"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-type GenesisContractsClient struct {
- validatorSetABI abi.ABI
- stateReceiverABI abi.ABI
- ValidatorContract string
- StateReceiverContract string
- chainConfig *params.ChainConfig
- ethAPI *ethapi.PublicBlockChainAPI
-}
-
-const validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]`
-const stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
-
-func NewGenesisContractsClient(
- chainConfig *params.ChainConfig,
- validatorContract,
- stateReceiverContract string,
- ethAPI *ethapi.PublicBlockChainAPI,
-) *GenesisContractsClient {
- vABI, _ := abi.JSON(strings.NewReader(validatorsetABI))
- sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI))
- return &GenesisContractsClient{
- validatorSetABI: vABI,
- stateReceiverABI: sABI,
- ValidatorContract: validatorContract,
- StateReceiverContract: stateReceiverContract,
- chainConfig: chainConfig,
- ethAPI: ethAPI,
- }
-}
-
-func (gc *GenesisContractsClient) CommitState(
- event *EventRecordWithTime,
- state *state.StateDB,
- header *types.Header,
- chCtx chainContext,
-) (uint64, error) {
- eventRecord := event.BuildEventRecord()
- recordBytes, err := rlp.EncodeToBytes(eventRecord)
- if err != nil {
- return 0, err
- }
- method := "commitState"
- t := event.Time.Unix()
- data, err := gc.stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(t), recordBytes)
- if err != nil {
- log.Error("Unable to pack tx for commitState", "error", err)
- return 0, err
- }
- msg := getSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
- gasUsed, err := applyMessage(msg, state, header, gc.chainConfig, chCtx)
- // Logging event log with time and individual gasUsed
- log.Info("→ committing new state", "eventRecord", event.String(gasUsed))
- if err != nil {
- return 0, err
- }
- return gasUsed, nil
-}
-
-func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, error) {
- blockNr := rpc.BlockNumber(snapshotNumber)
- method := "lastStateId"
- data, err := gc.stateReceiverABI.Pack(method)
- if err != nil {
- log.Error("Unable to pack tx for LastStateId", "error", err)
- return nil, err
- }
-
- msgData := (hexutil.Bytes)(data)
- toAddress := common.HexToAddress(gc.StateReceiverContract)
- gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
- result, err := gc.ethAPI.Call(context.Background(), ethapi.TransactionArgs{
- Gas: &gas,
- To: &toAddress,
- Data: &msgData,
- }, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil)
- if err != nil {
- return nil, err
- }
-
- var ret = new(*big.Int)
- if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil {
- return nil, err
- }
- return *ret, nil
-}
diff --git a/consensus/bor/heimdall.go b/consensus/bor/heimdall.go
new file mode 100644
index 0000000000..217de13fe9
--- /dev/null
+++ b/consensus/bor/heimdall.go
@@ -0,0 +1,15 @@
+package bor
+
+import (
+ "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
+)
+
+//go:generate mockgen -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks . IHeimdallClient
+type IHeimdallClient interface {
+ StateSyncEvents(fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error)
+ Span(spanID uint64) (*span.HeimdallSpan, error)
+ FetchLatestCheckpoint() (*checkpoint.Checkpoint, error)
+ Close()
+}
diff --git a/consensus/bor/heimdall/checkpoint/checkpoint.go b/consensus/bor/heimdall/checkpoint/checkpoint.go
new file mode 100644
index 0000000000..77569293ad
--- /dev/null
+++ b/consensus/bor/heimdall/checkpoint/checkpoint.go
@@ -0,0 +1,22 @@
+package checkpoint
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// Checkpoint defines a response object type of bor checkpoint
+type Checkpoint struct {
+ Proposer common.Address `json:"proposer"`
+ StartBlock *big.Int `json:"start_block"`
+ EndBlock *big.Int `json:"end_block"`
+ RootHash common.Hash `json:"root_hash"`
+ BorChainID string `json:"bor_chain_id"`
+ Timestamp uint64 `json:"timestamp"`
+}
+
+type CheckpointResponse struct {
+ Height string `json:"height"`
+ Result Checkpoint `json:"result"`
+}
diff --git a/consensus/bor/heimdall/client.go b/consensus/bor/heimdall/client.go
new file mode 100644
index 0000000000..2d42cfc31b
--- /dev/null
+++ b/consensus/bor/heimdall/client.go
@@ -0,0 +1,243 @@
+package heimdall
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "sort"
+ "time"
+
+ "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// errShutdownDetected is returned if a shutdown was detected
+var errShutdownDetected = errors.New("shutdown detected")
+
+const (
+ stateFetchLimit = 50
+ apiHeimdallTimeout = 5 * time.Second
+)
+
+type StateSyncEventsResponse struct {
+ Height string `json:"height"`
+ Result []*clerk.EventRecordWithTime `json:"result"`
+}
+
+type SpanResponse struct {
+ Height string `json:"height"`
+ Result span.HeimdallSpan `json:"result"`
+}
+
+type HeimdallClient struct {
+ urlString string
+ client http.Client
+ closeCh chan struct{}
+}
+
+func NewHeimdallClient(urlString string) *HeimdallClient {
+ return &HeimdallClient{
+ urlString: urlString,
+ client: http.Client{
+ Timeout: apiHeimdallTimeout,
+ },
+ closeCh: make(chan struct{}),
+ }
+}
+
+const (
+ fetchStateSyncEventsFormat = "from-id=%d&to-time=%d&limit=%d"
+ fetchStateSyncEventsPath = "clerk/event-record/list"
+ fetchLatestCheckpoint = "/checkpoints/latest"
+
+ fetchSpanFormat = "bor/span/%d"
+)
+
+func (h *HeimdallClient) StateSyncEvents(fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
+ eventRecords := make([]*clerk.EventRecordWithTime, 0)
+
+ for {
+ url, err := stateSyncURL(h.urlString, fromID, to)
+ if err != nil {
+ return nil, err
+ }
+
+ log.Info("Fetching state sync events", "queryParams", url.RawQuery)
+
+ response, err := FetchWithRetry[StateSyncEventsResponse](h.client, url, h.closeCh)
+ if err != nil {
+ return nil, err
+ }
+
+ if response == nil || response.Result == nil {
+ // status 204
+ break
+ }
+
+ eventRecords = append(eventRecords, response.Result...)
+
+ if len(response.Result) < stateFetchLimit {
+ break
+ }
+
+ fromID += uint64(stateFetchLimit)
+ }
+
+ sort.SliceStable(eventRecords, func(i, j int) bool {
+ return eventRecords[i].ID < eventRecords[j].ID
+ })
+
+ return eventRecords, nil
+}
+
+func (h *HeimdallClient) Span(spanID uint64) (*span.HeimdallSpan, error) {
+ url, err := spanURL(h.urlString, spanID)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := FetchWithRetry[SpanResponse](h.client, url, h.closeCh)
+ if err != nil {
+ return nil, err
+ }
+
+ return &response.Result, nil
+}
+
+// FetchLatestCheckpoint fetches the latest bor submitted checkpoint from heimdall
+func (h *HeimdallClient) FetchLatestCheckpoint() (*checkpoint.Checkpoint, error) {
+ url, err := latestCheckpointURL(h.urlString)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := FetchWithRetry[checkpoint.CheckpointResponse](h.client, url, h.closeCh)
+ if err != nil {
+ return nil, err
+ }
+
+ return &response.Result, nil
+}
+
+// FetchWithRetry returns data from heimdall with retry
+func FetchWithRetry[T any](client http.Client, url *url.URL, closeCh chan struct{}) (*T, error) {
+ // attempt counter
+ attempt := 1
+ result := new(T)
+
+ ctx, cancel := context.WithTimeout(context.Background(), apiHeimdallTimeout)
+
+ // request data once
+ body, err := internalFetch(ctx, client, url)
+
+ cancel()
+
+ if err == nil && body != nil {
+ err = json.Unmarshal(body, result)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+ }
+
+ // create a new ticker for retrying the request
+ ticker := time.NewTicker(5 * time.Second)
+ defer ticker.Stop()
+
+ for {
+ log.Info("Retrying again in 5 seconds to fetch data from Heimdall", "path", url.Path, "attempt", attempt)
+ attempt++
+ select {
+ case <-closeCh:
+ log.Debug("Shutdown detected, terminating request")
+
+ return nil, errShutdownDetected
+ case <-ticker.C:
+ ctx, cancel = context.WithTimeout(context.Background(), apiHeimdallTimeout)
+
+ body, err = internalFetch(ctx, client, url)
+
+ cancel()
+
+ if err == nil && body != nil {
+ err = json.Unmarshal(body, result)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+ }
+ }
+ }
+}
+
+func spanURL(urlString string, spanID uint64) (*url.URL, error) {
+ return makeURL(urlString, fmt.Sprintf(fetchSpanFormat, spanID), "")
+}
+
+func stateSyncURL(urlString string, fromID uint64, to int64) (*url.URL, error) {
+ queryParams := fmt.Sprintf(fetchStateSyncEventsFormat, fromID, to, stateFetchLimit)
+
+ return makeURL(urlString, fetchStateSyncEventsPath, queryParams)
+}
+
+func latestCheckpointURL(urlString string) (*url.URL, error) {
+ return makeURL(urlString, fetchLatestCheckpoint, "")
+}
+
+func makeURL(urlString, rawPath, rawQuery string) (*url.URL, error) {
+ u, err := url.Parse(urlString)
+ if err != nil {
+ return nil, err
+ }
+
+ u.Path = rawPath
+ u.RawQuery = rawQuery
+
+ return u, err
+}
+
+// internal fetch method
+func internalFetch(ctx context.Context, client http.Client, u *url.URL) ([]byte, error) {
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ res, err := client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+
+ // check status code
+ if res.StatusCode != 200 && res.StatusCode != 204 {
+ return nil, fmt.Errorf("Error while fetching data from Heimdall")
+ }
+
+ // unmarshall data from buffer
+ if res.StatusCode == 204 {
+ return nil, nil
+ }
+
+ // get response
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ return body, nil
+}
+
+// Close sends a signal to stop the running process
+func (h *HeimdallClient) Close() {
+ close(h.closeCh)
+ h.client.CloseIdleConnections()
+}
diff --git a/consensus/bor/heimdall/client_test.go b/consensus/bor/heimdall/client_test.go
new file mode 100644
index 0000000000..c423a6f659
--- /dev/null
+++ b/consensus/bor/heimdall/client_test.go
@@ -0,0 +1,35 @@
+package heimdall
+
+import (
+ "testing"
+)
+
+func TestSpanURL(t *testing.T) {
+ t.Parallel()
+
+ url, err := spanURL("http://bor0", 1)
+ if err != nil {
+ t.Fatal("got an error", err)
+ }
+
+ const expected = "http://bor0/bor/span/1"
+
+ if url.String() != expected {
+ t.Fatalf("expected URL %q, got %q", url.String(), expected)
+ }
+}
+
+func TestStateSyncURL(t *testing.T) {
+ t.Parallel()
+
+ url, err := stateSyncURL("http://bor0", 10, 100)
+ if err != nil {
+ t.Fatal("got an error", err)
+ }
+
+ const expected = "http://bor0/clerk/event-record/list?from-id=10&to-time=100&limit=50"
+
+ if url.String() != expected {
+ t.Fatalf("expected URL %q, got %q", url.String(), expected)
+ }
+}
diff --git a/consensus/bor/heimdall/span/span.go b/consensus/bor/heimdall/span/span.go
new file mode 100644
index 0000000000..5bf85fb341
--- /dev/null
+++ b/consensus/bor/heimdall/span/span.go
@@ -0,0 +1,20 @@
+package span
+
+import (
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
+)
+
+// Span Bor represents a current bor span
+type Span struct {
+ ID uint64 `json:"span_id" yaml:"span_id"`
+ StartBlock uint64 `json:"start_block" yaml:"start_block"`
+ EndBlock uint64 `json:"end_block" yaml:"end_block"`
+}
+
+// HeimdallSpan represents span from heimdall APIs
+type HeimdallSpan struct {
+ Span
+ ValidatorSet valset.ValidatorSet `json:"validator_set" yaml:"validator_set"`
+ SelectedProducers []valset.Validator `json:"selected_producers" yaml:"selected_producers"`
+ ChainID string `json:"bor_chain_id" yaml:"bor_chain_id"`
+}
diff --git a/consensus/bor/heimdall/span/spanner.go b/consensus/bor/heimdall/span/spanner.go
new file mode 100644
index 0000000000..7bf6e350ee
--- /dev/null
+++ b/consensus/bor/heimdall/span/spanner.go
@@ -0,0 +1,200 @@
+package span
+
+import (
+ "context"
+ "encoding/hex"
+ "math"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/consensus/bor/abi"
+ "github.com/ethereum/go-ethereum/consensus/bor/api"
+ "github.com/ethereum/go-ethereum/consensus/bor/statefull"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+type ChainSpanner struct {
+ ethAPI api.Caller
+ validatorSet abi.ABI
+ chainConfig *params.ChainConfig
+ validatorContractAddress common.Address
+}
+
+func NewChainSpanner(ethAPI api.Caller, validatorSet abi.ABI, chainConfig *params.ChainConfig, validatorContractAddress common.Address) *ChainSpanner {
+ return &ChainSpanner{
+ ethAPI: ethAPI,
+ validatorSet: validatorSet,
+ chainConfig: chainConfig,
+ validatorContractAddress: validatorContractAddress,
+ }
+}
+
+// GetCurrentSpan get current span from contract
+func (c *ChainSpanner) GetCurrentSpan(headerHash common.Hash) (*Span, error) {
+ // block
+ blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false)
+
+ // method
+ method := "getCurrentSpan"
+
+ data, err := c.validatorSet.Pack(method)
+ if err != nil {
+ log.Error("Unable to pack tx for getCurrentSpan", "error", err)
+
+ return nil, err
+ }
+
+ msgData := (hexutil.Bytes)(data)
+ toAddress := c.validatorContractAddress
+ gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+
+ // todo: would we like to have a timeout here?
+ result, err := c.ethAPI.Call(context.Background(), ethapi.TransactionArgs{
+ Gas: &gas,
+ To: &toAddress,
+ Data: &msgData,
+ }, blockNr, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // span result
+ ret := new(struct {
+ Number *big.Int
+ StartBlock *big.Int
+ EndBlock *big.Int
+ })
+
+ if err := c.validatorSet.UnpackIntoInterface(ret, method, result); err != nil {
+ return nil, err
+ }
+
+ // create new span
+ span := Span{
+ ID: ret.Number.Uint64(),
+ StartBlock: ret.StartBlock.Uint64(),
+ EndBlock: ret.EndBlock.Uint64(),
+ }
+
+ return &span, nil
+}
+
+// GetCurrentValidators get current validators
+func (c *ChainSpanner) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ // method
+ const method = "getBorValidators"
+
+ data, err := c.validatorSet.Pack(method, big.NewInt(0).SetUint64(blockNumber))
+ if err != nil {
+ log.Error("Unable to pack tx for getValidator", "error", err)
+ return nil, err
+ }
+
+ // call
+ msgData := (hexutil.Bytes)(data)
+ toAddress := c.validatorContractAddress
+ gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+
+ // block
+ blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false)
+
+ result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
+ Gas: &gas,
+ To: &toAddress,
+ Data: &msgData,
+ }, blockNr, nil)
+ if err != nil {
+ panic(err)
+ }
+
+ var (
+ ret0 = new([]common.Address)
+ ret1 = new([]*big.Int)
+ )
+
+ out := &[]interface{}{
+ ret0,
+ ret1,
+ }
+
+ if err := c.validatorSet.UnpackIntoInterface(out, method, result); err != nil {
+ return nil, err
+ }
+
+ valz := make([]*valset.Validator, len(*ret0))
+ for i, a := range *ret0 {
+ valz[i] = &valset.Validator{
+ Address: a,
+ VotingPower: (*ret1)[i].Int64(),
+ }
+ }
+
+ return valz, nil
+}
+
+const method = "commitSpan"
+
+func (c *ChainSpanner) CommitSpan(heimdallSpan HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error {
+ // get validators bytes
+ validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators))
+ for _, val := range heimdallSpan.ValidatorSet.Validators {
+ validators = append(validators, val.MinimalVal())
+ }
+
+ validatorBytes, err := rlp.EncodeToBytes(validators)
+ if err != nil {
+ return err
+ }
+
+ // get producers bytes
+ producers := make([]valset.MinimalVal, 0, len(heimdallSpan.SelectedProducers))
+ for _, val := range heimdallSpan.SelectedProducers {
+ producers = append(producers, val.MinimalVal())
+ }
+
+ producerBytes, err := rlp.EncodeToBytes(producers)
+ if err != nil {
+ return err
+ }
+
+ log.Info("✅ Committing new span",
+ "id", heimdallSpan.ID,
+ "startBlock", heimdallSpan.StartBlock,
+ "endBlock", heimdallSpan.EndBlock,
+ "validatorBytes", hex.EncodeToString(validatorBytes),
+ "producerBytes", hex.EncodeToString(producerBytes),
+ )
+
+ data, err := c.validatorSet.Pack(method,
+ big.NewInt(0).SetUint64(heimdallSpan.ID),
+ big.NewInt(0).SetUint64(heimdallSpan.StartBlock),
+ big.NewInt(0).SetUint64(heimdallSpan.EndBlock),
+ validatorBytes,
+ producerBytes,
+ )
+ if err != nil {
+ log.Error("Unable to pack tx for commitSpan", "error", err)
+
+ return err
+ }
+
+ // get system message
+ msg := statefull.GetSystemMessage(c.validatorContractAddress, data)
+
+ // apply message
+ _, err = statefull.ApplyMessage(msg, state, header, c.chainConfig, chainContext)
+
+ return err
+}
diff --git a/consensus/bor/merkle.go b/consensus/bor/merkle.go
index bdfbaba983..ef1b4eb87e 100644
--- a/consensus/bor/merkle.go
+++ b/consensus/bor/merkle.go
@@ -2,12 +2,12 @@ package bor
func appendBytes32(data ...[]byte) []byte {
var result []byte
+
for _, v := range data {
- paddedV, err := convertTo32(v)
- if err == nil {
- result = append(result, paddedV[:]...)
- }
+ paddedV := convertTo32(v)
+ result = append(result, paddedV[:]...)
}
+
return result
}
@@ -24,25 +24,29 @@ func nextPowerOfTwo(n uint64) uint64 {
n |= n >> 16
n |= n >> 32
n++
+
return n
}
-func convertTo32(input []byte) (output [32]byte, err error) {
+func convertTo32(input []byte) (output [32]byte) {
l := len(input)
if l > 32 || l == 0 {
return
}
+
copy(output[32-l:], input[:])
+
return
}
func convert(input []([32]byte)) [][]byte {
- var output [][]byte
+ output := make([][]byte, 0, len(input))
+
for _, in := range input {
newInput := make([]byte, len(in[:]))
copy(newInput, in[:])
output = append(output, newInput)
-
}
+
return output
}
diff --git a/consensus/bor/rest.go b/consensus/bor/rest.go
deleted file mode 100644
index 86f6146e77..0000000000
--- a/consensus/bor/rest.go
+++ /dev/null
@@ -1,196 +0,0 @@
-package bor
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "math/big"
- "net/http"
- "net/url"
- "sort"
- "time"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/log"
-)
-
-var (
- stateFetchLimit = 50
-)
-
-// ResponseWithHeight defines a response object type that wraps an original
-// response with a height.
-type ResponseWithHeight struct {
- Height string `json:"height"`
- Result json.RawMessage `json:"result"`
-}
-
-// Checkpoint defines a response object type of bor checkpoint
-type Checkpoint struct {
- Proposer common.Address `json:"proposer"`
- StartBlock *big.Int `json:"start_block"`
- EndBlock *big.Int `json:"end_block"`
- RootHash common.Hash `json:"root_hash"`
- BorChainID string `json:"bor_chain_id"`
- Timestamp uint64 `json:"timestamp"`
-}
-
-//go:generate mockgen -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks . IHeimdallClient
-type IHeimdallClient interface {
- Fetch(path string, query string) (*ResponseWithHeight, error)
- FetchWithRetry(path string, query string) (*ResponseWithHeight, error)
- FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error)
- FetchLatestCheckpoint() (*Checkpoint, error)
- Close()
-}
-
-type HeimdallClient struct {
- urlString string
- client http.Client
- closeCh chan struct{}
-}
-
-func NewHeimdallClient(urlString string) (*HeimdallClient, error) {
- h := &HeimdallClient{
- urlString: urlString,
- client: http.Client{
- Timeout: time.Duration(5 * time.Second),
- },
- closeCh: make(chan struct{}),
- }
- return h, nil
-}
-
-func (h *HeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error) {
- eventRecords := make([]*EventRecordWithTime, 0)
- for {
- queryParams := fmt.Sprintf("from-id=%d&to-time=%d&limit=%d", fromID, to, stateFetchLimit)
- log.Info("Fetching state sync events", "queryParams", queryParams)
- response, err := h.FetchWithRetry("clerk/event-record/list", queryParams)
- if err != nil {
- return nil, err
- }
- var _eventRecords []*EventRecordWithTime
- if response.Result == nil { // status 204
- break
- }
- if err := json.Unmarshal(response.Result, &_eventRecords); err != nil {
- return nil, err
- }
- eventRecords = append(eventRecords, _eventRecords...)
- if len(_eventRecords) < stateFetchLimit {
- break
- }
- fromID += uint64(stateFetchLimit)
- }
-
- sort.SliceStable(eventRecords, func(i, j int) bool {
- return eventRecords[i].ID < eventRecords[j].ID
- })
- return eventRecords, nil
-}
-
-// FetchLatestCheckpoint fetches the latest bor submitted checkpoint from heimdall
-func (h *HeimdallClient) FetchLatestCheckpoint() (*Checkpoint, error) {
- checkpoint := &Checkpoint{}
-
- response, err := h.Fetch("/checkpoints/latest", "")
- if err != nil {
- return nil, err
- }
- if err = json.Unmarshal(response.Result, checkpoint); err != nil {
- return nil, err
- }
-
- return checkpoint, nil
-}
-
-// Fetch fetches response from heimdall
-func (h *HeimdallClient) Fetch(rawPath string, rawQuery string) (*ResponseWithHeight, error) {
- u, err := url.Parse(h.urlString)
- if err != nil {
- return nil, err
- }
-
- u.Path = rawPath
- u.RawQuery = rawQuery
-
- return h.internalFetch(u)
-}
-
-// FetchWithRetry returns data from heimdall with retry
-func (h *HeimdallClient) FetchWithRetry(rawPath string, rawQuery string) (*ResponseWithHeight, error) {
- u, err := url.Parse(h.urlString)
- if err != nil {
- return nil, err
- }
-
- u.Path = rawPath
- u.RawQuery = rawQuery
-
- // attempt counter
- attempt := 1
-
- // request data once
- res, err := h.internalFetch(u)
- if err == nil && res != nil {
- return res, nil
- }
-
- // create a new ticker for retrying the request
- ticker := time.NewTicker(5 * time.Second)
- defer ticker.Stop()
-
- for {
- log.Info("Retrying again in 5 seconds to fetch data from Heimdall", "path", u.Path, "attempt", attempt)
- attempt++
- select {
- case <-h.closeCh:
- log.Debug("Shutdown detected, terminating request")
- return nil, errShutdownDetected
- case <-ticker.C:
- res, err := h.internalFetch(u)
- if err == nil && res != nil {
- return res, nil
- }
- }
- }
-}
-
-// internal fetch method
-func (h *HeimdallClient) internalFetch(u *url.URL) (*ResponseWithHeight, error) {
- res, err := h.client.Get(u.String())
- if err != nil {
- return nil, err
- }
- defer res.Body.Close()
-
- // check status code
- if res.StatusCode != 200 && res.StatusCode != 204 {
- return nil, fmt.Errorf("Error while fetching data from Heimdall")
- }
-
- // unmarshall data from buffer
- var response ResponseWithHeight
- if res.StatusCode == 204 {
- return &response, nil
- }
-
- // get response
- body, err := ioutil.ReadAll(res.Body)
- if err != nil {
- return nil, err
- }
-
- if err := json.Unmarshal(body, &response); err != nil {
- return nil, err
- }
-
- return &response, nil
-}
-
-// Close sends a signal to stop the running process
-func (h *HeimdallClient) Close() {
- close(h.closeCh)
- h.client.CloseIdleConnections()
-}
diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go
index 8d212f33ef..f71ceae0ad 100644
--- a/consensus/bor/snapshot.go
+++ b/consensus/bor/snapshot.go
@@ -1,37 +1,29 @@
package bor
import (
- "bytes"
"encoding/json"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
+
lru "github.com/hashicorp/golang-lru"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params"
)
// Snapshot is the state of the authorization voting at a given point in time.
type Snapshot struct {
config *params.BorConfig // Consensus engine parameters to fine tune behavior
- ethAPI *ethapi.PublicBlockChainAPI
- sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
+ sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
Number uint64 `json:"number"` // Block number where the snapshot was created
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
- ValidatorSet *ValidatorSet `json:"validatorSet"` // Validator set at this moment
+ ValidatorSet *valset.ValidatorSet `json:"validatorSet"` // Validator set at this moment
Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections
}
-// signersAscending implements the sort interface to allow sorting a list of addresses
-type signersAscending []common.Address
-
-func (s signersAscending) Len() int { return len(s) }
-func (s signersAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 }
-func (s signersAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
// newSnapshot creates a new snapshot with the specified startup parameters. This
// method does not initialize the set of recent signers, so only ever use if for
// the genesis block.
@@ -40,37 +32,38 @@ func newSnapshot(
sigcache *lru.ARCCache,
number uint64,
hash common.Hash,
- validators []*Validator,
- ethAPI *ethapi.PublicBlockChainAPI,
+ validators []*valset.Validator,
) *Snapshot {
snap := &Snapshot{
config: config,
- ethAPI: ethAPI,
sigcache: sigcache,
Number: number,
Hash: hash,
- ValidatorSet: NewValidatorSet(validators),
+ ValidatorSet: valset.NewValidatorSet(validators),
Recents: make(map[uint64]common.Address),
}
+
return snap
}
// loadSnapshot loads an existing snapshot from the database.
-func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash, ethAPI *ethapi.PublicBlockChainAPI) (*Snapshot, error) {
+func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
blob, err := db.Get(append([]byte("bor-"), hash[:]...))
if err != nil {
return nil, err
}
+
snap := new(Snapshot)
+
if err := json.Unmarshal(blob, snap); err != nil {
return nil, err
}
+
snap.config = config
snap.sigcache = sigcache
- snap.ethAPI = ethAPI
// update total voting power
- if err := snap.ValidatorSet.updateTotalVotingPower(); err != nil {
+ if err := snap.ValidatorSet.UpdateTotalVotingPower(); err != nil {
return nil, err
}
@@ -83,6 +76,7 @@ func (s *Snapshot) store(db ethdb.Database) error {
if err != nil {
return err
}
+
return db.Put(append([]byte("bor-"), s.Hash[:]...), blob)
}
@@ -90,7 +84,6 @@ func (s *Snapshot) store(db ethdb.Database) error {
func (s *Snapshot) copy() *Snapshot {
cpy := &Snapshot{
config: s.config,
- ethAPI: s.ethAPI,
sigcache: s.sigcache,
Number: s.Number,
Hash: s.Hash,
@@ -115,6 +108,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
return nil, errOutOfRangeChain
}
}
+
if headers[0].Number.Uint64() != s.Number+1 {
return nil, errOutOfRangeChain
}
@@ -126,7 +120,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
number := header.Number.Uint64()
// Delete the oldest signer from the recent list to allow it signing again
- if number >= s.config.Sprint && number-s.config.Sprint >= 0 {
+ if number >= s.config.Sprint {
delete(snap.Recents, number-s.config.Sprint)
}
@@ -153,15 +147,17 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
if err := validateHeaderExtraField(header.Extra); err != nil {
return nil, err
}
+
validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal]
// get validators from headers and use that for new validator set
- newVals, _ := ParseValidators(validatorBytes)
+ newVals, _ := valset.ParseValidators(validatorBytes)
v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals)
v.IncrementProposerPriority(1)
snap.ValidatorSet = v
}
}
+
snap.Number += uint64(len(headers))
snap.Hash = headers[len(headers)-1].Hash()
@@ -173,10 +169,13 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error)
validators := s.ValidatorSet.Validators
proposer := s.ValidatorSet.GetProposer().Address
proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer)
+
if proposerIndex == -1 {
return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()}
}
+
signerIndex, _ := s.ValidatorSet.GetByAddress(signer)
+
if signerIndex == -1 {
return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()}
}
@@ -187,6 +186,7 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error)
tempIndex = tempIndex + len(validators)
}
}
+
return tempIndex - proposerIndex, nil
}
@@ -196,13 +196,14 @@ func (s *Snapshot) signers() []common.Address {
for _, sig := range s.ValidatorSet.Validators {
sigs = append(sigs, sig.Address)
}
+
return sigs
}
// Difficulty returns the difficulty for a particular signer at the current snapshot number
func (s *Snapshot) Difficulty(signer common.Address) uint64 {
// if signer is empty
- if bytes.Compare(signer.Bytes(), common.Address{}.Bytes()) == 0 {
+ if signer == (common.Address{}) {
return 1
}
diff --git a/consensus/bor/snapshot_test.go b/consensus/bor/snapshot_test.go
index 6bb8547843..1a3e967613 100644
--- a/consensus/bor/snapshot_test.go
+++ b/consensus/bor/snapshot_test.go
@@ -7,8 +7,11 @@ import (
"time"
"github.com/stretchr/testify/assert"
+ "pgregory.net/rapid"
"github.com/ethereum/go-ethereum/common"
+ unique "github.com/ethereum/go-ethereum/common/set"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
)
const (
@@ -16,8 +19,10 @@ const (
)
func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) {
+ t.Parallel()
+
validators := buildRandomValidatorSet(numVals)
- validatorSet := NewValidatorSet(validators)
+ validatorSet := valset.NewValidatorSet(validators)
snap := Snapshot{
ValidatorSet: validatorSet,
}
@@ -28,20 +33,24 @@ func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) {
if err != nil {
t.Fatalf("%s", err)
}
+
assert.Equal(t, 0, successionNumber)
}
func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) {
+ t.Parallel()
+
validators := buildRandomValidatorSet(numVals)
// sort validators by address, which is what NewValidatorSet also does
- sort.Sort(ValidatorsByAddress(validators))
+ sort.Sort(valset.ValidatorsByAddress(validators))
+
proposerIndex := 32
signerIndex := 56
// give highest ProposerPriority to a particular val, so that they become the proposer
validators[proposerIndex].VotingPower = 200
snap := Snapshot{
- ValidatorSet: NewValidatorSet(validators),
+ ValidatorSet: valset.NewValidatorSet(validators),
}
// choose a signer at an index greater than proposer index
@@ -50,17 +59,20 @@ func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) {
if err != nil {
t.Fatalf("%s", err)
}
+
assert.Equal(t, signerIndex-proposerIndex, successionNumber)
}
func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) {
+ t.Parallel()
+
validators := buildRandomValidatorSet(numVals)
proposerIndex := 98
signerIndex := 11
// give highest ProposerPriority to a particular val, so that they become the proposer
validators[proposerIndex].VotingPower = 200
snap := Snapshot{
- ValidatorSet: NewValidatorSet(validators),
+ ValidatorSet: valset.NewValidatorSet(validators),
}
// choose a signer at an index greater than proposer index
@@ -69,29 +81,38 @@ func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) {
if err != nil {
t.Fatalf("%s", err)
}
+
assert.Equal(t, signerIndex+numVals-proposerIndex, successionNumber)
}
func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) {
+ t.Parallel()
+
validators := buildRandomValidatorSet(numVals)
snap := Snapshot{
- ValidatorSet: NewValidatorSet(validators),
+ ValidatorSet: valset.NewValidatorSet(validators),
}
+
dummyProposerAddress := randomAddress()
- snap.ValidatorSet.Proposer = &Validator{Address: dummyProposerAddress}
+ snap.ValidatorSet.Proposer = &valset.Validator{Address: dummyProposerAddress}
+
// choose any signer
signer := snap.ValidatorSet.Validators[3].Address
+
_, err := snap.GetSignerSuccessionNumber(signer)
assert.NotNil(t, err)
+
e, ok := err.(*UnauthorizedProposerError)
assert.True(t, ok)
assert.Equal(t, dummyProposerAddress.Bytes(), e.Proposer)
}
func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
+ t.Parallel()
+
validators := buildRandomValidatorSet(numVals)
snap := Snapshot{
- ValidatorSet: NewValidatorSet(validators),
+ ValidatorSet: valset.NewValidatorSet(validators),
}
dummySignerAddress := randomAddress()
_, err := snap.GetSignerSuccessionNumber(dummySignerAddress)
@@ -101,24 +122,78 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
assert.Equal(t, dummySignerAddress.Bytes(), e.Signer)
}
-func buildRandomValidatorSet(numVals int) []*Validator {
+// nolint: unparam
+func buildRandomValidatorSet(numVals int) []*valset.Validator {
rand.Seed(time.Now().Unix())
- validators := make([]*Validator, numVals)
+
+ validators := make([]*valset.Validator, numVals)
+ valAddrs := randomAddresses(numVals)
+
for i := 0; i < numVals; i++ {
- validators[i] = &Validator{
- Address: randomAddress(),
+ validators[i] = &valset.Validator{
+ Address: valAddrs[i],
// cannot process validators with voting power 0, hence +1
VotingPower: int64(rand.Intn(99) + 1),
}
}
// sort validators by address, which is what NewValidatorSet also does
- sort.Sort(ValidatorsByAddress(validators))
+ sort.Sort(valset.ValidatorsByAddress(validators))
+
return validators
}
func randomAddress() common.Address {
bytes := make([]byte, 32)
rand.Read(bytes)
+
return common.BytesToAddress(bytes)
}
+
+func randomAddresses(n int) []common.Address {
+ if n <= 0 {
+ return []common.Address{}
+ }
+
+ addrs := make([]common.Address, 0, n)
+ addrsSet := make(map[common.Address]struct{}, n)
+
+ var (
+ addr common.Address
+ exist bool
+ )
+
+ bytes := make([]byte, 32)
+
+ for {
+ rand.Read(bytes)
+
+ addr = common.BytesToAddress(bytes)
+
+ _, exist = addrsSet[addr]
+ if !exist {
+ addrs = append(addrs, addr)
+
+ addrsSet[addr] = struct{}{}
+ }
+
+ if len(addrs) == n {
+ return addrs
+ }
+ }
+}
+
+func TestRandomAddresses(t *testing.T) {
+ t.Parallel()
+
+ rapid.Check(t, func(t *rapid.T) {
+ length := rapid.IntMax(100).Draw(t, "length").(int)
+
+ addrs := randomAddresses(length)
+ addressSet := unique.New(addrs)
+
+ if len(addrs) != len(addressSet) {
+ t.Fatalf("length of unique addresses %d, expected %d", len(addressSet), len(addrs))
+ }
+ })
+}
diff --git a/consensus/bor/span.go b/consensus/bor/span.go
index 2fd0cf1079..4867635b8e 100644
--- a/consensus/bor/span.go
+++ b/consensus/bor/span.go
@@ -1,16 +1,17 @@
package bor
-// Span represents a current bor span
-type Span struct {
- ID uint64 `json:"span_id" yaml:"span_id"`
- StartBlock uint64 `json:"start_block" yaml:"start_block"`
- EndBlock uint64 `json:"end_block" yaml:"end_block"`
-}
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+)
-// HeimdallSpan represents span from heimdall APIs
-type HeimdallSpan struct {
- Span
- ValidatorSet ValidatorSet `json:"validator_set" yaml:"validator_set"`
- SelectedProducers []Validator `json:"selected_producers" yaml:"selected_producers"`
- ChainID string `json:"bor_chain_id" yaml:"bor_chain_id"`
+//go:generate mockgen -destination=./span_mock.go -package=bor . Spanner
+type Spanner interface {
+ GetCurrentSpan(headerHash common.Hash) (*span.Span, error)
+ GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error)
+ CommitSpan(heimdallSpan span.HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error
}
diff --git a/consensus/bor/span_mock.go b/consensus/bor/span_mock.go
new file mode 100644
index 0000000000..12ed945234
--- /dev/null
+++ b/consensus/bor/span_mock.go
@@ -0,0 +1,84 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: Spanner)
+
+// Package bor is a generated GoMock package.
+package bor
+
+import (
+ reflect "reflect"
+
+ common "github.com/ethereum/go-ethereum/common"
+ span "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
+ valset "github.com/ethereum/go-ethereum/consensus/bor/valset"
+ core "github.com/ethereum/go-ethereum/core"
+ state "github.com/ethereum/go-ethereum/core/state"
+ types "github.com/ethereum/go-ethereum/core/types"
+ gomock "github.com/golang/mock/gomock"
+)
+
+// MockSpanner is a mock of Spanner interface.
+type MockSpanner struct {
+ ctrl *gomock.Controller
+ recorder *MockSpannerMockRecorder
+}
+
+// MockSpannerMockRecorder is the mock recorder for MockSpanner.
+type MockSpannerMockRecorder struct {
+ mock *MockSpanner
+}
+
+// NewMockSpanner creates a new mock instance.
+func NewMockSpanner(ctrl *gomock.Controller) *MockSpanner {
+ mock := &MockSpanner{ctrl: ctrl}
+ mock.recorder = &MockSpannerMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder {
+ return m.recorder
+}
+
+// CommitSpan mocks base method.
+func (m *MockSpanner) CommitSpan(arg0 span.HeimdallSpan, arg1 *state.StateDB, arg2 *types.Header, arg3 core.ChainContext) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// CommitSpan indicates an expected call of CommitSpan.
+func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3)
+}
+
+// GetCurrentSpan mocks base method.
+func (m *MockSpanner) GetCurrentSpan(arg0 common.Hash) (*span.Span, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetCurrentSpan", arg0)
+ ret0, _ := ret[0].(*span.Span)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetCurrentSpan indicates an expected call of GetCurrentSpan.
+func (mr *MockSpannerMockRecorder) GetCurrentSpan(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), arg0)
+}
+
+// GetCurrentValidators mocks base method.
+func (m *MockSpanner) GetCurrentValidators(arg0 common.Hash, arg1 uint64) ([]*valset.Validator, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1)
+ ret0, _ := ret[0].([]*valset.Validator)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetCurrentValidators indicates an expected call of GetCurrentValidators.
+func (mr *MockSpannerMockRecorder) GetCurrentValidators(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidators", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidators), arg0, arg1)
+}
diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go
new file mode 100644
index 0000000000..e30fb4fd21
--- /dev/null
+++ b/consensus/bor/statefull/processor.go
@@ -0,0 +1,93 @@
+package statefull
+
+import (
+ "math"
+ "math/big"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
+
+type ChainContext struct {
+ Chain consensus.ChainHeaderReader
+ Bor consensus.Engine
+}
+
+func (c ChainContext) Engine() consensus.Engine {
+ return c.Bor
+}
+
+func (c ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
+ return c.Chain.GetHeader(hash, number)
+}
+
+// callmsg implements core.Message to allow passing it as a transaction simulator.
+type callmsg struct {
+ ethereum.CallMsg
+}
+
+func (m callmsg) From() common.Address { return m.CallMsg.From }
+func (m callmsg) Nonce() uint64 { return 0 }
+func (m callmsg) CheckNonce() bool { return false }
+func (m callmsg) To() *common.Address { return m.CallMsg.To }
+func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
+func (m callmsg) Gas() uint64 { return m.CallMsg.Gas }
+func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
+func (m callmsg) Data() []byte { return m.CallMsg.Data }
+
+// get system message
+func GetSystemMessage(toAddress common.Address, data []byte) callmsg {
+ return callmsg{
+ ethereum.CallMsg{
+ From: systemAddress,
+ Gas: math.MaxUint64 / 2,
+ GasPrice: big.NewInt(0),
+ Value: big.NewInt(0),
+ To: &toAddress,
+ Data: data,
+ },
+ }
+}
+
+// apply message
+func ApplyMessage(
+ msg callmsg,
+ state *state.StateDB,
+ header *types.Header,
+ chainConfig *params.ChainConfig,
+ chainContext core.ChainContext,
+) (uint64, error) {
+ initialGas := msg.Gas()
+
+ // Create a new context to be used in the EVM environment
+ blockContext := core.NewEVMBlockContext(header, chainContext, &header.Coinbase)
+
+ // Create a new environment which holds all relevant information
+ // about the transaction and calling mechanisms.
+ vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{})
+
+ // Apply the transaction to the current state (included in the env)
+ _, gasLeft, err := vmenv.Call(
+ vm.AccountRef(msg.From()),
+ *msg.To(),
+ msg.Data(),
+ msg.Gas(),
+ msg.Value(),
+ )
+ // Update the state with pending changes
+ if err != nil {
+ state.Finalise(true)
+ }
+
+ gasUsed := initialGas - gasLeft
+
+ return gasUsed, nil
+}
diff --git a/consensus/bor/validators_getter.go b/consensus/bor/validators_getter.go
new file mode 100644
index 0000000000..90d1fccf6e
--- /dev/null
+++ b/consensus/bor/validators_getter.go
@@ -0,0 +1,11 @@
+package bor
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
+)
+
+//go:generate mockgen -destination=./validators_getter_mock.go -package=bor . ValidatorsGetter
+type ValidatorsGetter interface {
+ GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error)
+}
diff --git a/consensus/bor/validators_getter_mock.go b/consensus/bor/validators_getter_mock.go
new file mode 100644
index 0000000000..ad99489d8e
--- /dev/null
+++ b/consensus/bor/validators_getter_mock.go
@@ -0,0 +1,51 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: ValidatorsGetter)
+
+// Package bor is a generated GoMock package.
+package bor
+
+import (
+ reflect "reflect"
+
+ common "github.com/ethereum/go-ethereum/common"
+ valset "github.com/ethereum/go-ethereum/consensus/bor/valset"
+ gomock "github.com/golang/mock/gomock"
+)
+
+// MockValidatorsGetter is a mock of ValidatorsGetter interface.
+type MockValidatorsGetter struct {
+ ctrl *gomock.Controller
+ recorder *MockValidatorsGetterMockRecorder
+}
+
+// MockValidatorsGetterMockRecorder is the mock recorder for MockValidatorsGetter.
+type MockValidatorsGetterMockRecorder struct {
+ mock *MockValidatorsGetter
+}
+
+// NewMockValidatorsGetter creates a new mock instance.
+func NewMockValidatorsGetter(ctrl *gomock.Controller) *MockValidatorsGetter {
+ mock := &MockValidatorsGetter{ctrl: ctrl}
+ mock.recorder = &MockValidatorsGetterMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockValidatorsGetter) EXPECT() *MockValidatorsGetterMockRecorder {
+ return m.recorder
+}
+
+// GetCurrentValidators mocks base method.
+func (m *MockValidatorsGetter) GetCurrentValidators(arg0 common.Hash, arg1 uint64) ([]*valset.Validator, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1)
+ ret0, _ := ret[0].([]*valset.Validator)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetCurrentValidators indicates an expected call of GetCurrentValidators.
+func (mr *MockValidatorsGetterMockRecorder) GetCurrentValidators(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidators", reflect.TypeOf((*MockValidatorsGetter)(nil).GetCurrentValidators), arg0, arg1)
+}
diff --git a/consensus/bor/valset/error.go b/consensus/bor/valset/error.go
new file mode 100644
index 0000000000..37add21683
--- /dev/null
+++ b/consensus/bor/valset/error.go
@@ -0,0 +1,32 @@
+package valset
+
+import "fmt"
+
+// TotalVotingPowerExceededError is returned when the maximum allowed total voting power is exceeded
+type TotalVotingPowerExceededError struct {
+ Sum int64
+ Validators []*Validator
+}
+
+func (e *TotalVotingPowerExceededError) Error() string {
+ return fmt.Sprintf(
+ "Total voting power should be guarded to not exceed %v; got: %v; for validator set: %v",
+ MaxTotalVotingPower,
+ e.Sum,
+ e.Validators,
+ )
+}
+
+type InvalidStartEndBlockError struct {
+ Start uint64
+ End uint64
+ CurrentHeader uint64
+}
+
+func (e *InvalidStartEndBlockError) Error() string {
+ return fmt.Sprintf(
+ "Invalid parameters start: %d and end block: %d params",
+ e.Start,
+ e.End,
+ )
+}
diff --git a/consensus/bor/validator.go b/consensus/bor/valset/validator.go
similarity index 99%
rename from consensus/bor/validator.go
rename to consensus/bor/valset/validator.go
index 00e9fdc645..250206c1f3 100644
--- a/consensus/bor/validator.go
+++ b/consensus/bor/valset/validator.go
@@ -1,8 +1,7 @@
-package bor
+package valset
import (
"bytes"
- // "encoding/json"
"errors"
"fmt"
"math/big"
@@ -43,9 +42,12 @@ func (v *Validator) Cmp(other *Validator) *Validator {
if v == nil {
return other
}
+
if other == nil {
return v
}
+
+ // nolint:nestif
if v.ProposerPriority > other.ProposerPriority {
return v
} else if v.ProposerPriority < other.ProposerPriority {
@@ -66,6 +68,7 @@ func (v *Validator) String() string {
if v == nil {
return "nil-Validator"
}
+
return fmt.Sprintf("Validator{%v Power:%v Priority:%v}",
v.Address.Hex(),
v.VotingPower,
@@ -87,6 +90,7 @@ func (v *Validator) HeaderBytes() []byte {
result := make([]byte, 40)
copy(result[:20], v.Address.Bytes())
copy(result[20:], v.PowerBytes())
+
return result
}
@@ -95,6 +99,7 @@ func (v *Validator) PowerBytes() []byte {
powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes()
result := make([]byte, 20)
copy(result[20-len(powerBytes):], powerBytes)
+
return result
}
@@ -114,6 +119,7 @@ func ParseValidators(validatorsBytes []byte) ([]*Validator, error) {
}
result := make([]*Validator, len(validatorsBytes)/40)
+
for i := 0; i < len(validatorsBytes); i += 40 {
address := make([]byte, 20)
power := make([]byte, 20)
@@ -142,6 +148,7 @@ func SortMinimalValByAddress(a []MinimalVal) []MinimalVal {
sort.Slice(a, func(i, j int) bool {
return bytes.Compare(a[i].Signer.Bytes(), a[j].Signer.Bytes()) < 0
})
+
return a
}
@@ -150,5 +157,6 @@ func ValidatorsToMinimalValidators(vals []Validator) (minVals []MinimalVal) {
for _, val := range vals {
minVals = append(minVals, val.MinimalVal())
}
+
return
}
diff --git a/consensus/bor/validator_set.go b/consensus/bor/valset/validator_set.go
similarity index 97%
rename from consensus/bor/validator_set.go
rename to consensus/bor/valset/validator_set.go
index 0b5c10ebd0..19e6c681fe 100644
--- a/consensus/bor/validator_set.go
+++ b/consensus/bor/valset/validator_set.go
@@ -1,4 +1,4 @@
-package bor
+package valset
// Tendermint leader selection algorithm
@@ -55,13 +55,16 @@ type ValidatorSet struct {
// function panics.
func NewValidatorSet(valz []*Validator) *ValidatorSet {
vals := &ValidatorSet{}
+
err := vals.updateWithChangeSet(valz, false)
if err != nil {
panic(fmt.Sprintf("cannot create validator set: %s", err))
}
+
if len(valz) > 0 {
vals.IncrementProposerPriority(1)
}
+
return vals
}
@@ -72,9 +75,10 @@ func (vals *ValidatorSet) IsNilOrEmpty() bool {
// Increment ProposerPriority and update the proposer on a copy, and return it.
func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet {
- copy := vals.Copy()
- copy.IncrementProposerPriority(times)
- return copy
+ validatorCopy := vals.Copy()
+ validatorCopy.IncrementProposerPriority(times)
+
+ return validatorCopy
}
// IncrementProposerPriority increments ProposerPriority of each validator and updates the
@@ -84,6 +88,7 @@ func (vals *ValidatorSet) IncrementProposerPriority(times int) {
if vals.IsNilOrEmpty() {
panic("empty validator set")
}
+
if times <= 0 {
panic("Cannot call IncrementProposerPriority with non-positive times")
}
@@ -120,6 +125,7 @@ func (vals *ValidatorSet) RescalePriorities(diffMax int64) {
// NOTE: This may make debugging priority issues easier as well.
diff := computeMaxMinPriorityDiff(vals)
ratio := (diff + diffMax - 1) / diffMax
+
if diff > diffMax {
for _, val := range vals.Validators {
val.ProposerPriority = val.ProposerPriority / ratio
@@ -145,10 +151,13 @@ func (vals *ValidatorSet) incrementProposerPriority() *Validator {
func (vals *ValidatorSet) computeAvgProposerPriority() int64 {
n := int64(len(vals.Validators))
sum := big.NewInt(0)
+
for _, val := range vals.Validators {
sum.Add(sum, big.NewInt(val.ProposerPriority))
}
+
avg := sum.Div(sum, big.NewInt(n))
+
if avg.IsInt64() {
return avg.Int64()
}
@@ -162,17 +171,22 @@ func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 {
if vals.IsNilOrEmpty() {
panic("empty validator set")
}
+
max := int64(math.MinInt64)
min := int64(math.MaxInt64)
+
for _, v := range vals.Validators {
if v.ProposerPriority < min {
min = v.ProposerPriority
}
+
if v.ProposerPriority > max {
max = v.ProposerPriority
}
}
+
diff := max - min
+
if diff < 0 {
return -1 * diff
} else {
@@ -185,6 +199,7 @@ func (vals *ValidatorSet) getValWithMostPriority() *Validator {
for _, val := range vals.Validators {
res = res.Cmp(val)
}
+
return res
}
@@ -192,7 +207,9 @@ func (vals *ValidatorSet) shiftByAvgProposerPriority() {
if vals.IsNilOrEmpty() {
panic("empty validator set")
}
+
avgProposerPriority := vals.computeAvgProposerPriority()
+
for _, val := range vals.Validators {
val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority)
}
@@ -203,10 +220,13 @@ func validatorListCopy(valsList []*Validator) []*Validator {
if valsList == nil {
return nil
}
+
valsCopy := make([]*Validator, len(valsList))
+
for i, val := range valsList {
valsCopy[i] = val.Copy()
}
+
return valsCopy
}
@@ -225,6 +245,7 @@ func (vals *ValidatorSet) HasAddress(address []byte) bool {
idx := sort.Search(len(vals.Validators), func(i int) bool {
return bytes.Compare(address, vals.Validators[i].Address.Bytes()) <= 0
})
+
return idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address)
}
@@ -234,9 +255,10 @@ func (vals *ValidatorSet) GetByAddress(address common.Address) (index int, val *
idx := sort.Search(len(vals.Validators), func(i int) bool {
return bytes.Compare(address.Bytes(), vals.Validators[i].Address.Bytes()) <= 0
})
- if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) {
+ if idx < len(vals.Validators) && vals.Validators[idx].Address == address {
return idx, vals.Validators[idx].Copy()
}
+
return -1, nil
}
@@ -247,7 +269,9 @@ func (vals *ValidatorSet) GetByIndex(index int) (address []byte, val *Validator)
if index < 0 || index >= len(vals.Validators) {
return nil, nil
}
+
val = vals.Validators[index]
+
return val.Address.Bytes(), val.Copy()
}
@@ -257,8 +281,7 @@ func (vals *ValidatorSet) Size() int {
}
// Force recalculation of the set's total voting power.
-func (vals *ValidatorSet) updateTotalVotingPower() error {
-
+func (vals *ValidatorSet) UpdateTotalVotingPower() error {
sum := int64(0)
for _, val := range vals.Validators {
// mind overflow
@@ -267,7 +290,9 @@ func (vals *ValidatorSet) updateTotalVotingPower() error {
return &TotalVotingPowerExceededError{sum, vals.Validators}
}
}
+
vals.totalVotingPower = sum
+
return nil
}
@@ -276,11 +301,13 @@ func (vals *ValidatorSet) updateTotalVotingPower() error {
func (vals *ValidatorSet) TotalVotingPower() int64 {
if vals.totalVotingPower == 0 {
log.Info("invoking updateTotalVotingPower before returning it")
- if err := vals.updateTotalVotingPower(); err != nil {
+
+ if err := vals.UpdateTotalVotingPower(); err != nil {
// Can/should we do better?
panic(err)
}
}
+
return vals.totalVotingPower
}
@@ -290,9 +317,11 @@ func (vals *ValidatorSet) GetProposer() (proposer *Validator) {
if len(vals.Validators) == 0 {
return nil
}
+
if vals.Proposer == nil {
vals.Proposer = vals.findProposer()
}
+
return vals.Proposer.Copy()
}
@@ -303,6 +332,7 @@ func (vals *ValidatorSet) findProposer() *Validator {
proposer = proposer.Cmp(val)
}
}
+
return proposer
}
@@ -343,6 +373,7 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e
removals = make([]*Validator, 0, len(changes))
updates = make([]*Validator, 0, len(changes))
+
var prevAddr common.Address
// Scan changes by address and append valid validators to updates or removals lists.
@@ -351,22 +382,27 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e
err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes)
return nil, nil, err
}
+
if valUpdate.VotingPower < 0 {
err = fmt.Errorf("voting power can't be negative: %v", valUpdate)
return nil, nil, err
}
+
if valUpdate.VotingPower > MaxTotalVotingPower {
err = fmt.Errorf("to prevent clipping/ overflow, voting power can't be higher than %v: %v ",
MaxTotalVotingPower, valUpdate)
return nil, nil, err
}
+
if valUpdate.VotingPower == 0 {
removals = append(removals, valUpdate)
} else {
updates = append(updates, valUpdate)
}
+
prevAddr = valUpdate.Address
}
+
return updates, removals, err
}
@@ -382,12 +418,12 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e
// by processChanges for duplicates and invalid values.
// No changes are made to the validator set 'vals'.
func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVotingPower int64, numNewValidators int, err error) {
-
updatedTotalVotingPower = vals.TotalVotingPower()
for _, valUpdate := range updates {
address := valUpdate.Address
_, val := vals.GetByAddress(address)
+
if val == nil {
// New validator, add its voting power the the total.
updatedTotalVotingPower += valUpdate.VotingPower
@@ -396,11 +432,14 @@ func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVoting
// Updated validator, add the difference in power to the total.
updatedTotalVotingPower += valUpdate.VotingPower - val.VotingPower
}
+
overflow := updatedTotalVotingPower > MaxTotalVotingPower
+
if overflow {
err = fmt.Errorf(
"failed to add/update validator %v, total voting power would exceed the max allowed %v",
valUpdate, MaxTotalVotingPower)
+
return 0, 0, err
}
}
@@ -414,10 +453,10 @@ func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVoting
// 'updates' parameter must be a list of unique validators to be added or updated.
// No changes are made to the validator set 'vals'.
func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) {
-
for _, valUpdate := range updates {
address := valUpdate.Address
_, val := vals.GetByAddress(address)
+
if val == nil {
// add val
// Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't
@@ -432,7 +471,6 @@ func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotal
valUpdate.ProposerPriority = val.ProposerPriority
}
}
-
}
// Merges the vals' validator list with the updates list.
@@ -440,7 +478,6 @@ func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotal
// Expects updates to be a list of updates sorted by address with no duplicates or errors,
// must have been validated with verifyUpdates() and priorities computed with computeNewPriorities().
func (vals *ValidatorSet) applyUpdates(updates []*Validator) {
-
existing := vals.Validators
merged := make([]*Validator, len(existing)+len(updates))
i := 0
@@ -478,24 +515,25 @@ func (vals *ValidatorSet) applyUpdates(updates []*Validator) {
// Checks that the validators to be removed are part of the validator set.
// No changes are made to the validator set 'vals'.
func verifyRemovals(deletes []*Validator, vals *ValidatorSet) error {
-
for _, valUpdate := range deletes {
address := valUpdate.Address
_, val := vals.GetByAddress(address)
+
if val == nil {
return fmt.Errorf("failed to find validator %X to remove", address)
}
}
+
if len(deletes) > len(vals.Validators) {
panic("more deletes than validators")
}
+
return nil
}
// Removes the validators specified in 'deletes' from validator set 'vals'.
// Should not fail as verification has been done before.
func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
-
existing := vals.Validators
merged := make([]*Validator, len(existing)-len(deletes))
@@ -509,6 +547,7 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
merged[i] = existing[0]
i++
}
+
existing = existing[1:]
}
@@ -526,7 +565,6 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
// are not allowed and will trigger an error if present in 'changes'.
// The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet().
func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error {
-
if len(changes) <= 0 {
return nil
}
@@ -564,7 +602,7 @@ func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes
vals.applyUpdates(updates)
vals.applyRemovals(deletes)
- if err := vals.updateTotalVotingPower(); err != nil {
+ if err := vals.UpdateTotalVotingPower(); err != nil {
return err
}
@@ -596,19 +634,19 @@ func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error {
func IsErrTooMuchChange(err error) bool {
switch err.(type) {
- case errTooMuchChange:
+ case tooMuchChangeError:
return true
default:
return false
}
}
-type errTooMuchChange struct {
+type tooMuchChangeError struct {
got int64
needed int64
}
-func (e errTooMuchChange) Error() string {
+func (e tooMuchChangeError) Error() string {
return fmt.Sprintf("Invalid commit -- insufficient old voting power: got %v, needed %v", e.got, e.needed)
}
@@ -622,11 +660,14 @@ func (vals *ValidatorSet) StringIndented(indent string) string {
if vals == nil {
return "nil-ValidatorSet"
}
+
var valStrings []string
+
vals.Iterate(func(index int, val *Validator) bool {
valStrings = append(valStrings, val.String())
return false
})
+
return fmt.Sprintf(`ValidatorSet{
%s Proposer: %v
%s Validators:
@@ -636,7 +677,6 @@ func (vals *ValidatorSet) StringIndented(indent string) string {
indent,
indent, strings.Join(valStrings, "\n"+indent+" "),
indent)
-
}
//-------------------------------------
@@ -668,6 +708,7 @@ func safeAdd(a, b int64) (int64, bool) {
} else if b < 0 && a < math.MinInt64-b {
return -1, true
}
+
return a + b, false
}
@@ -677,6 +718,7 @@ func safeSub(a, b int64) (int64, bool) {
} else if b < 0 && a > math.MaxInt64+b {
return -1, true
}
+
return a - b, false
}
@@ -686,8 +728,10 @@ func safeAddClip(a, b int64) int64 {
if b < 0 {
return math.MinInt64
}
+
return math.MaxInt64
}
+
return c
}
@@ -697,7 +741,9 @@ func safeSubClip(a, b int64) int64 {
if b > 0 {
return math.MinInt64
}
+
return math.MaxInt64
}
+
return c
}
diff --git a/consensus/ethash/sealer_test.go b/consensus/ethash/sealer_test.go
index c34e76aec2..a9e96af866 100644
--- a/consensus/ethash/sealer_test.go
+++ b/consensus/ethash/sealer_test.go
@@ -70,7 +70,7 @@ func TestRemoteNotify(t *testing.T) {
if want := common.BytesToHash(target.Bytes()).Hex(); work[2] != want {
t.Errorf("work packet target mismatch: have %s, want %s", work[2], want)
}
- case <-time.After(3 * time.Second):
+ case <-time.After(5 * time.Second):
t.Fatalf("notification timed out")
}
}
diff --git a/consensus/merger.go b/consensus/merger.go
index ffbcbf2b85..c435ecf91e 100644
--- a/consensus/merger.go
+++ b/consensus/merger.go
@@ -45,12 +45,14 @@ type Merger struct {
// NewMerger creates a new Merger which stores its transition status in the provided db.
func NewMerger(db ethdb.KeyValueStore) *Merger {
var status transitionStatus
+
blob := rawdb.ReadTransitionStatus(db)
if len(blob) != 0 {
if err := rlp.DecodeBytes(blob, &status); err != nil {
log.Crit("Failed to decode the transition status", "err", err)
}
}
+
return &Merger{
db: db,
status: status,
diff --git a/core/bench_test.go b/core/bench_test.go
index 959979763d..ad6179d0a8 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -305,7 +305,8 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
}
makeChainForBench(db, full, count)
db.Close()
- cacheConfig := *defaultCacheConfig
+
+ cacheConfig := *DefaultCacheConfig
cacheConfig.TrieDirtyDisabled = true
b.ReportAllocs()
diff --git a/core/blockchain.go b/core/blockchain.go
index 1b11c781c5..8a4c581f66 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -27,6 +27,8 @@ import (
"sync/atomic"
"time"
+ lru "github.com/hashicorp/golang-lru"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/common/prque"
@@ -43,7 +45,6 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
- lru "github.com/hashicorp/golang-lru"
)
var (
@@ -133,9 +134,9 @@ type CacheConfig struct {
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
}
-// defaultCacheConfig are the default caching values if none are specified by the
+// DefaultCacheConfig are the default caching values if none are specified by the
// user (also used during testing).
-var defaultCacheConfig = &CacheConfig{
+var DefaultCacheConfig = &CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
@@ -222,7 +223,7 @@ type BlockChain struct {
// and Processor.
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) {
if cacheConfig == nil {
- cacheConfig = defaultCacheConfig
+ cacheConfig = DefaultCacheConfig
}
bodyCache, _ := lru.New(bodyCacheLimit)
bodyRLPCache, _ := lru.New(bodyCacheLimit)
diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go
index b93444b8cd..f61f930496 100644
--- a/core/blockchain_reader.go
+++ b/core/blockchain_reader.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
@@ -397,10 +398,25 @@ func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscr
return bc.scope.Track(bc.blockProcFeed.Subscribe(ch))
}
+// Snaps retrieves the snapshot tree.
+func (bc *BlockChain) Snaps() *snapshot.Tree {
+ return bc.snaps
+}
+
+// DB retrieves the blockchain database.
+func (bc *BlockChain) DB() ethdb.Database {
+ return bc.db
+}
+
//
// Bor related changes
//
+type BorStateSyncer interface {
+ SetStateSync(stateData []*types.StateSyncData)
+ SubscribeStateSyncEvent(ch chan<- StateSyncEvent) event.Subscription
+}
+
// SetStateSync set sync data in state_data
func (bc *BlockChain) SetStateSync(stateData []*types.StateSyncData) {
bc.stateSyncData = stateData
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 37a1a42d0c..de97000918 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -920,7 +920,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
archiveDb, delfn := makeDb()
defer delfn()
- archiveCaching := *defaultCacheConfig
+ archiveCaching := *DefaultCacheConfig
archiveCaching.TrieDirtyDisabled = true
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
diff --git a/core/chain_makers.go b/core/chain_makers.go
index c7bf60a4b0..4b2d2082df 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
)
@@ -334,7 +335,10 @@ func makeBlockChain(parent *types.Block, n int, engine consensus.Engine, db ethd
}
type fakeChainReader struct {
- config *params.ChainConfig
+ config *params.ChainConfig
+ stateSyncData []*types.StateSyncData
+ stateSyncFeed event.Feed
+ scope event.SubscriptionScope
}
// Config returns the chain configuration.
@@ -348,3 +352,13 @@ func (cr *fakeChainReader) GetHeaderByHash(hash common.Hash) *types.Header
func (cr *fakeChainReader) GetHeader(hash common.Hash, number uint64) *types.Header { return nil }
func (cr *fakeChainReader) GetBlock(hash common.Hash, number uint64) *types.Block { return nil }
func (cr *fakeChainReader) GetTd(hash common.Hash, number uint64) *big.Int { return nil }
+
+// SetStateSync set sync data in state_data
+func (cr *fakeChainReader) SetStateSync(stateData []*types.StateSyncData) {
+ cr.stateSyncData = stateData
+}
+
+// SubscribeStateSyncEvent registers a subscription of StateSyncEvent.
+func (cr *fakeChainReader) SubscribeStateSyncEvent(ch chan<- StateSyncEvent) event.Subscription {
+ return cr.scope.Track(cr.stateSyncFeed.Subscribe(ch))
+}
diff --git a/core/state_processor_test.go b/core/state_processor_test.go
index 7d6939e1dc..158e8c1eeb 100644
--- a/core/state_processor_test.go
+++ b/core/state_processor_test.go
@@ -21,6 +21,8 @@ import (
"math/big"
"testing"
+ "golang.org/x/crypto/sha3"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
@@ -32,7 +34,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
- "golang.org/x/crypto/sha3"
)
// TestStateProcessorErrors tests the output from the 'core' errors
@@ -308,7 +309,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
header := &types.Header{
ParentHash: parent.Hash(),
Coinbase: parent.Coinbase(),
- Difficulty: engine.CalcDifficulty(&fakeChainReader{config}, parent.Time()+10, &types.Header{
+ Difficulty: engine.CalcDifficulty(&fakeChainReader{config: config}, parent.Time()+10, &types.Header{
Number: parent.Number(),
Time: parent.Time(),
Difficulty: parent.Difficulty(),
diff --git a/core/blockchain_repair_test.go b/core/tests/blockchain_repair_test.go
similarity index 93%
rename from core/blockchain_repair_test.go
rename to core/tests/blockchain_repair_test.go
index 9133671796..b52bf76fd9 100644
--- a/core/blockchain_repair_test.go
+++ b/core/tests/blockchain_repair_test.go
@@ -18,7 +18,7 @@
// the database in some strange state with gaps in the chain, nor with block data
// dangling in the future.
-package core
+package tests
import (
"io/ioutil"
@@ -27,12 +27,22 @@ import (
"testing"
"time"
+ "github.com/golang/mock/gomock"
+
+ "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/bor"
+ "github.com/ethereum/go-ethereum/consensus/bor/api"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
"github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/tests/bor/mocks"
)
// Tests a recovery for a short canonical chain where a recent block was already
@@ -1750,7 +1760,17 @@ func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
}, snapshots)
}
+var (
+ testKey1, _ = crypto.GenerateKey()
+ testAddress1 = crypto.PubkeyToAddress(testKey1.PublicKey)
+
+ testKey2, _ = crypto.GenerateKey()
+ testAddress2 = crypto.PubkeyToAddress(testKey2.PublicKey) //nolint:unused,varcheck
+)
+
func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
+ t.Skip("need to add a proper signer for Bor consensus")
+
// It's hard to follow the test case, visualize the input
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
// fmt.Println(tt.dump(true))
@@ -1768,47 +1788,104 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
}
defer db.Close() // Might double close, should be fine
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ ethAPIMock := api.NewMockCaller(ctrl)
+ ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+
+ spanner := bor.NewMockSpanner(ctrl)
+ spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{
+ {
+ ID: 0,
+ Address: common.Address{0x1},
+ VotingPower: 100,
+ ProposerPriority: 0,
+ },
+ }, nil).AnyTimes()
+
+ heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl)
+ heimdallClientMock.EXPECT().Close().Times(1)
+
+ contractMock := bor.NewMockGenesisContract(ctrl)
+
// Initialize a fresh chain
var (
- genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
- engine = ethash.NewFullFaker()
- config = &CacheConfig{
+ gspec = &core.Genesis{
+ Config: params.BorUnittestChainConfig,
+ BaseFee: big.NewInt(params.InitialBaseFee),
+ }
+ config = &core.CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, // Disable snapshot by default
}
)
+
+ engine := miner.NewFakeBor(t, db, params.BorUnittestChainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock)
defer engine.Close()
+
+ engineBorInternal, ok := engine.(*bor.Bor)
+ if ok {
+ gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength)
+ copy(gspec.ExtraData[32:32+common.AddressLength], testAddress1.Bytes())
+
+ engineBorInternal.Authorize(testAddress1, func(account accounts.Account, s string, data []byte) ([]byte, error) {
+ return crypto.Sign(crypto.Keccak256(data), testKey1)
+ })
+ }
+
+ genesis := gspec.MustCommit(db)
+
if snapshots {
config.SnapshotLimit = 256
config.SnapshotWait = true
}
- chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
+
+ chain, err := core.NewBlockChain(db, config, params.BorUnittestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
+
// If sidechain blocks are needed, make a light chain and import it
var sideblocks types.Blocks
if tt.sidechainBlocks > 0 {
- sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) {
- b.SetCoinbase(common.Address{0x01})
+ sideblocks, _ = core.GenerateChain(params.BorUnittestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *core.BlockGen) {
+ b.SetCoinbase(testAddress1)
+
+ if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.Sprint) {
+ b.SetExtra(gspec.ExtraData)
+ } else {
+ b.SetExtra(make([]byte, 32+crypto.SignatureLength))
+ }
})
if _, err := chain.InsertChain(sideblocks); err != nil {
t.Fatalf("Failed to import side chain: %v", err)
}
}
- canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) {
+
+ canonblocks, _ := core.GenerateChain(params.BorUnittestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0x02})
b.SetDifficulty(big.NewInt(1000000))
+
+ if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.Sprint) {
+ b.SetExtra(gspec.ExtraData)
+ } else {
+ b.SetExtra(make([]byte, 32+crypto.SignatureLength))
+ }
})
if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
if tt.commitBlock > 0 {
- chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil)
+ err = chain.StateCache().TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil)
+ if err != nil {
+ t.Fatal("on trieDB.Commit", err)
+ }
+
if snapshots {
- if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
+ if err := chain.Snaps().Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err)
}
}
@@ -1837,7 +1914,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
}
defer db.Close()
- newChain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
+ newChain, err := core.NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -1888,19 +1965,21 @@ func TestIssue23496(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create temporary datadir: %v", err)
}
+
os.RemoveAll(datadir)
db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
}
+
defer db.Close() // Might double close, should be fine
// Initialize a fresh chain
var (
- genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
+ genesis = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
engine = ethash.NewFullFaker()
- config = &CacheConfig{
+ config = &core.CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
@@ -1908,11 +1987,13 @@ func TestIssue23496(t *testing.T) {
SnapshotWait: true,
}
)
- chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
+
+ chain, err := core.NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
- blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), 4, func(i int, b *BlockGen) {
+
+ blocks, _ := core.GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), 4, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0x02})
b.SetDifficulty(big.NewInt(1000000))
})
@@ -1921,13 +2002,18 @@ func TestIssue23496(t *testing.T) {
if _, err := chain.InsertChain(blocks[:1]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
- chain.stateCache.TrieDB().Commit(blocks[0].Root(), true, nil)
+
+ err = chain.StateCache().TrieDB().Commit(blocks[0].Root(), true, nil)
+ if err != nil {
+ t.Fatal("on trieDB.Commit", err)
+ }
// Insert block B2 and commit the snapshot into disk
if _, err := chain.InsertChain(blocks[1:2]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
- if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil {
+
+ if err := chain.Snaps().Cap(blocks[1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err)
}
@@ -1935,7 +2021,11 @@ func TestIssue23496(t *testing.T) {
if _, err := chain.InsertChain(blocks[2:3]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
- chain.stateCache.TrieDB().Commit(blocks[2].Root(), true, nil)
+
+ err = chain.StateCache().TrieDB().Commit(blocks[2].Root(), true, nil)
+ if err != nil {
+ t.Fatal("on trieDB.Commit", err)
+ }
// Insert the remaining blocks
if _, err := chain.InsertChain(blocks[3:]); err != nil {
@@ -1950,20 +2040,24 @@ func TestIssue23496(t *testing.T) {
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
}
+
defer db.Close()
- chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
+ chain, err = core.NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
+
defer chain.Stop()
if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
}
+
if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) {
t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4))
}
+
if head := chain.CurrentBlock(); head.NumberU64() != uint64(1) {
t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(1))
}
@@ -1972,15 +2066,19 @@ func TestIssue23496(t *testing.T) {
if _, err := chain.InsertChain(blocks[1:]); err != nil {
t.Fatalf("Failed to import canonical chain tail: %v", err)
}
+
if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
}
+
if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) {
t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4))
}
+
if head := chain.CurrentBlock(); head.NumberU64() != uint64(4) {
t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(4))
}
+
if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil {
t.Error("Failed to regenerate the snapshot of known state")
}
diff --git a/core/blockchain_sethead_test.go b/core/tests/blockchain_sethead_test.go
similarity index 98%
rename from core/blockchain_sethead_test.go
rename to core/tests/blockchain_sethead_test.go
index b2b3a058a4..3a2d87c4eb 100644
--- a/core/blockchain_sethead_test.go
+++ b/core/tests/blockchain_sethead_test.go
@@ -17,7 +17,7 @@
// Tests that setting the chain head backwards doesn't leave the database in some
// strange state with gaps in the chain, nor with block data dangling in the future.
-package core
+package tests
import (
"fmt"
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -1959,79 +1960,98 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
if err != nil {
t.Fatalf("Failed to create temporary datadir: %v", err)
}
+
os.RemoveAll(datadir)
db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
}
+
defer db.Close()
// Initialize a fresh chain
var (
- genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
+ genesis = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
engine = ethash.NewFullFaker()
- config = &CacheConfig{
+ config = &core.CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, // Disable snapshot
}
)
+
if snapshots {
config.SnapshotLimit = 256
config.SnapshotWait = true
}
- chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
+
+ chain, err := core.NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
+
// If sidechain blocks are needed, make a light chain and import it
var sideblocks types.Blocks
if tt.sidechainBlocks > 0 {
- sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) {
+ sideblocks, _ = core.GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0x01})
})
+
if _, err := chain.InsertChain(sideblocks); err != nil {
t.Fatalf("Failed to import side chain: %v", err)
}
}
- canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) {
+
+ canonblocks, _ := core.GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0x02})
b.SetDifficulty(big.NewInt(1000000))
})
+
if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
+
if tt.commitBlock > 0 {
- chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil)
+ err = chain.StateCache().TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil)
+ if err != nil {
+ t.Fatal("on trieDB.Commit", err)
+ }
+
if snapshots {
- if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
+ if err := chain.Snaps().Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err)
}
}
}
+
if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil {
t.Fatalf("Failed to import canonical chain tail: %v", err)
}
+
// Manually dereference anything not committed to not have to work with 128+ tries
for _, block := range sideblocks {
- chain.stateCache.TrieDB().Dereference(block.Root())
+ chain.StateCache().TrieDB().Dereference(block.Root())
}
+
for _, block := range canonblocks {
- chain.stateCache.TrieDB().Dereference(block.Root())
+ chain.StateCache().TrieDB().Dereference(block.Root())
}
+
// Force run a freeze cycle
type freezer interface {
Freeze(threshold uint64) error
Ancients() (uint64, error)
}
+
db.(freezer).Freeze(tt.freezeThreshold)
// Set the simulated pivot block
if tt.pivotBlock != nil {
rawdb.WriteLastPivotNumber(db, *tt.pivotBlock)
}
+
// Set the head of the chain back to the requested number
chain.SetHead(tt.setheadBlock)
@@ -2044,12 +2064,15 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader)
}
+
if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock {
t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock)
}
+
if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock {
t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock)
}
+
if frozen, err := db.(freezer).Ancients(); err != nil {
t.Errorf("Failed to retrieve ancient count: %v\n", err)
} else if int(frozen) != tt.expFrozen {
@@ -2059,7 +2082,8 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
// verifyNoGaps checks that there are no gaps after the initial set of blocks in
// the database and errors if found.
-func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) {
+//nolint:gocognit
+func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks) {
t.Helper()
var end uint64
@@ -2111,7 +2135,8 @@ func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted type
// verifyCutoff checks that there are no chain data available in the chain after
// the specified limit, but that it is available before.
-func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) {
+//nolint:gocognit
+func verifyCutoff(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks, head int) {
t.Helper()
for i := 1; i <= len(inserted); i++ {
diff --git a/core/blockchain_snapshot_test.go b/core/tests/blockchain_snapshot_test.go
similarity index 87%
rename from core/blockchain_snapshot_test.go
rename to core/tests/blockchain_snapshot_test.go
index a8044ecb4d..fb4c09867c 100644
--- a/core/blockchain_snapshot_test.go
+++ b/core/tests/blockchain_snapshot_test.go
@@ -17,7 +17,7 @@
// Tests that abnormal program termination (i.e.crash) and restart can recovery
// the snapshot properly if the snapshot is enabled.
-package core
+package tests
import (
"bytes"
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -57,7 +58,9 @@ type snapshotTestBasic struct {
engine consensus.Engine
}
-func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Block) {
+func (basic *snapshotTestBasic) prepare(t *testing.T) (*core.BlockChain, []*types.Block) {
+ t.Helper()
+
// Create a temporary persistent database
datadir, err := ioutil.TempDir("", "")
if err != nil {
@@ -71,20 +74,22 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
}
// Initialize a fresh chain
var (
- genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
+ genesis = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
engine = ethash.NewFullFaker()
gendb = rawdb.NewMemoryDatabase()
// Snapshot is enabled, the first snapshot is created from the Genesis.
// The snapshot memory allowance is 256MB, it means no snapshot flush
// will happen during the block insertion.
- cacheConfig = defaultCacheConfig
+ cacheConfig = core.DefaultCacheConfig
)
- chain, err := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
+
+ chain, err := core.NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
- blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, gendb, basic.chainBlocks, func(i int, b *BlockGen) {})
+
+ blocks, _ := core.GenerateChain(params.TestChainConfig, genesis, engine, gendb, basic.chainBlocks, func(i int, b *core.BlockGen) {})
// Insert the blocks with configured settings.
var breakpoints []uint64
@@ -93,27 +98,39 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
} else {
breakpoints = append(breakpoints, basic.commitBlock, basic.snapshotBlock)
}
+
var startPoint uint64
+
for _, point := range breakpoints {
if _, err := chain.InsertChain(blocks[startPoint:point]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
+
startPoint = point
if basic.commitBlock > 0 && basic.commitBlock == point {
- chain.stateCache.TrieDB().Commit(blocks[point-1].Root(), true, nil)
+ err = chain.StateCache().TrieDB().Commit(blocks[point-1].Root(), true, nil)
+ if err != nil {
+ t.Fatal("on trieDB.Commit", err)
+ }
}
+
if basic.snapshotBlock > 0 && basic.snapshotBlock == point {
// Flushing the entire snap tree into the disk, the
// relevant (a) snapshot root and (b) snapshot generator
// will be persisted atomically.
- chain.snaps.Cap(blocks[point-1].Root(), 0)
- diskRoot, blockRoot := chain.snaps.DiskRoot(), blocks[point-1].Root()
+ err = chain.Snaps().Cap(blocks[point-1].Root(), 0)
+ if err != nil {
+ t.Fatal("on Snaps.Cap", err)
+ }
+
+ diskRoot, blockRoot := chain.Snaps().DiskRoot(), blocks[point-1].Root()
if !bytes.Equal(diskRoot.Bytes(), blockRoot.Bytes()) {
t.Fatalf("Failed to flush disk layer change, want %x, got %x", blockRoot, diskRoot)
}
}
}
+
if _, err := chain.InsertChain(blocks[startPoint:]); err != nil {
t.Fatalf("Failed to import canonical chain tail: %v", err)
}
@@ -123,10 +140,13 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
basic.db = db
basic.gendb = gendb
basic.engine = engine
+
return chain, blocks
}
-func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks []*types.Block) {
+func (basic *snapshotTestBasic) verify(t *testing.T, chain *core.BlockChain, blocks []*types.Block) {
+ t.Helper()
+
// Iterate over all the remaining blocks and ensure there are no gaps
verifyNoGaps(t, chain, true, blocks)
verifyCutoff(t, chain, true, blocks, basic.expCanonicalBlocks)
@@ -134,9 +154,11 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [
if head := chain.CurrentHeader(); head.Number.Uint64() != basic.expHeadHeader {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, basic.expHeadHeader)
}
+
if head := chain.CurrentFastBlock(); head.NumberU64() != basic.expHeadFastBlock {
t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), basic.expHeadFastBlock)
}
+
if head := chain.CurrentBlock(); head.NumberU64() != basic.expHeadBlock {
t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), basic.expHeadBlock)
}
@@ -145,12 +167,12 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [
block := chain.GetBlockByNumber(basic.expSnapshotBottom)
if block == nil {
t.Errorf("The correspnding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom)
- } else if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) {
- t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot())
+ } else if !bytes.Equal(chain.Snaps().DiskRoot().Bytes(), block.Root().Bytes()) {
+ t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.Snaps().DiskRoot())
}
// Check the snapshot, ensure it's integrated
- if err := chain.snaps.Verify(block.Root()); err != nil {
+ if err := chain.Snaps().Verify(block.Root()); err != nil {
t.Errorf("The disk layer is not integrated %v", err)
}
}
@@ -223,10 +245,12 @@ func (snaptest *snapshotTest) test(t *testing.T) {
// Restart the chain normally
chain.Stop()
- newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+
+ newchain, err := core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
+
defer newchain.Stop()
snaptest.verify(t, newchain, blocks)
@@ -245,7 +269,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
chain, blocks := snaptest.prepare(t)
// Pull the plug on the database, simulating a hard crash
- db := chain.db
+ db := chain.DB()
db.Close()
// Start a new blockchain back up and see where the repair leads us
@@ -259,13 +283,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
// the crash, we do restart twice here: one after the crash and one
// after the normal stop. It's used to ensure the broken snapshot
// can be detected all the time.
- newchain, err := NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+ newchain, err := core.NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
newchain.Stop()
- newchain, err = NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+ newchain, err = core.NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -292,27 +316,31 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
// Insert blocks without enabling snapshot if gapping is required.
chain.Stop()
- gappedBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.gapped, func(i int, b *BlockGen) {})
+
+ gappedBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.gapped, func(i int, b *core.BlockGen) {})
// Insert a few more blocks without enabling snapshot
- var cacheConfig = &CacheConfig{
+ var cacheConfig = &core.CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0,
}
- newchain, err := NewBlockChain(snaptest.db, cacheConfig, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+
+ newchain, err := core.NewBlockChain(snaptest.db, cacheConfig, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
+
newchain.InsertChain(gappedBlocks)
newchain.Stop()
// Restart the chain with enabling the snapshot
- newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+ newchain, err = core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
+
defer newchain.Stop()
snaptest.verify(t, newchain, blocks)
@@ -337,7 +365,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
chain.SetHead(snaptest.setHead)
chain.Stop()
- newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+ newchain, err := core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -368,11 +396,12 @@ func (snaptest *restartCrashSnapshotTest) test(t *testing.T) {
// and state committed.
chain.Stop()
- newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+ newchain, err := core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
- newBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *BlockGen) {})
+
+ newBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *core.BlockGen) {})
newchain.InsertChain(newBlocks)
// Commit the entire snapshot into the disk if requested. Note only
@@ -385,7 +414,7 @@ func (snaptest *restartCrashSnapshotTest) test(t *testing.T) {
// journal and latest state will be committed
// Restart the chain after the crash
- newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+ newchain, err = core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -414,38 +443,42 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
// and state committed.
chain.Stop()
- config := &CacheConfig{
+ config := &core.CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0,
}
- newchain, err := NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+
+ newchain, err := core.NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
- newBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *BlockGen) {})
+
+ newBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *core.BlockGen) {})
newchain.InsertChain(newBlocks)
newchain.Stop()
// Restart the chain, the wiper should starts working
- config = &CacheConfig{
+ config = &core.CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 256,
SnapshotWait: false, // Don't wait rebuild
}
- newchain, err = NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+
+ _, err = core.NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
// Simulate the blockchain crash.
- newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
+ newchain, err = core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
+
snaptest.verify(t, newchain, blocks)
}
diff --git a/docs/cli/README.md b/docs/cli/README.md
index ed8a3f5977..d92a7b5a05 100644
--- a/docs/cli/README.md
+++ b/docs/cli/README.md
@@ -1,24 +1,33 @@
-
-# Command line interface
+# Bor command line interface
## Commands
-- [```server```](./server.md)
-
-- [```debug```](./debug.md)
-
- [```account```](./account.md)
-- [```account new```](./account_new.md)
+- [```account import```](./account_import.md)
- [```account list```](./account_list.md)
-- [```account import```](./account_import.md)
+- [```account new```](./account_new.md)
+
+- [```attach```](./attach.md)
+
+- [```bootnode```](./bootnode.md)
- [```chain```](./chain.md)
- [```chain sethead```](./chain_sethead.md)
+- [```chain watch```](./chain_watch.md)
+
+- [```debug```](./debug.md)
+
+- [```debug block```](./debug_block.md)
+
+- [```debug pprof```](./debug_pprof.md)
+
+- [```fingerprint```](./fingerprint.md)
+
- [```peers```](./peers.md)
- [```peers add```](./peers_add.md)
@@ -29,8 +38,8 @@
- [```peers status```](./peers_status.md)
+- [```server```](./server.md)
+
- [```status```](./status.md)
-- [```chain watch```](./chain_watch.md)
-
-- [```version```](./version.md)
+- [```version```](./version.md)
\ No newline at end of file
diff --git a/docs/cli/account.md b/docs/cli/account.md
index 00fd6cbe65..b3659952f6 100644
--- a/docs/cli/account.md
+++ b/docs/cli/account.md
@@ -1,4 +1,3 @@
-
# Account
The ```account``` command groups actions to interact with accounts:
@@ -7,4 +6,4 @@ The ```account``` command groups actions to interact with accounts:
- [```account list```](./account_list.md): List the wallets in the Bor client.
-- [```account import```](./account_import.md): Import an account to the Bor client.
+- [```account import```](./account_import.md): Import an account to the Bor client.
\ No newline at end of file
diff --git a/docs/cli/account_import.md b/docs/cli/account_import.md
index 2a515866cf..d7b02195bc 100644
--- a/docs/cli/account_import.md
+++ b/docs/cli/account_import.md
@@ -1,4 +1,9 @@
-
# Account import
The ```account import``` command imports an account in Json format to the Bor data directory.
+
+## Options
+
+- ```datadir```: Path of the data directory to store information
+
+- ```keystore```: Path of the data directory to store information
\ No newline at end of file
diff --git a/docs/cli/account_list.md b/docs/cli/account_list.md
index 4a2d28de92..61ebf9e776 100644
--- a/docs/cli/account_list.md
+++ b/docs/cli/account_list.md
@@ -1,4 +1,9 @@
-
# Account list
-The ```account list``` command lists all the accounts in the Bor data directory.
+The `account list` command lists all the accounts in the Bor data directory.
+
+## Options
+
+- ```datadir```: Path of the data directory to store information
+
+- ```keystore```: Path of the data directory to store information
\ No newline at end of file
diff --git a/docs/cli/account_new.md b/docs/cli/account_new.md
index 41e53767a1..dd62061ba0 100644
--- a/docs/cli/account_new.md
+++ b/docs/cli/account_new.md
@@ -1,4 +1,9 @@
-
# Account new
-The ```account new``` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command.
+The `account new` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command.
+
+## Options
+
+- ```datadir```: Path of the data directory to store information
+
+- ```keystore```: Path of the data directory to store information
\ No newline at end of file
diff --git a/docs/cli/attach.md b/docs/cli/attach.md
new file mode 100644
index 0000000000..6e323b8d18
--- /dev/null
+++ b/docs/cli/attach.md
@@ -0,0 +1,11 @@
+# Attach
+
+Connect to remote Bor IPC console.
+
+## Options
+
+- ```exec```: Command to run in remote console
+
+- ```preload```: Comma separated list of JavaScript files to preload into the console
+
+- ```jspath```: JavaScript root path for `loadScript`
\ No newline at end of file
diff --git a/docs/cli/bootnode.md b/docs/cli/bootnode.md
new file mode 100644
index 0000000000..48e933a934
--- /dev/null
+++ b/docs/cli/bootnode.md
@@ -0,0 +1,17 @@
+# Bootnode
+
+## Options
+
+- ```listen-addr```: listening address of bootnode (:)
+
+- ```v5```: Enable UDP v5
+
+- ```log-level```: Log level (trace|debug|info|warn|error|crit)
+
+- ```nat```: port mapping mechanism (any|none|upnp|pmp|extip:)
+
+- ```node-key```: file or hex node key
+
+- ```save-key```: path to save the ecdsa private key
+
+- ```dry-run```: validates parameters and prints bootnode configurations, but does not start bootnode
\ No newline at end of file
diff --git a/docs/cli/chain.md b/docs/cli/chain.md
index e55a90f122..8412588e37 100644
--- a/docs/cli/chain.md
+++ b/docs/cli/chain.md
@@ -1,6 +1,7 @@
-
# Chain
The ```chain``` command groups actions to interact with the blockchain in the client:
- [```chain sethead```](./chain_sethead.md): Set the current chain to a certain block.
+
+- [```chain watch```](./chain_watch.md): Watch the chainHead, reorg and fork events in real-time.
\ No newline at end of file
diff --git a/docs/cli/chain_sethead.md b/docs/cli/chain_sethead.md
index 985383988f..bf97990e62 100644
--- a/docs/cli/chain_sethead.md
+++ b/docs/cli/chain_sethead.md
@@ -1,4 +1,3 @@
-
# Chain sethead
The ```chain sethead ``` command sets the current chain to a certain block.
@@ -9,4 +8,6 @@ The ```chain sethead ``` command sets the current chain to a certain blo
## Options
-- ```yes```: Force set head.
+- ```address```: Address of the grpc endpoint
+
+- ```yes```: Force set head
\ No newline at end of file
diff --git a/docs/cli/chain_watch.md b/docs/cli/chain_watch.md
index 4844bb7618..252ac02531 100644
--- a/docs/cli/chain_watch.md
+++ b/docs/cli/chain_watch.md
@@ -1,3 +1,3 @@
# Chain watch
-The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.
+The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.
\ No newline at end of file
diff --git a/docs/cli/debug.md b/docs/cli/debug.md
index c75ae79e49..a59e465745 100644
--- a/docs/cli/debug.md
+++ b/docs/cli/debug.md
@@ -1,13 +1,10 @@
-
# Debug
The ```bor debug``` command takes a debug dump of the running client.
-## Options
+- [```bor debug pprof```](./debug_pprof.md): Dumps bor pprof traces.
-- ```seconds```: Number of seconds to trace cpu and traces.
-
-- ```output```: Output directory for the data dump.
+- [```bor debug block ```](./debug_block.md): Dumps bor block traces.
## Examples
@@ -15,8 +12,8 @@ By default it creates a tar.gz file with the output:
```
$ bor debug
-Starting debugger...
-
+Starting debugger...
+
Created debug archive: bor-debug-2021-10-26-073819Z.tar.gz
```
@@ -27,4 +24,4 @@ $ bor debug --output data
Starting debugger...
Created debug directory: data/bor-debug-2021-10-26-075437Z
-```
+```
\ No newline at end of file
diff --git a/docs/cli/debug_block.md b/docs/cli/debug_block.md
new file mode 100644
index 0000000000..ced7e482ee
--- /dev/null
+++ b/docs/cli/debug_block.md
@@ -0,0 +1,9 @@
+# Debug trace
+
+The ```bor debug block ``` command will create an archive containing traces of a bor block.
+
+## Options
+
+- ```address```: Address of the grpc endpoint
+
+- ```output```: Output directory
\ No newline at end of file
diff --git a/docs/cli/debug_pprof.md b/docs/cli/debug_pprof.md
new file mode 100644
index 0000000000..86a84b6065
--- /dev/null
+++ b/docs/cli/debug_pprof.md
@@ -0,0 +1,11 @@
+# Debug Pprof
+
+The ```debug pprof ``` command will create an archive containing bor pprof traces.
+
+## Options
+
+- ```address```: Address of the grpc endpoint
+
+- ```seconds```: seconds to trace
+
+- ```output```: Output directory
\ No newline at end of file
diff --git a/docs/cli/fingerprint.md b/docs/cli/fingerprint.md
new file mode 100644
index 0000000000..8bb7cb1542
--- /dev/null
+++ b/docs/cli/fingerprint.md
@@ -0,0 +1,3 @@
+# Fingerprint
+
+Display the system fingerprint
\ No newline at end of file
diff --git a/docs/cli/peers.md b/docs/cli/peers.md
index 57b4889a00..ac6dfd676e 100644
--- a/docs/cli/peers.md
+++ b/docs/cli/peers.md
@@ -1,4 +1,3 @@
-
# Peers
The ```peers``` command groups actions to interact with peers:
@@ -9,4 +8,4 @@ The ```peers``` command groups actions to interact with peers:
- [```peers remove```](./peers_remove.md): Disconnects the local client from a connected peer if exists.
-- [```peers status```](./peers_status.md): Display the status of a peer by its id.
+- [```peers status```](./peers_status.md): Display the status of a peer by its id.
\ No newline at end of file
diff --git a/docs/cli/peers_add.md b/docs/cli/peers_add.md
index 35e5ece450..5bc4ed1448 100644
--- a/docs/cli/peers_add.md
+++ b/docs/cli/peers_add.md
@@ -1,8 +1,9 @@
-
# Peers add
The ```peers add ``` command joins the local client to another remote peer.
-## Arguments
+## Options
-- ```trusted```: Whether the peer is added as a trusted peer.
+- ```address```: Address of the grpc endpoint
+
+- ```trusted```: Add the peer as a trusted
\ No newline at end of file
diff --git a/docs/cli/peers_list.md b/docs/cli/peers_list.md
index cb1ef2f599..41f398b764 100644
--- a/docs/cli/peers_list.md
+++ b/docs/cli/peers_list.md
@@ -1,4 +1,7 @@
-
-# Peers list
+# Peers add
The ```peers list``` command lists the connected peers.
+
+## Options
+
+- ```address```: Address of the grpc endpoint
\ No newline at end of file
diff --git a/docs/cli/peers_remove.md b/docs/cli/peers_remove.md
index e2fa0a71df..2cac1e7656 100644
--- a/docs/cli/peers_remove.md
+++ b/docs/cli/peers_remove.md
@@ -1,4 +1,9 @@
-
# Peers remove
The ```peers remove ``` command disconnects the local client from a connected peer if exists.
+
+## Options
+
+- ```address```: Address of the grpc endpoint
+
+- ```trusted```: Add the peer as a trusted
\ No newline at end of file
diff --git a/docs/cli/peers_status.md b/docs/cli/peers_status.md
index 56343c8d6b..65a0fe9d8f 100644
--- a/docs/cli/peers_status.md
+++ b/docs/cli/peers_status.md
@@ -1,4 +1,7 @@
-
# Peers status
The ```peers status ``` command displays the status of a peer by its id.
+
+## Options
+
+- ```address```: Address of the grpc endpoint
\ No newline at end of file
diff --git a/docs/cli/server.md b/docs/cli/server.md
index 5a3e7e1052..0803208e3a 100644
--- a/docs/cli/server.md
+++ b/docs/cli/server.md
@@ -1,45 +1,182 @@
-
# Server
The ```bor server``` command runs the Bor client.
-## General Options
+## Options
-- ```chain```: Name of the chain to sync (mainnet or mumbai).
+- ```chain```: Name of the chain to sync
-- ```log-level```: Set log level for the server (info, warn, debug, trace).
+- ```name```: Name/Identity of the node
-- ```datadir```: Path of the data directory to store information (defaults to $HOME).
+- ```log-level```: Set log level for the server
-- ```config```: List of files that contain the configuration.
+- ```datadir```: Path of the data directory to store information
-- ```syncmode```: Blockchain sync mode ("fast", "full", "snap" or "light").
+- ```keystore```: Path of the directory to store keystores
-- ```gcmode```: Blockchain garbage collection mode ("full", "archive").
+- ```config```: File for the config file
-- ```whitelist```: Comma separated block number-to-hash mappings to enforce (=).
+- ```syncmode```: Blockchain sync mode ("fast", "full", or "snap")
-- ```snapshot```: Enables snapshot-database mode (default = enable).
+- ```gcmode```: Blockchain garbage collection mode ("full", "archive")
-- ```bor.heimdall```: URL of Heimdall service.
+- ```requiredblocks```: Comma separated block number-to-hash mappings to enforce (=)
-- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose).
+- ```no-snapshot```: Disables the snapshot-database mode (default = false)
-- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port).
+- ```bor.heimdall```: URL of Heimdall service
-- ```gpo.blocks```: Number of recent blocks to check for gas prices.
+- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose)
-- ```gpo.percentile```: Suggested gas price is the given percentile of a set of recent transaction gas prices.
+- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port)
-- ```gpo.maxprice```: Maximum gas price will be recommended by gpo.
+- ```gpo.blocks```: Number of recent blocks to check for gas prices
-- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions.
+- ```gpo.percentile```: Suggested gas price is the given percentile of a set of recent transaction gas prices
-- ```grpc.addr```: Address and port to bind the GRPC server.
+- ```gpo.maxprice```: Maximum gas price will be recommended by gpo
+
+- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions
+
+- ```disable-bor-wallet```: Disable the personal wallet endpoints
+
+- ```grpc.addr```: Address and port to bind the GRPC server
+
+- ```dev```: Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled
+
+- ```dev.period```: Block period to use in developer mode (0 = mine only if transaction pending)
+
+### Account Management Options
+
+- ```unlock```: Comma separated list of accounts to unlock
+
+- ```password```: Password file to use for non-interactive password input
+
+- ```allow-insecure-unlock```: Allow insecure account unlocking when account-related RPCs are exposed by http
+
+- ```lightkdf```: Reduce key-derivation RAM & CPU usage at some expense of KDF strength
+
+### Cache Options
+
+- ```cache```: Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)
+
+- ```cache.database```: Percentage of cache memory allowance to use for database io
+
+- ```cache.trie```: Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)
+
+- ```cache.trie.journal```: Disk journal directory for trie cache to survive node restarts
+
+- ```cache.trie.rejournal```: Time interval to regenerate the trie cache journal
+
+- ```cache.gc```: Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)
+
+- ```cache.snapshot```: Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)
+
+- ```cache.noprefetch```: Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)
+
+- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys
+
+- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)
+
+### JsonRPC Options
+
+- ```rpc.gascap```: Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)
+
+- ```rpc.txfeecap```: Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)
+
+- ```ipcdisable```: Disable the IPC-RPC server
+
+- ```ipcpath```: Filename for IPC socket/pipe within the datadir (explicit paths escape it)
+
+- ```jsonrpc.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced)
+
+- ```jsonrpc.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
+
+- ```http```: Enable the HTTP-RPC server
+
+- ```http.addr```: HTTP-RPC server listening interface
+
+- ```http.port```: HTTP-RPC server listening port
+
+- ```http.rpcprefix```: HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
+
+- ```http.modules```: API's offered over the HTTP-RPC interface
+
+- ```ws```: Enable the WS-RPC server
+
+- ```ws.addr```: WS-RPC server listening interface
+
+- ```ws.port```: WS-RPC server listening port
+
+- ```ws.rpcprefix```: HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
+
+- ```ws.modules```: API's offered over the WS-RPC interface
+
+- ```graphql```: Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.
+
+### P2P Options
+
+- ```bind```: Network binding address
+
+- ```port```: Network listening port
+
+- ```bootnodes```: Comma separated enode URLs for P2P discovery bootstrap
+
+- ```maxpeers```: Maximum number of network peers (network disabled if set to 0)
+
+- ```maxpendpeers```: Maximum number of pending connection attempts (defaults used if set to 0)
+
+- ```nat```: NAT port mapping mechanism (any|none|upnp|pmp|extip:)
+
+- ```nodiscover```: Disables the peer discovery mechanism (manual peer addition)
+
+- ```v5disc```: Enables the experimental RLPx V5 (Topic Discovery) mechanism
+
+### Sealer Options
+
+- ```mine```: Enable mining
+
+- ```miner.etherbase```: Public address for block mining rewards (default = first account)
+
+- ```miner.extradata```: Block extra data set by the miner (default = client version)
+
+- ```miner.gaslimit```: Target gas ceiling for mined blocks
+
+- ```miner.gasprice```: Minimum gas price for mining a transaction
+
+### Telemetry Options
+
+- ```metrics```: Enable metrics collection and reporting
+
+- ```metrics.expensive```: Enable expensive metrics collection and reporting
+
+- ```metrics.influxdb```: Enable metrics export/push to an external InfluxDB database (v1)
+
+- ```metrics.influxdb.endpoint```: InfluxDB API endpoint to report metrics to
+
+- ```metrics.influxdb.database```: InfluxDB database name to push reported metrics to
+
+- ```metrics.influxdb.username```: Username to authorize access to the database
+
+- ```metrics.influxdb.password```: Password to authorize access to the database
+
+- ```metrics.influxdb.tags```: Comma-separated InfluxDB tags (key/values) attached to all measurements
+
+- ```metrics.prometheus-addr```: Address for Prometheus Server
+
+- ```metrics.opencollector-endpoint```: OpenCollector Endpoint (host:port)
+
+- ```metrics.influxdbv2```: Enable metrics export/push to an external InfluxDB v2 database
+
+- ```metrics.influxdb.token```: Token to authorize access to the database (v2 only)
+
+- ```metrics.influxdb.bucket```: InfluxDB bucket name to push reported metrics to (v2 only)
+
+- ```metrics.influxdb.organization```: InfluxDB organization name (v2 only)
### Transaction Pool Options
-- ```txpool.locals```: Comma separated accounts to treat as locals (no flush, priority inclusion).
+- ```txpool.locals```: Comma separated accounts to treat as locals (no flush, priority inclusion)
- ```txpool.nolocals```: Disables price exemptions for locally submitted transactions
@@ -59,136 +196,4 @@ The ```bor server``` command runs the Bor client.
- ```txpool.globalqueue```: Maximum number of non-executable transaction slots for all accounts
-- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued
-
-### Sealer Options
-
-- ```mine```: Enable sealing.
-
-- ```miner.etherbase```: Public address for block mining rewards (default = first account)
-
-- ```miner.extradata```: Block extra data set by the miner (default = client version).
-
-- ```miner.gaslimit```: Target gas ceiling for mined blocks.
-
-- ```miner.gasprice```: Minimum gas price for mining a transaction.
-
-### Cache Options
-
-- ```cache```: Megabytes of memory allocated to internal caching (default = 4096 mainnet full node).
-
-- ```cache.database```: Percentage of cache memory allowance to use for database io.
-
-- ```cache.trie```: Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode).
-
-- ```cache.trie.journal```: Disk journal directory for trie cache to survive node restarts.
-
-- ```cache.trie.rejournal```: Time interval to regenerate the trie cache journal.
-
-- ```cache.gc```: Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode).
-
-- ```cache.snapshot```: Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode).
-
-- ```cache.noprefetch```: Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data).
-
-- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys.
-
-- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain).
-
-### JsonRPC Options
-
-- ```rpc.gascap```: Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite).
-
-- ```rpc.txfeecap```: Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap).
-
-- ```ipcdisable```: Disable the IPC-RPC server.
-
-- ```ipcpath```: Filename for IPC socket/pipe within the datadir (explicit paths escape it).
-
-- ```jsonrpc.corsdomain```: Comma separated list of domains from which to accept cross.
-
-- ```jsonrpc.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
-
-- ```http```: Enable the HTTP-RPC server.
-
-- ```http.addr```: HTTP-RPC server listening interface.
-
-- ```http.port```: HTTP-RPC server listening port.
-
-- ```http.rpcprefix```: HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
-
-- ```http.modules```: API's offered over the HTTP-RPC interface.
-
-- ```ws```: Enable the WS-RPC server.
-
-- ```ws.addr```: WS-RPC server listening interface.
-
-- ```ws.port```: WS-RPC server listening port.
-
-- ```ws.rpcprefix```: HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
-
-- ```ws.modules```: API's offered over the WS-RPC interface.
-
-- ```graphql```: Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.
-
-### P2P Options
-
-- ```bind```: Network binding address
-
-- ```port```: Network listening port
-
-- ```bootnodes```: Comma separated enode URLs for P2P discovery bootstrap
-
-- ```maxpeers```: "Maximum number of network peers (network disabled if set to 0)
-
-- ```maxpendpeers```: Maximum number of pending connection attempts (defaults used if set to 0)
-
-- ```nat```: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)
-
-- ```nodiscover```: "Disables the peer discovery mechanism (manual peer addition)
-
-- ```v5disc```: "Enables the experimental RLPx V5 (Topic Discovery) mechanism
-
-### Telemetry Options
-
-- ```metrics```: Enable metrics collection and reporting.
-
-- ```metrics.expensive```: Enable expensive metrics collection and reporting.
-
-- ```metrics.influxdb```: Enable metrics export/push to an external InfluxDB database (v1).
-
-- ```metrics.influxdb.endpoint```: InfluxDB API endpoint to report metrics to.
-
-- ```metrics.influxdb.database```: InfluxDB database name to push reported metrics to.
-
-- ```metrics.influxdb.username```: Username to authorize access to the database.
-
-- ```metrics.influxdb.password```: Password to authorize access to the database.
-
-- ```metrics.influxdb.tags```: Comma-separated InfluxDB tags (key/values) attached to all measurements.
-
-- ```metrics.influxdbv2```: Enable metrics export/push to an external InfluxDB v2 database.
-
-- ```metrics.influxdb.token```: Token to authorize access to the database (v2 only).
-
-- ```metrics.influxdb.bucket```: InfluxDB bucket name to push reported metrics to (v2 only).
-
-- ```metrics.influxdb.organization```: InfluxDB organization name (v2 only).
-
-### Account Management Options
-
-- ```unlock```: "Comma separated list of accounts to unlock.
-
-- ```password```: Password file to use for non-interactive password input.
-
-- ```allow-insecure-unlock```: Allow insecure account unlocking when account-related RPCs are exposed by http.
-
-- ```lightkdf```: Reduce key-derivation RAM & CPU usage at some expense of KDF strength.
-
-## Usage
-
-Use multiple files to configure the client:
-
-```
-$ bor server --config ./legacy-config.toml --config ./config2.hcl
-```
+- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued
\ No newline at end of file
diff --git a/docs/cli/status.md b/docs/cli/status.md
index fb7bddb182..9fa8e25905 100644
--- a/docs/cli/status.md
+++ b/docs/cli/status.md
@@ -1,4 +1,3 @@
-
# Status
-The ```status``` command outputs the status of the client.
+The ```status``` command outputs the status of the client.
\ No newline at end of file
diff --git a/docs/cli/version.md b/docs/cli/version.md
index 156bdf607c..87e7cf44a8 100644
--- a/docs/cli/version.md
+++ b/docs/cli/version.md
@@ -1,4 +1,3 @@
-
# Version
The ```bor version``` command outputs the version of the binary.
@@ -8,4 +7,4 @@ The ```bor version``` command outputs the version of the binary.
```
$ bor version
0.2.9-stable
-```
+```
\ No newline at end of file
diff --git a/eth/backend.go b/eth/backend.go
index fcba1c573b..0b8a956cfa 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -82,6 +82,7 @@ type Ethereum struct {
eventMux *event.TypeMux
engine consensus.Engine
accountManager *accounts.Manager
+ authorized bool // If consensus engine is authorized with keystore
bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests
bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports
@@ -155,6 +156,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
chainDb: chainDb,
eventMux: stack.EventMux(),
accountManager: stack.AccountManager(),
+ authorized: false,
engine: nil,
closeBloomHandler: make(chan struct{}),
networkID: config.NetworkId,
@@ -473,8 +475,10 @@ func (s *Ethereum) StartMining(threads int) error {
if threads == 0 {
threads = -1 // Disable the miner from within
}
+
th.SetThreads(threads)
}
+
// If the miner was not running, initialize it
if !s.IsMining() {
// Propagate the initial price point to the transaction pool
@@ -487,31 +491,43 @@ func (s *Ethereum) StartMining(threads int) error {
eb, err := s.Etherbase()
if err != nil {
log.Error("Cannot start mining without etherbase", "err", err)
+
return fmt.Errorf("etherbase missing: %v", err)
}
- var cli *clique.Clique
- if c, ok := s.engine.(*clique.Clique); ok {
- cli = c
- } else if cl, ok := s.engine.(*beacon.Beacon); ok {
- if c, ok := cl.InnerEngine().(*clique.Clique); ok {
+
+ // If personal endpoints are disabled, the server creating
+ // this Ethereum instance has already Authorized consensus.
+ if !s.authorized {
+ var cli *clique.Clique
+ if c, ok := s.engine.(*clique.Clique); ok {
cli = c
+ } else if cl, ok := s.engine.(*beacon.Beacon); ok {
+ if c, ok := cl.InnerEngine().(*clique.Clique); ok {
+ cli = c
+ }
}
- }
- if cli != nil {
- wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
- if wallet == nil || err != nil {
- log.Error("Etherbase account unavailable locally", "err", err)
- return fmt.Errorf("signer missing: %v", err)
+
+ if cli != nil {
+ wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
+ if wallet == nil || err != nil {
+ log.Error("Etherbase account unavailable locally", "err", err)
+
+ return fmt.Errorf("signer missing: %v", err)
+ }
+
+ cli.Authorize(eb, wallet.SignData)
}
- cli.Authorize(eb, wallet.SignData)
- }
- if bor, ok := s.engine.(*bor.Bor); ok {
- wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
- if wallet == nil || err != nil {
- log.Error("Etherbase account unavailable locally", "err", err)
- return fmt.Errorf("signer missing: %v", err)
+
+ if bor, ok := s.engine.(*bor.Bor); ok {
+ wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
+ if wallet == nil || err != nil {
+ log.Error("Etherbase account unavailable locally", "err", err)
+
+ return fmt.Errorf("signer missing: %v", err)
+ }
+
+ bor.Authorize(eb, wallet.SignData)
}
- bor.Authorize(eb, wallet.SignData)
}
// If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times.
@@ -519,6 +535,7 @@ func (s *Ethereum) StartMining(threads int) error {
go s.miner.Start(eb)
}
+
return nil
}
@@ -557,6 +574,14 @@ func (s *Ethereum) SyncMode() downloader.SyncMode {
return mode
}
+// SetAuthorized sets the authorized bool variable
+// denoting that consensus has been authorized while creation
+func (s *Ethereum) SetAuthorized(authorized bool) {
+ s.lock.Lock()
+ s.authorized = authorized
+ s.lock.Unlock()
+}
+
// Protocols returns all the currently configured
// network protocols to start.
func (s *Ethereum) Protocols() []p2p.Protocol {
@@ -564,6 +589,7 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
if s.config.SnapshotCache > 0 {
protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...)
}
+
return protos
}
@@ -645,7 +671,7 @@ func (s *Ethereum) handleWhitelistCheckpoint() error {
return ErrNotBorConsensus
}
- if bor.WithoutHeimdall {
+ if bor.HeimdallClient == nil {
return ErrBorConsensusWithoutHeimdall
}
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index b82a622893..1a9d815ccd 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -215,6 +215,7 @@ type BlockChain interface {
}
// New creates a new downloader to fetch hashes and blocks from remote peers.
+//nolint: staticcheck
func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, success func(), whitelistService ChainValidator) *Downloader {
if lightchain == nil {
lightchain = chain
@@ -1379,6 +1380,7 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
if chunkHeaders[len(chunkHeaders)-1].Number.Uint64()+uint64(fsHeaderForceVerify) > pivot {
frequency = 1
}
+
// Although the received headers might be all valid, a legacy
// PoW/PoA sync must not accept post-merge headers. Make sure
// that any transition is rejected at this point.
@@ -1386,13 +1388,16 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
rejected []*types.Header
td *big.Int
)
+
if !beaconMode && ttd != nil {
td = d.blockchain.GetTd(chunkHeaders[0].ParentHash, chunkHeaders[0].Number.Uint64()-1)
if td == nil {
// This should never really happen, but handle gracefully for now
log.Error("Failed to retrieve parent header TD", "number", chunkHeaders[0].Number.Uint64()-1, "hash", chunkHeaders[0].ParentHash)
+
return fmt.Errorf("%w: parent TD missing", errInvalidChain)
}
+
for i, header := range chunkHeaders {
td = new(big.Int).Add(td, header.Difficulty)
if td.Cmp(ttd) >= 0 {
@@ -1406,10 +1411,12 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
} else {
chunkHeaders, rejected = chunkHeaders[:i], chunkHeaders[i:]
}
+
break
}
}
}
+
if len(chunkHeaders) > 0 {
if n, err := d.lightchain.InsertHeaderChain(chunkHeaders, frequency); err != nil {
rollbackErr = err
@@ -1418,12 +1425,15 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
if (mode == SnapSync || frequency > 1) && n > 0 && rollback == 0 {
rollback = chunkHeaders[0].Number.Uint64()
}
+
log.Warn("Invalid header encountered", "number", chunkHeaders[n].Number, "hash", chunkHashes[n], "parent", chunkHeaders[n].ParentHash, "err", err)
+
return fmt.Errorf("%w: %v", errInvalidChain, err)
}
// All verifications passed, track all headers within the allowed limits
if mode == SnapSync {
head := chunkHeaders[len(chunkHeaders)-1].Number.Uint64()
+
if head-rollback > uint64(fsHeaderSafetyNet) {
rollback = head - uint64(fsHeaderSafetyNet)
} else {
@@ -1431,21 +1441,26 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
}
}
}
+
if len(rejected) != 0 {
// Merge threshold reached, stop importing, but don't roll back
rollback = 0
log.Info("Legacy sync reached merge threshold", "number", rejected[0].Number, "hash", rejected[0].Hash(), "td", td, "ttd", ttd)
+
return ErrMergeTransition
}
+
if len(rejected) != 0 {
// Merge threshold reached, stop importing, but don't roll back
rollback = 0
log.Info("Legacy sync reached merge threshold", "number", rejected[0].Number, "hash", rejected[0].Hash(), "td", td, "ttd", ttd)
+
return ErrMergeTransition
}
}
+
// Unless we're doing light chains, schedule the headers for associated content retrieval
if mode == FullSync || mode == SnapSync {
// If we've reached the allowed number of pending headers, stall a bit
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index bf9158d220..37b07424dd 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -43,6 +43,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
+
"github.com/stretchr/testify/assert"
)
@@ -62,23 +63,28 @@ func newTester() *downloadTester {
if err != nil {
panic(err)
}
+
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false)
if err != nil {
panic(err)
}
+
core.GenesisBlockForTesting(db, testAddress, big.NewInt(1000000000000000))
chain, err := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil {
panic(err)
}
+
tester := &downloadTester{
freezer: freezer,
chain: chain,
peers: make(map[string]*downloadTesterPeer),
}
+ //nolint: staticcheck
tester.downloader = New(0, db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, nil, whitelist.NewService(10))
+
return tester
}
@@ -1349,6 +1355,7 @@ func TestRemoteHeaderRequestSpan(t *testing.T) {
}
}
}
+
if failed {
res := strings.Replace(fmt.Sprint(data), " ", ",", -1)
exp := strings.Replace(fmt.Sprint(tt.expected), " ", ",", -1)
@@ -1383,9 +1390,11 @@ func testCheckpointEnforcement(t *testing.T, protocol uint, mode SyncMode) {
if mode == SnapSync || mode == LightSync {
expect = errUnsyncedPeer
}
+
if err := tester.sync("peer", nil, mode); !errors.Is(err, expect) {
t.Fatalf("block sync error mismatch: have %v, want %v", err, expect)
}
+
if mode == SnapSync || mode == LightSync {
assertOwnChain(t, tester, 1)
} else {
@@ -1409,14 +1418,15 @@ func newWhitelistFake(validate func(count int) (bool, error)) *whitelistFake {
// IsValidChain is the mock function which the downloader will use to validate the chain
// to be received from a peer.
-func (w *whitelistFake) IsValidChain(remoteHeader *types.Header, fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
+func (w *whitelistFake) IsValidChain(_ *types.Header, _ func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
defer func() {
w.count++
}()
+
return w.validate(w.count)
}
-func (w *whitelistFake) ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) {}
+func (w *whitelistFake) ProcessCheckpoint(_ uint64, _ common.Hash) {}
func (w *whitelistFake) GetCheckpointWhitelist() map[uint64]common.Hash {
return nil
@@ -1427,6 +1437,8 @@ func (w *whitelistFake) PurgeCheckpointWhitelist() {}
// TestFakedSyncProgress66WhitelistMismatch tests if in case of whitelisted
// checkpoint mismatch with opposite peer, the sync should fail.
func TestFakedSyncProgress66WhitelistMismatch(t *testing.T) {
+ t.Parallel()
+
protocol := uint(eth.ETH66)
mode := FullSync
@@ -1450,6 +1462,8 @@ func TestFakedSyncProgress66WhitelistMismatch(t *testing.T) {
// TestFakedSyncProgress66WhitelistMatch tests if in case of whitelisted
// checkpoint match with opposite peer, the sync should succeed.
func TestFakedSyncProgress66WhitelistMatch(t *testing.T) {
+ t.Parallel()
+
protocol := uint(eth.ETH66)
mode := FullSync
@@ -1474,6 +1488,8 @@ func TestFakedSyncProgress66WhitelistMatch(t *testing.T) {
// checkpointed blocks with opposite peer, the sync should fail initially but
// with the retry mechanism, it should succeed eventually.
func TestFakedSyncProgress66NoRemoteCheckpoint(t *testing.T) {
+ t.Parallel()
+
protocol := uint(eth.ETH66)
mode := FullSync
@@ -1483,8 +1499,10 @@ func TestFakedSyncProgress66NoRemoteCheckpoint(t *testing.T) {
if count == 0 {
return false, whitelist.ErrNoRemoteCheckoint
}
+
return true, nil
}
+
tester.downloader.ChainValidator = newWhitelistFake(validate)
defer tester.terminate()
diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go
index 428e3cb706..872bfcd1a9 100644
--- a/eth/downloader/queue_test.go
+++ b/eth/downloader/queue_test.go
@@ -65,9 +65,9 @@ type chainData struct {
}
var (
- chain *chainData
+ chain *chainData
chainLongerFork *chainData
- emptyChain *chainData
+ emptyChain *chainData
)
func init() {
@@ -78,7 +78,7 @@ func init() {
blocks, _ = makeChain(targetBlocks, 0, genesis, true)
emptyChain = &chainData{blocks, 0}
-
+
chainLongerForkBlocks, _ := makeChain(1024, 0, blocks[len(blocks)-1], false)
chainLongerFork = &chainData{chainLongerForkBlocks, 0}
}
diff --git a/eth/downloader/whitelist/service.go b/eth/downloader/whitelist/service.go
index c3b6ad6462..7036f24a8f 100644
--- a/eth/downloader/whitelist/service.go
+++ b/eth/downloader/whitelist/service.go
@@ -36,7 +36,7 @@ var (
func (w *Service) IsValidChain(remoteHeader *types.Header, fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
// We want to validate the chain by comparing the last checkpointed block
// we're storing in `checkpointWhitelist` with the peer's block.
-
+ //
// Check for availaibility of the last checkpointed block.
// This can be also be empty if our heimdall is not responding
// or we're running without it.
diff --git a/eth/downloader/whitelist/service_test.go b/eth/downloader/whitelist/service_test.go
index 79a92da826..ca202cc3ad 100644
--- a/eth/downloader/whitelist/service_test.go
+++ b/eth/downloader/whitelist/service_test.go
@@ -5,9 +5,10 @@ import (
"math/big"
"testing"
+ "gotest.tools/assert"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "gotest.tools/assert"
)
// NewMockService creates a new mock whitelist service
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index cb0c5a0aae..091600d8b5 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -29,6 +29,9 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/bor"
+ "github.com/ethereum/go-ethereum/consensus/bor/contract"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
@@ -237,7 +240,14 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, et
// In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config
// Then, bor != nil will also be enabled for ethash and clique. Only enable Bor for real if there is a validator contract present.
if chainConfig.Bor != nil && chainConfig.Bor.ValidatorContract != "" {
- return bor.New(chainConfig, db, blockchainAPI, ethConfig.HeimdallURL, ethConfig.WithoutHeimdall)
+ genesisContractsClient := contract.NewGenesisContractsClient(chainConfig, chainConfig.Bor.ValidatorContract, chainConfig.Bor.StateReceiverContract, blockchainAPI)
+ spanner := span.NewChainSpanner(blockchainAPI, contract.ValidatorSet(), chainConfig, common.HexToAddress(chainConfig.Bor.ValidatorContract))
+
+ if ethConfig.WithoutHeimdall {
+ return bor.New(chainConfig, db, blockchainAPI, spanner, nil, genesisContractsClient)
+ } else {
+ return bor.New(chainConfig, db, blockchainAPI, spanner, heimdall.NewHeimdallClient(ethConfig.HeimdallURL), genesisContractsClient)
+ }
} else {
switch config.PowMode {
case ethash.ModeFake:
diff --git a/eth/handler.go b/eth/handler.go
index 96eb3dc7be..ab95f5f769 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -86,7 +86,7 @@ type handlerConfig struct {
Network uint64 // Network identifier to adfvertise
Sync downloader.SyncMode // Whether to snap or full sync
BloomCache uint64 // Megabytes to alloc for snap sync bloom
- EventMux *event.TypeMux // Legacy event mux, deprecate for `feed`
+ EventMux *event.TypeMux //nolint:staticcheck // Legacy event mux, deprecate for `feed`
Checkpoint *params.TrustedCheckpoint // Hard coded checkpoint for sync challenges
EthAPI *ethapi.PublicBlockChainAPI // EthAPI to interact
diff --git a/eth/tracers/api_bor.go b/eth/tracers/api_bor.go
new file mode 100644
index 0000000000..6ab1a4290a
--- /dev/null
+++ b/eth/tracers/api_bor.go
@@ -0,0 +1,150 @@
+package tracers
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers/logger"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+type BlockTraceResult struct {
+ // Trace of each transaction executed
+ Transactions []*TxTraceResult `json:"transactions,omitempty"`
+
+ // Block that we are executing on the trace
+ Block interface{} `json:"block"`
+}
+
+type TxTraceResult struct {
+ // Trace results produced by the tracer
+ Result interface{} `json:"result,omitempty"`
+
+ // Trace failure produced by the tracer
+ Error string `json:"error,omitempty"`
+
+ // IntermediateHash of the execution if succeeds
+ IntermediateHash common.Hash `json:"intermediatehash"`
+}
+
+func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *TraceConfig) (*BlockTraceResult, error) {
+ if block.NumberU64() == 0 {
+ return nil, fmt.Errorf("genesis is not traceable")
+ }
+
+ res := &BlockTraceResult{
+ Block: block,
+ }
+
+ // block object cannot be converted to JSON since much of the fields are non-public
+ blockFields, err := ethapi.RPCMarshalBlock(block, true, true, api.backend.ChainConfig())
+ if err != nil {
+ return nil, err
+ }
+
+ res.Block = blockFields
+
+ parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
+ if err != nil {
+ return nil, err
+ }
+
+ reexec := defaultTraceReexec
+ if config != nil && config.Reexec != nil {
+ reexec = *config.Reexec
+ }
+
+ // TODO: discuss consequences of setting preferDisk false.
+ statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
+ if err != nil {
+ return nil, err
+ }
+
+ // Execute all the transaction contained within the block concurrently
+ var (
+ signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
+ txs = block.Transactions()
+ deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number())
+ )
+
+ blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
+
+ traceTxn := func(indx int, tx *types.Transaction) *TxTraceResult {
+ message, _ := tx.AsMessage(signer, block.BaseFee())
+ txContext := core.NewEVMTxContext(message)
+
+ tracer := logger.NewStructLogger(config.Config)
+
+ // Run the transaction with tracing enabled.
+ vmenv := vm.NewEVM(blockCtx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Debug: true, Tracer: tracer, NoBaseFee: true})
+
+ // Call Prepare to clear out the statedb access list
+ // Not sure if we need to do this
+ statedb.Prepare(tx.Hash(), indx)
+
+ execRes, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
+ if err != nil {
+ return &TxTraceResult{
+ Error: err.Error(),
+ }
+ }
+
+ returnVal := fmt.Sprintf("%x", execRes.Return())
+ if len(execRes.Revert()) > 0 {
+ returnVal = fmt.Sprintf("%x", execRes.Revert())
+ }
+
+ result := ðapi.ExecutionResult{
+ Gas: execRes.UsedGas,
+ Failed: execRes.Failed(),
+ ReturnValue: returnVal,
+ StructLogs: ethapi.FormatLogs(tracer.StructLogs()),
+ }
+ res := &TxTraceResult{
+ Result: result,
+ IntermediateHash: statedb.IntermediateRoot(deleteEmptyObjects),
+ }
+
+ return res
+ }
+
+ for indx, tx := range txs {
+ res.Transactions = append(res.Transactions, traceTxn(indx, tx))
+ }
+
+ return res, nil
+}
+
+type TraceBlockRequest struct {
+ Number int64
+ Hash string
+ IsBadBlock bool
+ Config *TraceConfig
+}
+
+// If you use context as first parameter this function gets exposed automaticall on rpc endpoint
+func (api *API) TraceBorBlock(req *TraceBlockRequest) (*BlockTraceResult, error) {
+ ctx := context.Background()
+
+ var blockNumber rpc.BlockNumber
+ if req.Number == -1 {
+ blockNumber = rpc.LatestBlockNumber
+ } else {
+ blockNumber = rpc.BlockNumber(req.Number)
+ }
+
+ log.Debug("Tracing Bor Block", "block number", blockNumber)
+
+ block, err := api.blockByNumber(ctx, blockNumber)
+ if err != nil {
+ return nil, err
+ }
+
+ return api.traceBorBlock(ctx, block, req.Config)
+}
diff --git a/go.mod b/go.mod
index 176df53a40..1b452a67a1 100644
--- a/go.mod
+++ b/go.mod
@@ -1,10 +1,9 @@
module github.com/ethereum/go-ethereum
-go 1.16
+go 1.18
require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
- github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/VictoriaMetrics/fastcache v1.6.0
github.com/aws/aws-sdk-go-v2 v1.2.0
github.com/aws/aws-sdk-go-v2/config v1.1.1
@@ -16,19 +15,15 @@ require (
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f
github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set v1.8.0
- github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48
github.com/edsrzf/mmap-go v1.0.0
github.com/fatih/color v1.7.0
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
- github.com/go-kit/kit v0.9.0 // indirect
- github.com/go-logfmt/logfmt v0.5.0 // indirect
- github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-stack/stack v1.8.0
github.com/golang-jwt/jwt/v4 v4.3.0
- github.com/golang/mock v1.3.1
+ github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.4
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa
@@ -44,18 +39,15 @@ require (
github.com/imdario/mergo v0.3.11
github.com/influxdata/influxdb v1.8.3
github.com/influxdata/influxdb-client-go/v2 v2.4.0
- github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/jackpal/go-nat-pmp v1.0.2
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
github.com/julienschmidt/httprouter v1.3.0
github.com/karalabe/usb v0.0.2
- github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.8
github.com/mattn/go-isatty v0.0.12
github.com/mitchellh/cli v1.1.2
github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0
github.com/mitchellh/go-homedir v1.1.0
- github.com/naoina/go-stringutil v0.1.0 // indirect
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
github.com/olekukonko/tablewriter v0.0.5
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7
@@ -67,22 +59,81 @@ require (
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
github.com/stretchr/testify v1.7.0
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
- github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
github.com/xsleonard/go-merkle v1.1.0
go.opentelemetry.io/otel v1.2.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0
go.opentelemetry.io/otel/sdk v1.2.0
- golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
+ go.uber.org/goleak v1.1.12
+ golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
- golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912
+ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6
golang.org/x/text v0.3.7
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
- golang.org/x/tools v0.1.0
+ golang.org/x/tools v0.1.10
google.golang.org/grpc v1.42.0
google.golang.org/protobuf v1.27.1
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
gopkg.in/urfave/cli.v1 v1.20.0
gotest.tools v2.2.0+incompatible
+ pgregory.net/rapid v0.4.7
+)
+
+require (
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect
+ github.com/Masterminds/goutils v1.1.0 // indirect
+ github.com/Masterminds/semver v1.5.0 // indirect
+ github.com/Masterminds/sprig v2.22.0+incompatible // indirect
+ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
+ github.com/agext/levenshtein v1.2.1 // indirect
+ github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
+ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
+ github.com/aws/smithy-go v1.1.0 // indirect
+ github.com/bgentry/speakeasy v0.1.0 // indirect
+ github.com/cenkalti/backoff/v4 v4.1.1 // indirect
+ github.com/cespare/xxhash/v2 v2.1.1 // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
+ github.com/deepmap/oapi-codegen v1.8.2 // indirect
+ github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
+ github.com/go-kit/kit v0.9.0 // indirect
+ github.com/go-logfmt/logfmt v0.5.0 // indirect
+ github.com/go-ole/go-ole v1.2.1 // indirect
+ github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
+ github.com/google/go-cmp v0.5.8 // indirect
+ github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
+ github.com/hashicorp/errwrap v1.0.0 // indirect
+ github.com/hashicorp/go-multierror v1.0.0 // indirect
+ github.com/huandu/xstrings v1.3.2 // indirect
+ github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
+ github.com/kylelemons/godebug v1.1.0 // indirect
+ github.com/mattn/go-runewidth v0.0.9 // indirect
+ github.com/mitchellh/copystructure v1.0.0 // indirect
+ github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
+ github.com/mitchellh/mapstructure v1.4.1 // indirect
+ github.com/mitchellh/pointerstructure v1.2.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.0 // indirect
+ github.com/naoina/go-stringutil v0.1.0 // indirect
+ github.com/opentracing/opentracing-go v1.1.0 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/posener/complete v1.1.1 // indirect
+ github.com/tklauser/go-sysconf v0.3.5 // indirect
+ github.com/tklauser/numcpus v0.2.2 // indirect
+ github.com/zclconf/go-cty v1.8.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect
+ go.opentelemetry.io/otel/trace v1.2.0 // indirect
+ go.opentelemetry.io/proto/otlp v0.10.0 // indirect
+ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
+ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
+ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
+ golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
+ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
diff --git a/go.sum b/go.sum
index ec2f200044..374ab3066e 100644
--- a/go.sum
+++ b/go.sum
@@ -49,7 +49,6 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
-github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
@@ -82,14 +81,12 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2
github.com/btcsuite/btcd/btcec/v2 v2.1.2 h1:YoYoC9J0jwfukodSBMzZYUVQ8PTiYg4BnOWiJVzTmLs=
github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q=
-github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -194,8 +191,9 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -229,8 +227,9 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -448,7 +447,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -479,6 +477,7 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut
github.com/xsleonard/go-merkle v1.1.0 h1:fHe1fuhJjGH22ZzVTAH0jqHLhTGhOq3wQjJN+8P0jQg=
github.com/xsleonard/go-merkle v1.1.0/go.mod h1:cW4z+UZ/4f2n9IJgIiyDCdYguchoDyDAPmpuOWGxdGg=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
@@ -500,6 +499,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
go.opentelemetry.io/proto/otlp v0.10.0 h1:n7brgtEbDvXEgGyKKo8SobKT1e9FewlDtXzkVP5djoE=
go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
+go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -512,8 +513,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8=
+golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -534,6 +536,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -541,8 +544,9 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -568,9 +572,11 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -620,11 +626,13 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU=
-golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -668,13 +676,17 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
+golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
+golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
@@ -770,5 +782,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
+pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g=
+pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/integration-tests/smoke_test.sh b/integration-tests/smoke_test.sh
new file mode 100644
index 0000000000..6f41aa5c16
--- /dev/null
+++ b/integration-tests/smoke_test.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+set -e
+
+delay=600
+
+echo "Wait ${delay} seconds for state-sync..."
+sleep $delay
+
+
+balance=$(docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'Math.round(web3.fromWei(eth.getBalance(eth.accounts[0])))'")
+
+if ! [[ "$balance" =~ ^[0-9]+$ ]]; then
+ echo "Something is wrong! Can't find the balance of first account in bor network."
+ exit 1
+fi
+
+echo "Found matic balance on account[0]: " $balance
+
+if (( $balance <= 1001 )); then
+ echo "Balance in bor network has not increased. This indicates that something is wrong with state sync."
+ exit 1
+fi
+
+checkpointID=$(curl -sL http://localhost:1317/checkpoints/latest | jq .result.id)
+
+if [ $checkpointID == "null" ]; then
+ echo "Something is wrong! Could not find any checkpoint."
+ exit 1
+else
+ echo "Found checkpoint ID:" $checkpointID
+fi
+
+echo "All tests have passed!"
\ No newline at end of file
diff --git a/internal/cli/account.go b/internal/cli/account.go
index b8661821d0..bb8b30b892 100644
--- a/internal/cli/account.go
+++ b/internal/cli/account.go
@@ -1,11 +1,28 @@
package cli
-import "github.com/mitchellh/cli"
+import (
+ "strings"
+
+ "github.com/mitchellh/cli"
+)
type Account struct {
UI cli.Ui
}
+// MarkDown implements cli.MarkDown interface
+func (a *Account) MarkDown() string {
+ items := []string{
+ "# Account",
+ "The ```account``` command groups actions to interact with accounts:",
+ "- [```account new```](./account_new.md): Create a new account in the Bor client.",
+ "- [```account list```](./account_list.md): List the wallets in the Bor client.",
+ "- [```account import```](./account_import.md): Import an account to the Bor client.",
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (a *Account) Help() string {
return `Usage: bor account
diff --git a/internal/cli/account_import.go b/internal/cli/account_import.go
index 8c9ff40e58..a3f65ab512 100644
--- a/internal/cli/account_import.go
+++ b/internal/cli/account_import.go
@@ -2,6 +2,7 @@ package cli
import (
"fmt"
+ "strings"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/crypto"
@@ -12,6 +13,17 @@ type AccountImportCommand struct {
*Meta
}
+// MarkDown implements cli.MarkDown interface
+func (a *AccountImportCommand) MarkDown() string {
+ items := []string{
+ "# Account import",
+ "The ```account import``` command imports an account in Json format to the Bor data directory.",
+ a.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (a *AccountImportCommand) Help() string {
return `Usage: bor account import
@@ -47,7 +59,9 @@ func (a *AccountImportCommand) Run(args []string) int {
a.UI.Error("Expected one argument")
return 1
}
+
key, err := crypto.LoadECDSA(args[0])
+
if err != nil {
a.UI.Error(fmt.Sprintf("Failed to load the private key '%s': %v", args[0], err))
return 1
@@ -69,6 +83,8 @@ func (a *AccountImportCommand) Run(args []string) int {
if err != nil {
utils.Fatalf("Could not create the account: %v", err)
}
+
a.UI.Output(fmt.Sprintf("Account created: %s", acct.Address.String()))
+
return 0
}
diff --git a/internal/cli/account_list.go b/internal/cli/account_list.go
index 360d41b558..854934c447 100644
--- a/internal/cli/account_list.go
+++ b/internal/cli/account_list.go
@@ -2,6 +2,7 @@ package cli
import (
"fmt"
+ "strings"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
@@ -11,6 +12,17 @@ type AccountListCommand struct {
*Meta
}
+// MarkDown implements cli.MarkDown interface
+func (a *AccountListCommand) MarkDown() string {
+ items := []string{
+ "# Account list",
+ "The `account list` command lists all the accounts in the Bor data directory.",
+ a.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (a *AccountListCommand) Help() string {
return `Usage: bor account list
@@ -42,7 +54,9 @@ func (a *AccountListCommand) Run(args []string) int {
a.UI.Error(fmt.Sprintf("Failed to get keystore: %v", err))
return 1
}
+
a.UI.Output(formatAccounts(keystore.Accounts()))
+
return 0
}
@@ -53,10 +67,12 @@ func formatAccounts(accts []accounts.Account) string {
rows := make([]string, len(accts)+1)
rows[0] = "Index|Address"
+
for i, d := range accts {
rows[i+1] = fmt.Sprintf("%d|%s",
i,
d.Address.String())
}
+
return formatList(rows)
}
diff --git a/internal/cli/account_new.go b/internal/cli/account_new.go
index 3334384cb0..aef272a389 100644
--- a/internal/cli/account_new.go
+++ b/internal/cli/account_new.go
@@ -2,6 +2,7 @@ package cli
import (
"fmt"
+ "strings"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
)
@@ -10,6 +11,17 @@ type AccountNewCommand struct {
*Meta
}
+// MarkDown implements cli.MarkDown interface
+func (a *AccountNewCommand) MarkDown() string {
+ items := []string{
+ "# Account new",
+ "The `account new` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command.",
+ a.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (a *AccountNewCommand) Help() string {
return `Usage: bor account new
diff --git a/internal/cli/attach.go b/internal/cli/attach.go
new file mode 100644
index 0000000000..134a282180
--- /dev/null
+++ b/internal/cli/attach.go
@@ -0,0 +1,193 @@
+package cli
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/cmd/utils"
+ "github.com/ethereum/go-ethereum/console"
+ "github.com/ethereum/go-ethereum/internal/cli/flagset"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/rpc"
+
+ "github.com/mitchellh/cli"
+)
+
+// AttachCommand is the command to Connect to remote Bor IPC console
+type AttachCommand struct {
+ UI cli.Ui
+ Meta *Meta
+ Meta2 *Meta2
+ ExecCMD string
+ Endpoint string
+ PreloadJSFlag string
+ JSpathFlag string
+}
+
+// MarkDown implements cli.MarkDown interface
+func (c *AttachCommand) MarkDown() string {
+ items := []string{
+ "# Attach",
+ "Connect to remote Bor IPC console.",
+ c.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
+// Help implements the cli.Command interface
+func (c *AttachCommand) Help() string {
+ return `Usage: bor attach
+
+ Connect to remote Bor IPC console.`
+}
+
+// Synopsis implements the cli.Command interface
+func (c *AttachCommand) Synopsis() string {
+ return "Connect to Bor via IPC"
+}
+
+func (c *AttachCommand) Flags() *flagset.Flagset {
+ f := flagset.NewFlagSet("attach")
+
+ f.StringFlag(&flagset.StringFlag{
+ Name: "exec",
+ Usage: "Command to run in remote console",
+ Value: &c.ExecCMD,
+ })
+
+ f.StringFlag(&flagset.StringFlag{
+ Name: "preload",
+ Usage: "Comma separated list of JavaScript files to preload into the console",
+ Value: &c.PreloadJSFlag,
+ })
+
+ f.StringFlag(&flagset.StringFlag{
+ Name: "jspath",
+ Usage: "JavaScript root path for `loadScript`",
+ Value: &c.JSpathFlag,
+ })
+
+ return f
+}
+
+// Run implements the cli.Command interface
+func (c *AttachCommand) Run(args []string) int {
+ flags := c.Flags()
+
+ //check if first arg is flag or IPC location
+ if len(args) == 0 {
+ args = append(args, "")
+ }
+
+ if args[0] != "" && strings.HasPrefix(args[0], "--") {
+ if err := flags.Parse(args); err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+ } else {
+ c.Endpoint = args[0]
+ if err := flags.Parse(args[1:]); err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+ }
+
+ if err := c.remoteConsole(); err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ return 0
+}
+
+// remoteConsole will connect to a remote bor instance, attaching a JavaScript
+// console to it.
+// nolint: unparam
+func (c *AttachCommand) remoteConsole() error {
+ // Attach to a remotely running geth instance and start the JavaScript console
+ path := node.DefaultDataDir()
+
+ if c.Endpoint == "" {
+ if c.Meta.dataDir != "" {
+ path = c.Meta.dataDir
+ }
+
+ if path != "" {
+ homeDir, _ := os.UserHomeDir()
+ path = filepath.Join(homeDir, "/.bor/data")
+ }
+
+ c.Endpoint = fmt.Sprintf("%s/bor.ipc", path)
+ }
+
+ client, err := dialRPC(c.Endpoint)
+
+ if err != nil {
+ utils.Fatalf("Unable to attach to remote bor: %v", err)
+ }
+
+ config := console.Config{
+ DataDir: path,
+ DocRoot: c.JSpathFlag,
+ Client: client,
+ Preload: c.makeConsolePreloads(),
+ }
+
+ console, err := console.New(config)
+ if err != nil {
+ utils.Fatalf("Failed to start the JavaScript console: %v", err)
+ }
+
+ defer func() {
+ if err := console.Stop(false); err != nil {
+ c.UI.Error(err.Error())
+ }
+ }()
+
+ if c.ExecCMD != "" {
+ console.Evaluate(c.ExecCMD)
+ return nil
+ }
+
+ // Otherwise print the welcome screen and enter interactive mode
+ console.Welcome()
+ console.Interactive()
+
+ return nil
+}
+
+// dialRPC returns a RPC client which connects to the given endpoint.
+// The check for empty endpoint implements the defaulting logic
+// for "geth attach" with no argument.
+func dialRPC(endpoint string) (*rpc.Client, error) {
+ if endpoint == "" {
+ endpoint = node.DefaultIPCEndpoint("bor")
+ } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
+ // Backwards compatibility with geth < 1.5 which required
+ // these prefixes.
+ endpoint = endpoint[4:]
+ }
+
+ return rpc.Dial(endpoint)
+}
+
+// MakeConsolePreloads retrieves the absolute paths for the console JavaScript
+// scripts to preload before starting.
+func (c *AttachCommand) makeConsolePreloads() []string {
+ // Skip preloading if there's nothing to preload
+ if c.PreloadJSFlag == "" {
+ return nil
+ }
+ // Otherwise resolve absolute paths and return them
+ splitFlags := strings.Split(c.PreloadJSFlag, ",")
+ preloads := make([]string, 0, len(splitFlags))
+
+ for _, file := range splitFlags {
+ preloads = append(preloads, strings.TrimSpace(file))
+ }
+
+ return preloads
+}
diff --git a/internal/cli/bootnode.go b/internal/cli/bootnode.go
new file mode 100644
index 0000000000..9e1a0fcde9
--- /dev/null
+++ b/internal/cli/bootnode.go
@@ -0,0 +1,230 @@
+package cli
+
+import (
+ "crypto/ecdsa"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/signal"
+ "path/filepath"
+ "strings"
+ "syscall"
+
+ "github.com/ethereum/go-ethereum/cmd/utils"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/internal/cli/flagset"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/p2p/discover"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/ethereum/go-ethereum/p2p/nat"
+
+ "github.com/mitchellh/cli"
+)
+
+type BootnodeCommand struct {
+ UI cli.Ui
+
+ listenAddr string
+ v5 bool
+ logLevel string
+ nat string
+ nodeKey string
+ saveKey string
+ dryRun bool
+}
+
+// Help implements the cli.Command interface
+func (b *BootnodeCommand) Help() string {
+ return `Usage: bor bootnode`
+}
+
+// MarkDown implements cli.MarkDown interface
+func (c *BootnodeCommand) MarkDown() string {
+ items := []string{
+ "# Bootnode",
+ c.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
+func (b *BootnodeCommand) Flags() *flagset.Flagset {
+ flags := flagset.NewFlagSet("bootnode")
+
+ flags.StringFlag(&flagset.StringFlag{
+ Name: "listen-addr",
+ Default: "0.0.0.0:30303",
+ Usage: "listening address of bootnode (:)",
+ Value: &b.listenAddr,
+ })
+ flags.BoolFlag(&flagset.BoolFlag{
+ Name: "v5",
+ Default: false,
+ Usage: "Enable UDP v5",
+ Value: &b.v5,
+ })
+ flags.StringFlag(&flagset.StringFlag{
+ Name: "log-level",
+ Default: "info",
+ Usage: "Log level (trace|debug|info|warn|error|crit)",
+ Value: &b.logLevel,
+ })
+ flags.StringFlag(&flagset.StringFlag{
+ Name: "nat",
+ Default: "none",
+ Usage: "port mapping mechanism (any|none|upnp|pmp|extip:)",
+ Value: &b.nat,
+ })
+ flags.StringFlag(&flagset.StringFlag{
+ Name: "node-key",
+ Default: "",
+ Usage: "file or hex node key",
+ Value: &b.nodeKey,
+ })
+ flags.StringFlag(&flagset.StringFlag{
+ Name: "save-key",
+ Default: "",
+ Usage: "path to save the ecdsa private key",
+ Value: &b.saveKey,
+ })
+ flags.BoolFlag(&flagset.BoolFlag{
+ Name: "dry-run",
+ Default: false,
+ Usage: "validates parameters and prints bootnode configurations, but does not start bootnode",
+ Value: &b.dryRun,
+ })
+
+ return flags
+}
+
+// Synopsis implements the cli.Command interface
+func (b *BootnodeCommand) Synopsis() string {
+ return "Start a bootnode"
+}
+
+// Run implements the cli.Command interface
+// nolint: gocognit
+func (b *BootnodeCommand) Run(args []string) int {
+ flags := b.Flags()
+ if err := flags.Parse(args); err != nil {
+ b.UI.Error(err.Error())
+ return 1
+ }
+
+ glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
+
+ lvl, err := log.LvlFromString(strings.ToLower(b.logLevel))
+ if err == nil {
+ glogger.Verbosity(lvl)
+ } else {
+ glogger.Verbosity(log.LvlInfo)
+ }
+
+ log.Root().SetHandler(glogger)
+
+ natm, err := nat.Parse(b.nat)
+ if err != nil {
+ b.UI.Error(fmt.Sprintf("failed to parse nat: %v", err))
+ return 1
+ }
+
+ // create a one time key
+ var nodeKey *ecdsa.PrivateKey
+ // nolint: nestif
+ if b.nodeKey != "" {
+ // try to read the key either from file or command line
+ if _, err := os.Stat(b.nodeKey); errors.Is(err, os.ErrNotExist) {
+ if nodeKey, err = crypto.HexToECDSA(b.nodeKey); err != nil {
+ b.UI.Error(fmt.Sprintf("failed to parse hex address: %v", err))
+ return 1
+ }
+ } else {
+ if nodeKey, err = crypto.LoadECDSA(b.nodeKey); err != nil {
+ b.UI.Error(fmt.Sprintf("failed to load node key: %v", err))
+ return 1
+ }
+ }
+ } else {
+ // generate a new temporal key
+ if nodeKey, err = crypto.GenerateKey(); err != nil {
+ b.UI.Error(fmt.Sprintf("could not generate key: %v", err))
+ return 1
+ }
+ if b.saveKey != "" {
+ path := b.saveKey
+
+ // save the private key
+ if err = crypto.SaveECDSA(filepath.Join(path, "priv.key"), nodeKey); err != nil {
+ b.UI.Error(fmt.Sprintf("failed to write node priv key: %v", err))
+ return 1
+ }
+ // save the public key
+ pubRaw := fmt.Sprintf("%x", crypto.FromECDSAPub(&nodeKey.PublicKey)[1:])
+ if err := ioutil.WriteFile(filepath.Join(path, "pub.key"), []byte(pubRaw), 0600); err != nil {
+ b.UI.Error(fmt.Sprintf("failed to write node pub key: %v", err))
+ return 1
+ }
+ }
+ }
+
+ addr, err := net.ResolveUDPAddr("udp", b.listenAddr)
+ if err != nil {
+ b.UI.Error(fmt.Sprintf("could not resolve udp addr '%s': %v", b.listenAddr, err))
+ return 1
+ }
+
+ conn, err := net.ListenUDP("udp", addr)
+
+ if err != nil {
+ b.UI.Error(fmt.Sprintf("failed to listen udp addr '%s': %v", b.listenAddr, err))
+ return 1
+ }
+
+ realaddr := conn.LocalAddr().(*net.UDPAddr)
+ if natm != nil {
+ if !realaddr.IP.IsLoopback() {
+ go nat.Map(natm, nil, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
+ }
+
+ if ext, err := natm.ExternalIP(); err == nil {
+ // nolint: govet
+ realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
+ }
+ }
+
+ n := enode.NewV4(&nodeKey.PublicKey, addr.IP, addr.Port, addr.Port)
+ b.UI.Info(n.String())
+
+ if b.dryRun {
+ return 0
+ }
+
+ db, _ := enode.OpenDB("")
+ ln := enode.NewLocalNode(db, nodeKey)
+ cfg := discover.Config{
+ PrivateKey: nodeKey,
+ Log: log.Root(),
+ }
+
+ if b.v5 {
+ if _, err := discover.ListenV5(conn, ln, cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ } else {
+ if _, err := discover.ListenUDP(conn, ln, cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+
+ signalCh := make(chan os.Signal, 4)
+ signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
+
+ sig := <-signalCh
+
+ b.UI.Output(fmt.Sprintf("Caught signal: %v", sig))
+ b.UI.Output("Gracefully shutting down agent...")
+
+ return 0
+}
diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go
new file mode 100644
index 0000000000..4e21f02956
--- /dev/null
+++ b/internal/cli/bor_fingerprint.go
@@ -0,0 +1,188 @@
+package cli
+
+import (
+ "fmt"
+ "math"
+ "os/exec"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/params"
+
+ "github.com/mitchellh/cli"
+ "github.com/shirou/gopsutil/cpu"
+ "github.com/shirou/gopsutil/disk"
+ "github.com/shirou/gopsutil/host"
+ "github.com/shirou/gopsutil/mem"
+)
+
+// VersionCommand is the command to show the version of the agent
+type FingerprintCommand struct {
+ UI cli.Ui
+}
+
+// MarkDown implements cli.MarkDown interface
+func (c *FingerprintCommand) MarkDown() string {
+ items := []string{
+ "# Fingerprint",
+ "Display the system fingerprint",
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
+// Help implements the cli.Command interface
+func (c *FingerprintCommand) Help() string {
+ return `Usage: bor fingerprint
+
+ Display the system fingerprint`
+}
+
+// Synopsis implements the cli.Command interface
+func (c *FingerprintCommand) Synopsis() string {
+ return "Display the system fingerprint"
+}
+
+func getCoresCount(cp []cpu.InfoStat) int {
+ cores := 0
+ for i := 0; i < len(cp); i++ {
+ cores += int(cp[i].Cores)
+ }
+
+ return cores
+}
+
+type MemoryDetails struct {
+ TotalMem float64 `json:"totalMem"`
+ FreeMem float64 `json:"freeMem"`
+ UsedMem float64 `json:"usedMem"`
+}
+
+type DiskDetails struct {
+ TotalDisk float64 `json:"totalDisk"`
+ FreeDisk float64 `json:"freeDisk"`
+ UsedDisk float64 `json:"usedDisk"`
+}
+
+type BorFingerprint struct {
+ CoresCount int `json:"coresCount"`
+ OsName string `json:"osName"`
+ OsVer string `json:"osVer"`
+ DiskDetails *DiskDetails `json:"diskDetails"`
+ MemoryDetails *MemoryDetails `json:"memoryDetails"`
+}
+
+func formatFingerprint(borFingerprint *BorFingerprint) string {
+ base := formatKV([]string{
+ fmt.Sprintf("Bor Version : %s", params.VersionWithMeta),
+ fmt.Sprintf("CPU : %d cores", borFingerprint.CoresCount),
+ fmt.Sprintf("OS : %s %s ", borFingerprint.OsName, borFingerprint.OsVer),
+ fmt.Sprintf("RAM :: total : %v GB, free : %v GB, used : %v GB", borFingerprint.MemoryDetails.TotalMem, borFingerprint.MemoryDetails.FreeMem, borFingerprint.MemoryDetails.UsedMem),
+ fmt.Sprintf("STORAGE :: total : %v GB, free : %v GB, used : %v GB", borFingerprint.DiskDetails.TotalDisk, borFingerprint.DiskDetails.FreeDisk, borFingerprint.DiskDetails.UsedDisk),
+ })
+
+ return base
+}
+
+func convertBytesToGB(bytesValue uint64) float64 {
+ return math.Floor(float64(bytesValue)/(1024*1024*1024)*100) / 100
+}
+
+// Checks if fio exists on the node
+func (c *FingerprintCommand) checkFio() error {
+ cmd := exec.Command("/bin/sh", "-c", "fio -v")
+
+ _, err := cmd.CombinedOutput()
+ if err != nil {
+ message := "\nFio package not installed. Install Fio for IOPS Benchmarking :\n\nDebianOS : 'sudo apt-get update && sudo apt-get install fio -y'\nAWS AMI/CentOS : 'sudo yum install fio -y'\nOracle LinuxOS : 'sudo dnf install fio -y'\n"
+ c.UI.Output(message)
+
+ return err
+ }
+
+ return nil
+}
+
+// Run the IOPS benchmark for the node
+func (c *FingerprintCommand) benchmark() error {
+ var b []byte
+
+ err := c.checkFio()
+
+ if err != nil {
+ // Missing Fio is not a fatal error. A message will be logged in console when it is missing in "checkFio()".
+ return nil //nolint:nilerr
+ }
+
+ c.UI.Output("\nRunning a 10 second test...\n")
+
+ cmd := exec.Command("/bin/sh", "-c", "sudo fio --filename=/file --size=2GB --direct=1 --rw=randrw --bs=64k --ioengine=libaio --iodepth=64 --runtime=10 --numjobs=4 --time_based --group_reporting --name=throughput-test-job --eta-newline=1 | grep -e 'read:' -e 'write:' | awk '{print $1,$2}' ")
+
+ b, err = cmd.CombinedOutput()
+ if err != nil {
+ return err
+ }
+
+ out := string(b)
+ c.UI.Output(out)
+
+ return nil
+}
+
+// Run implements the cli.Command interface
+func (c *FingerprintCommand) Run(args []string) int {
+ v, err := mem.VirtualMemory()
+ if err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ h, err := host.Info()
+ if err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ cp, err := cpu.Info()
+ if err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ d, err := disk.Usage("/")
+ if err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ diskDetails := &DiskDetails{
+ TotalDisk: convertBytesToGB(d.Total),
+ FreeDisk: convertBytesToGB(d.Free),
+ UsedDisk: convertBytesToGB(d.Used),
+ }
+
+ memoryDetails := &MemoryDetails{
+ TotalMem: convertBytesToGB(v.Total),
+ FreeMem: convertBytesToGB(v.Available),
+ UsedMem: convertBytesToGB(v.Used),
+ }
+
+ borFingerprint := &BorFingerprint{
+ CoresCount: getCoresCount(cp),
+ OsName: h.OS,
+ OsVer: h.Platform + " - " + h.PlatformVersion + " - " + h.KernelArch,
+ DiskDetails: diskDetails,
+ MemoryDetails: memoryDetails,
+ }
+
+ c.UI.Output(formatFingerprint(borFingerprint))
+
+ if borFingerprint.OsName == "linux" {
+ err = c.benchmark()
+ if err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+ }
+
+ return 0
+}
diff --git a/internal/cli/chain.go b/internal/cli/chain.go
index b43f22f999..9a7e9e8537 100644
--- a/internal/cli/chain.go
+++ b/internal/cli/chain.go
@@ -1,6 +1,8 @@
package cli
import (
+ "strings"
+
"github.com/mitchellh/cli"
)
@@ -9,6 +11,18 @@ type ChainCommand struct {
UI cli.Ui
}
+// MarkDown implements cli.MarkDown interface
+func (c *ChainCommand) MarkDown() string {
+ items := []string{
+ "# Chain",
+ "The ```chain``` command groups actions to interact with the blockchain in the client:",
+ "- [```chain sethead```](./chain_sethead.md): Set the current chain to a certain block.",
+ "- [```chain watch```](./chain_watch.md): Watch the chainHead, reorg and fork events in real-time.",
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (c *ChainCommand) Help() string {
return `Usage: bor chain
diff --git a/internal/cli/chain_sethead.go b/internal/cli/chain_sethead.go
index 127ac38f15..718ada4648 100644
--- a/internal/cli/chain_sethead.go
+++ b/internal/cli/chain_sethead.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"strconv"
+ "strings"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
@@ -16,6 +17,19 @@ type ChainSetHeadCommand struct {
yes bool
}
+// MarkDown implements cli.MarkDown interface
+func (a *ChainSetHeadCommand) MarkDown() string {
+ items := []string{
+ "# Chain sethead",
+ "The ```chain sethead ``` command sets the current chain to a certain block.",
+ "## Arguments",
+ "- ```number```: The block number to roll back.",
+ a.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (c *ChainSetHeadCommand) Help() string {
return `Usage: bor chain sethead [--yes]
@@ -32,6 +46,7 @@ func (c *ChainSetHeadCommand) Flags() *flagset.Flagset {
Default: false,
Value: &c.yes,
})
+
return flags
}
@@ -75,6 +90,7 @@ func (c *ChainSetHeadCommand) Run(args []string) int {
c.UI.Error(err.Error())
return 1
}
+
if response != "y" {
c.UI.Output("set head aborted")
return 0
@@ -87,5 +103,6 @@ func (c *ChainSetHeadCommand) Run(args []string) int {
}
c.UI.Output("Done!")
+
return 0
}
diff --git a/internal/cli/chain_watch.go b/internal/cli/chain_watch.go
index 9469c1df00..17a65a8d99 100644
--- a/internal/cli/chain_watch.go
+++ b/internal/cli/chain_watch.go
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/signal"
+ "strings"
"syscall"
"github.com/ethereum/go-ethereum/core"
@@ -17,6 +18,16 @@ type ChainWatchCommand struct {
*Meta2
}
+// MarkDown implements cli.MarkDown interface
+func (c *ChainWatchCommand) MarkDown() string {
+ items := []string{
+ "# Chain watch",
+ "The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.",
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (c *ChainWatchCommand) Help() string {
return `Usage: bor chain watch
@@ -60,7 +71,10 @@ func (c *ChainWatchCommand) Run(args []string) int {
go func() {
<-signalCh
- sub.CloseSend()
+
+ if err := sub.CloseSend(); err != nil {
+ c.UI.Error(err.Error())
+ }
}()
for {
@@ -70,6 +84,7 @@ func (c *ChainWatchCommand) Run(args []string) int {
c.UI.Output(err.Error())
break
}
+
c.UI.Output(formatHeadEvent(msg))
}
@@ -85,5 +100,6 @@ func formatHeadEvent(msg *proto.ChainWatchResponse) string {
} else if msg.Type == core.Chain2HeadReorgEvent {
out = fmt.Sprintf("Reorg Detected \nAdded : %v \nRemoved : %v", msg.Newchain, msg.Oldchain)
}
+
return out
}
diff --git a/internal/cli/command.go b/internal/cli/command.go
index d164791f80..1ff95b410f 100644
--- a/internal/cli/command.go
+++ b/internal/cli/command.go
@@ -9,18 +9,43 @@ import (
"github.com/ethereum/go-ethereum/internal/cli/server"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
"github.com/ethereum/go-ethereum/node"
+
"github.com/mitchellh/cli"
"github.com/ryanuber/columnize"
"google.golang.org/grpc"
)
+const (
+ emptyPlaceHolder = ""
+)
+
+type MarkDownCommand interface {
+ MarkDown
+ cli.Command
+}
+
+type MarkDownCommandFactory func() (MarkDownCommand, error)
+
func Run(args []string) int {
- commands := commands()
+ commands := Commands()
+
+ mappedCommands := make(map[string]cli.CommandFactory)
+
+ for k, v := range commands {
+ // Declare a new v to limit the scope of v to inside the block, so the anonymous function below
+ // can get the "current" value of v, instead of the value of last v in the loop.
+ // See this post: https://stackoverflow.com/questions/10116507/go-transfer-var-into-anonymous-function for more explanation
+ v := v
+ mappedCommands[k] = func() (cli.Command, error) {
+ cmd, err := v()
+ return cmd.(cli.Command), err
+ }
+ }
cli := &cli.CLI{
Name: "bor",
Args: args,
- Commands: commands,
+ Commands: mappedCommands,
}
exitCode, err := cli.Run()
@@ -28,10 +53,11 @@ func Run(args []string) int {
fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error())
return 1
}
+
return exitCode
}
-func commands() map[string]cli.CommandFactory {
+func Commands() map[string]MarkDownCommandFactory {
ui := &cli.BasicUi{
Reader: os.Stdin,
Writer: os.Stdout,
@@ -44,87 +70,115 @@ func commands() map[string]cli.CommandFactory {
meta := &Meta{
UI: ui,
}
- return map[string]cli.CommandFactory{
- "server": func() (cli.Command, error) {
+
+ return map[string]MarkDownCommandFactory{
+ "server": func() (MarkDownCommand, error) {
return &server.Command{
UI: ui,
}, nil
},
- "version": func() (cli.Command, error) {
+ "version": func() (MarkDownCommand, error) {
return &VersionCommand{
UI: ui,
}, nil
},
- "debug": func() (cli.Command, error) {
+ "debug": func() (MarkDownCommand, error) {
return &DebugCommand{
+ UI: ui,
+ }, nil
+ },
+ "debug pprof": func() (MarkDownCommand, error) {
+ return &DebugPprofCommand{
Meta2: meta2,
}, nil
},
- "chain": func() (cli.Command, error) {
+ "debug block": func() (MarkDownCommand, error) {
+ return &DebugBlockCommand{
+ Meta2: meta2,
+ }, nil
+ },
+ "chain": func() (MarkDownCommand, error) {
return &ChainCommand{
UI: ui,
}, nil
},
- "chain watch": func() (cli.Command, error) {
+ "chain watch": func() (MarkDownCommand, error) {
return &ChainWatchCommand{
Meta2: meta2,
}, nil
},
- "chain sethead": func() (cli.Command, error) {
+ "chain sethead": func() (MarkDownCommand, error) {
return &ChainSetHeadCommand{
Meta2: meta2,
}, nil
},
- "account": func() (cli.Command, error) {
+ "account": func() (MarkDownCommand, error) {
return &Account{
UI: ui,
}, nil
},
- "account new": func() (cli.Command, error) {
+ "account new": func() (MarkDownCommand, error) {
return &AccountNewCommand{
Meta: meta,
}, nil
},
- "account import": func() (cli.Command, error) {
+ "account import": func() (MarkDownCommand, error) {
return &AccountImportCommand{
Meta: meta,
}, nil
},
- "account list": func() (cli.Command, error) {
+ "account list": func() (MarkDownCommand, error) {
return &AccountListCommand{
Meta: meta,
}, nil
},
- "peers": func() (cli.Command, error) {
+ "peers": func() (MarkDownCommand, error) {
return &PeersCommand{
UI: ui,
}, nil
},
- "peers add": func() (cli.Command, error) {
+ "peers add": func() (MarkDownCommand, error) {
return &PeersAddCommand{
Meta2: meta2,
}, nil
},
- "peers remove": func() (cli.Command, error) {
+ "peers remove": func() (MarkDownCommand, error) {
return &PeersRemoveCommand{
Meta2: meta2,
}, nil
},
- "peers list": func() (cli.Command, error) {
+ "peers list": func() (MarkDownCommand, error) {
return &PeersListCommand{
Meta2: meta2,
}, nil
},
- "peers status": func() (cli.Command, error) {
+ "peers status": func() (MarkDownCommand, error) {
return &PeersStatusCommand{
Meta2: meta2,
}, nil
},
- "status": func() (cli.Command, error) {
+ "status": func() (MarkDownCommand, error) {
return &StatusCommand{
Meta2: meta2,
}, nil
},
+ "fingerprint": func() (MarkDownCommand, error) {
+ return &FingerprintCommand{
+ UI: ui,
+ }, nil
+ },
+ "attach": func() (MarkDownCommand, error) {
+ return &AttachCommand{
+ UI: ui,
+ Meta: meta,
+ Meta2: meta2,
+ }, nil
+ },
+ "bootnode": func() (MarkDownCommand, error) {
+ return &BootnodeCommand{
+ UI: ui,
+ }, nil
+ },
}
}
@@ -143,6 +197,7 @@ func (m *Meta2) NewFlagSet(n string) *flagset.Flagset {
Usage: "Address of the grpc endpoint",
Default: "127.0.0.1:3131",
})
+
return f
}
@@ -151,6 +206,7 @@ func (m *Meta2) Conn() (*grpc.ClientConn, error) {
if err != nil {
return nil, fmt.Errorf("failed to connect to server: %v", err)
}
+
return conn, nil
}
@@ -159,6 +215,7 @@ func (m *Meta2) BorConn() (proto.BorClient, error) {
if err != nil {
return nil, err
}
+
return proto.NewBorClient(conn), nil
}
@@ -206,18 +263,21 @@ func (m *Meta) GetKeystore() (*keystore.KeyStore, error) {
scryptP := keystore.StandardScryptP
keys := keystore.NewKeyStore(keydir, scryptN, scryptP)
+
return keys, nil
}
func formatList(in []string) string {
columnConf := columnize.DefaultConfig()
- columnConf.Empty = ""
+ columnConf.Empty = emptyPlaceHolder
+
return columnize.Format(in, columnConf)
}
func formatKV(in []string) string {
columnConf := columnize.DefaultConfig()
- columnConf.Empty = ""
+ columnConf.Empty = emptyPlaceHolder
columnConf.Glue = " = "
+
return columnize.Format(in, columnConf)
}
diff --git a/internal/cli/debug.go b/internal/cli/debug.go
index a6b6ff7973..6e083a6974 100644
--- a/internal/cli/debug.go
+++ b/internal/cli/debug.go
@@ -1,11 +1,8 @@
package cli
-// Based on https://github.com/hashicorp/nomad/blob/main/command/operator_debug.go
-
import (
"archive/tar"
"compress/gzip"
- "context"
"fmt"
"io"
"io/ioutil"
@@ -16,194 +13,187 @@ import (
"syscall"
"time"
- "github.com/ethereum/go-ethereum/internal/cli/flagset"
+ "github.com/mitchellh/cli"
+
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
- "github.com/golang/protobuf/jsonpb"
- gproto "github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/ptypes/empty"
+
+ "github.com/golang/protobuf/jsonpb" // nolint:staticcheck
+ gproto "github.com/golang/protobuf/proto" // nolint:staticcheck
grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
+ "google.golang.org/grpc"
+ "google.golang.org/protobuf/runtime/protoiface"
)
+// DebugCommand is the command to group the peers commands
type DebugCommand struct {
- *Meta2
+ UI cli.Ui
+}
- seconds uint64
- output string
+// MarkDown implements cli.MarkDown interface
+func (d *DebugCommand) MarkDown() string {
+ examples := []string{
+ "## Examples",
+ "By default it creates a tar.gz file with the output:",
+ CodeBlock([]string{
+ "$ bor debug",
+ "Starting debugger...\n",
+ "Created debug archive: bor-debug-2021-10-26-073819Z.tar.gz",
+ }),
+ "Send the output to a specific directory:",
+ CodeBlock([]string{
+ "$ bor debug --output data",
+ "Starting debugger...\n",
+ "Created debug directory: data/bor-debug-2021-10-26-075437Z",
+ }),
+ }
+
+ items := []string{
+ "# Debug",
+ "The ```bor debug``` command takes a debug dump of the running client.",
+ "- [```bor debug pprof```](./debug_pprof.md): Dumps bor pprof traces.",
+ "- [```bor debug block ```](./debug_block.md): Dumps bor block traces.",
+ }
+ items = append(items, examples...)
+
+ return strings.Join(items, "\n\n")
}
// Help implements the cli.Command interface
-func (d *DebugCommand) Help() string {
- return `Usage: bor debug
+func (c *DebugCommand) Help() string {
+ return `Usage: bor debug
- Build an archive containing Bor pprof traces
+ This command takes a debug dump of the running client.
+
+ Get the pprof traces:
- ` + d.Flags().Help()
-}
+ $ bor debug pprof
-func (d *DebugCommand) Flags() *flagset.Flagset {
- flags := d.NewFlagSet("debug")
+ Get the block traces:
- flags.Uint64Flag(&flagset.Uint64Flag{
- Name: "seconds",
- Usage: "seconds to trace",
- Value: &d.seconds,
- Default: 2,
- })
- flags.StringFlag(&flagset.StringFlag{
- Name: "output",
- Value: &d.output,
- Usage: "Output directory",
- })
-
- return flags
+ $ bor debug block `
}
// Synopsis implements the cli.Command interface
-func (d *DebugCommand) Synopsis() string {
- return "Build an archive containing Bor pprof traces"
+func (c *DebugCommand) Synopsis() string {
+ return "Get traces of the running client"
}
// Run implements the cli.Command interface
-func (d *DebugCommand) Run(args []string) int {
- flags := d.Flags()
- if err := flags.Parse(args); err != nil {
- d.UI.Error(err.Error())
- return 1
- }
+func (c *DebugCommand) Run(args []string) int {
+ return cli.RunResultHelp
+}
- clt, err := d.BorConn()
- if err != nil {
- d.UI.Error(err.Error())
- return 1
- }
+type debugEnv struct {
+ output string
+ prefix string
- stamped := "bor-debug-" + time.Now().UTC().Format("2006-01-02-150405Z")
+ name string
+ dst string
+}
+
+func (d *debugEnv) init() error {
+ d.name = d.prefix + time.Now().UTC().Format("2006-01-02-150405Z")
+
+ var err error
// Create the output directory
var tmp string
if d.output != "" {
// User specified output directory
- tmp = filepath.Join(d.output, stamped)
+ tmp = filepath.Join(d.output, d.name)
_, err := os.Stat(tmp)
+
if !os.IsNotExist(err) {
- d.UI.Error("Output directory already exists")
- return 1
+ return fmt.Errorf("output directory already exists")
}
} else {
// Generate temp directory
- tmp, err = ioutil.TempDir(os.TempDir(), stamped)
+ tmp, err = ioutil.TempDir(os.TempDir(), d.name)
if err != nil {
- d.UI.Error(fmt.Sprintf("Error creating tmp directory: %s", err.Error()))
- return 1
+ return fmt.Errorf("error creating tmp directory: %s", err.Error())
}
- defer os.RemoveAll(tmp)
}
- d.UI.Output("Starting debugger...")
- d.UI.Output("")
-
// ensure destine folder exists
if err := os.MkdirAll(tmp, os.ModePerm); err != nil {
- d.UI.Error(fmt.Sprintf("failed to create parent directory: %v", err))
- return 1
+ return fmt.Errorf("failed to create parent directory: %v", err)
}
- pprofProfile := func(ctx context.Context, profile string, filename string) error {
- req := &proto.PprofRequest{
- Seconds: int64(d.seconds),
- }
- switch profile {
- case "cpu":
- req.Type = proto.PprofRequest_CPU
- case "trace":
- req.Type = proto.PprofRequest_TRACE
- default:
- req.Type = proto.PprofRequest_LOOKUP
- req.Profile = profile
- }
- stream, err := clt.Pprof(ctx, req)
- if err != nil {
- return err
- }
- // wait for open request
- msg, err := stream.Recv()
- if err != nil {
- return err
- }
- if _, ok := msg.Event.(*proto.PprofResponse_Open_); !ok {
- return fmt.Errorf("expected open message")
- }
+ d.dst = tmp
- // create the stream
- conn := &grpc_net_conn.Conn{
- Stream: stream,
- Response: &proto.PprofResponse_Input{},
- Decode: grpc_net_conn.SimpleDecoder(func(msg gproto.Message) *[]byte {
- return &msg.(*proto.PprofResponse_Input).Data
- }),
- }
+ return nil
+}
- file, err := os.OpenFile(filepath.Join(tmp, filename+".prof"), os.O_RDWR|os.O_CREATE, 0644)
- if err != nil {
- return err
- }
- defer file.Close()
+func (d *debugEnv) tarName() string {
+ return d.name + ".tar.gz"
+}
- if _, err := io.Copy(file, conn); err != nil {
- return err
- }
+func (d *debugEnv) finish() error {
+ // Exit before archive if output directory was specified
+ if d.output != "" {
return nil
}
- ctx, cancelFn := context.WithCancel(context.Background())
- trapSignal(cancelFn)
-
- profiles := map[string]string{
- "heap": "heap",
- "cpu": "cpu",
- "trace": "trace",
- }
- for profile, filename := range profiles {
- if err := pprofProfile(ctx, profile, filename); err != nil {
- d.UI.Error(fmt.Sprintf("Error creating profile '%s': %v", profile, err))
- return 1
- }
- }
-
- // append the status
- {
- statusResp, err := clt.Status(ctx, &empty.Empty{})
- if err != nil {
- d.UI.Output(fmt.Sprintf("Failed to get status: %v", err))
- return 1
- }
- m := jsonpb.Marshaler{}
- data, err := m.MarshalToString(statusResp)
- if err != nil {
- d.UI.Output(err.Error())
- return 1
- }
- if err := ioutil.WriteFile(filepath.Join(tmp, "status.json"), []byte(data), 0644); err != nil {
- d.UI.Output(fmt.Sprintf("Failed to write status: %v", err))
- return 1
- }
- }
-
- // Exit before archive if output directory was specified
- if d.output != "" {
- d.UI.Output(fmt.Sprintf("Created debug directory: %s", tmp))
- return 0
- }
-
// Create archive tarball
- archiveFile := stamped + ".tar.gz"
- if err = tarCZF(archiveFile, tmp, stamped); err != nil {
- d.UI.Error(fmt.Sprintf("Error creating archive: %s", err.Error()))
- return 1
+ archiveFile := d.tarName()
+ if err := tarCZF(archiveFile, d.dst, d.name); err != nil {
+ return fmt.Errorf("error creating archive: %s", err.Error())
}
- d.UI.Output(fmt.Sprintf("Created debug archive: %s", archiveFile))
- return 0
+ return nil
+}
+
+type debugStream interface {
+ Recv() (*proto.DebugFileResponse, error)
+ grpc.ClientStream
+}
+
+func (d *debugEnv) writeFromStream(name string, stream debugStream) error {
+ // wait for open request
+ msg, err := stream.Recv()
+ if err != nil {
+ return err
+ }
+
+ if _, ok := msg.Event.(*proto.DebugFileResponse_Open_); !ok {
+ return fmt.Errorf("expected open message")
+ }
+
+ // create the stream
+ conn := &grpc_net_conn.Conn{
+ Stream: stream,
+ Response: &proto.DebugFileResponse_Input{},
+ Decode: grpc_net_conn.SimpleDecoder(func(msg gproto.Message) *[]byte {
+ return &msg.(*proto.DebugFileResponse_Input).Data
+ }),
+ }
+
+ file, err := os.OpenFile(filepath.Join(d.dst, name), os.O_RDWR|os.O_CREATE, 0644)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ if _, err := io.Copy(file, conn); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (d *debugEnv) writeJSON(name string, msg protoiface.MessageV1) error {
+ m := jsonpb.Marshaler{}
+ data, err := m.MarshalToString(msg)
+
+ if err != nil {
+ return err
+ }
+
+ if err := ioutil.WriteFile(filepath.Join(d.dst, name), []byte(data), 0600); err != nil {
+ return fmt.Errorf("failed to write status: %v", err)
+ }
+
+ return nil
}
func trapSignal(cancel func()) {
diff --git a/internal/cli/debug_block.go b/internal/cli/debug_block.go
new file mode 100644
index 0000000000..5a282cc550
--- /dev/null
+++ b/internal/cli/debug_block.go
@@ -0,0 +1,126 @@
+package cli
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/internal/cli/flagset"
+ "github.com/ethereum/go-ethereum/internal/cli/server/proto"
+)
+
+// DebugBlockCommand is the command to group the peers commands
+type DebugBlockCommand struct {
+ *Meta2
+
+ output string
+}
+
+func (p *DebugBlockCommand) MarkDown() string {
+ items := []string{
+ "# Debug trace",
+ "The ```bor debug block ``` command will create an archive containing traces of a bor block.",
+ p.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
+// Help implements the cli.Command interface
+func (c *DebugBlockCommand) Help() string {
+ return `Usage: bor debug block
+
+ This command is used get traces of a bor block`
+}
+
+func (c *DebugBlockCommand) Flags() *flagset.Flagset {
+ flags := c.NewFlagSet("trace")
+
+ flags.StringFlag(&flagset.StringFlag{
+ Name: "output",
+ Value: &c.output,
+ Usage: "Output directory",
+ })
+
+ return flags
+}
+
+// Synopsis implements the cli.Command interface
+func (c *DebugBlockCommand) Synopsis() string {
+ return "Get trace of a bor block"
+}
+
+// Run implements the cli.Command interface
+func (c *DebugBlockCommand) Run(args []string) int {
+ flags := c.Flags()
+
+ var number *int64 = nil
+
+ // parse the block number (if available)
+ if len(args)%2 != 0 {
+ num, err := strconv.ParseInt(args[0], 10, 64)
+ if err == nil {
+ number = &num
+ }
+
+ args = args[1:]
+ }
+ // parse output directory
+ if err := flags.Parse(args); err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ borClt, err := c.BorConn()
+ if err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ dEnv := &debugEnv{
+ output: c.output,
+ prefix: "bor-block-trace-",
+ }
+ if err := dEnv.init(); err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ c.UI.Output("Starting block tracer...")
+ c.UI.Output("")
+
+ // create a debug block request
+ var debugRequest *proto.DebugBlockRequest = &proto.DebugBlockRequest{}
+ if number != nil {
+ debugRequest.Number = *number
+ } else {
+ debugRequest.Number = -1
+ }
+
+ // send the request
+ // receives a grpc stream of debug block response
+ stream, err := borClt.DebugBlock(context.Background(), debugRequest)
+ if err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ if err := dEnv.writeFromStream("block.json", stream); err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ if err := dEnv.finish(); err != nil {
+ c.UI.Error(err.Error())
+ return 1
+ }
+
+ if c.output != "" {
+ c.UI.Output(fmt.Sprintf("Created debug directory: %s", dEnv.dst))
+ } else {
+ c.UI.Output(fmt.Sprintf("Created block trace archive: %s", dEnv.tarName()))
+ }
+
+ return 0
+}
diff --git a/internal/cli/debug_pprof.go b/internal/cli/debug_pprof.go
new file mode 100644
index 0000000000..ef15e45b58
--- /dev/null
+++ b/internal/cli/debug_pprof.go
@@ -0,0 +1,159 @@
+package cli
+
+// Based on https://github.com/hashicorp/nomad/blob/main/command/operator_debug.go
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/golang/protobuf/ptypes/empty"
+
+ "github.com/ethereum/go-ethereum/internal/cli/flagset"
+ "github.com/ethereum/go-ethereum/internal/cli/server/proto"
+)
+
+type DebugPprofCommand struct {
+ *Meta2
+
+ seconds uint64
+ output string
+}
+
+func (p *DebugPprofCommand) MarkDown() string {
+ items := []string{
+ "# Debug Pprof",
+ "The ```debug pprof ``` command will create an archive containing bor pprof traces.",
+ p.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
+// Help implements the cli.Command interface
+func (d *DebugPprofCommand) Help() string {
+ return `Usage: bor debug
+
+ Build an archive containing Bor pprof traces
+
+ ` + d.Flags().Help()
+}
+
+func (d *DebugPprofCommand) Flags() *flagset.Flagset {
+ flags := d.NewFlagSet("debug")
+
+ flags.Uint64Flag(&flagset.Uint64Flag{
+ Name: "seconds",
+ Usage: "seconds to trace",
+ Value: &d.seconds,
+ Default: 2,
+ })
+ flags.StringFlag(&flagset.StringFlag{
+ Name: "output",
+ Value: &d.output,
+ Usage: "Output directory",
+ })
+
+ return flags
+}
+
+// Synopsis implements the cli.Command interface
+func (d *DebugPprofCommand) Synopsis() string {
+ return "Build an archive containing Bor pprof traces"
+}
+
+// Run implements the cli.Command interface
+func (d *DebugPprofCommand) Run(args []string) int {
+ flags := d.Flags()
+ if err := flags.Parse(args); err != nil {
+ d.UI.Error(err.Error())
+ return 1
+ }
+
+ clt, err := d.BorConn()
+ if err != nil {
+ d.UI.Error(err.Error())
+ return 1
+ }
+
+ dEnv := &debugEnv{
+ output: d.output,
+ prefix: "bor-debug-",
+ }
+ if err := dEnv.init(); err != nil {
+ d.UI.Error(err.Error())
+ return 1
+ }
+
+ d.UI.Output("Starting debugger...")
+ d.UI.Output("")
+
+ pprofProfile := func(ctx context.Context, profile string, filename string) error {
+ req := &proto.DebugPprofRequest{
+ Seconds: int64(d.seconds),
+ }
+
+ switch profile {
+ case "cpu":
+ req.Type = proto.DebugPprofRequest_CPU
+ case "trace":
+ req.Type = proto.DebugPprofRequest_TRACE
+ default:
+ req.Type = proto.DebugPprofRequest_LOOKUP
+ req.Profile = profile
+ }
+
+ stream, err := clt.DebugPprof(ctx, req)
+
+ if err != nil {
+ return err
+ }
+
+ if err := dEnv.writeFromStream(filename+".prof", stream); err != nil {
+ return err
+ }
+
+ return nil
+ }
+
+ ctx, cancelFn := context.WithCancel(context.Background())
+ trapSignal(cancelFn)
+
+ profiles := map[string]string{
+ "heap": "heap",
+ "cpu": "cpu",
+ "trace": "trace",
+ }
+ for profile, filename := range profiles {
+ if err := pprofProfile(ctx, profile, filename); err != nil {
+ d.UI.Error(fmt.Sprintf("Error creating profile '%s': %v", profile, err))
+ return 1
+ }
+ }
+
+ // append the status
+ {
+ statusResp, err := clt.Status(ctx, &empty.Empty{})
+ if err != nil {
+ d.UI.Output(fmt.Sprintf("Failed to get status: %v", err))
+ return 1
+ }
+ if err := dEnv.writeJSON("status.json", statusResp); err != nil {
+ d.UI.Error(err.Error())
+ return 1
+ }
+ }
+
+ if err := dEnv.finish(); err != nil {
+ d.UI.Error(err.Error())
+ return 1
+ }
+
+ if d.output != "" {
+ d.UI.Output(fmt.Sprintf("Created debug directory: %s", dEnv.dst))
+ } else {
+ d.UI.Output(fmt.Sprintf("Created debug archive: %s", dEnv.tarName()))
+ }
+
+ return 0
+}
diff --git a/internal/cli/debug_test.go b/internal/cli/debug_test.go
new file mode 100644
index 0000000000..f77cf839ac
--- /dev/null
+++ b/internal/cli/debug_test.go
@@ -0,0 +1,112 @@
+package cli
+
+import (
+ "os"
+ "path"
+ "strconv"
+ "testing"
+ "time"
+
+ "github.com/mitchellh/cli"
+ "github.com/stretchr/testify/assert"
+
+ "github.com/ethereum/go-ethereum/internal/cli/server"
+)
+
+var currentDir string = ""
+
+func TestCommand_DebugBlock(t *testing.T) {
+ t.Parallel()
+
+ // Start a blockchain in developer mode and get trace of block
+ config := server.DefaultConfig()
+
+ // enable developer mode
+ config.Developer.Enabled = true
+ config.Developer.Period = 2 // block time
+
+ // enable archive mode for getting traces of ancient blocks
+ config.GcMode = "archive"
+
+ // start the mock server
+ srv, err := server.CreateMockServer(config)
+ assert.NoError(t, err)
+
+ defer server.CloseMockServer(srv)
+
+ // get the grpc port
+ port := srv.GetGrpcAddr()
+
+ // wait for 4 seconds to mine a 2 blocks
+ time.Sleep(2 * time.Duration(config.Developer.Period) * time.Second)
+
+ // add prefix for debug trace
+ prefix := "bor-block-trace-"
+
+ // output dir
+ output := "debug_block_test"
+
+ // set current directory
+ currentDir, _ = os.Getwd()
+
+ // trace 1st block
+ start := time.Now()
+ dst1 := path.Join(output, prefix+time.Now().UTC().Format("2006-01-02-150405Z"), "block.json")
+ res := traceBlock(port, 1, output)
+ assert.Equal(t, 0, res)
+ t.Logf("Completed trace of block %d in %d ms at %s", 1, time.Since(start).Milliseconds(), dst1)
+
+ // adding this to avoid debug directory name conflicts
+ time.Sleep(time.Second)
+
+ // trace last/recent block
+ start = time.Now()
+ latestBlock := srv.GetLatestBlockNumber().Int64()
+ dst2 := path.Join(output, prefix+time.Now().UTC().Format("2006-01-02-150405Z"), "block.json")
+ res = traceBlock(port, latestBlock, output)
+ assert.Equal(t, 0, res)
+ t.Logf("Completed trace of block %d in %d ms at %s", latestBlock, time.Since(start).Milliseconds(), dst2)
+
+ // verify if the trace files are created
+ done := verify(dst1)
+ assert.Equal(t, true, done)
+ done = verify(dst2)
+ assert.Equal(t, true, done)
+
+ // delete the traces
+ deleteTraces(output)
+}
+
+// traceBlock calls the cli command to trace a block
+func traceBlock(port string, number int64, output string) int {
+ ui := cli.NewMockUi()
+ command := &DebugBlockCommand{
+ Meta2: &Meta2{
+ UI: ui,
+ addr: "127.0.0.1:" + port,
+ },
+ }
+
+ // run trace (by explicitly passing the output directory and grpc address)
+ return command.Run([]string{strconv.FormatInt(number, 10), "--output", output, "--address", command.Meta2.addr})
+}
+
+// verify checks if the trace file is created at the destination
+// directory or not
+func verify(dst string) bool {
+ dst = path.Join(currentDir, dst)
+ if file, err := os.Stat(dst); err == nil {
+ // check if the file has content
+ if file.Size() > 0 {
+ return true
+ }
+ }
+
+ return false
+}
+
+// deleteTraces removes the traces created during the test
+func deleteTraces(dst string) {
+ dst = path.Join(currentDir, dst)
+ os.RemoveAll(dst)
+}
diff --git a/internal/cli/flagset/flagset.go b/internal/cli/flagset/flagset.go
index 4388dd03fc..b57fff9996 100644
--- a/internal/cli/flagset/flagset.go
+++ b/internal/cli/flagset/flagset.go
@@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"math/big"
+ "sort"
"strings"
"time"
)
@@ -18,12 +19,14 @@ func NewFlagSet(name string) *Flagset {
flags: []*FlagVar{},
set: flag.NewFlagSet(name, flag.ContinueOnError),
}
+
return f
}
type FlagVar struct {
Name string
Usage string
+ Group string
}
func (f *Flagset) addFlag(fl *FlagVar) {
@@ -32,13 +35,54 @@ func (f *Flagset) addFlag(fl *FlagVar) {
func (f *Flagset) Help() string {
str := "Options:\n\n"
+
items := []string{}
for _, item := range f.flags {
items = append(items, fmt.Sprintf(" -%s\n %s", item.Name, item.Usage))
}
+
return str + strings.Join(items, "\n\n")
}
+// MarkDown implements cli.MarkDown interface
+func (f *Flagset) MarkDown() string {
+ if len(f.flags) == 0 {
+ return ""
+ }
+
+ groups := make(map[string][]*FlagVar)
+
+ for _, item := range f.flags {
+ groups[item.Group] = append(groups[item.Group], item)
+ }
+
+ i := 0
+ keys := make([]string, len(groups))
+
+ for k := range groups {
+ keys[i] = k
+ i++
+ }
+
+ sort.Strings(keys)
+
+ items := []string{}
+
+ for _, k := range keys {
+ if k == "" {
+ items = append(items, "## Options")
+ } else {
+ items = append(items, fmt.Sprintf("### %s Options", k))
+ }
+
+ for _, item := range groups[k] {
+ items = append(items, fmt.Sprintf("- ```%s```: %s", item.Name, item.Usage))
+ }
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
func (f *Flagset) Parse(args []string) error {
return f.set.Parse(args)
}
@@ -52,12 +96,14 @@ type BoolFlag struct {
Usage string
Default bool
Value *bool
+ Group string
}
func (f *Flagset) BoolFlag(b *BoolFlag) {
f.addFlag(&FlagVar{
Name: b.Name,
Usage: b.Usage,
+ Group: b.Group,
})
f.set.BoolVar(b.Value, b.Name, b.Default, b.Usage)
}
@@ -67,12 +113,14 @@ type StringFlag struct {
Usage string
Default string
Value *string
+ Group string
}
func (f *Flagset) StringFlag(b *StringFlag) {
f.addFlag(&FlagVar{
Name: b.Name,
Usage: b.Usage,
+ Group: b.Group,
})
f.set.StringVar(b.Value, b.Name, b.Default, b.Usage)
}
@@ -82,12 +130,14 @@ type IntFlag struct {
Usage string
Value *int
Default int
+ Group string
}
func (f *Flagset) IntFlag(i *IntFlag) {
f.addFlag(&FlagVar{
Name: i.Name,
Usage: i.Usage,
+ Group: i.Group,
})
f.set.IntVar(i.Value, i.Name, i.Default, i.Usage)
}
@@ -97,12 +147,14 @@ type Uint64Flag struct {
Usage string
Value *uint64
Default uint64
+ Group string
}
func (f *Flagset) Uint64Flag(i *Uint64Flag) {
f.addFlag(&FlagVar{
Name: i.Name,
Usage: i.Usage,
+ Group: i.Group,
})
f.set.Uint64Var(i.Value, i.Name, i.Default, i.Usage)
}
@@ -111,12 +163,14 @@ type BigIntFlag struct {
Name string
Usage string
Value *big.Int
+ Group string
}
func (b *BigIntFlag) String() string {
if b.Value == nil {
return ""
}
+
return b.Value.String()
}
@@ -129,10 +183,12 @@ func (b *BigIntFlag) Set(value string) error {
} else {
num, ok = num.SetString(value, 10)
}
+
if !ok {
return fmt.Errorf("failed to set big int")
}
b.Value = num
+
return nil
}
@@ -140,6 +196,7 @@ func (f *Flagset) BigIntFlag(b *BigIntFlag) {
f.addFlag(&FlagVar{
Name: b.Name,
Usage: b.Usage,
+ Group: b.Group,
})
f.set.Var(b, b.Name, b.Usage)
}
@@ -148,17 +205,20 @@ type SliceStringFlag struct {
Name string
Usage string
Value *[]string
+ Group string
}
func (i *SliceStringFlag) String() string {
if i.Value == nil {
return ""
}
+
return strings.Join(*i.Value, ",")
}
func (i *SliceStringFlag) Set(value string) error {
*i.Value = append(*i.Value, strings.Split(value, ",")...)
+
return nil
}
@@ -166,6 +226,7 @@ func (f *Flagset) SliceStringFlag(s *SliceStringFlag) {
f.addFlag(&FlagVar{
Name: s.Name,
Usage: s.Usage,
+ Group: s.Group,
})
f.set.Var(s, s.Name, s.Usage)
}
@@ -175,12 +236,14 @@ type DurationFlag struct {
Usage string
Value *time.Duration
Default time.Duration
+ Group string
}
func (f *Flagset) DurationFlag(d *DurationFlag) {
f.addFlag(&FlagVar{
Name: d.Name,
Usage: d.Usage,
+ Group: d.Group,
})
f.set.DurationVar(d.Value, d.Name, d.Default, "")
}
@@ -189,16 +252,19 @@ type MapStringFlag struct {
Name string
Usage string
Value *map[string]string
+ Group string
}
func (m *MapStringFlag) String() string {
if m.Value == nil {
return ""
}
+
ls := []string{}
for k, v := range *m.Value {
ls = append(ls, k+"="+v)
}
+
return strings.Join(ls, ",")
}
@@ -206,6 +272,7 @@ func (m *MapStringFlag) Set(value string) error {
if m.Value == nil {
m.Value = &map[string]string{}
}
+
for _, t := range strings.Split(value, ",") {
if t != "" {
kv := strings.Split(t, "=")
@@ -215,6 +282,7 @@ func (m *MapStringFlag) Set(value string) error {
}
}
}
+
return nil
}
@@ -222,6 +290,7 @@ func (f *Flagset) MapStringFlag(m *MapStringFlag) {
f.addFlag(&FlagVar{
Name: m.Name,
Usage: m.Usage,
+ Group: m.Group,
})
f.set.Var(m, m.Name, m.Usage)
}
@@ -231,12 +300,14 @@ type Float64Flag struct {
Usage string
Value *float64
Default float64
+ Group string
}
func (f *Flagset) Float64Flag(i *Float64Flag) {
f.addFlag(&FlagVar{
Name: i.Name,
Usage: i.Usage,
+ Group: i.Group,
})
f.set.Float64Var(i.Value, i.Name, i.Default, "")
}
diff --git a/internal/cli/markdown.go b/internal/cli/markdown.go
new file mode 100644
index 0000000000..652c98e56b
--- /dev/null
+++ b/internal/cli/markdown.go
@@ -0,0 +1,14 @@
+package cli
+
+import (
+ "strings"
+)
+
+type MarkDown interface {
+ MarkDown() string
+}
+
+// Create a Markdown code block from a slice of string, where each string is a line of code
+func CodeBlock(lines []string) string {
+ return "```\n" + strings.Join(lines, "\n") + "\n```"
+}
diff --git a/internal/cli/markdown_test.go b/internal/cli/markdown_test.go
new file mode 100644
index 0000000000..30c272a220
--- /dev/null
+++ b/internal/cli/markdown_test.go
@@ -0,0 +1,20 @@
+package cli
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestCodeBlock(t *testing.T) {
+ t.Parallel()
+ assert := assert.New(t)
+
+ lines := []string{
+ "abc",
+ "bcd",
+ }
+
+ expected := "```\n" + "abc\n" + "bcd\n" + "```"
+ assert.Equal(expected, CodeBlock(lines))
+}
diff --git a/internal/cli/peers.go b/internal/cli/peers.go
index b591366222..fbbca24fad 100644
--- a/internal/cli/peers.go
+++ b/internal/cli/peers.go
@@ -1,6 +1,8 @@
package cli
import (
+ "strings"
+
"github.com/mitchellh/cli"
)
@@ -9,6 +11,20 @@ type PeersCommand struct {
UI cli.Ui
}
+// MarkDown implements cli.MarkDown interface
+func (a *PeersCommand) MarkDown() string {
+ items := []string{
+ "# Peers",
+ "The ```peers``` command groups actions to interact with peers:",
+ "- [```peers add```](./peers_add.md): Joins the local client to another remote peer.",
+ "- [```peers list```](./peers_list.md): Lists the connected peers to the Bor client.",
+ "- [```peers remove```](./peers_remove.md): Disconnects the local client from a connected peer if exists.",
+ "- [```peers status```](./peers_status.md): Display the status of a peer by its id.",
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (c *PeersCommand) Help() string {
return `Usage: bor peers
diff --git a/internal/cli/peers_add.go b/internal/cli/peers_add.go
index 2b2fe127e0..3df1a6b6cb 100644
--- a/internal/cli/peers_add.go
+++ b/internal/cli/peers_add.go
@@ -2,6 +2,7 @@ package cli
import (
"context"
+ "strings"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
@@ -14,6 +15,17 @@ type PeersAddCommand struct {
trusted bool
}
+// MarkDown implements cli.MarkDown interface
+func (p *PeersAddCommand) MarkDown() string {
+ items := []string{
+ "# Peers add",
+ "The ```peers add ``` command joins the local client to another remote peer.",
+ p.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (p *PeersAddCommand) Help() string {
return `Usage: bor peers add
@@ -68,5 +80,6 @@ func (c *PeersAddCommand) Run(args []string) int {
c.UI.Error(err.Error())
return 1
}
+
return 0
}
diff --git a/internal/cli/peers_list.go b/internal/cli/peers_list.go
index a42e0011a5..4a572447c1 100644
--- a/internal/cli/peers_list.go
+++ b/internal/cli/peers_list.go
@@ -14,6 +14,17 @@ type PeersListCommand struct {
*Meta2
}
+// MarkDown implements cli.MarkDown interface
+func (p *PeersListCommand) MarkDown() string {
+ items := []string{
+ "# Peers add",
+ "The ```peers list``` command lists the connected peers.",
+ p.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (p *PeersListCommand) Help() string {
return `Usage: bor peers list
@@ -50,12 +61,14 @@ func (c *PeersListCommand) Run(args []string) int {
req := &proto.PeersListRequest{}
resp, err := borClt.PeersList(context.Background(), req)
+
if err != nil {
c.UI.Error(err.Error())
return 1
}
c.UI.Output(formatPeers(resp.Peers))
+
return 0
}
@@ -66,6 +79,7 @@ func formatPeers(peers []*proto.Peer) string {
rows := make([]string, len(peers)+1)
rows[0] = "ID|Enode|Name|Caps|Static|Trusted"
+
for i, d := range peers {
enode := strings.TrimPrefix(d.Enode, "enode://")
@@ -77,5 +91,6 @@ func formatPeers(peers []*proto.Peer) string {
d.Static,
d.Trusted)
}
+
return formatList(rows)
}
diff --git a/internal/cli/peers_remove.go b/internal/cli/peers_remove.go
index 979f139251..f53284c40c 100644
--- a/internal/cli/peers_remove.go
+++ b/internal/cli/peers_remove.go
@@ -2,6 +2,7 @@ package cli
import (
"context"
+ "strings"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
@@ -14,6 +15,17 @@ type PeersRemoveCommand struct {
trusted bool
}
+// MarkDown implements cli.MarkDown interface
+func (p *PeersRemoveCommand) MarkDown() string {
+ items := []string{
+ "# Peers remove",
+ "The ```peers remove ``` command disconnects the local client from a connected peer if exists.",
+ p.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (p *PeersRemoveCommand) Help() string {
return `Usage: bor peers remove
@@ -68,5 +80,6 @@ func (c *PeersRemoveCommand) Run(args []string) int {
c.UI.Error(err.Error())
return 1
}
+
return 0
}
diff --git a/internal/cli/peers_status.go b/internal/cli/peers_status.go
index c1da2b2647..f5d700a273 100644
--- a/internal/cli/peers_status.go
+++ b/internal/cli/peers_status.go
@@ -14,6 +14,17 @@ type PeersStatusCommand struct {
*Meta2
}
+// MarkDown implements cli.MarkDown interface
+func (p *PeersStatusCommand) MarkDown() string {
+ items := []string{
+ "# Peers status",
+ "The ```peers status ``` command displays the status of a peer by its id.",
+ p.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (p *PeersStatusCommand) Help() string {
return `Usage: bor peers status
@@ -58,12 +69,14 @@ func (c *PeersStatusCommand) Run(args []string) int {
Enode: args[0],
}
resp, err := borClt.PeersStatus(context.Background(), req)
+
if err != nil {
c.UI.Error(err.Error())
return 1
}
c.UI.Output(formatPeer(resp.Peer))
+
return 0
}
@@ -77,5 +90,6 @@ func formatPeer(peer *proto.Peer) string {
fmt.Sprintf("Static|%v", peer.Static),
fmt.Sprintf("Trusted|%v", peer.Trusted),
})
+
return base
}
diff --git a/internal/cli/server/chains/chain.go b/internal/cli/server/chains/chain.go
index 05c12ef0b0..d6717f5893 100644
--- a/internal/cli/server/chains/chain.go
+++ b/internal/cli/server/chains/chain.go
@@ -1,8 +1,15 @@
package chains
import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/log"
)
type Chain struct {
@@ -18,7 +25,61 @@ var chains = map[string]*Chain{
"mumbai": mumbaiTestnet,
}
-func GetChain(name string) (*Chain, bool) {
- chain, ok := chains[name]
- return chain, ok
+func GetChain(name string) (*Chain, error) {
+ var (
+ chain *Chain
+ err error
+ )
+
+ if _, fileErr := os.Stat(name); fileErr == nil {
+ if chain, err = ImportFromFile(name); err != nil {
+ return nil, fmt.Errorf("error importing chain from file: %v", err)
+ }
+
+ return chain, nil
+ } else if errors.Is(fileErr, os.ErrNotExist) {
+ var ok bool
+ if chain, ok = chains[name]; !ok {
+ return nil, fmt.Errorf("chain %s not found", name)
+ }
+
+ return chain, nil
+ } else {
+ return nil, fileErr
+ }
+}
+
+func ImportFromFile(filename string) (*Chain, error) {
+ data, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+
+ return importChain(data)
+}
+
+func importChain(content []byte) (*Chain, error) {
+ var chain *Chain
+
+ if err := json.Unmarshal(content, &chain); err != nil {
+ return nil, err
+ }
+
+ if chain.Genesis == nil {
+ log.Info("Try reading as legacy genesis")
+
+ var genesis core.Genesis
+ if err := json.Unmarshal(content, &genesis); err != nil {
+ return nil, err
+ }
+
+ if genesis.Config != nil {
+ chain.Genesis = &genesis
+ chain.NetworkId = genesis.Config.ChainID.Uint64()
+ } else {
+ return nil, fmt.Errorf("unable to parse chain config")
+ }
+ }
+
+ return chain, nil
}
diff --git a/internal/cli/server/chains/chain_test.go b/internal/cli/server/chains/chain_test.go
new file mode 100644
index 0000000000..b372a3c4b9
--- /dev/null
+++ b/internal/cli/server/chains/chain_test.go
@@ -0,0 +1,54 @@
+package chains
+
+import (
+ "testing"
+)
+
+func TestChain_ImportFromFile(t *testing.T) {
+ t.Parallel()
+
+ type args struct {
+ filename string
+ }
+
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "ImportFromFile correct json file",
+ args: args{filename: "test_files/chain_test.json"},
+ wantErr: false,
+ },
+ {
+ name: "ImportFromFile correct legacy json file",
+ args: args{filename: "test_files/chain_legacy_test.json"},
+ wantErr: false,
+ },
+ {
+ name: "ImportFromFile wrong json file",
+ args: args{filename: "test_files/wrong_chain.json"},
+ wantErr: true,
+ },
+ {
+ name: "ImportFromFile nonexistent json file",
+ args: args{filename: "test_files/chain_test_nonexistent.json"},
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ tt := tt
+
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ _, err := ImportFromFile(tt.args.filename)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("ImportFromFile() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ })
+ }
+}
diff --git a/internal/cli/server/chains/test_files/chain_legacy_test.json b/internal/cli/server/chains/test_files/chain_legacy_test.json
new file mode 100644
index 0000000000..5702eaca40
--- /dev/null
+++ b/internal/cli/server/chains/test_files/chain_legacy_test.json
@@ -0,0 +1,83 @@
+{
+ "config":{
+ "chainId":80001,
+ "homesteadBlock":0,
+ "daoForkSupport":true,
+ "eip150Block":0,
+ "eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000",
+ "eip155Block":0,
+ "eip158Block":0,
+ "byzantiumBlock":0,
+ "constantinopleBlock":0,
+ "petersburgBlock":0,
+ "istanbulBlock":2722000,
+ "muirGlacierBlock":2722000,
+ "berlinBlock":13996000,
+ "londonBlock":13996000,
+ "bor":{
+ "period":{
+ "0":2
+ },
+ "producerDelay":6,
+ "sprint":64,
+ "backupMultiplier":{
+ "0":2
+ },
+ "validatorContract":"0x0000000000000000000000000000000000001000",
+ "stateReceiverContract":"0x0000000000000000000000000000000000001001",
+ "overrideStateSyncRecords":null,
+ "blockAlloc":{
+ "22244000":{
+ "0000000000000000000000000000000000001010":{
+ "balance":"0x0",
+ "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611548565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154e565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115db565b005b348015610b2e57600080fd5b50610b376115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161e90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da96023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163e90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d866023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165d565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611755565b90505b92915050565b6040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b12565b611be8565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611dcc605291396040516020018082805190602001908083835b6020831061159d578051825260208201915060208101905060208303925061157a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e3611381565b6115ec57600080fd5b6115f58161165d565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162d57600080fd5b600082840390508091505092915050565b60008082840190508381101561165357600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d557600080fd5b505afa1580156117e9573d6000803e3d6000fd5b505050506040513d60208110156117ff57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561189157600080fd5b505afa1580156118a5573d6000803e3d6000fd5b505050506040513d60208110156118bb57600080fd5b810190808051906020019092919050505090506118d9868686611c32565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119e157600080fd5b505afa1580156119f5573d6000803e3d6000fd5b505050506040513d6020811015611a0b57600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9957600080fd5b505afa158015611aad573d6000803e3d6000fd5b505050506040513d6020811015611ac357600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b60208310611b645780518252602082019150602081019050602083039250611b41565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d1a573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820ccd6c2a9c259832bbb367986ee06cd87af23022681b0cb22311a864b701d939564736f6c63430005100032"
+ }
+ }
+ },
+ "burntContract":{
+ "22640000":"0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"
+ },
+ "jaipurBlock":22770000
+ }
+ },
+ "nonce":"0x0",
+ "timestamp":"0x5ce28211",
+ "extraData":"0x",
+ "gasLimit":"0x989680",
+ "difficulty":"0x1",
+ "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase":"0x0000000000000000000000000000000000000000",
+ "alloc":{
+ "0000000000000000000000000000000000001000":{
+ "code":"0x608060405234801561001057600080fd5b50600436106101f05760003560e01c806360c8614d1161010f578063af26aa96116100a2578063d5b844eb11610071578063d5b844eb14610666578063dcf2793a14610684578063e3b7c924146106b6578063f59cf565146106d4576101f0565b8063af26aa96146105c7578063b71d7a69146105e7578063b7ab4db514610617578063c1b3c91914610636576101f0565b806370ba5707116100de57806370ba57071461052b57806398ab2b621461055b5780639d11b80714610579578063ae756451146105a9576101f0565b806360c8614d1461049c57806365b3a1e2146104bc57806366332354146104db578063687a9bd6146104f9576101f0565b80633434735f1161018757806344d6528f1161015657806344d6528f146103ee5780634dbc959f1461041e57806355614fcc1461043c578063582a8d081461046c576101f0565b80633434735f1461035257806335ddfeea1461037057806343ee8213146103a057806344c15cb1146103be576101f0565b806323f2a73f116101c357806323f2a73f146102a45780632bc06564146102d45780632de3a180146102f25780632eddf35214610322576101f0565b8063047a6c5b146101f55780630c35b1cb146102275780631270b5741461025857806323c2a2b414610288575b600080fd5b61020f600480360361020a9190810190612b24565b610706565b60405161021e93929190613463565b60405180910390f35b610241600480360361023c9190810190612b24565b61075d565b60405161024f929190613284565b60405180910390f35b610272600480360361026d9190810190612b4d565b610939565b60405161027f91906132bb565b60405180910390f35b6102a2600480360361029d9190810190612c2c565b610a91565b005b6102be60048036036102b99190810190612b4d565b61112a565b6040516102cb91906132bb565b60405180910390f35b6102dc611281565b6040516102e99190613411565b60405180910390f35b61030c60048036036103079190810190612a81565b611286565b60405161031991906132d6565b60405180910390f35b61033c60048036036103379190810190612b24565b611307565b6040516103499190613411565b60405180910390f35b61035a611437565b6040516103679190613269565b60405180910390f35b61038a60048036036103859190810190612abd565b61144f565b60405161039791906132bb565b60405180910390f35b6103a861151a565b6040516103b591906132d6565b60405180910390f35b6103d860048036036103d39190810190612b89565b611531565b6040516103e59190613411565b60405180910390f35b61040860048036036104039190810190612b4d565b611619565b60405161041591906133f6565b60405180910390f35b610426611781565b6040516104339190613411565b60405180910390f35b61045660048036036104519190810190612a06565b611791565b60405161046391906132bb565b60405180910390f35b61048660048036036104819190810190612a2f565b6117ab565b60405161049391906132d6565b60405180910390f35b6104a4611829565b6040516104b393929190613463565b60405180910390f35b6104c461189d565b6040516104d2929190613284565b60405180910390f35b6104e3611b6e565b6040516104f09190613411565b60405180910390f35b610513600480360361050e9190810190612bf0565b611b73565b6040516105229392919061342c565b60405180910390f35b61054560048036036105409190810190612a06565b611bd7565b60405161055291906132bb565b60405180910390f35b610563611bf1565b60405161057091906132d6565b60405180910390f35b610593600480360361058e9190810190612b24565b611c08565b6040516105a09190613411565b60405180910390f35b6105b1611d39565b6040516105be91906132d6565b60405180910390f35b6105cf611d50565b6040516105de93929190613463565b60405180910390f35b61060160048036036105fc9190810190612b24565b611db1565b60405161060e9190613411565b60405180910390f35b61061f611eb1565b60405161062d929190613284565b60405180910390f35b610650600480360361064b9190810190612b24565b611ec5565b60405161065d9190613411565b60405180910390f35b61066e611ee6565b60405161067b919061349a565b60405180910390f35b61069e60048036036106999190810190612bf0565b611eeb565b6040516106ad9392919061342c565b60405180910390f35b6106be611f4f565b6040516106cb9190613411565b60405180910390f35b6106ee60048036036106e99190810190612b24565b611f61565b6040516106fd93929190613463565b60405180910390f35b60008060006002600085815260200190815260200160002060000154600260008681526020019081526020016000206001015460026000878152602001908152602001600020600201549250925092509193909250565b60608060ff83116107795761077061189d565b91509150610934565b600061078484611db1565b9050606060016000838152602001908152602001600020805490506040519080825280602002602001820160405280156107cd5781602001602082028038833980820191505090505b509050606060016000848152602001908152602001600020805490506040519080825280602002602001820160405280156108175781602001602082028038833980820191505090505b50905060008090505b60016000858152602001908152602001600020805490508110156109295760016000858152602001908152602001600020818154811061085c57fe5b906000526020600020906003020160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683828151811061089a57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001600085815260200190815260200160002081815481106108f257fe5b90600052602060002090600302016001015482828151811061091057fe5b6020026020010181815250508080600101915050610820565b508181945094505050505b915091565b6000606060016000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610a0c578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190610970565b50505050905060008090505b8151811015610a84578373ffffffffffffffffffffffffffffffffffffffff16828281518110610a4457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff161415610a7757600192505050610a8b565b8080600101915050610a18565b5060009150505b92915050565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0a906133d6565b60405180910390fd5b6000610b1d611781565b90506000811415610b3157610b30611f8b565b5b610b456001826122ac90919063ffffffff16565b8814610b86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7d90613356565b60405180910390fd5b868611610bc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbf906133b6565b60405180910390fd5b6000604060018989030181610bd957fe5b0614610c1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1190613396565b60405180910390fd5b8660026000838152602001908152602001600020600101541115610c73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6a90613336565b60405180910390fd5b6000600260008a81526020019081526020016000206000015414610ccc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc390613376565b60405180910390fd5b604051806060016040528089815260200188815260200187815250600260008a8152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600388908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008a815260200190815260200160002081610d669190612800565b506000600160008a815260200190815260200160002081610d879190612800565b506060610ddf610dda87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b8151811015610f51576060610e0e838381518110610e0157fe5b60200260200101516122f9565b90506000808c81526020019081526020016000208054809190600101610e349190612800565b506040518060600160405280610e5d83600081518110610e5057fe5b60200260200101516123d6565b8152602001610e7f83600181518110610e7257fe5b60200260200101516123d6565b8152602001610ea183600281518110610e9457fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff168152506000808d81526020019081526020016000208381548110610ed757fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610de7565b506060610fa9610fa486868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b815181101561111d576060610fd8838381518110610fcb57fe5b60200260200101516122f9565b9050600160008d81526020019081526020016000208054809190600101610fff9190612800565b5060405180606001604052806110288360008151811061101b57fe5b60200260200101516123d6565b815260200161104a8360018151811061103d57fe5b60200260200101516123d6565b815260200161106c8360028151811061105f57fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff16815250600160008e815260200190815260200160002083815481106110a357fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610fb1565b5050505050505050505050565b60006060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156111fc578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611160565b50505050905060008090505b8151811015611274578373ffffffffffffffffffffffffffffffffffffffff1682828151811061123457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff1614156112675760019250505061127b565b8080600101915050611208565b5060009150505b92915050565b604081565b60006002600160f81b84846040516020016112a3939291906131d6565b6040516020818303038152906040526040516112bf9190613213565b602060405180830381855afa1580156112dc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506112ff9190810190612a58565b905092915050565b60006060600080848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156113d9578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001906001019061133d565b505050509050600080905060008090505b825181101561142c5761141d83828151811061140257fe5b602002602001015160200151836122ac90919063ffffffff16565b915080806001019150506113ea565b508092505050919050565b73fffffffffffffffffffffffffffffffffffffffe81565b600080600080859050600060218087518161146657fe5b04029050600081111561147f5761147c876117ab565b91505b6000602190505b818111611509576000600182038801519050818801519550806000602081106114ab57fe5b1a60f81b9450600060f81b857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156114f0576114e98685611286565b93506114fd565b6114fa8487611286565b93505b50602181019050611486565b508782149450505050509392505050565b60405161152690613254565b604051809103902081565b60008060009050600080905060008090505b84518167ffffffffffffffff16101561160c57606061156e868367ffffffffffffffff16604161246a565b9050600061158582896124f690919063ffffffff16565b905061158f612832565b6115998a83611619565b90506115a58a8361112a565b80156115dc57508473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16115b156115fe578194506115fb8160200151876122ac90919063ffffffff16565b95505b505050604181019050611543565b5081925050509392505050565b611621612832565b6060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156116f1578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611655565b50505050905060008090505b8151811015611779578373ffffffffffffffffffffffffffffffffffffffff1682828151811061172957fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff16141561176c5781818151811061175d57fe5b60200260200101519250611779565b80806001019150506116fd565b505092915050565b600061178c43611db1565b905090565b60006117a461179e611781565b8361112a565b9050919050565b60006002600060f81b836040516020016117c69291906131aa565b6040516020818303038152906040526040516117e29190613213565b602060405180830381855afa1580156117ff573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506118229190810190612a58565b9050919050565b60008060008061184a600161183c611781565b6122ac90919063ffffffff16565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b606080606060056040519080825280602002602001820160405280156118d25781602001602082028038833980820191505090505b50905073c26880a0af2ea0c7e8130e6ec47af756465452e8816000815181106118f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073be188d6641e8b680743a4815dfa0f6208038960f8160018151811061195357fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c275dc8be39f50d12f66b6a63629c39da5bae5bd816002815181106119af57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073f903ba9e006193c1527bfbe65fe2123704ea3f9981600381518110611a0b57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073928ed6a3e94437bbd316ccad78479f1d163a6a8c81600481518110611a6757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060606005604051908082528060200260200182016040528015611ad35781602001602082028038833980820191505090505b50905061271081600081518110611ae657fe5b60200260200101818152505061271081600181518110611b0257fe5b60200260200101818152505061271081600281518110611b1e57fe5b60200260200101818152505061271081600381518110611b3a57fe5b60200260200101818152505061271081600481518110611b5657fe5b60200260200101818152505081819350935050509091565b60ff81565b60016020528160005260406000208181548110611b8c57fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b6000611bea611be4611781565b83610939565b9050919050565b604051611bfd9061322a565b604051809103902081565b6000606060016000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611cdb578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611c3f565b505050509050600080905060008090505b8251811015611d2e57611d1f838281518110611d0457fe5b602002602001015160200151836122ac90919063ffffffff16565b91508080600101915050611cec565b508092505050919050565b604051611d459061323f565b604051809103902081565b600080600080611d5e611781565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b60008060038054905090505b6000811115611e7157611dce612869565b6002600060036001850381548110611de257fe5b906000526020600020015481526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905083816020015111158015611e3f57506000816040015114155b8015611e4f575080604001518411155b15611e6257806000015192505050611eac565b50808060019003915050611dbd565b5060006003805490501115611ea757600360016003805490500381548110611e9557fe5b90600052602060002001549050611eac565b600090505b919050565b606080611ebd4361075d565b915091509091565b60038181548110611ed257fe5b906000526020600020016000915090505481565b600281565b60006020528160005260406000208181548110611f0457fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b600060404381611f5b57fe5b04905090565b60026020528060005260406000206000915090508060000154908060010154908060020154905083565b606080611f9661189d565b8092508193505050600080905060405180606001604052808281526020016000815260200160ff81525060026000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600381908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008381526020019081526020016000208161203f9190612800565b50600060016000838152602001908152602001600020816120609190612800565b5060008090505b83518110156121825760008083815260200190815260200160002080548091906001016120949190612800565b5060405180606001604052808281526020018483815181106120b257fe5b602002602001015181526020018583815181106120cb57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16815250600080848152602001908152602001600020828154811061210957fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612067565b5060008090505b83518110156122a6576001600083815260200190815260200160002080548091906001016121b79190612800565b5060405180606001604052808281526020018483815181106121d557fe5b602002602001015181526020018583815181106121ee57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681525060016000848152602001908152602001600020828154811061222d57fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612189565b50505050565b6000808284019050838110156122c157600080fd5b8091505092915050565b6122d361288a565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061230482612600565b61230d57600080fd5b60006123188361264e565b905060608160405190808252806020026020018201604052801561235657816020015b6123436128a4565b81526020019060019003908161233b5790505b509050600061236885602001516126bf565b8560200151019050600080600090505b848110156123c95761238983612748565b91506040518060400160405280838152602001848152508482815181106123ac57fe5b602002602001018190525081830192508080600101915050612378565b5082945050505050919050565b60008082600001511180156123f057506021826000015111155b6123f957600080fd5b600061240883602001516126bf565b9050600081846000015103905060008083866020015101905080519150602083101561243b57826020036101000a820491505b81945050505050919050565b6000601582600001511461245a57600080fd5b612463826123d6565b9050919050565b60608183018451101561247c57600080fd5b6060821560008114612499576040519150602082016040526124ea565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156124d757805183526020830192506020810190506124ba565b50868552601f19601f8301166040525050505b50809150509392505050565b600080600080604185511461251157600093505050506125fa565b602085015192506040850151915060ff6041860151169050601b8160ff16101561253c57601b810190505b601b8160ff16141580156125545750601c8160ff1614155b1561256557600093505050506125fa565b60006001878386866040516000815260200160405260405161258a94939291906132f1565b6020604051602081039080840390855afa1580156125ac573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125f257600080fd5b809450505050505b92915050565b600080826000015114156126175760009050612649565b60008083602001519050805160001a915060c060ff168260ff16101561264257600092505050612649565b6001925050505b919050565b6000808260000151141561266557600090506126ba565b6000809050600061267984602001516126bf565b84602001510190506000846000015185602001510190505b808210156126b3576126a282612748565b820191508280600101935050612691565b8293505050505b919050565b600080825160001a9050608060ff168110156126df576000915050612743565b60b860ff16811080612704575060c060ff168110158015612703575060f860ff1681105b5b15612713576001915050612743565b60c060ff168110156127335760018060b80360ff16820301915050612743565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561276957600191506127f6565b60b860ff16811015612786576001608060ff1682030191506127f5565b60c060ff168110156127b65760b78103600185019450806020036101000a855104600182018101935050506127f4565b60f860ff168110156127d357600160c060ff1682030191506127f3565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b81548183558181111561282d5760030281600302836000526020600020918201910161282c91906128be565b5b505050565b60405180606001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b60405180606001604052806000815260200160008152602001600081525090565b604051806040016040528060008152602001600081525090565b604051806040016040528060008152602001600081525090565b61291191905b8082111561290d5760008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506003016128c4565b5090565b90565b60008135905061292381613693565b92915050565b600081359050612938816136aa565b92915050565b60008151905061294d816136aa565b92915050565b60008083601f84011261296557600080fd5b8235905067ffffffffffffffff81111561297e57600080fd5b60208301915083600182028301111561299657600080fd5b9250929050565b600082601f8301126129ae57600080fd5b81356129c16129bc826134e2565b6134b5565b915080825260208301602083018583830111156129dd57600080fd5b6129e883828461363d565b50505092915050565b600081359050612a00816136c1565b92915050565b600060208284031215612a1857600080fd5b6000612a2684828501612914565b91505092915050565b600060208284031215612a4157600080fd5b6000612a4f84828501612929565b91505092915050565b600060208284031215612a6a57600080fd5b6000612a788482850161293e565b91505092915050565b60008060408385031215612a9457600080fd5b6000612aa285828601612929565b9250506020612ab385828601612929565b9150509250929050565b600080600060608486031215612ad257600080fd5b6000612ae086828701612929565b9350506020612af186828701612929565b925050604084013567ffffffffffffffff811115612b0e57600080fd5b612b1a8682870161299d565b9150509250925092565b600060208284031215612b3657600080fd5b6000612b44848285016129f1565b91505092915050565b60008060408385031215612b6057600080fd5b6000612b6e858286016129f1565b9250506020612b7f85828601612914565b9150509250929050565b600080600060608486031215612b9e57600080fd5b6000612bac868287016129f1565b9350506020612bbd86828701612929565b925050604084013567ffffffffffffffff811115612bda57600080fd5b612be68682870161299d565b9150509250925092565b60008060408385031215612c0357600080fd5b6000612c11858286016129f1565b9250506020612c22858286016129f1565b9150509250929050565b600080600080600080600060a0888a031215612c4757600080fd5b6000612c558a828b016129f1565b9750506020612c668a828b016129f1565b9650506040612c778a828b016129f1565b955050606088013567ffffffffffffffff811115612c9457600080fd5b612ca08a828b01612953565b9450945050608088013567ffffffffffffffff811115612cbf57600080fd5b612ccb8a828b01612953565b925092505092959891949750929550565b6000612ce88383612d0c565b60208301905092915050565b6000612d00838361317d565b60208301905092915050565b612d15816135b2565b82525050565b612d24816135b2565b82525050565b6000612d358261352e565b612d3f8185613569565b9350612d4a8361350e565b8060005b83811015612d7b578151612d628882612cdc565b9750612d6d8361354f565b925050600181019050612d4e565b5085935050505092915050565b6000612d9382613539565b612d9d818561357a565b9350612da88361351e565b8060005b83811015612dd9578151612dc08882612cf4565b9750612dcb8361355c565b925050600181019050612dac565b5085935050505092915050565b612def816135c4565b82525050565b612e06612e01826135d0565b61367f565b82525050565b612e15816135fc565b82525050565b612e2c612e27826135fc565b613689565b82525050565b6000612e3d82613544565b612e47818561358b565b9350612e5781856020860161364c565b80840191505092915050565b6000612e706004836135a7565b91507f766f7465000000000000000000000000000000000000000000000000000000006000830152600482019050919050565b6000612eb0602d83613596565b91507f537461727420626c6f636b206d7573742062652067726561746572207468616e60008301527f2063757272656e74207370616e000000000000000000000000000000000000006020830152604082019050919050565b6000612f16600f83613596565b91507f496e76616c6964207370616e20696400000000000000000000000000000000006000830152602082019050919050565b6000612f56601383613596565b91507f5370616e20616c726561647920657869737473000000000000000000000000006000830152602082019050919050565b6000612f96604583613596565b91507f446966666572656e6365206265747765656e20737461727420616e6420656e6460008301527f20626c6f636b206d75737420626520696e206d756c7469706c6573206f66207360208301527f7072696e740000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000613022602a83613596565b91507f456e6420626c6f636b206d7573742062652067726561746572207468616e207360008301527f7461727420626c6f636b000000000000000000000000000000000000000000006020830152604082019050919050565b6000613088601283613596565b91507f4e6f742053797374656d204164646573732100000000000000000000000000006000830152602082019050919050565b60006130c86005836135a7565b91507f38303030310000000000000000000000000000000000000000000000000000006000830152600582019050919050565b6000613108600e836135a7565b91507f6865696d64616c6c2d38303030310000000000000000000000000000000000006000830152600e82019050919050565b606082016000820151613151600085018261317d565b506020820151613164602085018261317d565b5060408201516131776040850182612d0c565b50505050565b61318681613626565b82525050565b61319581613626565b82525050565b6131a481613630565b82525050565b60006131b68285612df5565b6001820191506131c68284612e1b565b6020820191508190509392505050565b60006131e28286612df5565b6001820191506131f28285612e1b565b6020820191506132028284612e1b565b602082019150819050949350505050565b600061321f8284612e32565b915081905092915050565b600061323582612e63565b9150819050919050565b600061324a826130bb565b9150819050919050565b600061325f826130fb565b9150819050919050565b600060208201905061327e6000830184612d1b565b92915050565b6000604082019050818103600083015261329e8185612d2a565b905081810360208301526132b28184612d88565b90509392505050565b60006020820190506132d06000830184612de6565b92915050565b60006020820190506132eb6000830184612e0c565b92915050565b60006080820190506133066000830187612e0c565b613313602083018661319b565b6133206040830185612e0c565b61332d6060830184612e0c565b95945050505050565b6000602082019050818103600083015261334f81612ea3565b9050919050565b6000602082019050818103600083015261336f81612f09565b9050919050565b6000602082019050818103600083015261338f81612f49565b9050919050565b600060208201905081810360008301526133af81612f89565b9050919050565b600060208201905081810360008301526133cf81613015565b9050919050565b600060208201905081810360008301526133ef8161307b565b9050919050565b600060608201905061340b600083018461313b565b92915050565b6000602082019050613426600083018461318c565b92915050565b6000606082019050613441600083018661318c565b61344e602083018561318c565b61345b6040830184612d1b565b949350505050565b6000606082019050613478600083018661318c565b613485602083018561318c565b613492604083018461318c565b949350505050565b60006020820190506134af600083018461319b565b92915050565b6000604051905081810181811067ffffffffffffffff821117156134d857600080fd5b8060405250919050565b600067ffffffffffffffff8211156134f957600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006135bd82613606565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561366a57808201518184015260208101905061364f565b83811115613679576000848401525b50505050565b6000819050919050565b6000819050919050565b61369c816135b2565b81146136a757600080fd5b50565b6136b3816135fc565b81146136be57600080fd5b50565b6136ca81613626565b81146136d557600080fd5b5056fea365627a7a723158208f52ee07630ffe523cc6ad3e15f437f973dcfa36729cd697f9b0fc4a145a48f06c6578706572696d656e74616cf564736f6c634300050b0040",
+ "balance":"0x0"
+ },
+ "0000000000000000000000000000000000001001":{
+ "code":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806319494a17146100465780633434735f146100e15780635407ca671461012b575b600080fd5b6100c76004803603604081101561005c57600080fd5b81019080803590602001909291908035906020019064010000000081111561008357600080fd5b82018360208201111561009557600080fd5b803590602001918460018302840111640100000000831117156100b757600080fd5b9091929391929390505050610149565b604051808215151515815260200191505060405180910390f35b6100e961047a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610133610492565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061025761025285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610498565b6104c6565b905060006102788260008151811061026b57fe5b60200260200101516105a3565b905080600160005401146102f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103248360018151811061031757fe5b6020026020010151610614565b905060606103458460028151811061033857fe5b6020026020010151610637565b9050610350826106c3565b1561046f576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103aa57808201518184015260208101905061038f565b50505050905090810190601f1680156103d75780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f1965050505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104a0610943565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606104d1826106dc565b6104da57600080fd5b60006104e58361072a565b905060608160405190808252806020026020018201604052801561052357816020015b61051061095d565b8152602001906001900390816105085790505b5090506000610535856020015161079b565b8560200151019050600080600090505b848110156105965761055683610824565b915060405180604001604052808381526020018481525084828151811061057957fe5b602002602001018190525081830192508080600101915050610545565b5082945050505050919050565b60008082600001511180156105bd57506021826000015111155b6105c657600080fd5b60006105d5836020015161079b565b9050600081846000015103905060008083866020015101905080519150602083101561060857826020036101000a820491505b81945050505050919050565b6000601582600001511461062757600080fd5b610630826105a3565b9050919050565b6060600082600001511161064a57600080fd5b6000610659836020015161079b565b905060008184600001510390506060816040519080825280601f01601f19166020018201604052801561069b5781602001600182028038833980820191505090505b50905060008160200190506106b78487602001510182856108dc565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b600080826000015114156106f35760009050610725565b60008083602001519050805160001a915060c060ff168260ff16101561071e57600092505050610725565b6001925050505b919050565b600080826000015114156107415760009050610796565b60008090506000610755846020015161079b565b84602001510190506000846000015185602001510190505b8082101561078f5761077e82610824565b82019150828060010193505061076d565b8293505050505b919050565b600080825160001a9050608060ff168110156107bb57600091505061081f565b60b860ff168110806107e0575060c060ff1681101580156107df575060f860ff1681105b5b156107ef57600191505061081f565b60c060ff1681101561080f5760018060b80360ff1682030191505061081f565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561084557600191506108d2565b60b860ff16811015610862576001608060ff1682030191506108d1565b60c060ff168110156108925760b78103600185019450806020036101000a855104600182018101935050506108d0565b60f860ff168110156108af57600160c060ff1682030191506108cf565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b60008114156108ea5761093e565b5b602060ff16811061091a5782518252602060ff1683019250602060ff1682019150602060ff16810390506108eb565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a7231582083fbdacb76f32b4112d0f7db9a596937925824798a0026ba0232322390b5263764736f6c634300050b0032",
+ "balance":"0x0"
+ },
+ "0000000000000000000000000000000000001010":{
+ "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610e06565b005b3480156103eb57600080fd5b506103f4610f58565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f61565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061111d565b005b3480156104e857600080fd5b506104f16111ec565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b50610548611212565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611238565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b50610604611259565b005b34801561061257600080fd5b5061061b611329565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061132f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b506107586114b4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af6114dd565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de611534565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e61156d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506115aa565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b506109646115d0565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b810190808035906020019092919050505061165d565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919050505061167d565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a6561169d565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a906116a4565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb6116aa565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611737565b005b348015610b2e57600080fd5b50610b37611754565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b6000808511610c4857600080fd5b6000831480610c575750824311155b610cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5369676e6174757265206973206578706972656400000000000000000000000081525060200191505060405180910390fd5b6000610cd73387878761167d565b9050600015156005600083815260200190815260200160002060009054906101000a900460ff16151514610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f536967206465616374697661746564000000000000000000000000000000000081525060200191505060405180910390fd5b60016005600083815260200190815260200160002060006101000a81548160ff021916908315150217905550610ded8189898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061132f565b9150610dfa82848861177a565b50509695505050505050565b60003390506000610e1682611238565b9050610e2d83600654611b3790919063ffffffff16565b600681905550600083118015610e4257508234145b610eb4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610f3087611238565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610f696114dd565b610f7257600080fd5b600081118015610faf5750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e636023913960400191505060405180910390fd5b600061100f83611238565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f1935050505015801561105c573d6000803e3d6000fd5b5061107283600654611b5790919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f685856110f489611238565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611183576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e406023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506111e882611b76565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b6112616114dd565b61126a57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b600080600080604185511461134a57600093505050506114ae565b602085015192506040850151915060ff6041860151169050601b8160ff16101561137557601b810190505b601b8160ff161415801561138d5750601c8160ff1614155b1561139e57600093505050506114ae565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156113fb573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156114aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b60008134146115bc57600090506115ca565b6115c733848461177a565b90505b92915050565b6040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b6020831061161f57805182526020820191506020810190506020830392506115fc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061169361168e86868686611c6e565b611d44565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611e86605291396040516020018082805190602001908083835b602083106116f957805182526020820191506020810190506020830392506116d6565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b61173f6114dd565b61174857600080fd5b61175181611b76565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d602081101561182457600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156118b657600080fd5b505afa1580156118ca573d6000803e3d6000fd5b505050506040513d60208110156118e057600080fd5b810190808051906020019092919050505090506118fe868686611d8e565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a0657600080fd5b505afa158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611abe57600080fd5b505afa158015611ad2573d6000803e3d6000fd5b505050506040513d6020811015611ae857600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b600082821115611b4657600080fd5b600082840390508091505092915050565b600080828401905083811015611b6c57600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611bb057600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000806040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b60208310611cc05780518252602082019150602081019050602083039250611c9d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611dd4573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158208f81700133738d766ae3d68af591ad588b0125bd91449192179f460893f79f6b64736f6c634300050b0032",
+ "balance":"0x204fcd4f31349d83b6e00000"
+ },
+ "928ed6a3e94437bbd316ccad78479f1d163a6a8c":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "be188d6641e8b680743a4815dfa0f6208038960f":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "c26880a0af2ea0c7e8130e6ec47af756465452e8":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "c275dc8be39f50d12f66b6a63629c39da5bae5bd":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "f903ba9e006193c1527bfbe65fe2123704ea3f99":{
+ "balance":"0x3635c9adc5dea00000"
+ }
+ },
+ "number":"0x0",
+ "gasUsed":"0x0",
+ "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
+ "baseFeePerGas":null
+}
diff --git a/internal/cli/server/chains/test_files/chain_test.json b/internal/cli/server/chains/test_files/chain_test.json
new file mode 100644
index 0000000000..5bfe155d27
--- /dev/null
+++ b/internal/cli/server/chains/test_files/chain_test.json
@@ -0,0 +1,92 @@
+{
+ "Hash":"0x7b66506a9ebdbf30d32b43c5f15a3b1216269a1ec3a75aa3182b86176a2b1ca7",
+ "Genesis":{
+ "config":{
+ "chainId":80001,
+ "homesteadBlock":0,
+ "daoForkSupport":true,
+ "eip150Block":0,
+ "eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000",
+ "eip155Block":0,
+ "eip158Block":0,
+ "byzantiumBlock":0,
+ "constantinopleBlock":0,
+ "petersburgBlock":0,
+ "istanbulBlock":2722000,
+ "muirGlacierBlock":2722000,
+ "berlinBlock":13996000,
+ "londonBlock":13996000,
+ "bor":{
+ "period":{
+ "0":2
+ },
+ "producerDelay":6,
+ "sprint":64,
+ "backupMultiplier":{
+ "0":2
+ },
+ "validatorContract":"0x0000000000000000000000000000000000001000",
+ "stateReceiverContract":"0x0000000000000000000000000000000000001001",
+ "overrideStateSyncRecords":null,
+ "blockAlloc":{
+ "22244000":{
+ "0000000000000000000000000000000000001010":{
+ "balance":"0x0",
+ "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611548565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154e565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115db565b005b348015610b2e57600080fd5b50610b376115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161e90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da96023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163e90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d866023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165d565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611755565b90505b92915050565b6040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b12565b611be8565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611dcc605291396040516020018082805190602001908083835b6020831061159d578051825260208201915060208101905060208303925061157a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e3611381565b6115ec57600080fd5b6115f58161165d565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162d57600080fd5b600082840390508091505092915050565b60008082840190508381101561165357600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d557600080fd5b505afa1580156117e9573d6000803e3d6000fd5b505050506040513d60208110156117ff57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561189157600080fd5b505afa1580156118a5573d6000803e3d6000fd5b505050506040513d60208110156118bb57600080fd5b810190808051906020019092919050505090506118d9868686611c32565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119e157600080fd5b505afa1580156119f5573d6000803e3d6000fd5b505050506040513d6020811015611a0b57600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9957600080fd5b505afa158015611aad573d6000803e3d6000fd5b505050506040513d6020811015611ac357600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b60208310611b645780518252602082019150602081019050602083039250611b41565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d1a573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820ccd6c2a9c259832bbb367986ee06cd87af23022681b0cb22311a864b701d939564736f6c63430005100032"
+ }
+ }
+ },
+ "burntContract":{
+ "22640000":"0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"
+ },
+ "jaipurBlock":22770000
+ }
+ },
+ "nonce":"0x0",
+ "timestamp":"0x5ce28211",
+ "extraData":"0x",
+ "gasLimit":"0x989680",
+ "difficulty":"0x1",
+ "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase":"0x0000000000000000000000000000000000000000",
+ "alloc":{
+ "0000000000000000000000000000000000001000":{
+ "code":"0x608060405234801561001057600080fd5b50600436106101f05760003560e01c806360c8614d1161010f578063af26aa96116100a2578063d5b844eb11610071578063d5b844eb14610666578063dcf2793a14610684578063e3b7c924146106b6578063f59cf565146106d4576101f0565b8063af26aa96146105c7578063b71d7a69146105e7578063b7ab4db514610617578063c1b3c91914610636576101f0565b806370ba5707116100de57806370ba57071461052b57806398ab2b621461055b5780639d11b80714610579578063ae756451146105a9576101f0565b806360c8614d1461049c57806365b3a1e2146104bc57806366332354146104db578063687a9bd6146104f9576101f0565b80633434735f1161018757806344d6528f1161015657806344d6528f146103ee5780634dbc959f1461041e57806355614fcc1461043c578063582a8d081461046c576101f0565b80633434735f1461035257806335ddfeea1461037057806343ee8213146103a057806344c15cb1146103be576101f0565b806323f2a73f116101c357806323f2a73f146102a45780632bc06564146102d45780632de3a180146102f25780632eddf35214610322576101f0565b8063047a6c5b146101f55780630c35b1cb146102275780631270b5741461025857806323c2a2b414610288575b600080fd5b61020f600480360361020a9190810190612b24565b610706565b60405161021e93929190613463565b60405180910390f35b610241600480360361023c9190810190612b24565b61075d565b60405161024f929190613284565b60405180910390f35b610272600480360361026d9190810190612b4d565b610939565b60405161027f91906132bb565b60405180910390f35b6102a2600480360361029d9190810190612c2c565b610a91565b005b6102be60048036036102b99190810190612b4d565b61112a565b6040516102cb91906132bb565b60405180910390f35b6102dc611281565b6040516102e99190613411565b60405180910390f35b61030c60048036036103079190810190612a81565b611286565b60405161031991906132d6565b60405180910390f35b61033c60048036036103379190810190612b24565b611307565b6040516103499190613411565b60405180910390f35b61035a611437565b6040516103679190613269565b60405180910390f35b61038a60048036036103859190810190612abd565b61144f565b60405161039791906132bb565b60405180910390f35b6103a861151a565b6040516103b591906132d6565b60405180910390f35b6103d860048036036103d39190810190612b89565b611531565b6040516103e59190613411565b60405180910390f35b61040860048036036104039190810190612b4d565b611619565b60405161041591906133f6565b60405180910390f35b610426611781565b6040516104339190613411565b60405180910390f35b61045660048036036104519190810190612a06565b611791565b60405161046391906132bb565b60405180910390f35b61048660048036036104819190810190612a2f565b6117ab565b60405161049391906132d6565b60405180910390f35b6104a4611829565b6040516104b393929190613463565b60405180910390f35b6104c461189d565b6040516104d2929190613284565b60405180910390f35b6104e3611b6e565b6040516104f09190613411565b60405180910390f35b610513600480360361050e9190810190612bf0565b611b73565b6040516105229392919061342c565b60405180910390f35b61054560048036036105409190810190612a06565b611bd7565b60405161055291906132bb565b60405180910390f35b610563611bf1565b60405161057091906132d6565b60405180910390f35b610593600480360361058e9190810190612b24565b611c08565b6040516105a09190613411565b60405180910390f35b6105b1611d39565b6040516105be91906132d6565b60405180910390f35b6105cf611d50565b6040516105de93929190613463565b60405180910390f35b61060160048036036105fc9190810190612b24565b611db1565b60405161060e9190613411565b60405180910390f35b61061f611eb1565b60405161062d929190613284565b60405180910390f35b610650600480360361064b9190810190612b24565b611ec5565b60405161065d9190613411565b60405180910390f35b61066e611ee6565b60405161067b919061349a565b60405180910390f35b61069e60048036036106999190810190612bf0565b611eeb565b6040516106ad9392919061342c565b60405180910390f35b6106be611f4f565b6040516106cb9190613411565b60405180910390f35b6106ee60048036036106e99190810190612b24565b611f61565b6040516106fd93929190613463565b60405180910390f35b60008060006002600085815260200190815260200160002060000154600260008681526020019081526020016000206001015460026000878152602001908152602001600020600201549250925092509193909250565b60608060ff83116107795761077061189d565b91509150610934565b600061078484611db1565b9050606060016000838152602001908152602001600020805490506040519080825280602002602001820160405280156107cd5781602001602082028038833980820191505090505b509050606060016000848152602001908152602001600020805490506040519080825280602002602001820160405280156108175781602001602082028038833980820191505090505b50905060008090505b60016000858152602001908152602001600020805490508110156109295760016000858152602001908152602001600020818154811061085c57fe5b906000526020600020906003020160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683828151811061089a57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001600085815260200190815260200160002081815481106108f257fe5b90600052602060002090600302016001015482828151811061091057fe5b6020026020010181815250508080600101915050610820565b508181945094505050505b915091565b6000606060016000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610a0c578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190610970565b50505050905060008090505b8151811015610a84578373ffffffffffffffffffffffffffffffffffffffff16828281518110610a4457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff161415610a7757600192505050610a8b565b8080600101915050610a18565b5060009150505b92915050565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0a906133d6565b60405180910390fd5b6000610b1d611781565b90506000811415610b3157610b30611f8b565b5b610b456001826122ac90919063ffffffff16565b8814610b86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7d90613356565b60405180910390fd5b868611610bc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbf906133b6565b60405180910390fd5b6000604060018989030181610bd957fe5b0614610c1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1190613396565b60405180910390fd5b8660026000838152602001908152602001600020600101541115610c73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6a90613336565b60405180910390fd5b6000600260008a81526020019081526020016000206000015414610ccc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc390613376565b60405180910390fd5b604051806060016040528089815260200188815260200187815250600260008a8152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600388908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008a815260200190815260200160002081610d669190612800565b506000600160008a815260200190815260200160002081610d879190612800565b506060610ddf610dda87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b8151811015610f51576060610e0e838381518110610e0157fe5b60200260200101516122f9565b90506000808c81526020019081526020016000208054809190600101610e349190612800565b506040518060600160405280610e5d83600081518110610e5057fe5b60200260200101516123d6565b8152602001610e7f83600181518110610e7257fe5b60200260200101516123d6565b8152602001610ea183600281518110610e9457fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff168152506000808d81526020019081526020016000208381548110610ed757fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610de7565b506060610fa9610fa486868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b815181101561111d576060610fd8838381518110610fcb57fe5b60200260200101516122f9565b9050600160008d81526020019081526020016000208054809190600101610fff9190612800565b5060405180606001604052806110288360008151811061101b57fe5b60200260200101516123d6565b815260200161104a8360018151811061103d57fe5b60200260200101516123d6565b815260200161106c8360028151811061105f57fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff16815250600160008e815260200190815260200160002083815481106110a357fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610fb1565b5050505050505050505050565b60006060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156111fc578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611160565b50505050905060008090505b8151811015611274578373ffffffffffffffffffffffffffffffffffffffff1682828151811061123457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff1614156112675760019250505061127b565b8080600101915050611208565b5060009150505b92915050565b604081565b60006002600160f81b84846040516020016112a3939291906131d6565b6040516020818303038152906040526040516112bf9190613213565b602060405180830381855afa1580156112dc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506112ff9190810190612a58565b905092915050565b60006060600080848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156113d9578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001906001019061133d565b505050509050600080905060008090505b825181101561142c5761141d83828151811061140257fe5b602002602001015160200151836122ac90919063ffffffff16565b915080806001019150506113ea565b508092505050919050565b73fffffffffffffffffffffffffffffffffffffffe81565b600080600080859050600060218087518161146657fe5b04029050600081111561147f5761147c876117ab565b91505b6000602190505b818111611509576000600182038801519050818801519550806000602081106114ab57fe5b1a60f81b9450600060f81b857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156114f0576114e98685611286565b93506114fd565b6114fa8487611286565b93505b50602181019050611486565b508782149450505050509392505050565b60405161152690613254565b604051809103902081565b60008060009050600080905060008090505b84518167ffffffffffffffff16101561160c57606061156e868367ffffffffffffffff16604161246a565b9050600061158582896124f690919063ffffffff16565b905061158f612832565b6115998a83611619565b90506115a58a8361112a565b80156115dc57508473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16115b156115fe578194506115fb8160200151876122ac90919063ffffffff16565b95505b505050604181019050611543565b5081925050509392505050565b611621612832565b6060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156116f1578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611655565b50505050905060008090505b8151811015611779578373ffffffffffffffffffffffffffffffffffffffff1682828151811061172957fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff16141561176c5781818151811061175d57fe5b60200260200101519250611779565b80806001019150506116fd565b505092915050565b600061178c43611db1565b905090565b60006117a461179e611781565b8361112a565b9050919050565b60006002600060f81b836040516020016117c69291906131aa565b6040516020818303038152906040526040516117e29190613213565b602060405180830381855afa1580156117ff573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506118229190810190612a58565b9050919050565b60008060008061184a600161183c611781565b6122ac90919063ffffffff16565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b606080606060056040519080825280602002602001820160405280156118d25781602001602082028038833980820191505090505b50905073c26880a0af2ea0c7e8130e6ec47af756465452e8816000815181106118f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073be188d6641e8b680743a4815dfa0f6208038960f8160018151811061195357fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c275dc8be39f50d12f66b6a63629c39da5bae5bd816002815181106119af57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073f903ba9e006193c1527bfbe65fe2123704ea3f9981600381518110611a0b57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073928ed6a3e94437bbd316ccad78479f1d163a6a8c81600481518110611a6757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060606005604051908082528060200260200182016040528015611ad35781602001602082028038833980820191505090505b50905061271081600081518110611ae657fe5b60200260200101818152505061271081600181518110611b0257fe5b60200260200101818152505061271081600281518110611b1e57fe5b60200260200101818152505061271081600381518110611b3a57fe5b60200260200101818152505061271081600481518110611b5657fe5b60200260200101818152505081819350935050509091565b60ff81565b60016020528160005260406000208181548110611b8c57fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b6000611bea611be4611781565b83610939565b9050919050565b604051611bfd9061322a565b604051809103902081565b6000606060016000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611cdb578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611c3f565b505050509050600080905060008090505b8251811015611d2e57611d1f838281518110611d0457fe5b602002602001015160200151836122ac90919063ffffffff16565b91508080600101915050611cec565b508092505050919050565b604051611d459061323f565b604051809103902081565b600080600080611d5e611781565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b60008060038054905090505b6000811115611e7157611dce612869565b6002600060036001850381548110611de257fe5b906000526020600020015481526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905083816020015111158015611e3f57506000816040015114155b8015611e4f575080604001518411155b15611e6257806000015192505050611eac565b50808060019003915050611dbd565b5060006003805490501115611ea757600360016003805490500381548110611e9557fe5b90600052602060002001549050611eac565b600090505b919050565b606080611ebd4361075d565b915091509091565b60038181548110611ed257fe5b906000526020600020016000915090505481565b600281565b60006020528160005260406000208181548110611f0457fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b600060404381611f5b57fe5b04905090565b60026020528060005260406000206000915090508060000154908060010154908060020154905083565b606080611f9661189d565b8092508193505050600080905060405180606001604052808281526020016000815260200160ff81525060026000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600381908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008381526020019081526020016000208161203f9190612800565b50600060016000838152602001908152602001600020816120609190612800565b5060008090505b83518110156121825760008083815260200190815260200160002080548091906001016120949190612800565b5060405180606001604052808281526020018483815181106120b257fe5b602002602001015181526020018583815181106120cb57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16815250600080848152602001908152602001600020828154811061210957fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612067565b5060008090505b83518110156122a6576001600083815260200190815260200160002080548091906001016121b79190612800565b5060405180606001604052808281526020018483815181106121d557fe5b602002602001015181526020018583815181106121ee57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681525060016000848152602001908152602001600020828154811061222d57fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612189565b50505050565b6000808284019050838110156122c157600080fd5b8091505092915050565b6122d361288a565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061230482612600565b61230d57600080fd5b60006123188361264e565b905060608160405190808252806020026020018201604052801561235657816020015b6123436128a4565b81526020019060019003908161233b5790505b509050600061236885602001516126bf565b8560200151019050600080600090505b848110156123c95761238983612748565b91506040518060400160405280838152602001848152508482815181106123ac57fe5b602002602001018190525081830192508080600101915050612378565b5082945050505050919050565b60008082600001511180156123f057506021826000015111155b6123f957600080fd5b600061240883602001516126bf565b9050600081846000015103905060008083866020015101905080519150602083101561243b57826020036101000a820491505b81945050505050919050565b6000601582600001511461245a57600080fd5b612463826123d6565b9050919050565b60608183018451101561247c57600080fd5b6060821560008114612499576040519150602082016040526124ea565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156124d757805183526020830192506020810190506124ba565b50868552601f19601f8301166040525050505b50809150509392505050565b600080600080604185511461251157600093505050506125fa565b602085015192506040850151915060ff6041860151169050601b8160ff16101561253c57601b810190505b601b8160ff16141580156125545750601c8160ff1614155b1561256557600093505050506125fa565b60006001878386866040516000815260200160405260405161258a94939291906132f1565b6020604051602081039080840390855afa1580156125ac573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125f257600080fd5b809450505050505b92915050565b600080826000015114156126175760009050612649565b60008083602001519050805160001a915060c060ff168260ff16101561264257600092505050612649565b6001925050505b919050565b6000808260000151141561266557600090506126ba565b6000809050600061267984602001516126bf565b84602001510190506000846000015185602001510190505b808210156126b3576126a282612748565b820191508280600101935050612691565b8293505050505b919050565b600080825160001a9050608060ff168110156126df576000915050612743565b60b860ff16811080612704575060c060ff168110158015612703575060f860ff1681105b5b15612713576001915050612743565b60c060ff168110156127335760018060b80360ff16820301915050612743565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561276957600191506127f6565b60b860ff16811015612786576001608060ff1682030191506127f5565b60c060ff168110156127b65760b78103600185019450806020036101000a855104600182018101935050506127f4565b60f860ff168110156127d357600160c060ff1682030191506127f3565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b81548183558181111561282d5760030281600302836000526020600020918201910161282c91906128be565b5b505050565b60405180606001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b60405180606001604052806000815260200160008152602001600081525090565b604051806040016040528060008152602001600081525090565b604051806040016040528060008152602001600081525090565b61291191905b8082111561290d5760008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506003016128c4565b5090565b90565b60008135905061292381613693565b92915050565b600081359050612938816136aa565b92915050565b60008151905061294d816136aa565b92915050565b60008083601f84011261296557600080fd5b8235905067ffffffffffffffff81111561297e57600080fd5b60208301915083600182028301111561299657600080fd5b9250929050565b600082601f8301126129ae57600080fd5b81356129c16129bc826134e2565b6134b5565b915080825260208301602083018583830111156129dd57600080fd5b6129e883828461363d565b50505092915050565b600081359050612a00816136c1565b92915050565b600060208284031215612a1857600080fd5b6000612a2684828501612914565b91505092915050565b600060208284031215612a4157600080fd5b6000612a4f84828501612929565b91505092915050565b600060208284031215612a6a57600080fd5b6000612a788482850161293e565b91505092915050565b60008060408385031215612a9457600080fd5b6000612aa285828601612929565b9250506020612ab385828601612929565b9150509250929050565b600080600060608486031215612ad257600080fd5b6000612ae086828701612929565b9350506020612af186828701612929565b925050604084013567ffffffffffffffff811115612b0e57600080fd5b612b1a8682870161299d565b9150509250925092565b600060208284031215612b3657600080fd5b6000612b44848285016129f1565b91505092915050565b60008060408385031215612b6057600080fd5b6000612b6e858286016129f1565b9250506020612b7f85828601612914565b9150509250929050565b600080600060608486031215612b9e57600080fd5b6000612bac868287016129f1565b9350506020612bbd86828701612929565b925050604084013567ffffffffffffffff811115612bda57600080fd5b612be68682870161299d565b9150509250925092565b60008060408385031215612c0357600080fd5b6000612c11858286016129f1565b9250506020612c22858286016129f1565b9150509250929050565b600080600080600080600060a0888a031215612c4757600080fd5b6000612c558a828b016129f1565b9750506020612c668a828b016129f1565b9650506040612c778a828b016129f1565b955050606088013567ffffffffffffffff811115612c9457600080fd5b612ca08a828b01612953565b9450945050608088013567ffffffffffffffff811115612cbf57600080fd5b612ccb8a828b01612953565b925092505092959891949750929550565b6000612ce88383612d0c565b60208301905092915050565b6000612d00838361317d565b60208301905092915050565b612d15816135b2565b82525050565b612d24816135b2565b82525050565b6000612d358261352e565b612d3f8185613569565b9350612d4a8361350e565b8060005b83811015612d7b578151612d628882612cdc565b9750612d6d8361354f565b925050600181019050612d4e565b5085935050505092915050565b6000612d9382613539565b612d9d818561357a565b9350612da88361351e565b8060005b83811015612dd9578151612dc08882612cf4565b9750612dcb8361355c565b925050600181019050612dac565b5085935050505092915050565b612def816135c4565b82525050565b612e06612e01826135d0565b61367f565b82525050565b612e15816135fc565b82525050565b612e2c612e27826135fc565b613689565b82525050565b6000612e3d82613544565b612e47818561358b565b9350612e5781856020860161364c565b80840191505092915050565b6000612e706004836135a7565b91507f766f7465000000000000000000000000000000000000000000000000000000006000830152600482019050919050565b6000612eb0602d83613596565b91507f537461727420626c6f636b206d7573742062652067726561746572207468616e60008301527f2063757272656e74207370616e000000000000000000000000000000000000006020830152604082019050919050565b6000612f16600f83613596565b91507f496e76616c6964207370616e20696400000000000000000000000000000000006000830152602082019050919050565b6000612f56601383613596565b91507f5370616e20616c726561647920657869737473000000000000000000000000006000830152602082019050919050565b6000612f96604583613596565b91507f446966666572656e6365206265747765656e20737461727420616e6420656e6460008301527f20626c6f636b206d75737420626520696e206d756c7469706c6573206f66207360208301527f7072696e740000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000613022602a83613596565b91507f456e6420626c6f636b206d7573742062652067726561746572207468616e207360008301527f7461727420626c6f636b000000000000000000000000000000000000000000006020830152604082019050919050565b6000613088601283613596565b91507f4e6f742053797374656d204164646573732100000000000000000000000000006000830152602082019050919050565b60006130c86005836135a7565b91507f38303030310000000000000000000000000000000000000000000000000000006000830152600582019050919050565b6000613108600e836135a7565b91507f6865696d64616c6c2d38303030310000000000000000000000000000000000006000830152600e82019050919050565b606082016000820151613151600085018261317d565b506020820151613164602085018261317d565b5060408201516131776040850182612d0c565b50505050565b61318681613626565b82525050565b61319581613626565b82525050565b6131a481613630565b82525050565b60006131b68285612df5565b6001820191506131c68284612e1b565b6020820191508190509392505050565b60006131e28286612df5565b6001820191506131f28285612e1b565b6020820191506132028284612e1b565b602082019150819050949350505050565b600061321f8284612e32565b915081905092915050565b600061323582612e63565b9150819050919050565b600061324a826130bb565b9150819050919050565b600061325f826130fb565b9150819050919050565b600060208201905061327e6000830184612d1b565b92915050565b6000604082019050818103600083015261329e8185612d2a565b905081810360208301526132b28184612d88565b90509392505050565b60006020820190506132d06000830184612de6565b92915050565b60006020820190506132eb6000830184612e0c565b92915050565b60006080820190506133066000830187612e0c565b613313602083018661319b565b6133206040830185612e0c565b61332d6060830184612e0c565b95945050505050565b6000602082019050818103600083015261334f81612ea3565b9050919050565b6000602082019050818103600083015261336f81612f09565b9050919050565b6000602082019050818103600083015261338f81612f49565b9050919050565b600060208201905081810360008301526133af81612f89565b9050919050565b600060208201905081810360008301526133cf81613015565b9050919050565b600060208201905081810360008301526133ef8161307b565b9050919050565b600060608201905061340b600083018461313b565b92915050565b6000602082019050613426600083018461318c565b92915050565b6000606082019050613441600083018661318c565b61344e602083018561318c565b61345b6040830184612d1b565b949350505050565b6000606082019050613478600083018661318c565b613485602083018561318c565b613492604083018461318c565b949350505050565b60006020820190506134af600083018461319b565b92915050565b6000604051905081810181811067ffffffffffffffff821117156134d857600080fd5b8060405250919050565b600067ffffffffffffffff8211156134f957600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006135bd82613606565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561366a57808201518184015260208101905061364f565b83811115613679576000848401525b50505050565b6000819050919050565b6000819050919050565b61369c816135b2565b81146136a757600080fd5b50565b6136b3816135fc565b81146136be57600080fd5b50565b6136ca81613626565b81146136d557600080fd5b5056fea365627a7a723158208f52ee07630ffe523cc6ad3e15f437f973dcfa36729cd697f9b0fc4a145a48f06c6578706572696d656e74616cf564736f6c634300050b0040",
+ "balance":"0x0"
+ },
+ "0000000000000000000000000000000000001001":{
+ "code":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806319494a17146100465780633434735f146100e15780635407ca671461012b575b600080fd5b6100c76004803603604081101561005c57600080fd5b81019080803590602001909291908035906020019064010000000081111561008357600080fd5b82018360208201111561009557600080fd5b803590602001918460018302840111640100000000831117156100b757600080fd5b9091929391929390505050610149565b604051808215151515815260200191505060405180910390f35b6100e961047a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610133610492565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061025761025285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610498565b6104c6565b905060006102788260008151811061026b57fe5b60200260200101516105a3565b905080600160005401146102f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103248360018151811061031757fe5b6020026020010151610614565b905060606103458460028151811061033857fe5b6020026020010151610637565b9050610350826106c3565b1561046f576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103aa57808201518184015260208101905061038f565b50505050905090810190601f1680156103d75780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f1965050505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104a0610943565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606104d1826106dc565b6104da57600080fd5b60006104e58361072a565b905060608160405190808252806020026020018201604052801561052357816020015b61051061095d565b8152602001906001900390816105085790505b5090506000610535856020015161079b565b8560200151019050600080600090505b848110156105965761055683610824565b915060405180604001604052808381526020018481525084828151811061057957fe5b602002602001018190525081830192508080600101915050610545565b5082945050505050919050565b60008082600001511180156105bd57506021826000015111155b6105c657600080fd5b60006105d5836020015161079b565b9050600081846000015103905060008083866020015101905080519150602083101561060857826020036101000a820491505b81945050505050919050565b6000601582600001511461062757600080fd5b610630826105a3565b9050919050565b6060600082600001511161064a57600080fd5b6000610659836020015161079b565b905060008184600001510390506060816040519080825280601f01601f19166020018201604052801561069b5781602001600182028038833980820191505090505b50905060008160200190506106b78487602001510182856108dc565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b600080826000015114156106f35760009050610725565b60008083602001519050805160001a915060c060ff168260ff16101561071e57600092505050610725565b6001925050505b919050565b600080826000015114156107415760009050610796565b60008090506000610755846020015161079b565b84602001510190506000846000015185602001510190505b8082101561078f5761077e82610824565b82019150828060010193505061076d565b8293505050505b919050565b600080825160001a9050608060ff168110156107bb57600091505061081f565b60b860ff168110806107e0575060c060ff1681101580156107df575060f860ff1681105b5b156107ef57600191505061081f565b60c060ff1681101561080f5760018060b80360ff1682030191505061081f565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561084557600191506108d2565b60b860ff16811015610862576001608060ff1682030191506108d1565b60c060ff168110156108925760b78103600185019450806020036101000a855104600182018101935050506108d0565b60f860ff168110156108af57600160c060ff1682030191506108cf565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b60008114156108ea5761093e565b5b602060ff16811061091a5782518252602060ff1683019250602060ff1682019150602060ff16810390506108eb565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a7231582083fbdacb76f32b4112d0f7db9a596937925824798a0026ba0232322390b5263764736f6c634300050b0032",
+ "balance":"0x0"
+ },
+ "0000000000000000000000000000000000001010":{
+ "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610e06565b005b3480156103eb57600080fd5b506103f4610f58565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f61565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061111d565b005b3480156104e857600080fd5b506104f16111ec565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b50610548611212565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611238565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b50610604611259565b005b34801561061257600080fd5b5061061b611329565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061132f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b506107586114b4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af6114dd565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de611534565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e61156d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506115aa565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b506109646115d0565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b810190808035906020019092919050505061165d565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919050505061167d565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a6561169d565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a906116a4565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb6116aa565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611737565b005b348015610b2e57600080fd5b50610b37611754565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b6000808511610c4857600080fd5b6000831480610c575750824311155b610cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5369676e6174757265206973206578706972656400000000000000000000000081525060200191505060405180910390fd5b6000610cd73387878761167d565b9050600015156005600083815260200190815260200160002060009054906101000a900460ff16151514610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f536967206465616374697661746564000000000000000000000000000000000081525060200191505060405180910390fd5b60016005600083815260200190815260200160002060006101000a81548160ff021916908315150217905550610ded8189898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061132f565b9150610dfa82848861177a565b50509695505050505050565b60003390506000610e1682611238565b9050610e2d83600654611b3790919063ffffffff16565b600681905550600083118015610e4257508234145b610eb4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610f3087611238565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610f696114dd565b610f7257600080fd5b600081118015610faf5750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e636023913960400191505060405180910390fd5b600061100f83611238565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f1935050505015801561105c573d6000803e3d6000fd5b5061107283600654611b5790919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f685856110f489611238565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611183576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e406023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506111e882611b76565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b6112616114dd565b61126a57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b600080600080604185511461134a57600093505050506114ae565b602085015192506040850151915060ff6041860151169050601b8160ff16101561137557601b810190505b601b8160ff161415801561138d5750601c8160ff1614155b1561139e57600093505050506114ae565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156113fb573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156114aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b60008134146115bc57600090506115ca565b6115c733848461177a565b90505b92915050565b6040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b6020831061161f57805182526020820191506020810190506020830392506115fc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061169361168e86868686611c6e565b611d44565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611e86605291396040516020018082805190602001908083835b602083106116f957805182526020820191506020810190506020830392506116d6565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b61173f6114dd565b61174857600080fd5b61175181611b76565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d602081101561182457600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156118b657600080fd5b505afa1580156118ca573d6000803e3d6000fd5b505050506040513d60208110156118e057600080fd5b810190808051906020019092919050505090506118fe868686611d8e565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a0657600080fd5b505afa158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611abe57600080fd5b505afa158015611ad2573d6000803e3d6000fd5b505050506040513d6020811015611ae857600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b600082821115611b4657600080fd5b600082840390508091505092915050565b600080828401905083811015611b6c57600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611bb057600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000806040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b60208310611cc05780518252602082019150602081019050602083039250611c9d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611dd4573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158208f81700133738d766ae3d68af591ad588b0125bd91449192179f460893f79f6b64736f6c634300050b0032",
+ "balance":"0x204fcd4f31349d83b6e00000"
+ },
+ "928ed6a3e94437bbd316ccad78479f1d163a6a8c":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "be188d6641e8b680743a4815dfa0f6208038960f":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "c26880a0af2ea0c7e8130e6ec47af756465452e8":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "c275dc8be39f50d12f66b6a63629c39da5bae5bd":{
+ "balance":"0x3635c9adc5dea00000"
+ },
+ "f903ba9e006193c1527bfbe65fe2123704ea3f99":{
+ "balance":"0x3635c9adc5dea00000"
+ }
+ },
+ "number":"0x0",
+ "gasUsed":"0x0",
+ "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
+ "baseFeePerGas":null
+ },
+ "Bootnodes":[
+ "enode://320553cda00dfc003f499a3ce9598029f364fbb3ed1222fdc20a94d97dcc4d8ba0cd0bfa996579dcc6d17a534741fb0a5da303a90579431259150de66b597251@54.147.31.250:30303",
+ "enode://f0f48a8781629f95ff02606081e6e43e4aebd503f3d07fc931fad7dd5ca1ba52bd849a6f6c3be0e375cf13c9ae04d859c4a9ae3546dc8ed4f10aa5dbb47d4998@34.226.134.117:30303"
+ ],
+ "NetworkId":80001,
+ "DNS":null
+ }
diff --git a/internal/cli/server/chains/test_files/wrong_chain.json b/internal/cli/server/chains/test_files/wrong_chain.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/internal/cli/server/chains/test_files/wrong_chain.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/internal/cli/server/command.go b/internal/cli/server/command.go
index 4b2374dc42..a0b8a6d87c 100644
--- a/internal/cli/server/command.go
+++ b/internal/cli/server/command.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/signal"
+ "strings"
"syscall"
"github.com/ethereum/go-ethereum/log"
@@ -25,6 +26,17 @@ type Command struct {
srv *Server
}
+// MarkDown implements cli.MarkDown interface
+func (c *Command) MarkDown() string {
+ items := []string{
+ "# Server",
+ "The ```bor server``` command runs the Bor client.",
+ c.Flags().MarkDown(),
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (c *Command) Help() string {
return `Usage: bor [options]
diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go
index 06ec8c16af..ab8c8e5155 100644
--- a/internal/cli/server/config.go
+++ b/internal/cli/server/config.go
@@ -43,8 +43,8 @@ type Config struct {
// Name, or identity of the node
Name string `hcl:"name,optional"`
- // Whitelist is a list of required (block number, hash) pairs to accept
- Whitelist map[string]string `hcl:"whitelist,optional"`
+ // RequiredBlocks is a list of required (block number, hash) pairs to accept
+ RequiredBlocks map[string]string `hcl:"requiredblocks,optional"`
// LogLevel is the level of the logs to put out
LogLevel string `hcl:"log-level,optional"`
@@ -52,14 +52,17 @@ type Config struct {
// DataDir is the directory to store the state in
DataDir string `hcl:"data-dir,optional"`
+ // KeyStoreDir is the directory to store keystores
+ KeyStoreDir string `hcl:"keystore-dir,optional"`
+
// SyncMode selects the sync protocol
SyncMode string `hcl:"sync-mode,optional"`
// GcMode selects the garbage collection mode for the trie
GcMode string `hcl:"gc-mode,optional"`
- // XXX
- Snapshot bool `hcl:"snapshot,optional"`
+ // NoSnapshot disables the snapshot database mode
+ NoSnapshot bool `hcl:"no-snapshot,optional"`
// Ethstats is the address of the ethstats server to send telemetry
Ethstats string `hcl:"ethstats,optional"`
@@ -368,6 +371,9 @@ type AccountsConfig struct {
// UseLightweightKDF enables a faster but less secure encryption of accounts
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`
+
+ // DisableBorWallet disables the personal wallet endpoints
+ DisableBorWallet bool `hcl:"disable-bor-wallet,optional"`
}
type DeveloperConfig struct {
@@ -380,11 +386,11 @@ type DeveloperConfig struct {
func DefaultConfig() *Config {
return &Config{
- Chain: "mainnet",
- Name: Hostname(),
- Whitelist: map[string]string{},
- LogLevel: "INFO",
- DataDir: defaultDataDir(),
+ Chain: "mainnet",
+ Name: Hostname(),
+ RequiredBlocks: map[string]string{},
+ LogLevel: "INFO",
+ DataDir: defaultDataDir(),
P2P: &P2PConfig{
MaxPeers: 30,
MaxPendPeers: 50,
@@ -406,27 +412,27 @@ func DefaultConfig() *Config {
URL: "http://localhost:1317",
Without: false,
},
- SyncMode: "full",
- GcMode: "full",
- Snapshot: true,
+ SyncMode: "full",
+ GcMode: "full",
+ NoSnapshot: false,
TxPool: &TxPoolConfig{
Locals: []string{},
NoLocals: false,
Journal: "",
Rejournal: time.Duration(1 * time.Hour),
- PriceLimit: 1,
+ PriceLimit: 30000000000,
PriceBump: 10,
AccountSlots: 16,
- GlobalSlots: 4096,
- AccountQueue: 64,
- GlobalQueue: 1024,
+ GlobalSlots: 32768,
+ AccountQueue: 16,
+ GlobalQueue: 32768,
LifeTime: time.Duration(3 * time.Hour),
},
Sealer: &SealerConfig{
Enabled: false,
Etherbase: "",
GasCeil: 8000000,
- GasPrice: big.NewInt(params.GWei),
+ GasPrice: big.NewInt(30 * params.GWei),
ExtraData: "",
},
Gpo: &GpoConfig{
@@ -447,7 +453,7 @@ func DefaultConfig() *Config {
Port: 8545,
Prefix: "",
Host: "localhost",
- Modules: []string{"web3", "net"},
+ Modules: []string{"eth", "net", "web3", "txpool", "bor"},
},
Ws: &APIConfig{
Enabled: false,
@@ -496,6 +502,7 @@ func DefaultConfig() *Config {
PasswordFile: "",
AllowInsecureUnlock: false,
UseLightweightKDF: false,
+ DisableBorWallet: false,
},
GRPC: &GRPCConfig{
Addr: ":3131",
@@ -523,18 +530,22 @@ func (c *Config) fillBigInt() error {
b := new(big.Int)
var ok bool
+
if strings.HasPrefix(*x.str, "0x") {
b, ok = b.SetString((*x.str)[2:], 16)
} else {
b, ok = b.SetString(*x.str, 10)
}
+
if !ok {
return fmt.Errorf("%s can't parse big int %s", x.path, *x.str)
}
+
*x.str = ""
*x.td = b
}
}
+
return nil
}
@@ -555,10 +566,12 @@ func (c *Config) fillTimeDurations() error {
if err != nil {
return fmt.Errorf("%s can't parse time duration %s", x.path, *x.str)
}
+
*x.str = ""
*x.td = d
}
}
+
return nil
}
@@ -570,6 +583,7 @@ func readConfigFile(path string) (*Config, error) {
if err != nil {
return nil, err
}
+
return readLegacyConfig(data)
}
@@ -578,26 +592,28 @@ func readConfigFile(path string) (*Config, error) {
Cache: &CacheConfig{},
Sealer: &SealerConfig{},
}
+
if err := hclsimple.DecodeFile(path, nil, config); err != nil {
return nil, fmt.Errorf("failed to decode config file '%s': %v", path, err)
}
+
if err := config.fillBigInt(); err != nil {
return nil, err
}
+
if err := config.fillTimeDurations(); err != nil {
return nil, err
}
+
return config, nil
}
func (c *Config) loadChain() error {
- if c.Developer.Enabled {
- return nil
- }
- chain, ok := chains.GetChain(c.Chain)
- if !ok {
- return fmt.Errorf("chain '%s' not found", c.Chain)
+ chain, err := chains.GetChain(c.Chain)
+ if err != nil {
+ return err
}
+
c.chain = chain
// preload some default values that depend on the chain file
@@ -611,14 +627,17 @@ func (c *Config) loadChain() error {
} else {
c.Cache.Cache = 1024
}
+
return nil
}
-func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
+//nolint:gocognit
+func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*ethconfig.Config, error) {
dbHandles, err := makeDatabaseHandles()
if err != nil {
return nil, err
}
+
n := ethconfig.Defaults
// only update for non-developer mode as we don't yet
@@ -662,15 +681,42 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
if !common.IsHexAddress(etherbase) {
return nil, fmt.Errorf("etherbase is not an address: %s", etherbase)
}
+
n.Miner.Etherbase = common.HexToAddress(etherbase)
}
}
+ // unlock accounts
+ if len(c.Accounts.Unlock) > 0 {
+ if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() {
+ return nil, fmt.Errorf("account unlock with HTTP access is forbidden")
+ }
+
+ ks := accountManager.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
+
+ passwords, err := MakePasswordListFromFile(c.Accounts.PasswordFile)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(passwords) < len(c.Accounts.Unlock) {
+ return nil, fmt.Errorf("number of passwords provided (%v) is less than number of accounts (%v) to unlock",
+ len(passwords), len(c.Accounts.Unlock))
+ }
+
+ for i, account := range c.Accounts.Unlock {
+ err = ks.Unlock(accounts.Account{Address: common.HexToAddress(account)}, passwords[i])
+ if err != nil {
+ return nil, fmt.Errorf("could not unlock an account %q", account)
+ }
+ }
+ }
+
// update for developer mode
if c.Developer.Enabled {
// Get a keystore
var ks *keystore.KeyStore
- if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
+ if keystores := accountManager.Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore)
}
@@ -680,6 +726,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
passphrase string
err error
)
+
// etherbase has been set above, configuring the miner address from command line flags.
if n.Miner.Etherbase != (common.Address{}) {
developer = accounts.Account{Address: n.Miner.Etherbase}
@@ -694,8 +741,13 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
if err := ks.Unlock(developer, passphrase); err != nil {
return nil, fmt.Errorf("failed to unlock developer account: %v", err)
}
+
log.Info("Using developer account", "address", developer.Address)
+ // Set the Etherbase
+ c.Sealer.Etherbase = developer.Address.Hex()
+ n.Miner.Etherbase = developer.Address
+
// get developer mode chain config
c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address)
@@ -721,18 +773,20 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
n.SnapDiscoveryURLs = c.P2P.Discovery.DNS
}
- // whitelist
+ // RequiredBlocks
{
n.PeerRequiredBlocks = map[uint64]common.Hash{}
- for k, v := range c.Whitelist {
+ for k, v := range c.RequiredBlocks {
number, err := strconv.ParseUint(k, 0, 64)
if err != nil {
- return nil, fmt.Errorf("invalid whitelist block number %s: %v", k, err)
+ return nil, fmt.Errorf("invalid required block number %s: %v", k, err)
}
+
var hash common.Hash
if err = hash.UnmarshalText([]byte(v)); err != nil {
- return nil, fmt.Errorf("invalid whitelist hash %s: %v", v, err)
+ return nil, fmt.Errorf("invalid required block hash %s: %v", v, err)
}
+
n.PeerRequiredBlocks[number] = hash
}
}
@@ -751,6 +805,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024)
mem.Total = 2 * 1024 * 1024 * 1024
}
+
allowance := uint64(mem.Total / 1024 / 1024 / 3)
if cache > allowance {
log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
@@ -780,6 +835,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
} else {
log.Info("Global gas cap disabled")
}
+
n.RPCTxFeeCap = c.JsonRPC.TxFeeCap
// sync mode. It can either be "fast", "full" or "snap". We disable
@@ -808,7 +864,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
}
// snapshot disable check
- if c.Snapshot {
+ if c.NoSnapshot {
if n.SyncMode == downloader.SnapSync {
log.Info("Snap sync requested, enabling --snapshot")
} else {
@@ -819,6 +875,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
}
n.DatabaseHandles = dbHandles
+
return &n, nil
}
@@ -840,6 +897,7 @@ func (c *Config) buildNode() (*node.Config, error) {
cfg := &node.Config{
Name: clientIdentifier,
DataDir: c.DataDir,
+ KeyStoreDir: c.KeyStoreDir,
UseLightweightKDF: c.Accounts.UseLightweightKDF,
InsecureUnlockAllowed: c.Accounts.AllowInsecureUnlock,
Version: params.VersionWithCommit(gitCommit, gitDate),
@@ -870,6 +928,10 @@ func (c *Config) buildNode() (*node.Config, error) {
cfg.P2P.ListenAddr = ""
cfg.P2P.NoDial = true
cfg.P2P.DiscoveryV5 = false
+
+ // enable JsonRPC HTTP API
+ c.JsonRPC.Http.Enabled = true
+ cfg.HTTPModules = []string{"admin", "debug", "eth", "miner", "net", "personal", "txpool", "web3", "bor"}
}
// enable jsonrpc endpoints
@@ -878,6 +940,7 @@ func (c *Config) buildNode() (*node.Config, error) {
cfg.HTTPHost = c.JsonRPC.Http.Host
cfg.HTTPPort = int(c.JsonRPC.Http.Port)
}
+
if c.JsonRPC.Ws.Enabled {
cfg.WSHost = c.JsonRPC.Ws.Host
cfg.WSPort = int(c.JsonRPC.Ws.Port)
@@ -888,6 +951,7 @@ func (c *Config) buildNode() (*node.Config, error) {
if err != nil {
return nil, fmt.Errorf("wrong 'nat' flag: %v", err)
}
+
cfg.P2P.NAT = natif
// only check for non-developer modes
@@ -898,18 +962,30 @@ func (c *Config) buildNode() (*node.Config, error) {
if len(bootnodes) == 0 {
bootnodes = c.chain.Bootnodes
}
+
if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil {
return nil, err
}
+
if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil {
return nil, err
}
+
if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil {
return nil, err
}
+
+ if len(cfg.P2P.StaticNodes) == 0 {
+ cfg.P2P.StaticNodes = cfg.StaticNodes()
+ }
+
if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil {
return nil, err
}
+
+ if len(cfg.P2P.TrustedNodes) == 0 {
+ cfg.P2P.TrustedNodes = cfg.TrustedNodes()
+ }
}
if c.P2P.NoDiscover {
@@ -917,15 +993,17 @@ func (c *Config) buildNode() (*node.Config, error) {
cfg.P2P.MaxPeers = 0
cfg.P2P.NoDiscovery = true
}
+
return cfg, nil
}
func (c *Config) Merge(cc ...*Config) error {
for _, elem := range cc {
- if err := mergo.Merge(c, elem, mergo.WithOverride, mergo.WithAppendSlice); err != nil {
+ if err := mergo.Merge(c, elem, mergo.WithOverwriteWithEmptyValue, mergo.WithAppendSlice); err != nil {
return fmt.Errorf("failed to merge configurations: %v", err)
}
}
+
return nil
}
@@ -934,10 +1012,12 @@ func makeDatabaseHandles() (int, error) {
if err != nil {
return -1, err
}
+
raised, err := fdlimit.Raise(uint64(limit))
if err != nil {
return -1, err
}
+
return int(raised / 2), nil
}
@@ -952,6 +1032,7 @@ func parseBootnodes(urls []string) ([]*enode.Node, error) {
dst = append(dst, node)
}
}
+
return dst, nil
}
@@ -962,6 +1043,7 @@ func defaultDataDir() string {
// we cannot guess a stable location
return ""
}
+
switch runtime.GOOS {
case "darwin":
return filepath.Join(home, "Library", "Bor")
@@ -971,6 +1053,7 @@ func defaultDataDir() string {
// Windows XP and below don't have LocalAppData.
panic("environment variable LocalAppData is undefined")
}
+
return filepath.Join(appdata, "Bor")
default:
return filepath.Join(home, ".bor")
@@ -982,5 +1065,22 @@ func Hostname() string {
if err != nil {
return "bor"
}
+
return hostname
}
+
+func MakePasswordListFromFile(path string) ([]string, error) {
+ text, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to read password file: %v", err)
+ }
+
+ lines := strings.Split(string(text), "\n")
+
+ // Sanitise DOS line endings.
+ for i := range lines {
+ lines[i] = strings.TrimRight(lines[i], "\r")
+ }
+
+ return lines, nil
+}
diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go
index 62296d82a4..94c4496c03 100644
--- a/internal/cli/server/config_test.go
+++ b/internal/cli/server/config_test.go
@@ -16,15 +16,15 @@ func TestConfigDefault(t *testing.T) {
_, err := config.buildNode()
assert.NoError(t, err)
- _, err = config.buildEth(nil)
+ _, err = config.buildEth(nil, nil)
assert.NoError(t, err)
}
func TestConfigMerge(t *testing.T) {
c0 := &Config{
- Chain: "0",
- Snapshot: true,
- Whitelist: map[string]string{
+ Chain: "0",
+ NoSnapshot: true,
+ RequiredBlocks: map[string]string{
"a": "b",
},
TxPool: &TxPoolConfig{
@@ -40,7 +40,7 @@ func TestConfigMerge(t *testing.T) {
}
c1 := &Config{
Chain: "1",
- Whitelist: map[string]string{
+ RequiredBlocks: map[string]string{
"b": "c",
},
P2P: &P2PConfig{
@@ -52,16 +52,14 @@ func TestConfigMerge(t *testing.T) {
},
},
}
+
expected := &Config{
- Chain: "1",
- Snapshot: true,
- Whitelist: map[string]string{
+ Chain: "1",
+ NoSnapshot: false,
+ RequiredBlocks: map[string]string{
"a": "b",
"b": "c",
},
- TxPool: &TxPoolConfig{
- LifeTime: 5 * time.Second,
- },
P2P: &P2PConfig{
MaxPeers: 10,
Discovery: &P2PDiscovery{
@@ -72,6 +70,34 @@ func TestConfigMerge(t *testing.T) {
},
},
}
+
+ assert.NoError(t, c0.Merge(c1))
+ assert.Equal(t, c0, expected)
+}
+
+func TestDefaultDatatypeOverride(t *testing.T) {
+ t.Parallel()
+
+ // This test is specific to `maxpeers` flag (for now) to check
+ // if default datatype value (0 in case of uint64) is overridden.
+ c0 := &Config{
+ P2P: &P2PConfig{
+ MaxPeers: 30,
+ },
+ }
+
+ c1 := &Config{
+ P2P: &P2PConfig{
+ MaxPeers: 0,
+ },
+ }
+
+ expected := &Config{
+ P2P: &P2PConfig{
+ MaxPeers: 0,
+ },
+ }
+
assert.NoError(t, c0.Merge(c1))
assert.Equal(t, c0, expected)
}
@@ -80,9 +106,10 @@ func TestConfigLoadFile(t *testing.T) {
readFile := func(path string) {
config, err := readConfigFile(path)
assert.NoError(t, err)
+
assert.Equal(t, config, &Config{
DataDir: "./data",
- Whitelist: map[string]string{
+ RequiredBlocks: map[string]string{
"a": "b",
},
P2P: &P2PConfig{
@@ -103,6 +130,7 @@ func TestConfigLoadFile(t *testing.T) {
t.Run("hcl", func(t *testing.T) {
readFile("./testdata/simple.hcl")
})
+
// read file in json format
t.Run("json", func(t *testing.T) {
readFile("./testdata/simple.json")
@@ -131,3 +159,14 @@ func TestConfigBootnodesDefault(t *testing.T) {
assert.Len(t, cfg.P2P.BootstrapNodes, 1)
})
}
+
+func TestMakePasswordListFromFile(t *testing.T) {
+ t.Parallel()
+
+ t.Run("ReadPasswordFile", func(t *testing.T) {
+ t.Parallel()
+
+ result, _ := MakePasswordListFromFile("./testdata/password.txt")
+ assert.Equal(t, []string{"test1", "test2"}, result)
+ })
+}
diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go
index b8f6003420..21e9a38cb9 100644
--- a/internal/cli/server/flags.go
+++ b/internal/cli/server/flags.go
@@ -10,24 +10,33 @@ func (c *Command) Flags() *flagset.Flagset {
f := flagset.NewFlagSet("server")
f.StringFlag(&flagset.StringFlag{
- Name: "chain",
- Usage: "Name of the chain to sync",
- Value: &c.cliConfig.Chain,
+ Name: "chain",
+ Usage: "Name of the chain to sync",
+ Value: &c.cliConfig.Chain,
+ Default: c.cliConfig.Chain,
})
f.StringFlag(&flagset.StringFlag{
- Name: "name",
- Usage: "Name/Identity of the node",
- Value: &c.cliConfig.Name,
+ Name: "name",
+ Usage: "Name/Identity of the node",
+ Value: &c.cliConfig.Name,
+ Default: c.cliConfig.Name,
})
f.StringFlag(&flagset.StringFlag{
- Name: "log-level",
- Usage: "Set log level for the server",
- Value: &c.cliConfig.LogLevel,
+ Name: "log-level",
+ Usage: "Set log level for the server",
+ Value: &c.cliConfig.LogLevel,
+ Default: c.cliConfig.LogLevel,
})
f.StringFlag(&flagset.StringFlag{
- Name: "datadir",
- Usage: "Path of the data directory to store information",
- Value: &c.cliConfig.DataDir,
+ Name: "datadir",
+ Usage: "Path of the data directory to store information",
+ Value: &c.cliConfig.DataDir,
+ Default: c.cliConfig.DataDir,
+ })
+ f.StringFlag(&flagset.StringFlag{
+ Name: "keystore",
+ Usage: "Path of the directory to store keystores",
+ Value: &c.cliConfig.KeyStoreDir,
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "config",
@@ -35,36 +44,41 @@ func (c *Command) Flags() *flagset.Flagset {
Value: &c.configFile,
})
f.StringFlag(&flagset.StringFlag{
- Name: "syncmode",
- Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`,
- Value: &c.cliConfig.SyncMode,
+ Name: "syncmode",
+ Usage: `Blockchain sync mode ("fast", "full", or "snap")`,
+ Value: &c.cliConfig.SyncMode,
+ Default: c.cliConfig.SyncMode,
})
f.StringFlag(&flagset.StringFlag{
- Name: "gcmode",
- Usage: `Blockchain garbage collection mode ("full", "archive")`,
- Value: &c.cliConfig.GcMode,
+ Name: "gcmode",
+ Usage: `Blockchain garbage collection mode ("full", "archive")`,
+ Value: &c.cliConfig.GcMode,
+ Default: c.cliConfig.GcMode,
})
f.MapStringFlag(&flagset.MapStringFlag{
- Name: "whitelist",
+ Name: "requiredblocks",
Usage: "Comma separated block number-to-hash mappings to enforce (=)",
- Value: &c.cliConfig.Whitelist,
+ Value: &c.cliConfig.RequiredBlocks,
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "snapshot",
- Usage: `Enables snapshot-database mode (default = enable)`,
- Value: &c.cliConfig.Snapshot,
+ Name: "no-snapshot",
+ Usage: `Disables the snapshot-database mode (default = false)`,
+ Value: &c.cliConfig.NoSnapshot,
+ Default: c.cliConfig.NoSnapshot,
})
// heimdall
f.StringFlag(&flagset.StringFlag{
- Name: "bor.heimdall",
- Usage: "URL of Heimdall service",
- Value: &c.cliConfig.Heimdall.URL,
+ Name: "bor.heimdall",
+ Usage: "URL of Heimdall service",
+ Value: &c.cliConfig.Heimdall.URL,
+ Default: c.cliConfig.Heimdall.URL,
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "bor.withoutheimdall",
- Usage: "Run without Heimdall service (for testing purpose)",
- Value: &c.cliConfig.Heimdall.Without,
+ Name: "bor.withoutheimdall",
+ Usage: "Run without Heimdall service (for testing purpose)",
+ Value: &c.cliConfig.Heimdall.Without,
+ Default: c.cliConfig.Heimdall.Without,
})
// txpool options
@@ -72,102 +86,135 @@ func (c *Command) Flags() *flagset.Flagset {
Name: "txpool.locals",
Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
Value: &c.cliConfig.TxPool.Locals,
+ Group: "Transaction Pool",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "txpool.nolocals",
- Usage: "Disables price exemptions for locally submitted transactions",
- Value: &c.cliConfig.TxPool.NoLocals,
+ Name: "txpool.nolocals",
+ Usage: "Disables price exemptions for locally submitted transactions",
+ Value: &c.cliConfig.TxPool.NoLocals,
+ Default: c.cliConfig.TxPool.NoLocals,
+ Group: "Transaction Pool",
})
f.StringFlag(&flagset.StringFlag{
- Name: "txpool.journal",
- Usage: "Disk journal for local transaction to survive node restarts",
- Value: &c.cliConfig.TxPool.Journal,
+ Name: "txpool.journal",
+ Usage: "Disk journal for local transaction to survive node restarts",
+ Value: &c.cliConfig.TxPool.Journal,
+ Default: c.cliConfig.TxPool.Journal,
+ Group: "Transaction Pool",
})
f.DurationFlag(&flagset.DurationFlag{
- Name: "txpool.rejournal",
- Usage: "Time interval to regenerate the local transaction journal",
- Value: &c.cliConfig.TxPool.Rejournal,
+ Name: "txpool.rejournal",
+ Usage: "Time interval to regenerate the local transaction journal",
+ Value: &c.cliConfig.TxPool.Rejournal,
+ Default: c.cliConfig.TxPool.Rejournal,
+ Group: "Transaction Pool",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "txpool.pricelimit",
- Usage: "Minimum gas price limit to enforce for acceptance into the pool",
- Value: &c.cliConfig.TxPool.PriceLimit,
+ Name: "txpool.pricelimit",
+ Usage: "Minimum gas price limit to enforce for acceptance into the pool",
+ Value: &c.cliConfig.TxPool.PriceLimit,
+ Default: c.cliConfig.TxPool.PriceLimit,
+ Group: "Transaction Pool",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "txpool.pricebump",
- Usage: "Price bump percentage to replace an already existing transaction",
- Value: &c.cliConfig.TxPool.PriceBump,
+ Name: "txpool.pricebump",
+ Usage: "Price bump percentage to replace an already existing transaction",
+ Value: &c.cliConfig.TxPool.PriceBump,
+ Default: c.cliConfig.TxPool.PriceBump,
+ Group: "Transaction Pool",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "txpool.accountslots",
- Usage: "Minimum number of executable transaction slots guaranteed per account",
- Value: &c.cliConfig.TxPool.AccountSlots,
+ Name: "txpool.accountslots",
+ Usage: "Minimum number of executable transaction slots guaranteed per account",
+ Value: &c.cliConfig.TxPool.AccountSlots,
+ Default: c.cliConfig.TxPool.AccountSlots,
+ Group: "Transaction Pool",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "txpool.globalslots",
- Usage: "Maximum number of executable transaction slots for all accounts",
- Value: &c.cliConfig.TxPool.GlobalSlots,
+ Name: "txpool.globalslots",
+ Usage: "Maximum number of executable transaction slots for all accounts",
+ Value: &c.cliConfig.TxPool.GlobalSlots,
+ Default: c.cliConfig.TxPool.GlobalSlots,
+ Group: "Transaction Pool",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "txpool.accountqueue",
- Usage: "Maximum number of non-executable transaction slots permitted per account",
- Value: &c.cliConfig.TxPool.AccountQueue,
+ Name: "txpool.accountqueue",
+ Usage: "Maximum number of non-executable transaction slots permitted per account",
+ Value: &c.cliConfig.TxPool.AccountQueue,
+ Default: c.cliConfig.TxPool.AccountQueue,
+ Group: "Transaction Pool",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "txpool.globalqueue",
- Usage: "Maximum number of non-executable transaction slots for all accounts",
- Value: &c.cliConfig.TxPool.GlobalQueue,
+ Name: "txpool.globalqueue",
+ Usage: "Maximum number of non-executable transaction slots for all accounts",
+ Value: &c.cliConfig.TxPool.GlobalQueue,
+ Default: c.cliConfig.TxPool.GlobalQueue,
+ Group: "Transaction Pool",
})
f.DurationFlag(&flagset.DurationFlag{
- Name: "txpool.lifetime",
- Usage: "Maximum amount of time non-executable transaction are queued",
- Value: &c.cliConfig.TxPool.LifeTime,
+ Name: "txpool.lifetime",
+ Usage: "Maximum amount of time non-executable transaction are queued",
+ Value: &c.cliConfig.TxPool.LifeTime,
+ Default: c.cliConfig.TxPool.LifeTime,
+ Group: "Transaction Pool",
})
// sealer options
f.BoolFlag(&flagset.BoolFlag{
- Name: "mine",
- Usage: "Enable mining",
- Value: &c.cliConfig.Sealer.Enabled,
+ Name: "mine",
+ Usage: "Enable mining",
+ Value: &c.cliConfig.Sealer.Enabled,
+ Default: c.cliConfig.Sealer.Enabled,
+ Group: "Sealer",
})
f.StringFlag(&flagset.StringFlag{
- Name: "miner.etherbase",
- Usage: "Public address for block mining rewards (default = first account)",
- Value: &c.cliConfig.Sealer.Etherbase,
+ Name: "miner.etherbase",
+ Usage: "Public address for block mining rewards (default = first account)",
+ Value: &c.cliConfig.Sealer.Etherbase,
+ Default: c.cliConfig.Sealer.Etherbase,
+ Group: "Sealer",
})
f.StringFlag(&flagset.StringFlag{
- Name: "miner.extradata",
- Usage: "Block extra data set by the miner (default = client version)",
- Value: &c.cliConfig.Sealer.ExtraData,
+ Name: "miner.extradata",
+ Usage: "Block extra data set by the miner (default = client version)",
+ Value: &c.cliConfig.Sealer.ExtraData,
+ Default: c.cliConfig.Sealer.ExtraData,
+ Group: "Sealer",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "miner.gaslimit",
- Usage: "Target gas ceiling for mined blocks",
- Value: &c.cliConfig.Sealer.GasCeil,
+ Name: "miner.gaslimit",
+ Usage: "Target gas ceiling for mined blocks",
+ Value: &c.cliConfig.Sealer.GasCeil,
+ Default: c.cliConfig.Sealer.GasCeil,
+ Group: "Sealer",
})
f.BigIntFlag(&flagset.BigIntFlag{
Name: "miner.gasprice",
Usage: "Minimum gas price for mining a transaction",
Value: c.cliConfig.Sealer.GasPrice,
+ Group: "Sealer",
})
// ethstats
f.StringFlag(&flagset.StringFlag{
- Name: "ethstats",
- Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
- Value: &c.cliConfig.Ethstats,
+ Name: "ethstats",
+ Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
+ Value: &c.cliConfig.Ethstats,
+ Default: c.cliConfig.Ethstats,
})
// gas price oracle
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "gpo.blocks",
- Usage: "Number of recent blocks to check for gas prices",
- Value: &c.cliConfig.Gpo.Blocks,
+ Name: "gpo.blocks",
+ Usage: "Number of recent blocks to check for gas prices",
+ Value: &c.cliConfig.Gpo.Blocks,
+ Default: c.cliConfig.Gpo.Blocks,
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "gpo.percentile",
- Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
- Value: &c.cliConfig.Gpo.Percentile,
+ Name: "gpo.percentile",
+ Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
+ Value: &c.cliConfig.Gpo.Percentile,
+ Default: c.cliConfig.Gpo.Percentile,
})
f.BigIntFlag(&flagset.BigIntFlag{
Name: "gpo.maxprice",
@@ -182,262 +229,354 @@ func (c *Command) Flags() *flagset.Flagset {
// cache options
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "cache",
- Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)",
- Value: &c.cliConfig.Cache.Cache,
+ Name: "cache",
+ Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)",
+ Value: &c.cliConfig.Cache.Cache,
+ Default: c.cliConfig.Cache.Cache,
+ Group: "Cache",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "cache.database",
- Usage: "Percentage of cache memory allowance to use for database io",
- Value: &c.cliConfig.Cache.PercDatabase,
+ Name: "cache.database",
+ Usage: "Percentage of cache memory allowance to use for database io",
+ Value: &c.cliConfig.Cache.PercDatabase,
+ Default: c.cliConfig.Cache.PercDatabase,
+ Group: "Cache",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "cache.trie",
- Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)",
- Value: &c.cliConfig.Cache.PercTrie,
+ Name: "cache.trie",
+ Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)",
+ Value: &c.cliConfig.Cache.PercTrie,
+ Default: c.cliConfig.Cache.PercTrie,
+ Group: "Cache",
})
f.StringFlag(&flagset.StringFlag{
- Name: "cache.trie.journal",
- Usage: "Disk journal directory for trie cache to survive node restarts",
- Value: &c.cliConfig.Cache.Journal,
+ Name: "cache.trie.journal",
+ Usage: "Disk journal directory for trie cache to survive node restarts",
+ Value: &c.cliConfig.Cache.Journal,
+ Default: c.cliConfig.Cache.Journal,
+ Group: "Cache",
})
f.DurationFlag(&flagset.DurationFlag{
- Name: "cache.trie.rejournal",
- Usage: "Time interval to regenerate the trie cache journal",
- Value: &c.cliConfig.Cache.Rejournal,
+ Name: "cache.trie.rejournal",
+ Usage: "Time interval to regenerate the trie cache journal",
+ Value: &c.cliConfig.Cache.Rejournal,
+ Default: c.cliConfig.Cache.Rejournal,
+ Group: "Cache",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "cache.gc",
- Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
- Value: &c.cliConfig.Cache.PercGc,
+ Name: "cache.gc",
+ Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
+ Value: &c.cliConfig.Cache.PercGc,
+ Default: c.cliConfig.Cache.PercGc,
+ Group: "Cache",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "cache.snapshot",
- Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)",
- Value: &c.cliConfig.Cache.PercSnapshot,
+ Name: "cache.snapshot",
+ Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)",
+ Value: &c.cliConfig.Cache.PercSnapshot,
+ Default: c.cliConfig.Cache.PercSnapshot,
+ Group: "Cache",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "cache.noprefetch",
- Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
- Value: &c.cliConfig.Cache.NoPrefetch,
+ Name: "cache.noprefetch",
+ Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
+ Value: &c.cliConfig.Cache.NoPrefetch,
+ Default: c.cliConfig.Cache.NoPrefetch,
+ Group: "Cache",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "cache.preimages",
- Usage: "Enable recording the SHA3/keccak preimages of trie keys",
- Value: &c.cliConfig.Cache.Preimages,
+ Name: "cache.preimages",
+ Usage: "Enable recording the SHA3/keccak preimages of trie keys",
+ Value: &c.cliConfig.Cache.Preimages,
+ Default: c.cliConfig.Cache.Preimages,
+ Group: "Cache",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "txlookuplimit",
- Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)",
- Value: &c.cliConfig.Cache.TxLookupLimit,
+ Name: "txlookuplimit",
+ Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)",
+ Value: &c.cliConfig.Cache.TxLookupLimit,
+ Default: c.cliConfig.Cache.TxLookupLimit,
+ Group: "Cache",
})
// rpc options
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "rpc.gascap",
- Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
- Value: &c.cliConfig.JsonRPC.GasCap,
+ Name: "rpc.gascap",
+ Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
+ Value: &c.cliConfig.JsonRPC.GasCap,
+ Default: c.cliConfig.JsonRPC.GasCap,
+ Group: "JsonRPC",
})
f.Float64Flag(&flagset.Float64Flag{
- Name: "rpc.txfeecap",
- Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)",
- Value: &c.cliConfig.JsonRPC.TxFeeCap,
+ Name: "rpc.txfeecap",
+ Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)",
+ Value: &c.cliConfig.JsonRPC.TxFeeCap,
+ Default: c.cliConfig.JsonRPC.TxFeeCap,
+ Group: "JsonRPC",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "ipcdisable",
- Usage: "Disable the IPC-RPC server",
- Value: &c.cliConfig.JsonRPC.IPCDisable,
+ Name: "ipcdisable",
+ Usage: "Disable the IPC-RPC server",
+ Value: &c.cliConfig.JsonRPC.IPCDisable,
+ Default: c.cliConfig.JsonRPC.IPCDisable,
+ Group: "JsonRPC",
})
f.StringFlag(&flagset.StringFlag{
- Name: "ipcpath",
- Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
- Value: &c.cliConfig.JsonRPC.IPCPath,
+ Name: "ipcpath",
+ Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
+ Value: &c.cliConfig.JsonRPC.IPCPath,
+ Default: c.cliConfig.JsonRPC.IPCPath,
+ Group: "JsonRPC",
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "jsonrpc.corsdomain",
Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
Value: &c.cliConfig.JsonRPC.Cors,
+ Group: "JsonRPC",
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "jsonrpc.vhosts",
Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
Value: &c.cliConfig.JsonRPC.VHost,
+ Group: "JsonRPC",
})
// http options
f.BoolFlag(&flagset.BoolFlag{
- Name: "http",
- Usage: "Enable the HTTP-RPC server",
- Value: &c.cliConfig.JsonRPC.Http.Enabled,
+ Name: "http",
+ Usage: "Enable the HTTP-RPC server",
+ Value: &c.cliConfig.JsonRPC.Http.Enabled,
+ Default: c.cliConfig.JsonRPC.Http.Enabled,
+ Group: "JsonRPC",
})
f.StringFlag(&flagset.StringFlag{
- Name: "http.addr",
- Usage: "HTTP-RPC server listening interface",
- Value: &c.cliConfig.JsonRPC.Http.Host,
+ Name: "http.addr",
+ Usage: "HTTP-RPC server listening interface",
+ Value: &c.cliConfig.JsonRPC.Http.Host,
+ Default: c.cliConfig.JsonRPC.Http.Host,
+ Group: "JsonRPC",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "http.port",
- Usage: "HTTP-RPC server listening port",
- Value: &c.cliConfig.JsonRPC.Http.Port,
+ Name: "http.port",
+ Usage: "HTTP-RPC server listening port",
+ Value: &c.cliConfig.JsonRPC.Http.Port,
+ Default: c.cliConfig.JsonRPC.Http.Port,
+ Group: "JsonRPC",
})
f.StringFlag(&flagset.StringFlag{
- Name: "http.rpcprefix",
- Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
- Value: &c.cliConfig.JsonRPC.Http.Prefix,
+ Name: "http.rpcprefix",
+ Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
+ Value: &c.cliConfig.JsonRPC.Http.Prefix,
+ Default: c.cliConfig.JsonRPC.Http.Prefix,
+ Group: "JsonRPC",
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "http.modules",
Usage: "API's offered over the HTTP-RPC interface",
Value: &c.cliConfig.JsonRPC.Http.Modules,
+ Group: "JsonRPC",
})
// ws options
f.BoolFlag(&flagset.BoolFlag{
- Name: "ws",
- Usage: "Enable the WS-RPC server",
- Value: &c.cliConfig.JsonRPC.Ws.Enabled,
+ Name: "ws",
+ Usage: "Enable the WS-RPC server",
+ Value: &c.cliConfig.JsonRPC.Ws.Enabled,
+ Default: c.cliConfig.JsonRPC.Ws.Enabled,
+ Group: "JsonRPC",
})
f.StringFlag(&flagset.StringFlag{
- Name: "ws.addr",
- Usage: "WS-RPC server listening interface",
- Value: &c.cliConfig.JsonRPC.Ws.Host,
+ Name: "ws.addr",
+ Usage: "WS-RPC server listening interface",
+ Value: &c.cliConfig.JsonRPC.Ws.Host,
+ Default: c.cliConfig.JsonRPC.Ws.Host,
+ Group: "JsonRPC",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "ws.port",
- Usage: "WS-RPC server listening port",
- Value: &c.cliConfig.JsonRPC.Ws.Port,
+ Name: "ws.port",
+ Usage: "WS-RPC server listening port",
+ Value: &c.cliConfig.JsonRPC.Ws.Port,
+ Default: c.cliConfig.JsonRPC.Ws.Port,
+ Group: "JsonRPC",
})
f.StringFlag(&flagset.StringFlag{
- Name: "ws.rpcprefix",
- Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
- Value: &c.cliConfig.JsonRPC.Ws.Prefix,
+ Name: "ws.rpcprefix",
+ Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
+ Value: &c.cliConfig.JsonRPC.Ws.Prefix,
+ Default: c.cliConfig.JsonRPC.Ws.Prefix,
+ Group: "JsonRPC",
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "ws.modules",
Usage: "API's offered over the WS-RPC interface",
Value: &c.cliConfig.JsonRPC.Ws.Modules,
+ Group: "JsonRPC",
})
// graphql options
f.BoolFlag(&flagset.BoolFlag{
- Name: "graphql",
- Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.",
- Value: &c.cliConfig.JsonRPC.Graphql.Enabled,
+ Name: "graphql",
+ Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.",
+ Value: &c.cliConfig.JsonRPC.Graphql.Enabled,
+ Default: c.cliConfig.JsonRPC.Graphql.Enabled,
+ Group: "JsonRPC",
})
// p2p options
f.StringFlag(&flagset.StringFlag{
- Name: "bind",
- Usage: "Network binding address",
- Value: &c.cliConfig.P2P.Bind,
+ Name: "bind",
+ Usage: "Network binding address",
+ Value: &c.cliConfig.P2P.Bind,
+ Default: c.cliConfig.P2P.Bind,
+ Group: "P2P",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "port",
- Usage: "Network listening port",
- Value: &c.cliConfig.P2P.Port,
+ Name: "port",
+ Usage: "Network listening port",
+ Value: &c.cliConfig.P2P.Port,
+ Default: c.cliConfig.P2P.Port,
+ Group: "P2P",
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "bootnodes",
Usage: "Comma separated enode URLs for P2P discovery bootstrap",
Value: &c.cliConfig.P2P.Discovery.Bootnodes,
+ Group: "P2P",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "maxpeers",
- Usage: "Maximum number of network peers (network disabled if set to 0)",
- Value: &c.cliConfig.P2P.MaxPeers,
+ Name: "maxpeers",
+ Usage: "Maximum number of network peers (network disabled if set to 0)",
+ Value: &c.cliConfig.P2P.MaxPeers,
+ Default: c.cliConfig.P2P.MaxPeers,
+ Group: "P2P",
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "maxpendpeers",
- Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
- Value: &c.cliConfig.P2P.MaxPendPeers,
+ Name: "maxpendpeers",
+ Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
+ Value: &c.cliConfig.P2P.MaxPendPeers,
+ Default: c.cliConfig.P2P.MaxPendPeers,
+ Group: "P2P",
})
f.StringFlag(&flagset.StringFlag{
- Name: "nat",
- Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)",
- Value: &c.cliConfig.P2P.NAT,
+ Name: "nat",
+ Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)",
+ Value: &c.cliConfig.P2P.NAT,
+ Default: c.cliConfig.P2P.NAT,
+ Group: "P2P",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "nodiscover",
- Usage: "Disables the peer discovery mechanism (manual peer addition)",
- Value: &c.cliConfig.P2P.NoDiscover,
+ Name: "nodiscover",
+ Usage: "Disables the peer discovery mechanism (manual peer addition)",
+ Value: &c.cliConfig.P2P.NoDiscover,
+ Default: c.cliConfig.P2P.NoDiscover,
+ Group: "P2P",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "v5disc",
- Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
- Value: &c.cliConfig.P2P.Discovery.V5Enabled,
+ Name: "v5disc",
+ Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
+ Value: &c.cliConfig.P2P.Discovery.V5Enabled,
+ Default: c.cliConfig.P2P.Discovery.V5Enabled,
+ Group: "P2P",
})
// metrics
f.BoolFlag(&flagset.BoolFlag{
- Name: "metrics",
- Usage: "Enable metrics collection and reporting",
- Value: &c.cliConfig.Telemetry.Enabled,
+ Name: "metrics",
+ Usage: "Enable metrics collection and reporting",
+ Value: &c.cliConfig.Telemetry.Enabled,
+ Default: c.cliConfig.Telemetry.Enabled,
+ Group: "Telemetry",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "metrics.expensive",
- Usage: "Enable expensive metrics collection and reporting",
- Value: &c.cliConfig.Telemetry.Expensive,
+ Name: "metrics.expensive",
+ Usage: "Enable expensive metrics collection and reporting",
+ Value: &c.cliConfig.Telemetry.Expensive,
+ Default: c.cliConfig.Telemetry.Expensive,
+ Group: "Telemetry",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "metrics.influxdb",
- Usage: "Enable metrics export/push to an external InfluxDB database (v1)",
- Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled,
+ Name: "metrics.influxdb",
+ Usage: "Enable metrics export/push to an external InfluxDB database (v1)",
+ Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled,
+ Default: c.cliConfig.Telemetry.InfluxDB.V1Enabled,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.influxdb.endpoint",
- Usage: "InfluxDB API endpoint to report metrics to",
- Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint,
+ Name: "metrics.influxdb.endpoint",
+ Usage: "InfluxDB API endpoint to report metrics to",
+ Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint,
+ Default: c.cliConfig.Telemetry.InfluxDB.Endpoint,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.influxdb.database",
- Usage: "InfluxDB database name to push reported metrics to",
- Value: &c.cliConfig.Telemetry.InfluxDB.Database,
+ Name: "metrics.influxdb.database",
+ Usage: "InfluxDB database name to push reported metrics to",
+ Value: &c.cliConfig.Telemetry.InfluxDB.Database,
+ Default: c.cliConfig.Telemetry.InfluxDB.Database,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.influxdb.username",
- Usage: "Username to authorize access to the database",
- Value: &c.cliConfig.Telemetry.InfluxDB.Username,
+ Name: "metrics.influxdb.username",
+ Usage: "Username to authorize access to the database",
+ Value: &c.cliConfig.Telemetry.InfluxDB.Username,
+ Default: c.cliConfig.Telemetry.InfluxDB.Username,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.influxdb.password",
- Usage: "Password to authorize access to the database",
- Value: &c.cliConfig.Telemetry.InfluxDB.Password,
+ Name: "metrics.influxdb.password",
+ Usage: "Password to authorize access to the database",
+ Value: &c.cliConfig.Telemetry.InfluxDB.Password,
+ Default: c.cliConfig.Telemetry.InfluxDB.Password,
+ Group: "Telemetry",
})
f.MapStringFlag(&flagset.MapStringFlag{
Name: "metrics.influxdb.tags",
Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements",
Value: &c.cliConfig.Telemetry.InfluxDB.Tags,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.prometheus-addr",
- Usage: "Address for Prometheus Server",
- Value: &c.cliConfig.Telemetry.PrometheusAddr,
+ Name: "metrics.prometheus-addr",
+ Usage: "Address for Prometheus Server",
+ Value: &c.cliConfig.Telemetry.PrometheusAddr,
+ Default: c.cliConfig.Telemetry.PrometheusAddr,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.opencollector-endpoint",
- Usage: "OpenCollector Endpoint (host:port)",
- Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint,
+ Name: "metrics.opencollector-endpoint",
+ Usage: "OpenCollector Endpoint (host:port)",
+ Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint,
+ Default: c.cliConfig.Telemetry.OpenCollectorEndpoint,
+ Group: "Telemetry",
})
// influx db v2
f.BoolFlag(&flagset.BoolFlag{
- Name: "metrics.influxdbv2",
- Usage: "Enable metrics export/push to an external InfluxDB v2 database",
- Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled,
+ Name: "metrics.influxdbv2",
+ Usage: "Enable metrics export/push to an external InfluxDB v2 database",
+ Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled,
+ Default: c.cliConfig.Telemetry.InfluxDB.V2Enabled,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.influxdb.token",
- Usage: "Token to authorize access to the database (v2 only)",
- Value: &c.cliConfig.Telemetry.InfluxDB.Token,
+ Name: "metrics.influxdb.token",
+ Usage: "Token to authorize access to the database (v2 only)",
+ Value: &c.cliConfig.Telemetry.InfluxDB.Token,
+ Default: c.cliConfig.Telemetry.InfluxDB.Token,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.influxdb.bucket",
- Usage: "InfluxDB bucket name to push reported metrics to (v2 only)",
- Value: &c.cliConfig.Telemetry.InfluxDB.Bucket,
+ Name: "metrics.influxdb.bucket",
+ Usage: "InfluxDB bucket name to push reported metrics to (v2 only)",
+ Value: &c.cliConfig.Telemetry.InfluxDB.Bucket,
+ Default: c.cliConfig.Telemetry.InfluxDB.Bucket,
+ Group: "Telemetry",
})
f.StringFlag(&flagset.StringFlag{
- Name: "metrics.influxdb.organization",
- Usage: "InfluxDB organization name (v2 only)",
- Value: &c.cliConfig.Telemetry.InfluxDB.Organization,
+ Name: "metrics.influxdb.organization",
+ Usage: "InfluxDB organization name (v2 only)",
+ Value: &c.cliConfig.Telemetry.InfluxDB.Organization,
+ Default: c.cliConfig.Telemetry.InfluxDB.Organization,
+ Group: "Telemetry",
})
// account
@@ -445,40 +584,56 @@ func (c *Command) Flags() *flagset.Flagset {
Name: "unlock",
Usage: "Comma separated list of accounts to unlock",
Value: &c.cliConfig.Accounts.Unlock,
+ Group: "Account Management",
})
f.StringFlag(&flagset.StringFlag{
- Name: "password",
- Usage: "Password file to use for non-interactive password input",
- Value: &c.cliConfig.Accounts.PasswordFile,
+ Name: "password",
+ Usage: "Password file to use for non-interactive password input",
+ Value: &c.cliConfig.Accounts.PasswordFile,
+ Default: c.cliConfig.Accounts.PasswordFile,
+ Group: "Account Management",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "allow-insecure-unlock",
- Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http",
- Value: &c.cliConfig.Accounts.AllowInsecureUnlock,
+ Name: "allow-insecure-unlock",
+ Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http",
+ Value: &c.cliConfig.Accounts.AllowInsecureUnlock,
+ Default: c.cliConfig.Accounts.AllowInsecureUnlock,
+ Group: "Account Management",
})
f.BoolFlag(&flagset.BoolFlag{
- Name: "lightkdf",
- Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
- Value: &c.cliConfig.Accounts.UseLightweightKDF,
+ Name: "lightkdf",
+ Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
+ Value: &c.cliConfig.Accounts.UseLightweightKDF,
+ Default: c.cliConfig.Accounts.UseLightweightKDF,
+ Group: "Account Management",
})
+ f.BoolFlag((&flagset.BoolFlag{
+ Name: "disable-bor-wallet",
+ Usage: "Disable the personal wallet endpoints",
+ Value: &c.cliConfig.Accounts.DisableBorWallet,
+ Default: c.cliConfig.Accounts.DisableBorWallet,
+ }))
// grpc
f.StringFlag(&flagset.StringFlag{
- Name: "grpc.addr",
- Usage: "Address and port to bind the GRPC server",
- Value: &c.cliConfig.GRPC.Addr,
+ Name: "grpc.addr",
+ Usage: "Address and port to bind the GRPC server",
+ Value: &c.cliConfig.GRPC.Addr,
+ Default: c.cliConfig.GRPC.Addr,
})
// developer
f.BoolFlag(&flagset.BoolFlag{
- Name: "dev",
- Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled",
- Value: &c.cliConfig.Developer.Enabled,
+ Name: "dev",
+ Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled",
+ Value: &c.cliConfig.Developer.Enabled,
+ Default: c.cliConfig.Developer.Enabled,
})
f.Uint64Flag(&flagset.Uint64Flag{
- Name: "dev.period",
- Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
- Value: &c.cliConfig.Developer.Period,
+ Name: "dev.period",
+ Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
+ Value: &c.cliConfig.Developer.Period,
+ Default: c.cliConfig.Developer.Period,
})
return f
}
diff --git a/internal/cli/server/helper.go b/internal/cli/server/helper.go
new file mode 100644
index 0000000000..3a232d3185
--- /dev/null
+++ b/internal/cli/server/helper.go
@@ -0,0 +1,83 @@
+package server
+
+import (
+ "fmt"
+ "io/ioutil"
+ "math/rand"
+ "net"
+ "os"
+ "sync/atomic"
+ "time"
+)
+
+var maxPortCheck int32 = 100
+
+// findAvailablePort returns the next available port starting from `from`
+func findAvailablePort(from int32, count int32) (int32, error) {
+ if count == maxPortCheck {
+ return 0, fmt.Errorf("no available port found")
+ }
+
+ port := atomic.AddInt32(&from, 1)
+ addr := fmt.Sprintf("localhost:%d", port)
+
+ count++
+
+ lis, err := net.Listen("tcp", addr)
+ if err == nil {
+ lis.Close()
+ return port, nil
+ } else {
+ return findAvailablePort(from, count)
+ }
+}
+
+func CreateMockServer(config *Config) (*Server, error) {
+ if config == nil {
+ config = DefaultConfig()
+ }
+
+ // find available port for grpc server
+ rand.Seed(time.Now().UnixNano())
+
+ var (
+ from int32 = 60000 // the min port to start checking from
+ to int32 = 61000 // the max port to start checking from
+ )
+
+ //nolint: gosec
+ port, err := findAvailablePort(rand.Int31n(to-from+1)+from, 0)
+ if err != nil {
+ return nil, err
+ }
+
+ // grpc port
+ config.GRPC.Addr = fmt.Sprintf(":%d", port)
+
+ // datadir
+ datadir, _ := ioutil.TempDir("/tmp", "bor-cli-test")
+ config.DataDir = datadir
+
+ // find available port for http server
+ from = 8545
+ to = 9545
+
+ //nolint: gosec
+ port, err = findAvailablePort(rand.Int31n(to-from+1)+from, 0)
+ if err != nil {
+ return nil, err
+ }
+
+ config.JsonRPC.Http.Port = uint64(port)
+
+ // start the server
+ return NewServer(config)
+}
+
+func CloseMockServer(server *Server) {
+ // remove the contents of temp data dir
+ os.RemoveAll(server.config.DataDir)
+
+ // close the server
+ server.Stop()
+}
diff --git a/internal/cli/server/proto/server.pb.go b/internal/cli/server/proto/server.pb.go
index a709c538ae..5512d83b72 100644
--- a/internal/cli/server/proto/server.pb.go
+++ b/internal/cli/server/proto/server.pb.go
@@ -1,13 +1,12 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.25.0
-// protoc v3.17.3
-// source: command/server/proto/server.proto
+// protoc-gen-go v1.27.1
+// protoc v3.19.3
+// source: internal/cli/server/proto/server.proto
package proto
import (
- proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
@@ -22,57 +21,138 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
-// This is a compile-time assertion that a sufficiently up-to-date version
-// of the legacy proto package is being used.
-const _ = proto.ProtoPackageIsVersion4
-
-type PprofRequest_Type int32
+type DebugPprofRequest_Type int32
const (
- PprofRequest_LOOKUP PprofRequest_Type = 0
- PprofRequest_CPU PprofRequest_Type = 1
- PprofRequest_TRACE PprofRequest_Type = 2
+ DebugPprofRequest_LOOKUP DebugPprofRequest_Type = 0
+ DebugPprofRequest_CPU DebugPprofRequest_Type = 1
+ DebugPprofRequest_TRACE DebugPprofRequest_Type = 2
)
-// Enum value maps for PprofRequest_Type.
+// Enum value maps for DebugPprofRequest_Type.
var (
- PprofRequest_Type_name = map[int32]string{
+ DebugPprofRequest_Type_name = map[int32]string{
0: "LOOKUP",
1: "CPU",
2: "TRACE",
}
- PprofRequest_Type_value = map[string]int32{
+ DebugPprofRequest_Type_value = map[string]int32{
"LOOKUP": 0,
"CPU": 1,
"TRACE": 2,
}
)
-func (x PprofRequest_Type) Enum() *PprofRequest_Type {
- p := new(PprofRequest_Type)
+func (x DebugPprofRequest_Type) Enum() *DebugPprofRequest_Type {
+ p := new(DebugPprofRequest_Type)
*p = x
return p
}
-func (x PprofRequest_Type) String() string {
+func (x DebugPprofRequest_Type) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
-func (PprofRequest_Type) Descriptor() protoreflect.EnumDescriptor {
- return file_command_server_proto_server_proto_enumTypes[0].Descriptor()
+func (DebugPprofRequest_Type) Descriptor() protoreflect.EnumDescriptor {
+ return file_internal_cli_server_proto_server_proto_enumTypes[0].Descriptor()
}
-func (PprofRequest_Type) Type() protoreflect.EnumType {
- return &file_command_server_proto_server_proto_enumTypes[0]
+func (DebugPprofRequest_Type) Type() protoreflect.EnumType {
+ return &file_internal_cli_server_proto_server_proto_enumTypes[0]
}
-func (x PprofRequest_Type) Number() protoreflect.EnumNumber {
+func (x DebugPprofRequest_Type) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
-// Deprecated: Use PprofRequest_Type.Descriptor instead.
-func (PprofRequest_Type) EnumDescriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{16, 0}
+// Deprecated: Use DebugPprofRequest_Type.Descriptor instead.
+func (DebugPprofRequest_Type) EnumDescriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{18, 0}
+}
+
+type TraceRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+}
+
+func (x *TraceRequest) Reset() {
+ *x = TraceRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TraceRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TraceRequest) ProtoMessage() {}
+
+func (x *TraceRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TraceRequest.ProtoReflect.Descriptor instead.
+func (*TraceRequest) Descriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *TraceRequest) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+type TraceResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *TraceResponse) Reset() {
+ *x = TraceResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TraceResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TraceResponse) ProtoMessage() {}
+
+func (x *TraceResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TraceResponse.ProtoReflect.Descriptor instead.
+func (*TraceResponse) Descriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{1}
}
type ChainWatchRequest struct {
@@ -84,7 +164,7 @@ type ChainWatchRequest struct {
func (x *ChainWatchRequest) Reset() {
*x = ChainWatchRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[0]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -97,7 +177,7 @@ func (x *ChainWatchRequest) String() string {
func (*ChainWatchRequest) ProtoMessage() {}
func (x *ChainWatchRequest) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[0]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -110,7 +190,7 @@ func (x *ChainWatchRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChainWatchRequest.ProtoReflect.Descriptor instead.
func (*ChainWatchRequest) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{0}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{2}
}
type ChainWatchResponse struct {
@@ -126,7 +206,7 @@ type ChainWatchResponse struct {
func (x *ChainWatchResponse) Reset() {
*x = ChainWatchResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[1]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -139,7 +219,7 @@ func (x *ChainWatchResponse) String() string {
func (*ChainWatchResponse) ProtoMessage() {}
func (x *ChainWatchResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[1]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -152,7 +232,7 @@ func (x *ChainWatchResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChainWatchResponse.ProtoReflect.Descriptor instead.
func (*ChainWatchResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{1}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{3}
}
func (x *ChainWatchResponse) GetOldchain() []*BlockStub {
@@ -188,7 +268,7 @@ type BlockStub struct {
func (x *BlockStub) Reset() {
*x = BlockStub{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[2]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -201,7 +281,7 @@ func (x *BlockStub) String() string {
func (*BlockStub) ProtoMessage() {}
func (x *BlockStub) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[2]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -214,7 +294,7 @@ func (x *BlockStub) ProtoReflect() protoreflect.Message {
// Deprecated: Use BlockStub.ProtoReflect.Descriptor instead.
func (*BlockStub) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{2}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{4}
}
func (x *BlockStub) GetHash() string {
@@ -243,7 +323,7 @@ type PeersAddRequest struct {
func (x *PeersAddRequest) Reset() {
*x = PeersAddRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[3]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -256,7 +336,7 @@ func (x *PeersAddRequest) String() string {
func (*PeersAddRequest) ProtoMessage() {}
func (x *PeersAddRequest) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[3]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -269,7 +349,7 @@ func (x *PeersAddRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersAddRequest.ProtoReflect.Descriptor instead.
func (*PeersAddRequest) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{3}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{5}
}
func (x *PeersAddRequest) GetEnode() string {
@@ -295,7 +375,7 @@ type PeersAddResponse struct {
func (x *PeersAddResponse) Reset() {
*x = PeersAddResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[4]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -308,7 +388,7 @@ func (x *PeersAddResponse) String() string {
func (*PeersAddResponse) ProtoMessage() {}
func (x *PeersAddResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[4]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -321,7 +401,7 @@ func (x *PeersAddResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersAddResponse.ProtoReflect.Descriptor instead.
func (*PeersAddResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{4}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{6}
}
type PeersRemoveRequest struct {
@@ -336,7 +416,7 @@ type PeersRemoveRequest struct {
func (x *PeersRemoveRequest) Reset() {
*x = PeersRemoveRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[5]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -349,7 +429,7 @@ func (x *PeersRemoveRequest) String() string {
func (*PeersRemoveRequest) ProtoMessage() {}
func (x *PeersRemoveRequest) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[5]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -362,7 +442,7 @@ func (x *PeersRemoveRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersRemoveRequest.ProtoReflect.Descriptor instead.
func (*PeersRemoveRequest) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{5}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{7}
}
func (x *PeersRemoveRequest) GetEnode() string {
@@ -388,7 +468,7 @@ type PeersRemoveResponse struct {
func (x *PeersRemoveResponse) Reset() {
*x = PeersRemoveResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[6]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -401,7 +481,7 @@ func (x *PeersRemoveResponse) String() string {
func (*PeersRemoveResponse) ProtoMessage() {}
func (x *PeersRemoveResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[6]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -414,7 +494,7 @@ func (x *PeersRemoveResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersRemoveResponse.ProtoReflect.Descriptor instead.
func (*PeersRemoveResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{6}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{8}
}
type PeersListRequest struct {
@@ -426,7 +506,7 @@ type PeersListRequest struct {
func (x *PeersListRequest) Reset() {
*x = PeersListRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[7]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -439,7 +519,7 @@ func (x *PeersListRequest) String() string {
func (*PeersListRequest) ProtoMessage() {}
func (x *PeersListRequest) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[7]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -452,7 +532,7 @@ func (x *PeersListRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersListRequest.ProtoReflect.Descriptor instead.
func (*PeersListRequest) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{7}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{9}
}
type PeersListResponse struct {
@@ -466,7 +546,7 @@ type PeersListResponse struct {
func (x *PeersListResponse) Reset() {
*x = PeersListResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[8]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -479,7 +559,7 @@ func (x *PeersListResponse) String() string {
func (*PeersListResponse) ProtoMessage() {}
func (x *PeersListResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[8]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -492,7 +572,7 @@ func (x *PeersListResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersListResponse.ProtoReflect.Descriptor instead.
func (*PeersListResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{8}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{10}
}
func (x *PeersListResponse) GetPeers() []*Peer {
@@ -513,7 +593,7 @@ type PeersStatusRequest struct {
func (x *PeersStatusRequest) Reset() {
*x = PeersStatusRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[9]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -526,7 +606,7 @@ func (x *PeersStatusRequest) String() string {
func (*PeersStatusRequest) ProtoMessage() {}
func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[9]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -539,7 +619,7 @@ func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersStatusRequest.ProtoReflect.Descriptor instead.
func (*PeersStatusRequest) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{9}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{11}
}
func (x *PeersStatusRequest) GetEnode() string {
@@ -560,7 +640,7 @@ type PeersStatusResponse struct {
func (x *PeersStatusResponse) Reset() {
*x = PeersStatusResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[10]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -573,7 +653,7 @@ func (x *PeersStatusResponse) String() string {
func (*PeersStatusResponse) ProtoMessage() {}
func (x *PeersStatusResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[10]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -586,7 +666,7 @@ func (x *PeersStatusResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeersStatusResponse.ProtoReflect.Descriptor instead.
func (*PeersStatusResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{10}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{12}
}
func (x *PeersStatusResponse) GetPeer() *Peer {
@@ -613,7 +693,7 @@ type Peer struct {
func (x *Peer) Reset() {
*x = Peer{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[11]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -626,7 +706,7 @@ func (x *Peer) String() string {
func (*Peer) ProtoMessage() {}
func (x *Peer) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[11]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -639,7 +719,7 @@ func (x *Peer) ProtoReflect() protoreflect.Message {
// Deprecated: Use Peer.ProtoReflect.Descriptor instead.
func (*Peer) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{11}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{13}
}
func (x *Peer) GetId() string {
@@ -702,7 +782,7 @@ type ChainSetHeadRequest struct {
func (x *ChainSetHeadRequest) Reset() {
*x = ChainSetHeadRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[12]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -715,7 +795,7 @@ func (x *ChainSetHeadRequest) String() string {
func (*ChainSetHeadRequest) ProtoMessage() {}
func (x *ChainSetHeadRequest) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[12]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -728,7 +808,7 @@ func (x *ChainSetHeadRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChainSetHeadRequest.ProtoReflect.Descriptor instead.
func (*ChainSetHeadRequest) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{12}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14}
}
func (x *ChainSetHeadRequest) GetNumber() uint64 {
@@ -747,7 +827,7 @@ type ChainSetHeadResponse struct {
func (x *ChainSetHeadResponse) Reset() {
*x = ChainSetHeadResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[13]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -760,7 +840,7 @@ func (x *ChainSetHeadResponse) String() string {
func (*ChainSetHeadResponse) ProtoMessage() {}
func (x *ChainSetHeadResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[13]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -773,7 +853,7 @@ func (x *ChainSetHeadResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChainSetHeadResponse.ProtoReflect.Descriptor instead.
func (*ChainSetHeadResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{13}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{15}
}
type StatusResponse struct {
@@ -792,7 +872,7 @@ type StatusResponse struct {
func (x *StatusResponse) Reset() {
*x = StatusResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[14]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -805,7 +885,7 @@ func (x *StatusResponse) String() string {
func (*StatusResponse) ProtoMessage() {}
func (x *StatusResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[14]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -818,7 +898,7 @@ func (x *StatusResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead.
func (*StatusResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{14}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16}
}
func (x *StatusResponse) GetCurrentBlock() *Header {
@@ -875,7 +955,7 @@ type Header struct {
func (x *Header) Reset() {
*x = Header{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[15]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -888,7 +968,7 @@ func (x *Header) String() string {
func (*Header) ProtoMessage() {}
func (x *Header) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[15]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -901,7 +981,7 @@ func (x *Header) ProtoReflect() protoreflect.Message {
// Deprecated: Use Header.ProtoReflect.Descriptor instead.
func (*Header) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{15}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17}
}
func (x *Header) GetHash() string {
@@ -918,33 +998,33 @@ func (x *Header) GetNumber() uint64 {
return 0
}
-type PprofRequest struct {
+type DebugPprofRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- Type PprofRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=proto.PprofRequest_Type" json:"type,omitempty"`
- Profile string `protobuf:"bytes,2,opt,name=profile,proto3" json:"profile,omitempty"`
- Seconds int64 `protobuf:"varint,3,opt,name=seconds,proto3" json:"seconds,omitempty"`
+ Type DebugPprofRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=proto.DebugPprofRequest_Type" json:"type,omitempty"`
+ Profile string `protobuf:"bytes,2,opt,name=profile,proto3" json:"profile,omitempty"`
+ Seconds int64 `protobuf:"varint,3,opt,name=seconds,proto3" json:"seconds,omitempty"`
}
-func (x *PprofRequest) Reset() {
- *x = PprofRequest{}
+func (x *DebugPprofRequest) Reset() {
+ *x = DebugPprofRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[16]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
-func (x *PprofRequest) String() string {
+func (x *DebugPprofRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
-func (*PprofRequest) ProtoMessage() {}
+func (*DebugPprofRequest) ProtoMessage() {}
-func (x *PprofRequest) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[16]
+func (x *DebugPprofRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -955,61 +1035,57 @@ func (x *PprofRequest) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
-// Deprecated: Use PprofRequest.ProtoReflect.Descriptor instead.
-func (*PprofRequest) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{16}
+// Deprecated: Use DebugPprofRequest.ProtoReflect.Descriptor instead.
+func (*DebugPprofRequest) Descriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{18}
}
-func (x *PprofRequest) GetType() PprofRequest_Type {
+func (x *DebugPprofRequest) GetType() DebugPprofRequest_Type {
if x != nil {
return x.Type
}
- return PprofRequest_LOOKUP
+ return DebugPprofRequest_LOOKUP
}
-func (x *PprofRequest) GetProfile() string {
+func (x *DebugPprofRequest) GetProfile() string {
if x != nil {
return x.Profile
}
return ""
}
-func (x *PprofRequest) GetSeconds() int64 {
+func (x *DebugPprofRequest) GetSeconds() int64 {
if x != nil {
return x.Seconds
}
return 0
}
-type PprofResponse struct {
+type DebugBlockRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- // Types that are assignable to Event:
- // *PprofResponse_Open_
- // *PprofResponse_Input_
- // *PprofResponse_Eof
- Event isPprofResponse_Event `protobuf_oneof:"event"`
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
}
-func (x *PprofResponse) Reset() {
- *x = PprofResponse{}
+func (x *DebugBlockRequest) Reset() {
+ *x = DebugBlockRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[17]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
-func (x *PprofResponse) String() string {
+func (x *DebugBlockRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
-func (*PprofResponse) ProtoMessage() {}
+func (*DebugBlockRequest) ProtoMessage() {}
-func (x *PprofResponse) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[17]
+func (x *DebugBlockRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1020,60 +1096,111 @@ func (x *PprofResponse) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
-// Deprecated: Use PprofResponse.ProtoReflect.Descriptor instead.
-func (*PprofResponse) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{17}
+// Deprecated: Use DebugBlockRequest.ProtoReflect.Descriptor instead.
+func (*DebugBlockRequest) Descriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{19}
}
-func (m *PprofResponse) GetEvent() isPprofResponse_Event {
+func (x *DebugBlockRequest) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+type DebugFileResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Types that are assignable to Event:
+ // *DebugFileResponse_Open_
+ // *DebugFileResponse_Input_
+ // *DebugFileResponse_Eof
+ Event isDebugFileResponse_Event `protobuf_oneof:"event"`
+}
+
+func (x *DebugFileResponse) Reset() {
+ *x = DebugFileResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[20]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *DebugFileResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DebugFileResponse) ProtoMessage() {}
+
+func (x *DebugFileResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[20]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DebugFileResponse.ProtoReflect.Descriptor instead.
+func (*DebugFileResponse) Descriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{20}
+}
+
+func (m *DebugFileResponse) GetEvent() isDebugFileResponse_Event {
if m != nil {
return m.Event
}
return nil
}
-func (x *PprofResponse) GetOpen() *PprofResponse_Open {
- if x, ok := x.GetEvent().(*PprofResponse_Open_); ok {
+func (x *DebugFileResponse) GetOpen() *DebugFileResponse_Open {
+ if x, ok := x.GetEvent().(*DebugFileResponse_Open_); ok {
return x.Open
}
return nil
}
-func (x *PprofResponse) GetInput() *PprofResponse_Input {
- if x, ok := x.GetEvent().(*PprofResponse_Input_); ok {
+func (x *DebugFileResponse) GetInput() *DebugFileResponse_Input {
+ if x, ok := x.GetEvent().(*DebugFileResponse_Input_); ok {
return x.Input
}
return nil
}
-func (x *PprofResponse) GetEof() *emptypb.Empty {
- if x, ok := x.GetEvent().(*PprofResponse_Eof); ok {
+func (x *DebugFileResponse) GetEof() *emptypb.Empty {
+ if x, ok := x.GetEvent().(*DebugFileResponse_Eof); ok {
return x.Eof
}
return nil
}
-type isPprofResponse_Event interface {
- isPprofResponse_Event()
+type isDebugFileResponse_Event interface {
+ isDebugFileResponse_Event()
}
-type PprofResponse_Open_ struct {
- Open *PprofResponse_Open `protobuf:"bytes,1,opt,name=open,proto3,oneof"`
+type DebugFileResponse_Open_ struct {
+ Open *DebugFileResponse_Open `protobuf:"bytes,1,opt,name=open,proto3,oneof"`
}
-type PprofResponse_Input_ struct {
- Input *PprofResponse_Input `protobuf:"bytes,2,opt,name=input,proto3,oneof"`
+type DebugFileResponse_Input_ struct {
+ Input *DebugFileResponse_Input `protobuf:"bytes,2,opt,name=input,proto3,oneof"`
}
-type PprofResponse_Eof struct {
+type DebugFileResponse_Eof struct {
Eof *emptypb.Empty `protobuf:"bytes,3,opt,name=eof,proto3,oneof"`
}
-func (*PprofResponse_Open_) isPprofResponse_Event() {}
+func (*DebugFileResponse_Open_) isDebugFileResponse_Event() {}
-func (*PprofResponse_Input_) isPprofResponse_Event() {}
+func (*DebugFileResponse_Input_) isDebugFileResponse_Event() {}
-func (*PprofResponse_Eof) isPprofResponse_Event() {}
+func (*DebugFileResponse_Eof) isDebugFileResponse_Event() {}
type StatusResponse_Fork struct {
state protoimpl.MessageState
@@ -1088,7 +1215,7 @@ type StatusResponse_Fork struct {
func (x *StatusResponse_Fork) Reset() {
*x = StatusResponse_Fork{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[18]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1101,7 +1228,7 @@ func (x *StatusResponse_Fork) String() string {
func (*StatusResponse_Fork) ProtoMessage() {}
func (x *StatusResponse_Fork) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[18]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1114,7 +1241,7 @@ func (x *StatusResponse_Fork) ProtoReflect() protoreflect.Message {
// Deprecated: Use StatusResponse_Fork.ProtoReflect.Descriptor instead.
func (*StatusResponse_Fork) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{14, 0}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16, 0}
}
func (x *StatusResponse_Fork) GetName() string {
@@ -1151,7 +1278,7 @@ type StatusResponse_Syncing struct {
func (x *StatusResponse_Syncing) Reset() {
*x = StatusResponse_Syncing{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[19]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1164,7 +1291,7 @@ func (x *StatusResponse_Syncing) String() string {
func (*StatusResponse_Syncing) ProtoMessage() {}
func (x *StatusResponse_Syncing) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[19]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1177,7 +1304,7 @@ func (x *StatusResponse_Syncing) ProtoReflect() protoreflect.Message {
// Deprecated: Use StatusResponse_Syncing.ProtoReflect.Descriptor instead.
func (*StatusResponse_Syncing) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{14, 1}
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16, 1}
}
func (x *StatusResponse_Syncing) GetStartingBlock() int64 {
@@ -1201,32 +1328,31 @@ func (x *StatusResponse_Syncing) GetCurrentBlock() int64 {
return 0
}
-type PprofResponse_Open struct {
+type DebugFileResponse_Open struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Headers map[string]string `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
- Size int64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
}
-func (x *PprofResponse_Open) Reset() {
- *x = PprofResponse_Open{}
+func (x *DebugFileResponse_Open) Reset() {
+ *x = DebugFileResponse_Open{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[20]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
-func (x *PprofResponse_Open) String() string {
+func (x *DebugFileResponse_Open) String() string {
return protoimpl.X.MessageStringOf(x)
}
-func (*PprofResponse_Open) ProtoMessage() {}
+func (*DebugFileResponse_Open) ProtoMessage() {}
-func (x *PprofResponse_Open) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[20]
+func (x *DebugFileResponse_Open) ProtoReflect() protoreflect.Message {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[23]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1237,26 +1363,19 @@ func (x *PprofResponse_Open) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
-// Deprecated: Use PprofResponse_Open.ProtoReflect.Descriptor instead.
-func (*PprofResponse_Open) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{17, 0}
+// Deprecated: Use DebugFileResponse_Open.ProtoReflect.Descriptor instead.
+func (*DebugFileResponse_Open) Descriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{20, 0}
}
-func (x *PprofResponse_Open) GetHeaders() map[string]string {
+func (x *DebugFileResponse_Open) GetHeaders() map[string]string {
if x != nil {
return x.Headers
}
return nil
}
-func (x *PprofResponse_Open) GetSize() int64 {
- if x != nil {
- return x.Size
- }
- return 0
-}
-
-type PprofResponse_Input struct {
+type DebugFileResponse_Input struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
@@ -1264,23 +1383,23 @@ type PprofResponse_Input struct {
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
}
-func (x *PprofResponse_Input) Reset() {
- *x = PprofResponse_Input{}
+func (x *DebugFileResponse_Input) Reset() {
+ *x = DebugFileResponse_Input{}
if protoimpl.UnsafeEnabled {
- mi := &file_command_server_proto_server_proto_msgTypes[21]
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
-func (x *PprofResponse_Input) String() string {
+func (x *DebugFileResponse_Input) String() string {
return protoimpl.X.MessageStringOf(x)
}
-func (*PprofResponse_Input) ProtoMessage() {}
+func (*DebugFileResponse_Input) ProtoMessage() {}
-func (x *PprofResponse_Input) ProtoReflect() protoreflect.Message {
- mi := &file_command_server_proto_server_proto_msgTypes[21]
+func (x *DebugFileResponse_Input) ProtoReflect() protoreflect.Message {
+ mi := &file_internal_cli_server_proto_server_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1291,263 +1410,305 @@ func (x *PprofResponse_Input) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
-// Deprecated: Use PprofResponse_Input.ProtoReflect.Descriptor instead.
-func (*PprofResponse_Input) Descriptor() ([]byte, []int) {
- return file_command_server_proto_server_proto_rawDescGZIP(), []int{17, 1}
+// Deprecated: Use DebugFileResponse_Input.ProtoReflect.Descriptor instead.
+func (*DebugFileResponse_Input) Descriptor() ([]byte, []int) {
+ return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{20, 1}
}
-func (x *PprofResponse_Input) GetData() []byte {
+func (x *DebugFileResponse_Input) GetData() []byte {
if x != nil {
return x.Data
}
return nil
}
-var File_command_server_proto_server_proto protoreflect.FileDescriptor
+var File_internal_cli_server_proto_server_proto protoreflect.FileDescriptor
-var file_command_server_proto_server_proto_rawDesc = []byte{
- 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74,
- 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, 0x11, 0x43, 0x68, 0x61, 0x69, 0x6e,
- 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x84, 0x01, 0x0a,
- 0x12, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c,
- 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69,
- 0x6e, 0x12, 0x2c, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
+var file_internal_cli_server_proto_server_proto_rawDesc = []byte{
+ 0x0a, 0x26, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+ 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x26, 0x0a, 0x0c,
+ 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06,
+ 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75,
+ 0x6d, 0x62, 0x65, 0x72, 0x22, 0x0f, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x0a, 0x11, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61,
+ 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x84, 0x01, 0x0a, 0x12, 0x43,
+ 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63,
- 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12,
- 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
- 0x79, 0x70, 0x65, 0x22, 0x37, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62,
- 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
- 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x0f,
- 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
- 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22,
- 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f,
- 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f,
- 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12,
- 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x50, 0x65, 0x65,
- 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x22, 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73,
- 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x05, 0x70, 0x65, 0x65,
- 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2a, 0x0a, 0x12,
+ 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12,
+ 0x2c, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53,
+ 0x74, 0x75, 0x62, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a,
+ 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x37, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x12, 0x12,
+ 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61,
+ 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x0f, 0x50, 0x65,
+ 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a,
+ 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e,
+ 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x12, 0x0a,
+ 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a,
+ 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
+ 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x73,
+ 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12,
+ 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50,
+ 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2a, 0x0a, 0x12, 0x50, 0x65,
+ 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a,
+ 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x22, 0x98,
+ 0x01, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a,
+ 0x03, 0x65, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x72, 0x12,
+ 0x12, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63,
+ 0x61, 0x70, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74,
+ 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65,
+ 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x22, 0x2d, 0x0a, 0x13, 0x43, 0x68, 0x61,
+ 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x68, 0x61, 0x69,
+ 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x22, 0xe2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
+ 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x33, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
+ 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0d, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6e,
+ 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e,
+ 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d,
+ 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d,
+ 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63,
+ 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x05,
+ 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x1a, 0x4c,
+ 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x77, 0x0a, 0x07,
+ 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a,
+ 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
+ 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12,
+ 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68,
+ 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xa2, 0x01, 0x0a, 0x11,
+ 0x44, 0x65, 0x62, 0x75, 0x67, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x50, 0x70, 0x72,
+ 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
+ 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18,
+ 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03,
+ 0x43, 0x50, 0x55, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x02,
+ 0x22, 0x2b, 0x0a, 0x11, 0x44, 0x65, 0x62, 0x75, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xdd, 0x02,
+ 0x0a, 0x11, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46,
+ 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e,
+ 0x48, 0x00, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x36, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x12, 0x2a, 0x0a, 0x03, 0x65, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x45, 0x6d, 0x70, 0x74, 0x79, 0x48, 0x00, 0x52, 0x03, 0x65, 0x6f, 0x66, 0x1a, 0x88, 0x01, 0x0a,
+ 0x04, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x44, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44,
+ 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74,
+ 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x48,
+ 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x1b, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74,
+ 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04,
+ 0x64, 0x61, 0x74, 0x61, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x32, 0xdd, 0x04,
+ 0x0a, 0x03, 0x42, 0x6f, 0x72, 0x12, 0x3b, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64,
+ 0x64, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41,
+ 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76,
+ 0x65, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52,
+ 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72,
+ 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65,
+ 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72,
+ 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72,
- 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x1f, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72,
- 0x22, 0x98, 0x01, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f,
- 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12,
- 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e,
- 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52,
- 0x04, 0x63, 0x61, 0x70, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75,
- 0x73, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73,
- 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x07, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x22, 0x2d, 0x0a, 0x13, 0x43,
- 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x68,
- 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0xe2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
- 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x33, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0d,
- 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a,
- 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x6e,
- 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x79, 0x6e,
- 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
- 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x79,
- 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x30,
- 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73,
- 0x1a, 0x4c, 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05,
- 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x6c, 0x6f,
- 0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x77,
- 0x0a, 0x07, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61,
- 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12,
- 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c,
- 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c,
- 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65,
- 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x98, 0x01,
- 0x0a, 0x0c, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c,
- 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07,
- 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70,
- 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64,
- 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73,
- 0x22, 0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x4f, 0x4b,
- 0x55, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x50, 0x55, 0x10, 0x01, 0x12, 0x09, 0x0a,
- 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x02, 0x22, 0xe1, 0x02, 0x0a, 0x0d, 0x50, 0x70, 0x72,
- 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x6f, 0x70,
- 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f,
- 0x70, 0x65, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x69,
- 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12,
- 0x2a, 0x0a, 0x03, 0x65, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67,
- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
- 0x6d, 0x70, 0x74, 0x79, 0x48, 0x00, 0x52, 0x03, 0x65, 0x6f, 0x66, 0x1a, 0x98, 0x01, 0x0a, 0x04,
- 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x40, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70,
- 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e,
- 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68,
- 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65,
- 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
- 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x1b, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12,
- 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64,
- 0x61, 0x74, 0x61, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x32, 0x8b, 0x04, 0x0a,
- 0x03, 0x42, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x05, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x12, 0x13, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x50, 0x65,
- 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50,
- 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73,
- 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50,
- 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52,
- 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a,
- 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72,
- 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a,
- 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
- 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48,
- 0x65, 0x61, 0x64, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69,
- 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74,
- 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06,
- 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61,
- 0x74, 0x63, 0x68, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69,
- 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x17, 0x5a, 0x15, 0x2f, 0x63,
- 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47,
+ 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1a,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48,
+ 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75,
+ 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x12, 0x43, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63,
+ 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x50, 0x70,
+ 0x72, 0x6f, 0x66, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75,
+ 0x67, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0a, 0x44, 0x65, 0x62,
+ 0x75, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x44, 0x65, 0x62, 0x75, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46,
+ 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x1c, 0x5a,
+ 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x33,
}
var (
- file_command_server_proto_server_proto_rawDescOnce sync.Once
- file_command_server_proto_server_proto_rawDescData = file_command_server_proto_server_proto_rawDesc
+ file_internal_cli_server_proto_server_proto_rawDescOnce sync.Once
+ file_internal_cli_server_proto_server_proto_rawDescData = file_internal_cli_server_proto_server_proto_rawDesc
)
-func file_command_server_proto_server_proto_rawDescGZIP() []byte {
- file_command_server_proto_server_proto_rawDescOnce.Do(func() {
- file_command_server_proto_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_command_server_proto_server_proto_rawDescData)
+func file_internal_cli_server_proto_server_proto_rawDescGZIP() []byte {
+ file_internal_cli_server_proto_server_proto_rawDescOnce.Do(func() {
+ file_internal_cli_server_proto_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_cli_server_proto_server_proto_rawDescData)
})
- return file_command_server_proto_server_proto_rawDescData
+ return file_internal_cli_server_proto_server_proto_rawDescData
}
-var file_command_server_proto_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_command_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
-var file_command_server_proto_server_proto_goTypes = []interface{}{
- (PprofRequest_Type)(0), // 0: proto.PprofRequest.Type
- (*ChainWatchRequest)(nil), // 1: proto.ChainWatchRequest
- (*ChainWatchResponse)(nil), // 2: proto.ChainWatchResponse
- (*BlockStub)(nil), // 3: proto.BlockStub
- (*PeersAddRequest)(nil), // 4: proto.PeersAddRequest
- (*PeersAddResponse)(nil), // 5: proto.PeersAddResponse
- (*PeersRemoveRequest)(nil), // 6: proto.PeersRemoveRequest
- (*PeersRemoveResponse)(nil), // 7: proto.PeersRemoveResponse
- (*PeersListRequest)(nil), // 8: proto.PeersListRequest
- (*PeersListResponse)(nil), // 9: proto.PeersListResponse
- (*PeersStatusRequest)(nil), // 10: proto.PeersStatusRequest
- (*PeersStatusResponse)(nil), // 11: proto.PeersStatusResponse
- (*Peer)(nil), // 12: proto.Peer
- (*ChainSetHeadRequest)(nil), // 13: proto.ChainSetHeadRequest
- (*ChainSetHeadResponse)(nil), // 14: proto.ChainSetHeadResponse
- (*StatusResponse)(nil), // 15: proto.StatusResponse
- (*Header)(nil), // 16: proto.Header
- (*PprofRequest)(nil), // 17: proto.PprofRequest
- (*PprofResponse)(nil), // 18: proto.PprofResponse
- (*StatusResponse_Fork)(nil), // 19: proto.StatusResponse.Fork
- (*StatusResponse_Syncing)(nil), // 20: proto.StatusResponse.Syncing
- (*PprofResponse_Open)(nil), // 21: proto.PprofResponse.Open
- (*PprofResponse_Input)(nil), // 22: proto.PprofResponse.Input
- nil, // 23: proto.PprofResponse.Open.HeadersEntry
- (*emptypb.Empty)(nil), // 24: google.protobuf.Empty
+var file_internal_cli_server_proto_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_internal_cli_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
+var file_internal_cli_server_proto_server_proto_goTypes = []interface{}{
+ (DebugPprofRequest_Type)(0), // 0: proto.DebugPprofRequest.Type
+ (*TraceRequest)(nil), // 1: proto.TraceRequest
+ (*TraceResponse)(nil), // 2: proto.TraceResponse
+ (*ChainWatchRequest)(nil), // 3: proto.ChainWatchRequest
+ (*ChainWatchResponse)(nil), // 4: proto.ChainWatchResponse
+ (*BlockStub)(nil), // 5: proto.BlockStub
+ (*PeersAddRequest)(nil), // 6: proto.PeersAddRequest
+ (*PeersAddResponse)(nil), // 7: proto.PeersAddResponse
+ (*PeersRemoveRequest)(nil), // 8: proto.PeersRemoveRequest
+ (*PeersRemoveResponse)(nil), // 9: proto.PeersRemoveResponse
+ (*PeersListRequest)(nil), // 10: proto.PeersListRequest
+ (*PeersListResponse)(nil), // 11: proto.PeersListResponse
+ (*PeersStatusRequest)(nil), // 12: proto.PeersStatusRequest
+ (*PeersStatusResponse)(nil), // 13: proto.PeersStatusResponse
+ (*Peer)(nil), // 14: proto.Peer
+ (*ChainSetHeadRequest)(nil), // 15: proto.ChainSetHeadRequest
+ (*ChainSetHeadResponse)(nil), // 16: proto.ChainSetHeadResponse
+ (*StatusResponse)(nil), // 17: proto.StatusResponse
+ (*Header)(nil), // 18: proto.Header
+ (*DebugPprofRequest)(nil), // 19: proto.DebugPprofRequest
+ (*DebugBlockRequest)(nil), // 20: proto.DebugBlockRequest
+ (*DebugFileResponse)(nil), // 21: proto.DebugFileResponse
+ (*StatusResponse_Fork)(nil), // 22: proto.StatusResponse.Fork
+ (*StatusResponse_Syncing)(nil), // 23: proto.StatusResponse.Syncing
+ (*DebugFileResponse_Open)(nil), // 24: proto.DebugFileResponse.Open
+ (*DebugFileResponse_Input)(nil), // 25: proto.DebugFileResponse.Input
+ nil, // 26: proto.DebugFileResponse.Open.HeadersEntry
+ (*emptypb.Empty)(nil), // 27: google.protobuf.Empty
}
-var file_command_server_proto_server_proto_depIdxs = []int32{
- 3, // 0: proto.ChainWatchResponse.oldchain:type_name -> proto.BlockStub
- 3, // 1: proto.ChainWatchResponse.newchain:type_name -> proto.BlockStub
- 12, // 2: proto.PeersListResponse.peers:type_name -> proto.Peer
- 12, // 3: proto.PeersStatusResponse.peer:type_name -> proto.Peer
- 16, // 4: proto.StatusResponse.currentBlock:type_name -> proto.Header
- 16, // 5: proto.StatusResponse.currentHeader:type_name -> proto.Header
- 20, // 6: proto.StatusResponse.syncing:type_name -> proto.StatusResponse.Syncing
- 19, // 7: proto.StatusResponse.forks:type_name -> proto.StatusResponse.Fork
- 0, // 8: proto.PprofRequest.type:type_name -> proto.PprofRequest.Type
- 21, // 9: proto.PprofResponse.open:type_name -> proto.PprofResponse.Open
- 22, // 10: proto.PprofResponse.input:type_name -> proto.PprofResponse.Input
- 24, // 11: proto.PprofResponse.eof:type_name -> google.protobuf.Empty
- 23, // 12: proto.PprofResponse.Open.headers:type_name -> proto.PprofResponse.Open.HeadersEntry
- 17, // 13: proto.Bor.Pprof:input_type -> proto.PprofRequest
- 4, // 14: proto.Bor.PeersAdd:input_type -> proto.PeersAddRequest
- 6, // 15: proto.Bor.PeersRemove:input_type -> proto.PeersRemoveRequest
- 8, // 16: proto.Bor.PeersList:input_type -> proto.PeersListRequest
- 10, // 17: proto.Bor.PeersStatus:input_type -> proto.PeersStatusRequest
- 13, // 18: proto.Bor.ChainSetHead:input_type -> proto.ChainSetHeadRequest
- 24, // 19: proto.Bor.Status:input_type -> google.protobuf.Empty
- 1, // 20: proto.Bor.ChainWatch:input_type -> proto.ChainWatchRequest
- 18, // 21: proto.Bor.Pprof:output_type -> proto.PprofResponse
- 5, // 22: proto.Bor.PeersAdd:output_type -> proto.PeersAddResponse
- 7, // 23: proto.Bor.PeersRemove:output_type -> proto.PeersRemoveResponse
- 9, // 24: proto.Bor.PeersList:output_type -> proto.PeersListResponse
- 11, // 25: proto.Bor.PeersStatus:output_type -> proto.PeersStatusResponse
- 14, // 26: proto.Bor.ChainSetHead:output_type -> proto.ChainSetHeadResponse
- 15, // 27: proto.Bor.Status:output_type -> proto.StatusResponse
- 2, // 28: proto.Bor.ChainWatch:output_type -> proto.ChainWatchResponse
- 21, // [21:29] is the sub-list for method output_type
- 13, // [13:21] is the sub-list for method input_type
+var file_internal_cli_server_proto_server_proto_depIdxs = []int32{
+ 5, // 0: proto.ChainWatchResponse.oldchain:type_name -> proto.BlockStub
+ 5, // 1: proto.ChainWatchResponse.newchain:type_name -> proto.BlockStub
+ 14, // 2: proto.PeersListResponse.peers:type_name -> proto.Peer
+ 14, // 3: proto.PeersStatusResponse.peer:type_name -> proto.Peer
+ 18, // 4: proto.StatusResponse.currentBlock:type_name -> proto.Header
+ 18, // 5: proto.StatusResponse.currentHeader:type_name -> proto.Header
+ 23, // 6: proto.StatusResponse.syncing:type_name -> proto.StatusResponse.Syncing
+ 22, // 7: proto.StatusResponse.forks:type_name -> proto.StatusResponse.Fork
+ 0, // 8: proto.DebugPprofRequest.type:type_name -> proto.DebugPprofRequest.Type
+ 24, // 9: proto.DebugFileResponse.open:type_name -> proto.DebugFileResponse.Open
+ 25, // 10: proto.DebugFileResponse.input:type_name -> proto.DebugFileResponse.Input
+ 27, // 11: proto.DebugFileResponse.eof:type_name -> google.protobuf.Empty
+ 26, // 12: proto.DebugFileResponse.Open.headers:type_name -> proto.DebugFileResponse.Open.HeadersEntry
+ 6, // 13: proto.Bor.PeersAdd:input_type -> proto.PeersAddRequest
+ 8, // 14: proto.Bor.PeersRemove:input_type -> proto.PeersRemoveRequest
+ 10, // 15: proto.Bor.PeersList:input_type -> proto.PeersListRequest
+ 12, // 16: proto.Bor.PeersStatus:input_type -> proto.PeersStatusRequest
+ 15, // 17: proto.Bor.ChainSetHead:input_type -> proto.ChainSetHeadRequest
+ 27, // 18: proto.Bor.Status:input_type -> google.protobuf.Empty
+ 3, // 19: proto.Bor.ChainWatch:input_type -> proto.ChainWatchRequest
+ 19, // 20: proto.Bor.DebugPprof:input_type -> proto.DebugPprofRequest
+ 20, // 21: proto.Bor.DebugBlock:input_type -> proto.DebugBlockRequest
+ 7, // 22: proto.Bor.PeersAdd:output_type -> proto.PeersAddResponse
+ 9, // 23: proto.Bor.PeersRemove:output_type -> proto.PeersRemoveResponse
+ 11, // 24: proto.Bor.PeersList:output_type -> proto.PeersListResponse
+ 13, // 25: proto.Bor.PeersStatus:output_type -> proto.PeersStatusResponse
+ 16, // 26: proto.Bor.ChainSetHead:output_type -> proto.ChainSetHeadResponse
+ 17, // 27: proto.Bor.Status:output_type -> proto.StatusResponse
+ 4, // 28: proto.Bor.ChainWatch:output_type -> proto.ChainWatchResponse
+ 21, // 29: proto.Bor.DebugPprof:output_type -> proto.DebugFileResponse
+ 21, // 30: proto.Bor.DebugBlock:output_type -> proto.DebugFileResponse
+ 22, // [22:31] is the sub-list for method output_type
+ 13, // [13:22] is the sub-list for method input_type
13, // [13:13] is the sub-list for extension type_name
13, // [13:13] is the sub-list for extension extendee
0, // [0:13] is the sub-list for field type_name
}
-func init() { file_command_server_proto_server_proto_init() }
-func file_command_server_proto_server_proto_init() {
- if File_command_server_proto_server_proto != nil {
+func init() { file_internal_cli_server_proto_server_proto_init() }
+func file_internal_cli_server_proto_server_proto_init() {
+ if File_internal_cli_server_proto_server_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
- file_command_server_proto_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TraceRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_internal_cli_server_proto_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TraceResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_internal_cli_server_proto_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChainWatchRequest); i {
case 0:
return &v.state
@@ -1559,7 +1720,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChainWatchResponse); i {
case 0:
return &v.state
@@ -1571,7 +1732,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BlockStub); i {
case 0:
return &v.state
@@ -1583,7 +1744,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersAddRequest); i {
case 0:
return &v.state
@@ -1595,7 +1756,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersAddResponse); i {
case 0:
return &v.state
@@ -1607,7 +1768,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersRemoveRequest); i {
case 0:
return &v.state
@@ -1619,7 +1780,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersRemoveResponse); i {
case 0:
return &v.state
@@ -1631,7 +1792,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersListRequest); i {
case 0:
return &v.state
@@ -1643,7 +1804,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersListResponse); i {
case 0:
return &v.state
@@ -1655,7 +1816,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersStatusRequest); i {
case 0:
return &v.state
@@ -1667,7 +1828,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PeersStatusResponse); i {
case 0:
return &v.state
@@ -1679,7 +1840,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Peer); i {
case 0:
return &v.state
@@ -1691,7 +1852,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChainSetHeadRequest); i {
case 0:
return &v.state
@@ -1703,7 +1864,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChainSetHeadResponse); i {
case 0:
return &v.state
@@ -1715,7 +1876,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StatusResponse); i {
case 0:
return &v.state
@@ -1727,7 +1888,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Header); i {
case 0:
return &v.state
@@ -1739,8 +1900,8 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PprofRequest); i {
+ file_internal_cli_server_proto_server_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DebugPprofRequest); i {
case 0:
return &v.state
case 1:
@@ -1751,8 +1912,8 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PprofResponse); i {
+ file_internal_cli_server_proto_server_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DebugBlockRequest); i {
case 0:
return &v.state
case 1:
@@ -1763,7 +1924,19 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DebugFileResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_internal_cli_server_proto_server_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StatusResponse_Fork); i {
case 0:
return &v.state
@@ -1775,7 +1948,7 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ file_internal_cli_server_proto_server_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StatusResponse_Syncing); i {
case 0:
return &v.state
@@ -1787,8 +1960,8 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PprofResponse_Open); i {
+ file_internal_cli_server_proto_server_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DebugFileResponse_Open); i {
case 0:
return &v.state
case 1:
@@ -1799,8 +1972,8 @@ func file_command_server_proto_server_proto_init() {
return nil
}
}
- file_command_server_proto_server_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PprofResponse_Input); i {
+ file_internal_cli_server_proto_server_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DebugFileResponse_Input); i {
case 0:
return &v.state
case 1:
@@ -1812,28 +1985,28 @@ func file_command_server_proto_server_proto_init() {
}
}
}
- file_command_server_proto_server_proto_msgTypes[17].OneofWrappers = []interface{}{
- (*PprofResponse_Open_)(nil),
- (*PprofResponse_Input_)(nil),
- (*PprofResponse_Eof)(nil),
+ file_internal_cli_server_proto_server_proto_msgTypes[20].OneofWrappers = []interface{}{
+ (*DebugFileResponse_Open_)(nil),
+ (*DebugFileResponse_Input_)(nil),
+ (*DebugFileResponse_Eof)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_command_server_proto_server_proto_rawDesc,
+ RawDescriptor: file_internal_cli_server_proto_server_proto_rawDesc,
NumEnums: 1,
- NumMessages: 23,
+ NumMessages: 26,
NumExtensions: 0,
NumServices: 1,
},
- GoTypes: file_command_server_proto_server_proto_goTypes,
- DependencyIndexes: file_command_server_proto_server_proto_depIdxs,
- EnumInfos: file_command_server_proto_server_proto_enumTypes,
- MessageInfos: file_command_server_proto_server_proto_msgTypes,
+ GoTypes: file_internal_cli_server_proto_server_proto_goTypes,
+ DependencyIndexes: file_internal_cli_server_proto_server_proto_depIdxs,
+ EnumInfos: file_internal_cli_server_proto_server_proto_enumTypes,
+ MessageInfos: file_internal_cli_server_proto_server_proto_msgTypes,
}.Build()
- File_command_server_proto_server_proto = out.File
- file_command_server_proto_server_proto_rawDesc = nil
- file_command_server_proto_server_proto_goTypes = nil
- file_command_server_proto_server_proto_depIdxs = nil
+ File_internal_cli_server_proto_server_proto = out.File
+ file_internal_cli_server_proto_server_proto_rawDesc = nil
+ file_internal_cli_server_proto_server_proto_goTypes = nil
+ file_internal_cli_server_proto_server_proto_depIdxs = nil
}
diff --git a/internal/cli/server/proto/server.proto b/internal/cli/server/proto/server.proto
index 2dc84bff78..1520ab6536 100644
--- a/internal/cli/server/proto/server.proto
+++ b/internal/cli/server/proto/server.proto
@@ -4,11 +4,9 @@ package proto;
import "google/protobuf/empty.proto";
-option go_package = "/command/server/proto";
+option go_package = "/internal/cli/server/proto";
service Bor {
- rpc Pprof(PprofRequest) returns (stream PprofResponse);
-
rpc PeersAdd(PeersAddRequest) returns (PeersAddResponse);
rpc PeersRemove(PeersRemoveRequest) returns (PeersRemoveResponse);
@@ -20,8 +18,20 @@ service Bor {
rpc ChainSetHead(ChainSetHeadRequest) returns (ChainSetHeadResponse);
rpc Status(google.protobuf.Empty) returns (StatusResponse);
-
+
rpc ChainWatch(ChainWatchRequest) returns (stream ChainWatchResponse);
+
+ rpc DebugPprof(DebugPprofRequest) returns (stream DebugFileResponse);
+
+ rpc DebugBlock(DebugBlockRequest) returns (stream DebugFileResponse);
+}
+
+message TraceRequest {
+ int64 number = 1;
+}
+
+message TraceResponse {
+
}
message ChainWatchRequest {
@@ -113,7 +123,7 @@ message Header {
uint64 number = 2;
}
-message PprofRequest {
+message DebugPprofRequest {
Type type = 1;
string profile = 2;
@@ -127,7 +137,11 @@ message PprofRequest {
}
}
-message PprofResponse {
+message DebugBlockRequest {
+ int64 number = 1;
+}
+
+message DebugFileResponse {
oneof event {
Open open = 1;
Input input = 2;
@@ -136,7 +150,6 @@ message PprofResponse {
message Open {
map headers = 1;
- int64 size = 2;
}
message Input {
diff --git a/internal/cli/server/proto/server_grpc.pb.go b/internal/cli/server/proto/server_grpc.pb.go
index 9ed2593e47..63f1fa6187 100644
--- a/internal/cli/server/proto/server_grpc.pb.go
+++ b/internal/cli/server/proto/server_grpc.pb.go
@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
-// - protoc v3.17.3
-// source: command/server/proto/server.proto
+// - protoc v3.19.3
+// source: internal/cli/server/proto/server.proto
package proto
@@ -23,7 +23,6 @@ const _ = grpc.SupportPackageIsVersion7
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type BorClient interface {
- Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error)
PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error)
PeersRemove(ctx context.Context, in *PeersRemoveRequest, opts ...grpc.CallOption) (*PeersRemoveResponse, error)
PeersList(ctx context.Context, in *PeersListRequest, opts ...grpc.CallOption) (*PeersListResponse, error)
@@ -31,6 +30,8 @@ type BorClient interface {
ChainSetHead(ctx context.Context, in *ChainSetHeadRequest, opts ...grpc.CallOption) (*ChainSetHeadResponse, error)
Status(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StatusResponse, error)
ChainWatch(ctx context.Context, in *ChainWatchRequest, opts ...grpc.CallOption) (Bor_ChainWatchClient, error)
+ DebugPprof(ctx context.Context, in *DebugPprofRequest, opts ...grpc.CallOption) (Bor_DebugPprofClient, error)
+ DebugBlock(ctx context.Context, in *DebugBlockRequest, opts ...grpc.CallOption) (Bor_DebugBlockClient, error)
}
type borClient struct {
@@ -41,38 +42,6 @@ func NewBorClient(cc grpc.ClientConnInterface) BorClient {
return &borClient{cc}
}
-func (c *borClient) Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error) {
- stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[0], "/proto.Bor/Pprof", opts...)
- if err != nil {
- return nil, err
- }
- x := &borPprofClient{stream}
- if err := x.ClientStream.SendMsg(in); err != nil {
- return nil, err
- }
- if err := x.ClientStream.CloseSend(); err != nil {
- return nil, err
- }
- return x, nil
-}
-
-type Bor_PprofClient interface {
- Recv() (*PprofResponse, error)
- grpc.ClientStream
-}
-
-type borPprofClient struct {
- grpc.ClientStream
-}
-
-func (x *borPprofClient) Recv() (*PprofResponse, error) {
- m := new(PprofResponse)
- if err := x.ClientStream.RecvMsg(m); err != nil {
- return nil, err
- }
- return m, nil
-}
-
func (c *borClient) PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) {
out := new(PeersAddResponse)
err := c.cc.Invoke(ctx, "/proto.Bor/PeersAdd", in, out, opts...)
@@ -128,7 +97,7 @@ func (c *borClient) Status(ctx context.Context, in *emptypb.Empty, opts ...grpc.
}
func (c *borClient) ChainWatch(ctx context.Context, in *ChainWatchRequest, opts ...grpc.CallOption) (Bor_ChainWatchClient, error) {
- stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[1], "/proto.Bor/ChainWatch", opts...)
+ stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[0], "/proto.Bor/ChainWatch", opts...)
if err != nil {
return nil, err
}
@@ -159,11 +128,74 @@ func (x *borChainWatchClient) Recv() (*ChainWatchResponse, error) {
return m, nil
}
+func (c *borClient) DebugPprof(ctx context.Context, in *DebugPprofRequest, opts ...grpc.CallOption) (Bor_DebugPprofClient, error) {
+ stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[1], "/proto.Bor/DebugPprof", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &borDebugPprofClient{stream}
+ if err := x.ClientStream.SendMsg(in); err != nil {
+ return nil, err
+ }
+ if err := x.ClientStream.CloseSend(); err != nil {
+ return nil, err
+ }
+ return x, nil
+}
+
+type Bor_DebugPprofClient interface {
+ Recv() (*DebugFileResponse, error)
+ grpc.ClientStream
+}
+
+type borDebugPprofClient struct {
+ grpc.ClientStream
+}
+
+func (x *borDebugPprofClient) Recv() (*DebugFileResponse, error) {
+ m := new(DebugFileResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *borClient) DebugBlock(ctx context.Context, in *DebugBlockRequest, opts ...grpc.CallOption) (Bor_DebugBlockClient, error) {
+ stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[2], "/proto.Bor/DebugBlock", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &borDebugBlockClient{stream}
+ if err := x.ClientStream.SendMsg(in); err != nil {
+ return nil, err
+ }
+ if err := x.ClientStream.CloseSend(); err != nil {
+ return nil, err
+ }
+ return x, nil
+}
+
+type Bor_DebugBlockClient interface {
+ Recv() (*DebugFileResponse, error)
+ grpc.ClientStream
+}
+
+type borDebugBlockClient struct {
+ grpc.ClientStream
+}
+
+func (x *borDebugBlockClient) Recv() (*DebugFileResponse, error) {
+ m := new(DebugFileResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
// BorServer is the server API for Bor service.
// All implementations must embed UnimplementedBorServer
// for forward compatibility
type BorServer interface {
- Pprof(*PprofRequest, Bor_PprofServer) error
PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error)
PeersRemove(context.Context, *PeersRemoveRequest) (*PeersRemoveResponse, error)
PeersList(context.Context, *PeersListRequest) (*PeersListResponse, error)
@@ -171,6 +203,8 @@ type BorServer interface {
ChainSetHead(context.Context, *ChainSetHeadRequest) (*ChainSetHeadResponse, error)
Status(context.Context, *emptypb.Empty) (*StatusResponse, error)
ChainWatch(*ChainWatchRequest, Bor_ChainWatchServer) error
+ DebugPprof(*DebugPprofRequest, Bor_DebugPprofServer) error
+ DebugBlock(*DebugBlockRequest, Bor_DebugBlockServer) error
mustEmbedUnimplementedBorServer()
}
@@ -178,9 +212,6 @@ type BorServer interface {
type UnimplementedBorServer struct {
}
-func (UnimplementedBorServer) Pprof(*PprofRequest, Bor_PprofServer) error {
- return status.Errorf(codes.Unimplemented, "method Pprof not implemented")
-}
func (UnimplementedBorServer) PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PeersAdd not implemented")
}
@@ -202,6 +233,12 @@ func (UnimplementedBorServer) Status(context.Context, *emptypb.Empty) (*StatusRe
func (UnimplementedBorServer) ChainWatch(*ChainWatchRequest, Bor_ChainWatchServer) error {
return status.Errorf(codes.Unimplemented, "method ChainWatch not implemented")
}
+func (UnimplementedBorServer) DebugPprof(*DebugPprofRequest, Bor_DebugPprofServer) error {
+ return status.Errorf(codes.Unimplemented, "method DebugPprof not implemented")
+}
+func (UnimplementedBorServer) DebugBlock(*DebugBlockRequest, Bor_DebugBlockServer) error {
+ return status.Errorf(codes.Unimplemented, "method DebugBlock not implemented")
+}
func (UnimplementedBorServer) mustEmbedUnimplementedBorServer() {}
// UnsafeBorServer may be embedded to opt out of forward compatibility for this service.
@@ -215,27 +252,6 @@ func RegisterBorServer(s grpc.ServiceRegistrar, srv BorServer) {
s.RegisterService(&Bor_ServiceDesc, srv)
}
-func _Bor_Pprof_Handler(srv interface{}, stream grpc.ServerStream) error {
- m := new(PprofRequest)
- if err := stream.RecvMsg(m); err != nil {
- return err
- }
- return srv.(BorServer).Pprof(m, &borPprofServer{stream})
-}
-
-type Bor_PprofServer interface {
- Send(*PprofResponse) error
- grpc.ServerStream
-}
-
-type borPprofServer struct {
- grpc.ServerStream
-}
-
-func (x *borPprofServer) Send(m *PprofResponse) error {
- return x.ServerStream.SendMsg(m)
-}
-
func _Bor_PeersAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PeersAddRequest)
if err := dec(in); err != nil {
@@ -365,6 +381,48 @@ func (x *borChainWatchServer) Send(m *ChainWatchResponse) error {
return x.ServerStream.SendMsg(m)
}
+func _Bor_DebugPprof_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(DebugPprofRequest)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(BorServer).DebugPprof(m, &borDebugPprofServer{stream})
+}
+
+type Bor_DebugPprofServer interface {
+ Send(*DebugFileResponse) error
+ grpc.ServerStream
+}
+
+type borDebugPprofServer struct {
+ grpc.ServerStream
+}
+
+func (x *borDebugPprofServer) Send(m *DebugFileResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func _Bor_DebugBlock_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(DebugBlockRequest)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(BorServer).DebugBlock(m, &borDebugBlockServer{stream})
+}
+
+type Bor_DebugBlockServer interface {
+ Send(*DebugFileResponse) error
+ grpc.ServerStream
+}
+
+type borDebugBlockServer struct {
+ grpc.ServerStream
+}
+
+func (x *borDebugBlockServer) Send(m *DebugFileResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
// Bor_ServiceDesc is the grpc.ServiceDesc for Bor service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -398,16 +456,21 @@ var Bor_ServiceDesc = grpc.ServiceDesc{
},
},
Streams: []grpc.StreamDesc{
- {
- StreamName: "Pprof",
- Handler: _Bor_Pprof_Handler,
- ServerStreams: true,
- },
{
StreamName: "ChainWatch",
Handler: _Bor_ChainWatch_Handler,
ServerStreams: true,
},
+ {
+ StreamName: "DebugPprof",
+ Handler: _Bor_DebugPprof_Handler,
+ ServerStreams: true,
+ },
+ {
+ StreamName: "DebugBlock",
+ Handler: _Bor_DebugBlock_Handler,
+ ServerStreams: true,
+ },
},
- Metadata: "command/server/proto/server.proto",
+ Metadata: "internal/cli/server/proto/server.proto",
}
diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go
index e882429e86..7d5ec2c8f3 100644
--- a/internal/cli/server/server.go
+++ b/internal/cli/server/server.go
@@ -4,13 +4,28 @@ import (
"context"
"fmt"
"io"
+ "math/big"
"net"
"net/http"
"os"
"strings"
"time"
+ "github.com/mattn/go-colorable"
+ "github.com/mattn/go-isatty"
+ "go.opentelemetry.io/otel"
+ "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
+ "go.opentelemetry.io/otel/propagation"
+ "go.opentelemetry.io/otel/sdk/resource"
+ sdktrace "go.opentelemetry.io/otel/sdk/trace"
+ semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
+ "google.golang.org/grpc"
+
+ "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
+ "github.com/ethereum/go-ethereum/consensus/beacon"
+ "github.com/ethereum/go-ethereum/consensus/bor"
+ "github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethstats"
@@ -21,15 +36,6 @@ import (
"github.com/ethereum/go-ethereum/metrics/influxdb"
"github.com/ethereum/go-ethereum/metrics/prometheus"
"github.com/ethereum/go-ethereum/node"
- "github.com/mattn/go-colorable"
- "github.com/mattn/go-isatty"
- "go.opentelemetry.io/otel"
- "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
- "go.opentelemetry.io/otel/propagation"
- "go.opentelemetry.io/otel/sdk/resource"
- sdktrace "go.opentelemetry.io/otel/sdk/trace"
- semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
- "google.golang.org/grpc"
)
type Server struct {
@@ -39,6 +45,9 @@ type Server struct {
grpcServer *grpc.Server
tracer *sdktrace.TracerProvider
config *Config
+
+ // tracerAPI to trace block executions
+ tracerAPI *tracers.API
}
func NewServer(config *Config) (*Server, error) {
@@ -63,54 +72,131 @@ func NewServer(config *Config) (*Server, error) {
if err != nil {
return nil, err
}
+
stack, err := node.New(nodeCfg)
if err != nil {
return nil, err
}
- srv.node = stack
// setup account manager (only keystore)
- {
- keydir := stack.KeyStoreDir()
- n, p := keystore.StandardScryptN, keystore.StandardScryptP
- if config.Accounts.UseLightweightKDF {
- n, p = keystore.LightScryptN, keystore.LightScryptP
- }
+ // create a new account manager, only for the scope of this function
+ accountManager := accounts.NewManager(&accounts.Config{})
+
+ // register backend to account manager with keystore for signing
+ keydir := stack.KeyStoreDir()
+
+ n, p := keystore.StandardScryptN, keystore.StandardScryptP
+ if config.Accounts.UseLightweightKDF {
+ n, p = keystore.LightScryptN, keystore.LightScryptP
+ }
+
+ // proceed to authorize the local account manager in any case
+ accountManager.AddBackend(keystore.NewKeyStore(keydir, n, p))
+
+ // flag to set if we're authorizing consensus here
+ authorized := false
+
+ // check if personal wallet endpoints are disabled or not
+ // nolint:nestif
+ if !config.Accounts.DisableBorWallet {
+ // add keystore globally to the node's account manager if personal wallet is enabled
stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))
+
+ // register the ethereum backend
+ ethCfg, err := config.buildEth(stack, stack.AccountManager())
+ if err != nil {
+ return nil, err
+ }
+
+ backend, err := eth.New(stack, ethCfg)
+ if err != nil {
+ return nil, err
+ }
+
+ srv.backend = backend
+ } else {
+ // register the ethereum backend (with temporary created account manager)
+ ethCfg, err := config.buildEth(stack, accountManager)
+ if err != nil {
+ return nil, err
+ }
+
+ backend, err := eth.New(stack, ethCfg)
+ if err != nil {
+ return nil, err
+ }
+
+ srv.backend = backend
+
+ // authorize only if mining or in developer mode
+ if config.Sealer.Enabled || config.Developer.Enabled {
+ // get the etherbase
+ eb, err := srv.backend.Etherbase()
+ if err != nil {
+ log.Error("Cannot start mining without etherbase", "err", err)
+
+ return nil, fmt.Errorf("etherbase missing: %v", err)
+ }
+
+ // Authorize the clique consensus (if chosen) to sign using wallet signer
+ var cli *clique.Clique
+ if c, ok := srv.backend.Engine().(*clique.Clique); ok {
+ cli = c
+ } else if cl, ok := srv.backend.Engine().(*beacon.Beacon); ok {
+ if c, ok := cl.InnerEngine().(*clique.Clique); ok {
+ cli = c
+ }
+ }
+ if cli != nil {
+ wallet, err := accountManager.Find(accounts.Account{Address: eb})
+ if wallet == nil || err != nil {
+ log.Error("Etherbase account unavailable locally", "err", err)
+
+ return nil, fmt.Errorf("signer missing: %v", err)
+ }
+
+ cli.Authorize(eb, wallet.SignData)
+ authorized = true
+ }
+
+ // Authorize the bor consensus (if chosen) to sign using wallet signer
+ if bor, ok := srv.backend.Engine().(*bor.Bor); ok {
+ wallet, err := accountManager.Find(accounts.Account{Address: eb})
+ if wallet == nil || err != nil {
+ log.Error("Etherbase account unavailable locally", "err", err)
+ return nil, fmt.Errorf("signer missing: %v", err)
+ }
+
+ bor.Authorize(eb, wallet.SignData)
+ authorized = true
+ }
+ }
}
- // register the ethereum backend
- ethCfg, err := config.buildEth(stack)
- if err != nil {
- return nil, err
- }
-
- backend, err := eth.New(stack, ethCfg)
- if err != nil {
- return nil, err
- }
- srv.backend = backend
+ // set the auth status in backend
+ srv.backend.SetAuthorized(authorized)
// debug tracing is enabled by default
- stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
+ stack.RegisterAPIs(tracers.APIs(srv.backend.APIBackend))
+ srv.tracerAPI = tracers.NewAPI(srv.backend.APIBackend)
// graphql is started from another place
if config.JsonRPC.Graphql.Enabled {
- if err := graphql.New(stack, backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.VHost); err != nil {
+ if err := graphql.New(stack, srv.backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.VHost); err != nil {
return nil, fmt.Errorf("failed to register the GraphQL service: %v", err)
}
}
// register ethash service
if config.Ethstats != "" {
- if err := ethstats.New(stack, backend.APIBackend, backend.Engine(), config.Ethstats); err != nil {
+ if err := ethstats.New(stack, srv.backend.APIBackend, srv.backend.Engine(), config.Ethstats); err != nil {
return nil, err
}
}
// sealing (if enabled) or in dev mode
if config.Sealer.Enabled || config.Developer.Enabled {
- if err := backend.StartMining(1); err != nil {
+ if err := srv.backend.StartMining(1); err != nil {
return nil, err
}
}
@@ -119,15 +205,20 @@ func NewServer(config *Config) (*Server, error) {
return nil, err
}
+ // Set the node instance
+ srv.node = stack
+
// start the node
if err := srv.node.Start(); err != nil {
return nil, err
}
+
return srv, nil
}
func (s *Server) Stop() {
s.node.Close()
+ s.grpcServer.Stop()
// shutdown the tracer
if s.tracer != nil {
@@ -160,10 +251,12 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error
if v1Enabled {
log.Info("Enabling metrics export to InfluxDB (v1)")
+
go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, cfg.Database, cfg.Username, cfg.Password, "geth.", tags)
}
if v2Enabled {
log.Info("Enabling metrics export to InfluxDB (v2)")
+
go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, cfg.Token, cfg.Bucket, cfg.Organization, "geth.", tags)
}
}
@@ -175,9 +268,7 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error
prometheusMux := http.NewServeMux()
- prometheusMux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
- prometheus.Handler(metrics.DefaultRegistry)
- })
+ prometheusMux.Handle("/debug/metrics/prometheus", prometheus.Handler(metrics.DefaultRegistry))
promServer := &http.Server{
Addr: config.PrometheusAddr,
@@ -252,6 +343,7 @@ func (s *Server) setupGRPCServer(addr string) error {
}()
log.Info("GRPC Server started", "addr", addr)
+
return nil
}
@@ -262,16 +354,20 @@ func (s *Server) withLoggingUnaryInterceptor() grpc.ServerOption {
func (s *Server) loggingServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
start := time.Now()
h, err := handler(ctx, req)
+
log.Trace("Request", "method", info.FullMethod, "duration", time.Since(start), "error", err)
+
return h, err
}
func setupLogger(logLevel string) {
output := io.Writer(os.Stderr)
+
usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
if usecolor {
output = colorable.NewColorableStderr()
}
+
ostream := log.StreamHandler(output, log.TerminalFormat(usecolor))
glogger := log.NewGlogHandler(ostream)
@@ -282,5 +378,14 @@ func setupLogger(logLevel string) {
} else {
glogger.Verbosity(log.LvlInfo)
}
+
log.Root().SetHandler(glogger)
}
+
+func (s *Server) GetLatestBlockNumber() *big.Int {
+ return s.backend.BlockChain().CurrentBlock().Number()
+}
+
+func (s *Server) GetGrpcAddr() string {
+ return s.config.GRPC.Addr[1:]
+}
diff --git a/internal/cli/server/server_test.go b/internal/cli/server/server_test.go
index 070739c687..c88c656b10 100644
--- a/internal/cli/server/server_test.go
+++ b/internal/cli/server/server_test.go
@@ -1,13 +1,37 @@
package server
import (
+ "fmt"
+ "net"
+ "sync/atomic"
"testing"
"time"
+ "github.com/ethereum/go-ethereum/log"
+
"github.com/stretchr/testify/assert"
)
+var initialPort uint64 = 61000
+
+// nextPort gives the next available port starting from 60000
+func nextPort() uint64 {
+ log.Info("Checking for new port", "current", initialPort)
+ port := atomic.AddUint64(&initialPort, 1)
+ addr := fmt.Sprintf("localhost:%d", port)
+
+ lis, err := net.Listen("tcp", addr)
+ if err == nil {
+ lis.Close()
+
+ return port
+ } else {
+ return nextPort()
+ }
+}
+
func TestServer_DeveloperMode(t *testing.T) {
+ t.Parallel()
// get the default config
config := DefaultConfig()
@@ -16,17 +40,17 @@ func TestServer_DeveloperMode(t *testing.T) {
config.Developer.Enabled = true
config.Developer.Period = 2 // block time
- // start the server
- server, err1 := NewServer(config)
- if err1 != nil {
- t.Fatalf("failed to start server: %v", err1)
- }
+ // start the mock server
+ server, err := CreateMockServer(config)
+ assert.NoError(t, err)
+
+ defer CloseMockServer(server)
// record the initial block number
blockNumber := server.backend.BlockChain().CurrentBlock().Header().Number.Int64()
var i int64 = 0
- for i = 0; i < 10; i++ {
+ for i = 0; i < 3; i++ {
// We expect the node to mine blocks every `config.Developer.Period` time period
time.Sleep(time.Duration(config.Developer.Period) * time.Second)
currBlock := server.backend.BlockChain().CurrentBlock().Header().Number.Int64()
@@ -35,7 +59,4 @@ func TestServer_DeveloperMode(t *testing.T) {
break
}
}
-
- // stop the server
- server.Stop()
}
diff --git a/internal/cli/server/service.go b/internal/cli/server/service.go
index e8e3928581..de240d5461 100644
--- a/internal/cli/server/service.go
+++ b/internal/cli/server/service.go
@@ -2,46 +2,34 @@ package server
import (
"context"
+ "encoding/json"
"fmt"
"math/big"
"reflect"
"strings"
+ gproto "github.com/golang/protobuf/proto" //nolint:staticcheck,typecheck
+ "github.com/golang/protobuf/ptypes/empty"
+ grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
+
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/internal/cli/server/pprof"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
- gproto "github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/ptypes/empty"
- grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
)
-func (s *Server) Pprof(req *proto.PprofRequest, stream proto.Bor_PprofServer) error {
- var payload []byte
- var headers map[string]string
- var err error
-
- ctx := context.Background()
- switch req.Type {
- case proto.PprofRequest_CPU:
- payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds))
- case proto.PprofRequest_TRACE:
- payload, headers, err = pprof.Trace(ctx, int(req.Seconds))
- case proto.PprofRequest_LOOKUP:
- payload, headers, err = pprof.Profile(req.Profile, 0, 0)
- }
- if err != nil {
- return err
- }
+const chunkSize = 1024 * 1024 * 1024
+func sendStreamDebugFile(stream proto.Bor_DebugPprofServer, headers map[string]string, data []byte) error {
// open the stream and send the headers
- err = stream.Send(&proto.PprofResponse{
- Event: &proto.PprofResponse_Open_{
- Open: &proto.PprofResponse_Open{
+ err := stream.Send(&proto.DebugFileResponse{
+ Event: &proto.DebugFileResponse_Open_{
+ Open: &proto.DebugFileResponse_Open{
Headers: headers,
- Size: int64(len(payload)),
},
},
})
@@ -50,24 +38,57 @@ func (s *Server) Pprof(req *proto.PprofRequest, stream proto.Bor_PprofServer) er
}
// Wrap our conn around the response.
+ encoder := grpc_net_conn.SimpleEncoder(func(msg gproto.Message) *[]byte {
+ return &msg.(*proto.DebugFileResponse_Input).Data
+ })
conn := &grpc_net_conn.Conn{
Stream: stream,
- Request: &proto.PprofResponse_Input{},
- Encode: grpc_net_conn.SimpleEncoder(func(msg gproto.Message) *[]byte {
- return &msg.(*proto.PprofResponse_Input).Data
- }),
+ Request: &proto.DebugFileResponse_Input{},
+ Encode: grpc_net_conn.ChunkedEncoder(encoder, chunkSize),
}
- if _, err := conn.Write(payload); err != nil {
+
+ if _, err := conn.Write(data); err != nil {
return err
}
// send the eof
- err = stream.Send(&proto.PprofResponse{
- Event: &proto.PprofResponse_Eof{},
+ err = stream.Send(&proto.DebugFileResponse{
+ Event: &proto.DebugFileResponse_Eof{},
})
if err != nil {
return err
}
+
+ return nil
+}
+
+func (s *Server) DebugPprof(req *proto.DebugPprofRequest, stream proto.Bor_DebugPprofServer) error {
+ var (
+ payload []byte
+ headers map[string]string
+ err error
+ )
+
+ ctx := context.Background()
+
+ switch req.Type {
+ case proto.DebugPprofRequest_CPU:
+ payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds))
+ case proto.DebugPprofRequest_TRACE:
+ payload, headers, err = pprof.Trace(ctx, int(req.Seconds))
+ case proto.DebugPprofRequest_LOOKUP:
+ payload, headers, err = pprof.Profile(req.Profile, 0, 0)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ // send the file on a grpc stream
+ if err := sendStreamDebugFile(stream, headers, payload); err != nil {
+ return err
+ }
+
return nil
}
@@ -169,6 +190,34 @@ func headerToProtoHeader(h *types.Header) *proto.Header {
}
}
+func (s *Server) DebugBlock(req *proto.DebugBlockRequest, stream proto.Bor_DebugBlockServer) error {
+ traceReq := &tracers.TraceBlockRequest{
+ Number: req.Number,
+ Config: &tracers.TraceConfig{
+ Config: &logger.Config{
+ EnableMemory: true,
+ },
+ },
+ }
+
+ res, err := s.tracerAPI.TraceBorBlock(traceReq)
+ if err != nil {
+ return err
+ }
+
+ // this is memory heavy
+ data, err := json.Marshal(res)
+ if err != nil {
+ return err
+ }
+
+ if err := sendStreamDebugFile(stream, map[string]string{}, data); err != nil {
+ return err
+ }
+
+ return nil
+}
+
var bigIntT = reflect.TypeOf(new(big.Int)).Kind()
// gatherForks gathers all the fork numbers via reflection
diff --git a/internal/cli/server/testdata/password.txt b/internal/cli/server/testdata/password.txt
new file mode 100644
index 0000000000..1827ffa521
--- /dev/null
+++ b/internal/cli/server/testdata/password.txt
@@ -0,0 +1,2 @@
+test1
+test2
\ No newline at end of file
diff --git a/internal/cli/server/testdata/simple.hcl b/internal/cli/server/testdata/simple.hcl
index e276960e6d..5afc091859 100644
--- a/internal/cli/server/testdata/simple.hcl
+++ b/internal/cli/server/testdata/simple.hcl
@@ -1,6 +1,6 @@
data-dir = "./data"
-whitelist = {
+requiredblocks = {
a = "b"
}
diff --git a/internal/cli/server/testdata/simple.json b/internal/cli/server/testdata/simple.json
index 277f05d105..6270ee6d13 100644
--- a/internal/cli/server/testdata/simple.json
+++ b/internal/cli/server/testdata/simple.json
@@ -1,6 +1,6 @@
{
"data-dir": "./data",
- "whitelist": {
+ "requiredblocks": {
"a": "b"
},
"p2p": {
diff --git a/internal/cli/status.go b/internal/cli/status.go
index ef0a42172b..2a8b7d7470 100644
--- a/internal/cli/status.go
+++ b/internal/cli/status.go
@@ -6,6 +6,7 @@ import (
"strings"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
+
"github.com/golang/protobuf/ptypes/empty"
)
@@ -14,6 +15,16 @@ type StatusCommand struct {
*Meta2
}
+// MarkDown implements cli.MarkDown interface
+func (p *StatusCommand) MarkDown() string {
+ items := []string{
+ "# Status",
+ "The ```status``` command outputs the status of the client.",
+ }
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (p *StatusCommand) Help() string {
return `Usage: bor status
@@ -47,6 +58,7 @@ func (c *StatusCommand) Run(args []string) int {
}
c.UI.Output(printStatus(status))
+
return 0
}
@@ -60,6 +72,7 @@ func printStatus(status *proto.StatusResponse) string {
forks := make([]string, len(status.Forks)+1)
forks[0] = "Name|Block|Enabled"
+
for i, d := range status.Forks {
forks[i+1] = fmt.Sprintf("%s|%d|%v", d.Name, d.Block, !d.Disabled)
}
@@ -83,5 +96,6 @@ func printStatus(status *proto.StatusResponse) string {
"\nForks",
formatList(forks),
}
+
return strings.Join(full, "\n")
}
diff --git a/internal/cli/version.go b/internal/cli/version.go
index 7433f208b2..cd155f43a7 100644
--- a/internal/cli/version.go
+++ b/internal/cli/version.go
@@ -1,7 +1,10 @@
package cli
import (
+ "strings"
+
"github.com/ethereum/go-ethereum/params"
+
"github.com/mitchellh/cli"
)
@@ -10,6 +13,25 @@ type VersionCommand struct {
UI cli.Ui
}
+// MarkDown implements cli.MarkDown interface
+func (d *VersionCommand) MarkDown() string {
+ examples := []string{
+ "## Usage",
+ CodeBlock([]string{
+ "$ bor version",
+ "0.2.9-stable",
+ }),
+ }
+
+ items := []string{
+ "# Version",
+ "The ```bor version``` command outputs the version of the binary.",
+ }
+ items = append(items, examples...)
+
+ return strings.Join(items, "\n\n")
+}
+
// Help implements the cli.Command interface
func (c *VersionCommand) Help() string {
return `Usage: bor version
diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go
index 2c3520a885..aa2596fe81 100644
--- a/internal/ethapi/transaction_args.go
+++ b/internal/ethapi/transaction_args.go
@@ -59,6 +59,7 @@ func (args *TransactionArgs) from() common.Address {
if args.From == nil {
return common.Address{}
}
+
return *args.From
}
@@ -67,9 +68,11 @@ func (args *TransactionArgs) data() []byte {
if args.Input != nil {
return *args.Input
}
+
if args.Data != nil {
return *args.Data
}
+
return nil
}
@@ -78,8 +81,10 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
+
// After london, default to 1559 unless gasPrice is set
head := b.CurrentHeader()
+
// If user specifies both maxPriorityfee and maxFee, then we do not
// need to consult the chain for defaults. It's definitely a London tx.
if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil {
@@ -90,6 +95,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
if err != nil {
return err
}
+
args.MaxPriorityFeePerGas = (*hexutil.Big)(tip)
}
if args.MaxFeePerGas == nil {
@@ -97,8 +103,10 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
(*big.Int)(args.MaxPriorityFeePerGas),
new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
)
+
args.MaxFeePerGas = (*hexutil.Big)(gasFeeCap)
}
+
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
}
@@ -106,17 +114,20 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil {
return errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet")
}
+
if args.GasPrice == nil {
price, err := b.SuggestGasTipCap(ctx)
if err != nil {
return err
}
+
if b.ChainConfig().IsLondon(head.Number) {
// The legacy tx gas price suggestion should not add 2x base fee
// because all fees are consumed, so it would result in a spiral
// upwards.
price.Add(price, head.BaseFee)
}
+
args.GasPrice = (*hexutil.Big)(price)
}
}
@@ -126,22 +137,28 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
}
}
+
if args.Value == nil {
args.Value = new(hexutil.Big)
}
+
if args.Nonce == nil {
nonce, err := b.GetPoolNonce(ctx, args.from())
if err != nil {
return err
}
+
args.Nonce = (*hexutil.Uint64)(&nonce)
}
+
if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) {
return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`)
}
+
if args.To == nil && len(args.data()) == 0 {
return errors.New(`contract creation without any data provided`)
}
+
// Estimate the gas usage if necessary.
if args.Gas == nil {
// These fields are immutable during the estimation, safe to
@@ -157,18 +174,23 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
Data: (*hexutil.Bytes)(&data),
AccessList: args.AccessList,
}
+
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
+
estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, b.RPCGasCap())
if err != nil {
return err
}
+
args.Gas = &estimated
log.Trace("Estimate gas usage automatically", "gas", args.Gas)
}
+
if args.ChainID == nil {
id := (*hexutil.Big)(b.ChainConfig().ChainID)
args.ChainID = id
}
+
return nil
}
@@ -180,6 +202,7 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return types.Message{}, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
+
// Set sender address or use zero address if none specified.
addr := args.from()
@@ -191,24 +214,29 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
if gas == 0 {
gas = uint64(math.MaxUint64 / 2)
}
+
if args.Gas != nil && *args.Gas != systemCallGas {
gas = uint64(*args.Gas)
}
+
if globalGasCap != 0 && globalGasCap < gas {
log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap)
gas = globalGasCap
}
+
var (
gasPrice *big.Int
gasFeeCap *big.Int
gasTipCap *big.Int
)
+
if baseFee == nil {
// If there's no basefee, then it must be a non-1559 execution
gasPrice = new(big.Int)
if args.GasPrice != nil {
gasPrice = args.GasPrice.ToInt()
}
+
gasFeeCap, gasTipCap = gasPrice, gasPrice
} else {
// A basefee is provided, necessitating 1559-type execution
@@ -219,30 +247,40 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
} else {
// User specified 1559 gas feilds (or none), use those
gasFeeCap = new(big.Int)
+
if args.MaxFeePerGas != nil {
gasFeeCap = args.MaxFeePerGas.ToInt()
}
+
gasTipCap = new(big.Int)
+
if args.MaxPriorityFeePerGas != nil {
gasTipCap = args.MaxPriorityFeePerGas.ToInt()
}
+
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
gasPrice = new(big.Int)
+
if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 {
gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
}
}
}
+
value := new(big.Int)
if args.Value != nil {
value = args.Value.ToInt()
}
+
data := args.data()
+
var accessList types.AccessList
if args.AccessList != nil {
accessList = *args.AccessList
}
+
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true)
+
return msg, nil
}
@@ -250,6 +288,7 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
// This assumes that setDefaults has been called.
func (args *TransactionArgs) toTransaction() *types.Transaction {
var data types.TxData
+
switch {
case args.MaxFeePerGas != nil:
al := types.AccessList{}
@@ -288,6 +327,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
Data: args.data(),
}
}
+
return types.NewTx(data)
}
diff --git a/internal/web3ext/bor_ext.go b/internal/web3ext/bor_ext.go
index b7fe9b4886..fe8b01da19 100644
--- a/internal/web3ext/bor_ext.go
+++ b/internal/web3ext/bor_ext.go
@@ -17,6 +17,18 @@ web3._extend({
params: 1,
inputFormatter: [null]
}),
+ new web3._extend.Method({
+ name: 'getSnapshotProposer',
+ call: 'bor_getSnapshotProposer',
+ params: 1,
+ inputFormatter: [null]
+ }),
+ new web3._extend.Method({
+ name: 'getSnapshotProposerSequence',
+ call: 'bor_getSnapshotProposerSequence',
+ params: 1,
+ inputFormatter: [null]
+ }),
new web3._extend.Method({
name: 'getSnapshotAtHash',
call: 'bor_getSnapshotAtHash',
diff --git a/metrics/sample_test.go b/metrics/sample_test.go
index c9168d3e82..d675862e84 100644
--- a/metrics/sample_test.go
+++ b/metrics/sample_test.go
@@ -244,6 +244,7 @@ func TestUniformSampleIncludesTail(t *testing.T) {
}
func TestUniformSampleSnapshot(t *testing.T) {
+ rand.Seed(1)
s := NewUniformSample(100)
for i := 1; i <= 10000; i++ {
s.Update(int64(i))
@@ -339,6 +340,9 @@ func TestUniformSampleConcurrentUpdateCount(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode")
}
+
+ rand.Seed(1)
+
s := NewUniformSample(100)
for i := 0; i < 100; i++ {
s.Update(int64(i))
diff --git a/miner/fake_miner.go b/miner/fake_miner.go
new file mode 100644
index 0000000000..cbe0d9f54c
--- /dev/null
+++ b/miner/fake_miner.go
@@ -0,0 +1,233 @@
+package miner
+
+import (
+ "errors"
+ "math/big"
+ "testing"
+ "time"
+
+ "github.com/golang/mock/gomock"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/bor"
+ "github.com/ethereum/go-ethereum/consensus/bor/api"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/ethdb/memorydb"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/tests/bor/mocks"
+ "github.com/ethereum/go-ethereum/trie"
+)
+
+type DefaultBorMiner struct {
+ Miner *Miner
+ Mux *event.TypeMux //nolint:staticcheck
+ Cleanup func(skipMiner bool)
+
+ Ctrl *gomock.Controller
+ EthAPIMock api.Caller
+ HeimdallClientMock bor.IHeimdallClient
+ ContractMock bor.GenesisContract
+}
+
+func NewBorDefaultMiner(t *testing.T) *DefaultBorMiner {
+ t.Helper()
+
+ ctrl := gomock.NewController(t)
+
+ ethAPI := api.NewMockCaller(ctrl)
+ ethAPI.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+
+ spanner := bor.NewMockSpanner(ctrl)
+ spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{
+ {
+ ID: 0,
+ Address: common.Address{0x1},
+ VotingPower: 100,
+ ProposerPriority: 0,
+ },
+ }, nil).AnyTimes()
+
+ heimdallClient := mocks.NewMockIHeimdallClient(ctrl)
+ heimdallClient.EXPECT().Close().Times(1)
+
+ genesisContracts := bor.NewMockGenesisContract(ctrl)
+
+ miner, mux, cleanup := createBorMiner(t, ethAPI, spanner, heimdallClient, genesisContracts)
+
+ return &DefaultBorMiner{
+ Miner: miner,
+ Mux: mux,
+ Cleanup: cleanup,
+ Ctrl: ctrl,
+ EthAPIMock: ethAPI,
+ HeimdallClientMock: heimdallClient,
+ ContractMock: genesisContracts,
+ }
+}
+
+//nolint:staticcheck
+func createBorMiner(t *testing.T, ethAPIMock api.Caller, spanner bor.Spanner, heimdallClientMock bor.IHeimdallClient, contractMock bor.GenesisContract) (*Miner, *event.TypeMux, func(skipMiner bool)) {
+ t.Helper()
+
+ // Create Ethash config
+ chainDB, _, chainConfig := NewDBForFakes(t)
+
+ engine := NewFakeBor(t, chainDB, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock)
+
+ // Create Ethereum backend
+ bc, err := core.NewBlockChain(chainDB, nil, chainConfig, engine, vm.Config{}, nil, nil)
+ if err != nil {
+ t.Fatalf("can't create new chain %v", err)
+ }
+
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil)
+ blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)}
+
+ pool := core.NewTxPool(testTxPoolConfig, chainConfig, blockchain)
+ backend := NewMockBackend(bc, pool)
+
+ // Create event Mux
+ mux := new(event.TypeMux)
+
+ config := Config{
+ Etherbase: common.HexToAddress("123456789"),
+ }
+
+ // Create Miner
+ miner := New(backend, &config, chainConfig, mux, engine, nil)
+
+ cleanup := func(skipMiner bool) {
+ bc.Stop()
+ engine.Close()
+ pool.Stop()
+
+ if !skipMiner {
+ miner.Close()
+ }
+ }
+
+ return miner, mux, cleanup
+}
+
+func NewDBForFakes(t *testing.T) (ethdb.Database, *core.Genesis, *params.ChainConfig) {
+ t.Helper()
+
+ memdb := memorydb.New()
+ chainDB := rawdb.NewDatabase(memdb)
+ genesis := core.DeveloperGenesisBlock(2, 11_500_000, common.HexToAddress("12345"))
+
+ chainConfig, _, err := core.SetupGenesisBlock(chainDB, genesis)
+ if err != nil {
+ t.Fatalf("can't create new chain config: %v", err)
+ }
+
+ chainConfig.Bor.Period = map[string]uint64{
+ "0": 1,
+ }
+
+ return chainDB, genesis, chainConfig
+}
+
+func NewFakeBor(t *testing.T, chainDB ethdb.Database, chainConfig *params.ChainConfig, ethAPIMock api.Caller, spanner bor.Spanner, heimdallClientMock bor.IHeimdallClient, contractMock bor.GenesisContract) consensus.Engine {
+ t.Helper()
+
+ if chainConfig.Bor == nil {
+ chainConfig.Bor = params.BorUnittestChainConfig.Bor
+ }
+
+ return bor.New(chainConfig, chainDB, ethAPIMock, spanner, heimdallClientMock, contractMock)
+}
+
+type mockBackend struct {
+ bc *core.BlockChain
+ txPool *core.TxPool
+}
+
+func NewMockBackend(bc *core.BlockChain, txPool *core.TxPool) *mockBackend {
+ return &mockBackend{
+ bc: bc,
+ txPool: txPool,
+ }
+}
+
+func (m *mockBackend) BlockChain() *core.BlockChain {
+ return m.bc
+}
+
+func (m *mockBackend) TxPool() *core.TxPool {
+ return m.txPool
+}
+
+func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) {
+ return nil, errors.New("not supported")
+}
+
+type testBlockChain struct {
+ statedb *state.StateDB
+ gasLimit uint64
+ chainHeadFeed *event.Feed
+}
+
+func (bc *testBlockChain) CurrentBlock() *types.Block {
+ return types.NewBlock(&types.Header{
+ GasLimit: bc.gasLimit,
+ }, nil, nil, nil, trie.NewStackTrie(nil))
+}
+
+func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
+ return bc.CurrentBlock()
+}
+
+func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
+ return bc.statedb, nil
+}
+
+func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
+ return bc.chainHeadFeed.Subscribe(ch)
+}
+
+var (
+ // Test chain configurations
+ testTxPoolConfig core.TxPoolConfig
+ ethashChainConfig *params.ChainConfig
+ cliqueChainConfig *params.ChainConfig
+
+ // Test accounts
+ testBankKey, _ = crypto.GenerateKey()
+ testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
+ testBankFunds = big.NewInt(1000000000000000000)
+
+ testUserKey, _ = crypto.GenerateKey()
+ testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey)
+
+ // Test transactions
+ pendingTxs []*types.Transaction
+ newTxs []*types.Transaction
+
+ testConfig = &Config{
+ Recommit: time.Second,
+ GasCeil: params.GenesisGasLimit,
+ }
+)
+
+func init() {
+ testTxPoolConfig = core.DefaultTxPoolConfig
+ testTxPoolConfig.Journal = ""
+ ethashChainConfig = new(params.ChainConfig)
+ *ethashChainConfig = *params.TestChainConfig
+ cliqueChainConfig = new(params.ChainConfig)
+ *cliqueChainConfig = *params.TestChainConfig
+ cliqueChainConfig.Clique = ¶ms.CliqueConfig{
+ Period: 10,
+ Epoch: 30000,
+ }
+}
diff --git a/miner/miner_test.go b/miner/miner_test.go
index 03c79cbbd5..76f61fd0d4 100644
--- a/miner/miner_test.go
+++ b/miner/miner_test.go
@@ -18,80 +18,32 @@
package miner
import (
- "errors"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/consensus"
- "github.com/ethereum/go-ethereum/consensus/clique"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
- "github.com/ethereum/go-ethereum/ethdb/memorydb"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/trie"
)
-type mockBackend struct {
- bc *core.BlockChain
- txPool *core.TxPool
-}
-
-func NewMockBackend(bc *core.BlockChain, txPool *core.TxPool) *mockBackend {
- return &mockBackend{
- bc: bc,
- txPool: txPool,
- }
-}
-
-func (m *mockBackend) BlockChain() *core.BlockChain {
- return m.bc
-}
-
-func (m *mockBackend) TxPool() *core.TxPool {
- return m.txPool
-}
-
-func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) {
- return nil, errors.New("not supported")
-}
-
-type testBlockChain struct {
- statedb *state.StateDB
- gasLimit uint64
- chainHeadFeed *event.Feed
-}
-
-func (bc *testBlockChain) CurrentBlock() *types.Block {
- return types.NewBlock(&types.Header{
- GasLimit: bc.gasLimit,
- }, nil, nil, nil, trie.NewStackTrie(nil))
-}
-
-func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
- return bc.CurrentBlock()
-}
-
-func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
- return bc.statedb, nil
-}
-
-func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
- return bc.chainHeadFeed.Subscribe(ch)
-}
-
func TestMiner(t *testing.T) {
- miner, mux, cleanup := createMiner(t)
- defer cleanup(false)
+ t.Parallel()
+
+ minerBor := NewBorDefaultMiner(t)
+ defer func() {
+ minerBor.Cleanup(false)
+ minerBor.Ctrl.Finish()
+ }()
+
+ miner := minerBor.Miner
+ mux := minerBor.Mux
+
miner.Start(common.HexToAddress("0x12345"))
waitForMiningState(t, miner, true)
+
// Start the downloader
mux.Post(downloader.StartEvent{})
waitForMiningState(t, miner, false)
+
// Stop the downloader and wait for the update loop to run
mux.Post(downloader.DoneEvent{})
waitForMiningState(t, miner, true)
@@ -113,10 +65,20 @@ func TestMiner(t *testing.T) {
// An initial FailedEvent should allow mining to stop on a subsequent
// downloader StartEvent.
func TestMinerDownloaderFirstFails(t *testing.T) {
- miner, mux, cleanup := createMiner(t)
- defer cleanup(false)
+ t.Parallel()
+
+ minerBor := NewBorDefaultMiner(t)
+ defer func() {
+ minerBor.Cleanup(false)
+ minerBor.Ctrl.Finish()
+ }()
+
+ miner := minerBor.Miner
+ mux := minerBor.Mux
+
miner.Start(common.HexToAddress("0x12345"))
waitForMiningState(t, miner, true)
+
// Start the downloader
mux.Post(downloader.StartEvent{})
waitForMiningState(t, miner, false)
@@ -145,10 +107,20 @@ func TestMinerDownloaderFirstFails(t *testing.T) {
}
func TestMinerStartStopAfterDownloaderEvents(t *testing.T) {
- miner, mux, cleanup := createMiner(t)
- defer cleanup(false)
+ t.Parallel()
+
+ minerBor := NewBorDefaultMiner(t)
+ defer func() {
+ minerBor.Cleanup(false)
+ minerBor.Ctrl.Finish()
+ }()
+
+ miner := minerBor.Miner
+ mux := minerBor.Mux
+
miner.Start(common.HexToAddress("0x12345"))
waitForMiningState(t, miner, true)
+
// Start the downloader
mux.Post(downloader.StartEvent{})
waitForMiningState(t, miner, false)
@@ -168,58 +140,104 @@ func TestMinerStartStopAfterDownloaderEvents(t *testing.T) {
}
func TestStartWhileDownload(t *testing.T) {
- miner, mux, cleanup := createMiner(t)
- defer cleanup(false)
+ t.Parallel()
+
+ minerBor := NewBorDefaultMiner(t)
+ defer func() {
+ minerBor.Cleanup(false)
+ minerBor.Ctrl.Finish()
+ }()
+
+ miner := minerBor.Miner
+ mux := minerBor.Mux
+
waitForMiningState(t, miner, false)
miner.Start(common.HexToAddress("0x12345"))
waitForMiningState(t, miner, true)
+
// Stop the downloader and wait for the update loop to run
mux.Post(downloader.StartEvent{})
waitForMiningState(t, miner, false)
+
// Starting the miner after the downloader should not work
miner.Start(common.HexToAddress("0x12345"))
waitForMiningState(t, miner, false)
}
func TestStartStopMiner(t *testing.T) {
- miner, _, cleanup := createMiner(t)
- defer cleanup(false)
+ t.Parallel()
+
+ minerBor := NewBorDefaultMiner(t)
+ defer func() {
+ minerBor.Cleanup(false)
+ minerBor.Ctrl.Finish()
+ }()
+
+ miner := minerBor.Miner
+
waitForMiningState(t, miner, false)
miner.Start(common.HexToAddress("0x12345"))
- waitForMiningState(t, miner, true)
- miner.Stop()
- waitForMiningState(t, miner, false)
+ waitForMiningState(t, miner, true)
+
+ miner.Stop()
+
+ waitForMiningState(t, miner, false)
}
func TestCloseMiner(t *testing.T) {
- miner, _, cleanup := createMiner(t)
- defer cleanup(true)
+ t.Parallel()
+
+ minerBor := NewBorDefaultMiner(t)
+ defer func() {
+ minerBor.Cleanup(true)
+ minerBor.Ctrl.Finish()
+ }()
+
+ miner := minerBor.Miner
+
waitForMiningState(t, miner, false)
+
miner.Start(common.HexToAddress("0x12345"))
+
waitForMiningState(t, miner, true)
+
// Terminate the miner and wait for the update loop to run
miner.Close()
+
waitForMiningState(t, miner, false)
}
// TestMinerSetEtherbase checks that etherbase becomes set even if mining isn't
// possible at the moment
func TestMinerSetEtherbase(t *testing.T) {
- miner, mux, cleanup := createMiner(t)
- defer cleanup(false)
+ t.Parallel()
+
+ minerBor := NewBorDefaultMiner(t)
+ defer func() {
+ minerBor.Cleanup(false)
+ minerBor.Ctrl.Finish()
+ }()
+
+ miner := minerBor.Miner
+ mux := minerBor.Mux
+
// Start with a 'bad' mining address
miner.Start(common.HexToAddress("0xdead"))
waitForMiningState(t, miner, true)
+
// Start the downloader
mux.Post(downloader.StartEvent{})
waitForMiningState(t, miner, false)
+
// Now user tries to configure proper mining address
miner.Start(common.HexToAddress("0x1337"))
+
// Stop the downloader and wait for the update loop to run
mux.Post(downloader.DoneEvent{})
waitForMiningState(t, miner, true)
+
// The miner should now be using the good address
if got, exp := miner.coinbase, common.HexToAddress("0x1337"); got != exp {
t.Fatalf("Wrong coinbase, got %x expected %x", got, exp)
@@ -239,46 +257,6 @@ func waitForMiningState(t *testing.T, m *Miner, mining bool) {
return
}
}
+
t.Fatalf("Mining() == %t, want %t", state, mining)
}
-
-func createMiner(t *testing.T) (*Miner, *event.TypeMux, func(skipMiner bool)) {
- // Create Ethash config
- config := Config{
- Etherbase: common.HexToAddress("123456789"),
- }
- // Create chainConfig
- memdb := memorydb.New()
- chainDB := rawdb.NewDatabase(memdb)
- genesis := core.DeveloperGenesisBlock(15, 11_500_000, common.HexToAddress("12345"))
- chainConfig, _, err := core.SetupGenesisBlock(chainDB, genesis)
- if err != nil {
- t.Fatalf("can't create new chain config: %v", err)
- }
- // Create consensus engine
- engine := clique.New(chainConfig.Clique, chainDB)
- // Create Ethereum backend
- consensus.NewMerger(rawdb.NewMemoryDatabase())
- bc, err := core.NewBlockChain(chainDB, nil, chainConfig, engine, vm.Config{}, nil, nil)
- if err != nil {
- t.Fatalf("can't create new chain %v", err)
- }
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil)
- blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)}
-
- pool := core.NewTxPool(testTxPoolConfig, chainConfig, blockchain)
- backend := NewMockBackend(bc, pool)
- // Create event Mux
- mux := new(event.TypeMux)
- // Create Miner
- miner := New(backend, &config, chainConfig, mux, engine, nil)
- cleanup := func(skipMiner bool) {
- bc.Stop()
- engine.Close()
- pool.Stop()
- if !skipMiner {
- miner.Close()
- }
- }
- return miner, mux, cleanup
-}
diff --git a/miner/unconfirmed_test.go b/miner/unconfirmed_test.go
index dc83cb9265..70d3325506 100644
--- a/miner/unconfirmed_test.go
+++ b/miner/unconfirmed_test.go
@@ -44,6 +44,7 @@ func TestUnconfirmedInsertBounds(t *testing.T) {
for i := 0; i < int(depth); i++ {
pool.Insert(depth, [32]byte{byte(depth), byte(i)})
}
+
// Validate that no blocks below the depth allowance are left in
pool.blocks.Do(func(block interface{}) {
if block := block.(*unconfirmedBlock); block.index+uint64(limit) <= depth {
@@ -64,23 +65,29 @@ func TestUnconfirmedShifts(t *testing.T) {
for depth := start; depth < start+uint64(limit); depth++ {
pool.Insert(depth, [32]byte{byte(depth)})
}
+
// Try to shift below the limit and ensure no blocks are dropped
pool.Shift(start + uint64(limit) - 1)
if n := pool.blocks.Len(); n != int(limit) {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, limit)
}
+
// Try to shift half the blocks out and verify remainder
pool.Shift(start + uint64(limit) - 1 + uint64(limit/2))
if n := pool.blocks.Len(); n != int(limit)/2 {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, limit/2)
}
+
// Try to shift all the remaining blocks out and verify emptyness
pool.Shift(start + 2*uint64(limit))
+
if n := pool.blocks.Len(); n != 0 {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, 0)
}
+
// Try to shift out from the empty set and make sure it doesn't break
pool.Shift(start + 3*uint64(limit))
+
if n := pool.blocks.Len(); n != 0 {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, 0)
}
diff --git a/miner/worker.go b/miner/worker.go
index 1da8a529d7..9fcb2140ca 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -25,6 +25,7 @@ import (
"time"
mapset "github.com/deckarep/golang-set"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
@@ -393,23 +394,27 @@ func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) t
// prevF = float64(prev.Nanoseconds())
// next float64
// )
+ //
// if inc {
// next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias)
// max := float64(maxRecommitInterval.Nanoseconds())
+ //
// if next > max {
// next = max
// }
// } else {
// next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target-intervalAdjustBias)
// min := float64(minRecommit.Nanoseconds())
+ //
// if next < min {
// next = min
// }
// }
+ //
// log.Info("Recalc Commit", "Prev", prev, "Next", next)
//returning the Same prev value to keep the recommit interval constant
- return time.Duration(int64(prev))
+ return prev
}
// newWorkLoop is a standalone goroutine to submit new sealing work upon received events.
diff --git a/miner/worker_test.go b/miner/worker_test.go
index 20dc3238da..6dae391c88 100644
--- a/miner/worker_test.go
+++ b/miner/worker_test.go
@@ -24,9 +24,14 @@ import (
"testing"
"time"
+ "github.com/golang/mock/gomock"
+
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/bor"
+ "github.com/ethereum/go-ethereum/consensus/bor/api"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
@@ -38,6 +43,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/tests/bor/mocks"
)
const (
@@ -49,43 +55,9 @@ const (
testGas = 144109
)
-var (
- // Test chain configurations
- testTxPoolConfig core.TxPoolConfig
- ethashChainConfig *params.ChainConfig
- cliqueChainConfig *params.ChainConfig
-
- // Test accounts
- testBankKey, _ = crypto.GenerateKey()
- testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
- testBankFunds = big.NewInt(1000000000000000000)
-
- testUserKey, _ = crypto.GenerateKey()
- testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey)
-
- // Test transactions
- pendingTxs []*types.Transaction
- newTxs []*types.Transaction
-
- testConfig = &Config{
- Recommit: time.Second,
- GasCeil: params.GenesisGasLimit,
- }
-)
-
func init() {
- testTxPoolConfig = core.DefaultTxPoolConfig
- testTxPoolConfig.Journal = ""
- ethashChainConfig = new(params.ChainConfig)
- *ethashChainConfig = *params.TestChainConfig
- cliqueChainConfig = new(params.ChainConfig)
- *cliqueChainConfig = *params.TestChainConfig
- cliqueChainConfig.Clique = ¶ms.CliqueConfig{
- Period: 10,
- Epoch: 30000,
- }
-
signer := types.LatestSigner(params.TestChainConfig)
+
tx1 := types.MustSignNewTx(testBankKey, signer, &types.AccessListTx{
ChainID: params.TestChainConfig.ChainID,
Nonce: 0,
@@ -94,6 +66,7 @@ func init() {
Gas: params.TxGas,
GasPrice: big.NewInt(params.InitialBaseFee),
})
+
pendingTxs = append(pendingTxs, tx1)
tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{
@@ -103,6 +76,7 @@ func init() {
Gas: params.TxGas,
GasPrice: big.NewInt(params.InitialBaseFee),
})
+
newTxs = append(newTxs, tx2)
rand.Seed(time.Now().UnixNano())
@@ -125,6 +99,12 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
}
switch e := engine.(type) {
+ case *bor.Bor:
+ gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength)
+ copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes())
+ e.Authorize(testBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) {
+ return crypto.Sign(crypto.Keccak256(data), testBankKey)
+ })
case *clique.Clique:
gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength)
copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes())
@@ -135,6 +115,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
default:
t.Fatalf("unexpected consensus engine type: %T", engine)
}
+
genesis := gspec.MustCommit(db)
chain, _ := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec.Config, engine, vm.Config{}, nil, nil)
@@ -149,10 +130,12 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
t.Fatalf("failed to insert origin chain: %v", err)
}
}
+
parent := genesis
if n > 0 {
parent = chain.GetBlockByHash(chain.CurrentBlock().ParentHash())
}
+
blocks, _ := core.GenerateChain(chainConfig, parent, engine, db, 1, func(i int, gen *core.BlockGen) {
gen.SetCoinbase(testUserAddress)
})
@@ -174,28 +157,36 @@ func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base
func (b *testWorkerBackend) newRandomUncle() *types.Block {
var parent *types.Block
+
cur := b.chain.CurrentBlock()
+
if cur.NumberU64() == 0 {
parent = b.chain.Genesis()
} else {
parent = b.chain.GetBlockByHash(b.chain.CurrentBlock().ParentHash())
}
+
blocks, _ := core.GenerateChain(b.chain.Config(), parent, b.chain.Engine(), b.db, 1, func(i int, gen *core.BlockGen) {
var addr = make([]byte, common.AddressLength)
+
rand.Read(addr)
gen.SetCoinbase(common.BytesToAddress(addr))
})
+
return blocks[0]
}
func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction {
var tx *types.Transaction
+
gasPrice := big.NewInt(10 * params.InitialBaseFee)
+
if creation {
tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(testBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(testCode)), types.HomesteadSigner{}, testBankKey)
} else {
tx, _ = types.SignTx(types.NewTransaction(b.txPool.Nonce(testBankAddress), testUserAddress, big.NewInt(1000), params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey)
}
+
return tx
}
@@ -204,39 +195,85 @@ func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consens
backend.txPool.AddLocals(pendingTxs)
w := newWorker(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false)
w.setEtherbase(testBankAddress)
+
return w, backend
}
func TestGenerateBlockAndImportEthash(t *testing.T) {
- testGenerateBlockAndImport(t, false)
+ t.Parallel()
+
+ testGenerateBlockAndImport(t, false, false)
}
func TestGenerateBlockAndImportClique(t *testing.T) {
- testGenerateBlockAndImport(t, true)
+ t.Parallel()
+
+ testGenerateBlockAndImport(t, true, false)
}
-func testGenerateBlockAndImport(t *testing.T, isClique bool) {
+func TestGenerateBlockAndImportBor(t *testing.T) {
+ t.Parallel()
+
+ testGenerateBlockAndImport(t, false, true)
+}
+
+//nolint:thelper
+func testGenerateBlockAndImport(t *testing.T, isClique bool, isBor bool) {
var (
engine consensus.Engine
chainConfig *params.ChainConfig
db = rawdb.NewMemoryDatabase()
)
- if isClique {
- chainConfig = params.AllCliqueProtocolChanges
- chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000}
- engine = clique.New(chainConfig.Clique, db)
+
+ if isBor {
+ chainConfig = params.BorUnittestChainConfig
+
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ ethAPIMock := api.NewMockCaller(ctrl)
+ ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+
+ spanner := bor.NewMockSpanner(ctrl)
+ spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{
+ {
+ ID: 0,
+ Address: testBankAddress,
+ VotingPower: 100,
+ ProposerPriority: 0,
+ },
+ }, nil).AnyTimes()
+
+ heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl)
+ heimdallClientMock.EXPECT().Close().Times(1)
+
+ contractMock := bor.NewMockGenesisContract(ctrl)
+
+ db, _, _ = NewDBForFakes(t)
+
+ engine = NewFakeBor(t, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock)
} else {
- chainConfig = params.AllEthashProtocolChanges
- engine = ethash.NewFaker()
+ if isClique {
+ chainConfig = params.AllCliqueProtocolChanges
+ chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000}
+ engine = clique.New(chainConfig.Clique, db)
+ } else {
+ chainConfig = params.AllEthashProtocolChanges
+ engine = ethash.NewFaker()
+ }
}
+ defer engine.Close()
+
chainConfig.LondonBlock = big.NewInt(0)
+
w, b := newTestWorker(t, chainConfig, engine, db, 0)
defer w.close()
// This test chain imports the mined blocks.
db2 := rawdb.NewMemoryDatabase()
b.genesis.MustCommit(db2)
+
chain, _ := core.NewBlockChain(db2, nil, b.chain.Config(), engine, vm.Config{}, nil, nil)
defer chain.Stop()
@@ -287,20 +324,25 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
taskIndex int
taskCh = make(chan struct{}, 2)
)
+
checkEqual := func(t *testing.T, task *task, index int) {
// The first empty work without any txs included
receiptLen, balance := 0, big.NewInt(0)
+
if index == 1 {
// The second full work with 1 tx included
receiptLen, balance = 1, big.NewInt(1000)
}
+
if len(task.receipts) != receiptLen {
t.Fatalf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen)
}
+
if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 {
t.Fatalf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance)
}
}
+
w.newTaskHook = func(task *task) {
if task.block.NumberU64() == 1 {
checkEqual(t, task, taskIndex)
@@ -308,11 +350,14 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
taskCh <- struct{}{}
}
}
+
w.skipSealHook = func(task *task) bool { return true }
w.fullTaskHook = func() {
time.Sleep(100 * time.Millisecond)
}
+
w.start() // Start mining!
+
for i := 0; i < 2; i += 1 {
select {
case <-taskCh:
@@ -344,16 +389,20 @@ func TestStreamUncleBlock(t *testing.T) {
t.Errorf("uncle hash mismatch: have %s, want %s", have.Hex(), want.Hex())
}
}
+
taskCh <- struct{}{}
taskIndex += 1
}
}
+
w.skipSealHook = func(task *task) bool {
return true
}
+
w.fullTaskHook = func() {
time.Sleep(100 * time.Millisecond)
}
+
w.start()
for i := 0; i < 2; i += 1 {
@@ -396,20 +445,25 @@ func testRegenerateMiningBlock(t *testing.T, chainConfig *params.ChainConfig, en
// one has 1 pending tx, the third one has 2 txs
if taskIndex == 2 {
receiptLen, balance := 2, big.NewInt(2000)
+
if len(task.receipts) != receiptLen {
t.Errorf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen)
}
+
if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 {
t.Errorf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance)
}
}
+
taskCh <- struct{}{}
taskIndex += 1
}
}
+
w.skipSealHook = func(task *task) bool {
return true
}
+
w.fullTaskHook = func() {
time.Sleep(100 * time.Millisecond)
}
@@ -423,6 +477,7 @@ func testRegenerateMiningBlock(t *testing.T, chainConfig *params.ChainConfig, en
t.Error("new task timeout")
}
}
+
b.txPool.AddLocals(newTxs)
time.Sleep(time.Second)
@@ -464,6 +519,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co
index = 0
start uint32
)
+
w.resubmitHook = func(minInterval time.Duration, recommitInterval time.Duration) {
// Short circuit if interval checking hasn't started.
if atomic.LoadUint32(&start) == 0 {
@@ -494,16 +550,19 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co
if recommitInterval != wantRecommitInterval {
t.Errorf("resubmit interval mismatch: have %v, want %v", recommitInterval, wantRecommitInterval)
}
+
result = append(result, float64(recommitInterval.Nanoseconds()))
index += 1
progress <- struct{}{}
}
+
w.start()
time.Sleep(time.Second) // Ensure two tasks have been summitted due to start opt
atomic.StoreUint32(&start, 1)
w.setRecommitInterval(3 * time.Second)
+
select {
case <-progress:
case <-time.NewTimer(time.Second).C:
@@ -511,6 +570,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co
}
w.resubmitAdjustCh <- &intervalAdjust{inc: true, ratio: 0.8}
+
select {
case <-progress:
case <-time.NewTimer(time.Second).C:
@@ -518,6 +578,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co
}
w.resubmitAdjustCh <- &intervalAdjust{inc: false}
+
select {
case <-progress:
case <-time.NewTimer(time.Second).C:
@@ -525,6 +586,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co
}
w.setRecommitInterval(500 * time.Millisecond)
+
select {
case <-progress:
case <-time.NewTimer(time.Second).C:
@@ -559,9 +621,11 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
w.skipSealHook = func(task *task) bool {
return true
}
+
w.fullTaskHook = func() {
time.Sleep(100 * time.Millisecond)
}
+
timestamp := uint64(time.Now().Unix())
assertBlock := func(block *types.Block, number uint64, coinbase common.Address, random common.Hash) {
if block.Time() != timestamp {
@@ -569,14 +633,17 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
// is even smaller than parent block's. It's OK.
t.Logf("Invalid timestamp, want %d, get %d", timestamp, block.Time())
}
+
if len(block.Uncles()) != 0 {
t.Error("Unexpected uncle block")
}
+
_, isClique := engine.(*clique.Clique)
if !isClique {
if len(block.Extra()) != 0 {
t.Error("Unexpected extra field")
}
+
if block.Coinbase() != coinbase {
t.Errorf("Unexpected coinbase got %x want %x", block.Coinbase(), coinbase)
}
@@ -585,18 +652,22 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
t.Error("Unexpected coinbase")
}
}
+
if !isClique {
if block.MixDigest() != random {
t.Error("Unexpected mix digest")
}
}
+
if block.Nonce() != 0 {
t.Error("Unexpected block nonce")
}
+
if block.NumberU64() != number {
t.Errorf("Mismatched block number, want %d got %d", number, block.NumberU64())
}
}
+
var cases = []struct {
parent common.Hash
coinbase common.Address
@@ -644,6 +715,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
// This API should work even when the automatic sealing is not enabled
for _, c := range cases {
block, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random)
+
if c.expectErr {
if err == nil {
t.Error("Expect error but get nil")
@@ -652,12 +724,14 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
if err != nil {
t.Errorf("Unexpected error %v", err)
}
+
assertBlock(block, c.expectNumber, c.coinbase, c.random)
}
}
// This API should work even when the automatic sealing is enabled
w.start()
+
for _, c := range cases {
block, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random)
if c.expectErr {
@@ -668,6 +742,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
if err != nil {
t.Errorf("Unexpected error %v", err)
}
+
assertBlock(block, c.expectNumber, c.coinbase, c.random)
}
}
diff --git a/params/config.go b/params/config.go
index 47e22f986c..980250a1ec 100644
--- a/params/config.go
+++ b/params/config.go
@@ -23,8 +23,9 @@ import (
"sort"
"strconv"
- "github.com/ethereum/go-ethereum/common"
"golang.org/x/crypto/sha3"
+
+ "github.com/ethereum/go-ethereum/common"
)
// Genesis hashes to enforce below configs on.
@@ -289,6 +290,38 @@ var (
},
},
}
+ BorUnittestChainConfig = &ChainConfig{
+ ChainID: big.NewInt(80001),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ EIP150Hash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ Bor: &BorConfig{
+ Period: map[string]uint64{
+ "0": 1,
+ },
+ ProducerDelay: 3,
+ Sprint: 32,
+ BackupMultiplier: map[string]uint64{
+ "0": 2,
+ },
+ ValidatorContract: "0x0000000000000000000000000000000000001000",
+ StateReceiverContract: "0x0000000000000000000000000000000000001001",
+ BurntContract: map[string]string{
+ "0": "0x00000000000000000000000000000000000000000",
+ },
+ },
+ }
// MumbaiChainConfig contains the chain parameters to run a node on the Mumbai test network.
MumbaiChainConfig = &ChainConfig{
@@ -550,7 +583,9 @@ func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uin
for k := range field {
keys = append(keys, k)
}
+
sort.Strings(keys)
+
for i := 0; i < len(keys)-1; i++ {
valUint, _ := strconv.ParseUint(keys[i], 10, 64)
valUintNext, _ := strconv.ParseUint(keys[i+1], 10, 64)
@@ -558,6 +593,7 @@ func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uin
return field[keys[i]]
}
}
+
return field[keys[len(keys)-1]]
}
diff --git a/scripts/tools-protobuf.sh b/scripts/tools-protobuf.sh
index fe03cab3cb..04144134f4 100755
--- a/scripts/tools-protobuf.sh
+++ b/scripts/tools-protobuf.sh
@@ -1,15 +1,24 @@
#!/bin/bash
# Install protobuf
-PROTOC_ZIP=protoc-3.12.0-linux-x86_64.zip
-curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/$PROTOC_ZIP
+if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ os="linux"
+elif [[ "$OSTYPE" == "darwin"* ]]; then
+ os="osx"
+else
+ echo "Unsupported platform"
+ exit 1
+fi
+
+PROTOC_ZIP=protoc-3.19.3-$os-x86_64.zip
+curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.19.3/$PROTOC_ZIP
sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
sudo unzip -o $PROTOC_ZIP -d /usr/local 'include/*'
rm -f $PROTOC_ZIP
# Change permissions to use the binary
-sudo chmod 755 -R /usr/local/bin/protoc
-sudo chmod 755 -R /usr/local/include
+sudo chmod -R 755 /usr/local/bin/protoc
+sudo chmod -R 755 /usr/local/include
# Install golang extensions (DO NOT CHANGE THE VERSIONS)
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.25.0
diff --git a/tests/block_test.go b/tests/block_test.go
index 74c7ed8197..591bff6e07 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -14,6 +14,9 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
+//go:build integration
+// +build integration
+
package tests
import (
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index bcf861e09b..d28f3a1237 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -15,6 +15,7 @@
// along with the go-ethereum library. If not, see .
// Package tests implements execution of Ethereum JSON tests.
+
package tests
import (
diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go
index a179616290..36d515c557 100644
--- a/tests/bor/bor_test.go
+++ b/tests/bor/bor_test.go
@@ -1,8 +1,10 @@
+//go:build integration
+// +build integration
+
package bor
import (
"encoding/hex"
- "encoding/json"
"io"
"math/big"
"testing"
@@ -14,6 +16,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/bor"
+ "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
@@ -25,19 +30,13 @@ import (
"github.com/ethereum/go-ethereum/tests/bor/mocks"
)
-var (
- spanPath = "bor/span/1"
- clerkPath = "clerk/event-record/list"
- clerkQueryParams = "from-time=%d&to-time=%d&page=%d&limit=50"
-)
-
func TestInsertingSpanSizeBlocks(t *testing.T) {
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
_bor := engine.(*bor.Bor)
- defer engine.Close()
+ defer _bor.Close()
h, heimdallSpan, ctrl := getMockedHeimdallClient(t)
defer ctrl.Finish()
@@ -45,7 +44,7 @@ func TestInsertingSpanSizeBlocks(t *testing.T) {
_, span := loadSpanFromFile(t)
h.EXPECT().Close().AnyTimes()
- h.EXPECT().FetchLatestCheckpoint().Return(&bor.Checkpoint{
+ h.EXPECT().FetchLatestCheckpoint().Return(&checkpoint.Checkpoint{
Proposer: span.SelectedProducers[0].Address,
StartBlock: big.NewInt(0),
EndBlock: big.NewInt(int64(spanSize)),
@@ -81,7 +80,7 @@ func TestFetchStateSyncEvents(t *testing.T) {
engine := init.ethereum.Engine()
_bor := engine.(*bor.Bor)
- defer engine.Close()
+ defer _bor.Close()
// A. Insert blocks for 0th sprint
db := init.ethereum.ChainDb()
@@ -101,6 +100,7 @@ func TestFetchStateSyncEvents(t *testing.T) {
h := mocks.NewMockIHeimdallClient(ctrl)
h.EXPECT().Close().AnyTimes()
+ h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes()
// B.2 Mock State Sync events
fromID := uint64(1)
@@ -112,9 +112,7 @@ func TestFetchStateSyncEvents(t *testing.T) {
sample.Time = time.Unix(to-int64(eventCount+1), 0) // last event.Time will be just < to
eventRecords := generateFakeStateSyncEvents(sample, eventCount)
- // Mock
- h.EXPECT().FetchWithRetry(spanPath, "").Return(res, nil).AnyTimes()
- h.EXPECT().FetchStateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
+ h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
_bor.SetHeimdallClient(h)
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
@@ -137,7 +135,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
h := mocks.NewMockIHeimdallClient(ctrl)
h.EXPECT().Close().AnyTimes()
- h.EXPECT().FetchWithRetry(spanPath, "").Return(res, nil).AnyTimes()
+ h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes()
// Mock State Sync events
// at # sprintSize, events are fetched for [fromID, (block-sprint).Time)
@@ -147,7 +145,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
// First query will be from [id=1, (block-sprint).Time]
// Insert 5 events in this time range
- eventRecords := []*bor.EventRecordWithTime{
+ eventRecords := []*clerk.EventRecordWithTime{
buildStateEvent(sample, 1, 3), // id = 1, time = 1
buildStateEvent(sample, 2, 1), // id = 2, time = 3
buildStateEvent(sample, 3, 2), // id = 3, time = 2
@@ -156,7 +154,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
buildStateEvent(sample, 6, 4), // id = 6, time = 4
}
- h.EXPECT().FetchStateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
+ h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
_bor.SetHeimdallClient(h)
// Insert blocks for 0th sprint
@@ -175,12 +173,12 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
//
fromID = uint64(5)
to = int64(chain.GetHeaderByNumber(sprintSize).Time)
- eventRecords = []*bor.EventRecordWithTime{
+
+ eventRecords = []*clerk.EventRecordWithTime{
buildStateEvent(sample, 5, 7),
buildStateEvent(sample, 6, 4),
}
-
- h.EXPECT().FetchStateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
+ h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
for i := sprintSize + 1; i <= spanSize; i++ {
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
@@ -278,58 +276,50 @@ func TestSignerNotFound(t *testing.T) {
bor.UnauthorizedSignerError{Number: 0, Signer: addr.Bytes()})
}
-func getMockedHeimdallClient(t *testing.T) (*mocks.MockIHeimdallClient, *bor.HeimdallSpan, *gomock.Controller) {
+func getMockedHeimdallClient(t *testing.T) (*mocks.MockIHeimdallClient, *span.HeimdallSpan, *gomock.Controller) {
ctrl := gomock.NewController(t)
h := mocks.NewMockIHeimdallClient(ctrl)
- res, heimdallSpan := loadSpanFromFile(t)
+ _, heimdallSpan := loadSpanFromFile(t)
- h.EXPECT().FetchWithRetry(spanPath, "").Return(res, nil).AnyTimes()
- h.EXPECT().FetchStateSyncEvents(gomock.Any(), gomock.Any()).Return(getEventRecords(t), nil).AnyTimes()
+ h.EXPECT().Span(uint64(1)).Return(heimdallSpan, nil).AnyTimes()
+
+ h.EXPECT().StateSyncEvents(gomock.Any(), gomock.Any()).
+ Return([]*clerk.EventRecordWithTime{getSampleEventRecord(t)}, nil).AnyTimes()
return h, heimdallSpan, ctrl
}
-func generateFakeStateSyncEvents(sample *bor.EventRecordWithTime, count int) []*bor.EventRecordWithTime {
- events := make([]*bor.EventRecordWithTime, count)
+func generateFakeStateSyncEvents(sample *clerk.EventRecordWithTime, count int) []*clerk.EventRecordWithTime {
+ events := make([]*clerk.EventRecordWithTime, count)
event := *sample
event.ID = 1
- events[0] = &bor.EventRecordWithTime{}
+ events[0] = &clerk.EventRecordWithTime{}
*events[0] = event
for i := 1; i < count; i++ {
event.ID = uint64(i)
event.Time = event.Time.Add(1 * time.Second)
- events[i] = &bor.EventRecordWithTime{}
+ events[i] = &clerk.EventRecordWithTime{}
*events[i] = event
}
return events
}
-func buildStateEvent(sample *bor.EventRecordWithTime, id uint64, timeStamp int64) *bor.EventRecordWithTime {
+func buildStateEvent(sample *clerk.EventRecordWithTime, id uint64, timeStamp int64) *clerk.EventRecordWithTime {
event := *sample
event.ID = id
event.Time = time.Unix(timeStamp, 0)
return &event
}
-func getSampleEventRecord(t *testing.T) *bor.EventRecordWithTime {
- res := stateSyncEventsPayload(t)
- var _eventRecords []*bor.EventRecordWithTime
- if err := json.Unmarshal(res.Result, &_eventRecords); err != nil {
- t.Fatalf("%s", err)
- }
- _eventRecords[0].Time = time.Unix(1, 0)
- return _eventRecords[0]
+func getSampleEventRecord(t *testing.T) *clerk.EventRecordWithTime {
+ eventRecords := stateSyncEventsPayload(t)
+ eventRecords.Result[0].Time = time.Unix(1, 0)
+ return eventRecords.Result[0]
}
-func getEventRecords(t *testing.T) []*bor.EventRecordWithTime {
- res := stateSyncEventsPayload(t)
- var _eventRecords []*bor.EventRecordWithTime
- if err := json.Unmarshal(res.Result, &_eventRecords); err != nil {
- t.Fatalf("%s", err)
- }
-
- return _eventRecords
+func getEventRecords(t *testing.T) []*clerk.EventRecordWithTime {
+ return stateSyncEventsPayload(t).Result
}
// TestEIP1559Transition tests the following:
diff --git a/tests/bor/helper.go b/tests/bor/helper.go
index a1b6a19742..a8a3ae4ea6 100644
--- a/tests/bor/helper.go
+++ b/tests/bor/helper.go
@@ -11,6 +11,9 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/bor"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall"
+ "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
+ "github.com/ethereum/go-ethereum/consensus/bor/valset"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@@ -46,17 +49,23 @@ type initializeData struct {
}
func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
+ t.Helper()
+
genesisData, err := ioutil.ReadFile("./testdata/genesis.json")
if err != nil {
t.Fatalf("%s", err)
}
+
gen := &core.Genesis{}
+
if err := json.Unmarshal(genesisData, gen); err != nil {
t.Fatalf("%s", err)
}
+
ethConf := ð.Config{
Genesis: gen,
}
+
ethConf.Genesis.MustCommit(db)
ethereum := utils.CreateBorEthereum(ethConf)
@@ -65,6 +74,7 @@ func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
}
ethConf.Genesis.MustCommit(ethereum.ChainDb())
+
return &initializeData{
genesis: gen,
ethereum: ethereum,
@@ -72,12 +82,16 @@ func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
}
func insertNewBlock(t *testing.T, chain *core.BlockChain, block *types.Block) {
+ t.Helper()
+
if _, err := chain.InsertChain([]*types.Block{block}); err != nil {
t.Fatalf("%s", err)
}
}
func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block *types.Block, signer []byte, borConfig *params.BorConfig) *types.Block {
+ t.Helper()
+
header := block.Header()
header.Number.Add(header.Number, big.NewInt(1))
number := header.Number.Uint64()
@@ -90,11 +104,12 @@ func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block *
header.Time += bor.CalcProducerDelay(header.Number.Uint64(), 0, borConfig)
header.Extra = make([]byte, 32+65) // vanity + extraSeal
- currentValidators := []*bor.Validator{bor.NewValidator(addr, 10)}
+ currentValidators := []*valset.Validator{valset.NewValidator(addr, 10)}
isSpanEnd := (number+1)%spanSize == 0
isSpanStart := number%spanSize == 0
isSprintEnd := (header.Number.Uint64()+1)%sprintSize == 0
+
if isSpanEnd {
_, heimdallSpan := loadSpanFromFile(t)
// this is to stash the validator bytes in the header
@@ -102,18 +117,23 @@ func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block *
} else if isSpanStart {
header.Difficulty = new(big.Int).SetInt64(3)
}
+
if isSprintEnd {
- sort.Sort(bor.ValidatorsByAddress(currentValidators))
+ sort.Sort(valset.ValidatorsByAddress(currentValidators))
+
validatorBytes := make([]byte, len(currentValidators)*validatorHeaderBytesLength)
header.Extra = make([]byte, 32+len(validatorBytes)+65) // vanity + validatorBytes + extraSeal
+
for i, val := range currentValidators {
copy(validatorBytes[i*validatorHeaderBytesLength:], val.HeaderBytes())
}
+
copy(header.Extra[32:], validatorBytes)
}
if chain.Config().IsLondon(header.Number) {
header.BaseFee = misc.CalcBaseFee(chain.Config(), block.Header())
+
if !chain.Config().IsLondon(block.Number()) {
parentGasLimit := block.GasLimit() * params.ElasticityMultiplier
header.GasLimit = core.CalcGasLimit(parentGasLimit, parentGasLimit)
@@ -124,58 +144,73 @@ func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block *
if err != nil {
t.Fatalf("%s", err)
}
+
_, err = _bor.FinalizeAndAssemble(chain, header, state, nil, nil, nil)
if err != nil {
t.Fatalf("%s", err)
}
+
sign(t, header, signer, borConfig)
+
return types.NewBlockWithHeader(header)
}
func sign(t *testing.T, header *types.Header, signer []byte, c *params.BorConfig) {
+ t.Helper()
+
sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header, c)), signer)
if err != nil {
t.Fatalf("%s", err)
}
+
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
}
-func stateSyncEventsPayload(t *testing.T) *bor.ResponseWithHeight {
+//nolint:unused,deadcode
+func stateSyncEventsPayload(t *testing.T) *heimdall.StateSyncEventsResponse {
+ t.Helper()
+
stateData, err := ioutil.ReadFile("./testdata/states.json")
if err != nil {
t.Fatalf("%s", err)
}
- res := &bor.ResponseWithHeight{}
+
+ res := &heimdall.StateSyncEventsResponse{}
if err := json.Unmarshal(stateData, res); err != nil {
t.Fatalf("%s", err)
}
+
return res
}
-func loadSpanFromFile(t *testing.T) (*bor.ResponseWithHeight, *bor.HeimdallSpan) {
+//nolint:unused,deadcode
+func loadSpanFromFile(t *testing.T) (*heimdall.SpanResponse, *span.HeimdallSpan) {
+ t.Helper()
+
spanData, err := ioutil.ReadFile("./testdata/span.json")
if err != nil {
t.Fatalf("%s", err)
}
- res := &bor.ResponseWithHeight{}
+
+ res := &heimdall.SpanResponse{}
+
if err := json.Unmarshal(spanData, res); err != nil {
t.Fatalf("%s", err)
}
- heimdallSpan := &bor.HeimdallSpan{}
- if err := json.Unmarshal(res.Result, heimdallSpan); err != nil {
- t.Fatalf("%s", err)
- }
- return res, heimdallSpan
+ return res, &res.Result
}
func getSignerKey(number uint64) []byte {
signerKey := privKey
+
isSpanStart := number%spanSize == 0
if isSpanStart {
// validator set in the new span has changed
signerKey = privKey2
}
+
_key, _ := hex.DecodeString(signerKey)
+
return _key
}
diff --git a/tests/bor/mocks/IHeimdallClient.go b/tests/bor/mocks/IHeimdallClient.go
index 9420c261fb..f770ed9fa8 100644
--- a/tests/bor/mocks/IHeimdallClient.go
+++ b/tests/bor/mocks/IHeimdallClient.go
@@ -7,7 +7,9 @@ package mocks
import (
reflect "reflect"
- bor "github.com/ethereum/go-ethereum/consensus/bor"
+ clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk"
+ checkpoint "github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
+ span "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
gomock "github.com/golang/mock/gomock"
)
@@ -46,26 +48,11 @@ func (mr *MockIHeimdallClientMockRecorder) Close() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockIHeimdallClient)(nil).Close))
}
-// Fetch mocks base method.
-func (m *MockIHeimdallClient) Fetch(arg0, arg1 string) (*bor.ResponseWithHeight, error) {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "Fetch", arg0, arg1)
- ret0, _ := ret[0].(*bor.ResponseWithHeight)
- ret1, _ := ret[1].(error)
- return ret0, ret1
-}
-
-// Fetch indicates an expected call of Fetch.
-func (mr *MockIHeimdallClientMockRecorder) Fetch(arg0, arg1 interface{}) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fetch", reflect.TypeOf((*MockIHeimdallClient)(nil).Fetch), arg0, arg1)
-}
-
// FetchLatestCheckpoint mocks base method.
-func (m *MockIHeimdallClient) FetchLatestCheckpoint() (*bor.Checkpoint, error) {
+func (m *MockIHeimdallClient) FetchLatestCheckpoint() (*checkpoint.Checkpoint, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchLatestCheckpoint")
- ret0, _ := ret[0].(*bor.Checkpoint)
+ ret0, _ := ret[0].(*checkpoint.Checkpoint)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -76,32 +63,32 @@ func (mr *MockIHeimdallClientMockRecorder) FetchLatestCheckpoint() *gomock.Call
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLatestCheckpoint", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchLatestCheckpoint))
}
-// FetchStateSyncEvents mocks base method.
-func (m *MockIHeimdallClient) FetchStateSyncEvents(arg0 uint64, arg1 int64) ([]*bor.EventRecordWithTime, error) {
+// Span mocks base method.
+func (m *MockIHeimdallClient) Span(arg0 uint64) (*span.HeimdallSpan, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "FetchStateSyncEvents", arg0, arg1)
- ret0, _ := ret[0].([]*bor.EventRecordWithTime)
+ ret := m.ctrl.Call(m, "Span", arg0)
+ ret0, _ := ret[0].(*span.HeimdallSpan)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// FetchStateSyncEvents indicates an expected call of FetchStateSyncEvents.
-func (mr *MockIHeimdallClientMockRecorder) FetchStateSyncEvents(arg0, arg1 interface{}) *gomock.Call {
+// Span indicates an expected call of Span.
+func (mr *MockIHeimdallClientMockRecorder) Span(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchStateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchStateSyncEvents), arg0, arg1)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Span", reflect.TypeOf((*MockIHeimdallClient)(nil).Span), arg0)
}
-// FetchWithRetry mocks base method.
-func (m *MockIHeimdallClient) FetchWithRetry(arg0, arg1 string) (*bor.ResponseWithHeight, error) {
+// StateSyncEvents mocks base method.
+func (m *MockIHeimdallClient) StateSyncEvents(arg0 uint64, arg1 int64) ([]*clerk.EventRecordWithTime, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "FetchWithRetry", arg0, arg1)
- ret0, _ := ret[0].(*bor.ResponseWithHeight)
+ ret := m.ctrl.Call(m, "StateSyncEvents", arg0, arg1)
+ ret0, _ := ret[0].([]*clerk.EventRecordWithTime)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// FetchWithRetry indicates an expected call of FetchWithRetry.
-func (mr *MockIHeimdallClientMockRecorder) FetchWithRetry(arg0, arg1 interface{}) *gomock.Call {
+// StateSyncEvents indicates an expected call of StateSyncEvents.
+func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchWithRetry", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchWithRetry), arg0, arg1)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).StateSyncEvents), arg0, arg1)
}
diff --git a/tests/difficulty_test.go b/tests/difficulty_test.go
index 192dff12cc..0b030c1485 100644
--- a/tests/difficulty_test.go
+++ b/tests/difficulty_test.go
@@ -14,6 +14,9 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
+//go:build integration
+// +build integration
+
package tests
import (
diff --git a/tests/init_test.go b/tests/init_test.go
index 7e2f3ff7f5..4ade0bfb90 100644
--- a/tests/init_test.go
+++ b/tests/init_test.go
@@ -14,6 +14,9 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
+//go:build integration
+// +build integration
+
package tests
import (
diff --git a/tests/rlp_test.go b/tests/rlp_test.go
index 79a1683eb2..dbca73efc6 100644
--- a/tests/rlp_test.go
+++ b/tests/rlp_test.go
@@ -14,6 +14,9 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
+//go:build integration
+// +build integration
+
package tests
import (
diff --git a/tests/state_test.go b/tests/state_test.go
index d2c92b211c..8fcf35b864 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -14,6 +14,9 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
+//go:build integration
+// +build integration
+
package tests
import (
diff --git a/tests/transaction_test.go b/tests/transaction_test.go
index cb0f262318..1197eebe19 100644
--- a/tests/transaction_test.go
+++ b/tests/transaction_test.go
@@ -14,6 +14,9 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
+//go:build integration
+// +build integration
+
package tests
import (
diff --git a/trie/hasher.go b/trie/hasher.go
index 7f0748c13d..c085970a3f 100644
--- a/trie/hasher.go
+++ b/trie/hasher.go
@@ -19,9 +19,10 @@ package trie
import (
"sync"
+ "golang.org/x/crypto/sha3"
+
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
- "golang.org/x/crypto/sha3"
)
// hasher is a type used for the trie Hash operation. A hasher has some