Compare commits

..

105 Commits

Author SHA1 Message Date
Roshan
0574452b4d upgrade: update testnet contracts bytecode and hardfork time for Feynman (#2237) 2024-02-26 16:08:50 +08:00
zjubfd
70adb6077a fix the double sign testcase 2024-02-19 12:56:09 +08:00
dylanhuang
316585ba9b ci: add nancy job (#2221) 2024-02-19 12:06:07 +08:00
Roshan
a2ddb75b02 chore: update bls generate-proof cmd (#2215) 2024-02-16 16:19:30 +08:00
zjubfd
9e4d15b5a6 fix: change the wrong precompile contract (#2206) 2024-02-05 17:51:38 +08:00
Roshan
fd0ee7d3e9 fix: adjust the timing of initializing Feynman system contracts (#2203)
* fix: adjust the timing of initializing Feynman system contracts

* fix test case
2024-02-04 17:53:34 +08:00
Roshan
e7cd04b38e fix: add check for block number (#2199)
* fix: add check for block number

* fix review comments

* fix review comments
2024-02-02 14:13:57 +08:00
Roshan
d7e7f73718 chore: add initialize for TokenRecoverPortalContract (#2194) 2024-02-01 16:18:34 +08:00
zjubfd
fc9230e4e6 Merge pull request #2192 from Pythonberg1997/bc-fusion
chore: merge with develop branch
2024-01-30 16:55:08 +08:00
Roshan
2f0b2f0cf3 chore: resolve merge conflicts and fix review comments 2024-01-30 16:29:23 +08:00
Roshan
7f6c4cd7cd Merge remote-tracking branch 'BNB-chain/develop' into bc-fusion-roshan
# Conflicts:
#	cmd/geth/blsaccountcmd.go
#	miner/worker.go
2024-01-30 16:27:57 +08:00
Ng Wei Han
3761bf0426 fix(legacypool): deprecate already known error (#2190) 2024-01-29 19:13:15 +08:00
buddho
29427c51fd consensus/parlia: set nonce before evm run (#2185) 2024-01-29 14:44:58 +08:00
Matus Kysel
220be95117 Merge pull request #2183 from bnb-chain/fix-p2p-server-timeout
p2p: resolved deadlock on p2p server shutdown
2024-01-26 10:58:29 +01:00
Matus Kysel
f0d9f61bf6 p2p: return increased timeout 2024-01-26 09:29:43 +01:00
Matus Kysel
d49da4348c p2p: resolved deadlock on p2p server shutdown 2024-01-25 15:53:33 +01:00
VM
fecd2bfafe cmd: fix dump cli cannot work in path mode (#2160) 2024-01-25 22:07:44 +08:00
Roshan
818379d999 fix: upgrade system contracts twice issue in traceBlockParallel (#2178)
* fix: upgrade system contracts twice issue in `traceBlockParallel`

* fix review comments
2024-01-25 19:40:26 +08:00
dependabot[bot]
ef13f3194d build(deps): bump github.com/quic-go/quic-go from 0.39.3 to 0.39.4 (#2177) 2024-01-23 17:41:20 +08:00
zzzckck
58602e6b53 release: prepare for release v1.3.8 (#2168) 2024-01-22 20:45:36 +08:00
Ng Wei Han
d10200175e p2p: reset disconnect set with magic enode ID (#2144) 2024-01-22 19:38:02 +08:00
Delweng
a6a956263e core/state: no need to prune block if the same (#1332) 2024-01-22 16:41:48 +08:00
zzzckck
ef462c2b47 Merge pull request #2155 from sysvm/fix-prunestate 2024-01-22 14:36:50 +08:00
Fynn
4829027a54 dbcmd: refactor concurrency Control and add EOA/Contract account stat (#2142)
* dbcmd: refactor add eoa account stat

* dbcmd: fix lint issues
2024-01-22 14:29:14 +08:00
Roshan
65baf18031 chore: update the contracts' byte code of Feynman upgrade (#2175)
* chore: update the contracts' byte code of Feynman upgrade

* add `OverrideFeynman`
2024-01-22 13:01:16 +08:00
Roshan
13f17f2970 fix: adjusted the timing of UpgradeBuildInSystemContract (#2166)
* fix: adjusted the timing of `UpgradeBuildInSystemContract`

* fix review comments

* fix review comments

* fix review comments

* fix review comments

* add `UpgradeBuildInSystemContract` to `traceBlock`

* add `UpgradeBuildInSystemContract` to `traceBlock`

* add `UpgradeBuildInSystemContract` to all trace functions
2024-01-22 12:15:05 +08:00
zzzckck
bea8f8ecfc improve: remove sharedpool from miner (#2172) 2024-01-22 11:04:55 +08:00
Eric
04d62b53da cmd/jsutil: add --miner when count tx (#2170) 2024-01-19 16:44:56 +08:00
zzzckck
d8b85839ee improve: increase SystemTxsGas from 1,500,000 to 5,000,000 (#2167) 2024-01-19 11:59:03 +08:00
zzzckck
e606461454 code: remove IsEuler check from worker.go (#2161) 2024-01-17 18:37:23 +08:00
Ng Wei Han
1c3d31c19f feat: enable NoDial should still dial static nodes (#2151) 2024-01-16 10:56:42 +08:00
kevaundray
0d5ecb5b90 crypto/kzg4844: use the new trusted setup file and format (#28383)
Changes the trusted_setup to the one created during the kzg-ceremony. The trusted setup file can be found in the consensus specs: https://github.com/ethereum/consensus-specs/blob/dev/presets/mainnet/trusted_setups/trusted_setup_4096.json
---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2024-01-15 17:09:47 +08:00
buddh0
1469bce18a go.mod: upgrade prysm to support built with go@v1.21 2024-01-15 17:09:47 +08:00
VM
a17fef4f15 test: add UT for resolveChainFreezerDir function 2024-01-15 11:09:41 +08:00
Roshan
7ade1d2a5d fix: compare headers' number in Big.Int rather than Uint64 (#2158) 2024-01-15 10:54:54 +08:00
VM
fee8a25957 fix: optimize resolveChainFreezerDir func 2024-01-12 15:36:26 +08:00
rjl493456442
ccb4d55a7c cmd, core: resolve scheme from a read-write database (#28313)
* cmd, core: resolve scheme from a read-write database

* cmd, core, eth: move the scheme check in the ethereum constructor

* cmd/geth: dump should in ro mode

* cmd: reverts
2024-01-12 14:47:01 +08:00
buddho
8ed5d24e1d tests: revive evm test cases (#2116) 2024-01-10 16:58:27 +08:00
Ng Wei Han
5853329c63 p2p: no peer reconnect if explicitly disconnected (#2115) 2024-01-08 16:34:02 +08:00
Ng Wei Han
69531d67a8 p2p: add serve metrics (#2114) 2024-01-08 16:32:22 +08:00
Ng Wei Han
7b22894146 p2p, eth: improve logs (#2123)
* p2p/discover: only show discovery status for bootnodes
* eth/downloader: uplevel expired request log
2024-01-08 16:32:06 +08:00
Marius van der Wijden
b2de32fb16 eth/fetcher: allow underpriced transactions in after timeout (#28097)
This PR will allow a previously underpriced transaction back in after a timeout
of 5 minutes. This will block most transaction spam but allow for transactions to
be re-broadcasted on networks with less transaction flow.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
# Conflicts:
#	eth/fetcher/tx_fetcher.go
2024-01-08 16:31:33 +08:00
Roshan
e2e2ac750c chore: fix lint issue (#2139) 2024-01-08 12:06:27 +08:00
zjubfd
85c6750592 Merge pull request #2138 from Pythonberg1997/bc-fusion
chore: merge with develop branch
2024-01-08 11:49:07 +08:00
Roshan
7466f0a075 Merge branch 'develop' into bc-fusion
# Conflicts:
#	core/systemcontracts/upgrade.go
#	params/config.go
2024-01-08 11:37:58 +08:00
Roshan
64a57a3e2a chore: update abi and bytecode (#2137) 2024-01-08 11:15:14 +08:00
Roshan
e5822640c6 chore: add SystemTxsGas for Feynman upgrade (#2133) 2024-01-04 20:18:45 +08:00
buddho
73d19c00cd core: fix systemcontracts.GenesisHash when run bsc firstly without init (#2132) 2024-01-04 18:26:36 +08:00
zzzckck
5fa1755329 Merge pull request #2098 from bnb-chain/remove-les
remove LES
2024-01-03 17:40:56 +08:00
lightclient
23a8d00334 light: remove package light(#28614)
This changes removes the package 'light', which is currently unused.
2024-01-03 09:27:04 +01:00
Martin Holst Swende
3349a24333 all: move light.NodeSet to trienode.ProofSet (#28287)
This is a minor refactor in preparation of changes to range verifier. This PR contains no intentional functional changes but moves (and renames) the light.NodeSet
2024-01-03 09:26:49 +01:00
Matus Kysel
7f2ef5987f les: removed test and web3 2024-01-03 09:26:49 +01:00
Matus Kysel
8d51cec12e cmd, les, tests: remove light client code (#28586)
* cmd, les, tests: remove light client code

This commit removes the light client (LES) code.
Since the merge the light client has been broken and
it is hard to maintain it alongside the normal client.
We decided it would be best to remove it for now and
maybe rework and reintroduce it in the future.

* cmd, eth: remove some more mentions of light mode

* cmd: re-add flags and mark as deprecated

* cmd: warn the user about deprecated flags

* eth: better error message
2024-01-03 09:26:49 +01:00
buddho
de1a126ec5 parlia: fix verifyVoteAttestation when verify a batch of headers (#2121) 2024-01-03 15:58:06 +08:00
VM
124939aaa4 cmd/geth: fix parse state scheme (#2107)
* cmd/geth: fix parse state scheme

* cmd/geth: enrich logs about state scheme

* cmd/geth: rename functions

---------

Co-authored-by: VM <arimas@foxmail.com>
2024-01-03 15:38:39 +08:00
wayen
a25a2143ce ethdb/pebble: cap memory table size as maxMemTableSize-1 (#28444) (#2120) 2024-01-03 14:37:01 +08:00
Fynn
7c8fa2b880 cmd/dbcmd: add inspect trie tool (#2082) 2023-12-28 16:48:15 +08:00
buddho
a6befb5078 params: use rialto to test builtin network logic (#2106) 2023-12-28 10:42:37 +08:00
dependabot[bot]
8e56d6b875 build(deps): bump golang.org/x/crypto from 0.12.0 to 0.17.0 (#2086) 2023-12-27 17:49:34 +08:00
dependabot[bot]
0bdd0d20e5 build(deps): bump github.com/docker/docker (#1953) 2023-12-27 17:49:07 +08:00
buddho
267c5c028c cmd/geth: tidy flags for geth command (#2109) 2023-12-27 14:27:35 +08:00
VM
c25594257d triedb/pathdb: fix async node buffer diskroot mismatches when journaling (#2083)
* triedb/pathdb: fix async node buffer diskroot mismatches when journaling

* triedb: check whether the async flush is done

* fix: generate new eth config

---------

Co-authored-by: VM <arimas@foxmail.com>
2023-12-26 14:12:51 +08:00
Matus Kysel
ad09930bdf faucet: new faucet client (#2074) 2023-12-26 11:32:04 +08:00
Roshan
432085ea62 fix: avoid update validators on Feynman block (#2102) 2023-12-25 11:20:50 +08:00
buddho
eb4ea42196 core: add metrics for bad block (#2101) 2023-12-25 11:07:31 +08:00
buddho
0ba5816cc7 core/genesis: support chapel to run without geth init (#2100) 2023-12-25 10:58:52 +08:00
buddho
354c0d7180 params/config: remove useless toml tag for hardforks (#2099) 2023-12-22 11:58:36 +08:00
Martin HS
9badb15e80 rpc: fix ns/µs mismatch in metrics (#28649)
The rpc/duration/all meter was in nanoseconds, the individual meter in microseconds.
This PR changes it so both of them use nanoseconds.
2023-12-21 16:41:55 +08:00
zjubfd
aab5ad94b8 Merge pull request #2096 from Pythonberg1997/bc-fusion
chore: merge with develop branch
2023-12-21 16:30:35 +08:00
Roshan
c0df5e7000 chore: add new byte code of TokenHub and GovHub to Feynman upgrade 2023-12-21 16:15:10 +08:00
Roshan
167da21801 Merge branch 'develop' into merge
# Conflicts:
#	params/config.go
2023-12-21 16:14:09 +08:00
Roshan
08f75ca23f chore: update system contracts' byte code (#2093) 2023-12-20 17:17:43 +08:00
zzzckck
01a4b00a2b release: prepare for release v1.3.7 (#2087) 2023-12-19 13:01:14 +08:00
zzzckck
474860ef77 Merge pull request #2035 from weiihann/v1.3.4-snapsync
all: pull snap sync PRs from upstream v1.13.5
2023-12-19 11:25:56 +08:00
qybdyx
4d2bd1253d internal/ethapi: fix TestRPCGetBlockReceipts 2023-12-19 11:24:15 +08:00
Adrian Sutton
ca058b7a69 rpc: use correct stringer-method for serializing BlockNumberOrHash (#28358)
Switch to using BlockNumber.String() which encodes it correctly for use in the JSON-RPC API.
2023-12-19 11:24:15 +08:00
Andryanau Kanstantsin
f4b7cdfe38 ethclient: fix BlockReceipts parameter encoding (#28087)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-12-19 11:24:15 +08:00
Delweng
f6fb2e9116 internal/ethapi: implement eth_getBlockReceipts (#27702) 2023-12-19 11:24:15 +08:00
Roshan
6685f68995 chore: fix CI issues (#2085) 2023-12-19 09:46:15 +08:00
buddho
e44de3ab27 core: LoadChainConfig return the predefined config for built-in networks firstly (#2078)
* core: LoadChainConfig return predefined config for built-in net firstly

* cmd/geth: add a warn message for chain config in the configuration file

* consensus/parlia: change chain config log level when New parlia

* core: fix code style
2023-12-18 17:07:50 +08:00
VM
07c46abcbe cmd/geth: add check func to validate state scheme (#2067)
* cmd/geth: add check func to validate state scheme

* cmd/geth: add detailed comments

---------

Co-authored-by: VM <arimas@foxmail.com>
2023-12-18 15:34:58 +08:00
wayen
8a440e753f fix: fix the pebble config of level option (#2072) 2023-12-18 13:11:17 +08:00
zzzckck
8205fdc525 release: prepare for release v1.3.6 (#2065) 2023-12-14 11:59:24 +08:00
Péter Szilágyi
0b632d97f3 cmd, core, ethdb: enable Pebble on 32 bits and OpenBSD 2023-12-14 11:10:45 +08:00
weiihann
84b268f6fb cmd, core, eth: change default network from ETH to BSC
fix tests

fix tests
2023-12-14 11:06:07 +08:00
Péter Szilágyi
f628e32ba5 cmd, core, params: add support for the Holesky testnet (#28007)
* cmd, core, params: add support for the Holesky testnet

* cmd/devp2p: add support for holesky for the dns crawler
# Conflicts:
#	cmd/devp2p/nodesetcmd.go
#	cmd/geth/main.go
#	cmd/utils/flags.go
#	core/genesis.go
#	params/bootnodes.go
#	params/config.go
2023-12-14 11:06:07 +08:00
Ng Wei Han
e4910b9540 cmd/utils: allow HTTPHost and WSHost flags precede (#2060) 2023-12-14 11:04:04 +08:00
buddho
2e69dcb342 log: limit rotateHours in range [0,23] (#2064) 2023-12-14 10:58:37 +08:00
buddho
64be7df9e2 log: support to disable log rotate by hours (#2063) 2023-12-14 10:02:26 +08:00
buddh0
1ebf2a4376 params: fix comment 2023-12-13 18:28:12 +08:00
buddh0
8ce9cdaae3 params: set default hardfork times 2023-12-13 18:28:12 +08:00
buddh0
b3df096358 core/vote: wait some blocks beforing voting since mining begin 2023-12-13 18:27:52 +08:00
Roshan
d4f7313760 chore: remove unused code (#2061) 2023-12-13 15:53:36 +08:00
zzzckck
4b107c5303 readme: update hardware requirements for BSC full node (#2057) 2023-12-12 18:44:06 +08:00
Roshan
94b68156c8 chore: update logic of determining breathe block and returned data of verifyDoubleSignEvidence (#2056) 2023-12-12 17:24:43 +08:00
Roshan
ab8793ae9f fix: bug in determining breathe block (#2055) 2023-12-12 14:21:30 +08:00
Eric
a140a5a324 cmd/jsutils: add 2 tools get validator version and block txs number (#2036) 2023-12-08 13:44:16 +08:00
weiihann
3a5ec36c54 fix: lint error 2023-12-05 15:46:43 +08:00
rjl493456442
7891b210e0 trie/triedb/pathdb, core/rawdb: enhance error message in freezer (#28198)
This PR adds more error message for debugging purpose.
2023-12-05 15:46:43 +08:00
rjl493456442
3076ad2ab9 eth/protocols/snap: fix snap sync failure on empty storage range (#28306) 2023-12-05 15:46:43 +08:00
rjl493456442
d9873bbf38 core, eth, trie: filter out boundary nodes and remove dangling nodes in (#28327) 2023-12-05 15:46:43 +08:00
Marius van der Wijden
3e6c16afd3 trie: reduce allocs in recHash (#27770)
# Conflicts:
#	trie/stacktrie.go
2023-12-05 15:32:12 +08:00
rjl493456442
1ddd337d1c core, trie, eth: refactor stacktrie constructor (#28350) 2023-12-05 15:32:11 +08:00
Martin Holst Swende
a182557ac3 trie: remove owner and binary marshaling from stacktrie (#28291) 2023-12-05 15:32:11 +08:00
Martin Holst Swende
4b32d400ee trie: refactor stacktrie (#28233) 2023-12-05 15:32:11 +08:00
245 changed files with 9033 additions and 36368 deletions

View File

@@ -15,7 +15,7 @@ jobs:
unit-test: unit-test:
strategy: strategy:
matrix: matrix:
go-version: [1.20.x] go-version: [1.21.x]
os: [ubuntu-latest] os: [ubuntu-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:

56
.github/workflows/evm-tests.yml vendored Normal file
View 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

View File

@@ -15,7 +15,7 @@ jobs:
golang-lint: golang-lint:
strategy: strategy:
matrix: matrix:
go-version: [1.20.x] go-version: [1.21.x]
os: [ubuntu-latest] os: [ubuntu-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@@ -50,7 +50,7 @@ jobs:
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@v3
with: with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version # 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: ./ working-directory: ./
skip-pkg-cache: true skip-pkg-cache: true
skip-cache: true skip-cache: true

37
.github/workflows/nancy.yml vendored Normal file
View 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

View File

@@ -15,7 +15,7 @@ jobs:
name: Build Release name: Build Release
strategy: strategy:
matrix: matrix:
go-version: [1.20.x] go-version: [1.21.x]
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:

View File

@@ -14,7 +14,7 @@ jobs:
name: Build Release name: Build Release
strategy: strategy:
matrix: matrix:
go-version: [1.20.x] go-version: [1.21.x]
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:

View File

@@ -15,7 +15,7 @@ jobs:
unit-test: unit-test:
strategy: strategy:
matrix: matrix:
go-version: [1.20.x] go-version: [1.21.x]
os: [ubuntu-latest] os: [ubuntu-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@@ -49,6 +49,5 @@ jobs:
CGO_CFLAGS_ALLOW: "-O -D__BLST_PORTABLE__" CGO_CFLAGS_ALLOW: "-O -D__BLST_PORTABLE__"
ANDROID_HOME: "" # Skip android test ANDROID_HOME: "" # Skip android test
run: | run: |
git submodule update --init --depth 1 --recursive
go mod download go mod download
make test make test

View File

@@ -15,7 +15,6 @@ output:
linters: linters:
disable-all: true disable-all: true
enable: enable:
- goconst
- goimports - goimports
- gosimple - gosimple
- govet - govet
@@ -42,9 +41,6 @@ linters:
linters-settings: linters-settings:
gofmt: gofmt:
simplify: true simplify: true
goconst:
min-len: 3 # minimum length of string constant
min-occurrences: 6 # minimum number of occurrences
issues: issues:
exclude-rules: exclude-rules:

View File

@@ -13,7 +13,7 @@ jobs:
- stage: lint - stage: lint
os: linux os: linux
dist: bionic dist: bionic
go: 1.20.x go: 1.21.x
env: env:
- lint - lint
git: git:
@@ -28,7 +28,7 @@ jobs:
os: linux os: linux
arch: amd64 arch: amd64
dist: bionic dist: bionic
go: 1.20.x go: 1.21.x
env: env:
- docker - docker
services: services:
@@ -45,7 +45,7 @@ jobs:
os: linux os: linux
arch: arm64 arch: arm64
dist: bionic dist: bionic
go: 1.20.x go: 1.21.x
env: env:
- docker - docker
services: services:
@@ -63,7 +63,7 @@ jobs:
os: linux os: linux
dist: bionic dist: bionic
sudo: required sudo: required
go: 1.20.x go: 1.21.x
env: env:
- azure-linux - azure-linux
- GO111MODULE=on - GO111MODULE=on
@@ -97,7 +97,7 @@ jobs:
- stage: build - stage: build
if: type = push if: type = push
os: osx os: osx
go: 1.20.x go: 1.21.x
env: env:
- azure-osx - azure-osx
- GO111MODULE=on - GO111MODULE=on
@@ -112,7 +112,7 @@ jobs:
os: linux os: linux
arch: amd64 arch: amd64
dist: bionic dist: bionic
go: 1.20.x go: 1.21.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:
@@ -123,7 +123,7 @@ jobs:
os: linux os: linux
arch: arm64 arch: arm64
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:
@@ -132,7 +132,7 @@ jobs:
- stage: build - stage: build
os: linux os: linux
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:
@@ -143,7 +143,7 @@ jobs:
if: type = cron || (type = push && tag ~= /^v[0-9]/) if: type = cron || (type = push && tag ~= /^v[0-9]/)
os: linux os: linux
dist: bionic dist: bionic
go: 1.20.x go: 1.21.x
env: env:
- ubuntu-ppa - ubuntu-ppa
- GO111MODULE=on - GO111MODULE=on
@@ -167,7 +167,7 @@ jobs:
if: type = cron if: type = cron
os: linux os: linux
dist: bionic dist: bionic
go: 1.20.x go: 1.21.x
env: env:
- azure-purge - azure-purge
- GO111MODULE=on - GO111MODULE=on
@@ -181,7 +181,7 @@ jobs:
if: type = cron if: type = cron
os: linux os: linux
dist: bionic dist: bionic
go: 1.20.x go: 1.21.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:

View File

@@ -1,4 +1,68 @@
# Changelog # Changelog
## 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 ## v1.3.5
FEATURE FEATURE
* [\#1970](https://github.com/bnb-chain/bsc/pull/1970) core: enable Shanghai EIPs * [\#1970](https://github.com/bnb-chain/bsc/pull/1970) core: enable Shanghai EIPs

View File

@@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM="" ARG BUILDNUM=""
# Build Geth in a stock Go builder container # 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 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 # Get dependencies - will also be cached if we won't change go.mod/go.sum

View File

@@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM="" ARG BUILDNUM=""
# Build Geth in a stock Go builder container # 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 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 # Get dependencies - will also be cached if we won't change go.mod/go.sum

View File

@@ -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). 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 them using your favourite package manager. Once the dependencies are installed, run
```shell ```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: The hardware must meet certain requirements to run a full node on mainnet:
- VPS running recent versions of Mac OS X, Linux, or Windows. - 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) - 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 - A broadband Internet connection with upload/download speeds of 5 MB/S
The requirement for testnet: The requirement for testnet:
- VPS running recent versions of Mac OS X, Linux, or Windows. - VPS running recent versions of Mac OS X, Linux, or Windows.
- 500G of storage for testnet. - 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 ### Steps to Run a Fullnode
@@ -149,15 +149,8 @@ unzip testnet.zip
#### 3. Download snapshot #### 3. Download snapshot
Download latest chaindata snapshot from [here](https://github.com/bnb-chain/bsc-snapshots). Follow the guide to structure your files. 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. 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.
So just run:
``` shell
## It will init genesis with Hash-Base Storage Scheme by default.
geth --datadir <datadir> init ./genesis.json
## It will init genesis with Path-Base Storage Scheme.
geth --datadir <datadir> --state.scheme path init ./genesis.json
```
#### 4. Start a full node #### 4. Start a full node
```shell ```shell
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0 ./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0

View File

@@ -94,7 +94,7 @@ func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.Genesis
filterBackend := &filterBackend{database, blockchain, backend} filterBackend := &filterBackend{database, blockchain, backend}
backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{}) backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
backend.events = filters.NewEventSystem(backend.filterSystem, false) backend.events = filters.NewEventSystem(backend.filterSystem)
header := backend.blockchain.CurrentBlock() header := backend.blockchain.CurrentBlock()
block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64()) block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64())

View File

@@ -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) 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 tidier.Dir = pkg
if out, err := tidier.CombinedOutput(); err != nil { if out, err := tidier.CombinedOutput(); err != nil {
t.Fatalf("failed to tidy Go module file: %v\n%s", err, out) t.Fatalf("failed to tidy Go module file: %v\n%s", err, out)

View File

@@ -72,11 +72,11 @@ func NewSecureChannelSession(card *pcsc.Card, keyData []byte) (*SecureChannelSes
if err != nil { if err != nil {
return nil, fmt.Errorf("could not unmarshal public key from card: %v", err) 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{ return &SecureChannelSession{
card: card, card: card,
secret: secret.Bytes(), 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 }, nil
} }

View File

@@ -1,69 +1,60 @@
# This file contains sha256 checksums of optional build dependencies. # This file contains sha256 checksums of optional build dependencies.
2c5ee9c9ec1e733b0dbbc2bdfed3f62306e51d8172bf38f4f4e542b27520f597 go1.20.7.src.tar.gz # version:golang 1.21.5
785170eab380a8985d53896808b0a71336d0ea60e0a26099b4ccec77798b1cf4 go1.20.7.darwin-amd64.tar.gz # https://go.dev/dl/
eea1e7e4c2f75c72629050e6a6c7c46c446d64056732a7787fb3ba16ace1982e go1.20.7.darwin-arm64.tar.gz 285cbbdf4b6e6e62ed58f370f3f6d8c30825d6e56c5853c66d3c23bcdb09db19 go1.21.5.src.tar.gz
d8cff0357ac24eb06f3f280535397eeaacf95611d29f9b2abc3060f3d6dce3b4 go1.20.7.freebsd-386.tar.gz a2e1d5743e896e5fe1e7d96479c0a769254aed18cf216cf8f4c3a2300a9b3923 go1.21.5.darwin-amd64.tar.gz
26918dcebf474a9e81ccf9f648cdf36968dfb76b481518cf615d78455dda4416 go1.20.7.freebsd-amd64.tar.gz d0f8ac0c4fb3efc223a833010901d02954e3923cfe2c9a2ff0e4254a777cc9cc go1.21.5.darwin-arm64.tar.gz
ddb48145f05bda2f4617a22c979d4e94b22802cdb1a1fde1b1974e733b26f091 go1.20.7.linux-386.tar.gz 2c05bbe0dc62456b90b7ddd354a54f373b7c377a98f8b22f52ab694b4f6cca58 go1.21.5.freebsd-386.tar.gz
f0a87f1bcae91c4b69f8dc2bc6d7e6bfcd7524fceec130af525058c0c17b1b44 go1.20.7.linux-amd64.tar.gz 30b6c64e9a77129605bc12f836422bf09eec577a8c899ee46130aeff81567003 go1.21.5.freebsd-amd64.tar.gz
44781ae3b153c3b07651d93b6bc554e835a36e2d72a696281c1e4dad9efffe43 go1.20.7.linux-arm64.tar.gz 8f4dba9cf5c61757bbd7e9ebdb93b6a30a1b03f4a636a1ba0cc2f27b907ab8e1 go1.21.5.linux-386.tar.gz
7cc231b415b94f2f7065870a73f67dd2b0ec12b5a98052b7ee0121c42bc04f8d go1.20.7.linux-armv6l.tar.gz e2bc0b3e4b64111ec117295c088bde5f00eeed1567999ff77bc859d7df70078e go1.21.5.linux-amd64.tar.gz
6318a1db307c12b8afe68808bd6fae4fba1e558a85b958216096869ed506dcb3 go1.20.7.linux-ppc64le.tar.gz 841cced7ecda9b2014f139f5bab5ae31785f35399f236b8b3e75dff2a2978d96 go1.21.5.linux-arm64.tar.gz
26aea2ede8722ceecbd9db883328a8d963136fd96c11dacc356c44c4c19c6515 go1.20.7.linux-s390x.tar.gz 837f4bf4e22fcdf920ffeaa4abf3d02d1314e03725431065f4d44c46a01b42fe go1.21.5.linux-armv6l.tar.gz
5b0ef6f58d3e04d6cc003aa98e9172f41ba9e091b1c98e7339b41c4c87fb78a1 go1.20.7.windows-386.zip 907b8c6ec4be9b184952e5d3493be66b1746442394a8bc78556c56834cd7c38b go1.21.5.linux-ppc64le.tar.gz
736dc6c7fcab1c96b682c8c93e38d7e371e62a17d34cb2c37d451a1147f66af9 go1.20.7.windows-amd64.zip 9c4a81b72ebe44368813cd03684e1080a818bf915d84163abae2ed325a1b2dc0 go1.21.5.linux-s390x.tar.gz
fc6f79c1e1ed9e506c65f2112ac4e387479916f1accb0d046a6a19ff6938baa5 go1.20.7.windows-arm64.zip 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 # version:golangci 1.55.2
0970b2e3ecc20003a0fc78b078623ab27c61f0f809a44288e2cc438bfbbf5616 golangci-lint-1.52.2-linux-s390x.deb # https://github.com/golangci/golangci-lint/releases/
0bfe9b51f68a33cc4e43139151d8032b57b15e61a19f5a7554b687a3fa166ab8 golangci-lint-1.52.2-netbsd-armv7.tar.gz # https://github.com/golangci/golangci-lint/releases/download/v1.55.2/
0e4e24085d364f4e03752c060d5f37b5ead52acd62f07392f4c9022515e0ecd8 golangci-lint-1.52.2-linux-armv7.rpm 632e96e6d5294fbbe7b2c410a49c8fa01c60712a0af85a567de85bcc1623ea21 golangci-lint-1.55.2-darwin-amd64.tar.gz
0f19ad6c037d45867f4978287a7a6d78bc761daf8e6cb3a5e6af86d5714b0258 golangci-lint-1.52.2-linux-armv6.tar.gz 234463f059249f82045824afdcdd5db5682d0593052f58f6a3039a0a1c3899f6 golangci-lint-1.55.2-darwin-arm64.tar.gz
1506b19f3f0410f6d85d1e339a47fcc84646d552516c0f429dc8cd7f34b4069a golangci-lint-1.52.2-windows-armv6.zip 2bdd105e2d4e003a9058c33a22bb191a1e0f30fa0790acca0d8fbffac1d6247c golangci-lint-1.55.2-freebsd-386.tar.gz
1cc68baa226e186c15c5514a6e93b1cc8d47ff06aaf1a395b8266434cb01df29 golangci-lint-1.52.2-linux-386.rpm e75056e8b082386676ce23eba455cf893931a792c0d87e1e3743c0aec33c7fb5 golangci-lint-1.55.2-freebsd-amd64.tar.gz
1d23661087ae686563e40d3b1e33f309dd3b4ba7d1c7e571ca7723f77a52a9e4 golangci-lint-1.52.2-linux-s390x.rpm 5789b933facaf6136bd23f1d50add67b79bbcf8dfdfc9069a37f729395940a66 golangci-lint-1.55.2-freebsd-armv6.tar.gz
227673a18d21b428f1768bb8ee46e38c36a0f002960bc6211ef6137b85d03f52 golangci-lint-1.52.2-freebsd-armv7.tar.gz 7f21ab1008d05f32c954f99470fc86a83a059e530fe2add1d0b7d8ed4d8992a7 golangci-lint-1.55.2-freebsd-armv7.tar.gz
24f0272e5741c05c59e7162b7ff0258cfa6beb0d9265bd87c386fe80ac25135d golangci-lint-1.52.2-linux-mips64.deb 33ab06139b9219a28251f10821da94423db30285cc2af97494cbb2a281927de9 golangci-lint-1.55.2-illumos-amd64.tar.gz
3abc8ad30b336ccbe3c5e3c65fa146f5b12d8e81e644345fa8d51cdbaa8cb570 golangci-lint-1.52.2-netbsd-amd64.tar.gz 57ce6f8ce3ad6ee45d7cc3d9a047545a851c2547637834a3fcb086c7b40b1e6b golangci-lint-1.55.2-linux-386.tar.gz
40a2645b4c7bd94c16618eb0f12b32cd54c17e5620f761cf477b256d3622f299 golangci-lint-1.52.2-windows-386.zip ca21c961a33be3bc15e4292dc40c98c8dcc5463a7b6768a3afc123761630c09c golangci-lint-1.55.2-linux-amd64.tar.gz
40b40002e07db81628d94108265525052c58fc9ce358bef26a36d27f0aea3d87 golangci-lint-1.52.2-windows-amd64.zip 8eb0cee9b1dbf0eaa49871798c7f8a5b35f2960c52d776a5f31eb7d886b92746 golangci-lint-1.55.2-linux-arm64.tar.gz
41e936b62ba4fc66c02daf6fa9cf74213bc2220745c7a796acbe197c05ed26bb golangci-lint-1.52.2-netbsd-armv6.tar.gz 3195f3e0f37d353fd5bd415cabcd4e263f5c29d3d0ffb176c26ff3d2c75eb3bb golangci-lint-1.55.2-linux-armv6.tar.gz
4bcbb4cf34bf3c8ae1ca880d12516a999499189326621599f8362ededd6e4229 golangci-lint-1.52.2-linux-riscv64.tar.gz c823ee36eb1a719e171de1f2f5ca3068033dce8d9817232fd10ed71fd6650406 golangci-lint-1.55.2-linux-armv7.tar.gz
4edb83f1433f7c57f06f79a7fc30bf3f920c1f86c334e481661ac6627d80293f golangci-lint-1.52.2-linux-arm64.deb 758a5d2a356dc494bd13ed4c0d4bf5a54a4dc91267ea5ecdd87b86c7ca0624e7 golangci-lint-1.55.2-linux-loong64.tar.gz
50d662e86d094dbad6634d086eca4f670ffa8ea7142508d8da357a2d750ac21a golangci-lint-1.52.2-linux-armv7.tar.gz 2c7b9abdce7cae802a67d583cd7c6dca520bff6d0e17c8535a918e2f2b437aa0 golangci-lint-1.55.2-linux-mips64.tar.gz
6891597bedbcd7e530d08ed198bab7eeb9b23f3f8161dc6e87505b783cb11593 golangci-lint-1.52.2-windows-arm64.zip 024e0a15b85352cc27271285526e16a4ab66d3e67afbbe446c9808c06cb8dbed golangci-lint-1.55.2-linux-mips64le.tar.gz
6d79f4f3448b70e83952e746fcb9e251c6ba94ec2790a912806cc1704ade4d64 golangci-lint-1.52.2-linux-mips64.rpm 6b00f89ba5506c1de1efdd9fa17c54093013a294fefd8b9b31534db626a672ee golangci-lint-1.55.2-linux-ppc64le.tar.gz
6de51ae05d39002421caf6049e0dd0014a2f10961471c5547c905d33d8e6adf1 golangci-lint-1.52.2-linux-armv6.deb 0faa0d047d9bf7b703ed3ea65b6117043c93504f9ca1de25ae929d3901c73d4a golangci-lint-1.55.2-linux-riscv64.tar.gz
715dc0f0cf3538c3b2c75f084dde8dcdc3485b3494f42a6d0d9c0dc61e62b5a8 golangci-lint-1.52.2-linux-s390x.tar.gz 30dec9b22e7d5bb4e9d5ccea96da20f71cd7db3c8cf30b8ddc7cb9174c4d742a golangci-lint-1.55.2-linux-s390x.tar.gz
7c559332a97ee49b80427aba5a7122e17cac18c57e700f48e6db5ffcbbb61b2b golangci-lint-1.52.2-linux-arm64.rpm 5a0ede48f79ad707902fdb29be8cd2abd8302dc122b65ebae3fdfc86751c7698 golangci-lint-1.55.2-netbsd-386.tar.gz
81201bb5f19897fefb4380af2e187a0133dc5efda22254698c063cc36a601f43 golangci-lint-1.52.2-linux-386.deb 95af20a2e617126dd5b08122ece7819101070e1582a961067ce8c41172f901ad golangci-lint-1.55.2-netbsd-amd64.tar.gz
89e523d45883903cfc472ab65621073f850abd4ffbb7720bbdd7ba66ee490bc8 golangci-lint-1.52.2-darwin-arm64.tar.gz 94fb7dacb7527847cc95d7120904e19a2a0a81a0d50d61766c9e0251da72ab9d golangci-lint-1.55.2-netbsd-armv6.tar.gz
8d60d63eee38f8de679e57b1a781de32987152f004f852f20cd47baa4c582209 golangci-lint-1.52.2-linux-mips64le.rpm ca906bce5fee9619400e4a321c56476fe4a4efb6ac4fc989d340eb5563348873 golangci-lint-1.55.2-netbsd-armv7.tar.gz
9e22df0516cbd847910f353d92245e58eab2b6edacc669646bfa06eb032a65a3 golangci-lint-1.52.2-linux-riscv64.deb 45b442f69fc8915c4500201c0247b7f3f69544dbc9165403a61f9095f2c57355 golangci-lint-1.55.2-windows-386.zip
a1a74747a196d4ccd2394ea8a461508eb2edf1eb5a88010611debf572991961d golangci-lint-1.52.2-linux-loong64.tar.gz f57d434d231d43417dfa631587522f8c1991220b43c8ffadb9c7bd279508bf81 golangci-lint-1.55.2-windows-amd64.zip
a7f076d0fb50e0f5bc24d0f3b2567f2cfe864441e6ad20323189b7fde7cc065d golangci-lint-1.52.2-freebsd-386.tar.gz fd7dc8f4c6829ee6fafb252a4d81d2155cd35da7833665cbb25d53ce7cecd990 golangci-lint-1.55.2-windows-arm64.zip
abc100851a59cbcea2a7e9ff5ad2974a43270135520aeac9a302ca6c712a41e1 golangci-lint-1.52.2-linux-loong64.rpm 1892c3c24f9e7ef44b02f6750c703864b6dc350129f3ec39510300007b2376f1 golangci-lint-1.55.2-windows-armv6.zip
adf11a1f7f43b5a431c19cccea260e6205e2e2b42a2d2d450e31c287fec199f2 golangci-lint-1.52.2-linux-amd64.rpm a5e68ae73d38748b5269fad36ac7575e3c162a5dc63ef58abdea03cc5da4522a golangci-lint-1.55.2-windows-armv7.zip
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
# This is the builder on PPA that will build Go itself (inception-y), don't modify! # This is the builder on PPA that will build Go itself (inception-y), don't modify!
#
# 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 d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz

View File

@@ -139,7 +139,7 @@ var (
// This is the version of Go that will be downloaded by // This is the version of Go that will be downloaded by
// //
// go run ci.go install -dlgo // 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. // 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. // downloadLinter downloads and unpacks golangci-lint.
func downloadLinter(cachedir string) string { func downloadLinter(cachedir string) string {
const version = "1.52.2" const version = "1.55.2"
csdb := build.MustLoadChecksums("build/checksums.txt") csdb := build.MustLoadChecksums("build/checksums.txt")
arch := runtime.GOARCH arch := runtime.GOARCH

View File

@@ -1206,7 +1206,7 @@ func GenDoc(ctx *cli.Context) error {
URL: accounts.URL{Path: ".. ignored .."}, URL: accounts.URL{Path: ".. ignored .."},
}, },
{ {
Address: common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff"), Address: common.MaxAddress,
}, },
}}) }})
} }

View File

@@ -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 - `-limit <N>` limits the output set to N entries, taking the top N nodes by score
- `-ip <CIDR>` filters nodes by IP subnet - `-ip <CIDR>` filters nodes by IP subnet
- `-min-age <duration>` filters nodes by 'first seen' time - `-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 - `-les-server` filters nodes by LES server support
- `-snap` filters nodes by snap protocol support - `-snap` filters nodes by snap protocol support

View File

@@ -27,8 +27,8 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/eth/protocols/snap"
"github.com/ethereum/go-ethereum/internal/utesting" "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"
"github.com/ethereum/go-ethereum/trie/trienode"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
@@ -58,7 +58,7 @@ type accRangeTest struct {
func (s *Suite) TestSnapGetAccountRange(t *utesting.T) { func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
var ( var (
root = s.chain.RootAt(999) root = s.chain.RootAt(999)
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") ffHash = common.MaxHash
zero = common.Hash{} zero = common.Hash{}
firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29") firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29")
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
@@ -125,7 +125,7 @@ type stRangesTest struct {
// TestSnapGetStorageRanges various forms of GetStorageRanges requests. // TestSnapGetStorageRanges various forms of GetStorageRanges requests.
func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) { func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) {
var ( var (
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") ffHash = common.MaxHash
zero = common.Hash{} zero = common.Hash{}
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606") secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
@@ -530,11 +530,11 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
for i, key := range hashes { for i, key := range hashes {
keys[i] = common.CopyBytes(key[:]) keys[i] = common.CopyBytes(key[:])
} }
nodes := make(light.NodeList, len(proof)) nodes := make(trienode.ProofList, len(proof))
for i, node := range proof { for i, node := range proof {
nodes[i] = node nodes[i] = node
} }
proofdb := nodes.NodeSet() proofdb := nodes.Set()
var end []byte var end []byte
if len(keys) > 0 { if len(keys) > 0 {

View File

@@ -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: 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: - `-genesis` is a path to a file containing the network `genesis.json`. or using:
- `-network` is the devp2p network id used during connection - `-ws` is ws endpoint to what faucet will connect to
- `-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).
## Funding ## Funding

View File

@@ -42,21 +42,11 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/keystore" "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/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "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/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/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/ethereum/go-ethereum/params"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
@@ -64,10 +54,7 @@ import (
var ( var (
genesisFlag = flag.String("genesis", "", "Genesis json file to seed the chain with") genesisFlag = flag.String("genesis", "", "Genesis json file to seed the chain with")
apiPortFlag = flag.Int("apiport", 8080, "Listener port for the HTTP API connection") apiPortFlag = flag.Int("apiport", 8080, "Listener port for the HTTP API connection")
ethPortFlag = flag.Int("ethport", 30303, "Listener port for the devp2p connection") wsEndpoint = flag.String("ws", "http://127.0.0.1:7777/", "Url to ws endpoint")
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")
netnameFlag = flag.String("faucet.name", "", "Network name to assign to the faucet") 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") payoutFlag = flag.Int("faucet.amount", 1, "Number of Ethers to pay out per user request")
@@ -163,15 +150,6 @@ func main() {
if err != nil { if err != nil {
log.Crit("Failed to read genesis block contents", "genesis", *genesisFlag, "err", err) 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 // Load up the account key and decrypt its password
blob, err := os.ReadFile(*accPassFlag) blob, err := os.ReadFile(*accPassFlag)
if err != nil { if err != nil {
@@ -191,7 +169,7 @@ func main() {
log.Crit("Failed to unlock faucet signer account", "err", err) log.Crit("Failed to unlock faucet signer account", "err", err)
} }
// Assemble and start the faucet light service // 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 { if err != nil {
log.Crit("Failed to start faucet", "err", err) 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. // faucet represents a crypto faucet backed by an Ethereum light client.
type faucet struct { type faucet struct {
config *params.ChainConfig // Chain configurations for signing config *params.ChainConfig // Chain configurations for signing
stack *node.Node // Ethereum protocol stack
client *ethclient.Client // Client connection to the Ethereum chain client *ethclient.Client // Client connection to the Ethereum chain
index []byte // Index page to serve up on the web index []byte // Index page to serve up on the web
@@ -248,65 +225,18 @@ type wsConn struct {
wlock sync.Mutex 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) { func newFaucet(genesis *core.Genesis, url 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
}
bep2eAbi, err := abi.JSON(strings.NewReader(bep2eAbiJson)) bep2eAbi, err := abi.JSON(strings.NewReader(bep2eAbiJson))
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Assemble the Ethereum light client protocol client, err := ethclient.Dial(url)
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)
if err != nil { 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 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{ return &faucet{
config: genesis.Config, config: genesis.Config,
stack: stack,
client: client, client: client,
index: index, index: index,
keystore: ks, 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. // close terminates the Ethereum connection and tears down the faucet.
func (f *faucet) close() error { func (f *faucet) close() {
return f.stack.Close() f.client.Close()
} }
// listenAndServe registers the HTTP handlers for the faucet and boots it up // 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. // apiHandler handles requests for Ether grants and transaction statuses.
func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) { 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) conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
return return
@@ -406,7 +336,6 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
if err = send(wsconn, map[string]interface{}{ if err = send(wsconn, map[string]interface{}{
"funds": new(big.Int).Div(balance, ether), "funds": new(big.Int).Div(balance, ether),
"funded": nonce, "funded": nonce,
"peers": f.stack.Server().PeerCount(),
"requests": reqs, "requests": reqs,
}, 3*time.Second); err != nil { }, 3*time.Second); err != nil {
log.Warn("Failed to send initial stats to client", "err", err) 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) 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) balance := new(big.Int).Div(f.balance, ether)
peers := f.stack.Server().PeerCount()
for _, conn := range f.conns { for _, conn := range f.conns {
if err := send(conn, map[string]interface{}{ if err := send(conn, map[string]interface{}{
"funds": balance, "funds": balance,
"funded": f.nonce, "funded": f.nonce,
"peers": peers,
"requests": f.reqs, "requests": f.reqs,
}, time.Second); err != nil { }, time.Second); err != nil {
log.Warn("Failed to send stats to client", "err", err) log.Warn("Failed to send stats to client", "err", err)

View File

@@ -15,7 +15,6 @@ import (
"github.com/prysmaticlabs/prysm/v4/crypto/bls" "github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/io/prompt" "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" 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"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface" "github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
@@ -466,7 +465,7 @@ func blsAccountImport(ctx *cli.Context) error {
utils.Fatalf("Import BLS account failed: %v.", err) utils.Fatalf("Import BLS account failed: %v.", err)
} }
// len(statuses)==len(Keystores) when err==nil // 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) fmt.Printf("Could not import keystore: %v.", statuses[0].Message)
} else { } else {
fmt.Println("Successfully import BLS account.") fmt.Println("Successfully import BLS account.")
@@ -634,29 +633,24 @@ func blsAccountDelete(ctx *cli.Context) error {
// blsAccountGenerateProof generate ownership proof for a selected BLS account. // blsAccountGenerateProof generate ownership proof for a selected BLS account.
func blsAccountGenerateProof(ctx *cli.Context) error { func blsAccountGenerateProof(ctx *cli.Context) error {
if ctx.Args().Len() == 0 { addrString := ctx.Args().First()
utils.Fatalf("No BLS account specified.") if addrString == "" {
utils.Fatalf("Operator account must be given as argument.")
} }
var filteredPubKeys []bls.PublicKey addr := common.HexToAddress(addrString)
for _, str := range ctx.Args().Slice() {
pkString := str blsPubkeyString := ctx.Args().Get(1)
if strings.Contains(pkString, "0x") { if blsPubkeyString == "" {
pkString = pkString[2:] utils.Fatalf("BLS pubkey must be given as argument.")
} }
pubKeyBytes, err := hex.DecodeString(pkString) blsPubkeyBz, err := hex.DecodeString(strings.TrimPrefix(blsPubkeyString, "0x"))
if err != nil { if err != nil {
utils.Fatalf("Could not decode string %s as hex.", pkString) utils.Fatalf("Could not decode string %s as hex.", blsPubkeyString)
} }
blsPublicKey, err := bls.PublicKeyFromBytes(pubKeyBytes) blsPublicKey, err := bls.PublicKeyFromBytes(blsPubkeyBz)
if err != nil { if err != nil {
utils.Fatalf("%#x is not a valid BLS public key.", pubKeyBytes) utils.Fatalf("%#x is not a valid BLS public key.", blsPubkeyBz)
} }
filteredPubKeys = append(filteredPubKeys, blsPublicKey)
}
if len(filteredPubKeys) > 1 {
utils.Fatalf("Only support one BLS account specified.")
}
pubkeyBz := filteredPubKeys[0].Marshal()
cfg := gethConfig{Node: defaultNodeConfig()} cfg := gethConfig{Node: defaultNodeConfig()}
// Load config file. // Load config file.
@@ -693,10 +687,10 @@ func blsAccountGenerateProof(ctx *cli.Context) error {
chainId := new(big.Int).SetInt64(chainIdInt64) chainId := new(big.Int).SetInt64(chainIdInt64)
paddedChainIdBytes := make([]byte, 32) paddedChainIdBytes := make([]byte, 32)
copy(paddedChainIdBytes[32-len(chainId.Bytes()):], chainId.Bytes()) copy(paddedChainIdBytes[32-len(chainId.Bytes()):], chainId.Bytes())
msgHash := crypto.Keccak256(append(pubkeyBz, paddedChainIdBytes...)) msgHash := crypto.Keccak256(append(addr.Bytes(), append(blsPublicKey.Marshal(), paddedChainIdBytes...)...))
req := &validatorpb.SignRequest{ req := &validatorpb.SignRequest{
PublicKey: pubkeyBz, PublicKey: blsPublicKey.Marshal(),
SigningRoot: msgHash, SigningRoot: msgHash,
} }
sig, err := km.Sign(context.Background(), req) sig, err := km.Sign(context.Background(), req)

View File

@@ -30,6 +30,9 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/olekukonko/tablewriter"
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@@ -44,7 +47,8 @@ import (
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/enode" "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 ( var (
@@ -191,6 +195,21 @@ It's deprecated, please use "geth db export" instead.
}, utils.DatabasePathFlags), }, utils.DatabasePathFlags),
Description: ` Description: `
This command dumps out the state for a given block (or latest, if none provided). 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 { if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err) 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 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) { 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 { if ctx.NArg() > 1 {
return nil, nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg()) 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 { if ctx.NArg() == 1 {
arg := ctx.Args().First() arg := ctx.Args().First()
if hashish(arg) { if hashish(arg) {
@@ -617,11 +645,22 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
} }
} else { } else {
// Use latest // Use latest
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) header = rawdb.ReadHeadHeader(db)
} }
}
if header == nil { if header == nil {
return nil, nil, common.Hash{}, errors.New("no head block found") return nil, nil, common.Hash{}, errors.New("no head block found")
} }
startArg := common.FromHex(ctx.String(utils.StartKeyFlag.Name)) startArg := common.FromHex(ctx.String(utils.StartKeyFlag.Name))
var start common.Hash var start common.Hash
switch len(startArg) { switch len(startArg) {
@@ -634,6 +673,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
default: default:
return nil, nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg) return nil, nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
} }
var conf = &state.DumpConfig{ var conf = &state.DumpConfig{
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name), SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.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(), Start: start.Bytes(),
Max: ctx.Uint64(utils.DumpLimitFlag.Name), Max: ctx.Uint64(utils.DumpLimitFlag.Name),
} }
conf.StateScheme = scheme
log.Info("State dump configured", "block", header.Number, "hash", header.Hash().Hex(), log.Info("State dump configured", "block", header.Number, "hash", header.Hash().Hex(),
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage, "skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage, "start", hexutil.Encode(conf.Start),
"start", hexutil.Encode(conf.Start), "limit", conf.Max) "limit", conf.Max, "state scheme", conf.StateScheme)
return conf, db, header.Root, nil return conf, db, header.Root, nil
} }
@@ -655,7 +696,7 @@ func dump(ctx *cli.Context) error {
if err != nil { if err != nil {
return err 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() defer triedb.Close()
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil) state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
@@ -675,6 +716,29 @@ func dump(ctx *cli.Context) error {
return nil 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. // hashish returns true for strings that look like hashes.
func hashish(x string) bool { func hashish(x string) bool {
_, err := strconv.Atoi(x) _, err := strconv.Atoi(x)

View File

@@ -24,6 +24,7 @@ import (
"reflect" "reflect"
"unicode" "unicode"
"github.com/naoina/toml"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
@@ -32,6 +33,8 @@ import (
"github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/accounts/usbwallet" "github.com/ethereum/go-ethereum/accounts/usbwallet"
"github.com/ethereum/go-ethereum/cmd/utils" "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/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
@@ -40,7 +43,6 @@ import (
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/naoina/toml"
) )
var ( var (
@@ -56,6 +58,7 @@ var (
configFileFlag = &cli.StringFlag{ configFileFlag = &cli.StringFlag{
Name: "config", Name: "config",
Usage: "TOML configuration file", 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. // Apply flags.
utils.SetNodeConfig(ctx, &cfg.Node) utils.SetNodeConfig(ctx, &cfg.Node)
return cfg return cfg
@@ -164,6 +177,19 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
// makeFullNode loads geth configuration and creates the Ethereum backend. // makeFullNode loads geth configuration and creates the Ethereum backend.
func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
stack, cfg := makeConfigNode(ctx) 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) { if ctx.IsSet(utils.OverrideCancun.Name) {
v := ctx.Uint64(utils.OverrideCancun.Name) v := ctx.Uint64(utils.OverrideCancun.Name)
cfg.Eth.OverrideCancun = &v cfg.Eth.OverrideCancun = &v
@@ -172,6 +198,10 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
v := ctx.Uint64(utils.OverrideVerkle.Name) v := ctx.Uint64(utils.OverrideVerkle.Name)
cfg.Eth.OverrideVerkle = &v cfg.Eth.OverrideVerkle = &v
} }
if ctx.IsSet(utils.OverrideFeynman.Name) {
v := ctx.Uint64(utils.OverrideFeynman.Name)
cfg.Eth.OverrideFeynman = &v
}
backend, _ := utils.RegisterEthService(stack, &cfg.Eth) backend, _ := utils.RegisterEthService(stack, &cfg.Eth)
// Configure log filter RPC API. // Configure log filter RPC API.

View File

@@ -60,7 +60,7 @@ func TestConsoleWelcome(t *testing.T) {
geth.SetTemplateFunc("gover", runtime.Version) geth.SetTemplateFunc("gover", runtime.Version)
geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") }) geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
geth.SetTemplateFunc("niltime", func() string { 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 }) 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("gethver", func() string { return params.VersionWithCommit("", "") })
attach.SetTemplateFunc("etherbase", func() string { return geth.Etherbase }) attach.SetTemplateFunc("etherbase", func() string { return geth.Etherbase })
attach.SetTemplateFunc("niltime", func() string { 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("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") })
attach.SetTemplateFunc("datadir", func() string { return geth.Datadir }) attach.SetTemplateFunc("datadir", func() string { return geth.Datadir })

View File

@@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@@ -63,6 +64,7 @@ Remove blockchain and state databases`,
dbCompactCmd, dbCompactCmd,
dbGetCmd, dbGetCmd,
dbDeleteCmd, dbDeleteCmd,
dbInspectTrieCmd,
dbPutCmd, dbPutCmd,
dbGetSlotsCmd, dbGetSlotsCmd,
dbDumpFreezerIndex, dbDumpFreezerIndex,
@@ -88,6 +90,17 @@ Remove blockchain and state databases`,
Usage: "Inspect the storage size for each type of data in the database", 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.`, 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{ dbCheckStateContentCmd = &cli.Command{
Action: checkStateContent, Action: checkStateContent,
Name: "check-state-content", Name: "check-state-content",
@@ -119,7 +132,8 @@ a data corruption.`,
Flags: []cli.Flag{ Flags: []cli.Flag{
utils.DataDirFlag, utils.DataDirFlag,
utils.SyncModeFlag, utils.SyncModeFlag,
utils.MainnetFlag, utils.BSCMainnetFlag,
utils.ChapelFlag,
utils.StateSchemeFlag, utils.StateSchemeFlag,
}, },
Description: "This command looks up the specified trie node key from the database.", Description: "This command looks up the specified trie node key from the database.",
@@ -132,7 +146,8 @@ a data corruption.`,
Flags: []cli.Flag{ Flags: []cli.Flag{
utils.DataDirFlag, utils.DataDirFlag,
utils.SyncModeFlag, utils.SyncModeFlag,
utils.MainnetFlag, utils.BSCMainnetFlag,
utils.ChapelFlag,
utils.StateSchemeFlag, utils.StateSchemeFlag,
}, },
Description: "This command delete the specify trie node from the database.", 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 { func inspect(ctx *cli.Context) error {
var ( var (
prefix []byte prefix []byte

View File

@@ -89,7 +89,7 @@ func TestCustomGenesis(t *testing.T) {
// Query the custom genesis block // Query the custom genesis block
geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16", 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", "--nodiscover", "--nat", "none", "--ipcdisable",
"--exec", tt.query, "console") "--exec", tt.query, "console")
geth.ExpectRegexp(tt.result) geth.ExpectRegexp(tt.result)
@@ -141,7 +141,7 @@ func TestCustomBackend(t *testing.T) {
} }
{ // Exec + query { // Exec + query
args := append(tt.execArgs, "--networkid", "1337", "--syncmode=full", "--cache", "16", 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", "--nodiscover", "--nat", "none", "--ipcdisable",
"--exec", "eth.getBlock(0).nonce", "console") "--exec", "eth.getBlock(0).nonce", "console")
geth := runGeth(t, args...) geth := runGeth(t, args...)
@@ -176,19 +176,19 @@ func TestCustomBackend(t *testing.T) {
{ // Can't start pebble on top of leveldb { // Can't start pebble on top of leveldb
initArgs: []string{"--db.engine", "leveldb"}, initArgs: []string{"--db.engine", "leveldb"},
execArgs: []string{"--db.engine", "pebble"}, 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 { // Can't start leveldb on top of pebble
initArgs: []string{"--db.engine", "pebble"}, initArgs: []string{"--db.engine", "pebble"},
execArgs: []string{"--db.engine", "leveldb"}, 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 { // Reject invalid backend choice
initArgs: []string{"--db.engine", "mssql"}, initArgs: []string{"--db.engine", "mssql"},
initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`, initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`,
// Since the init fails, this will return the (default) mainnet genesis // Since the init fails, this will return the (default) mainnet genesis
// block nonce // block nonce
execExpect: `0x0000000000000042`, execExpect: `0x0000000000000000`,
}, },
} { } {
if err := testfunc(t, tt); err != nil { if err := testfunc(t, tt); err != nil {

View File

@@ -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)
}
}

View File

@@ -61,7 +61,7 @@ var (
utils.MinFreeDiskSpaceFlag, utils.MinFreeDiskSpaceFlag,
utils.KeyStoreDirFlag, utils.KeyStoreDirFlag,
utils.ExternalSignerFlag, utils.ExternalSignerFlag,
utils.NoUSBFlag, utils.NoUSBFlag, // deprecated
utils.DirectBroadcastFlag, utils.DirectBroadcastFlag,
utils.DisableSnapProtocolFlag, utils.DisableSnapProtocolFlag,
utils.EnableTrustProtocolFlag, utils.EnableTrustProtocolFlag,
@@ -69,8 +69,12 @@ var (
utils.RangeLimitFlag, utils.RangeLimitFlag,
utils.USBFlag, utils.USBFlag,
utils.SmartCardDaemonPathFlag, utils.SmartCardDaemonPathFlag,
utils.RialtoHash,
utils.OverrideShanghai,
utils.OverrideKepler,
utils.OverrideCancun, utils.OverrideCancun,
utils.OverrideVerkle, utils.OverrideVerkle,
utils.OverrideFeynman,
utils.EnablePersonal, utils.EnablePersonal,
utils.TxPoolLocalsFlag, utils.TxPoolLocalsFlag,
utils.TxPoolNoLocalsFlag, utils.TxPoolNoLocalsFlag,
@@ -93,29 +97,30 @@ var (
utils.ExitWhenSyncedFlag, utils.ExitWhenSyncedFlag,
utils.GCModeFlag, utils.GCModeFlag,
utils.SnapshotFlag, utils.SnapshotFlag,
utils.TxLookupLimitFlag, utils.TxLookupLimitFlag, // deprecated
utils.TransactionHistoryFlag, utils.TransactionHistoryFlag,
utils.StateSchemeFlag, utils.StateSchemeFlag,
utils.StateHistoryFlag, utils.StateHistoryFlag,
utils.PathDBSyncFlag, utils.PathDBSyncFlag,
utils.LightServeFlag, utils.LightServeFlag, // deprecated
utils.LightIngressFlag, utils.LightIngressFlag, // deprecated
utils.LightEgressFlag, utils.LightEgressFlag, // deprecated
utils.LightMaxPeersFlag, utils.LightMaxPeersFlag, // deprecated
utils.LightNoPruneFlag, utils.LightNoPruneFlag, // deprecated
utils.LightKDFFlag, utils.LightKDFFlag, // deprecated
utils.LightNoSyncServeFlag, utils.LightNoSyncServeFlag, // deprecated
utils.EthRequiredBlocksFlag, utils.EthRequiredBlocksFlag,
utils.LegacyWhitelistFlag, utils.LegacyWhitelistFlag, // deprecated
utils.BloomFilterSizeFlag, utils.BloomFilterSizeFlag,
utils.TriesInMemoryFlag, utils.TriesInMemoryFlag,
utils.CacheFlag, utils.CacheFlag,
utils.CacheDatabaseFlag, utils.CacheDatabaseFlag,
utils.CacheTrieFlag, utils.CacheTrieFlag,
utils.CacheTrieJournalFlag, utils.CacheTrieJournalFlag, // deprecated
utils.CacheTrieRejournalFlag, utils.CacheTrieRejournalFlag, // deprecated
utils.CacheGCFlag, utils.CacheGCFlag,
utils.CacheSnapshotFlag, utils.CacheSnapshotFlag,
// utils.CacheNoPrefetchFlag,
utils.CachePreimagesFlag, utils.CachePreimagesFlag,
utils.PersistDiffFlag, utils.PersistDiffFlag,
utils.DiffBlockFlag, utils.DiffBlockFlag,
@@ -135,12 +140,12 @@ var (
utils.MinerExtraDataFlag, utils.MinerExtraDataFlag,
utils.MinerRecommitIntervalFlag, utils.MinerRecommitIntervalFlag,
utils.MinerDelayLeftoverFlag, utils.MinerDelayLeftoverFlag,
utils.MinerNewPayloadTimeout, // utils.MinerNewPayloadTimeout,
utils.NATFlag, utils.NATFlag,
utils.NoDiscoverFlag, utils.NoDiscoverFlag,
utils.DiscoveryV4Flag, utils.DiscoveryV4Flag,
utils.DiscoveryV5Flag, utils.DiscoveryV5Flag,
utils.LegacyDiscoveryV5Flag, utils.LegacyDiscoveryV5Flag, // deprecated
utils.NetrestrictFlag, utils.NetrestrictFlag,
utils.NodeKeyFileFlag, utils.NodeKeyFileFlag,
utils.NodeKeyHexFlag, utils.NodeKeyHexFlag,
@@ -173,10 +178,10 @@ var (
utils.HTTPListenAddrFlag, utils.HTTPListenAddrFlag,
utils.HTTPPortFlag, utils.HTTPPortFlag,
utils.HTTPCORSDomainFlag, utils.HTTPCORSDomainFlag,
utils.AuthListenFlag, // utils.AuthListenFlag,
utils.AuthPortFlag, // utils.AuthPortFlag,
utils.AuthVirtualHostsFlag, // utils.AuthVirtualHostsFlag,
utils.JWTSecretFlag, // utils.JWTSecretFlag,
utils.HTTPVirtualHostsFlag, utils.HTTPVirtualHostsFlag,
utils.GraphQLEnabledFlag, utils.GraphQLEnabledFlag,
utils.GraphQLCORSDomainFlag, utils.GraphQLCORSDomainFlag,
@@ -235,6 +240,7 @@ func init() {
removedbCommand, removedbCommand,
dumpCommand, dumpCommand,
dumpGenesisCommand, dumpGenesisCommand,
dumpRootHashCommand,
// See accountcmd.go: // See accountcmd.go:
accountCommand, accountCommand,
walletCommand, walletCommand,
@@ -292,6 +298,9 @@ func main() {
func prepare(ctx *cli.Context) { func prepare(ctx *cli.Context) {
// If we're running a known preset, log it for convenience. // If we're running a known preset, log it for convenience.
switch { switch {
case ctx.IsSet(utils.ChapelFlag.Name):
log.Info("Starting BSC on Chapel testnet...")
case ctx.IsSet(utils.DeveloperFlag.Name): case ctx.IsSet(utils.DeveloperFlag.Name):
log.Info("Starting Geth in ephemeral dev mode...") log.Info("Starting Geth in ephemeral dev mode...")
log.Warn(`You are running Geth in --dev mode. Please note the following: log.Warn(`You are running Geth in --dev mode. Please note the following:
@@ -311,22 +320,18 @@ func prepare(ctx *cli.Context) {
`) `)
case !ctx.IsSet(utils.NetworkIdFlag.Name): 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 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 // 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! // 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) log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
ctx.Set(utils.CacheFlag.Name, strconv.Itoa(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. // geth is the main entry point into the system if no special subcommand is run.

View File

@@ -55,6 +55,15 @@ func TestMain(m *testing.M) {
os.Exit(m.Run()) 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 // spawns geth with the given command line args. If the args don't set --datadir, the
// child g gets a temporary data directory. // child g gets a temporary data directory.
func runGeth(t *testing.T, args ...string) *testgeth { func runGeth(t *testing.T, args ...string) *testgeth {

25
cmd/jsutils/README.md Normal file
View 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
View 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);
});

View 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
View 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"
}

View File

@@ -18,6 +18,7 @@
package utils package utils
import ( import (
"bufio"
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"encoding/hex" "encoding/hex"
@@ -51,7 +52,6 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
@@ -63,7 +63,6 @@ import (
"github.com/ethereum/go-ethereum/graphql" "github.com/ethereum/go-ethereum/graphql"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/exp" "github.com/ethereum/go-ethereum/metrics/exp"
@@ -165,13 +164,18 @@ var (
} }
NetworkIdFlag = &cli.Uint64Flag{ NetworkIdFlag = &cli.Uint64Flag{
Name: "networkid", 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, Value: ethconfig.Defaults.NetworkId,
Category: flags.EthCategory, Category: flags.EthCategory,
} }
MainnetFlag = &cli.BoolFlag{ BSCMainnetFlag = &cli.BoolFlag{
Name: "mainnet", 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, Category: flags.EthCategory,
} }
DeveloperFlag = &cli.BoolFlag{ DeveloperFlag = &cli.BoolFlag{
@@ -286,6 +290,21 @@ var (
Value: &defaultVerifyMode, Value: &defaultVerifyMode,
Category: flags.FastNodeCategory, 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{ OverrideCancun = &cli.Uint64Flag{
Name: "override.cancun", Name: "override.cancun",
Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting", Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting",
@@ -296,9 +315,14 @@ var (
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting", Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideFeynman = &cli.Uint64Flag{
Name: "override.feynman",
Usage: "Manually specify the Feynman fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
SyncModeFlag = &flags.TextMarshalerFlag{ SyncModeFlag = &flags.TextMarshalerFlag{
Name: "syncmode", Name: "syncmode",
Usage: `Blockchain sync mode ("snap", "full" or "light")`, Usage: `Blockchain sync mode ("snap" or "full")`,
Value: &defaultSyncMode, Value: &defaultSyncMode,
Category: flags.StateCategory, Category: flags.StateCategory,
} }
@@ -311,7 +335,6 @@ var (
StateSchemeFlag = &cli.StringFlag{ StateSchemeFlag = &cli.StringFlag{
Name: "state.scheme", Name: "state.scheme",
Usage: "Scheme to use for storing ethereum state ('hash' or 'path')", Usage: "Scheme to use for storing ethereum state ('hash' or 'path')",
Value: rawdb.HashScheme,
Category: flags.StateCategory, Category: flags.StateCategory,
} }
PathDBSyncFlag = &cli.BoolFlag{ PathDBSyncFlag = &cli.BoolFlag{
@@ -332,41 +355,6 @@ var (
Value: ethconfig.Defaults.TransactionHistory, Value: ethconfig.Defaults.TransactionHistory,
Category: flags.StateCategory, 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 // Transaction pool settings
TxPoolLocalsFlag = &cli.StringFlag{ TxPoolLocalsFlag = &cli.StringFlag{
Name: "txpool.locals", Name: "txpool.locals",
@@ -436,6 +424,7 @@ var (
Name: "txpool.reannouncetime", Name: "txpool.reannouncetime",
Usage: "Duration for announcing local pending transactions again (default = 10 years, minimum = 1 minute)", Usage: "Duration for announcing local pending transactions again (default = 10 years, minimum = 1 minute)",
Value: ethconfig.Defaults.TxPool.ReannounceTime, Value: ethconfig.Defaults.TxPool.ReannounceTime,
Category: flags.TxPoolCategory,
} }
// Blob transaction pool settings // Blob transaction pool settings
BlobPoolDataDirFlag = &cli.StringFlag{ BlobPoolDataDirFlag = &cli.StringFlag{
@@ -511,7 +500,7 @@ var (
PruneAncientDataFlag = &cli.BoolFlag{ PruneAncientDataFlag = &cli.BoolFlag{
Name: "pruneancient", 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.", 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{ CacheLogSizeFlag = &cli.IntFlag{
Name: "cache.blocklogs", Name: "cache.blocklogs",
@@ -575,7 +564,7 @@ var (
Name: "miner.newpayload-timeout", Name: "miner.newpayload-timeout",
Usage: "Specify the maximum time allowance for creating a new payload", Usage: "Specify the maximum time allowance for creating a new payload",
Value: ethconfig.Defaults.Miner.NewPayloadTimeout, Value: ethconfig.Defaults.Miner.NewPayloadTimeout,
// Category: flags.MinerCategory, Category: flags.MinerCategory,
} }
// Account settings // Account settings
@@ -1057,7 +1046,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
BlockAmountReserved = &cli.Uint64Flag{ BlockAmountReserved = &cli.Uint64Flag{
Name: "block-amount-reserved", Name: "block-amount-reserved",
Usage: "Sets the expected remained amount of blocks for offline block prune", Usage: "Sets the expected remained amount of blocks for offline block prune",
Category: flags.HistoryCategory, Category: flags.BlockHistoryCategory,
} }
CheckSnapshotWithMPT = &cli.BoolFlag{ CheckSnapshotWithMPT = &cli.BoolFlag{
@@ -1069,7 +1058,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
EnableDoubleSignMonitorFlag = &cli.BoolFlag{ EnableDoubleSignMonitorFlag = &cli.BoolFlag{
Name: "monitor.doublesign", Name: "monitor.doublesign",
Usage: "Enable double sign monitor to check whether any validator signs multiple blocks", Usage: "Enable double sign monitor to check whether any validator signs multiple blocks",
Category: flags.FastFinalityCategory, Category: flags.MinerCategory,
} }
VotingEnabledFlag = &cli.BoolFlag{ VotingEnabledFlag = &cli.BoolFlag{
@@ -1111,25 +1100,22 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
var ( var (
// TestnetFlags is the flag group of all built-in supported testnets. // 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 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 is the flag group of all database path flags.
DatabasePathFlags = []cli.Flag{ DatabasePathFlags = []cli.Flag{
DataDirFlag, DataDirFlag,
AncientFlag, AncientFlag,
RemoteDBFlag, RemoteDBFlag,
DBEngineFlag,
HttpHeaderFlag, HttpHeaderFlag,
} }
) )
func init() {
if rawdb.PebbleEnabled {
DatabasePathFlags = append(DatabasePathFlags, DBEngineFlag)
}
}
// MakeDataDir retrieves the currently requested data directory, terminating // MakeDataDir retrieves the currently requested data directory, terminating
// if none (or the empty string) is specified. If the node is starting a testnet, // 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. // then a subdirectory of the specified datadir will be used.
@@ -1259,8 +1245,10 @@ func SplitAndTrim(input string) (ret []string) {
// setHTTP creates the HTTP RPC listener interface string from the set // setHTTP creates the HTTP RPC listener interface string from the set
// command line flags, returning empty if the HTTP endpoint is disabled. // command line flags, returning empty if the HTTP endpoint is disabled.
func setHTTP(ctx *cli.Context, cfg *node.Config) { func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.Bool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" { if ctx.Bool(HTTPEnabledFlag.Name) {
if cfg.HTTPHost == "" {
cfg.HTTPHost = "127.0.0.1" cfg.HTTPHost = "127.0.0.1"
}
if ctx.IsSet(HTTPListenAddrFlag.Name) { if ctx.IsSet(HTTPListenAddrFlag.Name) {
cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name) cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name)
} }
@@ -1324,8 +1312,10 @@ func setGraphQL(ctx *cli.Context, cfg *node.Config) {
// setWS creates the WebSocket RPC listener interface string from the set // setWS creates the WebSocket RPC listener interface string from the set
// command line flags, returning empty if the HTTP endpoint is disabled. // command line flags, returning empty if the HTTP endpoint is disabled.
func setWS(ctx *cli.Context, cfg *node.Config) { func setWS(ctx *cli.Context, cfg *node.Config) {
if ctx.Bool(WSEnabledFlag.Name) && cfg.WSHost == "" { if ctx.Bool(WSEnabledFlag.Name) {
if cfg.WSHost == "" {
cfg.WSHost = "127.0.0.1" cfg.WSHost = "127.0.0.1"
}
if ctx.IsSet(WSListenAddrFlag.Name) { if ctx.IsSet(WSListenAddrFlag.Name) {
cfg.WSHost = ctx.String(WSListenAddrFlag.Name) cfg.WSHost = ctx.String(WSListenAddrFlag.Name)
} }
@@ -1359,25 +1349,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) { func setLes(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.IsSet(LightServeFlag.Name) { 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) { 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) { 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) { 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) { 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) { 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)
} }
} }
@@ -1488,27 +1478,8 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
setBootstrapNodes(ctx, cfg) setBootstrapNodes(ctx, cfg)
setBootstrapNodesV5(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) { if ctx.IsSet(MaxPeersFlag.Name) {
cfg.MaxPeers = ctx.Int(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 max peers per ip is not set, use max peers
if cfg.MaxPeersPerIP <= 0 { if cfg.MaxPeersPerIP <= 0 {
@@ -1519,36 +1490,21 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
cfg.MaxPeersPerIP = ctx.Int(MaxPeersPerIPFlag.Name) cfg.MaxPeersPerIP = ctx.Int(MaxPeersPerIPFlag.Name)
} }
if !(lightClient || lightServer) { ethPeers := cfg.MaxPeers
lightPeers = 0 log.Info("Maximum peer count", "ETH", ethPeers, "total", cfg.MaxPeers)
}
ethPeers := cfg.MaxPeers - lightPeers
if lightClient {
ethPeers = 0
}
log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
if ctx.IsSet(MaxPendingPeersFlag.Name) { if ctx.IsSet(MaxPendingPeersFlag.Name) {
cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name) cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name)
} }
if ctx.IsSet(NoDiscoverFlag.Name) || lightClient { if ctx.IsSet(NoDiscoverFlag.Name) {
cfg.NoDiscovery = true 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, DiscoveryV4Flag, NoDiscoverFlag)
CheckExclusive(ctx, DiscoveryV5Flag, NoDiscoverFlag) CheckExclusive(ctx, DiscoveryV5Flag, NoDiscoverFlag)
cfg.DiscoveryV4 = ctx.Bool(DiscoveryV4Flag.Name) cfg.DiscoveryV4 = ctx.Bool(DiscoveryV4Flag.Name)
cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.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 != "" { if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" {
list, err := netutil.ParseNetlist(netrestrict) list, err := netutil.ParseNetlist(netrestrict)
if err != nil { if err != nil {
@@ -1680,12 +1636,7 @@ func setBLSWalletDir(ctx *cli.Context, cfg *node.Config) {
} }
} }
func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) { func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
// If we are running the light client, apply another group
// settings for gas oracle.
if light {
*cfg = ethconfig.LightClientGPO
}
if ctx.IsSet(GpoBlocksFlag.Name) { if ctx.IsSet(GpoBlocksFlag.Name) {
cfg.Blocks = ctx.Int(GpoBlocksFlag.Name) cfg.Blocks = ctx.Int(GpoBlocksFlag.Name)
} }
@@ -1845,13 +1796,12 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
// SetEthConfig applies eth-related command line flags to the config. // SetEthConfig applies eth-related command line flags to the config.
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// Avoid conflicting network flags // Avoid conflicting network flags
CheckExclusive(ctx, MainnetFlag, DeveloperFlag) CheckExclusive(ctx, BSCMainnetFlag, DeveloperFlag)
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
// Set configurations from CLI flags // Set configurations from CLI flags
setEtherbase(ctx, cfg) setEtherbase(ctx, cfg)
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light") setGPO(ctx, &cfg.GPO)
setTxPool(ctx, &cfg.TxPool) setTxPool(ctx, &cfg.TxPool)
setMiner(ctx, &cfg.Miner) setMiner(ctx, &cfg.Miner)
setRequiredBlocks(ctx, cfg) setRequiredBlocks(ctx, cfg)
@@ -1903,7 +1853,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if cfg.SyncMode == downloader.FullSync { if cfg.SyncMode == downloader.FullSync {
cfg.PruneAncientData = ctx.Bool(PruneAncientDataFlag.Name) cfg.PruneAncientData = ctx.Bool(PruneAncientDataFlag.Name)
} else { } 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" { if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
@@ -1939,15 +1889,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(StateHistoryFlag.Name) { if ctx.IsSet(StateHistoryFlag.Name) {
cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name) cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name)
} }
// Parse state scheme, abort the process if it's not compatible. scheme, err := CompareStateSchemeCLIWithConfig(ctx)
chaindb := tryMakeReadOnlyDatabase(ctx, stack)
scheme, err := ParseStateScheme(ctx, chaindb)
chaindb.Close()
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
cfg.StateScheme = scheme cfg.StateScheme = scheme
// Parse transaction history flag, if user is still using legacy config // Parse transaction history flag, if user is still using legacy config
// file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'. // file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'.
if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit { if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit {
@@ -1965,9 +1911,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.TransactionHistory = 0 cfg.TransactionHistory = 0
log.Warn("Disabled transaction unindexing for archive node") 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) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
} }
@@ -2034,12 +1977,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
} }
// Override any default configs for hard coded networks. // Override any default configs for hard coded networks.
switch { switch {
case ctx.Bool(MainnetFlag.Name): case ctx.Bool(BSCMainnetFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) { if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1 cfg.NetworkId = 56
} }
cfg.Genesis = core.DefaultGenesisBlock() cfg.Genesis = core.DefaultBSCGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) 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): case ctx.Bool(DeveloperFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) { if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1337 cfg.NetworkId = 1337
@@ -2098,7 +2047,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
readonly = false readonly = false
} }
// Check if we have an already initialized chain and fall back to // 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) chaindb := MakeChainDatabase(ctx, stack, readonly, false)
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) { if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
cfg.Genesis = nil // fallback to db content cfg.Genesis = nil // fallback to db content
@@ -2130,9 +2079,6 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
return // already set through flags/config return // already set through flags/config
} }
protocol := "all" protocol := "all"
if cfg.SyncMode == downloader.LightSync {
protocol = "les"
}
if url := params.KnownDNSNetwork(genesis, protocol); url != "" { if url := params.KnownDNSNetwork(genesis, protocol); url != "" {
cfg.EthDiscoveryURLs = []string{url} cfg.EthDiscoveryURLs = []string{url}
cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs
@@ -2142,27 +2088,12 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
} }
// RegisterEthService adds an Ethereum client to the stack. // RegisterEthService adds an Ethereum client to the stack.
// The second return value is the full node instance, which may be nil if the // The second return value is the full node instance.
// node is running as a light client.
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) { 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) backend, err := eth.New(stack, cfg)
if err != nil { if err != nil {
Fatalf("Failed to register the Ethereum service: %v", err) 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)) stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
return backend.APIBackend, backend return backend.APIBackend, backend
} }
@@ -2211,13 +2142,12 @@ func EnableMinerInfo(ctx *cli.Context, minerConfig miner.Config) SetupMetricsOpt
// RegisterFilterAPI adds the eth log filtering RPC API to the node. // RegisterFilterAPI adds the eth log filtering RPC API to the node.
func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem { func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
isLightClient := ethcfg.SyncMode == downloader.LightSync
filterSystem := filters.NewFilterSystem(backend, filters.Config{ filterSystem := filters.NewFilterSystem(backend, filters.Config{
LogCacheSize: ethcfg.FilterLogCacheSize, LogCacheSize: ethcfg.FilterLogCacheSize,
}) })
stack.RegisterAPIs([]rpc.API{{ stack.RegisterAPIs([]rpc.API{{
Namespace: "eth", Namespace: "eth",
Service: filters.NewFilterAPI(filterSystem, isLightClient, ethcfg.RangeLimit), Service: filters.NewFilterAPI(filterSystem, ethcfg.RangeLimit),
}}) }})
return filterSystem return filterSystem
} }
@@ -2352,6 +2282,8 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree
// tryMakeReadOnlyDatabase try to open the chain database in read-only mode, // tryMakeReadOnlyDatabase try to open the chain database in read-only mode,
// or fallback to write mode if the database is not initialized. // or fallback to write mode if the database is not initialized.
//
//nolint:unused
func tryMakeReadOnlyDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { func tryMakeReadOnlyDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
// If datadir doesn't exist we need to open db in write-mode // If datadir doesn't exist we need to open db in write-mode
// so database engine can create files. // so database engine can create files.
@@ -2399,8 +2331,10 @@ func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error)
func MakeGenesis(ctx *cli.Context) *core.Genesis { func MakeGenesis(ctx *cli.Context) *core.Genesis {
var genesis *core.Genesis var genesis *core.Genesis
switch { switch {
case ctx.Bool(MainnetFlag.Name): case ctx.Bool(BSCMainnetFlag.Name):
genesis = core.DefaultGenesisBlock() genesis = core.DefaultBSCGenesisBlock()
case ctx.Bool(ChapelFlag.Name):
genesis = core.DefaultChapelGenesisBlock()
case ctx.Bool(DeveloperFlag.Name): case ctx.Bool(DeveloperFlag.Name):
Fatalf("Developer chains are ephemeral") Fatalf("Developer chains are ephemeral")
} }
@@ -2424,7 +2358,11 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
} }
scheme, err := ParseStateScheme(ctx, chainDb) provided, err := CompareStateSchemeCLIWithConfig(ctx)
if err != nil {
Fatalf("%v", err)
}
scheme, err := rawdb.ParseStateScheme(provided, chainDb)
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
@@ -2487,47 +2425,16 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
return preloads 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. // MakeTrieDatabase constructs a trie database based on the configured scheme.
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool) *trie.Database { func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool) *trie.Database {
config := &trie.Config{ config := &trie.Config{
Preimages: preimage, Preimages: preimage,
} }
scheme, err := ParseStateScheme(ctx, disk) provided, err := CompareStateSchemeCLIWithConfig(ctx)
if err != nil {
Fatalf("%v", err)
}
scheme, err := rawdb.ParseStateScheme(provided, disk)
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
@@ -2545,3 +2452,66 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
} }
return trie.NewDatabase(disk, config) return trie.NewDatabase(disk, config)
} }
// CompareStateSchemeCLIWithConfig compare state scheme in CLI with config whether are equal.
func CompareStateSchemeCLIWithConfig(ctx *cli.Context) (string, error) {
var (
cfgScheme string
err error
)
if file := ctx.String("config"); file != "" {
// we don't validate cfgScheme because it's already checked in cmd/geth/loadBaseConfig
if cfgScheme, err = scanConfigForStateScheme(file); err != nil {
log.Error("Failed to parse config file", "error", err)
return "", err
}
}
if !ctx.IsSet(StateSchemeFlag.Name) {
if cfgScheme != "" {
log.Info("Use config state scheme", "config", cfgScheme)
}
return cfgScheme, nil
}
cliScheme := ctx.String(StateSchemeFlag.Name)
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)
}
func scanConfigForStateScheme(file string) (string, error) {
f, err := os.Open(file)
if err != nil {
return "", err
}
defer f.Close()
scanner := bufio.NewScanner(f)
targetStr := "StateScheme"
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, targetStr) {
return indexStateScheme(line), nil
}
}
if err = scanner.Err(); err != nil {
return "", err
}
return "", nil
}
func indexStateScheme(str string) string {
i1 := strings.Index(str, "\"")
i2 := strings.LastIndex(str, "\"")
if i1 != -1 && i2 != -1 && i1 < i2 {
return str[i1+1 : i2]
}
return ""
}

View File

@@ -39,6 +39,12 @@ var DeprecatedFlags = []cli.Flag{
CacheTrieRejournalFlag, CacheTrieRejournalFlag,
LegacyDiscoveryV5Flag, LegacyDiscoveryV5Flag,
TxLookupLimitFlag, TxLookupLimitFlag,
LightServeFlag,
LightIngressFlag,
LightEgressFlag,
LightMaxPeersFlag,
LightNoPruneFlag,
LightNoSyncServeFlag,
} }
var ( var (
@@ -77,6 +83,41 @@ var (
Value: ethconfig.Defaults.TransactionHistory, Value: ethconfig.Defaults.TransactionHistory,
Category: flags.DeprecatedCategory, 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. // showDeprecated displays deprecated flags that will be soon removed from the codebase.

View File

@@ -18,8 +18,13 @@
package utils package utils
import ( import (
"os"
"reflect" "reflect"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/ethereum/go-ethereum/core/rawdb"
) )
func Test_SplitTagsFlag(t *testing.T) { func Test_SplitTagsFlag(t *testing.T) {
@@ -62,3 +67,126 @@ func Test_SplitTagsFlag(t *testing.T) {
}) })
} }
} }
func Test_parseConfig(t *testing.T) {
tests := []struct {
name string
fn func() string
wantedResult string
wantedIsErr bool
wantedErrStr string
}{
{
name: "path",
fn: func() string {
tomlString := `[Eth]NetworkId = 56StateScheme = "path"`
return createTempTomlFile(t, tomlString)
},
wantedResult: rawdb.PathScheme,
wantedIsErr: false,
wantedErrStr: "",
},
{
name: "hash",
fn: func() string {
tomlString := `[Eth]NetworkId = 56StateScheme = "hash"`
return createTempTomlFile(t, tomlString)
},
wantedResult: rawdb.HashScheme,
wantedIsErr: false,
wantedErrStr: "",
},
{
name: "empty state scheme",
fn: func() string {
tomlString := `[Eth]NetworkId = 56StateScheme = ""`
return createTempTomlFile(t, tomlString)
},
wantedResult: "",
wantedIsErr: false,
wantedErrStr: "",
},
{
name: "unset state scheme",
fn: func() string {
tomlString := `[Eth]NetworkId = 56`
return createTempTomlFile(t, tomlString)
},
wantedResult: "",
wantedIsErr: false,
wantedErrStr: "",
},
{
name: "failed to open file",
fn: func() string { return "" },
wantedResult: "",
wantedIsErr: true,
wantedErrStr: "open : no such file or directory",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := scanConfigForStateScheme(tt.fn())
if tt.wantedIsErr {
assert.Contains(t, err.Error(), tt.wantedErrStr)
} else {
assert.Nil(t, err)
}
assert.Equal(t, tt.wantedResult, result)
})
}
}
// createTempTomlFile is a helper function to create a temp file with the provided TOML content
func createTempTomlFile(t *testing.T, content string) string {
t.Helper()
dir := t.TempDir()
file, err := os.CreateTemp(dir, "config.toml")
if err != nil {
t.Fatalf("Unable to create temporary file: %v", err)
}
defer file.Close()
_, err = file.WriteString(content)
if err != nil {
t.Fatalf("Unable to write to temporary file: %v", err)
}
return file.Name()
}
func Test_parseString(t *testing.T) {
tests := []struct {
name string
arg string
wantResult string
}{
{
name: "hash string",
arg: "\"hash\"",
wantResult: rawdb.HashScheme,
},
{
name: "path string",
arg: "\"path\"",
wantResult: rawdb.PathScheme,
},
{
name: "empty string",
arg: "",
wantResult: "",
},
{
name: "empty string",
arg: "\"\"",
wantResult: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := indexStateScheme(tt.arg); got != tt.wantResult {
t.Errorf("parseString() = %v, want %v", got, tt.wantResult)
}
})
}
}

View File

@@ -44,6 +44,12 @@ const (
var ( var (
hashT = reflect.TypeOf(Hash{}) hashT = reflect.TypeOf(Hash{})
addressT = reflect.TypeOf(Address{}) 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. // Hash represents the 32 byte Keccak256 hash of arbitrary data.

View File

@@ -150,7 +150,7 @@ type PoSA interface {
IsSystemContract(to *common.Address) bool IsSystemContract(to *common.Address) bool
EnoughDistance(chain ChainReader, header *types.Header) bool EnoughDistance(chain ChainReader, header *types.Header) bool
IsLocalBlock(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 GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool

View File

@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math" "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/core/types"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@@ -31,6 +32,16 @@ import (
// - gas limit check // - gas limit check
// - basefee check // - basefee check
func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Header) error { 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 // Verify the header is not malformed
if header.BaseFee == nil { if header.BaseFee == nil {
return errors.New("header is missing baseFee") return errors.New("header is missing baseFee")

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,17 @@ import (
"github.com/ethereum/go-ethereum/rpc" "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 // initializeFeynmanContract initialize new contracts of Feynman fork
func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.Header, chain core.ChainContext, 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, txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
@@ -31,6 +42,7 @@ func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.H
systemcontracts.GovernorContract, systemcontracts.GovernorContract,
systemcontracts.GovTokenContract, systemcontracts.GovTokenContract,
systemcontracts.TimelockContract, systemcontracts.TimelockContract,
systemcontracts.TokenRecoverPortalContract,
} }
// get packed data // get packed data
data, err := p.stakeHubABI.Pack(method) data, err := p.stakeHubABI.Pack(method)

View File

@@ -94,6 +94,7 @@ var (
common.HexToAddress(systemcontracts.GovernorContract): true, common.HexToAddress(systemcontracts.GovernorContract): true,
common.HexToAddress(systemcontracts.GovTokenContract): true, common.HexToAddress(systemcontracts.GovTokenContract): true,
common.HexToAddress(systemcontracts.TimelockContract): true, common.HexToAddress(systemcontracts.TimelockContract): true,
common.HexToAddress(systemcontracts.TokenRecoverPortalContract): true,
} }
) )
@@ -245,6 +246,7 @@ func New(
) *Parlia { ) *Parlia {
// get parlia config // get parlia config
parliaConfig := chainConfig.Parlia parliaConfig := chainConfig.Parlia
log.Info("Parlia", "chainConfig", chainConfig)
// Set any missing consensus parameters to their defaults // Set any missing consensus parameters to their defaults
if parliaConfig != nil && parliaConfig.Epoch == 0 { if parliaConfig != nil && parliaConfig.Epoch == 0 {
@@ -455,7 +457,11 @@ func (p *Parlia) verifyVoteAttestation(chain consensus.ChainHeaderReader, header
// The source block should be the highest justified block. // The source block should be the highest justified block.
sourceNumber := attestation.Data.SourceNumber sourceNumber := attestation.Data.SourceNumber
sourceHash := attestation.Data.SourceHash 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 { if err != nil {
return fmt.Errorf("unexpected error when getting the highest justified number and hash") return fmt.Errorf("unexpected error when getting the highest justified number and hash")
} }
@@ -879,7 +885,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
// Prepare vote attestation // Prepare vote attestation
// Prepare vote data // Prepare vote data
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent) justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{parent})
if err != nil { if err != nil {
return fmt.Errorf("unexpected error when getting the highest justified number and hash") return fmt.Errorf("unexpected error when getting the highest justified number and hash")
} }
@@ -1121,6 +1127,22 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
cx := chainContext{Chain: chain, parlia: p} 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 // No block rewards in PoA, so the state remains as is and uncles are dropped
if header.Number.Cmp(common.Big1) == 0 { if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false) err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
@@ -1163,22 +1185,10 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
} }
} }
parent := chain.GetHeaderByHash(header.ParentHash)
if parent == nil {
return errors.New("parent not found")
}
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)
}
}
// update validators every day // update validators every day
if p.chainConfig.IsFeynman(header.Number, header.Time) { if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
// TODO: revert this // we should avoid update validators in the Feynman upgrade block
// if time.Unix(int64(parent.Time), 0).Day() < time.Unix(int64(header.Time), 0).Day() { if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
if time.Unix(int64(header.Time), 0).Minute() != time.Unix(int64(parent.Time), 0).Minute() {
if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil { if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil {
return err return err
} }
@@ -1203,6 +1213,23 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
if receipts == nil { if receipts == nil {
receipts = make([]*types.Receipt, 0) 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 { if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil { if err != nil {
@@ -1247,22 +1274,10 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
} }
} }
parent := chain.GetHeaderByHash(header.ParentHash)
if parent == nil {
return nil, nil, errors.New("parent not found")
}
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)
}
}
// update validators every day // update validators every day
if p.chainConfig.IsFeynman(header.Number, header.Time) { if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
// TODO: revert this // we should avoid update validators in the Feynman upgrade block
// if time.Unix(int64(parent.Time), 0).Day() < time.Unix(int64(header.Time), 0).Day() { if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
if time.Unix(int64(header.Time), 0).Minute() != time.Unix(int64(parent.Time), 0).Minute() {
if err := p.updateValidatorSetV2(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil { if err := p.updateValidatorSetV2(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -1319,7 +1334,7 @@ func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteE
return fmt.Errorf("target number mismatch") 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 { if err != nil {
log.Error("failed to get the highest justified number and hash", "headerNumber", header.Number, "headerHash", header.Hash()) 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") return fmt.Errorf("unexpected error when getting the highest justified number and hash")
@@ -1614,7 +1629,7 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNum *big.Int)
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, 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 { txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
coinbase := header.Coinbase coinbase := header.Coinbase
@@ -1704,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) 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, func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address,
state *state.StateDB, header *types.Header, chain core.ChainContext, state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
@@ -1799,24 +1814,25 @@ func (p *Parlia) applyTransaction(
receipt.BlockNumber = header.Number receipt.BlockNumber = header.Number
receipt.TransactionIndex = uint(state.TxIndex()) receipt.TransactionIndex = uint(state.TxIndex())
*receipts = append(*receipts, receipt) *receipts = append(*receipts, receipt)
state.SetNonce(msg.From(), nonce+1)
return nil return nil
} }
// GetJustifiedNumberAndHash returns the highest justified block's number and hash on the branch including and before `header` // GetJustifiedNumberAndHash retrieves the number and hash of the highest justified block
func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) { // within the branch including `headers` and utilizing the latest element as the head.
if chain == nil || header == nil { 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") 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 { if err != nil {
log.Error("Unexpected error when getting snapshot", 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 return 0, common.Hash{}, err
} }
if snap.Attestation == nil { 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") log.Debug("once one attestation generated, attestation of snap would not be nil forever basically")
} }
return 0, chain.GetHeaderByNumber(0).Hash(), nil return 0, chain.GetHeaderByNumber(0).Hash(), nil
@@ -1965,6 +1981,8 @@ func applyMessage(
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, state, chainConfig, vm.Config{}) 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) // 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( ret, returnGas, err := vmenv.Call(
vm.AccountRef(msg.From()), vm.AccountRef(msg.From()),
*msg.To(), *msg.To(),

View File

@@ -28,6 +28,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
mapset "github.com/deckarep/golang-set/v2"
exlru "github.com/hashicorp/golang-lru" exlru "github.com/hashicorp/golang-lru"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
@@ -41,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot" "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/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@@ -58,6 +60,10 @@ import (
) )
var ( var (
badBlockRecords = mapset.NewSet[common.Hash]()
badBlockRecordslimit = 1000
badBlockGauge = metrics.NewRegisteredGauge("chain/insert/badBlock", nil)
headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil) headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil)
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", 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 { if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr return nil, genesisErr
} }
systemcontracts.GenesisHash = genesisHash
log.Info("Initialised chain configuration", "config", chainConfig) log.Info("Initialised chain configuration", "config", chainConfig)
// Description of chainConfig is empty now // Description of chainConfig is empty now
/* /*
@@ -632,7 +639,7 @@ func (bc *BlockChain) empty() bool {
// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`. // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 { func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 {
if p, ok := bc.engine.(consensus.PoSA); ok { 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 { if err == nil {
return justifiedBlockNumber return justifiedBlockNumber
} }
@@ -1015,11 +1022,6 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
return nil 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. // Reset purges the entire blockchain, restoring it to its genesis state.
func (bc *BlockChain) Reset() error { func (bc *BlockChain) Reset() error {
return bc.ResetWithGenesisBlock(bc.genesisBlock) return bc.ResetWithGenesisBlock(bc.genesisBlock)
@@ -2918,15 +2920,22 @@ func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *pa
if vcs != "" { if vcs != "" {
vcs = fmt.Sprintf("\nVCS: %s", vcs) vcs = fmt.Sprintf("\nVCS: %s", vcs)
} }
if badBlockRecords.Cardinality() < badBlockRecordslimit {
badBlockRecords.Add(block.Hash())
badBlockGauge.Update(int64(badBlockRecords.Cardinality()))
}
return fmt.Sprintf(` return fmt.Sprintf(`
########## BAD BLOCK ######### ########## BAD BLOCK #########
Block: %v (%#x) Block: %v (%#x)
Miner: %v
Error: %v Error: %v
Platform: %v%v Platform: %v%v
Chain config: %#v Chain config: %#v
Receipts: %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 // InsertHeaderChain attempts to insert the given header chain in to the local

View File

@@ -71,7 +71,7 @@ func (bc *BlockChain) CurrentSafeBlock() *types.Header {
if currentHeader == nil { if currentHeader == nil {
return nil return nil
} }
_, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, currentHeader) _, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{currentHeader})
if err == nil { if err == nil {
return bc.GetHeaderByHash(justifiedBlockHash) return bc.GetHeaderByHash(justifiedBlockHash)
} }

View File

@@ -205,6 +205,10 @@ func (b *BlockGen) AddUncle(h *types.Header) {
h.GasLimit = parent.GasLimit h.GasLimit = parent.GasLimit
if b.config.IsLondon(h.Number) { if b.config.IsLondon(h.Number) {
h.BaseFee = eip1559.CalcBaseFee(b.config, parent) 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) 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 { if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 {
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
if !config.IsFeynman(b.header.Number, b.header.Time) {
systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb) systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb)
}
// Execute any user modifications to the block // Execute any user modifications to the block
if gen != nil { if gen != nil {
gen(i, b) gen(i, b)
@@ -386,6 +394,10 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
} }
if chain.Config().IsLondon(header.Number) { if chain.Config().IsLondon(header.Number) {
header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header()) 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 return header
} }

View File

@@ -23,8 +23,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"reflect"
"regexp"
"strings" "strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@@ -32,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "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/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@@ -66,8 +63,8 @@ type Genesis struct {
GasUsed uint64 `json:"gasUsed"` GasUsed uint64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"` ParentHash common.Hash `json:"parentHash"`
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559 BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty" toml:",omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork ExcessBlobGas *uint64 `json:"excessBlobGas,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 BlobGasUsed *uint64 `json:"blobGasUsed,omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
} }
func ReadGenesis(db ethdb.Database) (*Genesis, error) { func ReadGenesis(db ethdb.Database) (*Genesis, error) {
@@ -123,8 +120,8 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
return nil return nil
} }
// deriveHash computes the state root according to the genesis specification. // hash computes the state root according to the genesis specification.
func (ga *GenesisAlloc) deriveHash() (common.Hash, error) { func (ga *GenesisAlloc) hash() (common.Hash, error) {
// Create an ephemeral in-memory database for computing hash, // Create an ephemeral in-memory database for computing hash,
// all the derived states will be discarded to not pollute disk. // all the derived states will be discarded to not pollute disk.
db := state.NewDatabase(rawdb.NewMemoryDatabase()) db := state.NewDatabase(rawdb.NewMemoryDatabase())
@@ -145,9 +142,9 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
return root, err return root, err
} }
// flush is very similar with deriveHash, but the main difference is // flush is very similar with hash, but the main difference is all the generated
// all the generated states will be persisted into the given database. // states will be persisted into the given database. Also, the genesis state
// Also, the genesis state specification will be flushed as well. // specification will be flushed as well.
func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error { func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
trieConfig := triedb.Config() trieConfig := triedb.Config()
if trieConfig != nil { if trieConfig != nil {
@@ -202,8 +199,8 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash comm
// - private network, can't recover // - private network, can't recover
var genesis *Genesis var genesis *Genesis
switch blockhash { switch blockhash {
case params.MainnetGenesisHash: case params.BSCGenesisHash:
genesis = DefaultGenesisBlock() genesis = DefaultBSCGenesisBlock()
} }
if genesis != nil { if genesis != nil {
alloc = genesis.Alloc alloc = genesis.Alloc
@@ -276,10 +273,14 @@ func (e *GenesisMismatchError) Error() string {
return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New) 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 { type ChainOverrides struct {
OverrideShanghai *uint64
OverrideKepler *uint64
OverrideCancun *uint64 OverrideCancun *uint64
OverrideVerkle *uint64 OverrideVerkle *uint64
OverrideFeynman *uint64
} }
// SetupGenesisBlock writes or updates the genesis block in db. // SetupGenesisBlock writes or updates the genesis block in db.
@@ -305,21 +306,29 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
} }
applyOverrides := func(config *params.ChainConfig) { applyOverrides := func(config *params.ChainConfig) {
if config != nil { 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 { if overrides != nil && overrides.OverrideCancun != nil {
config.CancunTime = overrides.OverrideCancun config.CancunTime = overrides.OverrideCancun
} }
if overrides != nil && overrides.OverrideVerkle != nil { if overrides != nil && overrides.OverrideVerkle != nil {
config.VerkleTime = overrides.OverrideVerkle config.VerkleTime = overrides.OverrideVerkle
} }
if overrides != nil && overrides.OverrideFeynman != nil {
config.FeynmanTime = overrides.OverrideFeynman
}
} }
} }
// Just commit the new block if there is no stored genesis block. // Just commit the new block if there is no stored genesis block.
stored := rawdb.ReadCanonicalHash(db, 0) stored := rawdb.ReadCanonicalHash(db, 0)
systemcontracts.GenesisHash = stored
if (stored == common.Hash{}) { if (stored == common.Hash{}) {
if genesis == nil { if genesis == nil {
log.Info("Writing default main-net genesis block") log.Info("Writing default BSC mainnet genesis block")
genesis = DefaultGenesisBlock() genesis = DefaultBSCGenesisBlock()
} else { } else {
log.Info("Writing custom genesis block") log.Info("Writing custom genesis block")
} }
@@ -328,6 +337,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
return genesis.Config, common.Hash{}, err return genesis.Config, common.Hash{}, err
} }
applyOverrides(genesis.Config) applyOverrides(genesis.Config)
log.Info("genesis block hash", "hash", block.Hash())
return genesis.Config, block.Hash(), nil return genesis.Config, block.Hash(), nil
} }
// The genesis block is present(perhaps in ancient database) while the // The genesis block is present(perhaps in ancient database) while the
@@ -337,7 +347,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
header := rawdb.ReadHeader(db, stored, 0) header := rawdb.ReadHeader(db, stored, 0)
if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) { if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) {
if genesis == nil { if genesis == nil {
genesis = DefaultGenesisBlock() genesis = DefaultBSCGenesisBlock()
} }
// Ensure the stored genesis matches with the given one. // Ensure the stored genesis matches with the given one.
hash := genesis.ToBlock().Hash() hash := genesis.ToBlock().Hash()
@@ -398,14 +408,19 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
return newcfg, stored, nil return newcfg, stored, nil
} }
// LoadChainConfig loads the stored chain config if it is already present in // LoadChainConfig retrieves the predefined chain configuration for the built-in network.
// database, otherwise, return the config in the provided genesis specification. // 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) { func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
// Load the stored chain config from the database. It can be nil // Load the stored chain config from the database. It can be nil
// in case the database is empty. Notably, we only care about the // in case the database is empty. Notably, we only care about the
// chain config corresponds to the canonical chain. // chain config corresponds to the canonical chain.
stored := rawdb.ReadCanonicalHash(db, 0) stored := rawdb.ReadCanonicalHash(db, 0)
if stored != (common.Hash{}) { if stored != (common.Hash{}) {
builtInConf := params.GetBuiltInChainConfig(stored)
if builtInConf != nil {
return builtInConf, stored, nil
}
storedcfg := rawdb.ReadChainConfig(db, stored) storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg != nil { if storedcfg != nil {
return storedcfg, stored, nil return storedcfg, stored, nil
@@ -431,76 +446,20 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig,
return params.BSCChainConfig, params.BSCGenesisHash, nil 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 { func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
var defaultConfig *params.ChainConfig conf := params.GetBuiltInChainConfig(ghash)
switch { if conf != nil {
case ghash == params.MainnetGenesisHash: return conf
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 { if g != nil {
// it could be a custom config for QA test, just return return g.Config // it could be a custom config for QA test, just return
return g.Config
} }
defaultConfig = params.AllEthashProtocolChanges return params.AllEthashProtocolChanges
}
if g == nil || g.Config == nil {
return defaultConfig
}
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
} }
// ToBlock returns the genesis block according to genesis specification. // ToBlock returns the genesis block according to genesis specification.
func (g *Genesis) ToBlock() *types.Block { func (g *Genesis) ToBlock() *types.Block {
root, err := g.Alloc.deriveHash() root, err := g.Alloc.hash()
if err != nil { if err != nil {
panic(err) panic(err)
} }
@@ -608,6 +567,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. // DeveloperGenesisBlock returns the 'geth --dev' genesis block.
func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis { func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
// Override the default period to the user requested one // Override the default period to the user requested one
@@ -635,13 +626,34 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
} }
func decodePrealloc(data string) GenesisAlloc { 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 { if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil {
panic(err) panic(err)
} }
ga := make(GenesisAlloc, len(p)) ga := make(GenesisAlloc, len(p))
for _, account := range 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 return ga
} }

File diff suppressed because one or more lines are too long

View File

@@ -71,8 +71,8 @@ func testSetupGenesis(t *testing.T, scheme string) {
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil) return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
}, },
wantHash: params.MainnetGenesisHash, wantHash: params.BSCGenesisHash,
wantConfig: params.MainnetChainConfig, wantConfig: params.BSCChainConfig,
}, },
{ {
name: "mainnet block in DB, genesis == nil", 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}}}, {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}}}, {2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
} }
hash, _ = alloc.deriveHash() hash, _ = alloc.hash()
) )
blob, _ := json.Marshal(alloc) blob, _ := json.Marshal(alloc)
rawdb.WriteGenesisStateSpec(db, hash, blob) rawdb.WriteGenesisStateSpec(db, hash, blob)
@@ -241,12 +241,12 @@ func TestConfigOrDefault(t *testing.T) {
gHash := params.BSCGenesisHash gHash := params.BSCGenesisHash
config := defaultGenesis.configOrDefault(gHash) 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) 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 { if config.HomesteadBlock.Cmp(params.BSCChainConfig.HomesteadBlock) != 0 {
t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.MainnetChainConfig, config.HomesteadBlock) t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.BSCChainConfig, config.HomesteadBlock)
} }
if config.PlanckBlock == nil { if config.PlanckBlock == nil {
@@ -258,34 +258,6 @@ func TestConfigOrDefault(t *testing.T) {
} }
} }
func TestSetDefaultBlockValues(t *testing.T) {
genesis := &Genesis{Config: &params.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 { func newDbConfig(scheme string) *trie.Config {
if scheme == rawdb.HashScheme { if scheme == rawdb.HashScheme {
return trie.HashDefaults return trie.HashDefaults

View File

@@ -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`. // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 { func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 {
if p, ok := hc.engine.(consensus.PoSA); ok { 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 { if err == nil {
return justifiedBlockNumber return justifiedBlockNumber
} }

View File

@@ -32,24 +32,51 @@ import (
"os" "os"
"strconv" "strconv"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"golang.org/x/exp/slices" "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 { func makelist(g *core.Genesis) []allocItem {
items := make([]allocItem, 0, len(g.Alloc)) items := make([]allocItem, 0, len(g.Alloc))
for addr, account := range g.Alloc { for addr, account := range g.Alloc {
var misc *allocItemMisc
if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 { 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()) 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 { slices.SortFunc(items, func(a, b allocItem) int {
return a.Addr.Cmp(b.Addr) < 0 return a.Addr.Cmp(b.Addr)
}) })
return items return items
} }

View File

@@ -305,3 +305,47 @@ func ReadStateScheme(db ethdb.Reader) string {
} }
return HashScheme 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 schema 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)
}

View 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)
}
})
}
}

View File

@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/leveldb" "github.com/ethereum/go-ethereum/ethdb/leveldb"
"github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/ethdb/pebble"
"github.com/ethereum/go-ethereum/log" "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 // resolveChainFreezerDir is a helper function which resolves the absolute path
// of chain freezer by considering backward compatibility. // 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 { func resolveChainFreezerDir(ancient string) string {
// Check if the chain freezer is already present in the specified // Check if the chain freezer is already present in the specified
// sub folder, if not then two possibilities: // sub folder, if not then two possibilities:
// - chain freezer is not initialized // - chain freezer is not initialized
// - chain freezer exists in legacy location (root ancient folder) // - chain freezer exists in legacy location (root ancient folder)
freezer := path.Join(ancient, chainFreezerName) chain := path.Join(ancient, chainFreezerName)
if !common.FileExist(freezer) { state := path.Join(ancient, stateFreezerName)
if !common.FileExist(ancient) { if common.FileExist(chain) {
// The entire ancient store is not initialized, still use the sub return chain
// folder for initialization. }
} else { if common.FileExist(state) {
// Ancient root is already initialized, then we hold the assumption return chain
// that chain freezer is also initialized and located in root folder. }
// In this case fallback to legacy location. if common.FileExist(ancient) {
freezer = ancient
log.Info("Found legacy ancient chain path", "location", ancient) log.Info("Found legacy ancient chain path", "location", ancient)
chain = ancient
} }
} return chain
return freezer
} }
// NewDatabaseWithFreezer creates a high level database on top of a given key- // 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) WriteAncientType(db, PruneFreezerType)
} }
return &freezerdb{ return &freezerdb{
ancientRoot: ancient,
KeyValueStore: db, KeyValueStore: db,
AncientStore: frdb, AncientStore: frdb,
}, nil }, nil
@@ -335,7 +340,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
break 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) printChainMetadata(db)
return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ", return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
frozen-1, number, head) frozen-1, number, head)
@@ -364,7 +369,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
// freezer. // freezer.
} }
} }
// no prune ancinet start success // no prune ancient start success
if !readonly { if !readonly {
WriteAncientType(db, EntireFreezerType) WriteAncientType(db, EntireFreezerType)
} }
@@ -425,6 +430,16 @@ func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient
return frdb, nil 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 ( const (
dbPebble = "pebble" dbPebble = "pebble"
dbLeveldb = "leveldb" 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) 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 o.Type == dbPebble || existingDb == dbPebble {
if PebbleEnabled {
log.Info("Using pebble as the backing database") log.Info("Using pebble as the backing database")
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) 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")
}
} }
if o.Type == dbLeveldb || existingDb == dbLeveldb { if o.Type == dbLeveldb || existingDb == dbLeveldb {
log.Info("Using leveldb as the backing database") 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 // No pre-existing database, no user-requested one either. Default to Pebble
// on supported platforms and LevelDB on anything else. // on supported platforms and LevelDB on anything else.
// if PebbleEnabled {
// log.Info("Defaulting to pebble as the backing database") // log.Info("Defaulting to pebble as the backing database")
// return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) // return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
// }
log.Info("Defaulting to leveldb as the backing database") log.Info("Defaulting to leveldb as the backing database")
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) 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 { if err != nil {
return nil, err return nil, err
} }
if ReadAncientType(kvdb) == PruneFreezerType {
if !o.PruneAncientData {
log.Warn("Disk db is pruned")
}
}
if len(o.AncientsDirectory) == 0 { if len(o.AncientsDirectory) == 0 {
return kvdb, nil return kvdb, nil
} }
@@ -551,6 +565,7 @@ func (s *stat) Size() string {
func (s *stat) Count() string { func (s *stat) Count() string {
return s.count.String() return s.count.String()
} }
func AncientInspect(db ethdb.Database) error { func AncientInspect(db ethdb.Database) error {
offset := counter(ReadOffSetOfCurrentAncientFreezer(db)) offset := counter(ReadOffSetOfCurrentAncientFreezer(db))
// Get number of ancient rows inside the freezer. // Get number of ancient rows inside the freezer.

View File

@@ -15,3 +15,80 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb 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)
}
})
}
}

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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 // 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.frozen.Add(offset)
freezer.tail.Add(offset) freezer.tail.Add(offset)

View File

@@ -22,6 +22,7 @@ import (
"sync" "sync"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
) )
const tmpSuffix = ".tmp" const tmpSuffix = ".tmp"
@@ -240,6 +241,7 @@ func cleanup(path string) error {
} }
for _, name := range names { for _, name := range names {
if name == filepath.Base(path)+tmpSuffix { if name == filepath.Base(path)+tmpSuffix {
log.Info("Removed leftover freezer directory", "name", name)
return os.RemoveAll(filepath.Join(parent, name)) return os.RemoveAll(filepath.Join(parent, name))
} }
} }

View File

@@ -265,6 +265,12 @@ func (t *freezerTable) repair() error {
t.index.ReadAt(buffer, offsetsSize-indexEntrySize) t.index.ReadAt(buffer, offsetsSize-indexEntrySize)
lastIndex.unmarshalBinary(buffer) 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, "items", offsetsSize%indexEntrySize-1)
}
if t.readonly { if t.readonly {
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly) t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
} else { } else {
@@ -357,7 +363,7 @@ func (t *freezerTable) repair() error {
return err return err
} }
if verbose { 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 { } else {
t.logger.Debug("Chain freezer table opened", "items", t.items.Load(), "size", common.StorageSize(t.headBytes)) t.logger.Debug("Chain freezer table opened", "items", t.items.Load(), "size", common.StorageSize(t.headBytes))
} }
@@ -530,6 +536,10 @@ func (t *freezerTable) truncateTail(items uint64) error {
if err := t.meta.Sync(); err != nil { if err := t.meta.Sync(); err != nil {
return err 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. // 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 { err = copyFrom(t.index.Name(), t.index.Name(), indexEntrySize*(newDeleted-deleted+1), func(f *os.File) error {
tailIndex := indexEntry{ tailIndex := indexEntry{
@@ -543,13 +553,14 @@ func (t *freezerTable) truncateTail(items uint64) error {
return err return err
} }
// Reopen the modified index file to load the changes // 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()) t.index, err = openFreezerFileForAppend(t.index.Name())
if err != nil { if err != nil {
return err 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 // Release any files before the current tail
t.tailId = newTailId t.tailId = newTailId
t.itemOffset.Store(newDeleted) t.itemOffset.Store(newDeleted)
@@ -782,7 +793,7 @@ func (t *freezerTable) retrieveItems(start, count, maxBytes uint64) ([]byte, []i
return fmt.Errorf("missing data file %d", fileId) return fmt.Errorf("missing data file %d", fileId)
} }
if _, err := dataFile.ReadAt(output[len(output)-length:], int64(start)); err != nil { 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 return nil
} }

View File

@@ -57,7 +57,7 @@ func newPrunedFreezer(datadir string, db ethdb.KeyValueStore, offset uint64) (*p
// delete ancient dir // delete ancient dir
if err := os.RemoveAll(datadir); err != nil && !os.IsNotExist(err) { 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 return nil, err
} }
log.Info("Opened ancientdb with nodata mode", "database", datadir, "frozen", freezer.frozen) log.Info("Opened ancientdb with nodata mode", "database", datadir, "frozen", freezer.frozen)

View File

@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "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/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@@ -37,6 +38,7 @@ type DumpConfig struct {
OnlyWithAddresses bool OnlyWithAddresses bool
Start []byte Start []byte
Max uint64 Max uint64
StateScheme string
} }
// DumpCollector interface which the state trie calls during iteration // DumpCollector interface which the state trie calls during iteration
@@ -57,7 +59,6 @@ type DumpAccount struct {
Storage map[common.Hash]string `json:"storage,omitempty"` Storage map[common.Hash]string `json:"storage,omitempty"`
Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode 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 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. // 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 { if !conf.SkipStorage {
account.Storage = make(map[common.Hash]string) 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 { if err != nil {
log.Error("Failed to load storage trie", "err", err) log.Error("Failed to load storage trie", "err", err)
continue continue

View File

@@ -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 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 { 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") 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 var oldOffSet uint64

View File

@@ -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) { 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 { 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) rawdb.WriteTrieNode(db, owner, path, hash, blob, scheme)
})
} }
} t := trie.NewStackTrie(options)
t := trie.NewStackTrieWithOwner(nodeWriter, owner)
for leaf := range in { for leaf := range in {
t.Update(leaf.key[:], leaf.value) t.Update(leaf.key[:], leaf.value)
} }
var root common.Hash out <- t.Commit()
if db == nil {
root = t.Hash()
} else {
root, _ = t.Commit()
}
out <- root
} }

View File

@@ -1363,10 +1363,12 @@ func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (boo
nodes = trienode.NewNodeSet(addrHash) nodes = trienode.NewNodeSet(addrHash)
slots = make(map[common.Hash][]byte) 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()) nodes.AddNode(path, trienode.NewDeleted())
size += common.StorageSize(len(path)) size += common.StorageSize(len(path))
}) })
stack := trie.NewStackTrie(options)
for iter.Next() { for iter.Next() {
if size > storageDeleteLimit { if size > storageDeleteLimit {
return true, size, nil, nil, nil return true, size, nil, nil, nil

View File

@@ -73,12 +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 { if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
// Handle upgrade build-in system contract code
lastBlock := p.bc.GetBlockByHash(block.ParentHash()) lastBlock := p.bc.GetBlockByHash(block.ParentHash())
if lastBlock == nil { if lastBlock == nil {
return statedb, nil, nil, 0, fmt.Errorf("could not get parent block") 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) systemcontracts.UpgradeBuildInSystemContract(p.config, blockNumber, lastBlock.Time(), block.Time(), statedb)
}
var ( var (
context = NewEVMBlockContext(header, p.bc, nil) context = NewEVMBlockContext(header, p.bc, nil)

View File

@@ -138,7 +138,7 @@ func TestStateProcessorErrors(t *testing.T) {
) )
defer blockchain.Stop() 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 := new(big.Int).Set(bigNumber)
tooBigNumber.Add(tooBigNumber, common.Big1) tooBigNumber.Add(tooBigNumber, common.Big1)
for i, tt := range []struct { for i, tt := range []struct {

File diff suppressed because one or more lines are too long

View File

@@ -57,10 +57,6 @@ const (
) )
var ( 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 // ErrTxPoolOverflow is returned if the transaction pool is full and can't accept
// another remote transaction. // another remote transaction.
ErrTxPoolOverflow = errors.New("txpool is full") 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 { if pool.all.Get(hash) != nil {
log.Trace("Discarding already known transaction", "hash", hash) log.Trace("Discarding already known transaction", "hash", hash)
knownTxMeter.Mark(1) 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 // 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. // the sender is marked as local previously, treat it as the local transaction.
@@ -1038,7 +1034,7 @@ func (pool *LegacyPool) addTxs(txs []*types.Transaction, local, sync bool) []err
for i, tx := range txs { for i, tx := range txs {
// If the transaction is known, pre-set the error slot // If the transaction is known, pre-set the error slot
if pool.all.Get(tx.Hash()) != nil { if pool.all.Get(tx.Hash()) != nil {
errs[i] = ErrAlreadyKnown errs[i] = txpool.ErrAlreadyKnown
knownTxMeter.Mark(1) knownTxMeter.Mark(1)
continue continue
} }

View File

@@ -222,6 +222,8 @@ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{}, common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
common.BytesToAddress([]byte{102}): &blsSignatureVerify{}, common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{}, common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{},
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
} }
// PrecompiledContractsFeynman contains the default set of pre-compiled Ethereum // PrecompiledContractsFeynman contains the default set of pre-compiled Ethereum
@@ -231,7 +233,7 @@ var PrecompiledContractsFeynman = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{},
common.BytesToAddress([]byte{4}): &dataCopy{}, common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{}, common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
@@ -240,7 +242,7 @@ var PrecompiledContractsFeynman = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{100}): &tmHeaderValidate{}, common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{}, common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
common.BytesToAddress([]byte{102}): &blsSignatureVerify{}, common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{}, common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidateHertz{},
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{}, common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{}, common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
} }
@@ -316,10 +318,10 @@ func init() {
// ActivePrecompiles returns the precompiles enabled with the current configuration. // ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules params.Rules) []common.Address { func ActivePrecompiles(rules params.Rules) []common.Address {
switch { switch {
case rules.IsFeynman:
return PrecompiledAddressesFeynman
case rules.IsCancun: case rules.IsCancun:
return PrecompiledAddressesCancun return PrecompiledAddressesCancun
case rules.IsFeynman:
return PrecompiledAddressesFeynman
case rules.IsHertz: case rules.IsHertz:
return PrecompiledAddressesHertz return PrecompiledAddressesHertz
case rules.IsPlato: case rules.IsPlato:
@@ -1396,19 +1398,23 @@ func (c *verifyDoubleSignEvidence) RequiredGas(input []byte) uint64 {
return params.DoubleSignEvidenceVerifyGas return params.DoubleSignEvidenceVerifyGas
} }
var (
extraSeal = 65
)
type DoubleSignEvidence struct { type DoubleSignEvidence struct {
ChainId *big.Int ChainId *big.Int
HeaderBytes1 []byte HeaderBytes1 []byte
HeaderBytes2 []byte HeaderBytes2 []byte
} }
const (
extraSeal = 65
)
var (
errInvalidEvidence = errors.New("invalid double sign evidence")
)
// Run input: rlp encoded DoubleSignEvidence // Run input: rlp encoded DoubleSignEvidence
// return: // return:
// signer address| evidence time| // signer address| evidence height|
// 20 bytes | 32 bytes | // 20 bytes | 32 bytes |
func (c *verifyDoubleSignEvidence) Run(input []byte) ([]byte, error) { func (c *verifyDoubleSignEvidence) Run(input []byte) ([]byte, error) {
evidence := &DoubleSignEvidence{} evidence := &DoubleSignEvidence{}
@@ -1430,31 +1436,30 @@ func (c *verifyDoubleSignEvidence) Run(input []byte) ([]byte, error) {
} }
// basic check // basic check
if header1.Number.Uint64() != header2.Number.Uint64() { if len(header1.Number.Bytes()) > 32 || len(header2.Number.Bytes()) > 32 { // block number should be less than 2^256
return nil, ErrExecutionReverted return nil, errInvalidEvidence
}
if header1.Number.Cmp(header2.Number) != 0 {
return nil, errInvalidEvidence
} }
if header1.ParentHash != header2.ParentHash { if header1.ParentHash != header2.ParentHash {
return nil, ErrExecutionReverted return nil, errInvalidEvidence
} }
if len(header1.Extra) < extraSeal || len(header2.Extra) < extraSeal { if len(header1.Extra) < extraSeal || len(header2.Extra) < extraSeal {
return nil, ErrExecutionReverted return nil, errInvalidEvidence
} }
sig1 := header1.Extra[len(header1.Extra)-extraSeal:] sig1 := header1.Extra[len(header1.Extra)-extraSeal:]
sig2 := header2.Extra[len(header2.Extra)-extraSeal:] sig2 := header2.Extra[len(header2.Extra)-extraSeal:]
if bytes.Equal(sig1, sig2) { if bytes.Equal(sig1, sig2) {
return nil, ErrExecutionReverted return nil, errInvalidEvidence
}
evidenceTime := header1.Time
if evidenceTime < header2.Time {
evidenceTime = header2.Time
} }
// check sig // check sig
msgHash1 := types.SealHash(header1, evidence.ChainId) msgHash1 := types.SealHash(header1, evidence.ChainId)
msgHash2 := types.SealHash(header2, evidence.ChainId) msgHash2 := types.SealHash(header2, evidence.ChainId)
if bytes.Equal(msgHash1.Bytes(), msgHash2.Bytes()) { if bytes.Equal(msgHash1.Bytes(), msgHash2.Bytes()) {
return nil, ErrExecutionReverted return nil, errInvalidEvidence
} }
pubkey1, err := secp256k1.RecoverPubkey(msgHash1.Bytes(), sig1) pubkey1, err := secp256k1.RecoverPubkey(msgHash1.Bytes(), sig1)
if err != nil { if err != nil {
@@ -1465,14 +1470,14 @@ func (c *verifyDoubleSignEvidence) Run(input []byte) ([]byte, error) {
return nil, ErrExecutionReverted return nil, ErrExecutionReverted
} }
if !bytes.Equal(pubkey1, pubkey2) { if !bytes.Equal(pubkey1, pubkey2) {
return nil, ErrExecutionReverted return nil, errInvalidEvidence
} }
returnBz := make([]byte, 52) // 20 + 32 returnBz := make([]byte, 52) // 20 + 32
signerAddr := crypto.Keccak256(pubkey1[1:])[12:] signerAddr := crypto.Keccak256(pubkey1[1:])[12:]
evidenceTimeBz := big.NewInt(int64(evidenceTime)).Bytes() evidenceHeightBz := header1.Number.Bytes()
copy(returnBz[:20], signerAddr) copy(returnBz[:20], signerAddr)
copy(returnBz[52-len(evidenceTimeBz):], evidenceTimeBz) copy(returnBz[52-len(evidenceHeightBz):], evidenceHeightBz)
return returnBz, nil return returnBz, nil
} }

View File

@@ -408,23 +408,23 @@ func (c *secp256k1SignatureRecover) RequiredGas(input []byte) uint64 {
} }
const ( const (
tmPubKeyLength uint8 = 33 secp256k1PubKeyLength uint8 = 33
tmSignatureLength uint8 = 64 secp256k1SignatureLength uint8 = 64
tmSignatureMsgHashLength uint8 = 32 secp256k1SignatureMsgHashLength uint8 = 32
) )
// input: // input:
// | tmPubKey | tmSignature | tmSignatureMsgHash | // | PubKey | Signature | SignatureMsgHash |
// | 33 bytes | 64 bytes | 32 bytes | // | 33 bytes | 64 bytes | 32 bytes |
func (c *secp256k1SignatureRecover) Run(input []byte) (result []byte, err error) { func (c *secp256k1SignatureRecover) Run(input []byte) (result []byte, err error) {
if len(input) != int(tmPubKeyLength)+int(tmSignatureLength)+int(tmSignatureMsgHashLength) { if len(input) != int(secp256k1PubKeyLength)+int(secp256k1SignatureLength)+int(secp256k1SignatureMsgHashLength) {
return nil, fmt.Errorf("invalid input") return nil, fmt.Errorf("invalid input")
} }
return c.runTMSecp256k1Signature( return c.runTMSecp256k1Signature(
input[:tmPubKeyLength], input[:secp256k1PubKeyLength],
input[tmPubKeyLength:tmPubKeyLength+tmSignatureLength], input[secp256k1PubKeyLength:secp256k1PubKeyLength+secp256k1SignatureLength],
input[tmPubKeyLength+tmSignatureLength:], input[secp256k1PubKeyLength+secp256k1SignatureLength:],
) )
} }

View File

@@ -410,10 +410,20 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
func TestDoubleSignSlash(t *testing.T) { func TestDoubleSignSlash(t *testing.T) {
tc := precompiledTest{ tc := precompiledTest{
Input: "f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000", Input: "f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",
Expected: "15d34aaf54267db7d7c367839aaf71a00a2c6a65000000000000000000000000000000000000000000000000000000006555fa64", Expected: "15d34aaf54267db7d7c367839aaf71a00a2c6a650000000000000000000000000000000000000000000000000000000000000cdf",
Gas: 1000, Gas: 10000,
Name: "", Name: "",
} }
testPrecompiled("68", tc, t) testPrecompiled("68", tc, t)
} }
func TestDoubleSignSlashFailure(t *testing.T) {
tc := precompiledFailureTest{
Input: "f9066b38b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494df87f0e2b8519ea2dd4abd8b639cdd628497ed25a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b980988e1b9d0beb91dab063e04879a24c43d33baae3759dee41fd62ffa83c77fd202bea27a829b49e8025bdd198393526dd12b223ab16052fd26a43f3aabf63e76901a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094df87f0e2b8519ea2dd4abd8b639cdd628497ed25a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b9804c71ed015dd0c5c2d7393b68c2927f83f0a5da4c66f761f09e2f950cc610832c7876144599368404096ddef0eadacfde57717e2c7d23982b927285b797d41bfa00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",
ExpectedError: errInvalidEvidence.Error(),
Name: "",
}
testPrecompiledFailure("68", tc, t)
}

View File

@@ -48,10 +48,10 @@ type (
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
var precompiles map[common.Address]PrecompiledContract var precompiles map[common.Address]PrecompiledContract
switch { switch {
case evm.chainRules.IsFeynman:
precompiles = PrecompiledContractsFeynman
case evm.chainRules.IsCancun: case evm.chainRules.IsCancun:
precompiles = PrecompiledContractsCancun precompiles = PrecompiledContractsCancun
case evm.chainRules.IsFeynman:
precompiles = PrecompiledContractsFeynman
case evm.chainRules.IsHertz: case evm.chainRules.IsHertz:
precompiles = PrecompiledContractsHertz precompiles = PrecompiledContractsHertz
case evm.chainRules.IsPlato: case evm.chainRules.IsPlato:

View File

@@ -1,6 +1,6 @@
[ [
{ {
"Input": "01d18459b334ffe8e2226eef1db874fda6db2bdd9357268b39220af2d59464fb564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a1978a0d595c823c05947b1156175e72634a377808384256e9921ebf72181890be2d6b58d4a73a880541d1656875654806942307f266e636553e94006d11423f2688945ff3bdf515859eba1005c1a7708d620a94d91a1c0c285f9584e75ec2f82a", "Input": "01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a",
"Expected": "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", "Expected": "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
"Name": "pointEvaluation1", "Name": "pointEvaluation1",
"Gas": 50000, "Gas": 50000,

View File

@@ -15,6 +15,8 @@ import (
"github.com/ethereum/go-ethereum/metrics" "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) var votesManagerCounter = metrics.NewRegisteredCounter("votesManager/local", nil)
// Backend wraps all methods required for voting. // Backend wraps all methods required for voting.
@@ -95,6 +97,7 @@ func (voteManager *VoteManager) loop() {
dlEventCh := events.Chan() dlEventCh := events.Chan()
startVote := true startVote := true
blockCountSinceMining := 0
var once sync.Once var once sync.Once
for { for {
select { select {
@@ -120,9 +123,15 @@ func (voteManager *VoteManager) loop() {
continue continue
} }
if !voteManager.eth.IsMining() { if !voteManager.eth.IsMining() {
blockCountSinceMining = 0
log.Debug("skip voting because mining is disabled, continue") log.Debug("skip voting because mining is disabled, continue")
continue continue
} }
blockCountSinceMining++
if blockCountSinceMining <= blocksNumberSinceMining {
log.Debug("skip voting", "blockCountSinceMining", blockCountSinceMining, "blocksNumberSinceMining", blocksNumberSinceMining)
continue
}
if cHead.Block == nil { if cHead.Block == nil {
log.Debug("cHead.Block is nil, continue") 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) // A validator must not vote within the span of its other votes . (Rule 2)
// Validators always vote for their canonical chains latest block. (Rule 3) // Validators always vote for their canonical chains latest block. (Rule 3)
func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64, common.Hash) { 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 { 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()) 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{} return false, 0, common.Hash{}

View File

@@ -78,15 +78,15 @@ func newTestBackend() *testBackend {
func (b *testBackend) IsMining() bool { return true } func (b *testBackend) IsMining() bool { return true }
func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux } func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux }
func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) { func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
parentHeader := chain.GetHeaderByHash(header.ParentHash) parentHeader := chain.GetHeaderByHash(headers[len(headers)-1].ParentHash)
if parentHeader == nil { if parentHeader == nil {
return 0, common.Hash{}, fmt.Errorf("unexpected error") return 0, common.Hash{}, fmt.Errorf("unexpected error")
} }
return parentHeader.Number.Uint64(), parentHeader.Hash(), nil 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") 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 { if _, err := chain.InsertChain(bs); err != nil {
panic(err) 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) bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
if _, err := chain.InsertChain(bs); err != nil { if _, err := chain.InsertChain(bs); err != nil {
panic(err) panic(err)

View File

@@ -199,7 +199,7 @@ func FromECDSA(priv *ecdsa.PrivateKey) []byte {
// UnmarshalPubkey converts bytes to a secp256k1 public key. // UnmarshalPubkey converts bytes to a secp256k1 public key.
func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) { 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 { if x == nil {
return nil, errInvalidPubkey return nil, errInvalidPubkey
} }
@@ -210,7 +210,7 @@ func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
if pub == nil || pub.X == nil || pub.Y == nil { if pub == nil || pub.X == nil || pub.Y == nil {
return 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. // HexToECDSA parses a secp256k1 private key.

View File

@@ -95,7 +95,7 @@ func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
// Generate an elliptic curve public / private keypair. If params is nil, // Generate an elliptic curve public / private keypair. If params is nil,
// the recommended default parameters for the key will be chosen. // the recommended default parameters for the key will be chosen.
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { 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 { if err != nil {
return 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) 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)) ct = make([]byte, len(Rb)+len(em)+len(d))
copy(ct, Rb) copy(ct, Rb)
copy(ct[len(Rb):], em) 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 := new(PublicKey)
R.Curve = prv.PublicKey.Curve 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 { if R.X == nil {
return nil, ErrInvalidPublicKey return nil, ErrInvalidPublicKey
} }

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@ func generateKeyPair() (pubkey, privkey []byte) {
if err != nil { if err != nil {
panic(err) 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) privkey = make([]byte, 32)
blob := key.D.Bytes() blob := key.D.Bytes()

View File

@@ -41,7 +41,7 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
return nil, err 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 return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
} }

View File

@@ -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 RUN apk add --no-cache make cmake gcc musl-dev linux-headers git bash build-base libc-dev

View File

@@ -59,6 +59,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
if stateDb == nil { if stateDb == nil {
return state.Dump{}, errors.New("pending state is not available") return state.Dump{}, errors.New("pending state is not available")
} }
opts.StateScheme = stateDb.Database().TrieDB().Scheme()
return stateDb.RawDump(opts), nil return stateDb.RawDump(opts), nil
} }
var header *types.Header var header *types.Header
@@ -83,6 +84,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }
opts.StateScheme = stateDb.Database().TrieDB().Scheme()
return stateDb.RawDump(opts), nil return stateDb.RawDump(opts), nil
} }
@@ -188,6 +190,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
OnlyWithAddresses: !incompletes, OnlyWithAddresses: !incompletes,
Start: start, Start: start,
Max: uint64(maxResults), Max: uint64(maxResults),
StateScheme: stateDb.Database().TrieDB().Scheme(),
} }
if maxResults > AccountRangeMaxResults || maxResults <= 0 { if maxResults > AccountRangeMaxResults || maxResults <= 0 {
opts.Max = AccountRangeMaxResults opts.Max = AccountRangeMaxResults

View File

@@ -118,7 +118,7 @@ type Ethereum struct {
func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
// Ensure configuration values are compatible and sane // Ensure configuration values are compatible and sane
if config.SyncMode == downloader.LightSync { 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() { if !config.SyncMode.IsValid() {
return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 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) 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) 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 // Redistribute memory allocation from in-memory trie node garbage collection
// to other caches when an archive node is requested. // to other caches when an archive node is requested.
if config.StateScheme == rawdb.HashScheme && config.NoPruning && config.TrieDirtyCache > 0 { 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) log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024)
// Assemble the Ethereum object // Try to recover offline state pruning only in hash-based.
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
}
if config.StateScheme == rawdb.HashScheme { if config.StateScheme == rawdb.HashScheme {
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, config.TriesInMemory); err != nil { if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, config.TriesInMemory); err != nil {
log.Error("Failed to recover state", "error", err) log.Error("Failed to recover state", "error", err)
@@ -165,6 +171,28 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if err != nil { if err != nil {
return nil, err 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
}
eth := &Ethereum{ eth := &Ethereum{
config: config, config: config,
@@ -241,14 +269,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
peers := newPeerSet() peers := newPeerSet()
bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) 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...) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -403,7 +423,7 @@ func (s *Ethereum) APIs() []rpc.API {
Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux), Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux),
}, { }, {
Namespace: "eth", 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", Namespace: "admin",
Service: NewAdminAPI(s), Service: NewAdminAPI(s),

View File

@@ -645,7 +645,7 @@ func (q *queue) expire(peer string, pendPool map[string]*fetchRequest, taskQueue
// as there's no order of events that should lead to such expirations. // as there's no order of events that should lead to such expirations.
req := pendPool[peer] req := pendPool[peer]
if req == nil { if req == nil {
log.Error("Expired request does not exist", "peer", peer) log.Trace("Expired request does not exist", "peer", peer)
return 0 return 0
} }
delete(pendPool, peer) delete(pendPool, peer)

View File

@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/consensus/parlia" "github.com/ethereum/go-ethereum/consensus/parlia"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool/blobpool" "github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
@@ -48,22 +47,13 @@ var FullNodeGPO = gasprice.Config{
IgnorePrice: gasprice.DefaultIgnorePrice, IgnorePrice: gasprice.DefaultIgnorePrice,
} }
// LightClientGPO contains default gasprice oracle settings for light client. // Defaults contains default settings for use on the BSC main net.
var LightClientGPO = gasprice.Config{
Blocks: 2,
Percentile: 60,
MaxPrice: gasprice.DefaultMaxPrice,
IgnorePrice: gasprice.DefaultIgnorePrice,
}
// Defaults contains default settings for use on the Ethereum main net.
var Defaults = Config{ var Defaults = Config{
SyncMode: downloader.SnapSync, SyncMode: downloader.SnapSync,
NetworkId: 1, NetworkId: 56,
TxLookupLimit: 2350000, TxLookupLimit: 2350000,
TransactionHistory: 2350000, TransactionHistory: 2350000,
StateHistory: params.FullImmutabilityThreshold, StateHistory: params.FullImmutabilityThreshold,
StateScheme: rawdb.HashScheme,
LightPeers: 100, LightPeers: 100,
DatabaseCache: 512, DatabaseCache: 512,
TrieCleanCache: 154, TrieCleanCache: 154,
@@ -122,9 +112,13 @@ type Config struct {
TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved. StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved.
StateScheme string `toml:",omitempty"` // State scheme used to store ethereum state and merkle trie nodes on top
PathSyncFlush bool `toml:",omitempty"` // State scheme used to store ethereum state and merkle trie nodes on top PathSyncFlush bool `toml:",omitempty"` // State scheme used to store ethereum state and merkle trie nodes on top
// State scheme represents the scheme used to store ethereum states and trie
// nodes on top. It can be 'hash', 'path', or none which means use the scheme
// consistent with persistent state.
StateScheme string `toml:",omitempty"`
// RequiredBlocks is a set of block number -> hash mappings which must be in the // RequiredBlocks is a set of block number -> hash mappings which must be in the
// canonical chain of all remote peers. Setting the option makes geth verify the // canonical chain of all remote peers. Setting the option makes geth verify the
// presence of these blocks for every new peer connection. // presence of these blocks for every new peer connection.
@@ -192,11 +186,20 @@ type Config struct {
// send-transaction variants. The unit is ether. // send-transaction variants. The unit is ether.
RPCTxFeeCap float64 RPCTxFeeCap float64
// OverrideShanghai (TODO: remove after the fork)
OverrideShanghai *uint64 `toml:",omitempty"`
// OverrideKepler (TODO: remove after the fork)
OverrideKepler *uint64 `toml:",omitempty"`
// OverrideCancun (TODO: remove after the fork) // OverrideCancun (TODO: remove after the fork)
OverrideCancun *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"`
// OverrideVerkle (TODO: remove after the fork) // OverrideVerkle (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
// OverrideFeynman (TODO: remove after the fork)
OverrideFeynman *uint64 `toml:",omitempty"`
} }
// CreateConsensusEngine creates a consensus engine for the given chain config. // CreateConsensusEngine creates a consensus engine for the given chain config.

View File

@@ -36,6 +36,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
TransactionHistory uint64 `toml:",omitempty"` TransactionHistory uint64 `toml:",omitempty"`
StateHistory uint64 `toml:",omitempty"` StateHistory uint64 `toml:",omitempty"`
StateScheme string `toml:",omitempty"` StateScheme string `toml:",omitempty"`
PathSyncFlush bool `toml:",omitempty"`
RequiredBlocks map[uint64]common.Hash `toml:"-"` RequiredBlocks map[uint64]common.Hash `toml:"-"`
LightServ int `toml:",omitempty"` LightServ int `toml:",omitempty"`
LightIngress int `toml:",omitempty"` LightIngress int `toml:",omitempty"`
@@ -68,6 +69,8 @@ func (c Config) MarshalTOML() (interface{}, error) {
RPCGasCap uint64 RPCGasCap uint64
RPCEVMTimeout time.Duration RPCEVMTimeout time.Duration
RPCTxFeeCap float64 RPCTxFeeCap float64
OverrideShanghai *uint64 `toml:",omitempty"`
OverrideKepler *uint64 `toml:",omitempty"`
OverrideCancun *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
} }
@@ -91,6 +94,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.TransactionHistory = c.TransactionHistory enc.TransactionHistory = c.TransactionHistory
enc.StateHistory = c.StateHistory enc.StateHistory = c.StateHistory
enc.StateScheme = c.StateScheme enc.StateScheme = c.StateScheme
enc.PathSyncFlush = c.PathSyncFlush
enc.RequiredBlocks = c.RequiredBlocks enc.RequiredBlocks = c.RequiredBlocks
enc.LightServ = c.LightServ enc.LightServ = c.LightServ
enc.LightIngress = c.LightIngress enc.LightIngress = c.LightIngress
@@ -123,6 +127,8 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.RPCGasCap = c.RPCGasCap enc.RPCGasCap = c.RPCGasCap
enc.RPCEVMTimeout = c.RPCEVMTimeout enc.RPCEVMTimeout = c.RPCEVMTimeout
enc.RPCTxFeeCap = c.RPCTxFeeCap enc.RPCTxFeeCap = c.RPCTxFeeCap
enc.OverrideShanghai = c.OverrideShanghai
enc.OverrideKepler = c.OverrideKepler
enc.OverrideCancun = c.OverrideCancun enc.OverrideCancun = c.OverrideCancun
enc.OverrideVerkle = c.OverrideVerkle enc.OverrideVerkle = c.OverrideVerkle
return &enc, nil return &enc, nil
@@ -150,6 +156,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
TransactionHistory *uint64 `toml:",omitempty"` TransactionHistory *uint64 `toml:",omitempty"`
StateHistory *uint64 `toml:",omitempty"` StateHistory *uint64 `toml:",omitempty"`
StateScheme *string `toml:",omitempty"` StateScheme *string `toml:",omitempty"`
PathSyncFlush *bool `toml:",omitempty"`
RequiredBlocks map[uint64]common.Hash `toml:"-"` RequiredBlocks map[uint64]common.Hash `toml:"-"`
LightServ *int `toml:",omitempty"` LightServ *int `toml:",omitempty"`
LightIngress *int `toml:",omitempty"` LightIngress *int `toml:",omitempty"`
@@ -182,6 +189,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
RPCGasCap *uint64 RPCGasCap *uint64
RPCEVMTimeout *time.Duration RPCEVMTimeout *time.Duration
RPCTxFeeCap *float64 RPCTxFeeCap *float64
OverrideShanghai *uint64 `toml:",omitempty"`
OverrideKepler *uint64 `toml:",omitempty"`
OverrideCancun *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
} }
@@ -246,6 +255,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.StateScheme != nil { if dec.StateScheme != nil {
c.StateScheme = *dec.StateScheme c.StateScheme = *dec.StateScheme
} }
if dec.PathSyncFlush != nil {
c.PathSyncFlush = *dec.PathSyncFlush
}
if dec.RequiredBlocks != nil { if dec.RequiredBlocks != nil {
c.RequiredBlocks = dec.RequiredBlocks c.RequiredBlocks = dec.RequiredBlocks
} }
@@ -342,6 +354,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.RPCTxFeeCap != nil { if dec.RPCTxFeeCap != nil {
c.RPCTxFeeCap = *dec.RPCTxFeeCap c.RPCTxFeeCap = *dec.RPCTxFeeCap
} }
if dec.OverrideShanghai != nil {
c.OverrideShanghai = dec.OverrideShanghai
}
if dec.OverrideKepler != nil {
c.OverrideKepler = dec.OverrideKepler
}
if dec.OverrideCancun != nil { if dec.OverrideCancun != nil {
c.OverrideCancun = dec.OverrideCancun c.OverrideCancun = dec.OverrideCancun
} }

View File

@@ -24,9 +24,9 @@ import (
"sort" "sort"
"time" "time"
mapset "github.com/deckarep/golang-set/v2"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/gopool" "github.com/ethereum/go-ethereum/common/gopool"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@@ -54,6 +54,9 @@ const (
// re-request them. // re-request them.
maxTxUnderpricedSetSize = 32768 maxTxUnderpricedSetSize = 32768
// maxTxUnderpricedTimeout is the max time a transaction should be stuck in the underpriced set.
maxTxUnderpricedTimeout = int64(5 * time.Minute)
// txArriveTimeout is the time allowance before an announced transaction is // txArriveTimeout is the time allowance before an announced transaction is
// explicitly requested. // explicitly requested.
txArriveTimeout = 500 * time.Millisecond txArriveTimeout = 500 * time.Millisecond
@@ -149,7 +152,7 @@ type TxFetcher struct {
drop chan *txDrop drop chan *txDrop
quit chan struct{} quit chan struct{}
underpriced mapset.Set[common.Hash] // Transactions discarded as too cheap (don't re-fetch) underpriced *lru.Cache[common.Hash, int64] // Transactions discarded as too cheap (don't re-fetch)
// Stage 1: Waiting lists for newly discovered transactions that might be // Stage 1: Waiting lists for newly discovered transactions that might be
// broadcast without needing explicit request/reply round trips. // broadcast without needing explicit request/reply round trips.
@@ -203,7 +206,7 @@ func NewTxFetcherForTests(
fetching: make(map[common.Hash]string), fetching: make(map[common.Hash]string),
requests: make(map[string]*txRequest), requests: make(map[string]*txRequest),
alternates: make(map[common.Hash]map[string]struct{}), alternates: make(map[common.Hash]map[string]struct{}),
underpriced: mapset.NewSet[common.Hash](), underpriced: lru.NewCache[common.Hash, int64](maxTxUnderpricedSetSize),
hasTx: hasTx, hasTx: hasTx,
addTxs: addTxs, addTxs: addTxs,
fetchTxs: fetchTxs, fetchTxs: fetchTxs,
@@ -225,16 +228,15 @@ func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
// loop, so anything caught here is time saved internally. // loop, so anything caught here is time saved internally.
var ( var (
unknowns = make([]common.Hash, 0, len(hashes)) unknowns = make([]common.Hash, 0, len(hashes))
duplicate, underpriced int64 duplicate int64
underpriced int64
) )
for _, hash := range hashes { for _, hash := range hashes {
switch { switch {
case f.hasTx(hash): case f.hasTx(hash):
duplicate++ duplicate++
case f.isKnownUnderpriced(hash):
case f.underpriced.Contains(hash):
underpriced++ underpriced++
default: default:
unknowns = append(unknowns, hash) unknowns = append(unknowns, hash)
} }
@@ -246,10 +248,7 @@ func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
if len(unknowns) == 0 { if len(unknowns) == 0 {
return nil return nil
} }
announce := &txAnnounce{ announce := &txAnnounce{origin: peer, hashes: unknowns}
origin: peer,
hashes: unknowns,
}
select { select {
case f.notify <- announce: case f.notify <- announce:
return nil return nil
@@ -258,6 +257,16 @@ func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
} }
} }
// isKnownUnderpriced reports whether a transaction hash was recently found to be underpriced.
func (f *TxFetcher) isKnownUnderpriced(hash common.Hash) bool {
prevTime, ok := f.underpriced.Peek(hash)
if ok && prevTime+maxTxUnderpricedTimeout < time.Now().Unix() {
f.underpriced.Remove(hash)
return false
}
return ok
}
// Enqueue imports a batch of received transaction into the transaction pool // Enqueue imports a batch of received transaction into the transaction pool
// and the fetcher. This method may be called by both transaction broadcasts and // and the fetcher. This method may be called by both transaction broadcasts and
// direct request replies. The differentiation is important so the fetcher can // direct request replies. The differentiation is important so the fetcher can
@@ -305,10 +314,7 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
// Avoid re-request this transaction when we receive another // Avoid re-request this transaction when we receive another
// announcement. // announcement.
if errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced) { if errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced) {
for f.underpriced.Cardinality() >= maxTxUnderpricedSetSize { f.underpriced.Add(batch[j].Hash(), batch[j].Time().Unix())
f.underpriced.Pop()
}
f.underpriced.Add(batch[j].Hash())
} }
// Track a few interesting failure types // Track a few interesting failure types
switch { switch {

View File

@@ -1509,8 +1509,8 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
} }
case isUnderpriced: case isUnderpriced:
if fetcher.underpriced.Cardinality() != int(step) { if fetcher.underpriced.Len() != int(step) {
t.Errorf("step %d: underpriced set size mismatch: have %d, want %d", i, fetcher.underpriced.Cardinality(), step) t.Errorf("step %d: underpriced set size mismatch: have %d, want %d", i, fetcher.underpriced.Len(), step)
} }
default: default:

View File

@@ -64,10 +64,10 @@ type FilterAPI struct {
} }
// NewFilterAPI returns a new FilterAPI instance. // NewFilterAPI returns a new FilterAPI instance.
func NewFilterAPI(system *FilterSystem, lightMode bool, rangeLimit bool) *FilterAPI { func NewFilterAPI(system *FilterSystem, rangeLimit bool) *FilterAPI {
api := &FilterAPI{ api := &FilterAPI{
sys: system, sys: system,
events: NewEventSystem(system, lightMode), events: NewEventSystem(system),
filters: make(map[rpc.ID]*filter), filters: make(map[rpc.ID]*filter),
timeout: system.cfg.Timeout, timeout: system.cfg.Timeout,
rangeLimit: rangeLimit, rangeLimit: rangeLimit,

View File

@@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@@ -207,8 +206,6 @@ type subscription struct {
type EventSystem struct { type EventSystem struct {
backend Backend backend Backend
sys *FilterSystem sys *FilterSystem
lightMode bool
lastHead *types.Header
// Subscriptions // Subscriptions
txsSub event.Subscription // Subscription for new transaction event txsSub event.Subscription // Subscription for new transaction event
@@ -237,11 +234,10 @@ type EventSystem struct {
// //
// The returned manager has a loop that needs to be stopped with the Stop function // The returned manager has a loop that needs to be stopped with the Stop function
// or by stopping the given mux. // or by stopping the given mux.
func NewEventSystem(sys *FilterSystem, lightMode bool) *EventSystem { func NewEventSystem(sys *FilterSystem) *EventSystem {
m := &EventSystem{ m := &EventSystem{
sys: sys, sys: sys,
backend: sys.backend, backend: sys.backend,
lightMode: lightMode,
install: make(chan *subscription), install: make(chan *subscription),
uninstall: make(chan *subscription), uninstall: make(chan *subscription),
txsCh: make(chan core.NewTxsEvent, txChanSize), txsCh: make(chan core.NewTxsEvent, txChanSize),
@@ -523,21 +519,6 @@ func (es *EventSystem) handleChainEvent(filters filterIndex, ev core.ChainEvent)
for _, f := range filters[BlocksSubscription] { for _, f := range filters[BlocksSubscription] {
f.headers <- ev.Block.Header() f.headers <- ev.Block.Header()
} }
if es.lightMode && len(filters[LogsSubscription]) > 0 {
es.lightFilterNewHead(ev.Block.Header(), func(header *types.Header, remove bool) {
for _, f := range filters[LogsSubscription] {
if f.logsCrit.FromBlock != nil && header.Number.Cmp(f.logsCrit.FromBlock) < 0 {
continue
}
if f.logsCrit.ToBlock != nil && header.Number.Cmp(f.logsCrit.ToBlock) > 0 {
continue
}
if matchedLogs := es.lightFilterLogs(header, f.logsCrit.Addresses, f.logsCrit.Topics, remove); len(matchedLogs) > 0 {
f.logs <- matchedLogs
}
}
})
}
} }
func (es *EventSystem) handleFinalizedHeaderEvent(filters filterIndex, ev core.FinalizedHeaderEvent) { func (es *EventSystem) handleFinalizedHeaderEvent(filters filterIndex, ev core.FinalizedHeaderEvent) {
@@ -546,76 +527,6 @@ func (es *EventSystem) handleFinalizedHeaderEvent(filters filterIndex, ev core.F
} }
} }
func (es *EventSystem) lightFilterNewHead(newHeader *types.Header, callBack func(*types.Header, bool)) {
oldh := es.lastHead
es.lastHead = newHeader
if oldh == nil {
return
}
newh := newHeader
// find common ancestor, create list of rolled back and new block hashes
var oldHeaders, newHeaders []*types.Header
for oldh.Hash() != newh.Hash() {
if oldh.Number.Uint64() >= newh.Number.Uint64() {
oldHeaders = append(oldHeaders, oldh)
oldh = rawdb.ReadHeader(es.backend.ChainDb(), oldh.ParentHash, oldh.Number.Uint64()-1)
}
if oldh.Number.Uint64() < newh.Number.Uint64() {
newHeaders = append(newHeaders, newh)
newh = rawdb.ReadHeader(es.backend.ChainDb(), newh.ParentHash, newh.Number.Uint64()-1)
if newh == nil {
// happens when CHT syncing, nothing to do
newh = oldh
}
}
}
// roll back old blocks
for _, h := range oldHeaders {
callBack(h, true)
}
// check new blocks (array is in reverse order)
for i := len(newHeaders) - 1; i >= 0; i-- {
callBack(newHeaders[i], false)
}
}
// filter logs of a single header in light client mode
func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.Address, topics [][]common.Hash, remove bool) []*types.Log {
if !bloomFilter(header.Bloom, addresses, topics) {
return nil
}
// Get the logs of the block
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
cached, err := es.sys.cachedLogElem(ctx, header.Hash(), header.Number.Uint64())
if err != nil {
return nil
}
unfiltered := append([]*types.Log{}, cached.logs...)
for i, log := range unfiltered {
// Don't modify in-cache elements
logcopy := *log
logcopy.Removed = remove
// Swap copy in-place
unfiltered[i] = &logcopy
}
logs := filterLogs(unfiltered, nil, nil, addresses, topics)
// Txhash is already resolved
if len(logs) > 0 && logs[0].TxHash != (common.Hash{}) {
return logs
}
// Resolve txhash
body, err := es.sys.cachedGetBody(ctx, cached, header.Hash(), header.Number.Uint64())
if err != nil {
return nil
}
for _, log := range logs {
// logs are already copied, safe to modify
log.TxHash = body.Transactions[log.TxIndex].Hash()
}
return logs
}
// eventLoop (un)installs filters and processes mux events. // eventLoop (un)installs filters and processes mux events.
func (es *EventSystem) eventLoop() { func (es *EventSystem) eventLoop() {
// Ensure all subscriptions get cleaned up // Ensure all subscriptions get cleaned up

View File

@@ -34,7 +34,6 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
@@ -202,7 +201,7 @@ func TestBlockSubscription(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{}) backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
genesis = &core.Genesis{ genesis = &core.Genesis{
Config: params.TestChainConfig, Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee), BaseFee: big.NewInt(params.InitialBaseFee),
@@ -257,7 +256,7 @@ func TestPendingTxFilter(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{}) backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
transactions = []*types.Transaction{ transactions = []*types.Transaction{
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
@@ -313,7 +312,7 @@ func TestPendingTxFilterFullTx(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{}) backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
transactions = []*types.Transaction{ transactions = []*types.Transaction{
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
@@ -369,7 +368,7 @@ func TestLogFilterCreation(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{}) _, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
testCases = []struct { testCases = []struct {
crit FilterCriteria crit FilterCriteria
@@ -416,7 +415,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{}) _, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
) )
// different situations where log filter creation should fail. // different situations where log filter creation should fail.
@@ -438,7 +437,7 @@ func TestInvalidGetLogsRequest(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{}) _, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
) )
@@ -463,7 +462,7 @@ func TestLogFilter(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{}) backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111") firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111")
secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222") secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222")
@@ -577,7 +576,7 @@ func TestPendingLogsSubscription(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{}) backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111") firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111")
secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222") secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222")
@@ -751,143 +750,6 @@ func TestPendingLogsSubscription(t *testing.T) {
} }
} }
func TestLightFilterLogs(t *testing.T) {
t.Parallel()
var (
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, true, false)
signer = types.HomesteadSigner{}
firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111")
secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222")
thirdAddress = common.HexToAddress("0x3333333333333333333333333333333333333333")
notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999")
firstTopic = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
secondTopic = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
// posted twice, once as regular logs and once as pending logs.
allLogs = []*types.Log{
// Block 1
{Address: firstAddr, Topics: []common.Hash{}, Data: []byte{}, BlockNumber: 2, Index: 0},
// Block 2
{Address: firstAddr, Topics: []common.Hash{firstTopic}, Data: []byte{}, BlockNumber: 3, Index: 0},
{Address: secondAddr, Topics: []common.Hash{firstTopic}, Data: []byte{}, BlockNumber: 3, Index: 1},
{Address: thirdAddress, Topics: []common.Hash{secondTopic}, Data: []byte{}, BlockNumber: 3, Index: 2},
// Block 3
{Address: thirdAddress, Topics: []common.Hash{secondTopic}, Data: []byte{}, BlockNumber: 4, Index: 0},
}
testCases = []struct {
crit FilterCriteria
expected []*types.Log
id rpc.ID
}{
// match all
0: {FilterCriteria{}, allLogs, ""},
// match none due to no matching addresses
1: {FilterCriteria{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, ""},
// match logs based on addresses, ignore topics
2: {FilterCriteria{Addresses: []common.Address{firstAddr}}, allLogs[:2], ""},
// match logs based on addresses and topics
3: {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[3:5], ""},
// all logs with block num >= 3
4: {FilterCriteria{FromBlock: big.NewInt(3), ToBlock: big.NewInt(5)}, allLogs[1:], ""},
// all logs
5: {FilterCriteria{FromBlock: big.NewInt(0), ToBlock: big.NewInt(5)}, allLogs, ""},
// all logs with 1>= block num <=2 and topic secondTopic
6: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(3), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""},
}
key, _ = crypto.GenerateKey()
addr = crypto.PubkeyToAddress(key.PublicKey)
genesis = &core.Genesis{Config: params.TestChainConfig,
Alloc: core.GenesisAlloc{
addr: {Balance: big.NewInt(params.Ether)},
},
}
receipts = []*types.Receipt{{
Logs: []*types.Log{allLogs[0]},
}, {
Logs: []*types.Log{allLogs[1], allLogs[2], allLogs[3]},
}, {
Logs: []*types.Log{allLogs[4]},
}}
)
_, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 4, func(i int, b *core.BlockGen) {
if i == 0 {
return
}
receipts[i-1].Bloom = types.CreateBloom(types.Receipts{receipts[i-1]})
b.AddUncheckedReceipt(receipts[i-1])
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i - 1), To: &common.Address{}, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, key)
b.AddTx(tx)
})
for i, block := range blocks {
rawdb.WriteBlock(db, block)
rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
rawdb.WriteHeadBlockHash(db, block.Hash())
if i > 0 {
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), []*types.Receipt{receipts[i-1]})
}
}
// create all filters
for i := range testCases {
id, err := api.NewFilter(testCases[i].crit)
if err != nil {
t.Fatal(err)
}
testCases[i].id = id
}
// raise events
time.Sleep(1 * time.Second)
for _, block := range blocks {
backend.chainFeed.Send(core.ChainEvent{Block: block, Hash: common.Hash{}, Logs: allLogs})
}
for i, tt := range testCases {
var fetched []*types.Log
timeout := time.Now().Add(1 * time.Second)
for { // fetch all expected logs
results, err := api.GetFilterChanges(tt.id)
if err != nil {
t.Fatalf("Unable to fetch logs: %v", err)
}
fetched = append(fetched, results.([]*types.Log)...)
if len(fetched) >= len(tt.expected) {
break
}
// check timeout
if time.Now().After(timeout) {
break
}
time.Sleep(100 * time.Millisecond)
}
if len(fetched) != len(tt.expected) {
t.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
return
}
for l := range fetched {
if fetched[l].Removed {
t.Errorf("expected log not to be removed for log %d in case %d", l, i)
}
expected := *tt.expected[l]
blockNum := expected.BlockNumber - 1
expected.BlockHash = blocks[blockNum].Hash()
expected.TxHash = blocks[blockNum].Transactions()[0].Hash()
if !reflect.DeepEqual(fetched[l], &expected) {
t.Errorf("invalid log on index %d for case %d", l, i)
}
}
}
}
// TestPendingTxFilterDeadlock tests if the event loop hangs when pending // TestPendingTxFilterDeadlock tests if the event loop hangs when pending
// txes arrive at the same time that one of multiple filters is timing out. // txes arrive at the same time that one of multiple filters is timing out.
// Please refer to #22131 for more details. // Please refer to #22131 for more details.
@@ -898,7 +760,7 @@ func TestPendingTxFilterDeadlock(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{Timeout: timeout}) backend, sys = newTestFilterSystem(t, db, Config{Timeout: timeout})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
done = make(chan struct{}) done = make(chan struct{})
) )
@@ -969,7 +831,7 @@ func TestVoteSubscription(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{Timeout: 5 * time.Minute}) backend, sys = newTestFilterSystem(t, db, Config{Timeout: 5 * time.Minute})
api = NewFilterAPI(sys, false, false) api = NewFilterAPI(sys, false)
votes = []*types.VoteEnvelope{ votes = []*types.VoteEnvelope{
&types.VoteEnvelope{ &types.VoteEnvelope{
VoteAddress: types.BLSPublicKey{}, VoteAddress: types.BLSPublicKey{},

View File

@@ -381,8 +381,6 @@ func (h *handler) protoTracker() {
<-h.handlerDoneCh <-h.handlerDoneCh
} }
return return
case <-h.stopCh:
return
} }
} }
} }

View File

@@ -24,13 +24,13 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
) )
const ( const (
@@ -321,7 +321,7 @@ func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePac
it.Release() it.Release()
// Generate the Merkle proofs for the first and last account // Generate the Merkle proofs for the first and last account
proof := light.NewNodeSet() proof := trienode.NewProofSet()
if err := tr.Prove(req.Origin[:], proof); err != nil { if err := tr.Prove(req.Origin[:], proof); err != nil {
log.Warn("Failed to prove account range", "origin", req.Origin, "err", err) log.Warn("Failed to prove account range", "origin", req.Origin, "err", err)
return nil, nil return nil, nil
@@ -333,7 +333,7 @@ func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePac
} }
} }
var proofs [][]byte var proofs [][]byte
for _, blob := range proof.NodeList() { for _, blob := range proof.List() {
proofs = append(proofs, blob) proofs = append(proofs, blob)
} }
return accounts, proofs return accounts, proofs
@@ -367,7 +367,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
if len(req.Origin) > 0 { if len(req.Origin) > 0 {
origin, req.Origin = common.BytesToHash(req.Origin), nil origin, req.Origin = common.BytesToHash(req.Origin), nil
} }
var limit = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") var limit = common.MaxHash
if len(req.Limit) > 0 { if len(req.Limit) > 0 {
limit, req.Limit = common.BytesToHash(req.Limit), nil limit, req.Limit = common.BytesToHash(req.Limit), nil
} }
@@ -427,7 +427,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
if err != nil { if err != nil {
return nil, nil return nil, nil
} }
proof := light.NewNodeSet() proof := trienode.NewProofSet()
if err := stTrie.Prove(origin[:], proof); err != nil { if err := stTrie.Prove(origin[:], proof); err != nil {
log.Warn("Failed to prove storage range", "origin", req.Origin, "err", err) log.Warn("Failed to prove storage range", "origin", req.Origin, "err", err)
return nil, nil return nil, nil
@@ -438,7 +438,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
return nil, nil return nil, nil
} }
} }
for _, blob := range proof.NodeList() { for _, blob := range proof.List() {
proofs = append(proofs, blob) proofs = append(proofs, blob)
} }
// Proof terminates the reply as proofs are only added if a node // Proof terminates the reply as proofs are only added if a node

View File

@@ -26,4 +26,32 @@ var (
IngressRegistrationErrorMeter = metrics.NewRegisteredMeter(ingressRegistrationErrorName, nil) IngressRegistrationErrorMeter = metrics.NewRegisteredMeter(ingressRegistrationErrorName, nil)
EgressRegistrationErrorMeter = metrics.NewRegisteredMeter(egressRegistrationErrorName, nil) EgressRegistrationErrorMeter = metrics.NewRegisteredMeter(egressRegistrationErrorName, nil)
// deletionGauge is the metric to track how many trie node deletions
// are performed in total during the sync process.
deletionGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete", nil)
// lookupGauge is the metric to track how many trie node lookups are
// performed to determine if node needs to be deleted.
lookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/lookup", nil)
// boundaryAccountNodesGauge is the metric to track how many boundary trie
// nodes in account trie are met.
boundaryAccountNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/account", nil)
// boundaryAccountNodesGauge is the metric to track how many boundary trie
// nodes in storage tries are met.
boundaryStorageNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/storage", nil)
// smallStorageGauge is the metric to track how many storages are small enough
// to retrieved in one or two request.
smallStorageGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/small", nil)
// largeStorageGauge is the metric to track how many storages are large enough
// to retrieved concurrently.
largeStorageGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/large", nil)
// skipStorageHealingGauge is the metric to track how many storages are retrieved
// in multiple requests but healing is not necessary.
skipStorageHealingGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/noheal", nil)
) )

View File

@@ -67,7 +67,7 @@ func (r *hashRange) End() common.Hash {
// If the end overflows (non divisible range), return a shorter interval // If the end overflows (non divisible range), return a shorter interval
next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) next, overflow := new(uint256.Int).AddOverflow(r.current, r.step)
if overflow { if overflow {
return common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") return common.MaxHash
} }
return next.SubUint64(next, 1).Bytes32() return next.SubUint64(next, 1).Bytes32()
} }

View File

@@ -45,7 +45,7 @@ func TestHashRanges(t *testing.T) {
common.HexToHash("0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.HexToHash("0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
common.HexToHash("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.HexToHash("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
common.HexToHash("0xbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.HexToHash("0xbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.MaxHash,
}, },
}, },
// Split a divisible part of the hash range up into 2 chunks // Split a divisible part of the hash range up into 2 chunks
@@ -58,7 +58,7 @@ func TestHashRanges(t *testing.T) {
}, },
ends: []common.Hash{ ends: []common.Hash{
common.HexToHash("0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.HexToHash("0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.MaxHash,
}, },
}, },
// Split the entire hash range into a non divisible 3 chunks // Split the entire hash range into a non divisible 3 chunks
@@ -73,7 +73,7 @@ func TestHashRanges(t *testing.T) {
ends: []common.Hash{ ends: []common.Hash{
common.HexToHash("0x5555555555555555555555555555555555555555555555555555555555555555"), common.HexToHash("0x5555555555555555555555555555555555555555555555555555555555555555"),
common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"), common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"),
common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.MaxHash,
}, },
}, },
// Split a part of hash range into a non divisible 3 chunks // Split a part of hash range into a non divisible 3 chunks
@@ -88,7 +88,7 @@ func TestHashRanges(t *testing.T) {
ends: []common.Hash{ ends: []common.Hash{
common.HexToHash("0x6aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), common.HexToHash("0x6aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
common.HexToHash("0xb555555555555555555555555555555555555555555555555555555555555555"), common.HexToHash("0xb555555555555555555555555555555555555555555555555555555555555555"),
common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.MaxHash,
}, },
}, },
// Split a part of hash range into a non divisible 3 chunks, but with a // Split a part of hash range into a non divisible 3 chunks, but with a
@@ -108,7 +108,7 @@ func TestHashRanges(t *testing.T) {
ends: []common.Hash{ ends: []common.Hash{
common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5"), common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5"),
common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"), common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"),
common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.MaxHash,
}, },
}, },
} }

View File

@@ -38,11 +38,11 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/msgrate" "github.com/ethereum/go-ethereum/p2p/msgrate"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
@@ -717,6 +717,19 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
} }
} }
// cleanPath is used to remove the dangling nodes in the stackTrie.
func (s *Syncer) cleanPath(batch ethdb.Batch, owner common.Hash, path []byte) {
if owner == (common.Hash{}) && rawdb.ExistsAccountTrieNode(s.db, path) {
rawdb.DeleteAccountTrieNode(batch, path)
deletionGauge.Inc(1)
}
if owner != (common.Hash{}) && rawdb.ExistsStorageTrieNode(s.db, owner, path) {
rawdb.DeleteStorageTrieNode(batch, owner, path)
deletionGauge.Inc(1)
}
lookupGauge.Inc(1)
}
// loadSyncStatus retrieves a previously aborted sync status from the database, // loadSyncStatus retrieves a previously aborted sync status from the database,
// or generates a fresh one if none is available. // or generates a fresh one if none is available.
func (s *Syncer) loadSyncStatus() { func (s *Syncer) loadSyncStatus() {
@@ -739,9 +752,22 @@ func (s *Syncer) loadSyncStatus() {
s.accountBytes += common.StorageSize(len(key) + len(value)) s.accountBytes += common.StorageSize(len(key) + len(value))
}, },
} }
task.genTrie = trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { options := trie.NewStackTrieOptions()
rawdb.WriteTrieNode(task.genBatch, owner, path, hash, val, s.scheme) options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(task.genBatch, common.Hash{}, path, hash, blob, s.scheme)
}) })
if s.scheme == rawdb.PathScheme {
// Configure the dangling node cleaner and also filter out boundary nodes
// only in the context of the path scheme. Deletion is forbidden in the
// hash scheme, as it can disrupt state completeness.
options = options.WithCleaner(func(path []byte) {
s.cleanPath(task.genBatch, common.Hash{}, path)
})
// Skip the left boundary if it's not the first range.
// Skip the right boundary if it's not the last range.
options = options.WithSkipBoundary(task.Next != (common.Hash{}), task.Last != common.MaxHash, boundaryAccountNodesGauge)
}
task.genTrie = trie.NewStackTrie(options)
for accountHash, subtasks := range task.SubTasks { for accountHash, subtasks := range task.SubTasks {
for _, subtask := range subtasks { for _, subtask := range subtasks {
subtask := subtask // closure for subtask.genBatch in the stacktrie writer callback subtask := subtask // closure for subtask.genBatch in the stacktrie writer callback
@@ -752,9 +778,23 @@ func (s *Syncer) loadSyncStatus() {
s.storageBytes += common.StorageSize(len(key) + len(value)) s.storageBytes += common.StorageSize(len(key) + len(value))
}, },
} }
subtask.genTrie = trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { owner := accountHash // local assignment for stacktrie writer closure
rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, val, s.scheme) options := trie.NewStackTrieOptions()
}, accountHash) options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, blob, s.scheme)
})
if s.scheme == rawdb.PathScheme {
// Configure the dangling node cleaner and also filter out boundary nodes
// only in the context of the path scheme. Deletion is forbidden in the
// hash scheme, as it can disrupt state completeness.
options = options.WithCleaner(func(path []byte) {
s.cleanPath(subtask.genBatch, owner, path)
})
// Skip the left boundary if it's not the first range.
// Skip the right boundary if it's not the last range.
options = options.WithSkipBoundary(subtask.Next != common.Hash{}, subtask.Last != common.MaxHash, boundaryStorageNodesGauge)
}
subtask.genTrie = trie.NewStackTrie(options)
} }
} }
} }
@@ -798,7 +838,7 @@ func (s *Syncer) loadSyncStatus() {
last := common.BigToHash(new(big.Int).Add(next.Big(), step)) last := common.BigToHash(new(big.Int).Add(next.Big(), step))
if i == accountConcurrency-1 { if i == accountConcurrency-1 {
// Make sure we don't overflow if the step is not a proper divisor // Make sure we don't overflow if the step is not a proper divisor
last = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") last = common.MaxHash
} }
batch := ethdb.HookedBatch{ batch := ethdb.HookedBatch{
Batch: s.db.NewBatch(), Batch: s.db.NewBatch(),
@@ -806,14 +846,27 @@ func (s *Syncer) loadSyncStatus() {
s.accountBytes += common.StorageSize(len(key) + len(value)) s.accountBytes += common.StorageSize(len(key) + len(value))
}, },
} }
options := trie.NewStackTrieOptions()
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(batch, common.Hash{}, path, hash, blob, s.scheme)
})
if s.scheme == rawdb.PathScheme {
// Configure the dangling node cleaner and also filter out boundary nodes
// only in the context of the path scheme. Deletion is forbidden in the
// hash scheme, as it can disrupt state completeness.
options = options.WithCleaner(func(path []byte) {
s.cleanPath(batch, common.Hash{}, path)
})
// Skip the left boundary if it's not the first range.
// Skip the right boundary if it's not the last range.
options = options.WithSkipBoundary(next != common.Hash{}, last != common.MaxHash, boundaryAccountNodesGauge)
}
s.tasks = append(s.tasks, &accountTask{ s.tasks = append(s.tasks, &accountTask{
Next: next, Next: next,
Last: last, Last: last,
SubTasks: make(map[common.Hash][]*storageTask), SubTasks: make(map[common.Hash][]*storageTask),
genBatch: batch, genBatch: batch,
genTrie: trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { genTrie: trie.NewStackTrie(options),
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme)
}),
}) })
log.Debug("Created account sync task", "from", next, "last", last) log.Debug("Created account sync task", "from", next, "last", last)
next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1)) next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1))
@@ -1877,7 +1930,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
return return
} }
// Some accounts are incomplete, leave as is for the storage and contract // Some accounts are incomplete, leave as is for the storage and contract
// task assigners to pick up and fill. // task assigners to pick up and fill
} }
// processBytecodeResponse integrates an already validated bytecode response // processBytecodeResponse integrates an already validated bytecode response
@@ -1965,6 +2018,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
if res.subTask == nil && res.mainTask.needState[j] && (i < len(res.hashes)-1 || !res.cont) { if res.subTask == nil && res.mainTask.needState[j] && (i < len(res.hashes)-1 || !res.cont) {
res.mainTask.needState[j] = false res.mainTask.needState[j] = false
res.mainTask.pend-- res.mainTask.pend--
smallStorageGauge.Inc(1)
} }
// If the last contract was chunked, mark it as needing healing // If the last contract was chunked, mark it as needing healing
// to avoid writing it out to disk prematurely. // to avoid writing it out to disk prematurely.
@@ -2000,7 +2054,11 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
log.Debug("Chunked large contract", "initiators", len(keys), "tail", lastKey, "chunks", chunks) log.Debug("Chunked large contract", "initiators", len(keys), "tail", lastKey, "chunks", chunks)
} }
r := newHashRange(lastKey, chunks) r := newHashRange(lastKey, chunks)
if chunks == 1 {
smallStorageGauge.Inc(1)
} else {
largeStorageGauge.Inc(1)
}
// Our first task is the one that was just filled by this response. // Our first task is the one that was just filled by this response.
batch := ethdb.HookedBatch{ batch := ethdb.HookedBatch{
Batch: s.db.NewBatch(), Batch: s.db.NewBatch(),
@@ -2008,14 +2066,25 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
s.storageBytes += common.StorageSize(len(key) + len(value)) s.storageBytes += common.StorageSize(len(key) + len(value))
}, },
} }
owner := account // local assignment for stacktrie writer closure
options := trie.NewStackTrieOptions()
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme)
})
if s.scheme == rawdb.PathScheme {
options = options.WithCleaner(func(path []byte) {
s.cleanPath(batch, owner, path)
})
// Keep the left boundary as it's the first range.
// Skip the right boundary if it's not the last range.
options = options.WithSkipBoundary(false, r.End() != common.MaxHash, boundaryStorageNodesGauge)
}
tasks = append(tasks, &storageTask{ tasks = append(tasks, &storageTask{
Next: common.Hash{}, Next: common.Hash{},
Last: r.End(), Last: r.End(),
root: acc.Root, root: acc.Root,
genBatch: batch, genBatch: batch,
genTrie: trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { genTrie: trie.NewStackTrie(options),
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme)
}, account),
}) })
for r.Next() { for r.Next() {
batch := ethdb.HookedBatch{ batch := ethdb.HookedBatch{
@@ -2024,14 +2093,27 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
s.storageBytes += common.StorageSize(len(key) + len(value)) s.storageBytes += common.StorageSize(len(key) + len(value))
}, },
} }
options := trie.NewStackTrieOptions()
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme)
})
if s.scheme == rawdb.PathScheme {
// Configure the dangling node cleaner and also filter out boundary nodes
// only in the context of the path scheme. Deletion is forbidden in the
// hash scheme, as it can disrupt state completeness.
options = options.WithCleaner(func(path []byte) {
s.cleanPath(batch, owner, path)
})
// Skip the left boundary as it's not the first range
// Skip the right boundary if it's not the last range.
options = options.WithSkipBoundary(true, r.End() != common.MaxHash, boundaryStorageNodesGauge)
}
tasks = append(tasks, &storageTask{ tasks = append(tasks, &storageTask{
Next: r.Start(), Next: r.Start(),
Last: r.End(), Last: r.End(),
root: acc.Root, root: acc.Root,
genBatch: batch, genBatch: batch,
genTrie: trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { genTrie: trie.NewStackTrie(options),
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme)
}, account),
}) })
} }
for _, task := range tasks { for _, task := range tasks {
@@ -2076,9 +2158,23 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
slots += len(res.hashes[i]) slots += len(res.hashes[i])
if i < len(res.hashes)-1 || res.subTask == nil { if i < len(res.hashes)-1 || res.subTask == nil {
tr := trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { // no need to make local reassignment of account: this closure does not outlive the loop
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme) options := trie.NewStackTrieOptions()
}, account) options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(batch, account, path, hash, blob, s.scheme)
})
if s.scheme == rawdb.PathScheme {
// Configure the dangling node cleaner only in the context of the
// path scheme. Deletion is forbidden in the hash scheme, as it can
// disrupt state completeness.
//
// Notably, boundary nodes can be also kept because the whole storage
// trie is complete.
options = options.WithCleaner(func(path []byte) {
s.cleanPath(batch, account, path)
})
}
tr := trie.NewStackTrie(options)
for j := 0; j < len(res.hashes[i]); j++ { for j := 0; j < len(res.hashes[i]); j++ {
tr.Update(res.hashes[i][j][:], res.slots[i][j]) tr.Update(res.hashes[i][j][:], res.slots[i][j])
} }
@@ -2100,18 +2196,25 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
// Large contracts could have generated new trie nodes, flush them to disk // Large contracts could have generated new trie nodes, flush them to disk
if res.subTask != nil { if res.subTask != nil {
if res.subTask.done { if res.subTask.done {
if root, err := res.subTask.genTrie.Commit(); err != nil { root := res.subTask.genTrie.Commit()
log.Error("Failed to commit stack slots", "err", err) if err := res.subTask.genBatch.Write(); err != nil {
} else if root == res.subTask.root { log.Error("Failed to persist stack slots", "err", err)
// If the chunk's root is an overflown but full delivery, clear the heal request }
res.subTask.genBatch.Reset()
// If the chunk's root is an overflown but full delivery,
// clear the heal request.
accountHash := res.accounts[len(res.accounts)-1]
if root == res.subTask.root && rawdb.HasStorageTrieNode(s.db, accountHash, nil, root) {
for i, account := range res.mainTask.res.hashes { for i, account := range res.mainTask.res.hashes {
if account == res.accounts[len(res.accounts)-1] { if account == accountHash {
res.mainTask.needHeal[i] = false res.mainTask.needHeal[i] = false
skipStorageHealingGauge.Inc(1)
} }
} }
} }
} }
if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize || res.subTask.done { if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize {
if err := res.subTask.genBatch.Write(); err != nil { if err := res.subTask.genBatch.Write(); err != nil {
log.Error("Failed to persist stack slots", "err", err) log.Error("Failed to persist stack slots", "err", err)
} }
@@ -2318,9 +2421,7 @@ func (s *Syncer) forwardAccountTask(task *accountTask) {
// flush after finalizing task.done. It's fine even if we crash and lose this // flush after finalizing task.done. It's fine even if we crash and lose this
// write as it will only cause more data to be downloaded during heal. // write as it will only cause more data to be downloaded during heal.
if task.done { if task.done {
if _, err := task.genTrie.Commit(); err != nil { task.genTrie.Commit()
log.Error("Failed to commit stack account", "err", err)
}
} }
if task.genBatch.ValueSize() > ethdb.IdealBatchSize || task.done { if task.genBatch.ValueSize() > ethdb.IdealBatchSize || task.done {
if err := task.genBatch.Write(); err != nil { if err := task.genBatch.Write(); err != nil {
@@ -2398,11 +2499,11 @@ func (s *Syncer) OnAccounts(peer SyncPeer, id uint64, hashes []common.Hash, acco
for i, key := range hashes { for i, key := range hashes {
keys[i] = common.CopyBytes(key[:]) keys[i] = common.CopyBytes(key[:])
} }
nodes := make(light.NodeList, len(proof)) nodes := make(trienode.ProofList, len(proof))
for i, node := range proof { for i, node := range proof {
nodes[i] = node nodes[i] = node
} }
proofdb := nodes.NodeSet() proofdb := nodes.Set()
var end []byte var end []byte
if len(keys) > 0 { if len(keys) > 0 {
@@ -2625,7 +2726,7 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
// the requested data. For storage range queries that means the state being // the requested data. For storage range queries that means the state being
// retrieved was either already pruned remotely, or the peer is not yet // retrieved was either already pruned remotely, or the peer is not yet
// synced to our head. // synced to our head.
if len(hashes) == 0 { if len(hashes) == 0 && len(proof) == 0 {
logger.Debug("Peer rejected storage request") logger.Debug("Peer rejected storage request")
s.statelessPeers[peer.ID()] = struct{}{} s.statelessPeers[peer.ID()] = struct{}{}
s.lock.Unlock() s.lock.Unlock()
@@ -2637,13 +2738,20 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
// Reconstruct the partial tries from the response and verify them // Reconstruct the partial tries from the response and verify them
var cont bool var cont bool
// If a proof was attached while the response is empty, it indicates that the
// requested range specified with 'origin' is empty. Construct an empty state
// response locally to finalize the range.
if len(hashes) == 0 && len(proof) > 0 {
hashes = append(hashes, []common.Hash{})
slots = append(slots, [][]byte{})
}
for i := 0; i < len(hashes); i++ { for i := 0; i < len(hashes); i++ {
// Convert the keys and proofs into an internal format // Convert the keys and proofs into an internal format
keys := make([][]byte, len(hashes[i])) keys := make([][]byte, len(hashes[i]))
for j, key := range hashes[i] { for j, key := range hashes[i] {
keys[j] = common.CopyBytes(key[:]) keys[j] = common.CopyBytes(key[:])
} }
nodes := make(light.NodeList, 0, len(proof)) nodes := make(trienode.ProofList, 0, len(proof))
if i == len(hashes)-1 { if i == len(hashes)-1 {
for _, node := range proof { for _, node := range proof {
nodes = append(nodes, node) nodes = append(nodes, node)
@@ -2662,7 +2770,7 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
} else { } else {
// A proof was attached, the response is only partial, check that the // A proof was attached, the response is only partial, check that the
// returned data is indeed part of the storage trie // returned data is indeed part of the storage trie
proofdb := nodes.NodeSet() proofdb := nodes.Set()
var end []byte var end []byte
if len(keys) > 0 { if len(keys) > 0 {

Some files were not shown because too many files have changed in this diff Show More