Compare commits
120 Commits
v1.3.4
...
v1.3.10_ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f769d5dd0 | ||
|
|
3b55be5eb2 | ||
|
|
280cad3098 | ||
|
|
9fb0241eab | ||
|
|
c8cc91963f | ||
|
|
bd13416162 | ||
|
|
b7b64da564 | ||
|
|
73f27a590f | ||
|
|
5e74ea650d | ||
|
|
5378df3702 | ||
|
|
40cae45436 | ||
|
|
361e8413e6 | ||
|
|
36a283ef98 | ||
|
|
78d1cade19 | ||
|
|
82beb2c5f3 | ||
|
|
3761bf0426 | ||
|
|
29427c51fd | ||
|
|
220be95117 | ||
|
|
f0d9f61bf6 | ||
|
|
d49da4348c | ||
|
|
fecd2bfafe | ||
|
|
ef13f3194d | ||
|
|
c6aeee2001 | ||
|
|
58602e6b53 | ||
|
|
d10200175e | ||
|
|
a6a956263e | ||
|
|
ef462c2b47 | ||
|
|
4829027a54 | ||
|
|
bea8f8ecfc | ||
|
|
04d62b53da | ||
|
|
d8b85839ee | ||
|
|
e606461454 | ||
|
|
1c3d31c19f | ||
|
|
0d5ecb5b90 | ||
|
|
1469bce18a | ||
|
|
a17fef4f15 | ||
|
|
fee8a25957 | ||
|
|
ccb4d55a7c | ||
|
|
8ed5d24e1d | ||
|
|
5853329c63 | ||
|
|
69531d67a8 | ||
|
|
7b22894146 | ||
|
|
b2de32fb16 | ||
|
|
73d19c00cd | ||
|
|
5fa1755329 | ||
|
|
23a8d00334 | ||
|
|
3349a24333 | ||
|
|
7f2ef5987f | ||
|
|
8d51cec12e | ||
|
|
de1a126ec5 | ||
|
|
124939aaa4 | ||
|
|
a25a2143ce | ||
|
|
7c8fa2b880 | ||
|
|
a6befb5078 | ||
|
|
8e56d6b875 | ||
|
|
0bdd0d20e5 | ||
|
|
267c5c028c | ||
|
|
c25594257d | ||
|
|
ad09930bdf | ||
|
|
eb4ea42196 | ||
|
|
0ba5816cc7 | ||
|
|
354c0d7180 | ||
|
|
9badb15e80 | ||
|
|
f28b98a994 | ||
|
|
01a4b00a2b | ||
|
|
474860ef77 | ||
|
|
4d2bd1253d | ||
|
|
ca058b7a69 | ||
|
|
f4b7cdfe38 | ||
|
|
f6fb2e9116 | ||
|
|
e44de3ab27 | ||
|
|
07c46abcbe | ||
|
|
8a440e753f | ||
|
|
5ee77bbe8b | ||
|
|
8205fdc525 | ||
|
|
0b632d97f3 | ||
|
|
84b268f6fb | ||
|
|
f628e32ba5 | ||
|
|
e4910b9540 | ||
|
|
2e69dcb342 | ||
|
|
64be7df9e2 | ||
|
|
1ebf2a4376 | ||
|
|
8ce9cdaae3 | ||
|
|
b3df096358 | ||
|
|
4b107c5303 | ||
|
|
fe928d4778 | ||
|
|
a140a5a324 | ||
|
|
e3ef62f3bd | ||
|
|
fa5d0cf287 | ||
|
|
6c788d7675 | ||
|
|
a30beeba59 | ||
|
|
aa15df2814 | ||
|
|
195ae35130 | ||
|
|
5db73c9837 | ||
|
|
3a5ec36c54 | ||
|
|
7891b210e0 | ||
|
|
3076ad2ab9 | ||
|
|
d9873bbf38 | ||
|
|
3e6c16afd3 | ||
|
|
1ddd337d1c | ||
|
|
a182557ac3 | ||
|
|
4b32d400ee | ||
|
|
7e6b43a5c7 | ||
|
|
5b78f5761a | ||
|
|
70ccc3d1fe | ||
|
|
20dcaabfdc | ||
|
|
c409eb6ac6 | ||
|
|
cf80501de5 | ||
|
|
3ce568ff44 | ||
|
|
8e19728ea7 | ||
|
|
1edb34fd67 | ||
|
|
789442372d | ||
|
|
c92b6ce2ad | ||
|
|
cd0356b106 | ||
|
|
0224d48df4 | ||
|
|
497fdf8358 | ||
|
|
8b94dd6b59 | ||
|
|
4be9481558 | ||
|
|
3fc9f750d1 | ||
|
|
72ffb0cbed |
6
.github/workflows/build-test.yml
vendored
6
.github/workflows/build-test.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
- develop
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
unit-test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.20.x]
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
@@ -47,5 +47,3 @@ jobs:
|
||||
run: |
|
||||
go mod download
|
||||
make geth
|
||||
|
||||
|
||||
|
||||
2
.github/workflows/commit-lint.yml
vendored
2
.github/workflows/commit-lint.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
- develop
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
|
||||
56
.github/workflows/evm-tests.yml
vendored
Normal file
56
.github/workflows/evm-tests.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: EVM Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
evm-test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
# In order:
|
||||
# * Module download cache
|
||||
# * Build cache (Linux)
|
||||
# * Build cache (Mac)
|
||||
# * Build cache (Windows)
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
~/Library/Caches/go-build
|
||||
~\AppData\Local\go-build
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-
|
||||
|
||||
- name: EVM Test
|
||||
env:
|
||||
CGO_CFLAGS: "-O -D__BLST_PORTABLE__"
|
||||
CGO_CFLAGS_ALLOW: "-O -D__BLST_PORTABLE__"
|
||||
ANDROID_HOME: "" # Skip android test
|
||||
run: |
|
||||
git submodule update --init --depth 1 --recursive
|
||||
go mod download
|
||||
cd tests
|
||||
sed -i -e 's/\/\/ bt.skipLoad/bt.skipLoad/g' block_test.go
|
||||
bash -x run-evm-tests.sh
|
||||
2
.github/workflows/integration-test.yml
vendored
2
.github/workflows/integration-test.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
- develop
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
|
||||
8
.github/workflows/lint.yml
vendored
8
.github/workflows/lint.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
- develop
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
golang-lint:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.20.x]
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
@@ -44,13 +44,13 @@ jobs:
|
||||
${{ runner.os }}-go-
|
||||
|
||||
- run: |
|
||||
go mod download
|
||||
go mod tidy
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
||||
version: v1.52.2
|
||||
version: v1.55.2
|
||||
working-directory: ./
|
||||
skip-pkg-cache: true
|
||||
skip-cache: true
|
||||
|
||||
37
.github/workflows/nancy.yml
vendored
Normal file
37
.github/workflows/nancy.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Go Nancy
|
||||
|
||||
on:
|
||||
# Scan changed files in PRs (diff-aware scanning):
|
||||
pull_request: {}
|
||||
# Scan on-demand through GitHub Actions interface:
|
||||
workflow_dispatch: {}
|
||||
# Scan mainline branches and report all findings:
|
||||
push:
|
||||
branches: ["master", "develop"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Go 1.x in order to write go.list file
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Go mod tidy
|
||||
run: go mod tidy
|
||||
|
||||
- name: WriteGoList
|
||||
run: go list -json -deps ./... > go.list
|
||||
|
||||
- name: Nancy
|
||||
uses: sonatype-nexus-community/nancy-github-action@main
|
||||
with:
|
||||
nancyCommand: sleuth --loud
|
||||
2
.github/workflows/pre-release.yml
vendored
2
.github/workflows/pre-release.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
name: Build Release
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.20.x]
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
name: Build Release
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.20.x]
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
||||
5
.github/workflows/unit-test.yml
vendored
5
.github/workflows/unit-test.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
- develop
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
unit-test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.20.x]
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
@@ -51,4 +51,3 @@ jobs:
|
||||
run: |
|
||||
go mod download
|
||||
make test
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,7 +14,6 @@
|
||||
*/**/*tx_database*
|
||||
*/**/*dapps*
|
||||
build/_vendor/pkg
|
||||
/tests/truffle/storage
|
||||
|
||||
#*
|
||||
.#*
|
||||
|
||||
@@ -15,7 +15,6 @@ output:
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- goconst
|
||||
- goimports
|
||||
- gosimple
|
||||
- govet
|
||||
@@ -42,9 +41,6 @@ linters:
|
||||
linters-settings:
|
||||
gofmt:
|
||||
simplify: true
|
||||
goconst:
|
||||
min-len: 3 # minimum length of string constant
|
||||
min-occurrences: 6 # minimum number of occurrences
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
|
||||
22
.travis.yml
22
.travis.yml
@@ -13,7 +13,7 @@ jobs:
|
||||
- stage: lint
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- lint
|
||||
git:
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
os: linux
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- docker
|
||||
services:
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- docker
|
||||
services:
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
os: linux
|
||||
dist: bionic
|
||||
sudo: required
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- azure-linux
|
||||
- GO111MODULE=on
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
- stage: build
|
||||
if: type = push
|
||||
os: osx
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- azure-osx
|
||||
- GO111MODULE=on
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
os: linux
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
script:
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
go: 1.19.x
|
||||
go: 1.20.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
script:
|
||||
@@ -132,7 +132,7 @@ jobs:
|
||||
- stage: build
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.19.x
|
||||
go: 1.20.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
script:
|
||||
@@ -143,7 +143,7 @@ jobs:
|
||||
if: type = cron || (type = push && tag ~= /^v[0-9]/)
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- ubuntu-ppa
|
||||
- GO111MODULE=on
|
||||
@@ -167,7 +167,7 @@ jobs:
|
||||
if: type = cron
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- azure-purge
|
||||
- GO111MODULE=on
|
||||
@@ -181,7 +181,7 @@ jobs:
|
||||
if: type = cron
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.20.x
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
script:
|
||||
|
||||
117
CHANGELOG.md
117
CHANGELOG.md
@@ -1,20 +1,131 @@
|
||||
# Changelog
|
||||
## v1.3.13
|
||||
* [\#2358](https://github.com/bnb-chain/bsc/pull/2358) doc: add Feynman upgrade for mainnet
|
||||
* [\#2335](https://github.com/bnb-chain/bsc/pull/2335) upgrade: update system contracts bytes code and hardfork time of Feynman upgrade
|
||||
|
||||
## v1.3.12
|
||||
BUGFIX
|
||||
* [\#2305](https://github.com/bnb-chain/bsc/pull/2305) fix: fix the wrong version number
|
||||
|
||||
## v1.3.11
|
||||
BUGFIX
|
||||
* [\#2288](https://github.com/bnb-chain/bsc/pull/2288) fix: add FeynmanFix upgrade for a testnet issue
|
||||
|
||||
## v1.3.10
|
||||
FEATURE
|
||||
* [\#2047](https://github.com/bnb-chain/bsc/pull/2047) feat: add new fork block and precompile contract for BEP294 and BEP299
|
||||
|
||||
## v1.3.9
|
||||
FEATURE
|
||||
* [\#2186](https://github.com/bnb-chain/bsc/pull/2186) log: support maxBackups in config.toml
|
||||
|
||||
BUGFIX
|
||||
* [\#2160](https://github.com/bnb-chain/bsc/pull/2160) cmd: fix dump cli cannot work in path mode
|
||||
* [\#2183](https://github.com/bnb-chain/bsc/pull/2183) p2p: resolved deadlock on p2p server shutdown
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#2177](https://github.com/bnb-chain/bsc/pull/0000) build(deps): bump github.com/quic-go/quic-go from 0.39.3 to 0.39.4
|
||||
* [\#2185](https://github.com/bnb-chain/bsc/pull/2185) consensus/parlia: set nonce before evm run
|
||||
* [\#2190](https://github.com/bnb-chain/bsc/pull/2190) fix(legacypool): deprecate already known error
|
||||
* [\#2195](https://github.com/bnb-chain/bsc/pull/2195) eth/fetcher: downgrade state tx log
|
||||
|
||||
## v1.3.8
|
||||
FEATURE
|
||||
* [\#2074](https://github.com/bnb-chain/bsc/pull/2074) faucet: new faucet client
|
||||
* [\#2082](https://github.com/bnb-chain/bsc/pull/2082) cmd/dbcmd: add inspect trie tool
|
||||
* [\#2140](https://github.com/bnb-chain/bsc/pull/2140) eth/fetcher: allow underpriced transactions in after timeout
|
||||
* [\#2115](https://github.com/bnb-chain/bsc/pull/2115) p2p: no peer reconnect if explicitly disconnected
|
||||
* [\#2128](https://github.com/bnb-chain/bsc/pull/2128) go.mod: upgrade prysm to support built with go@v1.21
|
||||
* [\#2151](https://github.com/bnb-chain/bsc/pull/2151) feat: enable NoDial should still dial static nodes
|
||||
* [\#2144](https://github.com/bnb-chain/bsc/pull/2144) p2p: reset disconnect set with magic enode ID
|
||||
|
||||
BUGFIX
|
||||
* [\#2095](https://github.com/bnb-chain/bsc/pull/2095) rpc: fix ns/µs mismatch in metrics
|
||||
* [\#2083](https://github.com/bnb-chain/bsc/pull/2083) triedb/pathdb: fix async node buffer diskroot mismatches when journaling
|
||||
* [\#2120](https://github.com/bnb-chain/bsc/pull/2120) ethdb/pebble: cap memory table size as maxMemTableSize-1
|
||||
* [\#2107](https://github.com/bnb-chain/bsc/pull/2107) cmd/geth: fix parse state scheme
|
||||
* [\#2121](https://github.com/bnb-chain/bsc/pull/2121) parlia: fix verifyVoteAttestation when verify a batch of headers
|
||||
* [\#2132](https://github.com/bnb-chain/bsc/pull/2132) core: fix systemcontracts.GenesisHash when run bsc firstly without init
|
||||
* [\#2155](https://github.com/bnb-chain/bsc/pull/2155) cmd, core: resolve scheme from a read-write database and refactor resolveChainFreezerDir func
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#2099](https://github.com/bnb-chain/bsc/pull/2099) params/config: remove useless toml tag for hardforks
|
||||
* [\#2100](https://github.com/bnb-chain/bsc/pull/2100) core/genesis: support chapel to run without geth init
|
||||
* [\#2101](https://github.com/bnb-chain/bsc/pull/2101) core: add metrics for bad block
|
||||
* [\#2109](https://github.com/bnb-chain/bsc/pull/2109) cmd/geth: tidy flags for geth command
|
||||
* [\#1953](https://github.com/bnb-chain/bsc/pull/1953) build(deps): bump github.com/docker/docker
|
||||
* [\#2086](https://github.com/bnb-chain/bsc/pull/2086) build(deps): bump golang.org/x/crypto from 0.12.0 to 0.17.0
|
||||
* [\#2106](https://github.com/bnb-chain/bsc/pull/2106) params: use rialto to test builtin network logic
|
||||
* [\#2098](https://github.com/bnb-chain/bsc/pull/2098) cmd, les, tests: remove light client code
|
||||
* [\#2114](https://github.com/bnb-chain/bsc/pull/2114) p2p: add serve metrics
|
||||
* [\#2123](https://github.com/bnb-chain/bsc/pull/2123) p2p, eth: improve logs
|
||||
* [\#2116](https://github.com/bnb-chain/bsc/pull/2116) tests: revive evm test cases
|
||||
* [\#2161](https://github.com/bnb-chain/bsc/pull/2161) code: remove IsEuler check from worker.go
|
||||
* [\#2167](https://github.com/bnb-chain/bsc/pull/2167) improve: increase SystemTxsGas from 1,500,000 to 5,000,000
|
||||
* [\#2172](https://github.com/bnb-chain/bsc/pull/2172) improve: remove sharedpool from miner
|
||||
* [\#1332](https://github.com/bnb-chain/bsc/pull/1332) core/state: no need to prune block if the same
|
||||
|
||||
## v1.3.7
|
||||
FEATURE
|
||||
* [\#2067](https://github.com/bnb-chain/bsc/pull/2067) cmd/geth: add check func to validate state scheme
|
||||
* [\#2068](https://github.com/bnb-chain/bsc/pull/2068) internal/ethapi: implement eth_getBlockReceipts
|
||||
|
||||
BUGFIX
|
||||
* [\#2035](https://github.com/bnb-chain/bsc/pull/2035) all: pull snap sync PRs from upstream v1.13.5
|
||||
* [\#2072](https://github.com/bnb-chain/bsc/pull/2072) fix: fix the pebble config of level option
|
||||
* [\#2078](https://github.com/bnb-chain/bsc/pull/2078) core: LoadChainConfig return the predefined config for built-in networks firstly
|
||||
|
||||
## v1.3.6
|
||||
FEATURE
|
||||
* [\#2012](https://github.com/bnb-chain/bsc/pull/2012) cmd, core, ethdb: enable Pebble on 32 bits and OpenBSD
|
||||
* [\#2063](https://github.com/bnb-chain/bsc/pull/2063) log: support to disable log rotate by hours
|
||||
* [\#2064](https://github.com/bnb-chain/bsc/pull/2064) log: limit rotateHours in range [0,23]
|
||||
|
||||
BUGFIX
|
||||
* [\#2058](https://github.com/bnb-chain/bsc/pull/2058) params: set default hardfork times
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#2015](https://github.com/bnb-chain/bsc/pull/2015) cmd, core, eth: change default network from ETH to BSC
|
||||
* [\#2036](https://github.com/bnb-chain/bsc/pull/2036) cmd/jsutils: add 2 tools get validator version and block txs number
|
||||
* [\#2037](https://github.com/bnb-chain/bsc/pull/2037) core/txpool/legacypool: respect nolocals-setting
|
||||
* [\#2042](https://github.com/bnb-chain/bsc/pull/2042) core/systemcontracts: update CommitUrl for keplerUpgrade
|
||||
* [\#2043](https://github.com/bnb-chain/bsc/pull/2043) tests/truffle: adapt changes in bsc-genesis-contracts
|
||||
* [\#2051](https://github.com/bnb-chain/bsc/pull/2051) core/vote: wait some blocks before voting since mining begin
|
||||
* [\#2060](https://github.com/bnb-chain/bsc/pull/2060) cmd/utils: allow HTTPHost and WSHost flags precede
|
||||
|
||||
## v1.3.5
|
||||
FEATURE
|
||||
* [\#1970](https://github.com/bnb-chain/bsc/pull/1970) core: enable Shanghai EIPs
|
||||
* [\#1973](https://github.com/bnb-chain/bsc/pull/1973) core/systemcontracts: include BEP-319 on kepler hardfork
|
||||
|
||||
BUGFIX
|
||||
* [\#1964](https://github.com/bnb-chain/bsc/pull/1964) consensus/parlia: hardfork block can be epoch block
|
||||
* [\#1979](https://github.com/bnb-chain/bsc/pull/1979) fix: upgrade pebble and improve config
|
||||
* [\#1980](https://github.com/bnb-chain/bsc/pull/1980) internal/ethapi: fix null effectiveGasPrice in GetTransactionReceipt
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#1977](https://github.com/bnb-chain/bsc/pull/1977) doc: add instructions for starting fullnode with pbss
|
||||
|
||||
## v1.3.4
|
||||
BUGFIX
|
||||
* fix: remove pipecommit in miner
|
||||
* add a hard fork: Hertzfix
|
||||
|
||||
## v1.3.3
|
||||
IMPROVEMENT
|
||||
* [\#2000](https://github.com/bnb-chain/bsc/pull/2000) cmd/utils: exit process if txlookuplimit flag is set
|
||||
|
||||
BUGFIX
|
||||
* [\#1986](https://github.com/bnb-chain/bsc/pull/1986) fix(cmd): check pruneancient when creating db
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#2000](https://github.com/bnb-chain/bsc/pull/2000) cmd/utils: exit process if txlookuplimit flag is set
|
||||
|
||||
## v1.3.2
|
||||
BUGFIX
|
||||
* fix: remove sharedPool
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#2007](https://github.com/bnb-chain/bsc/pull/2007) consensus/parlia: increase size of snapshot cache in parlia
|
||||
* [\#2008](https://github.com/bnb-chain/bsc/pull/2008) consensus/parlia: recover faster when snapshot of parlia is gone in disk
|
||||
|
||||
## v1.3.1
|
||||
FEATURE
|
||||
* [\#1881](https://github.com/bnb-chain/bsc/pull/1881) feat: active pbss
|
||||
|
||||
@@ -4,7 +4,7 @@ ARG VERSION=""
|
||||
ARG BUILDNUM=""
|
||||
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.20-alpine as builder
|
||||
FROM golang:1.21-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make cmake gcc musl-dev linux-headers git bash build-base libc-dev
|
||||
# Get dependencies - will also be cached if we won't change go.mod/go.sum
|
||||
|
||||
@@ -4,7 +4,7 @@ ARG VERSION=""
|
||||
ARG BUILDNUM=""
|
||||
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.20-alpine as builder
|
||||
FROM golang:1.21-alpine as builder
|
||||
|
||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||
# Get dependencies - will also be cached if we won't change go.mod/go.sum
|
||||
|
||||
18
README.md
18
README.md
@@ -61,7 +61,7 @@ Many of the below are the same as or similar to go-ethereum.
|
||||
|
||||
For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth).
|
||||
|
||||
Building `geth` requires both a Go (version 1.20 or later) and a C compiler (GCC 5 or higher). You can install
|
||||
Building `geth` requires both a Go (version 1.21 or later) and a C compiler (GCC 5 or higher). You can install
|
||||
them using your favourite package manager. Once the dependencies are installed, run
|
||||
|
||||
```shell
|
||||
@@ -110,15 +110,15 @@ on how you can run your own `geth` instance.
|
||||
|
||||
The hardware must meet certain requirements to run a full node on mainnet:
|
||||
- VPS running recent versions of Mac OS X, Linux, or Windows.
|
||||
- IMPORTANT 2.5 TB(May 2023) of free disk space, solid-state drive(SSD), gp3, 8k IOPS, 250 MB/S throughput, read latency <1ms. (if node is started with snap sync, it will need NVMe SSD)
|
||||
- IMPORTANT 3 TB(Dec 2023) of free disk space, solid-state drive(SSD), gp3, 8k IOPS, 500 MB/S throughput, read latency <1ms. (if node is started with snap sync, it will need NVMe SSD)
|
||||
- 16 cores of CPU and 64 GB of memory (RAM)
|
||||
- Suggest m5zn.3xlarge instance type on AWS, c2-standard-16 on Google cloud.
|
||||
- Suggest m5zn.6xlarge or r7iz.4xlarge instance type on AWS, c2-standard-16 on Google cloud.
|
||||
- A broadband Internet connection with upload/download speeds of 5 MB/S
|
||||
|
||||
The requirement for testnet:
|
||||
- VPS running recent versions of Mac OS X, Linux, or Windows.
|
||||
- 500G of storage for testnet.
|
||||
- 4 cores of CPU and 8 gigabytes of memory (RAM).
|
||||
- 4 cores of CPU and 16 gigabytes of memory (RAM).
|
||||
|
||||
### Steps to Run a Fullnode
|
||||
|
||||
@@ -149,15 +149,21 @@ unzip testnet.zip
|
||||
#### 3. Download snapshot
|
||||
Download latest chaindata snapshot from [here](https://github.com/bnb-chain/bsc-snapshots). Follow the guide to structure your files.
|
||||
|
||||
Note: if you can not download the chaindata snapshot and want to sync from genesis, you have to generate the genesis block first, you have already get the genesis.json in Step 2.
|
||||
So just run: `geth --datadir <datadir> init ./genesis.json`
|
||||
Note: If you encounter difficulties downloading the chaindata snapshot and prefer to synchronize from the genesis block on the Chapel testnet, remember to include the additional flag `--chapel` when initially launching Geth.
|
||||
|
||||
#### 4. Start a full node
|
||||
```shell
|
||||
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0
|
||||
|
||||
## It is recommand to run fullnode with `--tries-verify-mode none` if you want high performance and care little about state consistency
|
||||
## It will run with Hash-Base Storage Scheme by default
|
||||
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0 --tries-verify-mode none
|
||||
|
||||
## It runs fullnode with Path-Base Storage Scheme.
|
||||
## It will enable inline state prune, keeping the latest 90000 blocks' history state by default.
|
||||
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0 --tries-verify-mode none --state.scheme path
|
||||
```
|
||||
|
||||
#### 5. Monitor node status
|
||||
|
||||
Monitor the log from **./node/bsc.log** by default. When the node has started syncing, should be able to see the following output:
|
||||
|
||||
@@ -94,7 +94,7 @@ func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.Genesis
|
||||
|
||||
filterBackend := &filterBackend{database, blockchain, backend}
|
||||
backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
|
||||
backend.events = filters.NewEventSystem(backend.filterSystem, false)
|
||||
backend.events = filters.NewEventSystem(backend.filterSystem)
|
||||
|
||||
header := backend.blockchain.CurrentBlock()
|
||||
block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
|
||||
|
||||
@@ -2127,7 +2127,7 @@ func TestGolangBindings(t *testing.T) {
|
||||
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
|
||||
}
|
||||
|
||||
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.15") // Repo root
|
||||
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.16") // Repo root
|
||||
replacer.Dir = pkg
|
||||
if out, err := replacer.CombinedOutput(); err != nil {
|
||||
t.Fatalf("failed to replace tendermint dependency to bnb-chain source: %v\n%s", err, out)
|
||||
@@ -2145,7 +2145,7 @@ func TestGolangBindings(t *testing.T) {
|
||||
t.Fatalf("failed to replace cometbft dependency to bnb-chain source: %v\n%s", err, out)
|
||||
}
|
||||
|
||||
tidier := exec.Command(gocmd, "mod", "tidy", "-compat=1.20")
|
||||
tidier := exec.Command(gocmd, "mod", "tidy", "-compat=1.21")
|
||||
tidier.Dir = pkg
|
||||
if out, err := tidier.CombinedOutput(); err != nil {
|
||||
t.Fatalf("failed to tidy Go module file: %v\n%s", err, out)
|
||||
|
||||
@@ -72,11 +72,11 @@ func NewSecureChannelSession(card *pcsc.Card, keyData []byte) (*SecureChannelSes
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not unmarshal public key from card: %v", err)
|
||||
}
|
||||
secret, _ := key.Curve.ScalarMult(cardPublic.X, cardPublic.Y, key.D.Bytes())
|
||||
secret, _ := key.Curve.ScalarMult(cardPublic.X, cardPublic.Y, key.D.Bytes()) //nolint:all //TODO
|
||||
return &SecureChannelSession{
|
||||
card: card,
|
||||
secret: secret.Bytes(),
|
||||
publicKey: elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y),
|
||||
publicKey: elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y), //nolint:all //TODO
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,69 +1,60 @@
|
||||
# This file contains sha256 checksums of optional build dependencies.
|
||||
|
||||
2c5ee9c9ec1e733b0dbbc2bdfed3f62306e51d8172bf38f4f4e542b27520f597 go1.20.7.src.tar.gz
|
||||
785170eab380a8985d53896808b0a71336d0ea60e0a26099b4ccec77798b1cf4 go1.20.7.darwin-amd64.tar.gz
|
||||
eea1e7e4c2f75c72629050e6a6c7c46c446d64056732a7787fb3ba16ace1982e go1.20.7.darwin-arm64.tar.gz
|
||||
d8cff0357ac24eb06f3f280535397eeaacf95611d29f9b2abc3060f3d6dce3b4 go1.20.7.freebsd-386.tar.gz
|
||||
26918dcebf474a9e81ccf9f648cdf36968dfb76b481518cf615d78455dda4416 go1.20.7.freebsd-amd64.tar.gz
|
||||
ddb48145f05bda2f4617a22c979d4e94b22802cdb1a1fde1b1974e733b26f091 go1.20.7.linux-386.tar.gz
|
||||
f0a87f1bcae91c4b69f8dc2bc6d7e6bfcd7524fceec130af525058c0c17b1b44 go1.20.7.linux-amd64.tar.gz
|
||||
44781ae3b153c3b07651d93b6bc554e835a36e2d72a696281c1e4dad9efffe43 go1.20.7.linux-arm64.tar.gz
|
||||
7cc231b415b94f2f7065870a73f67dd2b0ec12b5a98052b7ee0121c42bc04f8d go1.20.7.linux-armv6l.tar.gz
|
||||
6318a1db307c12b8afe68808bd6fae4fba1e558a85b958216096869ed506dcb3 go1.20.7.linux-ppc64le.tar.gz
|
||||
26aea2ede8722ceecbd9db883328a8d963136fd96c11dacc356c44c4c19c6515 go1.20.7.linux-s390x.tar.gz
|
||||
5b0ef6f58d3e04d6cc003aa98e9172f41ba9e091b1c98e7339b41c4c87fb78a1 go1.20.7.windows-386.zip
|
||||
736dc6c7fcab1c96b682c8c93e38d7e371e62a17d34cb2c37d451a1147f66af9 go1.20.7.windows-amd64.zip
|
||||
fc6f79c1e1ed9e506c65f2112ac4e387479916f1accb0d046a6a19ff6938baa5 go1.20.7.windows-arm64.zip
|
||||
# version:golang 1.21.5
|
||||
# https://go.dev/dl/
|
||||
285cbbdf4b6e6e62ed58f370f3f6d8c30825d6e56c5853c66d3c23bcdb09db19 go1.21.5.src.tar.gz
|
||||
a2e1d5743e896e5fe1e7d96479c0a769254aed18cf216cf8f4c3a2300a9b3923 go1.21.5.darwin-amd64.tar.gz
|
||||
d0f8ac0c4fb3efc223a833010901d02954e3923cfe2c9a2ff0e4254a777cc9cc go1.21.5.darwin-arm64.tar.gz
|
||||
2c05bbe0dc62456b90b7ddd354a54f373b7c377a98f8b22f52ab694b4f6cca58 go1.21.5.freebsd-386.tar.gz
|
||||
30b6c64e9a77129605bc12f836422bf09eec577a8c899ee46130aeff81567003 go1.21.5.freebsd-amd64.tar.gz
|
||||
8f4dba9cf5c61757bbd7e9ebdb93b6a30a1b03f4a636a1ba0cc2f27b907ab8e1 go1.21.5.linux-386.tar.gz
|
||||
e2bc0b3e4b64111ec117295c088bde5f00eeed1567999ff77bc859d7df70078e go1.21.5.linux-amd64.tar.gz
|
||||
841cced7ecda9b2014f139f5bab5ae31785f35399f236b8b3e75dff2a2978d96 go1.21.5.linux-arm64.tar.gz
|
||||
837f4bf4e22fcdf920ffeaa4abf3d02d1314e03725431065f4d44c46a01b42fe go1.21.5.linux-armv6l.tar.gz
|
||||
907b8c6ec4be9b184952e5d3493be66b1746442394a8bc78556c56834cd7c38b go1.21.5.linux-ppc64le.tar.gz
|
||||
9c4a81b72ebe44368813cd03684e1080a818bf915d84163abae2ed325a1b2dc0 go1.21.5.linux-s390x.tar.gz
|
||||
6da2418889dfb37763d0eb149c4a8d728c029e12f0cd54fbca0a31ae547e2d34 go1.21.5.windows-386.zip
|
||||
bbe603cde7c9dee658f45164b4d06de1eff6e6e6b800100824e7c00d56a9a92f go1.21.5.windows-amd64.zip
|
||||
9b7acca50e674294e43202df4fbc26d5af4d8bc3170a3342a1514f09a2dab5e9 go1.21.5.windows-arm64.zip
|
||||
|
||||
000d4d58f1e25323aaf0da20b337d059d401c8c1fb31cef92ce50ef35c05e877 golangci-lint-1.52.2-linux-ppc64le.deb
|
||||
0970b2e3ecc20003a0fc78b078623ab27c61f0f809a44288e2cc438bfbbf5616 golangci-lint-1.52.2-linux-s390x.deb
|
||||
0bfe9b51f68a33cc4e43139151d8032b57b15e61a19f5a7554b687a3fa166ab8 golangci-lint-1.52.2-netbsd-armv7.tar.gz
|
||||
0e4e24085d364f4e03752c060d5f37b5ead52acd62f07392f4c9022515e0ecd8 golangci-lint-1.52.2-linux-armv7.rpm
|
||||
0f19ad6c037d45867f4978287a7a6d78bc761daf8e6cb3a5e6af86d5714b0258 golangci-lint-1.52.2-linux-armv6.tar.gz
|
||||
1506b19f3f0410f6d85d1e339a47fcc84646d552516c0f429dc8cd7f34b4069a golangci-lint-1.52.2-windows-armv6.zip
|
||||
1cc68baa226e186c15c5514a6e93b1cc8d47ff06aaf1a395b8266434cb01df29 golangci-lint-1.52.2-linux-386.rpm
|
||||
1d23661087ae686563e40d3b1e33f309dd3b4ba7d1c7e571ca7723f77a52a9e4 golangci-lint-1.52.2-linux-s390x.rpm
|
||||
227673a18d21b428f1768bb8ee46e38c36a0f002960bc6211ef6137b85d03f52 golangci-lint-1.52.2-freebsd-armv7.tar.gz
|
||||
24f0272e5741c05c59e7162b7ff0258cfa6beb0d9265bd87c386fe80ac25135d golangci-lint-1.52.2-linux-mips64.deb
|
||||
3abc8ad30b336ccbe3c5e3c65fa146f5b12d8e81e644345fa8d51cdbaa8cb570 golangci-lint-1.52.2-netbsd-amd64.tar.gz
|
||||
40a2645b4c7bd94c16618eb0f12b32cd54c17e5620f761cf477b256d3622f299 golangci-lint-1.52.2-windows-386.zip
|
||||
40b40002e07db81628d94108265525052c58fc9ce358bef26a36d27f0aea3d87 golangci-lint-1.52.2-windows-amd64.zip
|
||||
41e936b62ba4fc66c02daf6fa9cf74213bc2220745c7a796acbe197c05ed26bb golangci-lint-1.52.2-netbsd-armv6.tar.gz
|
||||
4bcbb4cf34bf3c8ae1ca880d12516a999499189326621599f8362ededd6e4229 golangci-lint-1.52.2-linux-riscv64.tar.gz
|
||||
4edb83f1433f7c57f06f79a7fc30bf3f920c1f86c334e481661ac6627d80293f golangci-lint-1.52.2-linux-arm64.deb
|
||||
50d662e86d094dbad6634d086eca4f670ffa8ea7142508d8da357a2d750ac21a golangci-lint-1.52.2-linux-armv7.tar.gz
|
||||
6891597bedbcd7e530d08ed198bab7eeb9b23f3f8161dc6e87505b783cb11593 golangci-lint-1.52.2-windows-arm64.zip
|
||||
6d79f4f3448b70e83952e746fcb9e251c6ba94ec2790a912806cc1704ade4d64 golangci-lint-1.52.2-linux-mips64.rpm
|
||||
6de51ae05d39002421caf6049e0dd0014a2f10961471c5547c905d33d8e6adf1 golangci-lint-1.52.2-linux-armv6.deb
|
||||
715dc0f0cf3538c3b2c75f084dde8dcdc3485b3494f42a6d0d9c0dc61e62b5a8 golangci-lint-1.52.2-linux-s390x.tar.gz
|
||||
7c559332a97ee49b80427aba5a7122e17cac18c57e700f48e6db5ffcbbb61b2b golangci-lint-1.52.2-linux-arm64.rpm
|
||||
81201bb5f19897fefb4380af2e187a0133dc5efda22254698c063cc36a601f43 golangci-lint-1.52.2-linux-386.deb
|
||||
89e523d45883903cfc472ab65621073f850abd4ffbb7720bbdd7ba66ee490bc8 golangci-lint-1.52.2-darwin-arm64.tar.gz
|
||||
8d60d63eee38f8de679e57b1a781de32987152f004f852f20cd47baa4c582209 golangci-lint-1.52.2-linux-mips64le.rpm
|
||||
9e22df0516cbd847910f353d92245e58eab2b6edacc669646bfa06eb032a65a3 golangci-lint-1.52.2-linux-riscv64.deb
|
||||
a1a74747a196d4ccd2394ea8a461508eb2edf1eb5a88010611debf572991961d golangci-lint-1.52.2-linux-loong64.tar.gz
|
||||
a7f076d0fb50e0f5bc24d0f3b2567f2cfe864441e6ad20323189b7fde7cc065d golangci-lint-1.52.2-freebsd-386.tar.gz
|
||||
abc100851a59cbcea2a7e9ff5ad2974a43270135520aeac9a302ca6c712a41e1 golangci-lint-1.52.2-linux-loong64.rpm
|
||||
adf11a1f7f43b5a431c19cccea260e6205e2e2b42a2d2d450e31c287fec199f2 golangci-lint-1.52.2-linux-amd64.rpm
|
||||
b2249e43e1624486398f41700dbe4094a4222bf50b2b1b3a740323adb9a1b66f golangci-lint-1.52.2-linux-386.tar.gz
|
||||
b8e81bf979dc8bf226cb592eb78c1792f1018c3dea1bbeb11517efc4cc3301bb golangci-lint-1.52.2-windows-armv7.zip
|
||||
bb9a6a0aabe39fb3d581cc200c639ce6598821a53b4d16ec59366c65f4cc2960 golangci-lint-1.52.2-source.tar.gz
|
||||
c152280b2e61c202614c1c476cf4458922cda0d2781e4492be2c22d45655cae0 golangci-lint-1.52.2-freebsd-armv6.tar.gz
|
||||
c8bf25c0bca142638ce4bfc921bf23d23038818d57658d69aa4a9947d514d48f golangci-lint-1.52.2-linux-ppc64le.rpm
|
||||
c9cf72d12058a131746edd409ed94ccd578fbd178899d1ed41ceae3ce5f54501 golangci-lint-1.52.2-linux-amd64.tar.gz
|
||||
d03f2b331b5139eddea5db2b49066d10a90094747b08d72d7b2d61cf91c79a27 golangci-lint-1.52.2-linux-mips64le.tar.gz
|
||||
d609c1d49591d714148e1f8c8b5ae9f9565c601aeabc44a5a53ba44b0eb99f36 golangci-lint-1.52.2-linux-riscv64.rpm
|
||||
d679adad29603ed7549372b64077cccad784e404deffe5c1e9495a06659cff33 golangci-lint-1.52.2-linux-mips64.tar.gz
|
||||
d91e8cb60920cf0e46958ed917fcdd059738c00d162189c2e878424ffc8ada75 golangci-lint-1.52.2-linux-ppc64le.tar.gz
|
||||
d9b5820b491e317fb1360775441d68bd3dc2f303439da5b6d536df23977e28c9 golangci-lint-1.52.2-freebsd-amd64.tar.gz
|
||||
ddeae781cf07c016898efd80eaed6853a91bfaf1f22c08fbbf5cf08a573b98c4 golangci-lint-1.52.2-linux-loong64.deb
|
||||
dfc5e755cfa95381f61f736780ff736a5b6c9cbccc88140348986c166d484f85 golangci-lint-1.52.2-linux-amd64.deb
|
||||
e57f2599de73c4da1d36d5255b9baec63f448b3d7fb726ebd3cd64dabbd3ee4a golangci-lint-1.52.2-darwin-amd64.tar.gz
|
||||
ebfb5b643ba73ef6007236b90f863ae49fc34fd366682c971b7d1308ab28f642 golangci-lint-1.52.2-netbsd-386.tar.gz
|
||||
f46b60a90fab5916a7de899ad9a3a4b3d77278c2e1737d070719d3ea27919557 golangci-lint-1.52.2-linux-armv7.deb
|
||||
f6e39d0ac4691c2b9f49d6d5819594f48bb03e18692fd6d100e7114077f710e6 golangci-lint-1.52.2-linux-armv6.rpm
|
||||
fa5da589075143628a49a0c123ccd76a8717bb6308fb3bdb6bf1df59435d921b golangci-lint-1.52.2-linux-mips64le.deb
|
||||
fc09a97f8888809fab83a316f7da70c8ed74d4863b7eed7d872cec41911a55e8 golangci-lint-1.52.2-linux-arm64.tar.gz
|
||||
# version:golangci 1.55.2
|
||||
# https://github.com/golangci/golangci-lint/releases/
|
||||
# https://github.com/golangci/golangci-lint/releases/download/v1.55.2/
|
||||
632e96e6d5294fbbe7b2c410a49c8fa01c60712a0af85a567de85bcc1623ea21 golangci-lint-1.55.2-darwin-amd64.tar.gz
|
||||
234463f059249f82045824afdcdd5db5682d0593052f58f6a3039a0a1c3899f6 golangci-lint-1.55.2-darwin-arm64.tar.gz
|
||||
2bdd105e2d4e003a9058c33a22bb191a1e0f30fa0790acca0d8fbffac1d6247c golangci-lint-1.55.2-freebsd-386.tar.gz
|
||||
e75056e8b082386676ce23eba455cf893931a792c0d87e1e3743c0aec33c7fb5 golangci-lint-1.55.2-freebsd-amd64.tar.gz
|
||||
5789b933facaf6136bd23f1d50add67b79bbcf8dfdfc9069a37f729395940a66 golangci-lint-1.55.2-freebsd-armv6.tar.gz
|
||||
7f21ab1008d05f32c954f99470fc86a83a059e530fe2add1d0b7d8ed4d8992a7 golangci-lint-1.55.2-freebsd-armv7.tar.gz
|
||||
33ab06139b9219a28251f10821da94423db30285cc2af97494cbb2a281927de9 golangci-lint-1.55.2-illumos-amd64.tar.gz
|
||||
57ce6f8ce3ad6ee45d7cc3d9a047545a851c2547637834a3fcb086c7b40b1e6b golangci-lint-1.55.2-linux-386.tar.gz
|
||||
ca21c961a33be3bc15e4292dc40c98c8dcc5463a7b6768a3afc123761630c09c golangci-lint-1.55.2-linux-amd64.tar.gz
|
||||
8eb0cee9b1dbf0eaa49871798c7f8a5b35f2960c52d776a5f31eb7d886b92746 golangci-lint-1.55.2-linux-arm64.tar.gz
|
||||
3195f3e0f37d353fd5bd415cabcd4e263f5c29d3d0ffb176c26ff3d2c75eb3bb golangci-lint-1.55.2-linux-armv6.tar.gz
|
||||
c823ee36eb1a719e171de1f2f5ca3068033dce8d9817232fd10ed71fd6650406 golangci-lint-1.55.2-linux-armv7.tar.gz
|
||||
758a5d2a356dc494bd13ed4c0d4bf5a54a4dc91267ea5ecdd87b86c7ca0624e7 golangci-lint-1.55.2-linux-loong64.tar.gz
|
||||
2c7b9abdce7cae802a67d583cd7c6dca520bff6d0e17c8535a918e2f2b437aa0 golangci-lint-1.55.2-linux-mips64.tar.gz
|
||||
024e0a15b85352cc27271285526e16a4ab66d3e67afbbe446c9808c06cb8dbed golangci-lint-1.55.2-linux-mips64le.tar.gz
|
||||
6b00f89ba5506c1de1efdd9fa17c54093013a294fefd8b9b31534db626a672ee golangci-lint-1.55.2-linux-ppc64le.tar.gz
|
||||
0faa0d047d9bf7b703ed3ea65b6117043c93504f9ca1de25ae929d3901c73d4a golangci-lint-1.55.2-linux-riscv64.tar.gz
|
||||
30dec9b22e7d5bb4e9d5ccea96da20f71cd7db3c8cf30b8ddc7cb9174c4d742a golangci-lint-1.55.2-linux-s390x.tar.gz
|
||||
5a0ede48f79ad707902fdb29be8cd2abd8302dc122b65ebae3fdfc86751c7698 golangci-lint-1.55.2-netbsd-386.tar.gz
|
||||
95af20a2e617126dd5b08122ece7819101070e1582a961067ce8c41172f901ad golangci-lint-1.55.2-netbsd-amd64.tar.gz
|
||||
94fb7dacb7527847cc95d7120904e19a2a0a81a0d50d61766c9e0251da72ab9d golangci-lint-1.55.2-netbsd-armv6.tar.gz
|
||||
ca906bce5fee9619400e4a321c56476fe4a4efb6ac4fc989d340eb5563348873 golangci-lint-1.55.2-netbsd-armv7.tar.gz
|
||||
45b442f69fc8915c4500201c0247b7f3f69544dbc9165403a61f9095f2c57355 golangci-lint-1.55.2-windows-386.zip
|
||||
f57d434d231d43417dfa631587522f8c1991220b43c8ffadb9c7bd279508bf81 golangci-lint-1.55.2-windows-amd64.zip
|
||||
fd7dc8f4c6829ee6fafb252a4d81d2155cd35da7833665cbb25d53ce7cecd990 golangci-lint-1.55.2-windows-arm64.zip
|
||||
1892c3c24f9e7ef44b02f6750c703864b6dc350129f3ec39510300007b2376f1 golangci-lint-1.55.2-windows-armv6.zip
|
||||
a5e68ae73d38748b5269fad36ac7575e3c162a5dc63ef58abdea03cc5da4522a golangci-lint-1.55.2-windows-armv7.zip
|
||||
|
||||
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
|
||||
d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz
|
||||
#
|
||||
# This version is fine to be old and full of security holes, we just use it
|
||||
# to build the latest Go. Don't change it. If it ever becomes insufficient,
|
||||
# we need to switch over to a recursive builder to jump across supported
|
||||
# versions.
|
||||
#
|
||||
# version:ppa-builder 1.19.6
|
||||
# https://go.dev/dl/
|
||||
d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz
|
||||
@@ -139,7 +139,7 @@ var (
|
||||
// This is the version of Go that will be downloaded by
|
||||
//
|
||||
// go run ci.go install -dlgo
|
||||
dlgoVersion = "1.20.7"
|
||||
dlgoVersion = "1.21.5"
|
||||
|
||||
// This is the version of Go that will be used to bootstrap the PPA builder.
|
||||
//
|
||||
@@ -360,7 +360,7 @@ func doLint(cmdline []string) {
|
||||
|
||||
// downloadLinter downloads and unpacks golangci-lint.
|
||||
func downloadLinter(cachedir string) string {
|
||||
const version = "1.52.2"
|
||||
const version = "1.55.2"
|
||||
|
||||
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||
arch := runtime.GOARCH
|
||||
|
||||
@@ -1206,7 +1206,7 @@ func GenDoc(ctx *cli.Context) error {
|
||||
URL: accounts.URL{Path: ".. ignored .."},
|
||||
},
|
||||
{
|
||||
Address: common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff"),
|
||||
Address: common.MaxAddress,
|
||||
},
|
||||
}})
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ set to standard output. The following filters are supported:
|
||||
- `-limit <N>` limits the output set to N entries, taking the top N nodes by score
|
||||
- `-ip <CIDR>` filters nodes by IP subnet
|
||||
- `-min-age <duration>` filters nodes by 'first seen' time
|
||||
- `-eth-network <mainnet/goerli/sepolia>` filters nodes by "eth" ENR entry
|
||||
- `-eth-network <mainnet/goerli/sepolia/holesky>` filters nodes by "eth" ENR entry
|
||||
- `-les-server` filters nodes by LES server support
|
||||
- `-snap` filters nodes by snap protocol support
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth/protocols/snap"
|
||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||
"github.com/ethereum/go-ethereum/light"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
@@ -58,7 +58,7 @@ type accRangeTest struct {
|
||||
func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
|
||||
var (
|
||||
root = s.chain.RootAt(999)
|
||||
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||
ffHash = common.MaxHash
|
||||
zero = common.Hash{}
|
||||
firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29")
|
||||
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
|
||||
@@ -125,7 +125,7 @@ type stRangesTest struct {
|
||||
// TestSnapGetStorageRanges various forms of GetStorageRanges requests.
|
||||
func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) {
|
||||
var (
|
||||
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||
ffHash = common.MaxHash
|
||||
zero = common.Hash{}
|
||||
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
|
||||
secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
|
||||
@@ -530,11 +530,11 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
|
||||
for i, key := range hashes {
|
||||
keys[i] = common.CopyBytes(key[:])
|
||||
}
|
||||
nodes := make(light.NodeList, len(proof))
|
||||
nodes := make(trienode.ProofList, len(proof))
|
||||
for i, node := range proof {
|
||||
nodes[i] = node
|
||||
}
|
||||
proofdb := nodes.NodeSet()
|
||||
proofdb := nodes.Set()
|
||||
|
||||
var end []byte
|
||||
if len(keys) > 0 {
|
||||
|
||||
@@ -11,10 +11,7 @@ The `faucet` is a single binary app (everything included) with all configuration
|
||||
First things first, the `faucet` needs to connect to an Ethereum network, for which it needs the necessary genesis and network infos. Each of the following flags must be set:
|
||||
|
||||
- `-genesis` is a path to a file containing the network `genesis.json`. or using:
|
||||
- `-network` is the devp2p network id used during connection
|
||||
- `-bootnodes` is a list of `enode://` ids to join the network through
|
||||
|
||||
The `faucet` will use the `les` protocol to join the configured Ethereum network and will store its data in `$HOME/.faucet` (currently not configurable).
|
||||
- `-ws` is ws endpoint to what faucet will connect to
|
||||
|
||||
## Funding
|
||||
|
||||
|
||||
@@ -42,21 +42,11 @@ import (
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/ethstats"
|
||||
"github.com/ethereum/go-ethereum/internal/version"
|
||||
"github.com/ethereum/go-ethereum/les"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
@@ -64,10 +54,7 @@ import (
|
||||
var (
|
||||
genesisFlag = flag.String("genesis", "", "Genesis json file to seed the chain with")
|
||||
apiPortFlag = flag.Int("apiport", 8080, "Listener port for the HTTP API connection")
|
||||
ethPortFlag = flag.Int("ethport", 30303, "Listener port for the devp2p connection")
|
||||
bootFlag = flag.String("bootnodes", "", "Comma separated bootnode enode URLs to seed with")
|
||||
netFlag = flag.Uint64("network", 0, "Network ID to use for the Ethereum protocol")
|
||||
statsFlag = flag.String("ethstats", "", "Ethstats network monitoring auth string")
|
||||
wsEndpoint = flag.String("ws", "http://127.0.0.1:7777/", "Url to ws endpoint")
|
||||
|
||||
netnameFlag = flag.String("faucet.name", "", "Network name to assign to the faucet")
|
||||
payoutFlag = flag.Int("faucet.amount", 1, "Number of Ethers to pay out per user request")
|
||||
@@ -163,15 +150,6 @@ func main() {
|
||||
if err != nil {
|
||||
log.Crit("Failed to read genesis block contents", "genesis", *genesisFlag, "err", err)
|
||||
}
|
||||
// Convert the bootnodes to internal enode representations
|
||||
var enodes []*enode.Node
|
||||
for _, boot := range strings.Split(*bootFlag, ",") {
|
||||
if url, err := enode.Parse(enode.ValidSchemes, boot); err == nil {
|
||||
enodes = append(enodes, url)
|
||||
} else {
|
||||
log.Error("Failed to parse bootnode URL", "url", boot, "err", err)
|
||||
}
|
||||
}
|
||||
// Load up the account key and decrypt its password
|
||||
blob, err := os.ReadFile(*accPassFlag)
|
||||
if err != nil {
|
||||
@@ -191,7 +169,7 @@ func main() {
|
||||
log.Crit("Failed to unlock faucet signer account", "err", err)
|
||||
}
|
||||
// Assemble and start the faucet light service
|
||||
faucet, err := newFaucet(genesis, *ethPortFlag, enodes, *netFlag, *statsFlag, ks, website.Bytes(), bep2eInfos)
|
||||
faucet, err := newFaucet(genesis, *wsEndpoint, ks, website.Bytes(), bep2eInfos)
|
||||
if err != nil {
|
||||
log.Crit("Failed to start faucet", "err", err)
|
||||
}
|
||||
@@ -219,7 +197,6 @@ type bep2eInfo struct {
|
||||
// faucet represents a crypto faucet backed by an Ethereum light client.
|
||||
type faucet struct {
|
||||
config *params.ChainConfig // Chain configurations for signing
|
||||
stack *node.Node // Ethereum protocol stack
|
||||
client *ethclient.Client // Client connection to the Ethereum chain
|
||||
index []byte // Index page to serve up on the web
|
||||
|
||||
@@ -248,65 +225,18 @@ type wsConn struct {
|
||||
wlock sync.Mutex
|
||||
}
|
||||
|
||||
func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) {
|
||||
// Assemble the raw devp2p protocol stack
|
||||
git, _ := version.VCS()
|
||||
stack, err := node.New(&node.Config{
|
||||
Name: "geth",
|
||||
Version: params.VersionWithCommit(git.Commit, git.Date),
|
||||
DataDir: filepath.Join(os.Getenv("HOME"), ".faucet"),
|
||||
NoUSB: true,
|
||||
P2P: p2p.Config{
|
||||
NAT: nat.Any(),
|
||||
NoDiscovery: true,
|
||||
DiscoveryV5: true,
|
||||
ListenAddr: fmt.Sprintf(":%d", port),
|
||||
MaxPeers: 25,
|
||||
BootstrapNodesV5: enodes,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func newFaucet(genesis *core.Genesis, url string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) {
|
||||
bep2eAbi, err := abi.JSON(strings.NewReader(bep2eAbiJson))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Assemble the Ethereum light client protocol
|
||||
cfg := ethconfig.Defaults
|
||||
cfg.SyncMode = downloader.LightSync
|
||||
cfg.NetworkId = network
|
||||
cfg.Genesis = genesis
|
||||
utils.SetDNSDiscoveryDefaults(&cfg, genesis.ToBlock().Hash())
|
||||
|
||||
lesBackend, err := les.New(stack, &cfg)
|
||||
client, err := ethclient.Dial(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to register the Ethereum service: %w", err)
|
||||
}
|
||||
|
||||
// Assemble the ethstats monitoring and reporting service'
|
||||
if stats != "" {
|
||||
if err := ethstats.New(stack, lesBackend.ApiBackend, lesBackend.Engine(), stats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Boot up the client and ensure it connects to bootnodes
|
||||
if err := stack.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, boot := range enodes {
|
||||
old, err := enode.Parse(enode.ValidSchemes, boot.String())
|
||||
if err == nil {
|
||||
stack.Server().AddPeer(old)
|
||||
}
|
||||
}
|
||||
// Attach to the client and retrieve and interesting metadatas
|
||||
api := stack.Attach()
|
||||
client := ethclient.NewClient(api)
|
||||
|
||||
return &faucet{
|
||||
config: genesis.Config,
|
||||
stack: stack,
|
||||
client: client,
|
||||
index: index,
|
||||
keystore: ks,
|
||||
@@ -319,8 +249,8 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network ui
|
||||
}
|
||||
|
||||
// close terminates the Ethereum connection and tears down the faucet.
|
||||
func (f *faucet) close() error {
|
||||
return f.stack.Close()
|
||||
func (f *faucet) close() {
|
||||
f.client.Close()
|
||||
}
|
||||
|
||||
// listenAndServe registers the HTTP handlers for the faucet and boots it up
|
||||
@@ -342,7 +272,7 @@ func (f *faucet) webHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// apiHandler handles requests for Ether grants and transaction statuses.
|
||||
func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
upgrader := websocket.Upgrader{}
|
||||
upgrader := websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -406,7 +336,6 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if err = send(wsconn, map[string]interface{}{
|
||||
"funds": new(big.Int).Div(balance, ether),
|
||||
"funded": nonce,
|
||||
"peers": f.stack.Server().PeerCount(),
|
||||
"requests": reqs,
|
||||
}, 3*time.Second); err != nil {
|
||||
log.Warn("Failed to send initial stats to client", "err", err)
|
||||
@@ -694,13 +623,11 @@ func (f *faucet) loop() {
|
||||
log.Info("Updated faucet state", "number", head.Number, "hash", head.Hash(), "age", common.PrettyAge(timestamp), "balance", f.balance, "nonce", f.nonce, "price", f.price)
|
||||
|
||||
balance := new(big.Int).Div(f.balance, ether)
|
||||
peers := f.stack.Server().PeerCount()
|
||||
|
||||
for _, conn := range f.conns {
|
||||
if err := send(conn, map[string]interface{}{
|
||||
"funds": balance,
|
||||
"funded": f.nonce,
|
||||
"peers": peers,
|
||||
"requests": f.reqs,
|
||||
}, time.Second); err != nil {
|
||||
log.Warn("Failed to send stats to client", "err", err)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -14,7 +15,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v4/io/prompt"
|
||||
"github.com/prysmaticlabs/prysm/v4/proto/eth/service"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/petnames"
|
||||
@@ -26,6 +27,8 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
"github.com/ethereum/go-ethereum/signer/core"
|
||||
)
|
||||
|
||||
@@ -35,19 +38,20 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
au = aurora.NewAurora(true)
|
||||
privateKeyFlag = &cli.StringFlag{
|
||||
Name: "private-key",
|
||||
Usage: "Hex string for the BLS12-381 private key you wish encrypt into a keystore file",
|
||||
Value: "",
|
||||
}
|
||||
au = aurora.NewAurora(true)
|
||||
showPrivateKeyFlag = &cli.BoolFlag{
|
||||
Name: "show-private-key",
|
||||
Usage: "Show the BLS12-381 private key you will encrypt into a keystore file",
|
||||
Name: "show-private-key",
|
||||
Usage: "Show the BLS12-381 private key you will encrypt into a keystore file",
|
||||
Category: flags.AccountCategory,
|
||||
}
|
||||
BLSAccountPasswordFileFlag = &cli.StringFlag{
|
||||
Name: "blsaccountpassword",
|
||||
Usage: "File path for the BLS account password, which contains the password to encrypt private key into keystore file for managing votes in fast_finality feature",
|
||||
importedAccountPasswordFileFlag = &cli.StringFlag{
|
||||
Name: "importedaccountpassword",
|
||||
Usage: "Password file path for the imported BLS account , which contains the password to get the private key by decrypting the keystore file",
|
||||
Category: flags.AccountCategory,
|
||||
}
|
||||
chainIdFlag = &cli.Int64Flag{
|
||||
Name: "chain-id",
|
||||
Usage: "The chain id of the network that the validator will be created at",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -130,10 +134,8 @@ Make sure you backup your BLS keys regularly.`,
|
||||
Category: "BLS ACCOUNT COMMANDS",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
privateKeyFlag,
|
||||
showPrivateKeyFlag,
|
||||
utils.BLSPasswordFileFlag,
|
||||
BLSAccountPasswordFileFlag,
|
||||
},
|
||||
Description: `
|
||||
geth bls account new
|
||||
@@ -149,17 +151,17 @@ You must remember this password to unlock your account in the future.`,
|
||||
Name: "import",
|
||||
Usage: "Import a BLS account",
|
||||
Action: blsAccountImport,
|
||||
ArgsUsage: "<keystore file>",
|
||||
ArgsUsage: "<keyFile>",
|
||||
Category: "BLS ACCOUNT COMMANDS",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.BLSPasswordFileFlag,
|
||||
BLSAccountPasswordFileFlag,
|
||||
importedAccountPasswordFileFlag,
|
||||
},
|
||||
Description: `
|
||||
geth bls account import <keyFile>
|
||||
|
||||
Import a encrypted BLS account from keystore file <keyFile> into the BLS wallet.
|
||||
Import a encrypted BLS account or a BLS12-381 private key from file <keyFile> into the BLS wallet.
|
||||
|
||||
If the BLS wallet not created yet, it will try to create BLS wallet first.`,
|
||||
},
|
||||
@@ -193,6 +195,22 @@ Print summary of existing BLS accounts in the current BLS wallet.`,
|
||||
|
||||
Delete the selected BLS account from the BLS wallet.`,
|
||||
},
|
||||
{
|
||||
Name: "generate-proof",
|
||||
Usage: "Generate ownership proof for the selected BLS account from the BLS wallet",
|
||||
Action: blsAccountGenerateProof,
|
||||
ArgsUsage: "<operator address> <BLS pubkey>",
|
||||
Category: "BLS ACCOUNT COMMANDS",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.BLSPasswordFileFlag,
|
||||
chainIdFlag,
|
||||
},
|
||||
Description: `
|
||||
geth bls account generate-proof
|
||||
|
||||
Generate ownership proof for the selected BLS account from the BLS wallet. The proof is used to prove the ownership of the BLS account when creating validator on BSC after feynman upgrade.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -219,7 +237,10 @@ func blsWalletCreate(ctx *cli.Context) error {
|
||||
utils.Fatalf("BLS wallet already exists in <DATADIR>/bls/wallet.")
|
||||
}
|
||||
|
||||
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, GetBLSPassword(ctx))
|
||||
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
|
||||
if err := core.ValidatePasswordFormat(password); err != nil {
|
||||
utils.Fatalf("Password invalid: %v.", err)
|
||||
}
|
||||
|
||||
opts := []accounts.Option{}
|
||||
opts = append(opts, accounts.WithWalletDir(dir))
|
||||
@@ -249,7 +270,10 @@ func openOrCreateBLSWallet(ctx *cli.Context, cfg *gethConfig) (*wallet.Wallet, e
|
||||
}
|
||||
if !dirExists {
|
||||
fmt.Println("BLS wallet not exists, creating BLS wallet...")
|
||||
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, GetBLSPassword(ctx))
|
||||
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
|
||||
if err := core.ValidatePasswordFormat(password); err != nil {
|
||||
utils.Fatalf("Password invalid: %v.", err)
|
||||
}
|
||||
|
||||
opts := []accounts.Option{}
|
||||
opts = append(opts, accounts.WithWalletDir(walletDir))
|
||||
@@ -269,7 +293,7 @@ func openOrCreateBLSWallet(ctx *cli.Context, cfg *gethConfig) (*wallet.Wallet, e
|
||||
return w, nil
|
||||
}
|
||||
|
||||
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
|
||||
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
|
||||
w, err = wallet.OpenWallet(context.Background(), &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
WalletPassword: walletPassword,
|
||||
@@ -309,27 +333,11 @@ func blsAccountCreate(ctx *cli.Context) error {
|
||||
if err := os.MkdirAll(keystoreDir, 0755); err != nil {
|
||||
utils.Fatalf("Could not access keystore dir: %v.", err)
|
||||
}
|
||||
accountPassword := utils.GetPassPhraseWithList("Your new BLS account will be encrypted with a password. Please give a password. Do not forget this password.", true, 0, GetBLSAccountPassword(ctx))
|
||||
if err := core.ValidatePasswordFormat(accountPassword); err != nil {
|
||||
utils.Fatalf("Password invalid: %v.", err)
|
||||
}
|
||||
accountPassword := w.Password()
|
||||
|
||||
encryptor := keystorev4.New()
|
||||
secretKey, err := bls.RandKey()
|
||||
privateKeyString := ctx.String(privateKeyFlag.Name)
|
||||
if privateKeyString != "" {
|
||||
if len(privateKeyString) > 2 && strings.Contains(privateKeyString, "0x") {
|
||||
privateKeyString = privateKeyString[2:] // Strip the 0x prefix, if any.
|
||||
}
|
||||
bytesValue, err := hex.DecodeString(privateKeyString)
|
||||
if err != nil {
|
||||
utils.Fatalf("could not decode as hex string: %s", privateKeyString)
|
||||
}
|
||||
secretKey, err = bls.SecretKeyFromBytes(bytesValue)
|
||||
if err != nil {
|
||||
utils.Fatalf("not a valid BLS12-381 private key")
|
||||
}
|
||||
} else if err != nil {
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not generate BLS secret key: %v.", err)
|
||||
}
|
||||
|
||||
@@ -383,22 +391,6 @@ func blsAccountCreate(ctx *cli.Context) error {
|
||||
|
||||
// blsAccountImport imports a BLS account into the BLS wallet.
|
||||
func blsAccountImport(ctx *cli.Context) error {
|
||||
keyfile := ctx.Args().First()
|
||||
if len(keyfile) == 0 {
|
||||
utils.Fatalf("The keystore file must be given as argument.")
|
||||
}
|
||||
keyJSON, err := os.ReadFile(keyfile)
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not read keystore file: %v", err)
|
||||
}
|
||||
keystore := &keymanager.Keystore{}
|
||||
if err := json.Unmarshal(keyJSON, keystore); err != nil {
|
||||
utils.Fatalf("Could not decode keystore file: %v.", err)
|
||||
}
|
||||
if keystore.Pubkey == "" {
|
||||
utils.Fatalf(" Missing public key, wrong keystore file.")
|
||||
}
|
||||
|
||||
cfg := gethConfig{Node: defaultNodeConfig()}
|
||||
// Load config file.
|
||||
if file := ctx.String(configFileFlag.Name); file != "" {
|
||||
@@ -421,19 +413,59 @@ func blsAccountImport(ctx *cli.Context) error {
|
||||
utils.Fatalf("The BLS keymanager cannot import keystores")
|
||||
}
|
||||
|
||||
password := utils.GetPassPhraseWithList("Enter the password for your imported account.", false, 0, GetBLSAccountPassword(ctx))
|
||||
keyfile := ctx.Args().First()
|
||||
if len(keyfile) == 0 {
|
||||
utils.Fatalf("The keystore file must be given as argument.")
|
||||
}
|
||||
keyInfo, err := os.ReadFile(keyfile)
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not read keystore file: %v", err)
|
||||
}
|
||||
keystore := &keymanager.Keystore{}
|
||||
var importedAccountPassword string
|
||||
if err := json.Unmarshal(keyInfo, keystore); err != nil {
|
||||
secretKey, err := bls.SecretKeyFromBytes(common.FromHex(strings.TrimRight(string(keyInfo), "\r\n")))
|
||||
if err != nil {
|
||||
utils.Fatalf("keyFile is neither a keystore file or include a valid BLS12-381 private key: %v.", err)
|
||||
}
|
||||
pubKeyBytes := secretKey.PublicKey().Marshal()
|
||||
encryptor := keystorev4.New()
|
||||
importedAccountPassword = w.Password()
|
||||
cryptoFields, err := encryptor.Encrypt(secretKey.Marshal(), importedAccountPassword)
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not encrypt secret key: %v.", err)
|
||||
}
|
||||
id, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not generate uuid: %v.", err)
|
||||
}
|
||||
keystore = &keymanager.Keystore{
|
||||
Crypto: cryptoFields,
|
||||
ID: id.String(),
|
||||
Pubkey: fmt.Sprintf("%x", pubKeyBytes),
|
||||
Version: encryptor.Version(),
|
||||
Name: encryptor.Name(),
|
||||
}
|
||||
}
|
||||
if keystore.Pubkey == "" {
|
||||
utils.Fatalf(" Missing public key, wrong keystore file.")
|
||||
}
|
||||
|
||||
if importedAccountPassword == "" {
|
||||
importedAccountPassword = utils.GetPassPhraseWithList("Enter the password for your imported account.", false, 0, utils.MakePasswordListFromPath(ctx.String(importedAccountPasswordFileFlag.Name)))
|
||||
}
|
||||
|
||||
fmt.Println("Importing BLS account, this may take a while...")
|
||||
statuses, err := accounts.ImportAccounts(context.Background(), &accounts.ImportAccountsConfig{
|
||||
Importer: k,
|
||||
Keystores: []*keymanager.Keystore{keystore},
|
||||
AccountPassword: password,
|
||||
AccountPassword: importedAccountPassword,
|
||||
})
|
||||
if err != nil {
|
||||
utils.Fatalf("Import BLS account failed: %v.", err)
|
||||
}
|
||||
// len(statuses)==len(Keystores) when err==nil
|
||||
if statuses[0].Status == service.ImportedKeystoreStatus_ERROR {
|
||||
if statuses[0].Status == keymanager.StatusError {
|
||||
fmt.Printf("Could not import keystore: %v.", statuses[0].Message)
|
||||
} else {
|
||||
fmt.Println("Successfully import BLS account.")
|
||||
@@ -458,7 +490,7 @@ func blsAccountList(ctx *cli.Context) error {
|
||||
utils.Fatalf("BLS wallet not exists.")
|
||||
}
|
||||
|
||||
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
|
||||
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
|
||||
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
WalletPassword: walletPassword,
|
||||
@@ -537,7 +569,7 @@ func blsAccountDelete(ctx *cli.Context) error {
|
||||
utils.Fatalf("BLS wallet not exists.")
|
||||
}
|
||||
|
||||
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
|
||||
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
|
||||
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
WalletPassword: walletPassword,
|
||||
@@ -599,26 +631,73 @@ func blsAccountDelete(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetBLSPassword(ctx *cli.Context) []string {
|
||||
path := ctx.String(utils.BLSPasswordFileFlag.Name)
|
||||
if path == "" {
|
||||
return nil
|
||||
// blsAccountGenerateProof generate ownership proof for a selected BLS account.
|
||||
func blsAccountGenerateProof(ctx *cli.Context) error {
|
||||
addrString := ctx.Args().First()
|
||||
if addrString == "" {
|
||||
utils.Fatalf("Operator account must be given as argument.")
|
||||
}
|
||||
text, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to read wallet password file: %v", err)
|
||||
}
|
||||
return []string{string(text)}
|
||||
}
|
||||
addr := common.HexToAddress(addrString)
|
||||
|
||||
func GetBLSAccountPassword(ctx *cli.Context) []string {
|
||||
path := ctx.String(BLSAccountPasswordFileFlag.Name)
|
||||
if path == "" {
|
||||
return nil
|
||||
blsPubkeyString := ctx.Args().Get(1)
|
||||
if blsPubkeyString == "" {
|
||||
utils.Fatalf("BLS pubkey must be given as argument.")
|
||||
}
|
||||
text, err := os.ReadFile(path)
|
||||
blsPubkeyBz, err := hex.DecodeString(strings.TrimPrefix(blsPubkeyString, "0x"))
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to read account password file: %v", err)
|
||||
utils.Fatalf("Could not decode string %s as hex.", blsPubkeyString)
|
||||
}
|
||||
return []string{string(text)}
|
||||
blsPublicKey, err := bls.PublicKeyFromBytes(blsPubkeyBz)
|
||||
if err != nil {
|
||||
utils.Fatalf("%#x is not a valid BLS public key.", blsPubkeyBz)
|
||||
}
|
||||
|
||||
cfg := gethConfig{Node: defaultNodeConfig()}
|
||||
// Load config file.
|
||||
if file := ctx.String(configFileFlag.Name); file != "" {
|
||||
if err := loadConfig(file, &cfg); err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
utils.SetNodeConfig(ctx, &cfg.Node)
|
||||
|
||||
walletDir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
|
||||
dirExists, err := wallet.Exists(walletDir)
|
||||
if err != nil || !dirExists {
|
||||
utils.Fatalf("BLS wallet not exists.")
|
||||
}
|
||||
|
||||
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
|
||||
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
WalletPassword: walletPassword,
|
||||
})
|
||||
if err != nil {
|
||||
utils.Fatalf("Open BLS wallet failed: %v.", err)
|
||||
}
|
||||
km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
|
||||
if err != nil {
|
||||
utils.Fatalf("Initialize key manager failed: %v.", err)
|
||||
}
|
||||
|
||||
chainIdInt64 := ctx.Int64(chainIdFlag.Name)
|
||||
if chainIdInt64 == 0 {
|
||||
utils.Fatalf("Chain id is required.")
|
||||
}
|
||||
chainId := new(big.Int).SetInt64(chainIdInt64)
|
||||
paddedChainIdBytes := make([]byte, 32)
|
||||
copy(paddedChainIdBytes[32-len(chainId.Bytes()):], chainId.Bytes())
|
||||
msgHash := crypto.Keccak256(append(addr.Bytes(), append(blsPublicKey.Marshal(), paddedChainIdBytes...)...))
|
||||
|
||||
req := &validatorpb.SignRequest{
|
||||
PublicKey: blsPublicKey.Marshal(),
|
||||
SigningRoot: msgHash,
|
||||
}
|
||||
sig, err := km.Sign(context.Background(), req)
|
||||
if err != nil {
|
||||
utils.Fatalf("Generate signature failed: %v.", err)
|
||||
}
|
||||
fmt.Printf("Proof: %#x\n", sig.Marshal())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@@ -44,7 +47,8 @@ import (
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -191,6 +195,21 @@ It's deprecated, please use "geth db export" instead.
|
||||
}, utils.DatabasePathFlags),
|
||||
Description: `
|
||||
This command dumps out the state for a given block (or latest, if none provided).
|
||||
If you use "dump" command in path mode, please firstly use "dump-roothash" command to get all available state root hash.
|
||||
`,
|
||||
}
|
||||
dumpRootHashCommand = &cli.Command{
|
||||
Action: dumpAllRootHashInPath,
|
||||
Name: "dump-roothash",
|
||||
Usage: "Dump all available state root hash in path mode",
|
||||
Flags: flags.Merge([]cli.Flag{
|
||||
utils.StateSchemeFlag,
|
||||
}, utils.DatabasePathFlags),
|
||||
Description: `
|
||||
The dump-roothash command dump all available state root hash in path mode.
|
||||
If you use "dump" command in path mode, please note that it only keeps at most 129 blocks which belongs to diffLayer or diskLayer.
|
||||
Therefore, you must specify the blockNumber or blockHash that locates in diffLayer or diskLayer.
|
||||
"geth" will print all available blockNumber and related block state root hash, and you can query block hash by block number.
|
||||
`,
|
||||
}
|
||||
)
|
||||
@@ -233,7 +252,7 @@ func initGenesis(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to write genesis block: %v", err)
|
||||
}
|
||||
log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
|
||||
log.Info(fmt.Sprintf("Successfully wrote genesis state database=%v hash=%v", name, hash))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -590,11 +609,20 @@ func exportPreimages(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, ethdb.Database, common.Hash, error) {
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
var header *types.Header
|
||||
if ctx.NArg() > 1 {
|
||||
return nil, nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg())
|
||||
}
|
||||
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db)
|
||||
if err != nil {
|
||||
return nil, nil, common.Hash{}, err
|
||||
}
|
||||
if scheme == rawdb.PathScheme {
|
||||
fmt.Println("You are using geth dump in path mode, please use `geth dump-roothash` command to get all available blocks.")
|
||||
}
|
||||
|
||||
header := &types.Header{}
|
||||
if ctx.NArg() == 1 {
|
||||
arg := ctx.Args().First()
|
||||
if hashish(arg) {
|
||||
@@ -617,11 +645,22 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
|
||||
}
|
||||
} else {
|
||||
// Use latest
|
||||
header = rawdb.ReadHeadHeader(db)
|
||||
if scheme == rawdb.PathScheme {
|
||||
triedb := trie.NewDatabase(db, &trie.Config{PathDB: pathdb.ReadOnly})
|
||||
defer triedb.Close()
|
||||
if stateRoot := triedb.Head(); stateRoot != (common.Hash{}) {
|
||||
header.Root = stateRoot
|
||||
} else {
|
||||
return nil, nil, common.Hash{}, fmt.Errorf("no top state root hash in path db")
|
||||
}
|
||||
} else {
|
||||
header = rawdb.ReadHeadHeader(db)
|
||||
}
|
||||
}
|
||||
if header == nil {
|
||||
return nil, nil, common.Hash{}, errors.New("no head block found")
|
||||
}
|
||||
|
||||
startArg := common.FromHex(ctx.String(utils.StartKeyFlag.Name))
|
||||
var start common.Hash
|
||||
switch len(startArg) {
|
||||
@@ -634,6 +673,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
|
||||
default:
|
||||
return nil, nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
|
||||
}
|
||||
|
||||
var conf = &state.DumpConfig{
|
||||
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
|
||||
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
|
||||
@@ -641,9 +681,10 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
|
||||
Start: start.Bytes(),
|
||||
Max: ctx.Uint64(utils.DumpLimitFlag.Name),
|
||||
}
|
||||
conf.StateScheme = scheme
|
||||
log.Info("State dump configured", "block", header.Number, "hash", header.Hash().Hex(),
|
||||
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage,
|
||||
"start", hexutil.Encode(conf.Start), "limit", conf.Max)
|
||||
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage, "start", hexutil.Encode(conf.Start),
|
||||
"limit", conf.Max, "state scheme", conf.StateScheme)
|
||||
return conf, db, header.Root, nil
|
||||
}
|
||||
|
||||
@@ -655,7 +696,7 @@ func dump(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
triedb := utils.MakeTrieDatabase(ctx, db, true, false) // always enable preimage lookup
|
||||
triedb := utils.MakeTrieDatabase(ctx, db, true, true) // always enable preimage lookup
|
||||
defer triedb.Close()
|
||||
|
||||
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||
@@ -675,6 +716,29 @@ func dump(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func dumpAllRootHashInPath(ctx *cli.Context) error {
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer db.Close()
|
||||
triedb := trie.NewDatabase(db, &trie.Config{PathDB: pathdb.ReadOnly})
|
||||
defer triedb.Close()
|
||||
|
||||
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if scheme == rawdb.HashScheme {
|
||||
return errors.New("incorrect state scheme, you should use it in path mode")
|
||||
}
|
||||
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Block Number", "Block State Root Hash"})
|
||||
table.AppendBulk(triedb.GetAllRooHash())
|
||||
table.Render()
|
||||
return nil
|
||||
}
|
||||
|
||||
// hashish returns true for strings that look like hashes.
|
||||
func hashish(x string) bool {
|
||||
_, err := strconv.Atoi(x)
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"reflect"
|
||||
"unicode"
|
||||
|
||||
"github.com/naoina/toml"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
@@ -32,6 +33,8 @@ import (
|
||||
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
||||
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
@@ -40,7 +43,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/naoina/toml"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -54,8 +56,9 @@ var (
|
||||
}
|
||||
|
||||
configFileFlag = &cli.StringFlag{
|
||||
Name: "config",
|
||||
Usage: "TOML configuration file",
|
||||
Name: "config",
|
||||
Usage: "TOML configuration file",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -135,6 +138,16 @@ func loadBaseConfig(ctx *cli.Context) gethConfig {
|
||||
}
|
||||
}
|
||||
|
||||
scheme := cfg.Eth.StateScheme
|
||||
if scheme != "" {
|
||||
if !rawdb.ValidateStateScheme(scheme) {
|
||||
utils.Fatalf("Invalid state scheme param in config: %s", scheme)
|
||||
}
|
||||
}
|
||||
if cfg.Eth.Genesis != nil && cfg.Eth.Genesis.Config != nil {
|
||||
log.Warn("Chain config in the configuration file is ignored!")
|
||||
}
|
||||
|
||||
// Apply flags.
|
||||
utils.SetNodeConfig(ctx, &cfg.Node)
|
||||
return cfg
|
||||
@@ -164,6 +177,19 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
||||
// makeFullNode loads geth configuration and creates the Ethereum backend.
|
||||
func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||
stack, cfg := makeConfigNode(ctx)
|
||||
if ctx.IsSet(utils.RialtoHash.Name) {
|
||||
v := ctx.String(utils.RialtoHash.Name)
|
||||
params.RialtoGenesisHash = common.HexToHash(v)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.OverrideShanghai.Name) {
|
||||
v := ctx.Uint64(utils.OverrideShanghai.Name)
|
||||
cfg.Eth.OverrideShanghai = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideKepler.Name) {
|
||||
v := ctx.Uint64(utils.OverrideKepler.Name)
|
||||
cfg.Eth.OverrideKepler = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideCancun.Name) {
|
||||
v := ctx.Uint64(utils.OverrideCancun.Name)
|
||||
cfg.Eth.OverrideCancun = &v
|
||||
@@ -172,6 +198,14 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||
cfg.Eth.OverrideVerkle = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideFeynman.Name) {
|
||||
v := ctx.Uint64(utils.OverrideFeynman.Name)
|
||||
cfg.Eth.OverrideFeynman = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideFeynmanFix.Name) {
|
||||
v := ctx.Uint64(utils.OverrideFeynmanFix.Name)
|
||||
cfg.Eth.OverrideFeynmanFix = &v
|
||||
}
|
||||
backend, _ := utils.RegisterEthService(stack, &cfg.Eth)
|
||||
|
||||
// Configure log filter RPC API.
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestConsoleWelcome(t *testing.T) {
|
||||
geth.SetTemplateFunc("gover", runtime.Version)
|
||||
geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
||||
geth.SetTemplateFunc("niltime", func() string {
|
||||
return time.Unix(0, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||
return time.Unix(0x5e9da7ce, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||
})
|
||||
geth.SetTemplateFunc("apis", func() string { return ipcAPIs })
|
||||
|
||||
@@ -131,7 +131,7 @@ func testAttachWelcome(t *testing.T, geth *testgeth, endpoint, apis string) {
|
||||
attach.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
||||
attach.SetTemplateFunc("etherbase", func() string { return geth.Etherbase })
|
||||
attach.SetTemplateFunc("niltime", func() string {
|
||||
return time.Unix(0, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||
return time.Unix(0x5e9da7ce, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||
})
|
||||
attach.SetTemplateFunc("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") })
|
||||
attach.SetTemplateFunc("datadir", func() string { return geth.Datadir })
|
||||
|
||||
@@ -39,6 +39,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -63,6 +64,7 @@ Remove blockchain and state databases`,
|
||||
dbCompactCmd,
|
||||
dbGetCmd,
|
||||
dbDeleteCmd,
|
||||
dbInspectTrieCmd,
|
||||
dbPutCmd,
|
||||
dbGetSlotsCmd,
|
||||
dbDumpFreezerIndex,
|
||||
@@ -88,6 +90,17 @@ Remove blockchain and state databases`,
|
||||
Usage: "Inspect the storage size for each type of data in the database",
|
||||
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
||||
}
|
||||
dbInspectTrieCmd = &cli.Command{
|
||||
Action: inspectTrie,
|
||||
Name: "inspect-trie",
|
||||
ArgsUsage: "<blocknum> <jobnum>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.SyncModeFlag,
|
||||
},
|
||||
Usage: "Inspect the MPT tree of the account and contract.",
|
||||
Description: `This commands iterates the entrie WorldState.`,
|
||||
}
|
||||
dbCheckStateContentCmd = &cli.Command{
|
||||
Action: checkStateContent,
|
||||
Name: "check-state-content",
|
||||
@@ -119,7 +132,8 @@ a data corruption.`,
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.SyncModeFlag,
|
||||
utils.MainnetFlag,
|
||||
utils.BSCMainnetFlag,
|
||||
utils.ChapelFlag,
|
||||
utils.StateSchemeFlag,
|
||||
},
|
||||
Description: "This command looks up the specified trie node key from the database.",
|
||||
@@ -132,7 +146,8 @@ a data corruption.`,
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.SyncModeFlag,
|
||||
utils.MainnetFlag,
|
||||
utils.BSCMainnetFlag,
|
||||
utils.ChapelFlag,
|
||||
utils.StateSchemeFlag,
|
||||
},
|
||||
Description: "This command delete the specify trie node from the database.",
|
||||
@@ -312,6 +327,92 @@ func confirmAndRemoveDB(database string, kind string) {
|
||||
}
|
||||
}
|
||||
|
||||
func inspectTrie(ctx *cli.Context) error {
|
||||
if ctx.NArg() < 1 {
|
||||
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
|
||||
}
|
||||
|
||||
if ctx.NArg() > 3 {
|
||||
return fmt.Errorf("Max 3 arguments: %v", ctx.Command.ArgsUsage)
|
||||
}
|
||||
|
||||
var (
|
||||
blockNumber uint64
|
||||
trieRootHash common.Hash
|
||||
jobnum uint64
|
||||
)
|
||||
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer db.Close()
|
||||
|
||||
var headerBlockHash common.Hash
|
||||
if ctx.NArg() >= 1 {
|
||||
if ctx.Args().Get(0) == "latest" {
|
||||
headerHash := rawdb.ReadHeadHeaderHash(db)
|
||||
blockNumber = *(rawdb.ReadHeaderNumber(db, headerHash))
|
||||
} else if ctx.Args().Get(0) == "snapshot" {
|
||||
trieRootHash = rawdb.ReadSnapshotRoot(db)
|
||||
blockNumber = math.MaxUint64
|
||||
} else {
|
||||
var err error
|
||||
blockNumber, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to Parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.NArg() == 1 {
|
||||
jobnum = 1000
|
||||
} else {
|
||||
var err error
|
||||
jobnum, err = strconv.ParseUint(ctx.Args().Get(1), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to Parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err)
|
||||
}
|
||||
}
|
||||
|
||||
if blockNumber != math.MaxUint64 {
|
||||
headerBlockHash = rawdb.ReadCanonicalHash(db, blockNumber)
|
||||
if headerBlockHash == (common.Hash{}) {
|
||||
return fmt.Errorf("ReadHeadBlockHash empry hash")
|
||||
}
|
||||
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
|
||||
trieRootHash = blockHeader.Root
|
||||
}
|
||||
if (trieRootHash == common.Hash{}) {
|
||||
log.Error("Empty root hash")
|
||||
}
|
||||
fmt.Printf("ReadBlockHeader, root: %v, blocknum: %v\n", trieRootHash, blockNumber)
|
||||
|
||||
dbScheme := rawdb.ReadStateScheme(db)
|
||||
var config *trie.Config
|
||||
if dbScheme == rawdb.PathScheme {
|
||||
config = &trie.Config{
|
||||
PathDB: pathdb.ReadOnly,
|
||||
}
|
||||
} else if dbScheme == rawdb.HashScheme {
|
||||
config = trie.HashDefaults
|
||||
}
|
||||
|
||||
triedb := trie.NewDatabase(db, config)
|
||||
theTrie, err := trie.New(trie.TrieID(trieRootHash), triedb)
|
||||
if err != nil {
|
||||
fmt.Printf("fail to new trie tree, err: %v, rootHash: %v\n", err, trieRootHash.String())
|
||||
return err
|
||||
}
|
||||
theInspect, err := trie.NewInspector(theTrie, triedb, trieRootHash, blockNumber, jobnum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
theInspect.Run()
|
||||
theInspect.DisplayResult()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func inspect(ctx *cli.Context) error {
|
||||
var (
|
||||
prefix []byte
|
||||
|
||||
@@ -89,7 +89,7 @@ func TestCustomGenesis(t *testing.T) {
|
||||
|
||||
// Query the custom genesis block
|
||||
geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16",
|
||||
"--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0",
|
||||
"--datadir", datadir, "--maxpeers", "0", "--port", "0",
|
||||
"--nodiscover", "--nat", "none", "--ipcdisable",
|
||||
"--exec", tt.query, "console")
|
||||
geth.ExpectRegexp(tt.result)
|
||||
@@ -141,7 +141,7 @@ func TestCustomBackend(t *testing.T) {
|
||||
}
|
||||
{ // Exec + query
|
||||
args := append(tt.execArgs, "--networkid", "1337", "--syncmode=full", "--cache", "16",
|
||||
"--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0",
|
||||
"--datadir", datadir, "--maxpeers", "0", "--port", "0",
|
||||
"--nodiscover", "--nat", "none", "--ipcdisable",
|
||||
"--exec", "eth.getBlock(0).nonce", "console")
|
||||
geth := runGeth(t, args...)
|
||||
@@ -176,19 +176,19 @@ func TestCustomBackend(t *testing.T) {
|
||||
{ // Can't start pebble on top of leveldb
|
||||
initArgs: []string{"--db.engine", "leveldb"},
|
||||
execArgs: []string{"--db.engine", "pebble"},
|
||||
execExpect: `Fatal: Could not open database: db.engine choice was pebble but found pre-existing leveldb database in specified data directory`,
|
||||
execExpect: `Fatal: Failed to register the Ethereum service: db.engine choice was pebble but found pre-existing leveldb database in specified data directory`,
|
||||
},
|
||||
{ // Can't start leveldb on top of pebble
|
||||
initArgs: []string{"--db.engine", "pebble"},
|
||||
execArgs: []string{"--db.engine", "leveldb"},
|
||||
execExpect: `Fatal: Could not open database: db.engine choice was leveldb but found pre-existing pebble database in specified data directory`,
|
||||
execExpect: `Fatal: Failed to register the Ethereum service: db.engine choice was leveldb but found pre-existing pebble database in specified data directory`,
|
||||
},
|
||||
{ // Reject invalid backend choice
|
||||
initArgs: []string{"--db.engine", "mssql"},
|
||||
initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`,
|
||||
// Since the init fails, this will return the (default) mainnet genesis
|
||||
// block nonce
|
||||
execExpect: `0x0000000000000042`,
|
||||
execExpect: `0x0000000000000000`,
|
||||
},
|
||||
} {
|
||||
if err := testfunc(t, tt); err != nil {
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
// Copyright 2020 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
type gethrpc struct {
|
||||
name string
|
||||
rpc *rpc.Client
|
||||
geth *testgeth
|
||||
nodeInfo *p2p.NodeInfo
|
||||
}
|
||||
|
||||
func (g *gethrpc) killAndWait() {
|
||||
g.geth.Kill()
|
||||
g.geth.WaitExit()
|
||||
}
|
||||
|
||||
func (g *gethrpc) callRPC(result interface{}, method string, args ...interface{}) {
|
||||
if err := g.rpc.Call(&result, method, args...); err != nil {
|
||||
g.geth.Fatalf("callRPC %v: %v", method, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *gethrpc) addPeer(peer *gethrpc) {
|
||||
g.geth.Logf("%v.addPeer(%v)", g.name, peer.name)
|
||||
enode := peer.getNodeInfo().Enode
|
||||
peerCh := make(chan *p2p.PeerEvent)
|
||||
sub, err := g.rpc.Subscribe(context.Background(), "admin", peerCh, "peerEvents")
|
||||
if err != nil {
|
||||
g.geth.Fatalf("subscribe %v: %v", g.name, err)
|
||||
}
|
||||
defer sub.Unsubscribe()
|
||||
g.callRPC(nil, "admin_addPeer", enode)
|
||||
dur := 14 * time.Second
|
||||
timeout := time.After(dur)
|
||||
select {
|
||||
case ev := <-peerCh:
|
||||
g.geth.Logf("%v received event: type=%v, peer=%v", g.name, ev.Type, ev.Peer)
|
||||
case err := <-sub.Err():
|
||||
g.geth.Fatalf("%v sub error: %v", g.name, err)
|
||||
case <-timeout:
|
||||
g.geth.Error("timeout adding peer after", dur)
|
||||
}
|
||||
}
|
||||
|
||||
// Use this function instead of `g.nodeInfo` directly
|
||||
func (g *gethrpc) getNodeInfo() *p2p.NodeInfo {
|
||||
if g.nodeInfo != nil {
|
||||
return g.nodeInfo
|
||||
}
|
||||
g.nodeInfo = &p2p.NodeInfo{}
|
||||
g.callRPC(&g.nodeInfo, "admin_nodeInfo")
|
||||
return g.nodeInfo
|
||||
}
|
||||
|
||||
// ipcEndpoint resolves an IPC endpoint based on a configured value, taking into
|
||||
// account the set data folders as well as the designated platform we're currently
|
||||
// running on.
|
||||
func ipcEndpoint(ipcPath, datadir string) string {
|
||||
// On windows we can only use plain top-level pipes
|
||||
if runtime.GOOS == "windows" {
|
||||
if strings.HasPrefix(ipcPath, `\\.\pipe\`) {
|
||||
return ipcPath
|
||||
}
|
||||
return `\\.\pipe\` + ipcPath
|
||||
}
|
||||
// Resolve names into the data directory full paths otherwise
|
||||
if filepath.Base(ipcPath) == ipcPath {
|
||||
if datadir == "" {
|
||||
return filepath.Join(os.TempDir(), ipcPath)
|
||||
}
|
||||
return filepath.Join(datadir, ipcPath)
|
||||
}
|
||||
return ipcPath
|
||||
}
|
||||
|
||||
// nextIPC ensures that each ipc pipe gets a unique name.
|
||||
// On linux, it works well to use ipc pipes all over the filesystem (in datadirs),
|
||||
// but windows require pipes to sit in "\\.\pipe\". Therefore, to run several
|
||||
// nodes simultaneously, we need to distinguish between them, which we do by
|
||||
// the pipe filename instead of folder.
|
||||
var nextIPC atomic.Uint32
|
||||
|
||||
func startGethWithIpc(t *testing.T, name string, args ...string) *gethrpc {
|
||||
ipcName := fmt.Sprintf("geth-%d.ipc", nextIPC.Add(1))
|
||||
args = append([]string{"--networkid=42", "--port=0", "--authrpc.port", "0", "--ipcpath", ipcName}, args...)
|
||||
t.Logf("Starting %v with rpc: %v", name, args)
|
||||
|
||||
g := &gethrpc{
|
||||
name: name,
|
||||
geth: runGeth(t, args...),
|
||||
}
|
||||
ipcpath := ipcEndpoint(ipcName, g.geth.Datadir)
|
||||
// We can't know exactly how long geth will take to start, so we try 10
|
||||
// times over a 5 second period.
|
||||
var err error
|
||||
for i := 0; i < 10; i++ {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
if g.rpc, err = rpc.Dial(ipcpath); err == nil {
|
||||
return g
|
||||
}
|
||||
}
|
||||
t.Fatalf("%v rpc connect to %v: %v", name, ipcpath, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
func initGeth(t *testing.T) string {
|
||||
args := []string{"--networkid=42", "init", "./testdata/clique.json"}
|
||||
t.Logf("Initializing geth: %v ", args)
|
||||
g := runGeth(t, args...)
|
||||
datadir := g.Datadir
|
||||
g.WaitExit()
|
||||
return datadir
|
||||
}
|
||||
|
||||
func startLightServer(t *testing.T) *gethrpc {
|
||||
datadir := initGeth(t)
|
||||
t.Logf("Importing keys to geth")
|
||||
runGeth(t, "account", "import", "--datadir", datadir, "--password", "./testdata/password.txt", "--lightkdf", "./testdata/key.prv").WaitExit()
|
||||
account := "0x02f0d131f1f97aef08aec6e3291b957d9efe7105"
|
||||
server := startGethWithIpc(t, "lightserver", "--allow-insecure-unlock", "--datadir", datadir, "--password", "./testdata/password.txt", "--unlock", account, "--miner.etherbase=0x02f0d131f1f97aef08aec6e3291b957d9efe7105", "--mine", "--light.serve=100", "--light.maxpeers=1", "--discv4=false", "--nat=extip:127.0.0.1", "--verbosity=4")
|
||||
return server
|
||||
}
|
||||
|
||||
func startClient(t *testing.T, name string) *gethrpc {
|
||||
datadir := initGeth(t)
|
||||
return startGethWithIpc(t, name, "--datadir", datadir, "--discv4=false", "--syncmode=light", "--nat=extip:127.0.0.1", "--verbosity=4")
|
||||
}
|
||||
|
||||
func TestPriorityClient(t *testing.T) {
|
||||
lightServer := startLightServer(t)
|
||||
defer lightServer.killAndWait()
|
||||
|
||||
// Start client and add lightServer as peer
|
||||
freeCli := startClient(t, "freeCli")
|
||||
defer freeCli.killAndWait()
|
||||
freeCli.addPeer(lightServer)
|
||||
|
||||
var peers []*p2p.PeerInfo
|
||||
freeCli.callRPC(&peers, "admin_peers")
|
||||
if len(peers) != 1 {
|
||||
t.Errorf("Expected: # of client peers == 1, actual: %v", len(peers))
|
||||
return
|
||||
}
|
||||
|
||||
// Set up priority client, get its nodeID, increase its balance on the lightServer
|
||||
prioCli := startClient(t, "prioCli")
|
||||
defer prioCli.killAndWait()
|
||||
// 3_000_000_000 once we move to Go 1.13
|
||||
tokens := uint64(3000000000)
|
||||
lightServer.callRPC(nil, "les_addBalance", prioCli.getNodeInfo().ID, tokens)
|
||||
prioCli.addPeer(lightServer)
|
||||
|
||||
// Check if priority client is actually syncing and the regular client got kicked out
|
||||
prioCli.callRPC(&peers, "admin_peers")
|
||||
if len(peers) != 1 {
|
||||
t.Errorf("Expected: # of prio peers == 1, actual: %v", len(peers))
|
||||
}
|
||||
|
||||
nodes := map[string]*gethrpc{
|
||||
lightServer.getNodeInfo().ID: lightServer,
|
||||
freeCli.getNodeInfo().ID: freeCli,
|
||||
prioCli.getNodeInfo().ID: prioCli,
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
lightServer.callRPC(&peers, "admin_peers")
|
||||
peersWithNames := make(map[string]string)
|
||||
for _, p := range peers {
|
||||
peersWithNames[nodes[p.ID].name] = p.ID
|
||||
}
|
||||
if _, freeClientFound := peersWithNames[freeCli.name]; freeClientFound {
|
||||
t.Error("client is still a peer of lightServer", peersWithNames)
|
||||
}
|
||||
if _, prioClientFound := peersWithNames[prioCli.name]; !prioClientFound {
|
||||
t.Error("prio client is not among lightServer peers", peersWithNames)
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ var (
|
||||
utils.MinFreeDiskSpaceFlag,
|
||||
utils.KeyStoreDirFlag,
|
||||
utils.ExternalSignerFlag,
|
||||
utils.NoUSBFlag,
|
||||
utils.NoUSBFlag, // deprecated
|
||||
utils.DirectBroadcastFlag,
|
||||
utils.DisableSnapProtocolFlag,
|
||||
utils.EnableTrustProtocolFlag,
|
||||
@@ -69,8 +69,13 @@ var (
|
||||
utils.RangeLimitFlag,
|
||||
utils.USBFlag,
|
||||
utils.SmartCardDaemonPathFlag,
|
||||
utils.RialtoHash,
|
||||
utils.OverrideShanghai,
|
||||
utils.OverrideKepler,
|
||||
utils.OverrideCancun,
|
||||
utils.OverrideVerkle,
|
||||
utils.OverrideFeynman,
|
||||
utils.OverrideFeynmanFix,
|
||||
utils.EnablePersonal,
|
||||
utils.TxPoolLocalsFlag,
|
||||
utils.TxPoolNoLocalsFlag,
|
||||
@@ -93,29 +98,30 @@ var (
|
||||
utils.ExitWhenSyncedFlag,
|
||||
utils.GCModeFlag,
|
||||
utils.SnapshotFlag,
|
||||
utils.TxLookupLimitFlag,
|
||||
utils.TxLookupLimitFlag, // deprecated
|
||||
utils.TransactionHistoryFlag,
|
||||
utils.StateSchemeFlag,
|
||||
utils.StateHistoryFlag,
|
||||
utils.PathDBSyncFlag,
|
||||
utils.LightServeFlag,
|
||||
utils.LightIngressFlag,
|
||||
utils.LightEgressFlag,
|
||||
utils.LightMaxPeersFlag,
|
||||
utils.LightNoPruneFlag,
|
||||
utils.LightKDFFlag,
|
||||
utils.LightNoSyncServeFlag,
|
||||
utils.LightServeFlag, // deprecated
|
||||
utils.LightIngressFlag, // deprecated
|
||||
utils.LightEgressFlag, // deprecated
|
||||
utils.LightMaxPeersFlag, // deprecated
|
||||
utils.LightNoPruneFlag, // deprecated
|
||||
utils.LightKDFFlag, // deprecated
|
||||
utils.LightNoSyncServeFlag, // deprecated
|
||||
utils.EthRequiredBlocksFlag,
|
||||
utils.LegacyWhitelistFlag,
|
||||
utils.LegacyWhitelistFlag, // deprecated
|
||||
utils.BloomFilterSizeFlag,
|
||||
utils.TriesInMemoryFlag,
|
||||
utils.CacheFlag,
|
||||
utils.CacheDatabaseFlag,
|
||||
utils.CacheTrieFlag,
|
||||
utils.CacheTrieJournalFlag,
|
||||
utils.CacheTrieRejournalFlag,
|
||||
utils.CacheTrieJournalFlag, // deprecated
|
||||
utils.CacheTrieRejournalFlag, // deprecated
|
||||
utils.CacheGCFlag,
|
||||
utils.CacheSnapshotFlag,
|
||||
// utils.CacheNoPrefetchFlag,
|
||||
utils.CachePreimagesFlag,
|
||||
utils.PersistDiffFlag,
|
||||
utils.DiffBlockFlag,
|
||||
@@ -135,12 +141,12 @@ var (
|
||||
utils.MinerExtraDataFlag,
|
||||
utils.MinerRecommitIntervalFlag,
|
||||
utils.MinerDelayLeftoverFlag,
|
||||
utils.MinerNewPayloadTimeout,
|
||||
// utils.MinerNewPayloadTimeout,
|
||||
utils.NATFlag,
|
||||
utils.NoDiscoverFlag,
|
||||
utils.DiscoveryV4Flag,
|
||||
utils.DiscoveryV5Flag,
|
||||
utils.LegacyDiscoveryV5Flag,
|
||||
utils.LegacyDiscoveryV5Flag, // deprecated
|
||||
utils.NetrestrictFlag,
|
||||
utils.NodeKeyFileFlag,
|
||||
utils.NodeKeyHexFlag,
|
||||
@@ -173,10 +179,10 @@ var (
|
||||
utils.HTTPListenAddrFlag,
|
||||
utils.HTTPPortFlag,
|
||||
utils.HTTPCORSDomainFlag,
|
||||
utils.AuthListenFlag,
|
||||
utils.AuthPortFlag,
|
||||
utils.AuthVirtualHostsFlag,
|
||||
utils.JWTSecretFlag,
|
||||
// utils.AuthListenFlag,
|
||||
// utils.AuthPortFlag,
|
||||
// utils.AuthVirtualHostsFlag,
|
||||
// utils.JWTSecretFlag,
|
||||
utils.HTTPVirtualHostsFlag,
|
||||
utils.GraphQLEnabledFlag,
|
||||
utils.GraphQLCORSDomainFlag,
|
||||
@@ -235,6 +241,7 @@ func init() {
|
||||
removedbCommand,
|
||||
dumpCommand,
|
||||
dumpGenesisCommand,
|
||||
dumpRootHashCommand,
|
||||
// See accountcmd.go:
|
||||
accountCommand,
|
||||
walletCommand,
|
||||
@@ -292,6 +299,9 @@ func main() {
|
||||
func prepare(ctx *cli.Context) {
|
||||
// If we're running a known preset, log it for convenience.
|
||||
switch {
|
||||
case ctx.IsSet(utils.ChapelFlag.Name):
|
||||
log.Info("Starting BSC on Chapel testnet...")
|
||||
|
||||
case ctx.IsSet(utils.DeveloperFlag.Name):
|
||||
log.Info("Starting Geth in ephemeral dev mode...")
|
||||
log.Warn(`You are running Geth in --dev mode. Please note the following:
|
||||
@@ -311,22 +321,18 @@ func prepare(ctx *cli.Context) {
|
||||
`)
|
||||
|
||||
case !ctx.IsSet(utils.NetworkIdFlag.Name):
|
||||
log.Info("Starting Geth on Ethereum mainnet...")
|
||||
log.Info("Starting Geth on BSC mainnet...")
|
||||
}
|
||||
// If we're a full node on mainnet without --cache specified, bump default cache allowance
|
||||
if ctx.String(utils.SyncModeFlag.Name) != "light" && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||
if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||
// Make sure we're not on any supported preconfigured testnet either
|
||||
if !ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||
if !ctx.IsSet(utils.DeveloperFlag.Name) &&
|
||||
!ctx.IsSet(utils.ChapelFlag.Name) {
|
||||
// Nope, we're really on mainnet. Bump that cache up!
|
||||
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
|
||||
ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096))
|
||||
}
|
||||
}
|
||||
// If we're running a light client on any network, drop the cache to some meaningfully low amount
|
||||
if ctx.String(utils.SyncModeFlag.Name) == "light" && !ctx.IsSet(utils.CacheFlag.Name) {
|
||||
log.Info("Dropping default light client cache", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 128)
|
||||
ctx.Set(utils.CacheFlag.Name, strconv.Itoa(128))
|
||||
}
|
||||
}
|
||||
|
||||
// geth is the main entry point into the system if no special subcommand is run.
|
||||
|
||||
@@ -55,6 +55,15 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func initGeth(t *testing.T) string {
|
||||
args := []string{"--networkid=42", "init", "./testdata/clique.json"}
|
||||
t.Logf("Initializing geth: %v ", args)
|
||||
g := runGeth(t, args...)
|
||||
datadir := g.Datadir
|
||||
g.WaitExit()
|
||||
return datadir
|
||||
}
|
||||
|
||||
// spawns geth with the given command line args. If the args don't set --datadir, the
|
||||
// child g gets a temporary data directory.
|
||||
func runGeth(t *testing.T, args ...string) *testgeth {
|
||||
|
||||
33
cmd/geth/testdata/bls-account-usage-demo.sh
vendored
Normal file
33
cmd/geth/testdata/bls-account-usage-demo.sh
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "0. prepare---------------------------------------------------------------------------------"
|
||||
echo 123abc7890 > bls-password.txt
|
||||
echo 123abc7891 > bls-password1.txt
|
||||
basedir=$(cd `dirname $0`; pwd)
|
||||
workspace=${basedir}/../../../
|
||||
|
||||
echo "1. create a bls account--------------------------------------------------------------------"
|
||||
${workspace}/build/bin/geth bls account new --blspassword ./bls-password.txt --datadir ./bls
|
||||
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
|
||||
|
||||
echo "2. import a bls account by passing file including a private key-----------------------------"
|
||||
secretKey=`${workspace}/build/bin/geth bls account new --show-private-key --blspassword ./bls-password1.txt --datadir ./bls1 | grep private | awk '{print $NF}'`
|
||||
echo ${secretKey} > ./bls1/secretKey
|
||||
${workspace}/build/bin/geth bls account import --blspassword ./bls-password.txt --datadir ./bls ./bls1/secretKey
|
||||
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
|
||||
|
||||
echo "3. delete the imported account above--------------------------------------------------------"
|
||||
publicKey=`${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls |grep public | tail -1 | awk '{print $NF}'`
|
||||
${workspace}/build/bin/geth bls account delete --blspassword ./bls-password.txt --datadir ./bls ${publicKey}
|
||||
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
|
||||
|
||||
echo "4. import a bls account by passing a keystore file------------------------------------------"
|
||||
keystoreFile=`ls bls1/bls/keystore`
|
||||
${workspace}/build/bin/geth bls account import --importedaccountpassword ./bls-password1.txt --blspassword ./bls-password.txt --datadir ./bls ./bls1/bls/keystore/${keystoreFile}
|
||||
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
|
||||
|
||||
echo "5. clearup----------------------------------------------------------------------------------"
|
||||
rm -rf bls
|
||||
rm -rf bls1
|
||||
rm -rf bls-password.txt
|
||||
rm -rf bls-password1.txt
|
||||
25
cmd/jsutils/README.md
Normal file
25
cmd/jsutils/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Requirement
|
||||
|
||||
- nodejs >= v16.20.2
|
||||
- npm >= v8.19.4
|
||||
|
||||
## Prepare
|
||||
Recommend use [nvm](https://github.com/nvm-sh/nvm) to manage node version.
|
||||
|
||||
Install node.js dependency:
|
||||
```shell script
|
||||
npm install
|
||||
```
|
||||
## Run
|
||||
mainnet validators version
|
||||
```bash
|
||||
npm run startMainnet
|
||||
```
|
||||
testnet validators version
|
||||
```bash
|
||||
npm run startTestnet
|
||||
```
|
||||
Transaction count
|
||||
```bash
|
||||
node gettxcount.js --rpc ${url} --startNum ${start} --endNum ${end} --miner ${miner} (optional)
|
||||
```
|
||||
38
cmd/jsutils/gettxcount.js
Normal file
38
cmd/jsutils/gettxcount.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
program.option("--rpc <rpc>", "Rpc");
|
||||
program.option("--startNum <startNum>", "start num")
|
||||
program.option("--endNum <endNum>", "end num")
|
||||
program.option("--miner <miner>", "miner", "")
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.rpc)
|
||||
|
||||
const main = async () => {
|
||||
let txCount = 0;
|
||||
let num = 0;
|
||||
console.log("Find the max txs count between", program.startNum, "and", program.endNum);
|
||||
for (let i = program.startNum; i < program.endNum; i++) {
|
||||
if (program.miner !== "") {
|
||||
let blockData = await provider.getBlock(Number(i))
|
||||
if (program.miner !== blockData.miner) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
let x = await provider.send("eth_getBlockTransactionCountByNumber", [
|
||||
ethers.toQuantity(i)]);
|
||||
let a = ethers.toNumber(x)
|
||||
if (a > txCount) {
|
||||
num = i;
|
||||
txCount = a;
|
||||
}
|
||||
}
|
||||
console.log("BlockNum = ", num, "TxCount =", txCount);
|
||||
};
|
||||
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
25
cmd/jsutils/getvalidatorversion.js
Normal file
25
cmd/jsutils/getvalidatorversion.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
program.option("--Rpc <Rpc>", "Rpc");
|
||||
program.option("--Num <Num>", "validator num", 21)
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.Rpc);
|
||||
|
||||
const main = async () => {
|
||||
const blockNum = await provider.getBlockNumber();
|
||||
console.log(blockNum);
|
||||
for (let i = 0; i < program.Num; i++) {
|
||||
let blockData = await provider.getBlock(blockNum - i);
|
||||
let major = ethers.toNumber(ethers.dataSlice(blockData.extraData, 2, 3))
|
||||
let minor = ethers.toNumber(ethers.dataSlice(blockData.extraData, 3, 4))
|
||||
let patch = ethers.toNumber(ethers.dataSlice(blockData.extraData, 4, 5))
|
||||
console.log(blockData.miner, "version =", major + "." + minor + "." + patch)
|
||||
}
|
||||
};
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
16
cmd/jsutils/package.json
Normal file
16
cmd/jsutils/package.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "jsutils",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"description": "jsUtils for bsc",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"startMainnet": "node getvalidatorversion.js --Rpc https://bsc-dataseed.bnbchain.org --Num 21",
|
||||
"startTestnet": "node getvalidatorversion.js --Rpc https://bsc-testnet-dataseed.bnbchain.org --Num 7"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": "^3.0.1",
|
||||
"ethers": "^6.2.3"
|
||||
},
|
||||
"author": "BNB Chain"
|
||||
}
|
||||
@@ -51,7 +51,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/eth/filters"
|
||||
@@ -63,7 +62,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/graphql"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
"github.com/ethereum/go-ethereum/les"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/metrics/exp"
|
||||
@@ -165,13 +163,18 @@ var (
|
||||
}
|
||||
NetworkIdFlag = &cli.Uint64Flag{
|
||||
Name: "networkid",
|
||||
Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia instead)",
|
||||
Usage: "Explicitly set network id (integer)(For testnets: use --chapel instead)",
|
||||
Value: ethconfig.Defaults.NetworkId,
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
MainnetFlag = &cli.BoolFlag{
|
||||
BSCMainnetFlag = &cli.BoolFlag{
|
||||
Name: "mainnet",
|
||||
Usage: "Ethereum mainnet",
|
||||
Usage: "BSC mainnet",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
ChapelFlag = &cli.BoolFlag{
|
||||
Name: "chapel",
|
||||
Usage: "Chapel network: pre-configured Proof-of-Stake-Authority BSC test network",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
DeveloperFlag = &cli.BoolFlag{
|
||||
@@ -286,6 +289,21 @@ var (
|
||||
Value: &defaultVerifyMode,
|
||||
Category: flags.FastNodeCategory,
|
||||
}
|
||||
RialtoHash = &cli.StringFlag{
|
||||
Name: "rialtohash",
|
||||
Usage: "Manually specify the Rialto Genesis Hash, to trigger builtin network logic",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideShanghai = &cli.Uint64Flag{
|
||||
Name: "override.shanghai",
|
||||
Usage: "Manually specify the Shanghai fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideKepler = &cli.Uint64Flag{
|
||||
Name: "override.kepler",
|
||||
Usage: "Manually specify the Kepler fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideCancun = &cli.Uint64Flag{
|
||||
Name: "override.cancun",
|
||||
Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting",
|
||||
@@ -296,9 +314,19 @@ var (
|
||||
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideFeynman = &cli.Uint64Flag{
|
||||
Name: "override.feynman",
|
||||
Usage: "Manually specify the Feynman fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideFeynmanFix = &cli.Uint64Flag{
|
||||
Name: "override.feynmanfix",
|
||||
Usage: "Manually specify the FeynmanFix fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
SyncModeFlag = &flags.TextMarshalerFlag{
|
||||
Name: "syncmode",
|
||||
Usage: `Blockchain sync mode ("snap", "full" or "light")`,
|
||||
Usage: `Blockchain sync mode ("snap" or "full")`,
|
||||
Value: &defaultSyncMode,
|
||||
Category: flags.StateCategory,
|
||||
}
|
||||
@@ -311,7 +339,6 @@ var (
|
||||
StateSchemeFlag = &cli.StringFlag{
|
||||
Name: "state.scheme",
|
||||
Usage: "Scheme to use for storing ethereum state ('hash' or 'path')",
|
||||
Value: rawdb.HashScheme,
|
||||
Category: flags.StateCategory,
|
||||
}
|
||||
PathDBSyncFlag = &cli.BoolFlag{
|
||||
@@ -332,41 +359,6 @@ var (
|
||||
Value: ethconfig.Defaults.TransactionHistory,
|
||||
Category: flags.StateCategory,
|
||||
}
|
||||
// Light server and client settings
|
||||
LightServeFlag = &cli.IntFlag{
|
||||
Name: "light.serve",
|
||||
Usage: "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)",
|
||||
Value: ethconfig.Defaults.LightServ,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightIngressFlag = &cli.IntFlag{
|
||||
Name: "light.ingress",
|
||||
Usage: "Incoming bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
|
||||
Value: ethconfig.Defaults.LightIngress,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightEgressFlag = &cli.IntFlag{
|
||||
Name: "light.egress",
|
||||
Usage: "Outgoing bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
|
||||
Value: ethconfig.Defaults.LightEgress,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightMaxPeersFlag = &cli.IntFlag{
|
||||
Name: "light.maxpeers",
|
||||
Usage: "Maximum number of light clients to serve, or light servers to attach to",
|
||||
Value: ethconfig.Defaults.LightPeers,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightNoPruneFlag = &cli.BoolFlag{
|
||||
Name: "light.nopruning",
|
||||
Usage: "Disable ancient light chain data pruning",
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightNoSyncServeFlag = &cli.BoolFlag{
|
||||
Name: "light.nosyncserve",
|
||||
Usage: "Enables serving light clients before syncing",
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
// Transaction pool settings
|
||||
TxPoolLocalsFlag = &cli.StringFlag{
|
||||
Name: "txpool.locals",
|
||||
@@ -433,9 +425,10 @@ var (
|
||||
Category: flags.TxPoolCategory,
|
||||
}
|
||||
TxPoolReannounceTimeFlag = &cli.DurationFlag{
|
||||
Name: "txpool.reannouncetime",
|
||||
Usage: "Duration for announcing local pending transactions again (default = 10 years, minimum = 1 minute)",
|
||||
Value: ethconfig.Defaults.TxPool.ReannounceTime,
|
||||
Name: "txpool.reannouncetime",
|
||||
Usage: "Duration for announcing local pending transactions again (default = 10 years, minimum = 1 minute)",
|
||||
Value: ethconfig.Defaults.TxPool.ReannounceTime,
|
||||
Category: flags.TxPoolCategory,
|
||||
}
|
||||
// Blob transaction pool settings
|
||||
BlobPoolDataDirFlag = &cli.StringFlag{
|
||||
@@ -511,7 +504,7 @@ var (
|
||||
PruneAncientDataFlag = &cli.BoolFlag{
|
||||
Name: "pruneancient",
|
||||
Usage: "Prune ancient data, is an optional config and disabled by default. Only keep the latest 9w blocks' data,the older blocks' data will be permanently pruned. Notice:the geth/chaindata/ancient dir will be removed, if restart without the flag, the ancient data will start with the previous point that the oldest unpruned block number. Recommends to the user who don't care about the ancient data.",
|
||||
Category: flags.HistoryCategory,
|
||||
Category: flags.BlockHistoryCategory,
|
||||
}
|
||||
CacheLogSizeFlag = &cli.IntFlag{
|
||||
Name: "cache.blocklogs",
|
||||
@@ -572,10 +565,10 @@ var (
|
||||
Category: flags.MinerCategory,
|
||||
}
|
||||
MinerNewPayloadTimeout = &cli.DurationFlag{
|
||||
Name: "miner.newpayload-timeout",
|
||||
Usage: "Specify the maximum time allowance for creating a new payload",
|
||||
Value: ethconfig.Defaults.Miner.NewPayloadTimeout,
|
||||
// Category: flags.MinerCategory,
|
||||
Name: "miner.newpayload-timeout",
|
||||
Usage: "Specify the maximum time allowance for creating a new payload",
|
||||
Value: ethconfig.Defaults.Miner.NewPayloadTimeout,
|
||||
Category: flags.MinerCategory,
|
||||
}
|
||||
|
||||
// Account settings
|
||||
@@ -1057,7 +1050,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||
BlockAmountReserved = &cli.Uint64Flag{
|
||||
Name: "block-amount-reserved",
|
||||
Usage: "Sets the expected remained amount of blocks for offline block prune",
|
||||
Category: flags.HistoryCategory,
|
||||
Category: flags.BlockHistoryCategory,
|
||||
}
|
||||
|
||||
CheckSnapshotWithMPT = &cli.BoolFlag{
|
||||
@@ -1069,7 +1062,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||
EnableDoubleSignMonitorFlag = &cli.BoolFlag{
|
||||
Name: "monitor.doublesign",
|
||||
Usage: "Enable double sign monitor to check whether any validator signs multiple blocks",
|
||||
Category: flags.FastFinalityCategory,
|
||||
Category: flags.MinerCategory,
|
||||
}
|
||||
|
||||
VotingEnabledFlag = &cli.BoolFlag{
|
||||
@@ -1092,14 +1085,14 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||
|
||||
BLSPasswordFileFlag = &cli.StringFlag{
|
||||
Name: "blspassword",
|
||||
Usage: "File path for the BLS password, which contains the password to unlock BLS wallet for managing votes in fast_finality feature",
|
||||
Category: flags.FastFinalityCategory,
|
||||
Usage: "Password file path for the BLS wallet, which contains the password to unlock BLS wallet for managing votes in fast_finality feature",
|
||||
Category: flags.AccountCategory,
|
||||
}
|
||||
|
||||
BLSWalletDirFlag = &flags.DirectoryFlag{
|
||||
Name: "blswallet",
|
||||
Usage: "Path for the blsWallet dir in fast finality feature (default = inside the datadir)",
|
||||
Category: flags.FastFinalityCategory,
|
||||
Category: flags.AccountCategory,
|
||||
}
|
||||
|
||||
VoteJournalDirFlag = &flags.DirectoryFlag{
|
||||
@@ -1111,25 +1104,22 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||
|
||||
var (
|
||||
// TestnetFlags is the flag group of all built-in supported testnets.
|
||||
TestnetFlags = []cli.Flag{}
|
||||
TestnetFlags = []cli.Flag{
|
||||
ChapelFlag,
|
||||
}
|
||||
// NetworkFlags is the flag group of all built-in supported networks.
|
||||
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
|
||||
NetworkFlags = append([]cli.Flag{BSCMainnetFlag}, TestnetFlags...)
|
||||
|
||||
// DatabasePathFlags is the flag group of all database path flags.
|
||||
DatabasePathFlags = []cli.Flag{
|
||||
DataDirFlag,
|
||||
AncientFlag,
|
||||
RemoteDBFlag,
|
||||
DBEngineFlag,
|
||||
HttpHeaderFlag,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
if rawdb.PebbleEnabled {
|
||||
DatabasePathFlags = append(DatabasePathFlags, DBEngineFlag)
|
||||
}
|
||||
}
|
||||
|
||||
// MakeDataDir retrieves the currently requested data directory, terminating
|
||||
// if none (or the empty string) is specified. If the node is starting a testnet,
|
||||
// then a subdirectory of the specified datadir will be used.
|
||||
@@ -1259,8 +1249,10 @@ func SplitAndTrim(input string) (ret []string) {
|
||||
// setHTTP creates the HTTP RPC listener interface string from the set
|
||||
// command line flags, returning empty if the HTTP endpoint is disabled.
|
||||
func setHTTP(ctx *cli.Context, cfg *node.Config) {
|
||||
if ctx.Bool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" {
|
||||
cfg.HTTPHost = "127.0.0.1"
|
||||
if ctx.Bool(HTTPEnabledFlag.Name) {
|
||||
if cfg.HTTPHost == "" {
|
||||
cfg.HTTPHost = "127.0.0.1"
|
||||
}
|
||||
if ctx.IsSet(HTTPListenAddrFlag.Name) {
|
||||
cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name)
|
||||
}
|
||||
@@ -1324,8 +1316,10 @@ func setGraphQL(ctx *cli.Context, cfg *node.Config) {
|
||||
// setWS creates the WebSocket RPC listener interface string from the set
|
||||
// command line flags, returning empty if the HTTP endpoint is disabled.
|
||||
func setWS(ctx *cli.Context, cfg *node.Config) {
|
||||
if ctx.Bool(WSEnabledFlag.Name) && cfg.WSHost == "" {
|
||||
cfg.WSHost = "127.0.0.1"
|
||||
if ctx.Bool(WSEnabledFlag.Name) {
|
||||
if cfg.WSHost == "" {
|
||||
cfg.WSHost = "127.0.0.1"
|
||||
}
|
||||
if ctx.IsSet(WSListenAddrFlag.Name) {
|
||||
cfg.WSHost = ctx.String(WSListenAddrFlag.Name)
|
||||
}
|
||||
@@ -1359,25 +1353,25 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
|
||||
}
|
||||
}
|
||||
|
||||
// setLes configures the les server and ultra light client settings from the command line flags.
|
||||
// setLes shows the deprecation warnings for LES flags.
|
||||
func setLes(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||
if ctx.IsSet(LightServeFlag.Name) {
|
||||
cfg.LightServ = ctx.Int(LightServeFlag.Name)
|
||||
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightServeFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(LightIngressFlag.Name) {
|
||||
cfg.LightIngress = ctx.Int(LightIngressFlag.Name)
|
||||
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightIngressFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(LightEgressFlag.Name) {
|
||||
cfg.LightEgress = ctx.Int(LightEgressFlag.Name)
|
||||
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightEgressFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(LightMaxPeersFlag.Name) {
|
||||
cfg.LightPeers = ctx.Int(LightMaxPeersFlag.Name)
|
||||
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightMaxPeersFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(LightNoPruneFlag.Name) {
|
||||
cfg.LightNoPrune = ctx.Bool(LightNoPruneFlag.Name)
|
||||
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoPruneFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(LightNoSyncServeFlag.Name) {
|
||||
cfg.LightNoSyncServe = ctx.Bool(LightNoSyncServeFlag.Name)
|
||||
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoSyncServeFlag.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1462,7 +1456,10 @@ func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||
|
||||
// MakePasswordList reads password lines from the file specified by the global --password flag.
|
||||
func MakePasswordList(ctx *cli.Context) []string {
|
||||
path := ctx.Path(PasswordFileFlag.Name)
|
||||
return MakePasswordListFromPath(ctx.Path(PasswordFileFlag.Name))
|
||||
}
|
||||
|
||||
func MakePasswordListFromPath(path string) []string {
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -1485,27 +1482,8 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
|
||||
setBootstrapNodes(ctx, cfg)
|
||||
setBootstrapNodesV5(ctx, cfg)
|
||||
|
||||
lightClient := ctx.String(SyncModeFlag.Name) == "light"
|
||||
lightServer := (ctx.Int(LightServeFlag.Name) != 0)
|
||||
|
||||
lightPeers := ctx.Int(LightMaxPeersFlag.Name)
|
||||
if lightClient && !ctx.IsSet(LightMaxPeersFlag.Name) {
|
||||
// dynamic default - for clients we use 1/10th of the default for servers
|
||||
lightPeers /= 10
|
||||
}
|
||||
|
||||
if ctx.IsSet(MaxPeersFlag.Name) {
|
||||
cfg.MaxPeers = ctx.Int(MaxPeersFlag.Name)
|
||||
if lightServer && !ctx.IsSet(LightMaxPeersFlag.Name) {
|
||||
cfg.MaxPeers += lightPeers
|
||||
}
|
||||
} else {
|
||||
if lightServer {
|
||||
cfg.MaxPeers += lightPeers
|
||||
}
|
||||
if lightClient && ctx.IsSet(LightMaxPeersFlag.Name) && cfg.MaxPeers < lightPeers {
|
||||
cfg.MaxPeers = lightPeers
|
||||
}
|
||||
}
|
||||
// if max peers per ip is not set, use max peers
|
||||
if cfg.MaxPeersPerIP <= 0 {
|
||||
@@ -1516,36 +1494,21 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
|
||||
cfg.MaxPeersPerIP = ctx.Int(MaxPeersPerIPFlag.Name)
|
||||
}
|
||||
|
||||
if !(lightClient || lightServer) {
|
||||
lightPeers = 0
|
||||
}
|
||||
ethPeers := cfg.MaxPeers - lightPeers
|
||||
if lightClient {
|
||||
ethPeers = 0
|
||||
}
|
||||
log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
|
||||
ethPeers := cfg.MaxPeers
|
||||
log.Info("Maximum peer count", "ETH", ethPeers, "total", cfg.MaxPeers)
|
||||
|
||||
if ctx.IsSet(MaxPendingPeersFlag.Name) {
|
||||
cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(NoDiscoverFlag.Name) || lightClient {
|
||||
if ctx.IsSet(NoDiscoverFlag.Name) {
|
||||
cfg.NoDiscovery = true
|
||||
}
|
||||
|
||||
// Disallow --nodiscover when used in conjunction with light mode.
|
||||
if (lightClient || lightServer) && ctx.Bool(NoDiscoverFlag.Name) {
|
||||
Fatalf("Cannot use --" + NoDiscoverFlag.Name + " in light client or light server mode")
|
||||
}
|
||||
CheckExclusive(ctx, DiscoveryV4Flag, NoDiscoverFlag)
|
||||
CheckExclusive(ctx, DiscoveryV5Flag, NoDiscoverFlag)
|
||||
cfg.DiscoveryV4 = ctx.Bool(DiscoveryV4Flag.Name)
|
||||
cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name)
|
||||
|
||||
// If we're running a light client or server, force enable the v5 peer discovery.
|
||||
if lightClient || lightServer {
|
||||
cfg.DiscoveryV5 = true
|
||||
}
|
||||
|
||||
if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" {
|
||||
list, err := netutil.ParseNetlist(netrestrict)
|
||||
if err != nil {
|
||||
@@ -1677,12 +1640,7 @@ func setBLSWalletDir(ctx *cli.Context, cfg *node.Config) {
|
||||
}
|
||||
}
|
||||
|
||||
func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
|
||||
// If we are running the light client, apply another group
|
||||
// settings for gas oracle.
|
||||
if light {
|
||||
*cfg = ethconfig.LightClientGPO
|
||||
}
|
||||
func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
|
||||
if ctx.IsSet(GpoBlocksFlag.Name) {
|
||||
cfg.Blocks = ctx.Int(GpoBlocksFlag.Name)
|
||||
}
|
||||
@@ -1842,13 +1800,12 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
|
||||
// SetEthConfig applies eth-related command line flags to the config.
|
||||
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
// Avoid conflicting network flags
|
||||
CheckExclusive(ctx, MainnetFlag, DeveloperFlag)
|
||||
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
|
||||
CheckExclusive(ctx, BSCMainnetFlag, DeveloperFlag)
|
||||
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||
|
||||
// Set configurations from CLI flags
|
||||
setEtherbase(ctx, cfg)
|
||||
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
|
||||
setGPO(ctx, &cfg.GPO)
|
||||
setTxPool(ctx, &cfg.TxPool)
|
||||
setMiner(ctx, &cfg.Miner)
|
||||
setRequiredBlocks(ctx, cfg)
|
||||
@@ -1900,7 +1857,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
if cfg.SyncMode == downloader.FullSync {
|
||||
cfg.PruneAncientData = ctx.Bool(PruneAncientDataFlag.Name)
|
||||
} else {
|
||||
log.Crit("pruneancient parameter didn't take effect for current syncmode")
|
||||
log.Crit("pruneancient parameter can only be used with syncmode=full")
|
||||
}
|
||||
}
|
||||
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
|
||||
@@ -1936,15 +1893,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
if ctx.IsSet(StateHistoryFlag.Name) {
|
||||
cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name)
|
||||
}
|
||||
// Parse state scheme, abort the process if it's not compatible.
|
||||
chaindb := tryMakeReadOnlyDatabase(ctx, stack)
|
||||
scheme, err := ParseStateScheme(ctx, chaindb)
|
||||
chaindb.Close()
|
||||
scheme, err := ParseCLIAndConfigStateScheme(ctx.String(StateSchemeFlag.Name), cfg.StateScheme)
|
||||
if err != nil {
|
||||
Fatalf("%v", err)
|
||||
}
|
||||
cfg.StateScheme = scheme
|
||||
|
||||
// Parse transaction history flag, if user is still using legacy config
|
||||
// file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'.
|
||||
if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit {
|
||||
@@ -1962,9 +1915,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
cfg.TransactionHistory = 0
|
||||
log.Warn("Disabled transaction unindexing for archive node")
|
||||
}
|
||||
if ctx.IsSet(LightServeFlag.Name) && cfg.TransactionHistory != 0 {
|
||||
log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
|
||||
}
|
||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
||||
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
||||
}
|
||||
@@ -2031,12 +1981,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
}
|
||||
// Override any default configs for hard coded networks.
|
||||
switch {
|
||||
case ctx.Bool(MainnetFlag.Name):
|
||||
case ctx.Bool(BSCMainnetFlag.Name):
|
||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||
cfg.NetworkId = 1
|
||||
cfg.NetworkId = 56
|
||||
}
|
||||
cfg.Genesis = core.DefaultGenesisBlock()
|
||||
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
|
||||
cfg.Genesis = core.DefaultBSCGenesisBlock()
|
||||
SetDNSDiscoveryDefaults(cfg, params.BSCGenesisHash)
|
||||
case ctx.Bool(ChapelFlag.Name):
|
||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||
cfg.NetworkId = 97
|
||||
}
|
||||
cfg.Genesis = core.DefaultChapelGenesisBlock()
|
||||
SetDNSDiscoveryDefaults(cfg, params.ChapelGenesisHash)
|
||||
case ctx.Bool(DeveloperFlag.Name):
|
||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||
cfg.NetworkId = 1337
|
||||
@@ -2095,7 +2051,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
readonly = false
|
||||
}
|
||||
// Check if we have an already initialized chain and fall back to
|
||||
// that if so. Otherwise we need to generate a new genesis spec.
|
||||
// that if so. Otherwise, we need to generate a new genesis spec.
|
||||
chaindb := MakeChainDatabase(ctx, stack, readonly, false)
|
||||
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
|
||||
cfg.Genesis = nil // fallback to db content
|
||||
@@ -2127,9 +2083,6 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
|
||||
return // already set through flags/config
|
||||
}
|
||||
protocol := "all"
|
||||
if cfg.SyncMode == downloader.LightSync {
|
||||
protocol = "les"
|
||||
}
|
||||
if url := params.KnownDNSNetwork(genesis, protocol); url != "" {
|
||||
cfg.EthDiscoveryURLs = []string{url}
|
||||
cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs
|
||||
@@ -2139,27 +2092,12 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
|
||||
}
|
||||
|
||||
// RegisterEthService adds an Ethereum client to the stack.
|
||||
// The second return value is the full node instance, which may be nil if the
|
||||
// node is running as a light client.
|
||||
// The second return value is the full node instance.
|
||||
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) {
|
||||
if cfg.SyncMode == downloader.LightSync {
|
||||
backend, err := les.New(stack, cfg)
|
||||
if err != nil {
|
||||
Fatalf("Failed to register the Ethereum service: %v", err)
|
||||
}
|
||||
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
|
||||
return backend.ApiBackend, nil
|
||||
}
|
||||
backend, err := eth.New(stack, cfg)
|
||||
if err != nil {
|
||||
Fatalf("Failed to register the Ethereum service: %v", err)
|
||||
}
|
||||
if cfg.LightServ > 0 {
|
||||
_, err := les.NewLesServer(stack, backend, cfg)
|
||||
if err != nil {
|
||||
Fatalf("Failed to create the LES server: %v", err)
|
||||
}
|
||||
}
|
||||
stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
|
||||
return backend.APIBackend, backend
|
||||
}
|
||||
@@ -2208,13 +2146,12 @@ func EnableMinerInfo(ctx *cli.Context, minerConfig miner.Config) SetupMetricsOpt
|
||||
|
||||
// RegisterFilterAPI adds the eth log filtering RPC API to the node.
|
||||
func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
|
||||
isLightClient := ethcfg.SyncMode == downloader.LightSync
|
||||
filterSystem := filters.NewFilterSystem(backend, filters.Config{
|
||||
LogCacheSize: ethcfg.FilterLogCacheSize,
|
||||
})
|
||||
stack.RegisterAPIs([]rpc.API{{
|
||||
Namespace: "eth",
|
||||
Service: filters.NewFilterAPI(filterSystem, isLightClient, ethcfg.RangeLimit),
|
||||
Service: filters.NewFilterAPI(filterSystem, ethcfg.RangeLimit),
|
||||
}})
|
||||
return filterSystem
|
||||
}
|
||||
@@ -2349,6 +2286,8 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree
|
||||
|
||||
// tryMakeReadOnlyDatabase try to open the chain database in read-only mode,
|
||||
// or fallback to write mode if the database is not initialized.
|
||||
//
|
||||
//nolint:unused
|
||||
func tryMakeReadOnlyDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
|
||||
// If datadir doesn't exist we need to open db in write-mode
|
||||
// so database engine can create files.
|
||||
@@ -2396,8 +2335,10 @@ func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error)
|
||||
func MakeGenesis(ctx *cli.Context) *core.Genesis {
|
||||
var genesis *core.Genesis
|
||||
switch {
|
||||
case ctx.Bool(MainnetFlag.Name):
|
||||
genesis = core.DefaultGenesisBlock()
|
||||
case ctx.Bool(BSCMainnetFlag.Name):
|
||||
genesis = core.DefaultBSCGenesisBlock()
|
||||
case ctx.Bool(ChapelFlag.Name):
|
||||
genesis = core.DefaultChapelGenesisBlock()
|
||||
case ctx.Bool(DeveloperFlag.Name):
|
||||
Fatalf("Developer chains are ephemeral")
|
||||
}
|
||||
@@ -2421,7 +2362,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
|
||||
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
|
||||
}
|
||||
scheme, err := ParseStateScheme(ctx, chainDb)
|
||||
scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), chainDb)
|
||||
if err != nil {
|
||||
Fatalf("%v", err)
|
||||
}
|
||||
@@ -2484,47 +2425,12 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
|
||||
return preloads
|
||||
}
|
||||
|
||||
// ParseStateScheme resolves scheme identifier from CLI flag. If the provided
|
||||
// state scheme is not compatible with the one of persistent scheme, an error
|
||||
// will be returned.
|
||||
//
|
||||
// - none: use the scheme consistent with persistent state, or fallback
|
||||
// to hash-based scheme if state is empty.
|
||||
// - hash: use hash-based scheme or error out if not compatible with
|
||||
// persistent state scheme.
|
||||
// - path: use path-based scheme or error out if not compatible with
|
||||
// persistent state scheme.
|
||||
func ParseStateScheme(ctx *cli.Context, disk ethdb.Database) (string, error) {
|
||||
// If state scheme is not specified, use the scheme consistent
|
||||
// with persistent state, or fallback to hash mode if database
|
||||
// is empty.
|
||||
stored := rawdb.ReadStateScheme(disk)
|
||||
if !ctx.IsSet(StateSchemeFlag.Name) {
|
||||
if stored == "" {
|
||||
// use default scheme for empty database, flip it when
|
||||
// path mode is chosen as default
|
||||
log.Info("State schema set to default", "scheme", "hash")
|
||||
return rawdb.HashScheme, nil
|
||||
}
|
||||
log.Info("State scheme set to already existing", "scheme", stored)
|
||||
return stored, nil // reuse scheme of persistent scheme
|
||||
}
|
||||
// If state scheme is specified, ensure it's compatible with
|
||||
// persistent state.
|
||||
scheme := ctx.String(StateSchemeFlag.Name)
|
||||
if stored == "" || scheme == stored {
|
||||
log.Info("State scheme set by user", "scheme", scheme)
|
||||
return scheme, nil
|
||||
}
|
||||
return "", fmt.Errorf("incompatible state scheme, stored: %s, provided: %s", stored, scheme)
|
||||
}
|
||||
|
||||
// MakeTrieDatabase constructs a trie database based on the configured scheme.
|
||||
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool) *trie.Database {
|
||||
config := &trie.Config{
|
||||
Preimages: preimage,
|
||||
}
|
||||
scheme, err := ParseStateScheme(ctx, disk)
|
||||
scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk)
|
||||
if err != nil {
|
||||
Fatalf("%v", err)
|
||||
}
|
||||
@@ -2542,3 +2448,22 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
|
||||
}
|
||||
return trie.NewDatabase(disk, config)
|
||||
}
|
||||
|
||||
// ParseCLIAndConfigStateScheme parses state scheme in CLI and config.
|
||||
func ParseCLIAndConfigStateScheme(cliScheme, cfgScheme string) (string, error) {
|
||||
if cliScheme == "" {
|
||||
if cfgScheme != "" {
|
||||
log.Info("Use config state scheme", "config", cfgScheme)
|
||||
}
|
||||
return cfgScheme, nil
|
||||
}
|
||||
|
||||
if !rawdb.ValidateStateScheme(cliScheme) {
|
||||
return "", fmt.Errorf("invalid state scheme in CLI: %s", cliScheme)
|
||||
}
|
||||
if cfgScheme == "" || cliScheme == cfgScheme {
|
||||
log.Info("Use CLI state scheme", "CLI", cliScheme)
|
||||
return cliScheme, nil
|
||||
}
|
||||
return "", fmt.Errorf("incompatible state scheme, CLI: %s, config: %s", cliScheme, cfgScheme)
|
||||
}
|
||||
|
||||
@@ -39,6 +39,12 @@ var DeprecatedFlags = []cli.Flag{
|
||||
CacheTrieRejournalFlag,
|
||||
LegacyDiscoveryV5Flag,
|
||||
TxLookupLimitFlag,
|
||||
LightServeFlag,
|
||||
LightIngressFlag,
|
||||
LightEgressFlag,
|
||||
LightMaxPeersFlag,
|
||||
LightNoPruneFlag,
|
||||
LightNoSyncServeFlag,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -77,6 +83,41 @@ var (
|
||||
Value: ethconfig.Defaults.TransactionHistory,
|
||||
Category: flags.DeprecatedCategory,
|
||||
}
|
||||
// Light server and client settings, Deprecated November 2023
|
||||
LightServeFlag = &cli.IntFlag{
|
||||
Name: "light.serve",
|
||||
Usage: "Maximum percentage of time allowed for serving LES requests (deprecated)",
|
||||
Value: ethconfig.Defaults.LightServ,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightIngressFlag = &cli.IntFlag{
|
||||
Name: "light.ingress",
|
||||
Usage: "Incoming bandwidth limit for serving light clients (deprecated)",
|
||||
Value: ethconfig.Defaults.LightIngress,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightEgressFlag = &cli.IntFlag{
|
||||
Name: "light.egress",
|
||||
Usage: "Outgoing bandwidth limit for serving light clients (deprecated)",
|
||||
Value: ethconfig.Defaults.LightEgress,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightMaxPeersFlag = &cli.IntFlag{
|
||||
Name: "light.maxpeers",
|
||||
Usage: "Maximum number of light clients to serve, or light servers to attach to (deprecated)",
|
||||
Value: ethconfig.Defaults.LightPeers,
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightNoPruneFlag = &cli.BoolFlag{
|
||||
Name: "light.nopruning",
|
||||
Usage: "Disable ancient light chain data pruning (deprecated)",
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
LightNoSyncServeFlag = &cli.BoolFlag{
|
||||
Name: "light.nosyncserve",
|
||||
Usage: "Enables serving light clients before syncing (deprecated)",
|
||||
Category: flags.LightCategory,
|
||||
}
|
||||
)
|
||||
|
||||
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
||||
|
||||
@@ -44,6 +44,12 @@ const (
|
||||
var (
|
||||
hashT = reflect.TypeOf(Hash{})
|
||||
addressT = reflect.TypeOf(Address{})
|
||||
|
||||
// MaxAddress represents the maximum possible address value.
|
||||
MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff")
|
||||
|
||||
// MaxHash represents the maximum possible hash value.
|
||||
MaxHash = HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||
)
|
||||
|
||||
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
||||
|
||||
@@ -150,7 +150,7 @@ type PoSA interface {
|
||||
IsSystemContract(to *common.Address) bool
|
||||
EnoughDistance(chain ChainReader, header *types.Header) bool
|
||||
IsLocalBlock(header *types.Header) bool
|
||||
GetJustifiedNumberAndHash(chain ChainHeaderReader, header *types.Header) (uint64, common.Hash, error)
|
||||
GetJustifiedNumberAndHash(chain ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error)
|
||||
GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
|
||||
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
|
||||
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool
|
||||
|
||||
@@ -21,6 +21,9 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
@@ -29,6 +32,16 @@ import (
|
||||
// - gas limit check
|
||||
// - basefee check
|
||||
func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Header) error {
|
||||
if config.Parlia == nil {
|
||||
// Verify that the gas limit remains within allowed bounds
|
||||
parentGasLimit := parent.GasLimit
|
||||
if !config.IsLondon(parent.Number) {
|
||||
parentGasLimit = parent.GasLimit * config.ElasticityMultiplier()
|
||||
}
|
||||
if err := misc.VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Verify the header is not malformed
|
||||
if header.BaseFee == nil {
|
||||
return errors.New("header is missing baseFee")
|
||||
@@ -45,5 +58,45 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
|
||||
|
||||
// CalcBaseFee calculates the basefee of the header.
|
||||
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||
return new(big.Int).SetUint64(params.InitialBaseFee)
|
||||
if config.Parlia != nil {
|
||||
return new(big.Int).SetUint64(params.InitialBaseFee)
|
||||
}
|
||||
|
||||
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
||||
if !config.IsLondon(parent.Number) {
|
||||
return new(big.Int).SetUint64(params.InitialBaseFee)
|
||||
}
|
||||
|
||||
parentGasTarget := parent.GasLimit / config.ElasticityMultiplier()
|
||||
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
|
||||
if parent.GasUsed == parentGasTarget {
|
||||
return new(big.Int).Set(parent.BaseFee)
|
||||
}
|
||||
|
||||
var (
|
||||
num = new(big.Int)
|
||||
denom = new(big.Int)
|
||||
)
|
||||
|
||||
if parent.GasUsed > parentGasTarget {
|
||||
// If the parent block used more gas than its target, the baseFee should increase.
|
||||
// max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
|
||||
num.SetUint64(parent.GasUsed - parentGasTarget)
|
||||
num.Mul(num, parent.BaseFee)
|
||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
||||
baseFeeDelta := math.BigMax(num, common.Big1)
|
||||
|
||||
return num.Add(parent.BaseFee, baseFeeDelta)
|
||||
} else {
|
||||
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
|
||||
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
|
||||
num.SetUint64(parentGasTarget - parent.GasUsed)
|
||||
num.Mul(num, parent.BaseFee)
|
||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
||||
baseFee := num.Sub(parent.BaseFee, num)
|
||||
|
||||
return math.BigMax(baseFee, common.Big0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,11 @@ func copyConfig(original *params.ChainConfig) *params.ChainConfig {
|
||||
|
||||
func config() *params.ChainConfig {
|
||||
config := copyConfig(params.TestChainConfig)
|
||||
config.Ethash = nil
|
||||
config.Parlia = ¶ms.ParliaConfig{
|
||||
Period: 3,
|
||||
Epoch: 200,
|
||||
}
|
||||
config.LondonBlock = big.NewInt(5)
|
||||
return config
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
235
consensus/parlia/feynmanfork.go
Normal file
235
consensus/parlia/feynmanfork.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts"
|
||||
"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/rpc"
|
||||
)
|
||||
|
||||
const SecondsPerDay uint64 = 86400
|
||||
|
||||
// the params should be two blocks' time(timestamp)
|
||||
func sameDayInUTC(first, second uint64) bool {
|
||||
return first/SecondsPerDay == second/SecondsPerDay
|
||||
}
|
||||
|
||||
func isBreatheBlock(lastBlockTime, blockTime uint64) bool {
|
||||
return lastBlockTime != 0 && !sameDayInUTC(lastBlockTime, blockTime)
|
||||
}
|
||||
|
||||
// initializeFeynmanContract initialize new contracts of Feynman fork
|
||||
func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.Header, chain core.ChainContext,
|
||||
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
|
||||
) error {
|
||||
// method
|
||||
method := "initialize"
|
||||
|
||||
// initialize contracts
|
||||
contracts := []string{
|
||||
systemcontracts.StakeHubContract,
|
||||
systemcontracts.GovernorContract,
|
||||
systemcontracts.GovTokenContract,
|
||||
systemcontracts.TimelockContract,
|
||||
systemcontracts.TokenRecoverPortalContract,
|
||||
}
|
||||
// get packed data
|
||||
data, err := p.stakeHubABI.Pack(method)
|
||||
if err != nil {
|
||||
log.Error("Unable to pack tx for initialize feynman contracts", "error", err)
|
||||
return err
|
||||
}
|
||||
for _, c := range contracts {
|
||||
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0)
|
||||
// apply message
|
||||
log.Info("initialize feynman contract", "block number", header.Number.Uint64(), "contract", c)
|
||||
err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ValidatorItem struct {
|
||||
address common.Address
|
||||
votingPower *big.Int
|
||||
voteAddress []byte
|
||||
}
|
||||
|
||||
// An ValidatorHeap is a max-heap of validator's votingPower.
|
||||
type ValidatorHeap []ValidatorItem
|
||||
|
||||
func (h *ValidatorHeap) Len() int { return len(*h) }
|
||||
|
||||
func (h *ValidatorHeap) Less(i, j int) bool {
|
||||
// We want topK validators with max voting power, so we need a max-heap
|
||||
if (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 0 {
|
||||
return (*h)[i].address.Hex() < (*h)[j].address.Hex()
|
||||
} else {
|
||||
return (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 1
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ValidatorHeap) Swap(i, j int) { (*h)[i], (*h)[j] = (*h)[j], (*h)[i] }
|
||||
|
||||
func (h *ValidatorHeap) Push(x interface{}) {
|
||||
*h = append(*h, x.(ValidatorItem))
|
||||
}
|
||||
|
||||
func (h *ValidatorHeap) Pop() interface{} {
|
||||
old := *h
|
||||
n := len(old)
|
||||
x := old[n-1]
|
||||
*h = old[0 : n-1]
|
||||
return x
|
||||
}
|
||||
|
||||
func (p *Parlia) updateValidatorSetV2(state *state.StateDB, header *types.Header, chain core.ChainContext,
|
||||
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
|
||||
) error {
|
||||
// 1. get all validators and its voting power
|
||||
blockNr := rpc.BlockNumberOrHashWithHash(header.ParentHash, false)
|
||||
validatorItems, err := p.getValidatorElectionInfo(blockNr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
maxElectedValidators, err := p.getMaxElectedValidators(blockNr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. sort by voting power
|
||||
eValidators, eVotingPowers, eVoteAddrs := getTopValidatorsByVotingPower(validatorItems, maxElectedValidators)
|
||||
|
||||
// 3. update validator set to system contract
|
||||
method := "updateValidatorSetV2"
|
||||
data, err := p.validatorSetABI.Pack(method, eValidators, eVotingPowers, eVoteAddrs)
|
||||
if err != nil {
|
||||
log.Error("Unable to pack tx for updateValidatorSetV2", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// get system message
|
||||
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0)
|
||||
// apply message
|
||||
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||
}
|
||||
|
||||
func (p *Parlia) getValidatorElectionInfo(blockNr rpc.BlockNumberOrHash) ([]ValidatorItem, error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
method := "getValidatorElectionInfo"
|
||||
toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
|
||||
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||
|
||||
data, err := p.stakeHubABI.Pack(method, big.NewInt(0), big.NewInt(0))
|
||||
if err != nil {
|
||||
log.Error("Unable to pack tx for getValidatorElectionInfo", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
msgData := (hexutil.Bytes)(data)
|
||||
|
||||
result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||
Gas: &gas,
|
||||
To: &toAddress,
|
||||
Data: &msgData,
|
||||
}, blockNr, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var validators []common.Address
|
||||
var votingPowers []*big.Int
|
||||
var voteAddrs [][]byte
|
||||
var totalLength *big.Int
|
||||
if err := p.stakeHubABI.UnpackIntoInterface(&[]interface{}{&validators, &votingPowers, &voteAddrs, &totalLength}, method, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if totalLength.Int64() != int64(len(validators)) || totalLength.Int64() != int64(len(votingPowers)) || totalLength.Int64() != int64(len(voteAddrs)) {
|
||||
return nil, fmt.Errorf("validator length not match")
|
||||
}
|
||||
|
||||
validatorItems := make([]ValidatorItem, len(validators))
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validatorItems[i] = ValidatorItem{
|
||||
address: validators[i],
|
||||
votingPower: votingPowers[i],
|
||||
voteAddress: voteAddrs[i],
|
||||
}
|
||||
}
|
||||
|
||||
return validatorItems, nil
|
||||
}
|
||||
|
||||
func (p *Parlia) getMaxElectedValidators(blockNr rpc.BlockNumberOrHash) (maxElectedValidators *big.Int, err error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
method := "maxElectedValidators"
|
||||
toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
|
||||
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||
|
||||
data, err := p.stakeHubABI.Pack(method)
|
||||
if err != nil {
|
||||
log.Error("Unable to pack tx for maxElectedValidators", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
msgData := (hexutil.Bytes)(data)
|
||||
|
||||
result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||
Gas: &gas,
|
||||
To: &toAddress,
|
||||
Data: &msgData,
|
||||
}, blockNr, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.stakeHubABI.UnpackIntoInterface(&maxElectedValidators, method, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return maxElectedValidators, nil
|
||||
}
|
||||
|
||||
func getTopValidatorsByVotingPower(validatorItems []ValidatorItem, maxElectedValidators *big.Int) ([]common.Address, []uint64, [][]byte) {
|
||||
var validatorHeap ValidatorHeap
|
||||
for i := 0; i < len(validatorItems); i++ {
|
||||
// only keep validators with voting power > 0
|
||||
if validatorItems[i].votingPower.Cmp(big.NewInt(0)) == 1 {
|
||||
validatorHeap = append(validatorHeap, validatorItems[i])
|
||||
}
|
||||
}
|
||||
hp := &validatorHeap
|
||||
heap.Init(hp)
|
||||
|
||||
topN := int(maxElectedValidators.Int64())
|
||||
if topN > len(validatorHeap) {
|
||||
topN = len(validatorHeap)
|
||||
}
|
||||
eValidators := make([]common.Address, topN)
|
||||
eVotingPowers := make([]uint64, topN)
|
||||
eVoteAddrs := make([][]byte, topN)
|
||||
for i := 0; i < topN; i++ {
|
||||
item := heap.Pop(hp).(ValidatorItem)
|
||||
eValidators[i] = item.address
|
||||
// as the decimal in BNB Beacon Chain is 1e8 and in BNB Smart Chain is 1e18, we need to divide it by 1e10
|
||||
eVotingPowers[i] = new(big.Int).Div(item.votingPower, big.NewInt(1e10)).Uint64()
|
||||
eVoteAddrs[i] = item.voteAddress
|
||||
}
|
||||
|
||||
return eValidators, eVotingPowers, eVoteAddrs
|
||||
}
|
||||
166
consensus/parlia/feynmanfork_test.go
Normal file
166
consensus/parlia/feynmanfork_test.go
Normal file
@@ -0,0 +1,166 @@
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func TestValidatorHeap(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
k int64
|
||||
validators []ValidatorItem
|
||||
expected []common.Address
|
||||
}{
|
||||
{
|
||||
description: "normal case",
|
||||
k: 2,
|
||||
validators: []ValidatorItem{
|
||||
{
|
||||
address: common.HexToAddress("0x1"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x1"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x2"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(200), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x2"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x3"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x3"),
|
||||
},
|
||||
},
|
||||
expected: []common.Address{
|
||||
common.HexToAddress("0x1"),
|
||||
common.HexToAddress("0x2"),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "same voting power",
|
||||
k: 2,
|
||||
validators: []ValidatorItem{
|
||||
{
|
||||
address: common.HexToAddress("0x1"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x1"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x2"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x2"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x3"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x3"),
|
||||
},
|
||||
},
|
||||
expected: []common.Address{
|
||||
common.HexToAddress("0x1"),
|
||||
common.HexToAddress("0x2"),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "zero voting power and k > len(validators)",
|
||||
k: 5,
|
||||
validators: []ValidatorItem{
|
||||
{
|
||||
address: common.HexToAddress("0x1"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x1"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x2"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x2"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x3"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x3"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x4"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x4"),
|
||||
},
|
||||
},
|
||||
expected: []common.Address{
|
||||
common.HexToAddress("0x1"),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "zero voting power and k < len(validators)",
|
||||
k: 2,
|
||||
validators: []ValidatorItem{
|
||||
{
|
||||
address: common.HexToAddress("0x1"),
|
||||
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||
voteAddress: []byte("0x1"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x2"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x2"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x3"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x3"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x4"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x4"),
|
||||
},
|
||||
},
|
||||
expected: []common.Address{
|
||||
common.HexToAddress("0x1"),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "all zero voting power",
|
||||
k: 2,
|
||||
validators: []ValidatorItem{
|
||||
{
|
||||
address: common.HexToAddress("0x1"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x1"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x2"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x2"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x3"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x3"),
|
||||
},
|
||||
{
|
||||
address: common.HexToAddress("0x4"),
|
||||
votingPower: big.NewInt(0),
|
||||
voteAddress: []byte("0x4"),
|
||||
},
|
||||
},
|
||||
expected: []common.Address{},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
eligibleValidators, _, _ := getTopValidatorsByVotingPower(tc.validators, big.NewInt(tc.k))
|
||||
|
||||
// check
|
||||
if len(eligibleValidators) != len(tc.expected) {
|
||||
t.Errorf("expected %d, got %d", len(tc.expected), len(eligibleValidators))
|
||||
}
|
||||
for i := 0; i < len(tc.expected); i++ {
|
||||
if eligibleValidators[i] != tc.expected[i] {
|
||||
t.Errorf("expected %s, got %s", tc.expected[i].Hex(), eligibleValidators[i].Hex())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
@@ -48,7 +47,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
inMemorySnapshots = 128 // Number of recent snapshots to keep in memory
|
||||
inMemorySnapshots = 256 // Number of recent snapshots to keep in memory
|
||||
inMemorySignatures = 4096 // Number of recent block signatures to keep in memory
|
||||
|
||||
checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database
|
||||
@@ -91,6 +90,11 @@ var (
|
||||
common.HexToAddress(systemcontracts.TokenHubContract): true,
|
||||
common.HexToAddress(systemcontracts.RelayerIncentivizeContract): true,
|
||||
common.HexToAddress(systemcontracts.CrossChainContract): true,
|
||||
common.HexToAddress(systemcontracts.StakeHubContract): true,
|
||||
common.HexToAddress(systemcontracts.GovernorContract): true,
|
||||
common.HexToAddress(systemcontracts.GovTokenContract): true,
|
||||
common.HexToAddress(systemcontracts.TimelockContract): true,
|
||||
common.HexToAddress(systemcontracts.TokenRecoverPortalContract): true,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -180,7 +184,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
|
||||
signature := header.Extra[len(header.Extra)-extraSeal:]
|
||||
|
||||
// Recover the public key and the Ethereum address
|
||||
pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature)
|
||||
pubkey, err := crypto.Ecrecover(types.SealHash(header, chainId).Bytes(), signature)
|
||||
if err != nil {
|
||||
return common.Address{}, err
|
||||
}
|
||||
@@ -200,7 +204,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
|
||||
// or not), which could be abused to produce different hashes for the same header.
|
||||
func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
|
||||
b := new(bytes.Buffer)
|
||||
encodeSigHeader(b, header, chainId)
|
||||
types.EncodeSigHeader(b, header, chainId)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@@ -227,6 +231,7 @@ type Parlia struct {
|
||||
validatorSetABIBeforeLuban abi.ABI
|
||||
validatorSetABI abi.ABI
|
||||
slashABI abi.ABI
|
||||
stakeHubABI abi.ABI
|
||||
|
||||
// The fields below are for testing only
|
||||
fakeDiff bool // Skip difficulty verifications
|
||||
@@ -241,6 +246,7 @@ func New(
|
||||
) *Parlia {
|
||||
// get parlia config
|
||||
parliaConfig := chainConfig.Parlia
|
||||
log.Info("Parlia", "chainConfig", chainConfig)
|
||||
|
||||
// Set any missing consensus parameters to their defaults
|
||||
if parliaConfig != nil && parliaConfig.Epoch == 0 {
|
||||
@@ -268,6 +274,10 @@ func New(
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
stABI, err := abi.JSON(strings.NewReader(stakeABI))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c := &Parlia{
|
||||
chainConfig: chainConfig,
|
||||
config: parliaConfig,
|
||||
@@ -279,6 +289,7 @@ func New(
|
||||
validatorSetABIBeforeLuban: vABIBeforeLuban,
|
||||
validatorSetABI: vABI,
|
||||
slashABI: sABI,
|
||||
stakeHubABI: stABI,
|
||||
signer: types.LatestSigner(chainConfig),
|
||||
}
|
||||
|
||||
@@ -446,7 +457,11 @@ func (p *Parlia) verifyVoteAttestation(chain consensus.ChainHeaderReader, header
|
||||
// The source block should be the highest justified block.
|
||||
sourceNumber := attestation.Data.SourceNumber
|
||||
sourceHash := attestation.Data.SourceHash
|
||||
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent)
|
||||
headers := []*types.Header{parent}
|
||||
if len(parents) > 0 {
|
||||
headers = parents
|
||||
}
|
||||
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, headers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unexpected error when getting the highest justified number and hash")
|
||||
}
|
||||
@@ -680,7 +695,7 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
|
||||
// If we're at the genesis, snapshot the initial state. Alternatively if we have
|
||||
// piled up more headers than allowed to be reorged (chain reinit from a freezer),
|
||||
// consider the checkpoint trusted and snapshot it.
|
||||
if number == 0 || (number%p.config.Epoch == 0 && (len(headers) > params.FullImmutabilityThreshold)) {
|
||||
if number == 0 || (number%p.config.Epoch == 0 && (len(headers) > params.FullImmutabilityThreshold/10)) {
|
||||
checkpoint := chain.GetHeaderByNumber(number)
|
||||
if checkpoint != nil {
|
||||
// get checkpoint data
|
||||
@@ -694,10 +709,12 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
|
||||
|
||||
// new snapshot
|
||||
snap = newSnapshot(p.config, p.signatures, number, hash, validators, voteAddrs, p.ethAPI)
|
||||
if err := snap.store(p.db); err != nil {
|
||||
return nil, err
|
||||
if snap.Number%checkpointInterval == 0 { // snapshot will only be loaded when snap.Number%checkpointInterval == 0
|
||||
if err := snap.store(p.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
|
||||
}
|
||||
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -828,6 +845,13 @@ func (p *Parlia) prepareValidators(header *types.Header) error {
|
||||
}
|
||||
} else {
|
||||
header.Extra = append(header.Extra, byte(len(newValidators)))
|
||||
if p.chainConfig.IsOnLuban(header.Number) {
|
||||
voteAddressMap = make(map[common.Address]*types.BLSPublicKey, len(newValidators))
|
||||
var zeroBlsKey types.BLSPublicKey
|
||||
for _, validator := range newValidators {
|
||||
voteAddressMap[validator] = &zeroBlsKey
|
||||
}
|
||||
}
|
||||
for _, validator := range newValidators {
|
||||
header.Extra = append(header.Extra, validator.Bytes()...)
|
||||
header.Extra = append(header.Extra, voteAddressMap[validator].Bytes()...)
|
||||
@@ -861,7 +885,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
|
||||
|
||||
// Prepare vote attestation
|
||||
// Prepare vote data
|
||||
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent)
|
||||
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{parent})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unexpected error when getting the highest justified number and hash")
|
||||
}
|
||||
@@ -894,7 +918,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
|
||||
// Prepare vote address bitset.
|
||||
for _, valInfo := range snap.Validators {
|
||||
if _, ok := voteAddrSet[valInfo.VoteAddress]; ok {
|
||||
attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) //Index is offset by 1
|
||||
attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) // Index is offset by 1
|
||||
}
|
||||
}
|
||||
validatorsBitSet := bitset.From([]uint64{uint64(attestation.VoteAddressSet)})
|
||||
@@ -989,6 +1013,13 @@ func (p *Parlia) verifyValidators(header *types.Header) error {
|
||||
return errMismatchingEpochValidators
|
||||
}
|
||||
validatorsBytes = make([]byte, validatorsNumber*validatorBytesLength)
|
||||
if p.chainConfig.IsOnLuban(header.Number) {
|
||||
voteAddressMap = make(map[common.Address]*types.BLSPublicKey, len(newValidators))
|
||||
var zeroBlsKey types.BLSPublicKey
|
||||
for _, validator := range newValidators {
|
||||
voteAddressMap[validator] = &zeroBlsKey
|
||||
}
|
||||
}
|
||||
for i, validator := range newValidators {
|
||||
copy(validatorsBytes[i*validatorBytesLength:], validator.Bytes())
|
||||
copy(validatorsBytes[i*validatorBytesLength+common.AddressLength:], voteAddressMap[validator].Bytes())
|
||||
@@ -1096,6 +1127,22 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
|
||||
|
||||
cx := chainContext{Chain: chain, parlia: p}
|
||||
|
||||
parent := chain.GetHeaderByHash(header.ParentHash)
|
||||
if parent == nil {
|
||||
return errors.New("parent not found")
|
||||
}
|
||||
|
||||
if p.chainConfig.IsFeynman(header.Number, header.Time) {
|
||||
systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
|
||||
}
|
||||
|
||||
if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||
err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
|
||||
if err != nil {
|
||||
log.Error("init feynman contract failed", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// No block rewards in PoA, so the state remains as is and uncles are dropped
|
||||
if header.Number.Cmp(common.Big1) == 0 {
|
||||
err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
|
||||
@@ -1137,6 +1184,17 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// update validators every day
|
||||
if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
|
||||
// we should avoid update validators in the Feynman upgrade block
|
||||
if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||
if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(*systemTxs) > 0 {
|
||||
return errors.New("the length of systemTxs do not match")
|
||||
}
|
||||
@@ -1155,6 +1213,23 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
|
||||
if receipts == nil {
|
||||
receipts = make([]*types.Receipt, 0)
|
||||
}
|
||||
|
||||
parent := chain.GetHeaderByHash(header.ParentHash)
|
||||
if parent == nil {
|
||||
return nil, nil, errors.New("parent not found")
|
||||
}
|
||||
|
||||
if p.chainConfig.IsFeynman(header.Number, header.Time) {
|
||||
systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
|
||||
}
|
||||
|
||||
if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||
err := p.initializeFeynmanContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
|
||||
if err != nil {
|
||||
log.Error("init feynman contract failed", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
if header.Number.Cmp(common.Big1) == 0 {
|
||||
err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
|
||||
if err != nil {
|
||||
@@ -1199,6 +1274,16 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
|
||||
}
|
||||
}
|
||||
|
||||
// update validators every day
|
||||
if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
|
||||
// we should avoid update validators in the Feynman upgrade block
|
||||
if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||
if err := p.updateValidatorSetV2(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// should not happen. Once happen, stop the node is better than broadcast the block
|
||||
if header.GasLimit < header.GasUsed {
|
||||
return nil, nil, errors.New("gas consumption of system txs exceed the gas limit")
|
||||
@@ -1249,7 +1334,7 @@ func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteE
|
||||
return fmt.Errorf("target number mismatch")
|
||||
}
|
||||
|
||||
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, header)
|
||||
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{header})
|
||||
if err != nil {
|
||||
log.Error("failed to get the highest justified number and hash", "headerNumber", header.Number, "headerHash", header.Hash())
|
||||
return fmt.Errorf("unexpected error when getting the highest justified number and hash")
|
||||
@@ -1401,7 +1486,7 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
|
||||
select {
|
||||
case results <- block.WithSeal(header):
|
||||
default:
|
||||
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
|
||||
log.Warn("Sealing result is not read by miner", "sealhash", types.SealHash(header, p.chainConfig.ChainID))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -1475,7 +1560,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
|
||||
// So it's not the real hash of a block, just used as unique id to distinguish task
|
||||
func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
encodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
|
||||
types.EncodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
@@ -1533,19 +1618,18 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNum *big.Int)
|
||||
|
||||
var valSet []common.Address
|
||||
var voteAddrSet []types.BLSPublicKey
|
||||
|
||||
if err := p.validatorSetABI.UnpackIntoInterface(&[]interface{}{&valSet, &voteAddrSet}, method, result); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
voteAddrmap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
|
||||
voteAddrMap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
|
||||
for i := 0; i < len(valSet); i++ {
|
||||
voteAddrmap[valSet[i]] = &(voteAddrSet)[i]
|
||||
voteAddrMap[valSet[i]] = &(voteAddrSet)[i]
|
||||
}
|
||||
return valSet, voteAddrmap, nil
|
||||
return valSet, voteAddrMap, nil
|
||||
}
|
||||
|
||||
// slash spoiled validators
|
||||
// distributeIncoming distributes system incoming of the block
|
||||
func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext,
|
||||
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
|
||||
coinbase := header.Coinbase
|
||||
@@ -1556,9 +1640,10 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
|
||||
state.SetBalance(consensus.SystemAddress, big.NewInt(0))
|
||||
state.AddBalance(coinbase, balance)
|
||||
|
||||
doDistributeSysReward := state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
|
||||
doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) &&
|
||||
state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
|
||||
if doDistributeSysReward {
|
||||
var rewards = new(big.Int)
|
||||
rewards := new(big.Int)
|
||||
rewards = rewards.Rsh(balance, systemRewardPercent)
|
||||
if rewards.Cmp(common.Big0) > 0 {
|
||||
err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||
@@ -1634,7 +1719,7 @@ func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, heade
|
||||
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||
}
|
||||
|
||||
// slash spoiled validators
|
||||
// distributeToValidator deposits validator reward to validator contract
|
||||
func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address,
|
||||
state *state.StateDB, header *types.Header, chain core.ChainContext,
|
||||
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
|
||||
@@ -1729,24 +1814,25 @@ func (p *Parlia) applyTransaction(
|
||||
receipt.BlockNumber = header.Number
|
||||
receipt.TransactionIndex = uint(state.TxIndex())
|
||||
*receipts = append(*receipts, receipt)
|
||||
state.SetNonce(msg.From(), nonce+1)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetJustifiedNumberAndHash returns the highest justified block's number and hash on the branch including and before `header`
|
||||
func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) {
|
||||
if chain == nil || header == nil {
|
||||
// GetJustifiedNumberAndHash retrieves the number and hash of the highest justified block
|
||||
// within the branch including `headers` and utilizing the latest element as the head.
|
||||
func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
|
||||
if chain == nil || len(headers) == 0 || headers[len(headers)-1] == nil {
|
||||
return 0, common.Hash{}, fmt.Errorf("illegal chain or header")
|
||||
}
|
||||
snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil)
|
||||
head := headers[len(headers)-1]
|
||||
snap, err := p.snapshot(chain, head.Number.Uint64(), head.Hash(), headers)
|
||||
if err != nil {
|
||||
log.Error("Unexpected error when getting snapshot",
|
||||
"error", err, "blockNumber", header.Number.Uint64(), "blockHash", header.Hash())
|
||||
"error", err, "blockNumber", head.Number.Uint64(), "blockHash", head.Hash())
|
||||
return 0, common.Hash{}, err
|
||||
}
|
||||
|
||||
if snap.Attestation == nil {
|
||||
if p.chainConfig.IsLuban(header.Number) {
|
||||
if p.chainConfig.IsLuban(head.Number) {
|
||||
log.Debug("once one attestation generated, attestation of snap would not be nil forever basically")
|
||||
}
|
||||
return 0, chain.GetHeaderByNumber(0).Hash(), nil
|
||||
@@ -1778,62 +1864,6 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t
|
||||
}
|
||||
|
||||
// =========================== utility function ==========================
|
||||
// SealHash returns the hash of a block prior to it being sealed.
|
||||
func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
encodeSigHeader(hasher, header, chainId)
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
|
||||
func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
|
||||
err := rlp.Encode(w, []interface{}{
|
||||
chainId,
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
header.Root,
|
||||
header.TxHash,
|
||||
header.ReceiptHash,
|
||||
header.Bloom,
|
||||
header.Difficulty,
|
||||
header.Number,
|
||||
header.GasLimit,
|
||||
header.GasUsed,
|
||||
header.Time,
|
||||
header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
panic("can't encode: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func encodeSigHeaderWithoutVoteAttestation(w io.Writer, header *types.Header, chainId *big.Int) {
|
||||
err := rlp.Encode(w, []interface{}{
|
||||
chainId,
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
header.Root,
|
||||
header.TxHash,
|
||||
header.ReceiptHash,
|
||||
header.Bloom,
|
||||
header.Difficulty,
|
||||
header.Number,
|
||||
header.GasLimit,
|
||||
header.GasUsed,
|
||||
header.Time,
|
||||
header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
panic("can't encode: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
|
||||
if snap.inturn(val) {
|
||||
return 0
|
||||
@@ -1951,6 +1981,8 @@ func applyMessage(
|
||||
// about the transaction and calling mechanisms.
|
||||
vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, state, chainConfig, vm.Config{})
|
||||
// Apply the transaction to the current state (included in the env)
|
||||
// Increment the nonce for the next transaction
|
||||
state.SetNonce(msg.From(), state.GetNonce(msg.From())+1)
|
||||
ret, returnGas, err := vmenv.Call(
|
||||
vm.AccountRef(msg.From()),
|
||||
*msg.To(),
|
||||
|
||||
@@ -199,6 +199,9 @@ func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.C
|
||||
}
|
||||
|
||||
// Update attestation
|
||||
// Two scenarios for s.Attestation being nil:
|
||||
// 1) The first attestation is assembled.
|
||||
// 2) The snapshot on disk is missing, prompting the creation of a new snapshot using `newSnapshot`.
|
||||
if s.Attestation != nil && attestation.Data.SourceNumber+1 != attestation.Data.TargetNumber {
|
||||
s.Attestation.TargetNumber = attestation.Data.TargetNumber
|
||||
s.Attestation.TargetHash = attestation.Data.TargetHash
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
mapset "github.com/deckarep/golang-set/v2"
|
||||
exlru "github.com/hashicorp/golang-lru"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
@@ -41,6 +42,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
@@ -58,6 +60,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
badBlockRecords = mapset.NewSet[common.Hash]()
|
||||
badBlockRecordslimit = 1000
|
||||
badBlockGauge = metrics.NewRegisteredGauge("chain/insert/badBlock", nil)
|
||||
|
||||
headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil)
|
||||
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
|
||||
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
|
||||
@@ -323,6 +329,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
|
||||
return nil, genesisErr
|
||||
}
|
||||
systemcontracts.GenesisHash = genesisHash
|
||||
log.Info("Initialised chain configuration", "config", chainConfig)
|
||||
// Description of chainConfig is empty now
|
||||
/*
|
||||
@@ -552,7 +559,7 @@ func (bc *BlockChain) GetVMConfig() *vm.Config {
|
||||
return &bc.vmConfig
|
||||
}
|
||||
|
||||
func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts) {
|
||||
func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts, block *types.Block) {
|
||||
// TODO, This is a hot fix for the block hash of logs is `0x0000000000000000000000000000000000000000000000000000000000000000` for system tx
|
||||
// Please check details in https://github.com/bnb-chain/bsc/issues/443
|
||||
// This is a temporary fix, the official fix should be a hard fork.
|
||||
@@ -563,6 +570,16 @@ func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts) {
|
||||
receipts[i].Logs[j].BlockHash = hash
|
||||
}
|
||||
}
|
||||
|
||||
txs := block.Transactions()
|
||||
if len(txs) != len(receipts) {
|
||||
log.Warn("transaction and receipt count mismatch")
|
||||
return
|
||||
}
|
||||
for i, receipt := range receipts {
|
||||
receipt.EffectiveGasPrice = txs[i].EffectiveGasTipValue(block.BaseFee()) // basefee is supposed to be nil or zero
|
||||
}
|
||||
|
||||
bc.receiptsCache.Add(hash, receipts)
|
||||
}
|
||||
|
||||
@@ -622,7 +639,7 @@ func (bc *BlockChain) empty() bool {
|
||||
// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
|
||||
func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 {
|
||||
if p, ok := bc.engine.(consensus.PoSA); ok {
|
||||
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(bc, header)
|
||||
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{header})
|
||||
if err == nil {
|
||||
return justifiedBlockNumber
|
||||
}
|
||||
@@ -1005,11 +1022,6 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// StateAtWithSharedPool returns a new mutable state based on a particular point in time with sharedStorage
|
||||
func (bc *BlockChain) StateAtWithSharedPool(root common.Hash) (*state.StateDB, error) {
|
||||
return state.NewWithSharedPool(root, bc.stateCache, bc.snaps)
|
||||
}
|
||||
|
||||
// Reset purges the entire blockchain, restoring it to its genesis state.
|
||||
func (bc *BlockChain) Reset() error {
|
||||
return bc.ResetWithGenesisBlock(bc.genesisBlock)
|
||||
@@ -2049,7 +2061,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||
vtime := time.Since(vstart)
|
||||
proctime := time.Since(start) // processing + validation
|
||||
|
||||
bc.cacheReceipts(block.Hash(), receipts)
|
||||
bc.cacheBlock(block.Hash(), block)
|
||||
|
||||
// Update the metrics touched during block processing and validation
|
||||
@@ -2082,6 +2093,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||
if err != nil {
|
||||
return it.index, err
|
||||
}
|
||||
|
||||
bc.cacheReceipts(block.Hash(), receipts, block)
|
||||
|
||||
// Update the metrics touched during block commit
|
||||
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
|
||||
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
|
||||
@@ -2906,15 +2920,22 @@ func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *pa
|
||||
if vcs != "" {
|
||||
vcs = fmt.Sprintf("\nVCS: %s", vcs)
|
||||
}
|
||||
|
||||
if badBlockRecords.Cardinality() < badBlockRecordslimit {
|
||||
badBlockRecords.Add(block.Hash())
|
||||
badBlockGauge.Update(int64(badBlockRecords.Cardinality()))
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`
|
||||
########## BAD BLOCK #########
|
||||
Block: %v (%#x)
|
||||
Miner: %v
|
||||
Error: %v
|
||||
Platform: %v%v
|
||||
Chain config: %#v
|
||||
Receipts: %v
|
||||
##############################
|
||||
`, block.Number(), block.Hash(), err, platform, vcs, config, receiptString)
|
||||
`, block.Number(), block.Hash(), block.Coinbase(), err, platform, vcs, config, receiptString)
|
||||
}
|
||||
|
||||
// InsertHeaderChain attempts to insert the given header chain in to the local
|
||||
|
||||
@@ -71,7 +71,7 @@ func (bc *BlockChain) CurrentSafeBlock() *types.Header {
|
||||
if currentHeader == nil {
|
||||
return nil
|
||||
}
|
||||
_, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, currentHeader)
|
||||
_, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{currentHeader})
|
||||
if err == nil {
|
||||
return bc.GetHeaderByHash(justifiedBlockHash)
|
||||
}
|
||||
|
||||
@@ -205,6 +205,10 @@ func (b *BlockGen) AddUncle(h *types.Header) {
|
||||
h.GasLimit = parent.GasLimit
|
||||
if b.config.IsLondon(h.Number) {
|
||||
h.BaseFee = eip1559.CalcBaseFee(b.config, parent)
|
||||
if b.config.Parlia == nil && !b.config.IsLondon(parent.Number) {
|
||||
parentGasLimit := parent.GasLimit * b.config.ElasticityMultiplier()
|
||||
h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
|
||||
}
|
||||
}
|
||||
b.uncles = append(b.uncles, h)
|
||||
}
|
||||
@@ -308,7 +312,11 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||
if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 {
|
||||
misc.ApplyDAOHardFork(statedb)
|
||||
}
|
||||
systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, statedb)
|
||||
|
||||
if !config.IsFeynman(b.header.Number, b.header.Time) {
|
||||
systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb)
|
||||
}
|
||||
|
||||
// Execute any user modifications to the block
|
||||
if gen != nil {
|
||||
gen(i, b)
|
||||
@@ -386,6 +394,10 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
|
||||
}
|
||||
if chain.Config().IsLondon(header.Number) {
|
||||
header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header())
|
||||
if chain.Config().Parlia == nil && !chain.Config().IsLondon(parent.Number()) {
|
||||
parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier()
|
||||
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
|
||||
}
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
192
core/genesis.go
192
core/genesis.go
@@ -23,8 +23,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@@ -32,7 +30,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
@@ -65,9 +62,9 @@ type Genesis struct {
|
||||
Number uint64 `json:"number"`
|
||||
GasUsed uint64 `json:"gasUsed"`
|
||||
ParentHash common.Hash `json:"parentHash"`
|
||||
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty" toml:",omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed,omitempty" toml:",omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
|
||||
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed,omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
|
||||
}
|
||||
|
||||
func ReadGenesis(db ethdb.Database) (*Genesis, error) {
|
||||
@@ -123,8 +120,8 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// deriveHash computes the state root according to the genesis specification.
|
||||
func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
||||
// hash computes the state root according to the genesis specification.
|
||||
func (ga *GenesisAlloc) hash() (common.Hash, error) {
|
||||
// Create an ephemeral in-memory database for computing hash,
|
||||
// all the derived states will be discarded to not pollute disk.
|
||||
db := state.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
@@ -145,9 +142,9 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
||||
return root, err
|
||||
}
|
||||
|
||||
// flush is very similar with deriveHash, but the main difference is
|
||||
// all the generated states will be persisted into the given database.
|
||||
// Also, the genesis state specification will be flushed as well.
|
||||
// flush is very similar with hash, but the main difference is all the generated
|
||||
// states will be persisted into the given database. Also, the genesis state
|
||||
// specification will be flushed as well.
|
||||
func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
|
||||
trieConfig := triedb.Config()
|
||||
if trieConfig != nil {
|
||||
@@ -202,8 +199,8 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash comm
|
||||
// - private network, can't recover
|
||||
var genesis *Genesis
|
||||
switch blockhash {
|
||||
case params.MainnetGenesisHash:
|
||||
genesis = DefaultGenesisBlock()
|
||||
case params.BSCGenesisHash:
|
||||
genesis = DefaultBSCGenesisBlock()
|
||||
}
|
||||
if genesis != nil {
|
||||
alloc = genesis.Alloc
|
||||
@@ -276,10 +273,15 @@ func (e *GenesisMismatchError) Error() string {
|
||||
return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
|
||||
}
|
||||
|
||||
// ChainOverrides contains the changes to chain config.
|
||||
// ChainOverrides contains the changes to chain config
|
||||
// Typically, these modifications involve hardforks that are not enabled on the BSC mainnet, intended for testing purposes.
|
||||
type ChainOverrides struct {
|
||||
OverrideCancun *uint64
|
||||
OverrideVerkle *uint64
|
||||
OverrideShanghai *uint64
|
||||
OverrideKepler *uint64
|
||||
OverrideCancun *uint64
|
||||
OverrideVerkle *uint64
|
||||
OverrideFeynman *uint64
|
||||
OverrideFeynmanFix *uint64
|
||||
}
|
||||
|
||||
// SetupGenesisBlock writes or updates the genesis block in db.
|
||||
@@ -305,21 +307,32 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
||||
}
|
||||
applyOverrides := func(config *params.ChainConfig) {
|
||||
if config != nil {
|
||||
if overrides != nil && overrides.OverrideShanghai != nil {
|
||||
config.ShanghaiTime = overrides.OverrideShanghai
|
||||
}
|
||||
if overrides != nil && overrides.OverrideKepler != nil {
|
||||
config.KeplerTime = overrides.OverrideKepler
|
||||
}
|
||||
if overrides != nil && overrides.OverrideCancun != nil {
|
||||
config.CancunTime = overrides.OverrideCancun
|
||||
}
|
||||
if overrides != nil && overrides.OverrideVerkle != nil {
|
||||
config.VerkleTime = overrides.OverrideVerkle
|
||||
}
|
||||
if overrides != nil && overrides.OverrideFeynman != nil {
|
||||
config.FeynmanTime = overrides.OverrideFeynman
|
||||
}
|
||||
if overrides != nil && overrides.OverrideFeynmanFix != nil {
|
||||
config.FeynmanFixTime = overrides.OverrideFeynmanFix
|
||||
}
|
||||
}
|
||||
}
|
||||
// Just commit the new block if there is no stored genesis block.
|
||||
stored := rawdb.ReadCanonicalHash(db, 0)
|
||||
systemcontracts.GenesisHash = stored
|
||||
if (stored == common.Hash{}) {
|
||||
if genesis == nil {
|
||||
log.Info("Writing default main-net genesis block")
|
||||
genesis = DefaultGenesisBlock()
|
||||
log.Info("Writing default BSC mainnet genesis block")
|
||||
genesis = DefaultBSCGenesisBlock()
|
||||
} else {
|
||||
log.Info("Writing custom genesis block")
|
||||
}
|
||||
@@ -328,6 +341,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
||||
return genesis.Config, common.Hash{}, err
|
||||
}
|
||||
applyOverrides(genesis.Config)
|
||||
log.Info("genesis block hash", "hash", block.Hash())
|
||||
return genesis.Config, block.Hash(), nil
|
||||
}
|
||||
// The genesis block is present(perhaps in ancient database) while the
|
||||
@@ -337,7 +351,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
||||
header := rawdb.ReadHeader(db, stored, 0)
|
||||
if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) {
|
||||
if genesis == nil {
|
||||
genesis = DefaultGenesisBlock()
|
||||
genesis = DefaultBSCGenesisBlock()
|
||||
}
|
||||
// Ensure the stored genesis matches with the given one.
|
||||
hash := genesis.ToBlock().Hash()
|
||||
@@ -398,14 +412,19 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
||||
return newcfg, stored, nil
|
||||
}
|
||||
|
||||
// LoadChainConfig loads the stored chain config if it is already present in
|
||||
// database, otherwise, return the config in the provided genesis specification.
|
||||
// LoadChainConfig retrieves the predefined chain configuration for the built-in network.
|
||||
// For non-built-in networks, it first attempts to load the stored chain configuration from the database.
|
||||
// If the configuration is not present, it returns the configuration specified in the provided genesis specification.
|
||||
func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
|
||||
// Load the stored chain config from the database. It can be nil
|
||||
// in case the database is empty. Notably, we only care about the
|
||||
// chain config corresponds to the canonical chain.
|
||||
stored := rawdb.ReadCanonicalHash(db, 0)
|
||||
if stored != (common.Hash{}) {
|
||||
builtInConf := params.GetBuiltInChainConfig(stored)
|
||||
if builtInConf != nil {
|
||||
return builtInConf, stored, nil
|
||||
}
|
||||
storedcfg := rawdb.ReadChainConfig(db, stored)
|
||||
if storedcfg != nil {
|
||||
return storedcfg, stored, nil
|
||||
@@ -431,76 +450,20 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig,
|
||||
return params.BSCChainConfig, params.BSCGenesisHash, nil
|
||||
}
|
||||
|
||||
// For any block in g.Config which is nil but the same block in defaultConfig is not
|
||||
// set the block in genesis config to the block in defaultConfig.
|
||||
// Reflection is used to avoid a long series of if statements with hardcoded block names.
|
||||
func (g *Genesis) setDefaultBlockValues(defaultConfig *params.ChainConfig) {
|
||||
// Regex to match block names
|
||||
blockRegex := regexp.MustCompile(`.*Block$`)
|
||||
|
||||
// Get reflect values
|
||||
gConfigElem := reflect.ValueOf(g.Config).Elem()
|
||||
defaultConfigElem := reflect.ValueOf(defaultConfig).Elem()
|
||||
|
||||
// Iterate over fields in config
|
||||
for i := 0; i < gConfigElem.NumField(); i++ {
|
||||
gConfigField := gConfigElem.Field(i)
|
||||
defaultConfigField := defaultConfigElem.Field(i)
|
||||
fieldName := gConfigElem.Type().Field(i).Name
|
||||
|
||||
// Use the regex to check if the field is a Block field
|
||||
if gConfigField.Kind() == reflect.Ptr && blockRegex.MatchString(fieldName) {
|
||||
if gConfigField.IsNil() {
|
||||
gConfigField.Set(defaultConfigField)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hard fork block height specified in config.toml has higher priority, but
|
||||
// if it is not specified in config.toml, use the default height in code.
|
||||
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
||||
var defaultConfig *params.ChainConfig
|
||||
switch {
|
||||
case ghash == params.MainnetGenesisHash:
|
||||
defaultConfig = params.MainnetChainConfig
|
||||
case ghash == params.BSCGenesisHash:
|
||||
defaultConfig = params.BSCChainConfig
|
||||
case ghash == params.ChapelGenesisHash:
|
||||
defaultConfig = params.ChapelChainConfig
|
||||
case ghash == params.RialtoGenesisHash:
|
||||
defaultConfig = params.RialtoChainConfig
|
||||
default:
|
||||
if g != nil {
|
||||
// it could be a custom config for QA test, just return
|
||||
return g.Config
|
||||
}
|
||||
defaultConfig = params.AllEthashProtocolChanges
|
||||
conf := params.GetBuiltInChainConfig(ghash)
|
||||
if conf != nil {
|
||||
return conf
|
||||
}
|
||||
if g == nil || g.Config == nil {
|
||||
return defaultConfig
|
||||
if g != nil {
|
||||
return g.Config // it could be a custom config for QA test, just return
|
||||
}
|
||||
|
||||
g.setDefaultBlockValues(defaultConfig)
|
||||
|
||||
// BSC Parlia set up
|
||||
if g.Config.Parlia == nil {
|
||||
g.Config.Parlia = defaultConfig.Parlia
|
||||
} else {
|
||||
if g.Config.Parlia.Period == 0 {
|
||||
g.Config.Parlia.Period = defaultConfig.Parlia.Period
|
||||
}
|
||||
if g.Config.Parlia.Epoch == 0 {
|
||||
g.Config.Parlia.Epoch = defaultConfig.Parlia.Epoch
|
||||
}
|
||||
}
|
||||
|
||||
return g.Config
|
||||
return params.AllEthashProtocolChanges
|
||||
}
|
||||
|
||||
// ToBlock returns the genesis block according to genesis specification.
|
||||
func (g *Genesis) ToBlock() *types.Block {
|
||||
root, err := g.Alloc.deriveHash()
|
||||
root, err := g.Alloc.hash()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -534,7 +497,7 @@ func (g *Genesis) ToBlock() *types.Block {
|
||||
var withdrawals []*types.Withdrawal
|
||||
if conf := g.Config; conf != nil {
|
||||
num := big.NewInt(int64(g.Number))
|
||||
if conf.IsShanghai(num, g.Timestamp) {
|
||||
if conf.Parlia == nil && conf.IsShanghai(num, g.Timestamp) {
|
||||
head.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||
withdrawals = make([]*types.Withdrawal, 0)
|
||||
}
|
||||
@@ -608,6 +571,38 @@ func DefaultGenesisBlock() *Genesis {
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultBSCGenesisBlock returns the BSC mainnet genesis block.
|
||||
func DefaultBSCGenesisBlock() *Genesis {
|
||||
alloc := decodePrealloc(bscMainnetAllocData)
|
||||
return &Genesis{
|
||||
Config: params.BSCChainConfig,
|
||||
Nonce: 0,
|
||||
ExtraData: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000002a7cdd959bfe8d9487b2a43b33565295a698f7e26488aa4d1955ee33403f8ccb1d4de5fb97c7ade29ef9f4360c606c7ab4db26b016007d3ad0ab86a0ee01c3b1283aa067c58eab4709f85e99d46de5fe685b1ded8013785d6623cc18d214320b6bb6475978f3adfc719c99674c072166708589033e2d9afec2be4ec20253b8642161bc3f444f53679c1f3d472f7be8361c80a4c1e7e9aaf001d0877f1cfde218ce2fd7544e0b2cc94692d4a704debef7bcb61328b8f7166496996a7da21cf1f1b04d9b3e26a3d0772d4c407bbe49438ed859fe965b140dcf1aab71a96bbad7cf34b5fa511d8e963dbba288b1960e75d64430b3230294d12c6ab2aac5c2cd68e80b16b581ea0a6e3c511bbd10f4519ece37dc24887e11b55d7ae2f5b9e386cd1b50a4550696d957cb4900f03a82012708dafc9e1b880fd083b32182b869be8e0922b81f8e175ffde54d797fe11eb03f9e3bf75f1d68bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d8c4d90829ce8f72d0163c1d5cf348a862d55063035e7a025f4da968de7e4d7e4004197917f4070f1d6caa02bbebaebb5d7e581e4b66559e635f805ff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
GasLimit: 40000000,
|
||||
Difficulty: big.NewInt(1),
|
||||
Mixhash: common.Hash(hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000")),
|
||||
Coinbase: common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE"),
|
||||
Timestamp: 0x5e9da7ce,
|
||||
Alloc: alloc,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultChapelGenesisBlock returns the BSC mainnet genesis block.
|
||||
func DefaultChapelGenesisBlock() *Genesis {
|
||||
alloc := decodePrealloc(bscChapelAllocData)
|
||||
return &Genesis{
|
||||
Config: params.ChapelChainConfig,
|
||||
Nonce: 0,
|
||||
ExtraData: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000001284214b9b9c85549ab3d2b972df0deef66ac2c9b71b214cb885500844365e95cd9942c7276e7fd8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0980a75ecd1309ea12fa2ed87a8744fbfc9b863d535552c16704d214347f29fa77f77da6d75d7c752f474cf03cceff28abc65c9cbae594f725c80e12d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
GasLimit: 40000000,
|
||||
Difficulty: big.NewInt(1),
|
||||
Mixhash: common.Hash(hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000")),
|
||||
Coinbase: common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE"),
|
||||
Timestamp: 0x5e9da7ce,
|
||||
Alloc: alloc,
|
||||
}
|
||||
}
|
||||
|
||||
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
||||
func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
|
||||
// Override the default period to the user requested one
|
||||
@@ -635,13 +630,34 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
|
||||
}
|
||||
|
||||
func decodePrealloc(data string) GenesisAlloc {
|
||||
var p []struct{ Addr, Balance *big.Int }
|
||||
var p []struct {
|
||||
Addr *big.Int
|
||||
Balance *big.Int
|
||||
Misc *struct {
|
||||
Nonce uint64
|
||||
Code []byte
|
||||
Slots []struct {
|
||||
Key common.Hash
|
||||
Val common.Hash
|
||||
}
|
||||
} `rlp:"optional"`
|
||||
}
|
||||
if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ga := make(GenesisAlloc, len(p))
|
||||
for _, account := range p {
|
||||
ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance}
|
||||
acc := GenesisAccount{Balance: account.Balance}
|
||||
if account.Misc != nil {
|
||||
acc.Nonce = account.Misc.Nonce
|
||||
acc.Code = account.Misc.Code
|
||||
|
||||
acc.Storage = make(map[common.Hash]common.Hash)
|
||||
for _, slot := range account.Misc.Slots {
|
||||
acc.Storage[slot.Key] = slot.Val
|
||||
}
|
||||
}
|
||||
ga[common.BigToAddress(account.Addr)] = acc
|
||||
}
|
||||
return ga
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -71,8 +71,8 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
|
||||
},
|
||||
wantHash: params.MainnetGenesisHash,
|
||||
wantConfig: params.MainnetChainConfig,
|
||||
wantHash: params.BSCGenesisHash,
|
||||
wantConfig: params.BSCChainConfig,
|
||||
},
|
||||
{
|
||||
name: "mainnet block in DB, genesis == nil",
|
||||
@@ -209,7 +209,7 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
|
||||
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
|
||||
{2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
|
||||
}
|
||||
hash, _ = alloc.deriveHash()
|
||||
hash, _ = alloc.hash()
|
||||
)
|
||||
blob, _ := json.Marshal(alloc)
|
||||
rawdb.WriteGenesisStateSpec(db, hash, blob)
|
||||
@@ -241,12 +241,12 @@ func TestConfigOrDefault(t *testing.T) {
|
||||
gHash := params.BSCGenesisHash
|
||||
config := defaultGenesis.configOrDefault(gHash)
|
||||
|
||||
if config.ChainID.Cmp(params.MainnetChainConfig.ChainID) != 0 {
|
||||
if config.ChainID.Cmp(params.BSCChainConfig.ChainID) != 0 {
|
||||
t.Errorf("ChainID of resulting config should be %v, but is %v instead", params.BSCChainConfig.ChainID, config.ChainID)
|
||||
}
|
||||
|
||||
if config.HomesteadBlock.Cmp(params.MainnetChainConfig.HomesteadBlock) != 0 {
|
||||
t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.MainnetChainConfig, config.HomesteadBlock)
|
||||
if config.HomesteadBlock.Cmp(params.BSCChainConfig.HomesteadBlock) != 0 {
|
||||
t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.BSCChainConfig, config.HomesteadBlock)
|
||||
}
|
||||
|
||||
if config.PlanckBlock == nil {
|
||||
@@ -258,34 +258,6 @@ func TestConfigOrDefault(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultBlockValues(t *testing.T) {
|
||||
genesis := &Genesis{Config: ¶ms.ChainConfig{ChainID: big.NewInt(66), HomesteadBlock: big.NewInt(11)}}
|
||||
genesis.setDefaultBlockValues(params.BSCChainConfig)
|
||||
|
||||
// Make sure the non-nil block was not modified
|
||||
if genesis.Config.HomesteadBlock.Cmp(big.NewInt(11)) != 0 {
|
||||
t.Errorf("Homestead block should not have been modified. HomesteadBlock = %v", genesis.Config.HomesteadBlock)
|
||||
}
|
||||
|
||||
// Spot check a few blocks
|
||||
if genesis.Config.NielsBlock.Cmp(params.BSCChainConfig.NielsBlock) != 0 {
|
||||
t.Errorf("Niels block not matching: in genesis = %v , in defaultConfig = %v", genesis.Config.NielsBlock, params.BSCChainConfig.NielsBlock)
|
||||
}
|
||||
|
||||
if genesis.Config.NanoBlock.Cmp(params.BSCChainConfig.NanoBlock) != 0 {
|
||||
t.Errorf("Nano block not matching: in genesis = %v , in defaultConfig = %v", genesis.Config.NanoBlock, params.BSCChainConfig.NanoBlock)
|
||||
}
|
||||
|
||||
if genesis.Config.PlanckBlock.Cmp(params.BSCChainConfig.PlanckBlock) != 0 {
|
||||
t.Errorf("Nano block not matching: in genesis = %v , in defaultConfig = %v", genesis.Config.PlanckBlock, params.BSCChainConfig.PlanckBlock)
|
||||
}
|
||||
|
||||
// Lastly make sure non-block fields such as ChainID have not been modified
|
||||
if genesis.Config.ChainID.Cmp(big.NewInt(66)) != 0 {
|
||||
t.Errorf("ChainID should not have been modified. ChainID = %v", genesis.Config.ChainID)
|
||||
}
|
||||
}
|
||||
|
||||
func newDbConfig(scheme string) *trie.Config {
|
||||
if scheme == rawdb.HashScheme {
|
||||
return trie.HashDefaults
|
||||
|
||||
@@ -113,7 +113,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
|
||||
// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
|
||||
func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 {
|
||||
if p, ok := hc.engine.(consensus.PoSA); ok {
|
||||
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(hc, header)
|
||||
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(hc, []*types.Header{header})
|
||||
if err == nil {
|
||||
return justifiedBlockNumber
|
||||
}
|
||||
|
||||
@@ -32,24 +32,51 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
type allocItem struct{ Addr, Balance *big.Int }
|
||||
type allocItem struct {
|
||||
Addr *big.Int
|
||||
Balance *big.Int
|
||||
Misc *allocItemMisc `rlp:"optional"`
|
||||
}
|
||||
|
||||
type allocItemMisc struct {
|
||||
Nonce uint64
|
||||
Code []byte
|
||||
Slots []allocItemStorageItem
|
||||
}
|
||||
|
||||
type allocItemStorageItem struct {
|
||||
Key common.Hash
|
||||
Val common.Hash
|
||||
}
|
||||
|
||||
func makelist(g *core.Genesis) []allocItem {
|
||||
items := make([]allocItem, 0, len(g.Alloc))
|
||||
for addr, account := range g.Alloc {
|
||||
var misc *allocItemMisc
|
||||
if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 {
|
||||
panic(fmt.Sprintf("can't encode account %x", addr))
|
||||
misc = &allocItemMisc{
|
||||
Nonce: account.Nonce,
|
||||
Code: account.Code,
|
||||
Slots: make([]allocItemStorageItem, 0, len(account.Storage)),
|
||||
}
|
||||
for key, val := range account.Storage {
|
||||
misc.Slots = append(misc.Slots, allocItemStorageItem{key, val})
|
||||
}
|
||||
slices.SortFunc(misc.Slots, func(a, b allocItemStorageItem) int {
|
||||
return a.Key.Cmp(b.Key)
|
||||
})
|
||||
}
|
||||
bigAddr := new(big.Int).SetBytes(addr.Bytes())
|
||||
items = append(items, allocItem{bigAddr, account.Balance})
|
||||
items = append(items, allocItem{bigAddr, account.Balance, misc})
|
||||
}
|
||||
slices.SortFunc(items, func(a, b allocItem) bool {
|
||||
return a.Addr.Cmp(b.Addr) < 0
|
||||
slices.SortFunc(items, func(a, b allocItem) int {
|
||||
return a.Addr.Cmp(b.Addr)
|
||||
})
|
||||
return items
|
||||
}
|
||||
|
||||
@@ -305,3 +305,47 @@ func ReadStateScheme(db ethdb.Reader) string {
|
||||
}
|
||||
return HashScheme
|
||||
}
|
||||
|
||||
// ValidateStateScheme used to check state scheme whether is valid.
|
||||
// Valid state scheme: hash and path.
|
||||
func ValidateStateScheme(stateScheme string) bool {
|
||||
if stateScheme == HashScheme || stateScheme == PathScheme {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ParseStateScheme checks if the specified state scheme is compatible with
|
||||
// the stored state.
|
||||
//
|
||||
// - If the provided scheme is none, use the scheme consistent with persistent
|
||||
// state, or fallback to hash-based scheme if state is empty.
|
||||
//
|
||||
// - If the provided scheme is hash, use hash-based scheme or error out if not
|
||||
// compatible with persistent state scheme.
|
||||
//
|
||||
// - If the provided scheme is path: use path-based scheme or error out if not
|
||||
// compatible with persistent state scheme.
|
||||
func ParseStateScheme(provided string, disk ethdb.Database) (string, error) {
|
||||
// If state scheme is not specified, use the scheme consistent
|
||||
// with persistent state, or fallback to hash mode if database
|
||||
// is empty.
|
||||
stored := ReadStateScheme(disk)
|
||||
if provided == "" {
|
||||
if stored == "" {
|
||||
// use default scheme for empty database, flip it when
|
||||
// path mode is chosen as default
|
||||
log.Info("State scheme set to default", "scheme", "hash")
|
||||
return HashScheme, nil
|
||||
}
|
||||
log.Info("State scheme set to already existing disk db", "scheme", stored)
|
||||
return stored, nil // reuse scheme of persistent scheme
|
||||
}
|
||||
// If state scheme is specified, ensure it's compatible with
|
||||
// persistent state.
|
||||
if stored == "" || provided == stored {
|
||||
log.Info("State scheme set by user", "scheme", provided)
|
||||
return provided, nil
|
||||
}
|
||||
return "", fmt.Errorf("incompatible state scheme, stored: %s, user provided: %s", stored, provided)
|
||||
}
|
||||
|
||||
34
core/rawdb/accessors_trie_test.go
Normal file
34
core/rawdb/accessors_trie_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package rawdb
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestValidateStateScheme(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
wantResult bool
|
||||
}{
|
||||
{
|
||||
name: "hash scheme",
|
||||
arg: HashScheme,
|
||||
wantResult: true,
|
||||
},
|
||||
{
|
||||
name: "path scheme",
|
||||
arg: PathScheme,
|
||||
wantResult: true,
|
||||
},
|
||||
{
|
||||
name: "invalid scheme",
|
||||
arg: "mockScheme",
|
||||
wantResult: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ValidateStateScheme(tt.arg); got != tt.wantResult {
|
||||
t.Errorf("ValidateStateScheme() = %v, want %v", got, tt.wantResult)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -129,6 +129,8 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
|
||||
switch freezerName {
|
||||
case chainFreezerName:
|
||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||
case stateFreezerName:
|
||||
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
||||
default:
|
||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/ethdb/leveldb"
|
||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
@@ -218,25 +219,28 @@ func NewFreezerDb(db ethdb.KeyValueStore, frz, namespace string, readonly bool,
|
||||
|
||||
// resolveChainFreezerDir is a helper function which resolves the absolute path
|
||||
// of chain freezer by considering backward compatibility.
|
||||
//
|
||||
// rules:
|
||||
// 1. in path mode, block data is stored in chain dir and state data is in state dir.
|
||||
// 2. in hash mode, block data is stored in chain dir or ancient dir(before big merge), no state dir.
|
||||
func resolveChainFreezerDir(ancient string) string {
|
||||
// Check if the chain freezer is already present in the specified
|
||||
// sub folder, if not then two possibilities:
|
||||
// - chain freezer is not initialized
|
||||
// - chain freezer exists in legacy location (root ancient folder)
|
||||
freezer := path.Join(ancient, chainFreezerName)
|
||||
if !common.FileExist(freezer) {
|
||||
if !common.FileExist(ancient) {
|
||||
// The entire ancient store is not initialized, still use the sub
|
||||
// folder for initialization.
|
||||
} else {
|
||||
// Ancient root is already initialized, then we hold the assumption
|
||||
// that chain freezer is also initialized and located in root folder.
|
||||
// In this case fallback to legacy location.
|
||||
freezer = ancient
|
||||
log.Info("Found legacy ancient chain path", "location", ancient)
|
||||
}
|
||||
chain := path.Join(ancient, chainFreezerName)
|
||||
state := path.Join(ancient, stateFreezerName)
|
||||
if common.FileExist(chain) {
|
||||
return chain
|
||||
}
|
||||
return freezer
|
||||
if common.FileExist(state) {
|
||||
return chain
|
||||
}
|
||||
if common.FileExist(ancient) {
|
||||
log.Info("Found legacy ancient chain path", "location", ancient)
|
||||
chain = ancient
|
||||
}
|
||||
return chain
|
||||
}
|
||||
|
||||
// NewDatabaseWithFreezer creates a high level database on top of a given key-
|
||||
@@ -263,6 +267,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
WriteAncientType(db, PruneFreezerType)
|
||||
}
|
||||
return &freezerdb{
|
||||
ancientRoot: ancient,
|
||||
KeyValueStore: db,
|
||||
AncientStore: frdb,
|
||||
}, nil
|
||||
@@ -335,7 +340,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
break
|
||||
}
|
||||
}
|
||||
// We are about to exit on error. Print database metdata beore exiting
|
||||
// We are about to exit on error. Print database metdata before exiting
|
||||
printChainMetadata(db)
|
||||
return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
|
||||
frozen-1, number, head)
|
||||
@@ -364,7 +369,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
// freezer.
|
||||
}
|
||||
}
|
||||
// no prune ancinet start success
|
||||
// no prune ancient start success
|
||||
if !readonly {
|
||||
WriteAncientType(db, EntireFreezerType)
|
||||
}
|
||||
@@ -425,6 +430,16 @@ func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient
|
||||
return frdb, nil
|
||||
}
|
||||
|
||||
// NewPebbleDBDatabase creates a persistent key-value database without a freezer
|
||||
// moving immutable chain segments into cold storage.
|
||||
func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
db, err := pebble.New(file, cache, handles, namespace, readonly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewDatabase(db), nil
|
||||
}
|
||||
|
||||
const (
|
||||
dbPebble = "pebble"
|
||||
dbLeveldb = "leveldb"
|
||||
@@ -480,12 +495,8 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
|
||||
return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb)
|
||||
}
|
||||
if o.Type == dbPebble || existingDb == dbPebble {
|
||||
if PebbleEnabled {
|
||||
log.Info("Using pebble as the backing database")
|
||||
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
} else {
|
||||
return nil, errors.New("db.engine 'pebble' not supported on this platform")
|
||||
}
|
||||
log.Info("Using pebble as the backing database")
|
||||
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
if o.Type == dbLeveldb || existingDb == dbLeveldb {
|
||||
log.Info("Using leveldb as the backing database")
|
||||
@@ -493,10 +504,8 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
|
||||
}
|
||||
// No pre-existing database, no user-requested one either. Default to Pebble
|
||||
// on supported platforms and LevelDB on anything else.
|
||||
// if PebbleEnabled {
|
||||
// log.Info("Defaulting to pebble as the backing database")
|
||||
// return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
// }
|
||||
log.Info("Defaulting to leveldb as the backing database")
|
||||
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
@@ -511,6 +520,11 @@ func Open(o OpenOptions) (ethdb.Database, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ReadAncientType(kvdb) == PruneFreezerType {
|
||||
if !o.PruneAncientData {
|
||||
log.Warn("Disk db is pruned")
|
||||
}
|
||||
}
|
||||
if len(o.AncientsDirectory) == 0 {
|
||||
return kvdb, nil
|
||||
}
|
||||
@@ -551,6 +565,7 @@ func (s *stat) Size() string {
|
||||
func (s *stat) Count() string {
|
||||
return s.count.String()
|
||||
}
|
||||
|
||||
func AncientInspect(db ethdb.Database) error {
|
||||
offset := counter(ReadOffSetOfCurrentAncientFreezer(db))
|
||||
// Get number of ancient rows inside the freezer.
|
||||
|
||||
@@ -15,3 +15,80 @@
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package rawdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
mockChainFreezerPath = "/geth/chaindata/ancient/chain"
|
||||
mockStateFreezerPath = "/geth/chaindata/ancient/state"
|
||||
mockAncientFreezerPath = "/geth/chaindata/ancient"
|
||||
)
|
||||
|
||||
func Test_resolveChainFreezerDir(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fn func(dir string) string
|
||||
ancient string
|
||||
wantedResult string
|
||||
}{
|
||||
{
|
||||
// chain dir is existent, so it should be returned.
|
||||
name: "1",
|
||||
fn: func(dir string) string {
|
||||
path := fmt.Sprintf("%s%s", dir, mockChainFreezerPath)
|
||||
if err := os.MkdirAll(path, 0700); err != nil {
|
||||
t.Fatalf("Failed to mkdir all dirs, error: %v", err)
|
||||
}
|
||||
return fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
|
||||
},
|
||||
wantedResult: mockChainFreezerPath,
|
||||
},
|
||||
{
|
||||
// chain dir is nonexistent and state dir is existent; so chain
|
||||
// dir should be returned.
|
||||
name: "2",
|
||||
fn: func(dir string) string {
|
||||
path := fmt.Sprintf("%s%s", dir, mockStateFreezerPath)
|
||||
if err := os.MkdirAll(path, 0700); err != nil {
|
||||
t.Fatalf("Failed to mkdir all dirs, error: %v", err)
|
||||
}
|
||||
return fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
|
||||
},
|
||||
wantedResult: mockChainFreezerPath,
|
||||
},
|
||||
{
|
||||
// both chain dir and state dir are nonexistent, if ancient dir is
|
||||
// existent, so ancient dir should be returned.
|
||||
name: "3",
|
||||
fn: func(dir string) string {
|
||||
path := fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
|
||||
if err := os.MkdirAll(path, 0700); err != nil {
|
||||
t.Fatalf("Failed to mkdir all dirs, error: %v", err)
|
||||
}
|
||||
return path
|
||||
},
|
||||
wantedResult: mockAncientFreezerPath,
|
||||
},
|
||||
{
|
||||
// ancient dir is nonexistent, so chain dir should be returned.
|
||||
name: "4",
|
||||
fn: func(dir string) string {
|
||||
return fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
|
||||
},
|
||||
wantedResult: mockChainFreezerPath,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
got := resolveChainFreezerDir(tt.fn(tempDir))
|
||||
if got != fmt.Sprintf("%s%s", tempDir, tt.wantedResult) {
|
||||
t.Fatalf("resolveChainFreezerDir() = %s, wanted = %s", got, tt.wantedResult)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright 2023 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
//go:build (arm64 || amd64) && !openbsd
|
||||
|
||||
package rawdb
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||
)
|
||||
|
||||
// Pebble is unsuported on 32bit architecture
|
||||
const PebbleEnabled = true
|
||||
|
||||
// NewPebbleDBDatabase creates a persistent key-value database without a freezer
|
||||
// moving immutable chain segments into cold storage.
|
||||
func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
db, err := pebble.New(file, cache, handles, namespace, readonly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewDatabase(db), nil
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2023 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !((arm64 || amd64) && !openbsd)
|
||||
|
||||
package rawdb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
)
|
||||
|
||||
// Pebble is unsuported on 32bit architecture
|
||||
const PebbleEnabled = false
|
||||
|
||||
// NewPebbleDBDatabase creates a persistent key-value database without a freezer
|
||||
// moving immutable chain segments into cold storage.
|
||||
func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
return nil, errors.New("pebble is not supported on this platform")
|
||||
}
|
||||
@@ -152,7 +152,7 @@ func NewFreezer(datadir string, namespace string, readonly bool, offset uint64,
|
||||
}
|
||||
|
||||
// Some blocks in ancientDB may have already been frozen and been pruned, so adding the offset to
|
||||
// reprensent the absolute number of blocks already frozen.
|
||||
// represent the absolute number of blocks already frozen.
|
||||
freezer.frozen.Add(offset)
|
||||
freezer.tail.Add(offset)
|
||||
|
||||
|
||||
@@ -188,19 +188,27 @@ func (batch *freezerTableBatch) maybeCommit() error {
|
||||
|
||||
// commit writes the batched items to the backing freezerTable.
|
||||
func (batch *freezerTableBatch) commit() error {
|
||||
// Write data.
|
||||
// Write data. The head file is fsync'd after write to ensure the
|
||||
// data is truly transferred to disk.
|
||||
_, err := batch.t.head.Write(batch.dataBuffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := batch.t.head.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
dataSize := int64(len(batch.dataBuffer))
|
||||
batch.dataBuffer = batch.dataBuffer[:0]
|
||||
|
||||
// Write indices.
|
||||
// Write indices. The index file is fsync'd after write to ensure the
|
||||
// data indexes are truly transferred to disk.
|
||||
_, err = batch.t.index.Write(batch.indexBuffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := batch.t.index.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
indexSize := int64(len(batch.indexBuffer))
|
||||
batch.indexBuffer = batch.indexBuffer[:0]
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
const tmpSuffix = ".tmp"
|
||||
@@ -240,6 +241,7 @@ func cleanup(path string) error {
|
||||
}
|
||||
for _, name := range names {
|
||||
if name == filepath.Base(path)+tmpSuffix {
|
||||
log.Info("Removed leftover freezer directory", "name", name)
|
||||
return os.RemoveAll(filepath.Join(parent, name))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,9 @@ func (t *freezerTable) repair() error {
|
||||
if t.readonly {
|
||||
return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize)
|
||||
}
|
||||
truncateFreezerFile(t.index, stat.Size()-overflow) // New file can't trigger this path
|
||||
if err := truncateFreezerFile(t.index, stat.Size()-overflow); err != nil {
|
||||
return err
|
||||
} // New file can't trigger this path
|
||||
}
|
||||
// Retrieve the file sizes and prepare for truncation
|
||||
if stat, err = t.index.Stat(); err != nil {
|
||||
@@ -265,6 +267,12 @@ func (t *freezerTable) repair() error {
|
||||
t.index.ReadAt(buffer, offsetsSize-indexEntrySize)
|
||||
lastIndex.unmarshalBinary(buffer)
|
||||
}
|
||||
// Print an error log if the index is corrupted due to an incorrect
|
||||
// last index item. While it is theoretically possible to have a zero offset
|
||||
// by storing all zero-size items, it is highly unlikely to occur in practice.
|
||||
if lastIndex.offset == 0 && offsetsSize/indexEntrySize > 1 {
|
||||
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "indexes", offsetsSize/indexEntrySize)
|
||||
}
|
||||
if t.readonly {
|
||||
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
|
||||
} else {
|
||||
@@ -357,7 +365,7 @@ func (t *freezerTable) repair() error {
|
||||
return err
|
||||
}
|
||||
if verbose {
|
||||
t.logger.Info("Chain freezer table opened", "items", t.items.Load(), "size", t.headBytes)
|
||||
t.logger.Info("Chain freezer table opened", "items", t.items.Load(), "deleted", t.itemOffset.Load(), "hidden", t.itemHidden.Load(), "tailId", t.tailId, "headId", t.headId, "size", t.headBytes)
|
||||
} else {
|
||||
t.logger.Debug("Chain freezer table opened", "items", t.items.Load(), "size", common.StorageSize(t.headBytes))
|
||||
}
|
||||
@@ -418,6 +426,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
||||
if err := truncateFreezerFile(t.index, int64(length+1)*indexEntrySize); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.index.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Calculate the new expected size of the data file and truncate it
|
||||
var expected indexEntry
|
||||
if length == 0 {
|
||||
@@ -440,6 +451,7 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
||||
// Release any files _after the current head -- both the previous head
|
||||
// and any files which may have been opened for reading
|
||||
t.releaseFilesAfter(expected.filenum, true)
|
||||
|
||||
// Set back the historic head
|
||||
t.head = newHead
|
||||
t.headId = expected.filenum
|
||||
@@ -447,6 +459,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
||||
if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.head.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
// All data files truncated, set internal counters and return
|
||||
t.headBytes = int64(expected.offset)
|
||||
t.items.Store(items)
|
||||
@@ -530,6 +545,10 @@ func (t *freezerTable) truncateTail(items uint64) error {
|
||||
if err := t.meta.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Close the index file before shorten it.
|
||||
if err := t.index.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Truncate the deleted index entries from the index file.
|
||||
err = copyFrom(t.index.Name(), t.index.Name(), indexEntrySize*(newDeleted-deleted+1), func(f *os.File) error {
|
||||
tailIndex := indexEntry{
|
||||
@@ -543,13 +562,14 @@ func (t *freezerTable) truncateTail(items uint64) error {
|
||||
return err
|
||||
}
|
||||
// Reopen the modified index file to load the changes
|
||||
if err := t.index.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
t.index, err = openFreezerFileForAppend(t.index.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Sync the file to ensure changes are flushed to disk
|
||||
if err := t.index.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Release any files before the current tail
|
||||
t.tailId = newTailId
|
||||
t.itemOffset.Store(newDeleted)
|
||||
@@ -586,10 +606,12 @@ func (t *freezerTable) Close() error {
|
||||
// error on Windows.
|
||||
doClose(t.index, true, true)
|
||||
doClose(t.meta, true, true)
|
||||
|
||||
// The preopened non-head data-files are all opened in readonly.
|
||||
// The head is opened in rw-mode, so we sync it here - but since it's also
|
||||
// part of t.files, it will be closed in the loop below.
|
||||
doClose(t.head, true, false) // sync but do not close
|
||||
|
||||
for _, f := range t.files {
|
||||
doClose(f, false, true) // close but do not sync
|
||||
}
|
||||
@@ -782,7 +804,7 @@ func (t *freezerTable) retrieveItems(start, count, maxBytes uint64) ([]byte, []i
|
||||
return fmt.Errorf("missing data file %d", fileId)
|
||||
}
|
||||
if _, err := dataFile.ReadAt(output[len(output)-length:], int64(start)); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("%w, fileid: %d, start: %d, length: %d", err, fileId, start, length)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -73,11 +73,7 @@ func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) e
|
||||
return err
|
||||
}
|
||||
f = nil
|
||||
|
||||
if err := os.Rename(fname, destPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return os.Rename(fname, destPath)
|
||||
}
|
||||
|
||||
// openFreezerFileForAppend opens a freezer table file and seeks to the end
|
||||
|
||||
@@ -57,7 +57,7 @@ func newPrunedFreezer(datadir string, db ethdb.KeyValueStore, offset uint64) (*p
|
||||
|
||||
// delete ancient dir
|
||||
if err := os.RemoveAll(datadir); err != nil && !os.IsNotExist(err) {
|
||||
log.Warn("remove the ancient dir failed.", "path", datadir, "error", err)
|
||||
log.Warn("Failed to remove the ancient dir", "path", datadir, "error", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Info("Opened ancientdb with nodata mode", "database", datadir, "frozen", freezer.frozen)
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@@ -37,6 +38,7 @@ type DumpConfig struct {
|
||||
OnlyWithAddresses bool
|
||||
Start []byte
|
||||
Max uint64
|
||||
StateScheme string
|
||||
}
|
||||
|
||||
// DumpCollector interface which the state trie calls during iteration
|
||||
@@ -57,7 +59,6 @@ type DumpAccount struct {
|
||||
Storage map[common.Hash]string `json:"storage,omitempty"`
|
||||
Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode
|
||||
SecureKey hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key
|
||||
|
||||
}
|
||||
|
||||
// Dump represents the full dump in a collected format, as one large map.
|
||||
@@ -177,7 +178,13 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
|
||||
}
|
||||
if !conf.SkipStorage {
|
||||
account.Storage = make(map[common.Hash]string)
|
||||
tr, err := obj.getTrie()
|
||||
var tr Trie
|
||||
if conf.StateScheme == rawdb.PathScheme {
|
||||
tr, err = trie.NewStateTrie(trie.StorageTrieID(obj.db.originalRoot, common.BytesToHash(it.Key),
|
||||
obj.data.Root), obj.db.db.TrieDB())
|
||||
} else {
|
||||
tr, err = obj.getTrie()
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("Failed to load storage trie", "err", err)
|
||||
continue
|
||||
|
||||
@@ -378,8 +378,11 @@ func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace str
|
||||
|
||||
// If the items in freezer is less than the block amount that we want to reserve, it is not enough, should stop.
|
||||
if itemsOfAncient < p.BlockAmountReserved {
|
||||
log.Error("the number of old blocks is not enough to reserve,", "ancient items", itemsOfAncient, "the amount specified", p.BlockAmountReserved)
|
||||
log.Error("the number of old blocks is not enough to reserve", "ancient items", itemsOfAncient, "the amount specified", p.BlockAmountReserved)
|
||||
return errors.New("the number of old blocks is not enough to reserve")
|
||||
} else if itemsOfAncient == p.BlockAmountReserved {
|
||||
log.Error("the number of old blocks is the same to be reserved", "ancient items", itemsOfAncient, "the amount specified", p.BlockAmountReserved)
|
||||
return errors.New("the number of old blocks is the same to be reserved")
|
||||
}
|
||||
|
||||
var oldOffSet uint64
|
||||
|
||||
@@ -365,21 +365,15 @@ func generateTrieRoot(db ethdb.KeyValueWriter, scheme string, it Iterator, accou
|
||||
}
|
||||
|
||||
func stackTrieGenerate(db ethdb.KeyValueWriter, scheme string, owner common.Hash, in chan trieKV, out chan common.Hash) {
|
||||
var nodeWriter trie.NodeWriteFunc
|
||||
options := trie.NewStackTrieOptions()
|
||||
if db != nil {
|
||||
nodeWriter = func(owner common.Hash, path []byte, hash common.Hash, blob []byte) {
|
||||
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
|
||||
rawdb.WriteTrieNode(db, owner, path, hash, blob, scheme)
|
||||
}
|
||||
})
|
||||
}
|
||||
t := trie.NewStackTrieWithOwner(nodeWriter, owner)
|
||||
t := trie.NewStackTrie(options)
|
||||
for leaf := range in {
|
||||
t.Update(leaf.key[:], leaf.value)
|
||||
}
|
||||
var root common.Hash
|
||||
if db == nil {
|
||||
root = t.Hash()
|
||||
} else {
|
||||
root, _ = t.Commit()
|
||||
}
|
||||
out <- root
|
||||
out <- t.Commit()
|
||||
}
|
||||
|
||||
@@ -1363,10 +1363,12 @@ func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (boo
|
||||
nodes = trienode.NewNodeSet(addrHash)
|
||||
slots = make(map[common.Hash][]byte)
|
||||
)
|
||||
stack := trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, blob []byte) {
|
||||
options := trie.NewStackTrieOptions()
|
||||
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
|
||||
nodes.AddNode(path, trienode.NewDeleted())
|
||||
size += common.StorageSize(len(path))
|
||||
})
|
||||
stack := trie.NewStackTrie(options)
|
||||
for iter.Next() {
|
||||
if size > storageDeleteLimit {
|
||||
return true, size, nil, nil, nil
|
||||
|
||||
@@ -73,8 +73,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||
misc.ApplyDAOHardFork(statedb)
|
||||
}
|
||||
// Handle upgrade build-in system contract code
|
||||
systemcontracts.UpgradeBuildInSystemContract(p.config, block.Number(), statedb)
|
||||
|
||||
lastBlock := p.bc.GetBlockByHash(block.ParentHash())
|
||||
if lastBlock == nil {
|
||||
return statedb, nil, nil, 0, fmt.Errorf("could not get parent block")
|
||||
}
|
||||
if !p.config.IsFeynman(block.Number(), block.Time()) {
|
||||
// Handle upgrade build-in system contract code
|
||||
systemcontracts.UpgradeBuildInSystemContract(p.config, blockNumber, lastBlock.Time(), block.Time(), statedb)
|
||||
}
|
||||
|
||||
var (
|
||||
context = NewEVMBlockContext(header, p.bc, nil)
|
||||
|
||||
@@ -138,7 +138,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||
)
|
||||
|
||||
defer blockchain.Stop()
|
||||
bigNumber := new(big.Int).SetBytes(common.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
|
||||
bigNumber := new(big.Int).SetBytes(common.MaxHash.Bytes())
|
||||
tooBigNumber := new(big.Int).Set(bigNumber)
|
||||
tooBigNumber.Add(tooBigNumber, common.Big1)
|
||||
for i, tt := range []struct {
|
||||
|
||||
@@ -13,4 +13,10 @@ const (
|
||||
TokenManagerContract = "0x0000000000000000000000000000000000001008"
|
||||
CrossChainContract = "0x0000000000000000000000000000000000002000"
|
||||
StakingContract = "0x0000000000000000000000000000000000002001"
|
||||
StakeHubContract = "0x0000000000000000000000000000000000002002"
|
||||
StakeCreditContract = "0x0000000000000000000000000000000000002003"
|
||||
GovernorContract = "0x0000000000000000000000000000000000002004"
|
||||
GovTokenContract = "0x0000000000000000000000000000000000002005"
|
||||
TimelockContract = "0x0000000000000000000000000000000000002006"
|
||||
TokenRecoverPortalContract = "0x0000000000000000000000000000000000003000"
|
||||
)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -57,10 +57,6 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAlreadyKnown is returned if the transactions is already contained
|
||||
// within the pool.
|
||||
ErrAlreadyKnown = errors.New("already known")
|
||||
|
||||
// ErrTxPoolOverflow is returned if the transaction pool is full and can't accept
|
||||
// another remote transaction.
|
||||
ErrTxPoolOverflow = errors.New("txpool is full")
|
||||
@@ -715,7 +711,7 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e
|
||||
if pool.all.Get(hash) != nil {
|
||||
log.Trace("Discarding already known transaction", "hash", hash)
|
||||
knownTxMeter.Mark(1)
|
||||
return false, ErrAlreadyKnown
|
||||
return false, txpool.ErrAlreadyKnown
|
||||
}
|
||||
// Make the local flag. If it's from local source or it's from the network but
|
||||
// the sender is marked as local previously, treat it as the local transaction.
|
||||
@@ -1027,6 +1023,9 @@ func (pool *LegacyPool) addRemoteSync(tx *types.Transaction) error {
|
||||
|
||||
// addTxs attempts to queue a batch of transactions if they are valid.
|
||||
func (pool *LegacyPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
|
||||
// Do not treat as local if local transactions have been disabled
|
||||
local = local && !pool.config.NoLocals
|
||||
|
||||
// Filter out known ones without obtaining the pool lock or recovering signatures
|
||||
var (
|
||||
errs = make([]error, len(txs))
|
||||
@@ -1035,7 +1034,7 @@ func (pool *LegacyPool) addTxs(txs []*types.Transaction, local, sync bool) []err
|
||||
for i, tx := range txs {
|
||||
// If the transaction is known, pre-set the error slot
|
||||
if pool.all.Get(tx.Hash()) != nil {
|
||||
errs[i] = ErrAlreadyKnown
|
||||
errs[i] = txpool.ErrAlreadyKnown
|
||||
knownTxMeter.Mark(1)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@@ -560,8 +562,7 @@ func (d *DiffLayer) DecodeRLP(s *rlp.Stream) error {
|
||||
if err := s.Decode(&ed); err != nil {
|
||||
return err
|
||||
}
|
||||
d.BlockHash, d.Number, d.Codes, d.Destructs, d.Accounts, d.Storages =
|
||||
ed.BlockHash, ed.Number, ed.Codes, ed.Destructs, ed.Accounts, ed.Storages
|
||||
d.BlockHash, d.Number, d.Codes, d.Destructs, d.Accounts, d.Storages = ed.BlockHash, ed.Number, ed.Codes, ed.Destructs, ed.Accounts, ed.Storages
|
||||
|
||||
d.Receipts = make([]*Receipt, len(ed.Receipts))
|
||||
for i, storageReceipt := range ed.Receipts {
|
||||
@@ -608,6 +609,7 @@ func (storage *DiffStorage) Swap(i, j int) {
|
||||
storage.Keys[i], storage.Keys[j] = storage.Keys[j], storage.Keys[i]
|
||||
storage.Vals[i], storage.Vals[j] = storage.Vals[j], storage.Vals[i]
|
||||
}
|
||||
|
||||
func (storage *DiffStorage) Less(i, j int) bool {
|
||||
return string(storage.Keys[i][:]) < string(storage.Keys[j][:])
|
||||
}
|
||||
@@ -622,3 +624,64 @@ type DiffAccountsInBlock struct {
|
||||
BlockHash common.Hash
|
||||
Transactions []DiffAccountsInTx
|
||||
}
|
||||
|
||||
var (
|
||||
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
||||
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||
)
|
||||
|
||||
// SealHash returns the hash of a block prior to it being sealed.
|
||||
func SealHash(header *Header, chainId *big.Int) (hash common.Hash) {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
EncodeSigHeader(hasher, header, chainId)
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
|
||||
func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) {
|
||||
err := rlp.Encode(w, []interface{}{
|
||||
chainId,
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
header.Root,
|
||||
header.TxHash,
|
||||
header.ReceiptHash,
|
||||
header.Bloom,
|
||||
header.Difficulty,
|
||||
header.Number,
|
||||
header.GasLimit,
|
||||
header.GasUsed,
|
||||
header.Time,
|
||||
header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
panic("can't encode: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func EncodeSigHeaderWithoutVoteAttestation(w io.Writer, header *Header, chainId *big.Int) {
|
||||
err := rlp.Encode(w, []interface{}{
|
||||
chainId,
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
header.Root,
|
||||
header.TxHash,
|
||||
header.ReceiptHash,
|
||||
header.Bloom,
|
||||
header.Difficulty,
|
||||
header.Number,
|
||||
header.GasLimit,
|
||||
header.GasUsed,
|
||||
header.Time,
|
||||
header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
panic("can't encode: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,23 +17,28 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/blake2b"
|
||||
"github.com/ethereum/go-ethereum/crypto/bls12381"
|
||||
"github.com/ethereum/go-ethereum/crypto/bn256"
|
||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
// PrecompiledContract is the basic interface for native Go contracts. The implementation
|
||||
@@ -217,6 +222,29 @@ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
|
||||
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
|
||||
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{},
|
||||
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
|
||||
common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
|
||||
}
|
||||
|
||||
// PrecompiledContractsFeynman contains the default set of pre-compiled Ethereum
|
||||
// contracts used in the Feynman release.
|
||||
var PrecompiledContractsFeynman = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
|
||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
||||
|
||||
common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
|
||||
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
|
||||
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
|
||||
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidateHertz{},
|
||||
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
|
||||
common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
|
||||
}
|
||||
|
||||
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
|
||||
@@ -245,6 +273,7 @@ var (
|
||||
PrecompiledAddressesIstanbul []common.Address
|
||||
PrecompiledAddressesByzantium []common.Address
|
||||
PrecompiledAddressesHomestead []common.Address
|
||||
PrecompiledAddressesFeynman []common.Address
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -281,6 +310,9 @@ func init() {
|
||||
for k := range PrecompiledContractsCancun {
|
||||
PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k)
|
||||
}
|
||||
for k := range PrecompiledContractsFeynman {
|
||||
PrecompiledAddressesFeynman = append(PrecompiledAddressesFeynman, k)
|
||||
}
|
||||
}
|
||||
|
||||
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
||||
@@ -288,6 +320,8 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
|
||||
switch {
|
||||
case rules.IsCancun:
|
||||
return PrecompiledAddressesCancun
|
||||
case rules.IsFeynman:
|
||||
return PrecompiledAddressesFeynman
|
||||
case rules.IsHertz:
|
||||
return PrecompiledAddressesHertz
|
||||
case rules.IsPlato:
|
||||
@@ -561,7 +595,7 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
|
||||
// Modulo 0 is undefined, return zero
|
||||
return common.LeftPadBytes([]byte{}, int(modLen)), nil
|
||||
case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1).
|
||||
//If base == 1, then we can just return base % mod (if mod >= 1, which it is)
|
||||
// If base == 1, then we can just return base % mod (if mod >= 1, which it is)
|
||||
v = base.Mod(base, mod).Bytes()
|
||||
default:
|
||||
v = base.Exp(base, exp, mod).Bytes()
|
||||
@@ -1355,3 +1389,95 @@ func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash {
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// verifyDoubleSignEvidence implements bsc header verification precompile.
|
||||
type verifyDoubleSignEvidence struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *verifyDoubleSignEvidence) RequiredGas(input []byte) uint64 {
|
||||
return params.DoubleSignEvidenceVerifyGas
|
||||
}
|
||||
|
||||
type DoubleSignEvidence struct {
|
||||
ChainId *big.Int
|
||||
HeaderBytes1 []byte
|
||||
HeaderBytes2 []byte
|
||||
}
|
||||
|
||||
const (
|
||||
extraSeal = 65
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidEvidence = errors.New("invalid double sign evidence")
|
||||
)
|
||||
|
||||
// Run input: rlp encoded DoubleSignEvidence
|
||||
// return:
|
||||
// signer address| evidence height|
|
||||
// 20 bytes | 32 bytes |
|
||||
func (c *verifyDoubleSignEvidence) Run(input []byte) ([]byte, error) {
|
||||
evidence := &DoubleSignEvidence{}
|
||||
err := rlp.DecodeBytes(input, evidence)
|
||||
if err != nil {
|
||||
return nil, ErrExecutionReverted
|
||||
}
|
||||
|
||||
header1 := &types.Header{}
|
||||
err = rlp.DecodeBytes(evidence.HeaderBytes1, header1)
|
||||
if err != nil {
|
||||
return nil, ErrExecutionReverted
|
||||
}
|
||||
|
||||
header2 := &types.Header{}
|
||||
err = rlp.DecodeBytes(evidence.HeaderBytes2, header2)
|
||||
if err != nil {
|
||||
return nil, ErrExecutionReverted
|
||||
}
|
||||
|
||||
// basic check
|
||||
if len(header1.Number.Bytes()) > 32 || len(header2.Number.Bytes()) > 32 { // block number should be less than 2^256
|
||||
return nil, errInvalidEvidence
|
||||
}
|
||||
if header1.Number.Cmp(header2.Number) != 0 {
|
||||
return nil, errInvalidEvidence
|
||||
}
|
||||
if header1.ParentHash != header2.ParentHash {
|
||||
return nil, errInvalidEvidence
|
||||
}
|
||||
|
||||
if len(header1.Extra) < extraSeal || len(header2.Extra) < extraSeal {
|
||||
return nil, errInvalidEvidence
|
||||
}
|
||||
sig1 := header1.Extra[len(header1.Extra)-extraSeal:]
|
||||
sig2 := header2.Extra[len(header2.Extra)-extraSeal:]
|
||||
if bytes.Equal(sig1, sig2) {
|
||||
return nil, errInvalidEvidence
|
||||
}
|
||||
|
||||
// check sig
|
||||
msgHash1 := types.SealHash(header1, evidence.ChainId)
|
||||
msgHash2 := types.SealHash(header2, evidence.ChainId)
|
||||
if bytes.Equal(msgHash1.Bytes(), msgHash2.Bytes()) {
|
||||
return nil, errInvalidEvidence
|
||||
}
|
||||
pubkey1, err := secp256k1.RecoverPubkey(msgHash1.Bytes(), sig1)
|
||||
if err != nil {
|
||||
return nil, ErrExecutionReverted
|
||||
}
|
||||
pubkey2, err := secp256k1.RecoverPubkey(msgHash2.Bytes(), sig2)
|
||||
if err != nil {
|
||||
return nil, ErrExecutionReverted
|
||||
}
|
||||
if !bytes.Equal(pubkey1, pubkey2) {
|
||||
return nil, errInvalidEvidence
|
||||
}
|
||||
|
||||
returnBz := make([]byte, 52) // 20 + 32
|
||||
signerAddr := crypto.Keccak256(pubkey1[1:])[12:]
|
||||
evidenceHeightBz := header1.Number.Bytes()
|
||||
copy(returnBz[:20], signerAddr)
|
||||
copy(returnBz[52-len(evidenceHeightBz):], evidenceHeightBz)
|
||||
|
||||
return returnBz, nil
|
||||
}
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
|
||||
"github.com/tendermint/iavl"
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
|
||||
//nolint:staticcheck
|
||||
v1 "github.com/ethereum/go-ethereum/core/vm/lightclient/v1"
|
||||
v2 "github.com/ethereum/go-ethereum/core/vm/lightclient/v2"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
@@ -104,7 +106,7 @@ func (c *tmHeaderValidate) Run(input []byte) (result []byte, err error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// iavlMerkleProofValidate implemented as a native contract.
|
||||
type iavlMerkleProofValidate struct {
|
||||
@@ -397,3 +399,40 @@ type cometBFTLightBlockValidateHertz struct {
|
||||
func (c *cometBFTLightBlockValidateHertz) Run(input []byte) (result []byte, err error) {
|
||||
return c.run(input, true)
|
||||
}
|
||||
|
||||
// secp256k1SignatureRecover implemented as a native contract.
|
||||
type secp256k1SignatureRecover struct{}
|
||||
|
||||
func (c *secp256k1SignatureRecover) RequiredGas(input []byte) uint64 {
|
||||
return params.EcrecoverGas
|
||||
}
|
||||
|
||||
const (
|
||||
secp256k1PubKeyLength uint8 = 33
|
||||
secp256k1SignatureLength uint8 = 64
|
||||
secp256k1SignatureMsgHashLength uint8 = 32
|
||||
)
|
||||
|
||||
// input:
|
||||
// | PubKey | Signature | SignatureMsgHash |
|
||||
// | 33 bytes | 64 bytes | 32 bytes |
|
||||
func (c *secp256k1SignatureRecover) Run(input []byte) (result []byte, err error) {
|
||||
if len(input) != int(secp256k1PubKeyLength)+int(secp256k1SignatureLength)+int(secp256k1SignatureMsgHashLength) {
|
||||
return nil, fmt.Errorf("invalid input")
|
||||
}
|
||||
|
||||
return c.runTMSecp256k1Signature(
|
||||
input[:secp256k1PubKeyLength],
|
||||
input[secp256k1PubKeyLength:secp256k1PubKeyLength+secp256k1SignatureLength],
|
||||
input[secp256k1PubKeyLength+secp256k1SignatureLength:],
|
||||
)
|
||||
}
|
||||
|
||||
func (c *secp256k1SignatureRecover) runTMSecp256k1Signature(pubkey, signatureStr, msgHash []byte) (result []byte, err error) {
|
||||
tmPubKey := secp256k1.PubKeySecp256k1(pubkey)
|
||||
ok := tmPubKey.VerifyBytesWithMsgHash(msgHash, signatureStr)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid signature")
|
||||
}
|
||||
return tmPubKey.Address().Bytes(), nil
|
||||
}
|
||||
|
||||
@@ -373,3 +373,42 @@ func TestCometBFTLightBlockValidateHertz(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectOutputStr, hex.EncodeToString(res))
|
||||
}
|
||||
|
||||
func TestSecp256k1SignatureRecover(t *testing.T) {
|
||||
// local key
|
||||
{
|
||||
pubKey, err := hex.DecodeString("0278caa4d6321aa856d6341dd3e8bcdfe0b55901548871c63c3f5cec43c2ae88a9")
|
||||
require.NoError(t, err)
|
||||
sig, err := hex.DecodeString("0cb78be0d8eaeab991907b06c61240c04f4ca83f54b7799ce77cf029b837988038c4b3b7f5df231695b0d14499b716e1fd6504860eb3c9244ecb4e569d44c062")
|
||||
require.NoError(t, err)
|
||||
msghash, err := hex.DecodeString("b6ac827edff4bbbf23579720782dbef40b65780af292cc66849e7e5944f1230f")
|
||||
require.NoError(t, err)
|
||||
expectedAddr, err := hex.DecodeString("fa3B227adFf8EA1706098928715076D76959Ae6c")
|
||||
require.NoError(t, err)
|
||||
|
||||
input := append(append(pubKey, sig...), msghash...)
|
||||
contract := &secp256k1SignatureRecover{}
|
||||
res, err := contract.Run(input)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedAddr, res)
|
||||
}
|
||||
// ledger
|
||||
{
|
||||
pubKey, err := hex.DecodeString("02d63ee39adb1779353b4393dd5ea9d6d2b6df63b71d168571803cc7b9a0a20e98")
|
||||
require.NoError(t, err)
|
||||
sig, err := hex.DecodeString("66bdb5d381b2773c0f569858c7ee143959522d7c1f46dc656c325cb7353ec40c28ec22dff3650b34c096c5b12e702d7237d409f1ebaaa6dd1128a8f2d401fd5b")
|
||||
require.NoError(t, err)
|
||||
msghash, err := hex.DecodeString("c45e8f0dc7c054c31912beeffd6f10f1c585606d61e252e97968cd66661c2571")
|
||||
require.NoError(t, err)
|
||||
expectedAddr, err := hex.DecodeString("65a284146b84210a01add088954bb52d88b230af")
|
||||
require.NoError(t, err)
|
||||
|
||||
input := append(append(pubKey, sig...), msghash...)
|
||||
contract := &secp256k1SignatureRecover{}
|
||||
res, err := contract.Run(input)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedAddr, res)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{},
|
||||
common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{},
|
||||
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
|
||||
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
|
||||
}
|
||||
|
||||
// EIP-152 test vectors
|
||||
@@ -405,3 +406,24 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
|
||||
}
|
||||
benchmarkPrecompiled("0f", testcase, b)
|
||||
}
|
||||
|
||||
func TestDoubleSignSlash(t *testing.T) {
|
||||
tc := precompiledTest{
|
||||
Input: "f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",
|
||||
Expected: "15d34aaf54267db7d7c367839aaf71a00a2c6a650000000000000000000000000000000000000000000000000000000000000cdf",
|
||||
Gas: 10000,
|
||||
Name: "",
|
||||
}
|
||||
|
||||
testPrecompiled("68", tc, t)
|
||||
}
|
||||
|
||||
func TestDoubleSignSlashFailure(t *testing.T) {
|
||||
tc := precompiledFailureTest{
|
||||
Input: "f9066b38b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494df87f0e2b8519ea2dd4abd8b639cdd628497ed25a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b980988e1b9d0beb91dab063e04879a24c43d33baae3759dee41fd62ffa83c77fd202bea27a829b49e8025bdd198393526dd12b223ab16052fd26a43f3aabf63e76901a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094df87f0e2b8519ea2dd4abd8b639cdd628497ed25a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b9804c71ed015dd0c5c2d7393b68c2927f83f0a5da4c66f761f09e2f950cc610832c7876144599368404096ddef0eadacfde57717e2c7d23982b927285b797d41bfa00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",
|
||||
ExpectedError: errInvalidEvidence.Error(),
|
||||
Name: "",
|
||||
}
|
||||
|
||||
testPrecompiledFailure("68", tc, t)
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
||||
switch {
|
||||
case evm.chainRules.IsCancun:
|
||||
precompiles = PrecompiledContractsCancun
|
||||
case evm.chainRules.IsFeynman:
|
||||
precompiles = PrecompiledContractsFeynman
|
||||
case evm.chainRules.IsHertz:
|
||||
precompiles = PrecompiledContractsHertz
|
||||
case evm.chainRules.IsPlato:
|
||||
|
||||
@@ -90,7 +90,7 @@ func newCancunInstructionSet() JumpTable {
|
||||
}
|
||||
|
||||
func newShanghaiInstructionSet() JumpTable {
|
||||
instructionSet := newMergeInstructionSet()
|
||||
instructionSet := newLondonInstructionSet()
|
||||
enable3855(&instructionSet) // PUSH0 instruction
|
||||
enable3860(&instructionSet) // Limit and meter initcode
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"Input": "01d18459b334ffe8e2226eef1db874fda6db2bdd9357268b39220af2d59464fb564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a1978a0d595c823c05947b1156175e72634a377808384256e9921ebf72181890be2d6b58d4a73a880541d1656875654806942307f266e636553e94006d11423f2688945ff3bdf515859eba1005c1a7708d620a94d91a1c0c285f9584e75ec2f82a",
|
||||
"Input": "01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a",
|
||||
"Expected": "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
|
||||
"Name": "pointEvaluation1",
|
||||
"Gas": 50000,
|
||||
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
)
|
||||
|
||||
const blocksNumberSinceMining = 5 // the number of blocks need to wait before voting, counting from the validator begin to mine
|
||||
|
||||
var votesManagerCounter = metrics.NewRegisteredCounter("votesManager/local", nil)
|
||||
|
||||
// Backend wraps all methods required for voting.
|
||||
@@ -95,6 +97,7 @@ func (voteManager *VoteManager) loop() {
|
||||
dlEventCh := events.Chan()
|
||||
|
||||
startVote := true
|
||||
blockCountSinceMining := 0
|
||||
var once sync.Once
|
||||
for {
|
||||
select {
|
||||
@@ -120,9 +123,15 @@ func (voteManager *VoteManager) loop() {
|
||||
continue
|
||||
}
|
||||
if !voteManager.eth.IsMining() {
|
||||
blockCountSinceMining = 0
|
||||
log.Debug("skip voting because mining is disabled, continue")
|
||||
continue
|
||||
}
|
||||
blockCountSinceMining++
|
||||
if blockCountSinceMining <= blocksNumberSinceMining {
|
||||
log.Debug("skip voting", "blockCountSinceMining", blockCountSinceMining, "blocksNumberSinceMining", blocksNumberSinceMining)
|
||||
continue
|
||||
}
|
||||
|
||||
if cHead.Block == nil {
|
||||
log.Debug("cHead.Block is nil, continue")
|
||||
@@ -209,7 +218,7 @@ func (voteManager *VoteManager) loop() {
|
||||
// A validator must not vote within the span of its other votes . (Rule 2)
|
||||
// Validators always vote for their canonical chain’s latest block. (Rule 3)
|
||||
func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64, common.Hash) {
|
||||
sourceNumber, sourceHash, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, header)
|
||||
sourceNumber, sourceHash, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, []*types.Header{header})
|
||||
if err != nil {
|
||||
log.Error("failed to get the highest justified number and hash at cur header", "curHeader's BlockNumber", header.Number, "curHeader's BlockHash", header.Hash())
|
||||
return false, 0, common.Hash{}
|
||||
|
||||
@@ -78,15 +78,15 @@ func newTestBackend() *testBackend {
|
||||
func (b *testBackend) IsMining() bool { return true }
|
||||
func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux }
|
||||
|
||||
func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) {
|
||||
parentHeader := chain.GetHeaderByHash(header.ParentHash)
|
||||
func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
|
||||
parentHeader := chain.GetHeaderByHash(headers[len(headers)-1].ParentHash)
|
||||
if parentHeader == nil {
|
||||
return 0, common.Hash{}, fmt.Errorf("unexpected error")
|
||||
}
|
||||
return parentHeader.Number.Uint64(), parentHeader.Hash(), nil
|
||||
}
|
||||
|
||||
func (p *mockInvalidPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) {
|
||||
func (p *mockInvalidPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
|
||||
return 0, common.Hash{}, fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ func testVotePool(t *testing.T, isValidRules bool) {
|
||||
if _, err := chain.InsertChain(bs); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
for i := 0; i < 10+blocksNumberSinceMining; i++ {
|
||||
bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
|
||||
if _, err := chain.InsertChain(bs); err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -199,7 +199,7 @@ func FromECDSA(priv *ecdsa.PrivateKey) []byte {
|
||||
|
||||
// UnmarshalPubkey converts bytes to a secp256k1 public key.
|
||||
func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) {
|
||||
x, y := elliptic.Unmarshal(S256(), pub)
|
||||
x, y := elliptic.Unmarshal(S256(), pub) //nolint:all //TODO
|
||||
if x == nil {
|
||||
return nil, errInvalidPubkey
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
|
||||
if pub == nil || pub.X == nil || pub.Y == nil {
|
||||
return nil
|
||||
}
|
||||
return elliptic.Marshal(S256(), pub.X, pub.Y)
|
||||
return elliptic.Marshal(S256(), pub.X, pub.Y) //nolint:all //TODO
|
||||
}
|
||||
|
||||
// HexToECDSA parses a secp256k1 private key.
|
||||
|
||||
@@ -95,7 +95,7 @@ func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
|
||||
// Generate an elliptic curve public / private keypair. If params is nil,
|
||||
// the recommended default parameters for the key will be chosen.
|
||||
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
|
||||
pb, x, y, err := elliptic.GenerateKey(curve, rand)
|
||||
pb, x, y, err := elliptic.GenerateKey(curve, rand) //nolint:all //TODO
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -255,7 +255,7 @@ func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err e
|
||||
|
||||
d := messageTag(params.Hash, Km, em, s2)
|
||||
|
||||
Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
|
||||
Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) //nolint:all //TODO
|
||||
ct = make([]byte, len(Rb)+len(em)+len(d))
|
||||
copy(ct, Rb)
|
||||
copy(ct[len(Rb):], em)
|
||||
@@ -297,7 +297,7 @@ func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) {
|
||||
|
||||
R := new(PublicKey)
|
||||
R.Curve = prv.PublicKey.Curve
|
||||
R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
|
||||
R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) //nolint:all //TODO
|
||||
if R.X == nil {
|
||||
return nil, ErrInvalidPublicKey
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ func generateKeyPair() (pubkey, privkey []byte) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubkey = elliptic.Marshal(S256(), key.X, key.Y)
|
||||
pubkey = elliptic.Marshal(S256(), key.X, key.Y) //nolint:all //TODO
|
||||
|
||||
privkey = make([]byte, 32)
|
||||
blob := key.D.Bytes()
|
||||
|
||||
@@ -41,7 +41,7 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
x, y := elliptic.Unmarshal(S256(), s)
|
||||
x, y := elliptic.Unmarshal(S256(), s) //nolint:all, TODO
|
||||
return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.20-alpine as bsc
|
||||
FROM golang:1.21-alpine as bsc
|
||||
|
||||
RUN apk add --no-cache make cmake gcc musl-dev linux-headers git bash build-base libc-dev
|
||||
|
||||
@@ -18,6 +18,7 @@ RUN apk add --no-cache ca-certificates npm nodejs bash alpine-sdk expect
|
||||
|
||||
RUN git clone https://github.com/bnb-chain/bsc-genesis-contract.git /root/genesis \
|
||||
&& cd /root/genesis && npm install
|
||||
#RUN curl -L https://foundry.paradigm.xyz | bash
|
||||
|
||||
COPY --from=bsc /usr/local/bin/geth /usr/local/bin/geth
|
||||
|
||||
|
||||
@@ -39,9 +39,7 @@ web3.eth.sendTransaction({
|
||||
web3.eth.sendTransaction({
|
||||
from: "consensus address of your validator",
|
||||
to: "0x0000000000000000000000000000000000001000",
|
||||
gas: "1000000",
|
||||
data: "0x04c4fec6"
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
|
||||
if stateDb == nil {
|
||||
return state.Dump{}, errors.New("pending state is not available")
|
||||
}
|
||||
opts.StateScheme = stateDb.Database().TrieDB().Scheme()
|
||||
return stateDb.RawDump(opts), nil
|
||||
}
|
||||
var header *types.Header
|
||||
@@ -83,6 +84,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
|
||||
if err != nil {
|
||||
return state.Dump{}, err
|
||||
}
|
||||
opts.StateScheme = stateDb.Database().TrieDB().Scheme()
|
||||
return stateDb.RawDump(opts), nil
|
||||
}
|
||||
|
||||
@@ -188,6 +190,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
|
||||
OnlyWithAddresses: !incompletes,
|
||||
Start: start,
|
||||
Max: uint64(maxResults),
|
||||
StateScheme: stateDb.Database().TrieDB().Scheme(),
|
||||
}
|
||||
if maxResults > AccountRangeMaxResults || maxResults <= 0 {
|
||||
opts.Max = AccountRangeMaxResults
|
||||
|
||||
@@ -118,7 +118,7 @@ type Ethereum struct {
|
||||
func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
// Ensure configuration values are compatible and sane
|
||||
if config.SyncMode == downloader.LightSync {
|
||||
return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum")
|
||||
return nil, errors.New("can't run eth.Ethereum in light sync mode, light mode has been deprecated")
|
||||
}
|
||||
if !config.SyncMode.IsValid() {
|
||||
return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode)
|
||||
@@ -130,6 +130,17 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice)
|
||||
config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice)
|
||||
}
|
||||
|
||||
// Assemble the Ethereum object
|
||||
chainDb, err := stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles,
|
||||
config.DatabaseFreezer, config.DatabaseDiff, "eth/db/chaindata/", false, config.PersistDiff, config.PruneAncientData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.StateScheme, err = rawdb.ParseStateScheme(config.StateScheme, chainDb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Redistribute memory allocation from in-memory trie node garbage collection
|
||||
// to other caches when an archive node is requested.
|
||||
if config.StateScheme == rawdb.HashScheme && config.NoPruning && config.TrieDirtyCache > 0 {
|
||||
@@ -150,12 +161,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
}
|
||||
log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024)
|
||||
|
||||
// Assemble the Ethereum object
|
||||
chainDb, err := stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles,
|
||||
config.DatabaseFreezer, config.DatabaseDiff, "eth/db/chaindata/", false, config.PersistDiff, config.PruneAncientData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Try to recover offline state pruning only in hash-based.
|
||||
if config.StateScheme == rawdb.HashScheme {
|
||||
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, config.TriesInMemory); err != nil {
|
||||
log.Error("Failed to recover state", "error", err)
|
||||
@@ -165,6 +171,32 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Override the chain config with provided settings.
|
||||
var overrides core.ChainOverrides
|
||||
if config.OverrideShanghai != nil {
|
||||
chainConfig.ShanghaiTime = config.OverrideShanghai
|
||||
overrides.OverrideShanghai = config.OverrideShanghai
|
||||
}
|
||||
if config.OverrideKepler != nil {
|
||||
chainConfig.KeplerTime = config.OverrideKepler
|
||||
overrides.OverrideKepler = config.OverrideKepler
|
||||
}
|
||||
if config.OverrideCancun != nil {
|
||||
chainConfig.CancunTime = config.OverrideCancun
|
||||
overrides.OverrideCancun = config.OverrideCancun
|
||||
}
|
||||
if config.OverrideVerkle != nil {
|
||||
chainConfig.VerkleTime = config.OverrideVerkle
|
||||
overrides.OverrideVerkle = config.OverrideVerkle
|
||||
}
|
||||
if config.OverrideFeynman != nil {
|
||||
chainConfig.FeynmanTime = config.OverrideFeynman
|
||||
overrides.OverrideFeynman = config.OverrideFeynman
|
||||
}
|
||||
if config.OverrideFeynmanFix != nil {
|
||||
chainConfig.FeynmanFixTime = config.OverrideFeynmanFix
|
||||
overrides.OverrideFeynmanFix = config.OverrideFeynmanFix
|
||||
}
|
||||
|
||||
eth := &Ethereum{
|
||||
config: config,
|
||||
@@ -241,14 +273,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
|
||||
peers := newPeerSet()
|
||||
bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers))
|
||||
// Override the chain config with provided settings.
|
||||
var overrides core.ChainOverrides
|
||||
if config.OverrideCancun != nil {
|
||||
overrides.OverrideCancun = config.OverrideCancun
|
||||
}
|
||||
if config.OverrideVerkle != nil {
|
||||
overrides.OverrideVerkle = config.OverrideVerkle
|
||||
}
|
||||
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -403,7 +427,7 @@ func (s *Ethereum) APIs() []rpc.API {
|
||||
Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux),
|
||||
}, {
|
||||
Namespace: "eth",
|
||||
Service: filters.NewFilterAPI(filters.NewFilterSystem(s.APIBackend, filters.Config{}), false, s.config.RangeLimit),
|
||||
Service: filters.NewFilterAPI(filters.NewFilterSystem(s.APIBackend, filters.Config{}), s.config.RangeLimit),
|
||||
}, {
|
||||
Namespace: "admin",
|
||||
Service: NewAdminAPI(s),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user