Compare commits

..

195 Commits

Author SHA1 Message Date
j75689
05c1f1438c chore: rialto network for testing 2024-03-15 09:56:52 +08:00
Roshan
4b5eebead1 fix review comments 2024-03-14 18:55:12 +08:00
Roshan
b5603d2e98 fix: add FeynmanFix upgrade for a testnet issue 2024-03-14 18:41:53 +08:00
Eric
c8cc91963f eth/gasprice: fix percentile validation in eth_feeHistory (#2242) 2024-03-04 10:53:21 +08:00
zzzckck
bd13416162 Merge pull request #2239 from bnb-chain/develop
draft release v1.3.10
2024-02-27 14:50:53 +08:00
zzzckck
b7b64da564 release: prepare for release v1.3.10 (#2238) 2024-02-27 14:19:32 +08:00
zjubfd
73f27a590f feat: add new fork block and precompile contract for BEP294 and BEP299 (#2047) 2024-02-26 16:17:03 +08:00
zzzckck
5e74ea650d Merge pull request #2218 from bnb-chain/develop
draft release v1.3.9
2024-02-20 17:52:32 +08:00
VM
5378df3702 cmd: optimize parse state scheme in cli and config (#2220) 2024-02-20 17:22:27 +08:00
Matus Kysel
40cae45436 Merge pull request #2213 from bnb-chain/freezer-fix
Freezer fix
2024-02-20 09:30:30 +01:00
zzzckck
361e8413e6 release: prepare for release v1.3.9 (#2217) 2024-02-19 14:43:15 +08:00
rjl493456442
36a283ef98 core/rawdb: fsync the index file after each freezer write (#28483)
* core/rawdb: fsync the index and data file after each freezer write

* core/rawdb: fsync the data file in freezer after write
2024-02-14 08:22:43 +01:00
Ng Wei Han
78d1cade19 eth/fetcher: downgrade state tx log (#2195) 2024-02-02 10:58:17 +08:00
Eric
82beb2c5f3 log: support maxBackups in config.toml (#2186) 2024-01-30 19:16:01 +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
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
c6aeee2001 Merge pull request #2169 from bnb-chain/develop
draft release v1.3.8
2024-01-23 17:22:42 +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
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
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
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
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
zzzckck
f28b98a994 Merge pull request #2088 from bnb-chain/develop
draft release v1.3.7
2023-12-19 14:09:44 +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
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
5ee77bbe8b Merge pull request #2066 from bnb-chain/develop
draft release v1.3.6
2023-12-14 14:26:55 +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
zzzckck
4b107c5303 readme: update hardware requirements for BSC full node (#2057) 2023-12-12 18:44:06 +08:00
zzzckck
fe928d4778 Merge pull request #2006 from bnb-chain/develop
release: draft release v1.3.5
2023-12-08 14:17:24 +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
buddho
e3ef62f3bd rpc,eth: output more info about failed txs(#2041) 2023-12-07 16:07:48 +08:00
buddh0
fa5d0cf287 core/systemcontracts: update CommitUrl for keplerUpgrade 2023-12-07 15:53:25 +08:00
buddh0
6c788d7675 tests/truffle: adapt changes in bsc-genesis-contracts 2023-12-07 14:57:55 +08:00
buddho
a30beeba59 core/txpool/legacypool: respect nolocals-setting (#2037) 2023-12-06 17:05:13 +08:00
lx
aa15df2814 config: setup Kepler/Shanghai hardfork date
expected hard fork date:
- Testnet: 19th Dec 2023, 2pm UTC+8, Tuesday
- Mainnet: 23th Jan 2024, 4pm UTC+8, Tuesday
2023-12-05 17:41:28 +08:00
larry.lx
195ae35130 release: prepare for release v1.3.5 2023-12-05 17:41:28 +08:00
buddho
5db73c9837 cmd/geth: standardize the action of importing bls account (#2020)
* cmd/geth: standardize the action of importing bls account
* rename bLSAccountPasswordFileFlag to blsAccountPasswordFileFlag
* use password of wallet as account password when new an account or importing a raw key
2023-12-05 16:37:19 +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
zzzckck
7e6b43a5c7 Merge pull request #2033 from bnb-chain/develop_lock_v1.3.4_merge
merge v1.3.4 into develop branch
2023-12-05 12:04:39 +08:00
zzzckck
5b78f5761a Merge branch 'develop' into develop_lock_v1.3.4_merge 2023-12-05 11:29:13 +08:00
larry.lx
885de2c1ca fix: failed ut 2023-12-04 19:06:48 +08:00
larry.lx
afc3b42241 fix: disable flag --pipecommit 2023-12-04 19:06:48 +08:00
larry.lx
a2f9ac0c8b release: prepare v1.3.4 2023-12-04 19:06:48 +08:00
larry.lx
761563155c fork: add hardfork Hertzfix 2023-12-04 19:06:48 +08:00
larry.lx
8b00720640 fix: remove pipecommit in miner 2023-12-04 19:06:48 +08:00
larry.lx
a8409158a5 release: draft v1.3.3 2023-12-04 19:06:48 +08:00
Ng Wei Han
a3507cc2c1 cmd/utils: exit process if txlookuplimit flag is set (#2000) 2023-12-04 19:06:48 +08:00
Ng Wei Han
b494339e10 fix(cmd): check pruneancient when creating db (#1986) 2023-12-04 19:06:48 +08:00
larry.lx
f7e9adc2c8 fix: remove sharedPool 2023-12-04 19:06:48 +08:00
lx
70ccc3d1fe Merge pull request #2019 from bnb-chain/develop_lock_v1.3.3 2023-11-30 15:17:47 +08:00
lx
20dcaabfdc Merge branch 'develop' into develop_lock_v1.3.3 2023-11-30 10:14:39 +08:00
larry.lx
c409eb6ac6 release: draft v1.3.3 2023-11-30 09:35:50 +08:00
Ng Wei Han
cf80501de5 cmd/utils: exit process if txlookuplimit flag is set (#2000) 2023-11-30 09:33:17 +08:00
Ng Wei Han
3ce568ff44 fix(cmd): check pruneancient when creating db (#1986) 2023-11-30 09:31:44 +08:00
larry.lx
8e19728ea7 fix: remove sharedPool 2023-11-29 15:02:58 +08:00
buddho
1edb34fd67 consensus/parlia: recover faster when snapshot of parlia is gone in disk (#2008) 2023-11-28 14:03:05 +08:00
buddho
789442372d consensus/parlia: increase size of snapshot cache in parlia (#2007) 2023-11-28 13:56:01 +08:00
Ng Wei Han
c92b6ce2ad cmd/utils: exit process if txlookuplimit flag is set (#2000) 2023-11-25 20:57:23 +08:00
buddh0
cd0356b106 core/systemcontracts: include BEP-319 on kepler hardfork 2023-11-22 19:09:34 +08:00
buddho
0224d48df4 core: enable Shanghai EIPs (#1970) 2023-11-20 19:19:26 +08:00
wayen
497fdf8358 fix: upgrade pebble and improve config (#1979) 2023-11-20 14:28:01 +08:00
Ng Wei Han
8b94dd6b59 fix(cmd): check pruneancient when creating db (#1986) 2023-11-14 20:10:41 +08:00
buddho
4be9481558 internal/ethapi: fix null effectiveGasPrice in GetTransactionReceipt (#1980) 2023-11-14 16:40:25 +08:00
buddho
3fc9f750d1 consensus/parlia: hardfork block can be epoch block (#1964) 2023-11-14 16:33:57 +08:00
joey
72ffb0cbed doc: add instructions for starting fullnode with pbss (#1977) 2023-11-10 19:23:14 +08:00
lx
1dca486622 Merge pull request #1928 from bnb-chain/develop 2023-11-09 15:44:20 +08:00
lx
a4eee3bdaa doc: update changelog for v1.3.1 (#1976) 2023-11-09 14:31:14 +08:00
joey
53559fc4d7 eth, trie/triedb/pathdb: pbss patches (#1955)
* fix: use the top root hash for rewinding under path schema

* feat: add async flush nodebuffer in path schema

* chore: add prun-block param suffix check

* fix: code review comments
2023-11-06 14:11:17 +08:00
joey
62862471f8 fix: revert trie commited flag after delete statedb mpt cache (#1963) 2023-11-03 15:58:43 +08:00
lx
ea9c962d1f Merge pull request #1962 from bnb-chain/cherry_pick_pbss_patches
cherry pick pbss patches from go-ethereum
2023-11-03 14:31:47 +08:00
Gary Rong
f5a854c9c4 trie/triedb/pathdb: improve dirty node flushing trigger
trie/triedb/pathdb: add tests

trie/triedb/pathdb: address comment
2023-11-03 12:11:33 +08:00
Gary Rong
604f1608b3 eth, trie/triedb/pathdb: reallocate excess memory to clean cache
eth, trie/triedb/pathdb: address comments
2023-11-03 12:11:24 +08:00
lx
56424d390f trie: keep trie prefetch during validation phase (#1954) 2023-10-31 11:32:31 +08:00
GalaIO
0d9151eb8f txpool: fix a potential crash issue in shutdown; (#1951) 2023-10-30 15:56:37 +08:00
Eric
3e298c1586 fix: 2 APIs of get receipt related(#1950)
* fix: GetTransactionReceiptsByBlockNumber &  GetTransactionDataAndReceipt
2023-10-30 13:38:47 +08:00
lx
3bf998f55c code: remove accountTrieCache and storageTrieCache (#1949)
accountTrieCache and storageTrieCache were introduced in this PR:
https://github.com/bnb-chain/bsc/pull/257, which is to improve performance.
Actually the performance gain is quite limited, as there is already dirty
and clean cache for trie node.
And after big merge, these 2 cache can not be used when PBSS is enabled.
So remove these code to simplify the logic.
2023-10-30 10:29:54 +08:00
lx
fd6e7bb3b2 performance: commitTire concurrently (#1948) 2023-10-27 08:55:51 +08:00
lx
01d75a9d21 dependency: go version to 1.20 and some dependencies in go.mod (#1939)
* go.mod: upgrade prysm and the indrect dependency
prysm from v4.0.2 to v4.0.8, and run go mod tidy

* ci: upgrade go version from 1.19 to 1.20
* go-version: upgrade from v1.19 to v1.20
there is some dependency on go v1.20, such as go-libp2p v0.27.8
and also run go mod tidy

* dependency: upgrade docker version for security
it is not a big issue, since docker is only used for test purpose.

* rand: update the usage of math/rand after golang v1.20

2 APIs of math/rand module were deprecated since golang v1.20.
that is: rand.Seed() and rand.Read(), refer: ettps://pkg.go.dev/math/rand

"rand.Seed(seed int64)" has been replaced by: "r := rand.New(rand.NewSource(seed int64))",
need to initialize it with an instance before use

"rand.Read()" has been replaced by "crypto/rand.Read()"

* readme: need golang v1.20+ to build bsc
2023-10-24 21:51:30 +08:00
lx
4493ab8a07 release: prepare for release v1.3.1 (#1927) 2023-10-18 11:31:38 +08:00
Nathan
a6cfcfe2b3 consensus/parlia: fix nextForkHash in Extra filed of block header (#1923) 2023-10-17 19:09:11 +08:00
joeycli
9f5842e0ec fix: recover TestStateChanges 2023-10-16 15:27:17 +08:00
rjl493456442
fdfc6371f6 trie/triedb/pathdb: improve error log (#28177) 2023-10-16 15:27:17 +08:00
rjl493456442
5a3109b1bf trie: remove internal nodes between shortNode and child in path mode (#28163)
* trie: remove internal nodes between shortNode and child in path mode

* trie: address comments

* core/rawdb, trie: address comments

* core/rawdb: delete unused func

* trie: change comments

* trie: add missing tests

* trie: fix lint
2023-10-16 15:27:17 +08:00
joeycli
c3199ab5fc fix: ut error 2023-10-16 15:27:17 +08:00
Delweng
9baffb33b6 core/rawdb: no need to run truncateFile for readonly mode (#28145)
Avoid truncating files, if ancients are opened in readonly mode. With this change, we return error instead of trying (and failing)  to repair
2023-10-16 15:27:17 +08:00
Darioush Jalali
d3a6f9a19e core/state: check err for iter.Error in fastDeleteStorage (#28122)
core/state: check err for iter.Error
2023-10-16 15:27:17 +08:00
rjl493456442
713d8d66a9 core/state: implement fast storage deletion (#27955)
This changes implements faster post-selfdestruct iteration of storage slots for deletion, by using snapshot-storage+stacktrie to recover the trienodes to be deleted. This mechanism is only implemented for path-based schema.

For hash-based schema, the entire post-selfdestruct storage iteration is skipped, with this change, since hash-based does not actually perform deletion anyway.

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-10-16 15:27:17 +08:00
Péter Szilágyi
4be2e1bb70 eth/protocols/eth: stop advertising eth/66 for pathdb nodes (#28006) 2023-10-16 15:27:17 +08:00
Marius van der Wijden
959b7332bf core/rawdb: allocate database keys with explicit size to avoid slice growth (#27772) 2023-10-16 15:27:17 +08:00
Péter Szilágyi
dda8c00eec trie/triedb/pathdb: make shutdown journal log friendlier (#27905) 2023-10-16 15:27:17 +08:00
lx
423d4137e5 Merge pull request #1917 from bnb-chain/master
branch: merge v1.3.0 fix ups from master to develop
2023-10-13 10:01:16 +08:00
lx
181218128b Merge branch 'develop' into master 2023-10-12 22:17:11 +08:00
Nathan
b86459a722 core/txpool: ignore nil sub when subpool have been shut down (#1915)
Co-authored-by: buddh0 <galaxystroller@gmail.com>
2023-10-12 10:20:48 +08:00
Nathan
73cfed0ea1 core/vm: clean up evm clearly when get it from pool (#1914) 2023-10-11 16:20:47 +08:00
Nathan
35d85e250b core: write head block hash when shutdown (#1912) 2023-10-11 16:17:17 +08:00
lx
43e2c779b4 Revert "fix: skip a patch that could fork the chain (#1902)" (#1913)
This reverts commit 0d47213199.
2023-10-11 14:37:34 +08:00
Nathan
17ffdf1a9d core/state: skip deleting storages for EmptyTrie (#1911) 2023-10-10 18:15:24 +08:00
Nathan
f8439514e3 core/state: skip handleDestruction in hash based mode (#1908) 2023-10-08 18:55:30 +08:00
Fynn
5cd647bb7d Merge pull request #1906 from Fynnss/fix_state_history_write_error
cmd/geth: fix error when writing state history after covert from hbss to pbss
2023-10-08 00:40:43 -05:00
Nathan
44b2f4a787 metrics: fix missing miner-info, build-info and node-info (#1907) 2023-10-08 10:19:38 +08:00
lx
0d47213199 fix: skip a patch that could fork the chain (#1902) 2023-10-07 16:02:33 +08:00
Fynn
4259f4c1f8 fix: state history hasn't write 2023-10-07 14:42:25 +08:00
Fynn
c26a30392a Merge pull request #1882 from Fynnss/add_hash_trie_node_prune_tool
cmd/geth: add hbss to pbss convert tool
2023-10-05 09:13:51 +08:00
Mister-EA
6932673003 cmd: add tests for init-network (#1899)
* cmd: add tests for init-network command

* cmd: add setup function
2023-09-29 20:54:20 +08:00
lx
4b45c5993c fix: skip HasState check for fast node (#1901) 2023-09-28 10:07:21 +08:00
tokikuch
35b21cac14 core/bloombits: fix deadlock when matcher session hits an error (#1895)
When MatcherSession encounters an error, it attempts to close the session.
Closing waits for all goroutines to finish, including the 'distributor'.
However, the distributor will not exit until all requests have returned.

This patch fixes the issue by delivering the (empty) result to the distributor
before calling Close().
2023-09-27 15:00:27 +08:00
Nathan
f8bc2b76ac core/state: ensure triedb Commit after Update (#1900) 2023-09-27 11:07:45 +08:00
Nathan
c955dd2189 cmd/geth: fix listern port when initNetwork (#1897) 2023-09-27 10:43:13 +08:00
Fynn
b8bad314ed cmd/geth: add hash2path & trie get tools 2023-09-26 20:45:05 +08:00
joeycli
528d97b541 feat: active pbss on bsc
fix: lint error

fix: ut error

fix: code review comments
2023-09-26 16:14:32 +08:00
rjl493456442
720ff1fe57 all: activate pbss as experimental feature from eth (#26274)
* all: activate pbss

* core/rawdb: fix compilation error

* cma, core, eth, les, trie: address comments

* cmd, core, eth, trie: polish code

* core, cmd, eth: address comments

* cmd, core, eth, les, light, tests: address comment

* cmd/utils: shorten log message

* trie/triedb/pathdb: limit node buffer size to 1gb

* cmd/utils: fix opening non-existing db

* cmd/utils: rename flag name

* cmd, core: group chain history flags and fix tests

* core, eth, trie: fix memory leak in snapshot generation

* cmd, eth, internal: deprecate flags

* all: enable state tests for pathdb, fixes

* cmd, core: polish code

* trie/triedb/pathdb: limit the node buffer size to 256mb

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-09-26 16:14:32 +08:00
GalaIO
d179056512 logs: add some logs to trace block miner, justified reorg; (#1894) 2023-09-26 14:21:22 +08:00
GalaIO
2f7d305013 logs: add some logs to trace block miner, justified reorg; (#1894) 2023-09-25 20:11:52 +08:00
lx
b3ef585957 Merge pull request #1892 from bnb-chain/develop
draft release v1.3.0
2023-09-25 16:45:45 +08:00
lx
c5647b128c release: prepare for release v1.3.0 (#1891) 2023-09-25 14:20:48 +08:00
Nathan
52e2cb86a5 parlia: reject header with non-nil WithdrawalsHash(#1884)
* parlia: reject header with `WithdrawalsHash` before shanghai fork

* log: output chainconfig when start up

* eth: fix TestOptionMaxPeersPerIP failure of goroutine order
2023-09-21 12:02:59 +08:00
Nathan
41f0667ce1 Revert "core/rawdb: open meta file in read only mode (#26009)" (#1879)
This reverts commit b9ba6f6e4d.
2023-09-20 07:05:18 +08:00
Matus Kysel
2c7a07bc57 discov: add status log for bootnode (#1878) 2023-09-19 14:40:35 +08:00
NathanBSC
1bc27f6d98 core/state: handle account destruction after updating account state 2023-09-19 10:58:35 +08:00
Nathan
9edad94115 cmd/utils: make uncategorized flags of geth categorized (#1877) 2023-09-18 20:07:03 +08:00
NathanBSC
e379117b79 tests/truffle: adapt for changes in bsc-genesis-contract 2023-09-18 18:22:24 +08:00
NathanBSC
782aea5841 build: run full unit test cases, except ./tests 2023-09-14 13:58:08 +08:00
lx
fe5df933b6 Merge pull request #1840 from bnb-chain/big_merge_v1.10.16_v1.12.2
Big merge from v1.10.16 to v1.12.2
2023-09-14 13:19:42 +08:00
lx
bb6bdc055d Merge pull request #1860 from bnb-chain/develop
draft release v1.2.12
2023-09-11 17:43:19 +08:00
lx
1c17c47df7 release: prepare for release v1.2.12 (#1859) 2023-09-08 14:20:19 +08:00
lx
7a19cd27b6 Merge pull request #1833 from bnb-chain/develop
draft release v1.2.11
2023-08-23 11:32:08 +08:00
lx
c431373bd5 ci: increase header-max-length from 72 to 80 for master branch (#1834)
PR merge will append the PR number at the end, like:... (#1805), which
has extra 8 characters
2023-08-22 21:35:43 +08:00
lx
2b836937a2 Merge pull request #1793 from bnb-chain/develop
draft release v1.2.10
2023-08-03 11:58:13 +08:00
lx
34b065aecb Merge pull request #1777 from bnb-chain/develop
release: draft release v1.2.9
2023-07-21 17:35:10 +08:00
lx
5f87ddf9f6 docs: some url update (#1742) 2023-06-30 17:26:38 +08:00
lx
fd58e6f0ac Merge pull request #1737 from bnb-chain/develop
release: draft release v1.2.8
2023-06-27 14:08:04 +08:00
lx
9ed95d826e Merge pull request #1723 from bnb-chain/develop
release: draft release v1.2.7
2023-06-20 20:01:00 +08:00
364 changed files with 18610 additions and 39063 deletions

View File

@@ -36,7 +36,7 @@ module.exports = {
'header-max-length': [
2,
'always',
72,
80,
],
},
helpUrl:

View File

@@ -7,7 +7,7 @@ on:
- develop
pull_request:
branches:
branches:
- master
- develop
@@ -15,7 +15,7 @@ jobs:
unit-test:
strategy:
matrix:
go-version: [1.19.x]
go-version: [1.21.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
@@ -47,5 +47,3 @@ jobs:
run: |
go mod download
make geth

View File

@@ -7,7 +7,7 @@ on:
- develop
pull_request:
branches:
branches:
- master
- develop

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

@@ -7,7 +7,7 @@ on:
- develop
pull_request:
branches:
branches:
- master
- develop

View File

@@ -7,7 +7,7 @@ on:
- develop
pull_request:
branches:
branches:
- master
- develop
@@ -15,7 +15,7 @@ jobs:
golang-lint:
strategy:
matrix:
go-version: [1.19.x]
go-version: [1.21.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
@@ -44,13 +44,13 @@ jobs:
${{ runner.os }}-go-
- run: |
go mod download
go mod tidy
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: v1.52.2
version: v1.55.2
working-directory: ./
skip-pkg-cache: true
skip-cache: true

37
.github/workflows/nancy.yml vendored Normal file
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
strategy:
matrix:
go-version: [1.19.x]
go-version: [1.21.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:

View File

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

View File

@@ -7,7 +7,7 @@ on:
- develop
pull_request:
branches:
branches:
- master
- develop
@@ -15,7 +15,7 @@ jobs:
unit-test:
strategy:
matrix:
go-version: [1.19.x]
go-version: [1.21.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
@@ -51,4 +51,3 @@ jobs:
run: |
go mod download
make test

1
.gitignore vendored
View File

@@ -14,7 +14,6 @@
*/**/*tx_database*
*/**/*dapps*
build/_vendor/pkg
/tests/truffle/storage
#*
.#*

View File

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

View File

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

View File

@@ -1,4 +1,283 @@
# Changelog
## v1.3.11
BUGFIX
* [\#2288](https://github.com/bnb-chain/bsc/pull/2288) fix: add FeynmanFix upgrade for a testnet issue
## v1.3.10
FEATURE
* [\#2047](https://github.com/bnb-chain/bsc/pull/2047) feat: add new fork block and precompile contract for BEP294 and BEP299
## v1.3.9
FEATURE
* [\#2186](https://github.com/bnb-chain/bsc/pull/2186) log: support maxBackups in config.toml
BUGFIX
* [\#2160](https://github.com/bnb-chain/bsc/pull/2160) cmd: fix dump cli cannot work in path mode
* [\#2183](https://github.com/bnb-chain/bsc/pull/2183) p2p: resolved deadlock on p2p server shutdown
IMPROVEMENT
* [\#2177](https://github.com/bnb-chain/bsc/pull/0000) build(deps): bump github.com/quic-go/quic-go from 0.39.3 to 0.39.4
* [\#2185](https://github.com/bnb-chain/bsc/pull/2185) consensus/parlia: set nonce before evm run
* [\#2190](https://github.com/bnb-chain/bsc/pull/2190) fix(legacypool): deprecate already known error
* [\#2195](https://github.com/bnb-chain/bsc/pull/2195) eth/fetcher: downgrade state tx log
## v1.3.8
FEATURE
* [\#2074](https://github.com/bnb-chain/bsc/pull/2074) faucet: new faucet client
* [\#2082](https://github.com/bnb-chain/bsc/pull/2082) cmd/dbcmd: add inspect trie tool
* [\#2140](https://github.com/bnb-chain/bsc/pull/2140) eth/fetcher: allow underpriced transactions in after timeout
* [\#2115](https://github.com/bnb-chain/bsc/pull/2115) p2p: no peer reconnect if explicitly disconnected
* [\#2128](https://github.com/bnb-chain/bsc/pull/2128) go.mod: upgrade prysm to support built with go@v1.21
* [\#2151](https://github.com/bnb-chain/bsc/pull/2151) feat: enable NoDial should still dial static nodes
* [\#2144](https://github.com/bnb-chain/bsc/pull/2144) p2p: reset disconnect set with magic enode ID
BUGFIX
* [\#2095](https://github.com/bnb-chain/bsc/pull/2095) rpc: fix ns/µs mismatch in metrics
* [\#2083](https://github.com/bnb-chain/bsc/pull/2083) triedb/pathdb: fix async node buffer diskroot mismatches when journaling
* [\#2120](https://github.com/bnb-chain/bsc/pull/2120) ethdb/pebble: cap memory table size as maxMemTableSize-1
* [\#2107](https://github.com/bnb-chain/bsc/pull/2107) cmd/geth: fix parse state scheme
* [\#2121](https://github.com/bnb-chain/bsc/pull/2121) parlia: fix verifyVoteAttestation when verify a batch of headers
* [\#2132](https://github.com/bnb-chain/bsc/pull/2132) core: fix systemcontracts.GenesisHash when run bsc firstly without init
* [\#2155](https://github.com/bnb-chain/bsc/pull/2155) cmd, core: resolve scheme from a read-write database and refactor resolveChainFreezerDir func
IMPROVEMENT
* [\#2099](https://github.com/bnb-chain/bsc/pull/2099) params/config: remove useless toml tag for hardforks
* [\#2100](https://github.com/bnb-chain/bsc/pull/2100) core/genesis: support chapel to run without geth init
* [\#2101](https://github.com/bnb-chain/bsc/pull/2101) core: add metrics for bad block
* [\#2109](https://github.com/bnb-chain/bsc/pull/2109) cmd/geth: tidy flags for geth command
* [\#1953](https://github.com/bnb-chain/bsc/pull/1953) build(deps): bump github.com/docker/docker
* [\#2086](https://github.com/bnb-chain/bsc/pull/2086) build(deps): bump golang.org/x/crypto from 0.12.0 to 0.17.0
* [\#2106](https://github.com/bnb-chain/bsc/pull/2106) params: use rialto to test builtin network logic
* [\#2098](https://github.com/bnb-chain/bsc/pull/2098) cmd, les, tests: remove light client code
* [\#2114](https://github.com/bnb-chain/bsc/pull/2114) p2p: add serve metrics
* [\#2123](https://github.com/bnb-chain/bsc/pull/2123) p2p, eth: improve logs
* [\#2116](https://github.com/bnb-chain/bsc/pull/2116) tests: revive evm test cases
* [\#2161](https://github.com/bnb-chain/bsc/pull/2161) code: remove IsEuler check from worker.go
* [\#2167](https://github.com/bnb-chain/bsc/pull/2167) improve: increase SystemTxsGas from 1,500,000 to 5,000,000
* [\#2172](https://github.com/bnb-chain/bsc/pull/2172) improve: remove sharedpool from miner
* [\#1332](https://github.com/bnb-chain/bsc/pull/1332) core/state: no need to prune block if the same
## v1.3.7
FEATURE
* [\#2067](https://github.com/bnb-chain/bsc/pull/2067) cmd/geth: add check func to validate state scheme
* [\#2068](https://github.com/bnb-chain/bsc/pull/2068) internal/ethapi: implement eth_getBlockReceipts
BUGFIX
* [\#2035](https://github.com/bnb-chain/bsc/pull/2035) all: pull snap sync PRs from upstream v1.13.5
* [\#2072](https://github.com/bnb-chain/bsc/pull/2072) fix: fix the pebble config of level option
* [\#2078](https://github.com/bnb-chain/bsc/pull/2078) core: LoadChainConfig return the predefined config for built-in networks firstly
## v1.3.6
FEATURE
* [\#2012](https://github.com/bnb-chain/bsc/pull/2012) cmd, core, ethdb: enable Pebble on 32 bits and OpenBSD
* [\#2063](https://github.com/bnb-chain/bsc/pull/2063) log: support to disable log rotate by hours
* [\#2064](https://github.com/bnb-chain/bsc/pull/2064) log: limit rotateHours in range [0,23]
BUGFIX
* [\#2058](https://github.com/bnb-chain/bsc/pull/2058) params: set default hardfork times
IMPROVEMENT
* [\#2015](https://github.com/bnb-chain/bsc/pull/2015) cmd, core, eth: change default network from ETH to BSC
* [\#2036](https://github.com/bnb-chain/bsc/pull/2036) cmd/jsutils: add 2 tools get validator version and block txs number
* [\#2037](https://github.com/bnb-chain/bsc/pull/2037) core/txpool/legacypool: respect nolocals-setting
* [\#2042](https://github.com/bnb-chain/bsc/pull/2042) core/systemcontracts: update CommitUrl for keplerUpgrade
* [\#2043](https://github.com/bnb-chain/bsc/pull/2043) tests/truffle: adapt changes in bsc-genesis-contracts
* [\#2051](https://github.com/bnb-chain/bsc/pull/2051) core/vote: wait some blocks before voting since mining begin
* [\#2060](https://github.com/bnb-chain/bsc/pull/2060) cmd/utils: allow HTTPHost and WSHost flags precede
## v1.3.5
FEATURE
* [\#1970](https://github.com/bnb-chain/bsc/pull/1970) core: enable Shanghai EIPs
* [\#1973](https://github.com/bnb-chain/bsc/pull/1973) core/systemcontracts: include BEP-319 on kepler hardfork
BUGFIX
* [\#1964](https://github.com/bnb-chain/bsc/pull/1964) consensus/parlia: hardfork block can be epoch block
* [\#1979](https://github.com/bnb-chain/bsc/pull/1979) fix: upgrade pebble and improve config
* [\#1980](https://github.com/bnb-chain/bsc/pull/1980) internal/ethapi: fix null effectiveGasPrice in GetTransactionReceipt
IMPROVEMENT
* [\#1977](https://github.com/bnb-chain/bsc/pull/1977) doc: add instructions for starting fullnode with pbss
## v1.3.4
BUGFIX
* fix: remove pipecommit in miner
* add a hard fork: Hertzfix
## v1.3.3
BUGFIX
* [\#1986](https://github.com/bnb-chain/bsc/pull/1986) fix(cmd): check pruneancient when creating db
IMPROVEMENT
* [\#2000](https://github.com/bnb-chain/bsc/pull/2000) cmd/utils: exit process if txlookuplimit flag is set
## v1.3.2
BUGFIX
* fix: remove sharedPool
IMPROVEMENT
* [\#2007](https://github.com/bnb-chain/bsc/pull/2007) consensus/parlia: increase size of snapshot cache in parlia
* [\#2008](https://github.com/bnb-chain/bsc/pull/2008) consensus/parlia: recover faster when snapshot of parlia is gone in disk
## v1.3.1
FEATURE
* [\#1881](https://github.com/bnb-chain/bsc/pull/1881) feat: active pbss
* [\#1882](https://github.com/bnb-chain/bsc/pull/1882) cmd/geth: add hbss to pbss convert tool
* [\#1916](https://github.com/bnb-chain/bsc/pull/1916) feat: cherry-pick pbss patch commits from eth repo in v1.13.2
* [\#1939](https://github.com/bnb-chain/bsc/pull/1939) dependency: go version to 1.20 and some dependencies in go.mod
* [\#1955](https://github.com/bnb-chain/bsc/pull/1955) eth, trie/triedb/pathdb: pbss patches
* [\#1962](https://github.com/bnb-chain/bsc/pull/1962) cherry pick pbss patches from go-ethereum
BUGFIX
* [\#1923](https://github.com/bnb-chain/bsc/pull/1923) consensus/parlia: fix nextForkHash in Extra filed of block header
* [\#1950](https://github.com/bnb-chain/bsc/pull/1950) fix: 2 APIs of get receipt related
* [\#1951](https://github.com/bnb-chain/bsc/pull/1951) txpool: fix a potential crash issue in shutdown;
* [\#1963](https://github.com/bnb-chain/bsc/pull/1963) fix: revert trie commited flag after delete statedb mpt cache
IMPROVEMENT
* [\#1948](https://github.com/bnb-chain/bsc/pull/1948) performance: commitTire concurrently
* [\#1949](https://github.com/bnb-chain/bsc/pull/1949) code: remove accountTrieCache and storageTrieCache
* [\#1954](https://github.com/bnb-chain/bsc/pull/1954) trie: keep trie prefetch during validation phase
## v1.3.0
#### RPC
* [internal/ethapi: add debug_getRawReceipts RPC method (#24773)](https://github.com/bnb-chain/bsc/pull/1840/commits/ae7d834bc752a2d94fef9d354ee78fcb9425f3d1)
* [node, rpc: add ReadHeaderTimeout config option (#25338)](https://github.com/bnb-chain/bsc/pull/1840/commits/9244f87dc1c8869a2632176f719e515217720a43)
* [rpc: check that "version" is "2.0" in request objects (#25570)](https://github.com/bnb-chain/bsc/pull/1840/commits/38e002f4641c2779c897ccaca575ec5ddeee9254)
* [rpc: support injecting HTTP headers through context (#26023)](https://github.com/bnb-chain/bsc/pull/1840/commits/add337e0f7bad02f3cf535c66cd31f252b0b5c99)
* [rpc: websocket should respect the "HTTP_PROXY" by default (#27264)](https://github.com/bnb-chain/bsc/pull/1840/commits/73697529994e14996b7740730481e926d5ec3e40)
* [rpc: change BlockNumber constant values to match ethclient (#27219)](https://github.com/bnb-chain/bsc/pull/1840/commits/9231770811cda0473a7fa4e2bccc95bf62aae634)
* [eth: make debug_StorageRangeAt take a block hash or number (#27328)](https://github.com/bnb-chain/bsc/pull/1840/commits/d789c68b667e13eb5cefd19d09ae84f7d016df6a)
* [eth,core: add api debug_getTrieFlushInterval (#27303)](https://github.com/bnb-chain/bsc/pull/1840/commits/0783cb7d91ad7b3cdf72ac6c6edaec8318673eb6)
* [rpc: add limit for batch request items and response size (#26681)](https://github.com/bnb-chain/bsc/pull/1840/commits/f3314bb6df4c86e650f0e47cbb5a21ca0616ac11)
* [core/types: support yParity field in JSON transactions (#27744)](https://github.com/bnb-chain/bsc/pull/1840/commits/bb148dd342ba03ce40cf04295e193c94b9dda322)
* [eth/filters: send rpctransactions in pending-subscription (#26126)](https://github.com/bnb-chain/bsc/pull/1840/commits/8c5ce1107b3110c7cb735d8dfa91c9c701393c85)
#### Flag
* [cmd/geth: rename --whitelist to --eth.requiredblocks (#24505)](https://github.com/bnb-chain/bsc/pull/1840/commits/dbfd3972624c1d82db21f5dfceab8fde7a1eee0a)
* [cmd: migrate to urfave/cli/v2 (#24751)](https://github.com/bnb-chain/bsc/pull/1840/commits/52ed3570c483693fdd6667add7e3050520ad3ba2)
* [cmd/utils: print warning when --metrics.port set without --metrics.ad…](https://github.com/bnb-chain/bsc/pull/1840/commits/8846c07d044f30dca8cd0db91c6245f71f4b24fa)
* [cmd/devp2p: add --extaddr flag (#26312)](https://github.com/bnb-chain/bsc/pull/1840/commits/b44abf56a966016cbb651648ac2d7b6705e80b11)
* [core,eth: adddebug_setTrieFlushInterval to change trie flush frequ](https://github.com/bnb-chain/bsc/pull/1840/commits/711afbc7fd76f1f206429e26f9aa5bf98bc7b43d)
* [miner, cmd, eth: require explicit etherbase address (#26413)](https://github.com/bnb-chain/bsc/pull/1840/commits/2b44ef5f93cc7479a77890917a29684b56e9167a)
* [cmd/geth: Add[--log.format] cli param (#27001)](https://github.com/bnb-chain/bsc/pull/1840/commits/2d1492821d058a3488b4da2c1f62906eaf6d7c95)
* [cmd/geth: rename --vmodule to --log.vmodule (#27071)](https://github.com/bnb-chain/bsc/pull/1840/commits/f2df2b1981fa1e014e4cb34cf9a8dd7b8519e0ac)
* [params, trie: add verkle fork management + upgrade go-verkle (#27464)](https://github.com/bnb-chain/bsc/pull/1840/commits/85b8d1c06c49342966cad2bbdc17d0dc28b66ffd)
#### GraphQL
* [graphql: fee history fields (#24452)](https://github.com/bnb-chain/bsc/pull/1840/commits/57cec892536270fc6dafae01ded2c528ffa370e9)
* [graphql: add rawReceipt field to transaction type (#24738)](https://github.com/bnb-chain/bsc/pull/1840/commits/d73df893a6fc528e69506397322205bd9258b6fa)
* [graphql: add raw fields to block and tx (#24816)](https://github.com/bnb-chain/bsc/pull/1840/commits/29a6b6bcac170ca7f8fceb242eba45ff15df17a1)
* [graphql: return correct logs for tx (#25612)](https://github.com/bnb-chain/bsc/pull/1840/commits/d0dc349fd36bd79f94516c866251783641ed12f1)
* [graphql: add query timeout (#26116)](https://github.com/bnb-chain/bsc/pull/1840/commits/ee9ff064694c445a3a6972001ccbce2cc5b9c3f2)
* [graphql, node, rpc: improve HTTP write timeout handling (#25457)](https://github.com/bnb-chain/bsc/pull/1840/commits/f20eba426a1a871f98d0d988bfd51767364650b7)
* [graphql: implement withdrawals (EIP-4895) (#27072)](https://github.com/bnb-chain/bsc/pull/1840/commits/fbe432fa1584bc976fe0242d999a7dd8903378b2)
#### Client
* [ethclient: add CallContractAtHash (#24355)](https://github.com/bnb-chain/bsc/pull/1700/commits/e98114da4feedf6dfb17b9839fc2c314cf1e5768)
* [ethclient: add PeerCount method (#24849)](https://github.com/bnb-chain/bsc/pull/1840/commits/f5ff022dbca2b14af59974154874537b5ed4cc5e)
* [ethereum, ethclient: add FeeHistory support (#25403)](https://github.com/bnb-chain/bsc/pull/1840/commits/9ad508018e4790da0c1c00ac355f206fca12ab7c)
* [eth/filters, ethclient/gethclient: add fullTx option to pending tx fi…](https://github.com/bnb-chain/bsc/pull/1840/commits/5b1a04b9c749d804b51159fe12246c56de8515c1)
* [ethclient: include withdrawals in ethclient block responses (#26778)](https://github.com/bnb-chain/bsc/pull/1840/commits/e1b98f49a5075694c5022f5ec74425e40da415dd)
#### Tracer
* [eth/tracers/js: drop duktape engine (#24934)](https://github.com/bnb-chain/bsc/pull/1840/commits/ba47d800b13058885288c38bd174babb38560c89)
* [eth/tracers: add support for block overrides in debug_traceCall (#24871)](https://github.com/bnb-chain/bsc/pull/1840/commits/d8a2305565b1f97c451f8595e0f65358d6842714)
* [eth/tracers: add onlyTopCall option to callTracer (#25430)](https://github.com/bnb-chain/bsc/pull/1840/commits/86de2e516e5a4a2bbe1d29b46a0f460fbdde8303)
* [eth/tracers: remove revertReasonTracer, add revert reason to callTracer](https://github.com/bnb-chain/bsc/pull/1840/commits/ff1f49245d641a7268ade38cf512bdc7b26f9b7c)
* [eth/tracers: add diffMode to prestateTracer (#25422)](https://github.com/bnb-chain/bsc/pull/1840/commits/5d52a35931bba10f438ce4f41410442dd9cd396c)
* [eth/tracers: add multiplexing tracer (#26086)](https://github.com/bnb-chain/bsc/pull/1840/commits/53b624b56d4f36c90ebf8046bd1ca78c87a3b6df)
* [core/vm: set tracer-observable value of a delegatecall to match parent `value`](https://github.com/bnb-chain/bsc/pull/1840/commits/b0cd8c4a5c4f0f25011ed64235a3ea1280f03c51)
* [eth/tracers: add native flatCallTracer (aka parity style tracer) (#26…](https://github.com/bnb-chain/bsc/pull/1840/commits/2ad150d986dab085965be047c94af6b2952a9e24)
* [eth/tracers/native: set created address to nil in case of failure (#2…](https://github.com/bnb-chain/bsc/pull/1840/commits/41af42e97c9d62d303a883cc3c143f560867fa34)
* [eth/tracers: report correct gasLimit in call tracers (#27029)](https://github.com/bnb-chain/bsc/pull/1840/commits/0b76eb3708626fbd2eb9c1b58d7b4eac6a5eec15)
* [eth/tracers: addtxHashfield on txTraceResult (#27183)](https://github.com/bnb-chain/bsc/pull/1840/commits/604e215d1bb070dff98fb76aa965064c74e3633f)
* [eth/tracers: add ReturnData in the tracer's response (#27704)](https://github.com/bnb-chain/bsc/pull/1840/commits/1e069cf8026a9f71b5f7e80959465e4b273d5806)
#### Command
* [cmd/geth: inspect snapshot dangling storage (#24643)](https://github.com/bnb-chain/bsc/pull/1840/commits/92e3c56e7be26aac4a25859f55f234aadeec7dbf)
* [core/state/snapshot: detect and clean up dangling storage snapshot in generation](https://github.com/bnb-chain/bsc/pull/1840/commits/59ac229f87831bd74b4dc07d34f54137cca78095)
* [internal/ethapi: add db operations to api (#24739)](https://github.com/bnb-chain/bsc/pull/1840/commits/16701c51697e28986feebd122c6a491e4d9ac0e7)
* [cmd/geth: adddb check-state-contentto verify integrity of trie nodes (#24840)](https://github.com/bnb-chain/bsc/pull/1840/commits/e0a9752b965f243313f2c32a91d306600dc3863c)
* [ethdb/remotedb, cmd: add support for remote (readonly) databases](https://github.com/bnb-chain/bsc/pull/1840/commits/57192bd0dc545d921306f6a4d7566c0c70c764c5)
* [cmd/abigen: accept combined-json via stdin (#24960)](https://github.com/bnb-chain/bsc/pull/1840/commits/0287e1a7c00c1eaad1a99b4ea05d70f1ed685140)
* [cmd/geth: extend traverseRawState command (#24954)](https://github.com/bnb-chain/bsc/pull/1840/commits/a10660b7f8f4fa218ee62a7664b47eb6028fee84)
* [cmd/geth, core/state/snapshot: rework journal loading, implement account-check (#24765)](https://github.com/bnb-chain/bsc/pull/1840/commits/c375ee91e99cd9c072f2fe9b535c5cb780b5f8a0)
* [cmd/geth: add a verkle subcommand (#25718)](https://github.com/bnb-chain/bsc/pull/1840/commits/9d717167aaf27a48d56ad9d1a2c36f90eba1cc13)
* [cmd/geth, cmd/utils: geth attach with custom headers (#25829)](https://github.com/bnb-chain/bsc/pull/1840/commits/ea26fc8a6c44ebb48223f991048f41b2ec0a6414)
* [core/rawdb: refactor db inspector for extending multiple ancient storage](https://github.com/bnb-chain/bsc/pull/1840/commits/60e30a940bbba2c0d26de040195a5ccdb14d8c10)
* [cmd/clef: addlist-accountsandlist-walletsto CLI (#26080)](https://github.com/bnb-chain/bsc/pull/1840/commits/f3a005f176372ff291dfa7c02ee1c87d18e9c788)
* [cmd/clef: add importraw feature to clef (#26058)](https://github.com/bnb-chain/bsc/pull/1840/commits/17744639dafc5a54f21e220660bd39d765a09051)
* [cmd/devp2p: add more nodekey commands (#26129)](https://github.com/bnb-chain/bsc/pull/1840/commits/913973436bb88b652faffc10d8f97e4c19722883)
* [internal/web3ext: fix eth_call stateOverrides in console (#26265)](https://github.com/bnb-chain/bsc/pull/1840/commits/1325fef1025b9feb3342308265b6d1399614be30)
* [cmd/evm: add blocktest subcommand to evm (#26526)](https://github.com/bnb-chain/bsc/pull/1840/commits/90f15a0230be34a292c5d0574ee7910ee44267de)
#### HardFork
* [params: define cancun and prague as timestamp based forks (#26481)](https://github.com/bnb-chain/bsc/pull/1840/commits/f3a005f176372ff291dfa7c02ee1c87d18e9c788)
* [all: tie timestamp based forks to the passage of London (#27279)](https://github.com/bnb-chain/bsc/pull/1840/commits/85a4b82b3373fc5f3fa8b7c68061c55b0db0e9b7)
##### Shanghai
* [core/vm: implement EIP-3855: PUSH0 instruction (#24039)](https://github.com/bnb-chain/bsc/pull/1840/commits/3b967d16caf306ccf8eb78b3a68bec36fa2a52ee)
* [core: implement EIP-3651, warm coinbase (#25819)](https://github.com/bnb-chain/bsc/pull/1840/commits/ec2ec2d08e28571dc189903f743cc3931da254a9)
* [core/vm: implement EIP-3860: Limit and meter initcode (#23847)](https://github.com/bnb-chain/bsc/pull/1840/commits/793f0f9ec860f6f51e0cec943a268c10863097c7)
* [all: implement withdrawals (EIP-4895) (#26484)](https://github.com/bnb-chain/bsc/pull/1840/commits/2a2b0419fb966c54fb86b17bbccea743a45b4d2a)
##### CanCun (almost ready)
* [all: implement EIP-1153 transient storage (#26003)](https://github.com/bnb-chain/bsc/pull/1840/commits/b4ea2bf7dda9def5374ed3ab16a3dfd872eaa40a)
* [core: 4844 opcode and precompile (#27356)](https://github.com/bnb-chain/bsc/pull/1840/commits/c537ace249805903f068c4c66b90558848b49a2f)
* [core/vm: implement EIP-5656, mcopy instruction (#26181)](https://github.com/bnb-chain/bsc/pull/1840/commits/5c9cbc218a67ea6d71652f0d93f4c354a687a965)
* [core/state, core/vm: implement EIP 6780 (#27189)](https://github.com/bnb-chain/bsc/pull/1840/commits/988d84aa7caf8e71ce441fa65f80d44216d9e00e)
#### New Feature
* [eth: introduce eth67 protocol (#24093)](https://github.com/bnb-chain/bsc/pull/1840/commits/30602163d5d8321fbc68afdcbbaf2362b2641bde)
* [eth: implement eth/68 (#25980)](https://github.com/bnb-chain/bsc/pull/1840/commits/b0d44338bbcefee044f1f635a84487cbbd8f0538)
* [PBBS(ready to activate)](https://github.com/ethereum/go-ethereum/commits?author=rjl493456442)
#### P2P
* [eth/fetcher: throttle peers which deliver many invalid transactions (…](https://github.com/bnb-chain/bsc/pull/1840/commits/7f2890a9be1f91368582479f171248b972b45ae3)
#### Build
* [build/bot: add ppa-build.sh (#24919)](https://github.com/bnb-chain/bsc/pull/1840/commits/adcad1cd39ad2bc9ddab67b4bee3023b3e6c9873)
* [more checs in ci](https://github.com/bnb-chain/bsc/pull/1840/files#diff-6179837f7df53a6f05c522b6b7bb566d484d5465d9894fb04910dd08bb40dcc9)
#### Improvement
* [all: use 'embed' instead of go-bindata (#24744)](https://github.com/bnb-chain/bsc/pull/1840/commits/7ab15490e93e6384cfaa233238777ea88a88b8b6)
* [all: move genesis initialization to blockchain (#25523)](https://github.com/bnb-chain/bsc/pull/1840/commits/d10c28030944d1c32febba3f45ae8c175ab34063)
#### Clear Up
* [common/compiler, cmd/abigen: remove solc/vyper compiler integration](https://github.com/bnb-chain/bsc/pull/1840/commits/8541ddbd951370b2a42df8d82b0633ff0efeba12)
* [all: remove concept of public/private API definitions (#25053)](https://github.com/bnb-chain/bsc/pull/1840/commits/10dc5dce0871bf8c24bac41b04e47c3b9ad2b93e)
* [cmd/geth: drop geth js command (#25000)](https://github.com/bnb-chain/bsc/pull/1840/commits/f20a56926551ae91a349498f9ce97c8ee373d6bb)
* [core/genesis: remove calaverasAllocData (#25516)](https://github.com/bnb-chain/bsc/pull/1840/commits/141cd425310b503c5678e674a8c3872cf46b7086)
* [node: drop support for static & trusted node list files (#25610)](https://github.com/bnb-chain/bsc/pull/1840/commits/3630cafb34f7c48b9cc78cf736309275cbd70f74)
* [core: drop legacy receipt types (#26225)](https://github.com/bnb-chain/bsc/pull/1840/commits/10347c6b54d5b28a2e71d9c4993e7f44b0a359c3)
* [cmd/puppeth: remove puppeth](https://github.com/bnb-chain/bsc/pull/1840/commits/8ded6a9fcd883d7d96ef695f5b312c509eae3a0a)
* [cmd, eth, node: deprecate personal namespace (#26390)](https://github.com/bnb-chain/bsc/pull/1840/commits/d0a4989a8def7e6bad182d1513e8d4a093c1672d)
* [accounts, build, mobile: remove Andriod and iOS support](https://github.com/bnb-chain/bsc/pull/1840/commits/d9699c8238307d5c3081c12078f78527468d7dbc)
* [params: remove EIP150Hash from chainconfig (#27087)](https://github.com/bnb-chain/bsc/pull/1840/commits/5e4d726e2a05aee80a75e5f99fd699f220dd503e)
* [all: remove notion of trusted checkpoints in the post-merge world (#2…](https://github.com/bnb-chain/bsc/pull/1840/commits/1e556d220c3a40286dd90b37a08bb5fc659ee6ee)
* [all: remove ethash pow, only retain shims needed for consensus and te](https://github.com/bnb-chain/bsc/pull/1840/commits/dde2da0efb8e9a1812f470bc43254134cd1f8cc0)
* [cmd, core, eth, graphql, trie: no persisted clean trie cache file (#2…](https://github.com/bnb-chain/bsc/pull/1840/commits/59f7b289c329b5a56fa6f4e9acee64e504c4cc0d)
* [les: remove obsolete code related to PoW header syncing (#27737)](https://github.com/bnb-chain/bsc/pull/1840/commits/d4d88f9bce13ca9310bf28f5f26ea9f1915ba90d)
* remove diffsync
#### Others
* [accounts/usbwallet: support Ledger Nano S Plus and FTS (#25933)](https://github.com/bnb-chain/bsc/pull/1840/commits/7eafbec741d124bc53896f6bfc2408b70ab9a82a)
* [accounts/scwallet: fix keycard data signing error (#25331)](https://github.com/bnb-chain/bsc/pull/1840/commits/0c66d971e7f3557df297cbe450fe7fc7826017be)
* [core/state: replace fastcache code cache with gc-friendly structure (…](https://github.com/bnb-chain/bsc/pull/1840/commits/5fded040372784985265f83f33f15cb6a51bebdb)
* [internal/debug: add --log.file option (#26149)](https://github.com/bnb-chain/bsc/pull/1840/commits/5b4c149f97408ecefc7f440e86c12a30c4342620)
* [ci: disable coverage reporting in appveyor and travis](https://github.com/bnb-chain/bsc/pull/1840/commits/a0d63bc69a659009a3884f50c563a0e58483cdd0)
* [all: change chain head markers from block to header (#26777)](https://github.com/bnb-chain/bsc/pull/1840/commits/cd31f2dee2843776e485769ce85e0524716199bc)
* [core, miner: revert block gas counter in case of invalid transaction](https://github.com/bnb-chain/bsc/pull/1840/commits/77e33e5a49be99130a02dc72d6a0e4739fdd44d6)
* [accounts/usbwallet: mitigate ledger app chunking issue (#26773)](https://github.com/bnb-chain/bsc/pull/1840/commits/1e3177de220b1590704c96572fce820bfc87281e)
* [signer/core: accept all solidity primitive types for EIP-712 signing](https://github.com/bnb-chain/bsc/pull/1840/commits/02796f6bee7e014fd16ad39f0bcd3b665b51e0bb)
* [cmd/geth: enable log rotation (#26843)](https://github.com/bnb-chain/bsc/pull/1840/commits/7076ae00aa36ae250608455de928557ce4e5549f)
* [internal/ethapi: make EstimateGas use[latest] block by default (#24363)](https://github.com/bnb-chain/bsc/pull/1840/commits/0b66d47449f61e9ebaf9e1db3ed290b59844d4c1)
* [miner: suspend miner if node is syncing (#27218)](https://github.com/bnb-chain/bsc/pull/1840/commits/d4961881d7c92603f591f9cb8c705d00d8cbdfc0)
* [all: move main transaction pool into a subpool (#27463)](https://github.com/bnb-chain/bsc/pull/1840/commits/d40a255e973775575d8d16456252f93ac75c09f0)
* [core/txpool/blobpool: 4844 blob transaction pool (#26940)](https://github.com/bnb-chain/bsc/pull/1840/commits/1662228ac68325b4024e0cb6a4ce7dde27eb4c2d)
* [eth: send big transactions by announce/retrieve only (#27618)](https://github.com/bnb-chain/bsc/pull/1840/commits/f5d3d486e459dce29130576ae88f2324ad586b50)
* [core/rawdb: support freezer batch read with no size limit (#27687)](https://github.com/bnb-chain/bsc/pull/1840/commits/0b1f97e151e8b34a0a0d528a3472e27de1d12a9c)
* disable pipeCommit, break now
## v1.2.12
FEATURE
* [\#1852](https://github.com/bnb-chain/bsc/pull/1852) discov: add hardcoded bootnodes
BUGFIX
* [\#1844](https://github.com/bnb-chain/bsc/pull/1844) crypto: Update BLST to v0.3.11
* [\#1854](https://github.com/bnb-chain/bsc/pull/1854) fetcher: no import blocks before or equal to the finalized height
* [\#1855](https://github.com/bnb-chain/bsc/pull/1855) eth/tracers: trace system tx should add intrinsicGas
IMPROVEMENT
* [\#1839](https://github.com/bnb-chain/bsc/pull/1839) Update init-network command
* [\#1858](https://github.com/bnb-chain/bsc/pull/1858) vote: check consensus key match vote key before voting
## v1.2.11
FEATURE
* [\#1797](https://github.com/bnb-chain/bsc/pull/1797) client: add FinalizedHeader/Block to use the fast finality

View File

@@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM golang:1.20-alpine as builder
FROM golang:1.21-alpine as builder
RUN apk add --no-cache make cmake gcc musl-dev linux-headers git bash build-base libc-dev
# Get dependencies - will also be cached if we won't change go.mod/go.sum

View File

@@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM golang:1.20-alpine as builder
FROM golang:1.21-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git
# Get dependencies - will also be cached if we won't change go.mod/go.sum

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).
Building `geth` requires both a Go (version 1.19 or later) and a C compiler (GCC 5 or higher). You can install
Building `geth` requires both a Go (version 1.21 or later) and a C compiler (GCC 5 or higher). You can install
them using your favourite package manager. Once the dependencies are installed, run
```shell
@@ -110,15 +110,15 @@ on how you can run your own `geth` instance.
The hardware must meet certain requirements to run a full node on mainnet:
- VPS running recent versions of Mac OS X, Linux, or Windows.
- IMPORTANT 2.5 TB(May 2023) of free disk space, solid-state drive(SSD), gp3, 8k IOPS, 250 MB/S throughput, read latency <1ms. (if node is started with snap sync, it will need NVMe SSD)
- IMPORTANT 3 TB(Dec 2023) of free disk space, solid-state drive(SSD), gp3, 8k IOPS, 500 MB/S throughput, read latency <1ms. (if node is started with snap sync, it will need NVMe SSD)
- 16 cores of CPU and 64 GB of memory (RAM)
- Suggest m5zn.3xlarge instance type on AWS, c2-standard-16 on Google cloud.
- Suggest m5zn.6xlarge or r7iz.4xlarge instance type on AWS, c2-standard-16 on Google cloud.
- A broadband Internet connection with upload/download speeds of 5 MB/S
The requirement for testnet:
- VPS running recent versions of Mac OS X, Linux, or Windows.
- 500G of storage for testnet.
- 4 cores of CPU and 8 gigabytes of memory (RAM).
- 4 cores of CPU and 16 gigabytes of memory (RAM).
### Steps to Run a Fullnode
@@ -149,14 +149,19 @@ unzip testnet.zip
#### 3. Download snapshot
Download latest chaindata snapshot from [here](https://github.com/bnb-chain/bsc-snapshots). Follow the guide to structure your files.
Note: if you can not download the chaindata snapshot and want to sync from genesis, you have to generate the genesis block first, you have already get the genesis.json in Step 2.
So just run: `geth --datadir <datadir> init ./genesis.json`
Note: If you encounter difficulties downloading the chaindata snapshot and prefer to synchronize from the genesis block on the Chapel testnet, remember to include the additional flag `--chapel` when initially launching Geth.
#### 4. Start a full node
```shell
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --txlookuplimit 0
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0
## It is recommand to run fullnode with `--tries-verify-mode none` if you want high performance and care little about state consistency
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --txlookuplimit 0 --tries-verify-mode none
## It will run with Hash-Base Storage Scheme by default
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0 --tries-verify-mode none
## It runs fullnode with Path-Base Storage Scheme.
## It will enable inline state prune, keeping the latest 90000 blocks' history state by default.
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0 --tries-verify-mode none --state.scheme path
```
#### 5. Monitor node status

View File

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

View File

@@ -2127,7 +2127,7 @@ func TestGolangBindings(t *testing.T) {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
}
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.15") // Repo root
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.16") // Repo root
replacer.Dir = pkg
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace tendermint dependency to bnb-chain source: %v\n%s", err, out)
@@ -2145,7 +2145,7 @@ func TestGolangBindings(t *testing.T) {
t.Fatalf("failed to replace cometbft dependency to bnb-chain source: %v\n%s", err, out)
}
tidier := exec.Command(gocmd, "mod", "tidy", "-compat=1.19")
tidier := exec.Command(gocmd, "mod", "tidy", "-compat=1.21")
tidier.Dir = pkg
if out, err := tidier.CombinedOutput(); err != nil {
t.Fatalf("failed to tidy Go module file: %v\n%s", err, out)

View File

@@ -72,11 +72,11 @@ func NewSecureChannelSession(card *pcsc.Card, keyData []byte) (*SecureChannelSes
if err != nil {
return nil, fmt.Errorf("could not unmarshal public key from card: %v", err)
}
secret, _ := key.Curve.ScalarMult(cardPublic.X, cardPublic.Y, key.D.Bytes())
secret, _ := key.Curve.ScalarMult(cardPublic.X, cardPublic.Y, key.D.Bytes()) //nolint:all //TODO
return &SecureChannelSession{
card: card,
secret: secret.Bytes(),
publicKey: elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y),
publicKey: elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y), //nolint:all //TODO
}, nil
}

View File

@@ -1,69 +1,60 @@
# This file contains sha256 checksums of optional build dependencies.
2c5ee9c9ec1e733b0dbbc2bdfed3f62306e51d8172bf38f4f4e542b27520f597 go1.20.7.src.tar.gz
785170eab380a8985d53896808b0a71336d0ea60e0a26099b4ccec77798b1cf4 go1.20.7.darwin-amd64.tar.gz
eea1e7e4c2f75c72629050e6a6c7c46c446d64056732a7787fb3ba16ace1982e go1.20.7.darwin-arm64.tar.gz
d8cff0357ac24eb06f3f280535397eeaacf95611d29f9b2abc3060f3d6dce3b4 go1.20.7.freebsd-386.tar.gz
26918dcebf474a9e81ccf9f648cdf36968dfb76b481518cf615d78455dda4416 go1.20.7.freebsd-amd64.tar.gz
ddb48145f05bda2f4617a22c979d4e94b22802cdb1a1fde1b1974e733b26f091 go1.20.7.linux-386.tar.gz
f0a87f1bcae91c4b69f8dc2bc6d7e6bfcd7524fceec130af525058c0c17b1b44 go1.20.7.linux-amd64.tar.gz
44781ae3b153c3b07651d93b6bc554e835a36e2d72a696281c1e4dad9efffe43 go1.20.7.linux-arm64.tar.gz
7cc231b415b94f2f7065870a73f67dd2b0ec12b5a98052b7ee0121c42bc04f8d go1.20.7.linux-armv6l.tar.gz
6318a1db307c12b8afe68808bd6fae4fba1e558a85b958216096869ed506dcb3 go1.20.7.linux-ppc64le.tar.gz
26aea2ede8722ceecbd9db883328a8d963136fd96c11dacc356c44c4c19c6515 go1.20.7.linux-s390x.tar.gz
5b0ef6f58d3e04d6cc003aa98e9172f41ba9e091b1c98e7339b41c4c87fb78a1 go1.20.7.windows-386.zip
736dc6c7fcab1c96b682c8c93e38d7e371e62a17d34cb2c37d451a1147f66af9 go1.20.7.windows-amd64.zip
fc6f79c1e1ed9e506c65f2112ac4e387479916f1accb0d046a6a19ff6938baa5 go1.20.7.windows-arm64.zip
# version:golang 1.21.5
# https://go.dev/dl/
285cbbdf4b6e6e62ed58f370f3f6d8c30825d6e56c5853c66d3c23bcdb09db19 go1.21.5.src.tar.gz
a2e1d5743e896e5fe1e7d96479c0a769254aed18cf216cf8f4c3a2300a9b3923 go1.21.5.darwin-amd64.tar.gz
d0f8ac0c4fb3efc223a833010901d02954e3923cfe2c9a2ff0e4254a777cc9cc go1.21.5.darwin-arm64.tar.gz
2c05bbe0dc62456b90b7ddd354a54f373b7c377a98f8b22f52ab694b4f6cca58 go1.21.5.freebsd-386.tar.gz
30b6c64e9a77129605bc12f836422bf09eec577a8c899ee46130aeff81567003 go1.21.5.freebsd-amd64.tar.gz
8f4dba9cf5c61757bbd7e9ebdb93b6a30a1b03f4a636a1ba0cc2f27b907ab8e1 go1.21.5.linux-386.tar.gz
e2bc0b3e4b64111ec117295c088bde5f00eeed1567999ff77bc859d7df70078e go1.21.5.linux-amd64.tar.gz
841cced7ecda9b2014f139f5bab5ae31785f35399f236b8b3e75dff2a2978d96 go1.21.5.linux-arm64.tar.gz
837f4bf4e22fcdf920ffeaa4abf3d02d1314e03725431065f4d44c46a01b42fe go1.21.5.linux-armv6l.tar.gz
907b8c6ec4be9b184952e5d3493be66b1746442394a8bc78556c56834cd7c38b go1.21.5.linux-ppc64le.tar.gz
9c4a81b72ebe44368813cd03684e1080a818bf915d84163abae2ed325a1b2dc0 go1.21.5.linux-s390x.tar.gz
6da2418889dfb37763d0eb149c4a8d728c029e12f0cd54fbca0a31ae547e2d34 go1.21.5.windows-386.zip
bbe603cde7c9dee658f45164b4d06de1eff6e6e6b800100824e7c00d56a9a92f go1.21.5.windows-amd64.zip
9b7acca50e674294e43202df4fbc26d5af4d8bc3170a3342a1514f09a2dab5e9 go1.21.5.windows-arm64.zip
000d4d58f1e25323aaf0da20b337d059d401c8c1fb31cef92ce50ef35c05e877 golangci-lint-1.52.2-linux-ppc64le.deb
0970b2e3ecc20003a0fc78b078623ab27c61f0f809a44288e2cc438bfbbf5616 golangci-lint-1.52.2-linux-s390x.deb
0bfe9b51f68a33cc4e43139151d8032b57b15e61a19f5a7554b687a3fa166ab8 golangci-lint-1.52.2-netbsd-armv7.tar.gz
0e4e24085d364f4e03752c060d5f37b5ead52acd62f07392f4c9022515e0ecd8 golangci-lint-1.52.2-linux-armv7.rpm
0f19ad6c037d45867f4978287a7a6d78bc761daf8e6cb3a5e6af86d5714b0258 golangci-lint-1.52.2-linux-armv6.tar.gz
1506b19f3f0410f6d85d1e339a47fcc84646d552516c0f429dc8cd7f34b4069a golangci-lint-1.52.2-windows-armv6.zip
1cc68baa226e186c15c5514a6e93b1cc8d47ff06aaf1a395b8266434cb01df29 golangci-lint-1.52.2-linux-386.rpm
1d23661087ae686563e40d3b1e33f309dd3b4ba7d1c7e571ca7723f77a52a9e4 golangci-lint-1.52.2-linux-s390x.rpm
227673a18d21b428f1768bb8ee46e38c36a0f002960bc6211ef6137b85d03f52 golangci-lint-1.52.2-freebsd-armv7.tar.gz
24f0272e5741c05c59e7162b7ff0258cfa6beb0d9265bd87c386fe80ac25135d golangci-lint-1.52.2-linux-mips64.deb
3abc8ad30b336ccbe3c5e3c65fa146f5b12d8e81e644345fa8d51cdbaa8cb570 golangci-lint-1.52.2-netbsd-amd64.tar.gz
40a2645b4c7bd94c16618eb0f12b32cd54c17e5620f761cf477b256d3622f299 golangci-lint-1.52.2-windows-386.zip
40b40002e07db81628d94108265525052c58fc9ce358bef26a36d27f0aea3d87 golangci-lint-1.52.2-windows-amd64.zip
41e936b62ba4fc66c02daf6fa9cf74213bc2220745c7a796acbe197c05ed26bb golangci-lint-1.52.2-netbsd-armv6.tar.gz
4bcbb4cf34bf3c8ae1ca880d12516a999499189326621599f8362ededd6e4229 golangci-lint-1.52.2-linux-riscv64.tar.gz
4edb83f1433f7c57f06f79a7fc30bf3f920c1f86c334e481661ac6627d80293f golangci-lint-1.52.2-linux-arm64.deb
50d662e86d094dbad6634d086eca4f670ffa8ea7142508d8da357a2d750ac21a golangci-lint-1.52.2-linux-armv7.tar.gz
6891597bedbcd7e530d08ed198bab7eeb9b23f3f8161dc6e87505b783cb11593 golangci-lint-1.52.2-windows-arm64.zip
6d79f4f3448b70e83952e746fcb9e251c6ba94ec2790a912806cc1704ade4d64 golangci-lint-1.52.2-linux-mips64.rpm
6de51ae05d39002421caf6049e0dd0014a2f10961471c5547c905d33d8e6adf1 golangci-lint-1.52.2-linux-armv6.deb
715dc0f0cf3538c3b2c75f084dde8dcdc3485b3494f42a6d0d9c0dc61e62b5a8 golangci-lint-1.52.2-linux-s390x.tar.gz
7c559332a97ee49b80427aba5a7122e17cac18c57e700f48e6db5ffcbbb61b2b golangci-lint-1.52.2-linux-arm64.rpm
81201bb5f19897fefb4380af2e187a0133dc5efda22254698c063cc36a601f43 golangci-lint-1.52.2-linux-386.deb
89e523d45883903cfc472ab65621073f850abd4ffbb7720bbdd7ba66ee490bc8 golangci-lint-1.52.2-darwin-arm64.tar.gz
8d60d63eee38f8de679e57b1a781de32987152f004f852f20cd47baa4c582209 golangci-lint-1.52.2-linux-mips64le.rpm
9e22df0516cbd847910f353d92245e58eab2b6edacc669646bfa06eb032a65a3 golangci-lint-1.52.2-linux-riscv64.deb
a1a74747a196d4ccd2394ea8a461508eb2edf1eb5a88010611debf572991961d golangci-lint-1.52.2-linux-loong64.tar.gz
a7f076d0fb50e0f5bc24d0f3b2567f2cfe864441e6ad20323189b7fde7cc065d golangci-lint-1.52.2-freebsd-386.tar.gz
abc100851a59cbcea2a7e9ff5ad2974a43270135520aeac9a302ca6c712a41e1 golangci-lint-1.52.2-linux-loong64.rpm
adf11a1f7f43b5a431c19cccea260e6205e2e2b42a2d2d450e31c287fec199f2 golangci-lint-1.52.2-linux-amd64.rpm
b2249e43e1624486398f41700dbe4094a4222bf50b2b1b3a740323adb9a1b66f golangci-lint-1.52.2-linux-386.tar.gz
b8e81bf979dc8bf226cb592eb78c1792f1018c3dea1bbeb11517efc4cc3301bb golangci-lint-1.52.2-windows-armv7.zip
bb9a6a0aabe39fb3d581cc200c639ce6598821a53b4d16ec59366c65f4cc2960 golangci-lint-1.52.2-source.tar.gz
c152280b2e61c202614c1c476cf4458922cda0d2781e4492be2c22d45655cae0 golangci-lint-1.52.2-freebsd-armv6.tar.gz
c8bf25c0bca142638ce4bfc921bf23d23038818d57658d69aa4a9947d514d48f golangci-lint-1.52.2-linux-ppc64le.rpm
c9cf72d12058a131746edd409ed94ccd578fbd178899d1ed41ceae3ce5f54501 golangci-lint-1.52.2-linux-amd64.tar.gz
d03f2b331b5139eddea5db2b49066d10a90094747b08d72d7b2d61cf91c79a27 golangci-lint-1.52.2-linux-mips64le.tar.gz
d609c1d49591d714148e1f8c8b5ae9f9565c601aeabc44a5a53ba44b0eb99f36 golangci-lint-1.52.2-linux-riscv64.rpm
d679adad29603ed7549372b64077cccad784e404deffe5c1e9495a06659cff33 golangci-lint-1.52.2-linux-mips64.tar.gz
d91e8cb60920cf0e46958ed917fcdd059738c00d162189c2e878424ffc8ada75 golangci-lint-1.52.2-linux-ppc64le.tar.gz
d9b5820b491e317fb1360775441d68bd3dc2f303439da5b6d536df23977e28c9 golangci-lint-1.52.2-freebsd-amd64.tar.gz
ddeae781cf07c016898efd80eaed6853a91bfaf1f22c08fbbf5cf08a573b98c4 golangci-lint-1.52.2-linux-loong64.deb
dfc5e755cfa95381f61f736780ff736a5b6c9cbccc88140348986c166d484f85 golangci-lint-1.52.2-linux-amd64.deb
e57f2599de73c4da1d36d5255b9baec63f448b3d7fb726ebd3cd64dabbd3ee4a golangci-lint-1.52.2-darwin-amd64.tar.gz
ebfb5b643ba73ef6007236b90f863ae49fc34fd366682c971b7d1308ab28f642 golangci-lint-1.52.2-netbsd-386.tar.gz
f46b60a90fab5916a7de899ad9a3a4b3d77278c2e1737d070719d3ea27919557 golangci-lint-1.52.2-linux-armv7.deb
f6e39d0ac4691c2b9f49d6d5819594f48bb03e18692fd6d100e7114077f710e6 golangci-lint-1.52.2-linux-armv6.rpm
fa5da589075143628a49a0c123ccd76a8717bb6308fb3bdb6bf1df59435d921b golangci-lint-1.52.2-linux-mips64le.deb
fc09a97f8888809fab83a316f7da70c8ed74d4863b7eed7d872cec41911a55e8 golangci-lint-1.52.2-linux-arm64.tar.gz
# version:golangci 1.55.2
# https://github.com/golangci/golangci-lint/releases/
# https://github.com/golangci/golangci-lint/releases/download/v1.55.2/
632e96e6d5294fbbe7b2c410a49c8fa01c60712a0af85a567de85bcc1623ea21 golangci-lint-1.55.2-darwin-amd64.tar.gz
234463f059249f82045824afdcdd5db5682d0593052f58f6a3039a0a1c3899f6 golangci-lint-1.55.2-darwin-arm64.tar.gz
2bdd105e2d4e003a9058c33a22bb191a1e0f30fa0790acca0d8fbffac1d6247c golangci-lint-1.55.2-freebsd-386.tar.gz
e75056e8b082386676ce23eba455cf893931a792c0d87e1e3743c0aec33c7fb5 golangci-lint-1.55.2-freebsd-amd64.tar.gz
5789b933facaf6136bd23f1d50add67b79bbcf8dfdfc9069a37f729395940a66 golangci-lint-1.55.2-freebsd-armv6.tar.gz
7f21ab1008d05f32c954f99470fc86a83a059e530fe2add1d0b7d8ed4d8992a7 golangci-lint-1.55.2-freebsd-armv7.tar.gz
33ab06139b9219a28251f10821da94423db30285cc2af97494cbb2a281927de9 golangci-lint-1.55.2-illumos-amd64.tar.gz
57ce6f8ce3ad6ee45d7cc3d9a047545a851c2547637834a3fcb086c7b40b1e6b golangci-lint-1.55.2-linux-386.tar.gz
ca21c961a33be3bc15e4292dc40c98c8dcc5463a7b6768a3afc123761630c09c golangci-lint-1.55.2-linux-amd64.tar.gz
8eb0cee9b1dbf0eaa49871798c7f8a5b35f2960c52d776a5f31eb7d886b92746 golangci-lint-1.55.2-linux-arm64.tar.gz
3195f3e0f37d353fd5bd415cabcd4e263f5c29d3d0ffb176c26ff3d2c75eb3bb golangci-lint-1.55.2-linux-armv6.tar.gz
c823ee36eb1a719e171de1f2f5ca3068033dce8d9817232fd10ed71fd6650406 golangci-lint-1.55.2-linux-armv7.tar.gz
758a5d2a356dc494bd13ed4c0d4bf5a54a4dc91267ea5ecdd87b86c7ca0624e7 golangci-lint-1.55.2-linux-loong64.tar.gz
2c7b9abdce7cae802a67d583cd7c6dca520bff6d0e17c8535a918e2f2b437aa0 golangci-lint-1.55.2-linux-mips64.tar.gz
024e0a15b85352cc27271285526e16a4ab66d3e67afbbe446c9808c06cb8dbed golangci-lint-1.55.2-linux-mips64le.tar.gz
6b00f89ba5506c1de1efdd9fa17c54093013a294fefd8b9b31534db626a672ee golangci-lint-1.55.2-linux-ppc64le.tar.gz
0faa0d047d9bf7b703ed3ea65b6117043c93504f9ca1de25ae929d3901c73d4a golangci-lint-1.55.2-linux-riscv64.tar.gz
30dec9b22e7d5bb4e9d5ccea96da20f71cd7db3c8cf30b8ddc7cb9174c4d742a golangci-lint-1.55.2-linux-s390x.tar.gz
5a0ede48f79ad707902fdb29be8cd2abd8302dc122b65ebae3fdfc86751c7698 golangci-lint-1.55.2-netbsd-386.tar.gz
95af20a2e617126dd5b08122ece7819101070e1582a961067ce8c41172f901ad golangci-lint-1.55.2-netbsd-amd64.tar.gz
94fb7dacb7527847cc95d7120904e19a2a0a81a0d50d61766c9e0251da72ab9d golangci-lint-1.55.2-netbsd-armv6.tar.gz
ca906bce5fee9619400e4a321c56476fe4a4efb6ac4fc989d340eb5563348873 golangci-lint-1.55.2-netbsd-armv7.tar.gz
45b442f69fc8915c4500201c0247b7f3f69544dbc9165403a61f9095f2c57355 golangci-lint-1.55.2-windows-386.zip
f57d434d231d43417dfa631587522f8c1991220b43c8ffadb9c7bd279508bf81 golangci-lint-1.55.2-windows-amd64.zip
fd7dc8f4c6829ee6fafb252a4d81d2155cd35da7833665cbb25d53ce7cecd990 golangci-lint-1.55.2-windows-arm64.zip
1892c3c24f9e7ef44b02f6750c703864b6dc350129f3ec39510300007b2376f1 golangci-lint-1.55.2-windows-armv6.zip
a5e68ae73d38748b5269fad36ac7575e3c162a5dc63ef58abdea03cc5da4522a golangci-lint-1.55.2-windows-armv7.zip
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz
#
# This version is fine to be old and full of security holes, we just use it
# to build the latest Go. Don't change it. If it ever becomes insufficient,
# we need to switch over to a recursive builder to jump across supported
# versions.
#
# version:ppa-builder 1.19.6
# https://go.dev/dl/
d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz

View File

@@ -139,7 +139,7 @@ var (
// This is the version of Go that will be downloaded by
//
// go run ci.go install -dlgo
dlgoVersion = "1.20.7"
dlgoVersion = "1.21.5"
// This is the version of Go that will be used to bootstrap the PPA builder.
//
@@ -333,10 +333,7 @@ func doTest(cmdline []string) {
gotest.Args = append(gotest.Args, "-race")
}
packages := []string{"./accounts/...", "./cmd/geth/...", "./common/...", "./consensus/...", "./console/...",
"./core/...", "./crypto/...", "./eth/...", "./ethstats/...", "./ethclient/...", "./ethdb/...", "./event/...",
"./graphql/...", "./internal/...", "./les/...", "./light/...", "./log/...", "./metrics/...", "./miner/...",
"./node/...", "./p2p/...", "./params/...", "./rlp/...", "./rpc/...", "./signer/...", "./tests/...", "./trie/..."}
packages := []string{"./..."}
if len(flag.CommandLine.Args()) > 0 {
packages = flag.CommandLine.Args()
}
@@ -363,7 +360,7 @@ func doLint(cmdline []string) {
// downloadLinter downloads and unpacks golangci-lint.
func downloadLinter(cachedir string) string {
const version = "1.52.2"
const version = "1.55.2"
csdb := build.MustLoadChecksums("build/checksums.txt")
arch := runtime.GOARCH

View File

@@ -1206,7 +1206,7 @@ func GenDoc(ctx *cli.Context) error {
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
- `-ip <CIDR>` filters nodes by IP subnet
- `-min-age <duration>` filters nodes by 'first seen' time
- `-eth-network <mainnet/goerli/sepolia>` filters nodes by "eth" ENR entry
- `-eth-network <mainnet/goerli/sepolia/holesky>` filters nodes by "eth" ENR entry
- `-les-server` filters nodes by LES server support
- `-snap` filters nodes by snap protocol support

View File

@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/internal/utesting"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/rlpx"
)
@@ -202,6 +203,29 @@ loop:
if err := c.Write(status); err != nil {
return nil, fmt.Errorf("write to connection failed: %v", err)
}
// exchange UpgradeStatus
if c.negotiatedProtoVersion >= eth.ETH67 {
extensionRaw, _ := (&eth.UpgradeStatusExtension{}).Encode()
upgradeStatus := UpgradeStatus{
Extension: extensionRaw,
}
if err := c.Write(upgradeStatus); err != nil {
return nil, fmt.Errorf("write to connection failed: %v", err)
}
switch msg := c.Read().(type) {
case *UpgradeStatus:
log.Debug("receive UpgradeStatus")
case *Disconnect:
return nil, fmt.Errorf("disconnect received: %v", msg.Reason)
case *Ping:
c.Write(&Pong{}) // TODO (renaynay): in the future, this should be an error
// (PINGs should not be a response upon fresh connection)
default:
return nil, fmt.Errorf("bad status message: %s", pretty.Sdump(msg))
}
}
return message, nil
}

View File

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

View File

@@ -80,10 +80,11 @@ func TestSnapSuite(t *testing.T) {
func runGeth() (*node.Node, error) {
stack, err := node.New(&node.Config{
P2P: p2p.Config{
ListenAddr: "127.0.0.1:0",
NoDiscovery: true,
MaxPeers: 10, // in case a test requires multiple connections, can be changed in the future
NoDial: true,
ListenAddr: "127.0.0.1:0",
NoDiscovery: true,
MaxPeers: 10, // in case a test requires multiple connections, can be changed in the future
MaxPeersPerIP: 10,
NoDial: true,
},
})
if err != nil {
@@ -116,6 +117,7 @@ func setupGeth(stack *node.Node) error {
TrieDirtyCache: 16,
TrieTimeout: 60 * time.Minute,
SnapshotCache: 10,
TriesInMemory: 128,
})
if err != nil {
return err

View File

@@ -87,6 +87,11 @@ type Status eth.StatusPacket
func (msg Status) Code() int { return 16 }
func (msg Status) ReqID() uint64 { return 0 }
type UpgradeStatus eth.UpgradeStatusPacket
func (msg UpgradeStatus) Code() int { return 27 } // p2p.baseProtocolLength + eth.UpgradeStatusMsg
func (msg UpgradeStatus) ReqID() uint64 { return 0 }
// NewBlockHashes is the network packet for the block announcements.
type NewBlockHashes eth.NewBlockHashesPacket
@@ -179,6 +184,8 @@ func (c *Conn) Read() Message {
msg = new(Disconnect)
case (Status{}).Code():
msg = new(Status)
case (UpgradeStatus{}).Code():
msg = new(UpgradeStatus)
case (GetBlockHeaders{}).Code():
ethMsg := new(eth.GetBlockHeadersPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {

View File

@@ -22,6 +22,7 @@ import (
"fmt"
"os"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/log"
@@ -64,7 +65,7 @@ func blockTestCmd(ctx *cli.Context) error {
return err
}
for i, test := range tests {
if err := test.Run(false, tracer); err != nil {
if err := test.Run(false, rawdb.HashScheme, tracer); err != nil {
return fmt.Errorf("test %v: %w", i, err)
}
}

View File

@@ -42,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/urfave/cli/v2"
)
@@ -142,12 +143,23 @@ func runCmd(ctx *cli.Context) error {
gen := readGenesis(ctx.String(GenesisFlag.Name))
genesisConfig = gen
db := rawdb.NewMemoryDatabase()
genesis := gen.MustCommit(db)
sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: preimages})
triedb := trie.NewDatabase(db, &trie.Config{
Preimages: preimages,
HashDB: hashdb.Defaults,
})
defer triedb.Close()
genesis := gen.MustCommit(db, triedb)
sdb := state.NewDatabaseWithNodeDB(db, triedb)
statedb, _ = state.New(genesis.Root(), sdb, nil)
chainConfig = gen.Config
} else {
sdb := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: preimages})
db := rawdb.NewMemoryDatabase()
triedb := trie.NewDatabase(db, &trie.Config{
Preimages: preimages,
HashDB: hashdb.Defaults,
})
defer triedb.Close()
sdb := state.NewDatabaseWithNodeDB(db, triedb)
statedb, _ = state.New(types.EmptyRootHash, sdb, nil)
genesisConfig = new(core.Genesis)
}

View File

@@ -23,7 +23,9 @@ import (
"os"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/log"
@@ -104,25 +106,22 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
for _, st := range test.Subtests() {
// Run the test and aggregate the result
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
_, s, err := test.Run(st, cfg, false)
// print state root for evmlab tracing
if s != nil {
root := s.IntermediateRoot(false)
result.Root = &root
if jsonOut {
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
if err != nil {
// Test failed, mark as so and dump any state to aid debugging
result.Pass, result.Error = false, err.Error()
if dump {
dump := state.RawDump(nil)
result.State = &dump
}
} else {
root := state.IntermediateRoot(false)
result.Root = &root
if jsonOut {
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
}
}
}
if err != nil {
// Test failed, mark as so and dump any state to aid debugging
result.Pass, result.Error = false, err.Error()
if dump && s != nil {
s, _ = state.New(*result.Root, s.Database(), nil)
dump := s.RawDump(nil)
result.State = &dump
}
}
})
results = append(results, *result)
}
}

View File

@@ -243,14 +243,17 @@ func TestT8n(t *testing.T) {
output: t8nOutput{alloc: false, result: false},
expExitCode: 3,
},
{ // Test base fee calculation
base: "./testdata/25",
input: t8nInput{
"alloc.json", "txs.json", "env.json", "Merge", "",
// base fee logic is different with go-ethereum
/*
{ // Test base fee calculation
base: "./testdata/25",
input: t8nInput{
"alloc.json", "txs.json", "env.json", "Merge", "",
},
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
*/
{ // Test withdrawals transition
base: "./testdata/26",
input: t8nInput{
@@ -259,14 +262,17 @@ func TestT8n(t *testing.T) {
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
{ // Cancun tests
base: "./testdata/28",
input: t8nInput{
"alloc.json", "txs.rlp", "env.json", "Cancun", "",
// TODO(Nathan): Cancun not ready
/*
{ // Cancun tests
base: "./testdata/28",
input: t8nInput{
"alloc.json", "txs.rlp", "env.json", "Cancun", "",
},
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
*/
} {
args := []string{"t8n"}
args = append(args, tc.output.get()...)

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:
- `-genesis` is a path to a file containing the network `genesis.json`. or using:
- `-network` is the devp2p network id used during connection
- `-bootnodes` is a list of `enode://` ids to join the network through
The `faucet` will use the `les` protocol to join the configured Ethereum network and will store its data in `$HOME/.faucet` (currently not configurable).
- `-ws` is ws endpoint to what faucet will connect to
## Funding

View File

@@ -42,21 +42,11 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethstats"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/params"
"github.com/gorilla/websocket"
)
@@ -64,10 +54,7 @@ import (
var (
genesisFlag = flag.String("genesis", "", "Genesis json file to seed the chain with")
apiPortFlag = flag.Int("apiport", 8080, "Listener port for the HTTP API connection")
ethPortFlag = flag.Int("ethport", 30303, "Listener port for the devp2p connection")
bootFlag = flag.String("bootnodes", "", "Comma separated bootnode enode URLs to seed with")
netFlag = flag.Uint64("network", 0, "Network ID to use for the Ethereum protocol")
statsFlag = flag.String("ethstats", "", "Ethstats network monitoring auth string")
wsEndpoint = flag.String("ws", "http://127.0.0.1:7777/", "Url to ws endpoint")
netnameFlag = flag.String("faucet.name", "", "Network name to assign to the faucet")
payoutFlag = flag.Int("faucet.amount", 1, "Number of Ethers to pay out per user request")
@@ -163,15 +150,6 @@ func main() {
if err != nil {
log.Crit("Failed to read genesis block contents", "genesis", *genesisFlag, "err", err)
}
// Convert the bootnodes to internal enode representations
var enodes []*enode.Node
for _, boot := range strings.Split(*bootFlag, ",") {
if url, err := enode.Parse(enode.ValidSchemes, boot); err == nil {
enodes = append(enodes, url)
} else {
log.Error("Failed to parse bootnode URL", "url", boot, "err", err)
}
}
// Load up the account key and decrypt its password
blob, err := os.ReadFile(*accPassFlag)
if err != nil {
@@ -191,7 +169,7 @@ func main() {
log.Crit("Failed to unlock faucet signer account", "err", err)
}
// Assemble and start the faucet light service
faucet, err := newFaucet(genesis, *ethPortFlag, enodes, *netFlag, *statsFlag, ks, website.Bytes(), bep2eInfos)
faucet, err := newFaucet(genesis, *wsEndpoint, ks, website.Bytes(), bep2eInfos)
if err != nil {
log.Crit("Failed to start faucet", "err", err)
}
@@ -219,7 +197,6 @@ type bep2eInfo struct {
// faucet represents a crypto faucet backed by an Ethereum light client.
type faucet struct {
config *params.ChainConfig // Chain configurations for signing
stack *node.Node // Ethereum protocol stack
client *ethclient.Client // Client connection to the Ethereum chain
index []byte // Index page to serve up on the web
@@ -248,65 +225,18 @@ type wsConn struct {
wlock sync.Mutex
}
func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) {
// Assemble the raw devp2p protocol stack
git, _ := version.VCS()
stack, err := node.New(&node.Config{
Name: "geth",
Version: params.VersionWithCommit(git.Commit, git.Date),
DataDir: filepath.Join(os.Getenv("HOME"), ".faucet"),
NoUSB: true,
P2P: p2p.Config{
NAT: nat.Any(),
NoDiscovery: true,
DiscoveryV5: true,
ListenAddr: fmt.Sprintf(":%d", port),
MaxPeers: 25,
BootstrapNodesV5: enodes,
},
})
if err != nil {
return nil, err
}
func newFaucet(genesis *core.Genesis, url string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) {
bep2eAbi, err := abi.JSON(strings.NewReader(bep2eAbiJson))
if err != nil {
return nil, err
}
// Assemble the Ethereum light client protocol
cfg := ethconfig.Defaults
cfg.SyncMode = downloader.LightSync
cfg.NetworkId = network
cfg.Genesis = genesis
utils.SetDNSDiscoveryDefaults(&cfg, genesis.ToBlock().Hash())
lesBackend, err := les.New(stack, &cfg)
client, err := ethclient.Dial(url)
if err != nil {
return nil, fmt.Errorf("Failed to register the Ethereum service: %w", err)
}
// Assemble the ethstats monitoring and reporting service'
if stats != "" {
if err := ethstats.New(stack, lesBackend.ApiBackend, lesBackend.Engine(), stats); err != nil {
return nil, err
}
}
// Boot up the client and ensure it connects to bootnodes
if err := stack.Start(); err != nil {
return nil, err
}
for _, boot := range enodes {
old, err := enode.Parse(enode.ValidSchemes, boot.String())
if err == nil {
stack.Server().AddPeer(old)
}
}
// Attach to the client and retrieve and interesting metadatas
api := stack.Attach()
client := ethclient.NewClient(api)
return &faucet{
config: genesis.Config,
stack: stack,
client: client,
index: index,
keystore: ks,
@@ -319,8 +249,8 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network ui
}
// close terminates the Ethereum connection and tears down the faucet.
func (f *faucet) close() error {
return f.stack.Close()
func (f *faucet) close() {
f.client.Close()
}
// listenAndServe registers the HTTP handlers for the faucet and boots it up
@@ -342,7 +272,7 @@ func (f *faucet) webHandler(w http.ResponseWriter, r *http.Request) {
// apiHandler handles requests for Ether grants and transaction statuses.
func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
upgrader := websocket.Upgrader{}
upgrader := websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
@@ -406,7 +336,6 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
if err = send(wsconn, map[string]interface{}{
"funds": new(big.Int).Div(balance, ether),
"funded": nonce,
"peers": f.stack.Server().PeerCount(),
"requests": reqs,
}, 3*time.Second); err != nil {
log.Warn("Failed to send initial stats to client", "err", err)
@@ -694,13 +623,11 @@ func (f *faucet) loop() {
log.Info("Updated faucet state", "number", head.Number, "hash", head.Hash(), "age", common.PrettyAge(timestamp), "balance", f.balance, "nonce", f.nonce, "price", f.price)
balance := new(big.Int).Div(f.balance, ether)
peers := f.stack.Server().PeerCount()
for _, conn := range f.conns {
if err := send(conn, map[string]interface{}{
"funds": balance,
"funded": f.nonce,
"peers": peers,
"requests": f.reqs,
}, time.Second); err != nil {
log.Warn("Failed to send stats to client", "err", err)

View File

@@ -5,6 +5,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"os"
"path/filepath"
"strings"
@@ -14,7 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/io/prompt"
"github.com/prysmaticlabs/prysm/v4/proto/eth/service"
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v4/validator/accounts"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/petnames"
@@ -26,6 +27,8 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/signer/core"
)
@@ -35,19 +38,20 @@ const (
)
var (
au = aurora.NewAurora(true)
privateKeyFlag = &cli.StringFlag{
Name: "private-key",
Usage: "Hex string for the BLS12-381 private key you wish encrypt into a keystore file",
Value: "",
}
au = aurora.NewAurora(true)
showPrivateKeyFlag = &cli.BoolFlag{
Name: "show-private-key",
Usage: "Show the BLS12-381 private key you will encrypt into a keystore file",
Name: "show-private-key",
Usage: "Show the BLS12-381 private key you will encrypt into a keystore file",
Category: flags.AccountCategory,
}
BLSAccountPasswordFileFlag = &cli.StringFlag{
Name: "blsaccountpassword",
Usage: "File path for the BLS account password, which contains the password to encrypt private key into keystore file for managing votes in fast_finality feature",
importedAccountPasswordFileFlag = &cli.StringFlag{
Name: "importedaccountpassword",
Usage: "Password file path for the imported BLS account , which contains the password to get the private key by decrypting the keystore file",
Category: flags.AccountCategory,
}
chainIdFlag = &cli.Int64Flag{
Name: "chain-id",
Usage: "The chain id of the network that the validator will be created at",
}
)
@@ -130,10 +134,8 @@ Make sure you backup your BLS keys regularly.`,
Category: "BLS ACCOUNT COMMANDS",
Flags: []cli.Flag{
utils.DataDirFlag,
privateKeyFlag,
showPrivateKeyFlag,
utils.BLSPasswordFileFlag,
BLSAccountPasswordFileFlag,
},
Description: `
geth bls account new
@@ -149,17 +151,17 @@ You must remember this password to unlock your account in the future.`,
Name: "import",
Usage: "Import a BLS account",
Action: blsAccountImport,
ArgsUsage: "<keystore file>",
ArgsUsage: "<keyFile>",
Category: "BLS ACCOUNT COMMANDS",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.BLSPasswordFileFlag,
BLSAccountPasswordFileFlag,
importedAccountPasswordFileFlag,
},
Description: `
geth bls account import <keyFile>
Import a encrypted BLS account from keystore file <keyFile> into the BLS wallet.
Import a encrypted BLS account or a BLS12-381 private key from file <keyFile> into the BLS wallet.
If the BLS wallet not created yet, it will try to create BLS wallet first.`,
},
@@ -193,6 +195,22 @@ Print summary of existing BLS accounts in the current BLS wallet.`,
Delete the selected BLS account from the BLS wallet.`,
},
{
Name: "generate-proof",
Usage: "Generate ownership proof for the selected BLS account from the BLS wallet",
Action: blsAccountGenerateProof,
ArgsUsage: "<BLS pubkey>",
Category: "BLS ACCOUNT COMMANDS",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.BLSPasswordFileFlag,
chainIdFlag,
},
Description: `
geth bls account generate-proof
Generate ownership proof for the selected BLS account from the BLS wallet. The proof is used to prove the ownership of the BLS account when creating validator on BSC after feynman upgrade.`,
},
},
},
},
@@ -219,7 +237,10 @@ func blsWalletCreate(ctx *cli.Context) error {
utils.Fatalf("BLS wallet already exists in <DATADIR>/bls/wallet.")
}
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, GetBLSPassword(ctx))
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
if err := core.ValidatePasswordFormat(password); err != nil {
utils.Fatalf("Password invalid: %v.", err)
}
opts := []accounts.Option{}
opts = append(opts, accounts.WithWalletDir(dir))
@@ -249,7 +270,10 @@ func openOrCreateBLSWallet(ctx *cli.Context, cfg *gethConfig) (*wallet.Wallet, e
}
if !dirExists {
fmt.Println("BLS wallet not exists, creating BLS wallet...")
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, GetBLSPassword(ctx))
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
if err := core.ValidatePasswordFormat(password); err != nil {
utils.Fatalf("Password invalid: %v.", err)
}
opts := []accounts.Option{}
opts = append(opts, accounts.WithWalletDir(walletDir))
@@ -269,7 +293,7 @@ func openOrCreateBLSWallet(ctx *cli.Context, cfg *gethConfig) (*wallet.Wallet, e
return w, nil
}
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
w, err = wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: walletDir,
WalletPassword: walletPassword,
@@ -309,27 +333,11 @@ func blsAccountCreate(ctx *cli.Context) error {
if err := os.MkdirAll(keystoreDir, 0755); err != nil {
utils.Fatalf("Could not access keystore dir: %v.", err)
}
accountPassword := utils.GetPassPhraseWithList("Your new BLS account will be encrypted with a password. Please give a password. Do not forget this password.", true, 0, GetBLSAccountPassword(ctx))
if err := core.ValidatePasswordFormat(accountPassword); err != nil {
utils.Fatalf("Password invalid: %v.", err)
}
accountPassword := w.Password()
encryptor := keystorev4.New()
secretKey, err := bls.RandKey()
privateKeyString := ctx.String(privateKeyFlag.Name)
if privateKeyString != "" {
if len(privateKeyString) > 2 && strings.Contains(privateKeyString, "0x") {
privateKeyString = privateKeyString[2:] // Strip the 0x prefix, if any.
}
bytesValue, err := hex.DecodeString(privateKeyString)
if err != nil {
utils.Fatalf("could not decode as hex string: %s", privateKeyString)
}
secretKey, err = bls.SecretKeyFromBytes(bytesValue)
if err != nil {
utils.Fatalf("not a valid BLS12-381 private key")
}
} else if err != nil {
if err != nil {
utils.Fatalf("Could not generate BLS secret key: %v.", err)
}
@@ -383,22 +391,6 @@ func blsAccountCreate(ctx *cli.Context) error {
// blsAccountImport imports a BLS account into the BLS wallet.
func blsAccountImport(ctx *cli.Context) error {
keyfile := ctx.Args().First()
if len(keyfile) == 0 {
utils.Fatalf("The keystore file must be given as argument.")
}
keyJSON, err := os.ReadFile(keyfile)
if err != nil {
utils.Fatalf("Could not read keystore file: %v", err)
}
keystore := &keymanager.Keystore{}
if err := json.Unmarshal(keyJSON, keystore); err != nil {
utils.Fatalf("Could not decode keystore file: %v.", err)
}
if keystore.Pubkey == "" {
utils.Fatalf(" Missing public key, wrong keystore file.")
}
cfg := gethConfig{Node: defaultNodeConfig()}
// Load config file.
if file := ctx.String(configFileFlag.Name); file != "" {
@@ -421,19 +413,59 @@ func blsAccountImport(ctx *cli.Context) error {
utils.Fatalf("The BLS keymanager cannot import keystores")
}
password := utils.GetPassPhraseWithList("Enter the password for your imported account.", false, 0, GetBLSAccountPassword(ctx))
keyfile := ctx.Args().First()
if len(keyfile) == 0 {
utils.Fatalf("The keystore file must be given as argument.")
}
keyInfo, err := os.ReadFile(keyfile)
if err != nil {
utils.Fatalf("Could not read keystore file: %v", err)
}
keystore := &keymanager.Keystore{}
var importedAccountPassword string
if err := json.Unmarshal(keyInfo, keystore); err != nil {
secretKey, err := bls.SecretKeyFromBytes(common.FromHex(strings.TrimRight(string(keyInfo), "\r\n")))
if err != nil {
utils.Fatalf("keyFile is neither a keystore file or include a valid BLS12-381 private key: %v.", err)
}
pubKeyBytes := secretKey.PublicKey().Marshal()
encryptor := keystorev4.New()
importedAccountPassword = w.Password()
cryptoFields, err := encryptor.Encrypt(secretKey.Marshal(), importedAccountPassword)
if err != nil {
utils.Fatalf("Could not encrypt secret key: %v.", err)
}
id, err := uuid.NewRandom()
if err != nil {
utils.Fatalf("Could not generate uuid: %v.", err)
}
keystore = &keymanager.Keystore{
Crypto: cryptoFields,
ID: id.String(),
Pubkey: fmt.Sprintf("%x", pubKeyBytes),
Version: encryptor.Version(),
Name: encryptor.Name(),
}
}
if keystore.Pubkey == "" {
utils.Fatalf(" Missing public key, wrong keystore file.")
}
if importedAccountPassword == "" {
importedAccountPassword = utils.GetPassPhraseWithList("Enter the password for your imported account.", false, 0, utils.MakePasswordListFromPath(ctx.String(importedAccountPasswordFileFlag.Name)))
}
fmt.Println("Importing BLS account, this may take a while...")
statuses, err := accounts.ImportAccounts(context.Background(), &accounts.ImportAccountsConfig{
Importer: k,
Keystores: []*keymanager.Keystore{keystore},
AccountPassword: password,
AccountPassword: importedAccountPassword,
})
if err != nil {
utils.Fatalf("Import BLS account failed: %v.", err)
}
// len(statuses)==len(Keystores) when err==nil
if statuses[0].Status == service.ImportedKeystoreStatus_ERROR {
if statuses[0].Status == keymanager.StatusError {
fmt.Printf("Could not import keystore: %v.", statuses[0].Message)
} else {
fmt.Println("Successfully import BLS account.")
@@ -458,7 +490,7 @@ func blsAccountList(ctx *cli.Context) error {
utils.Fatalf("BLS wallet not exists.")
}
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: walletDir,
WalletPassword: walletPassword,
@@ -537,7 +569,7 @@ func blsAccountDelete(ctx *cli.Context) error {
utils.Fatalf("BLS wallet not exists.")
}
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: walletDir,
WalletPassword: walletPassword,
@@ -599,26 +631,73 @@ func blsAccountDelete(ctx *cli.Context) error {
return nil
}
func GetBLSPassword(ctx *cli.Context) []string {
path := ctx.String(utils.BLSPasswordFileFlag.Name)
if path == "" {
return nil
// blsAccountGenerateProof generate ownership proof for a selected BLS account.
func blsAccountGenerateProof(ctx *cli.Context) error {
addrString := ctx.Args().First()
if addrString == "" {
utils.Fatalf("Operator account must be given as argument.")
}
text, err := os.ReadFile(path)
if err != nil {
utils.Fatalf("Failed to read wallet password file: %v", err)
}
return []string{string(text)}
}
addr := common.HexToAddress(addrString)
func GetBLSAccountPassword(ctx *cli.Context) []string {
path := ctx.String(BLSAccountPasswordFileFlag.Name)
if path == "" {
return nil
blsPubkeyString := ctx.Args().Get(1)
if blsPubkeyString == "" {
utils.Fatalf("BLS pubkey must be given as argument.")
}
text, err := os.ReadFile(path)
blsPubkeyBz, err := hex.DecodeString(strings.TrimPrefix(blsPubkeyString, "0x"))
if err != nil {
utils.Fatalf("Failed to read account password file: %v", err)
utils.Fatalf("Could not decode string %s as hex.", blsPubkeyString)
}
return []string{string(text)}
blsPublicKey, err := bls.PublicKeyFromBytes(blsPubkeyBz)
if err != nil {
utils.Fatalf("%#x is not a valid BLS public key.", blsPubkeyBz)
}
cfg := gethConfig{Node: defaultNodeConfig()}
// Load config file.
if file := ctx.String(configFileFlag.Name); file != "" {
if err := loadConfig(file, &cfg); err != nil {
utils.Fatalf("%v", err)
}
}
utils.SetNodeConfig(ctx, &cfg.Node)
walletDir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
dirExists, err := wallet.Exists(walletDir)
if err != nil || !dirExists {
utils.Fatalf("BLS wallet not exists.")
}
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: walletDir,
WalletPassword: walletPassword,
})
if err != nil {
utils.Fatalf("Open BLS wallet failed: %v.", err)
}
km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
if err != nil {
utils.Fatalf("Initialize key manager failed: %v.", err)
}
chainIdInt64 := ctx.Int64(chainIdFlag.Name)
if chainIdInt64 == 0 {
utils.Fatalf("Chain id is required.")
}
chainId := new(big.Int).SetInt64(chainIdInt64)
paddedChainIdBytes := make([]byte, 32)
copy(paddedChainIdBytes[32-len(chainId.Bytes()):], chainId.Bytes())
msgHash := crypto.Keccak256(append(addr.Bytes(), append(blsPublicKey.Marshal(), paddedChainIdBytes...)...))
req := &validatorpb.SignRequest{
PublicKey: blsPublicKey.Marshal(),
SigningRoot: msgHash,
}
sig, err := km.Sign(context.Background(), req)
if err != nil {
utils.Fatalf("Generate signature failed: %v.", err)
}
fmt.Printf("Proof: %#x\n", sig.Marshal())
return nil
}

View File

@@ -30,6 +30,9 @@ import (
"sync/atomic"
"time"
"github.com/olekukonko/tablewriter"
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -45,7 +48,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/trie"
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
)
var (
@@ -54,7 +57,10 @@ var (
Name: "init",
Usage: "Bootstrap and initialize a new genesis block",
ArgsUsage: "<genesisPath>",
Flags: flags.Merge([]cli.Flag{utils.CachePreimagesFlag}, utils.DatabasePathFlags),
Flags: flags.Merge([]cli.Flag{
utils.CachePreimagesFlag,
utils.StateSchemeFlag,
}, utils.DatabasePathFlags),
Description: `
The init command initializes a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be
@@ -116,6 +122,9 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
utils.MetricsInfluxDBBucketFlag,
utils.MetricsInfluxDBOrganizationFlag,
utils.TxLookupLimitFlag,
utils.TransactionHistoryFlag,
utils.StateSchemeFlag,
utils.StateHistoryFlag,
}, utils.DatabasePathFlags),
Description: `
The import command imports blocks from an RLP-encoded form. The form can be one file
@@ -132,6 +141,7 @@ processing will proceed even if an individual RLP-file import failure occurs.`,
Flags: flags.Merge([]cli.Flag{
utils.CacheFlag,
utils.SyncModeFlag,
utils.StateSchemeFlag,
}, utils.DatabasePathFlags),
Description: `
Requires a first argument of the file to write to.
@@ -181,9 +191,25 @@ It's deprecated, please use "geth db export" instead.
utils.IncludeIncompletesFlag,
utils.StartKeyFlag,
utils.DumpLimitFlag,
utils.StateSchemeFlag,
}, utils.DatabasePathFlags),
Description: `
This command dumps out the state for a given block (or latest, if none provided).
If you use "dump" command in path mode, please firstly use "dump-roothash" command to get all available state root hash.
`,
}
dumpRootHashCommand = &cli.Command{
Action: dumpAllRootHashInPath,
Name: "dump-roothash",
Usage: "Dump all available state root hash in path mode",
Flags: flags.Merge([]cli.Flag{
utils.StateSchemeFlag,
}, utils.DatabasePathFlags),
Description: `
The dump-roothash command dump all available state root hash in path mode.
If you use "dump" command in path mode, please note that it only keeps at most 129 blocks which belongs to diffLayer or diskLayer.
Therefore, you must specify the blockNumber or blockHash that locates in diffLayer or diskLayer.
"geth" will print all available blockNumber and related block state root hash, and you can query block hash by block number.
`,
}
)
@@ -217,15 +243,16 @@ func initGenesis(ctx *cli.Context) error {
if err != nil {
utils.Fatalf("Failed to open database: %v", err)
}
triedb := trie.NewDatabaseWithConfig(chaindb, &trie.Config{
Preimages: ctx.Bool(utils.CachePreimagesFlag.Name),
})
defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false)
defer triedb.Close()
_, hash, err := core.SetupGenesisBlock(chaindb, triedb, genesis)
if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err)
}
chaindb.Close()
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
}
@@ -269,7 +296,7 @@ func createPorts(ipStr string, port int, size int) []int {
// Create config for node i in the cluster
func createNodeConfig(baseConfig gethConfig, enodes []*enode.Node, ip string, port int, size int, i int) gethConfig {
baseConfig.Node.HTTPHost = ip
baseConfig.Node.P2P.ListenAddr = fmt.Sprintf(":%d", port+i)
baseConfig.Node.P2P.ListenAddr = fmt.Sprintf(":%d", port)
baseConfig.Node.P2P.BootstrapNodes = make([]*enode.Node, size-1)
// Set the P2P connections between this node and the other nodes
for j := 0; j < i; j++ {
@@ -286,11 +313,12 @@ func createNodeConfigs(baseConfig gethConfig, initDir string, ips []string, port
// Create the nodes
enodes := make([]*enode.Node, size)
for i := 0; i < size; i++ {
stack, err := node.New(&baseConfig.Node)
nodeConfig := baseConfig.Node
nodeConfig.DataDir = path.Join(initDir, fmt.Sprintf("node%d", i))
stack, err := node.New(&nodeConfig)
if err != nil {
return nil, err
}
stack.Config().DataDir = path.Join(initDir, fmt.Sprintf("node%d", i))
pk := stack.Config().NodeKey()
enodes[i] = enode.NewV4(&pk.PublicKey, net.ParseIP(ips[i]), ports[i], ports[i])
}
@@ -422,7 +450,7 @@ func dumpGenesis(ctx *cli.Context) error {
if ctx.IsSet(utils.DataDirFlag.Name) {
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
}
utils.Fatalf("no network preset provided. no exisiting genesis in the default datadir")
utils.Fatalf("no network preset provided, no existing genesis in the default datadir")
return nil
}
@@ -581,11 +609,20 @@ func exportPreimages(ctx *cli.Context) error {
}
func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, ethdb.Database, common.Hash, error) {
db := utils.MakeChainDatabase(ctx, stack, true, false)
var header *types.Header
if ctx.NArg() > 1 {
return nil, nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg())
}
db := utils.MakeChainDatabase(ctx, stack, true, false)
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db)
if err != nil {
return nil, nil, common.Hash{}, err
}
if scheme == rawdb.PathScheme {
fmt.Println("You are using geth dump in path mode, please use `geth dump-roothash` command to get all available blocks.")
}
header := &types.Header{}
if ctx.NArg() == 1 {
arg := ctx.Args().First()
if hashish(arg) {
@@ -608,11 +645,22 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
}
} else {
// Use latest
header = rawdb.ReadHeadHeader(db)
if scheme == rawdb.PathScheme {
triedb := trie.NewDatabase(db, &trie.Config{PathDB: pathdb.ReadOnly})
defer triedb.Close()
if stateRoot := triedb.Head(); stateRoot != (common.Hash{}) {
header.Root = stateRoot
} else {
return nil, nil, common.Hash{}, fmt.Errorf("no top state root hash in path db")
}
} else {
header = rawdb.ReadHeadHeader(db)
}
}
if header == nil {
return nil, nil, common.Hash{}, errors.New("no head block found")
}
startArg := common.FromHex(ctx.String(utils.StartKeyFlag.Name))
var start common.Hash
switch len(startArg) {
@@ -625,6 +673,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
default:
return nil, nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
}
var conf = &state.DumpConfig{
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
@@ -632,9 +681,10 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
Start: start.Bytes(),
Max: ctx.Uint64(utils.DumpLimitFlag.Name),
}
conf.StateScheme = scheme
log.Info("State dump configured", "block", header.Number, "hash", header.Hash().Hex(),
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage,
"start", hexutil.Encode(conf.Start), "limit", conf.Max)
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage, "start", hexutil.Encode(conf.Start),
"limit", conf.Max, "state scheme", conf.StateScheme)
return conf, db, header.Root, nil
}
@@ -646,10 +696,10 @@ func dump(ctx *cli.Context) error {
if err != nil {
return err
}
config := &trie.Config{
Preimages: true, // always enable preimage lookup
}
state, err := state.New(root, state.NewDatabaseWithConfig(db, config), nil)
triedb := utils.MakeTrieDatabase(ctx, db, true, true) // always enable preimage lookup
defer triedb.Close()
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
if err != nil {
return err
}
@@ -666,6 +716,29 @@ func dump(ctx *cli.Context) error {
return nil
}
func dumpAllRootHashInPath(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
triedb := trie.NewDatabase(db, &trie.Config{PathDB: pathdb.ReadOnly})
defer triedb.Close()
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db)
if err != nil {
return err
}
if scheme == rawdb.HashScheme {
return errors.New("incorrect state scheme, you should use it in path mode")
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Block Number", "Block State Root Hash"})
table.AppendBulk(triedb.GetAllRooHash())
table.Render()
return nil
}
// hashish returns true for strings that look like hashes.
func hashish(x string) bool {
_, err := strconv.Atoi(x)

View File

@@ -24,6 +24,7 @@ import (
"reflect"
"unicode"
"github.com/naoina/toml"
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/accounts"
@@ -32,6 +33,8 @@ import (
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/accounts/usbwallet"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags"
@@ -40,7 +43,6 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/naoina/toml"
)
var (
@@ -54,8 +56,9 @@ var (
}
configFileFlag = &cli.StringFlag{
Name: "config",
Usage: "TOML configuration file",
Name: "config",
Usage: "TOML configuration file",
Category: flags.EthCategory,
}
)
@@ -135,6 +138,16 @@ func loadBaseConfig(ctx *cli.Context) gethConfig {
}
}
scheme := cfg.Eth.StateScheme
if scheme != "" {
if !rawdb.ValidateStateScheme(scheme) {
utils.Fatalf("Invalid state scheme param in config: %s", scheme)
}
}
if cfg.Eth.Genesis != nil && cfg.Eth.Genesis.Config != nil {
log.Warn("Chain config in the configuration file is ignored!")
}
// Apply flags.
utils.SetNodeConfig(ctx, &cfg.Node)
return cfg
@@ -164,6 +177,19 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
// makeFullNode loads geth configuration and creates the Ethereum backend.
func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
stack, cfg := makeConfigNode(ctx)
if ctx.IsSet(utils.RialtoHash.Name) {
v := ctx.String(utils.RialtoHash.Name)
params.RialtoGenesisHash = common.HexToHash(v)
}
if ctx.IsSet(utils.OverrideShanghai.Name) {
v := ctx.Uint64(utils.OverrideShanghai.Name)
cfg.Eth.OverrideShanghai = &v
}
if ctx.IsSet(utils.OverrideKepler.Name) {
v := ctx.Uint64(utils.OverrideKepler.Name)
cfg.Eth.OverrideKepler = &v
}
if ctx.IsSet(utils.OverrideCancun.Name) {
v := ctx.Uint64(utils.OverrideCancun.Name)
cfg.Eth.OverrideCancun = &v
@@ -172,6 +198,10 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
v := ctx.Uint64(utils.OverrideVerkle.Name)
cfg.Eth.OverrideVerkle = &v
}
if ctx.IsSet(utils.OverrideFeynman.Name) {
v := ctx.Uint64(utils.OverrideFeynman.Name)
cfg.Eth.OverrideFeynman = &v
}
backend, _ := utils.RegisterEthService(stack, &cfg.Eth)
// Configure log filter RPC API.

View File

@@ -30,7 +30,7 @@ import (
)
const (
ipcAPIs = "admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0"
ipcAPIs = "admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 parlia:1.0 rpc:1.0 txpool:1.0 web3:1.0"
httpAPIs = "eth:1.0 net:1.0 rpc:1.0 web3:1.0"
)
@@ -60,7 +60,7 @@ func TestConsoleWelcome(t *testing.T) {
geth.SetTemplateFunc("gover", runtime.Version)
geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
geth.SetTemplateFunc("niltime", func() string {
return time.Unix(0, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
return time.Unix(0x5e9da7ce, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
})
geth.SetTemplateFunc("apis", func() string { return ipcAPIs })
@@ -131,7 +131,7 @@ func testAttachWelcome(t *testing.T, geth *testgeth, endpoint, apis string) {
attach.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
attach.SetTemplateFunc("etherbase", func() string { return geth.Etherbase })
attach.SetTemplateFunc("niltime", func() string {
return time.Unix(0, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
return time.Unix(0x5e9da7ce, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
})
attach.SetTemplateFunc("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") })
attach.SetTemplateFunc("datadir", func() string { return geth.Datadir })

View File

@@ -19,6 +19,7 @@ package main
import (
"bytes"
"fmt"
"math"
"os"
"os/signal"
"path/filepath"
@@ -38,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/olekukonko/tablewriter"
"github.com/urfave/cli/v2"
)
@@ -62,6 +64,7 @@ Remove blockchain and state databases`,
dbCompactCmd,
dbGetCmd,
dbDeleteCmd,
dbInspectTrieCmd,
dbPutCmd,
dbGetSlotsCmd,
dbDumpFreezerIndex,
@@ -72,6 +75,9 @@ Remove blockchain and state databases`,
// no legacy stored receipts for bsc
// dbMigrateFreezerCmd,
dbCheckStateContentCmd,
dbHbss2PbssCmd,
dbTrieGetCmd,
dbTrieDeleteCmd,
},
}
dbInspectCmd = &cli.Command{
@@ -84,6 +90,17 @@ Remove blockchain and state databases`,
Usage: "Inspect the storage size for each type of data in the database",
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
}
dbInspectTrieCmd = &cli.Command{
Action: inspectTrie,
Name: "inspect-trie",
ArgsUsage: "<blocknum> <jobnum>",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.SyncModeFlag,
},
Usage: "Inspect the MPT tree of the account and contract.",
Description: `This commands iterates the entrie WorldState.`,
}
dbCheckStateContentCmd = &cli.Command{
Action: checkStateContent,
Name: "check-state-content",
@@ -94,6 +111,47 @@ Remove blockchain and state databases`,
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
a data corruption.`,
}
dbHbss2PbssCmd = &cli.Command{
Action: hbss2pbss,
Name: "hbss-to-pbss",
ArgsUsage: "<jobnum (optional)>",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.SyncModeFlag,
utils.ForceFlag,
utils.AncientFlag,
},
Usage: "Convert Hash-Base to Path-Base trie node.",
Description: `This command iterates the entire trie node database and convert the hash-base node to path-base node.`,
}
dbTrieGetCmd = &cli.Command{
Action: dbTrieGet,
Name: "trie-get",
Usage: "Show the value of a trie node path key",
ArgsUsage: "[trie owner] <path-base key>",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.SyncModeFlag,
utils.BSCMainnetFlag,
utils.ChapelFlag,
utils.StateSchemeFlag,
},
Description: "This command looks up the specified trie node key from the database.",
}
dbTrieDeleteCmd = &cli.Command{
Action: dbTrieDelete,
Name: "trie-delete",
Usage: "delete the specify trie node",
ArgsUsage: "[trie owner] <hash-base key> | <path-base key>",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.SyncModeFlag,
utils.BSCMainnetFlag,
utils.ChapelFlag,
utils.StateSchemeFlag,
},
Description: "This command delete the specify trie node from the database.",
}
dbStatCmd = &cli.Command{
Action: dbStats,
Name: "stats",
@@ -154,6 +212,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
utils.StateSchemeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags),
Description: "This command looks up the specified database key from the database.",
}
@@ -268,6 +327,92 @@ func confirmAndRemoveDB(database string, kind string) {
}
}
func inspectTrie(ctx *cli.Context) error {
if ctx.NArg() < 1 {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
}
if ctx.NArg() > 3 {
return fmt.Errorf("Max 3 arguments: %v", ctx.Command.ArgsUsage)
}
var (
blockNumber uint64
trieRootHash common.Hash
jobnum uint64
)
stack, _ := makeConfigNode(ctx)
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
var headerBlockHash common.Hash
if ctx.NArg() >= 1 {
if ctx.Args().Get(0) == "latest" {
headerHash := rawdb.ReadHeadHeaderHash(db)
blockNumber = *(rawdb.ReadHeaderNumber(db, headerHash))
} else if ctx.Args().Get(0) == "snapshot" {
trieRootHash = rawdb.ReadSnapshotRoot(db)
blockNumber = math.MaxUint64
} else {
var err error
blockNumber, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
if err != nil {
return fmt.Errorf("failed to Parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err)
}
}
if ctx.NArg() == 1 {
jobnum = 1000
} else {
var err error
jobnum, err = strconv.ParseUint(ctx.Args().Get(1), 10, 64)
if err != nil {
return fmt.Errorf("failed to Parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err)
}
}
if blockNumber != math.MaxUint64 {
headerBlockHash = rawdb.ReadCanonicalHash(db, blockNumber)
if headerBlockHash == (common.Hash{}) {
return fmt.Errorf("ReadHeadBlockHash empry hash")
}
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
trieRootHash = blockHeader.Root
}
if (trieRootHash == common.Hash{}) {
log.Error("Empty root hash")
}
fmt.Printf("ReadBlockHeader, root: %v, blocknum: %v\n", trieRootHash, blockNumber)
dbScheme := rawdb.ReadStateScheme(db)
var config *trie.Config
if dbScheme == rawdb.PathScheme {
config = &trie.Config{
PathDB: pathdb.ReadOnly,
}
} else if dbScheme == rawdb.HashScheme {
config = trie.HashDefaults
}
triedb := trie.NewDatabase(db, config)
theTrie, err := trie.New(trie.TrieID(trieRootHash), triedb)
if err != nil {
fmt.Printf("fail to new trie tree, err: %v, rootHash: %v\n", err, trieRootHash.String())
return err
}
theInspect, err := trie.NewInspector(theTrie, triedb, trieRootHash, blockNumber, jobnum)
if err != nil {
return err
}
theInspect.Run()
theInspect.DisplayResult()
}
return nil
}
func inspect(ctx *cli.Context) error {
var (
prefix []byte
@@ -432,6 +577,133 @@ func dbGet(ctx *cli.Context) error {
return nil
}
// dbTrieGet shows the value of a given database key
func dbTrieGet(ctx *cli.Context) error {
if ctx.NArg() < 1 || ctx.NArg() > 2 {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
}
stack, _ := makeConfigNode(ctx)
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, false, false)
defer db.Close()
scheme := ctx.String(utils.StateSchemeFlag.Name)
if scheme == "" {
scheme = rawdb.HashScheme
}
if scheme == rawdb.PathScheme {
var (
pathKey []byte
owner []byte
err error
)
if ctx.NArg() == 1 {
pathKey, err = hexutil.Decode(ctx.Args().Get(0))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
nodeVal, hash := rawdb.ReadAccountTrieNode(db, pathKey)
log.Info("TrieGet result ", "PathKey", common.Bytes2Hex(pathKey), "Hash: ", hash, "node: ", trie.NodeString(hash.Bytes(), nodeVal))
} else if ctx.NArg() == 2 {
owner, err = hexutil.Decode(ctx.Args().Get(0))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
pathKey, err = hexutil.Decode(ctx.Args().Get(1))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
nodeVal, hash := rawdb.ReadStorageTrieNode(db, common.BytesToHash(owner), pathKey)
log.Info("TrieGet result ", "PathKey: ", common.Bytes2Hex(pathKey), "Owner: ", common.BytesToHash(owner), "Hash: ", hash, "node: ", trie.NodeString(hash.Bytes(), nodeVal))
}
} else if scheme == rawdb.HashScheme {
if ctx.NArg() == 1 {
hashKey, err := hexutil.Decode(ctx.Args().Get(0))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
val, err := db.Get(hashKey)
if err != nil {
log.Error("db get failed, ", "error: ", err)
return err
}
log.Info("TrieGet result ", "HashKey: ", common.BytesToHash(hashKey), "node: ", trie.NodeString(hashKey, val))
} else {
log.Error("args too much")
}
}
return nil
}
// dbTrieDelete delete the trienode of a given database key
func dbTrieDelete(ctx *cli.Context) error {
if ctx.NArg() < 1 || ctx.NArg() > 2 {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
}
stack, _ := makeConfigNode(ctx)
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, false, false)
defer db.Close()
scheme := ctx.String(utils.StateSchemeFlag.Name)
if scheme == "" {
scheme = rawdb.HashScheme
}
if scheme == rawdb.PathScheme {
var (
pathKey []byte
owner []byte
err error
)
if ctx.NArg() == 1 {
pathKey, err = hexutil.Decode(ctx.Args().Get(0))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
rawdb.DeleteAccountTrieNode(db, pathKey)
} else if ctx.NArg() == 2 {
owner, err = hexutil.Decode(ctx.Args().Get(0))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
pathKey, err = hexutil.Decode(ctx.Args().Get(1))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
rawdb.DeleteStorageTrieNode(db, common.BytesToHash(owner), pathKey)
}
} else if scheme == rawdb.HashScheme {
if ctx.NArg() == 1 {
hashKey, err := hexutil.Decode(ctx.Args().Get(0))
if err != nil {
log.Info("Could not decode the value", "error", err)
return err
}
err = db.Delete(hashKey)
if err != nil {
log.Error("db delete failed", "err", err)
return err
}
} else {
log.Error("args too much")
}
}
return nil
}
// dbDelete deletes a key from the database
func dbDelete(ctx *cli.Context) error {
if ctx.NArg() != 1 {
@@ -504,6 +776,9 @@ func dbDumpTrie(ctx *cli.Context) error {
db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
triedb := utils.MakeTrieDatabase(ctx, db, false, true)
defer triedb.Close()
var (
state []byte
storage []byte
@@ -537,7 +812,7 @@ func dbDumpTrie(ctx *cli.Context) error {
}
}
id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage))
theTrie, err := trie.New(id, trie.NewDatabase(db))
theTrie, err := trie.New(id, triedb)
if err != nil {
return err
}
@@ -739,3 +1014,101 @@ func showMetaData(ctx *cli.Context) error {
table.Render()
return nil
}
func hbss2pbss(ctx *cli.Context) error {
if ctx.NArg() > 1 {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
}
var jobnum uint64
var err error
if ctx.NArg() == 1 {
jobnum, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
if err != nil {
return fmt.Errorf("failed to Parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err)
}
} else {
// by default
jobnum = 1000
}
force := ctx.Bool(utils.ForceFlag.Name)
stack, _ := makeConfigNode(ctx)
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, false, false)
db.Sync()
defer db.Close()
// convert hbss trie node to pbss trie node
lastStateID := rawdb.ReadPersistentStateID(db)
if lastStateID == 0 || force {
config := trie.HashDefaults
triedb := trie.NewDatabase(db, config)
triedb.Cap(0)
log.Info("hbss2pbss triedb", "scheme", triedb.Scheme())
defer triedb.Close()
headerHash := rawdb.ReadHeadHeaderHash(db)
blockNumber := rawdb.ReadHeaderNumber(db, headerHash)
if blockNumber == nil {
log.Error("read header number failed.")
return fmt.Errorf("read header number failed")
}
log.Info("hbss2pbss converting", "HeaderHash: ", headerHash.String(), ", blockNumber: ", *blockNumber)
var headerBlockHash common.Hash
var trieRootHash common.Hash
if *blockNumber != math.MaxUint64 {
headerBlockHash = rawdb.ReadCanonicalHash(db, *blockNumber)
if headerBlockHash == (common.Hash{}) {
return fmt.Errorf("ReadHeadBlockHash empty hash")
}
blockHeader := rawdb.ReadHeader(db, headerBlockHash, *blockNumber)
trieRootHash = blockHeader.Root
fmt.Println("Canonical Hash: ", headerBlockHash.String(), ", TrieRootHash: ", trieRootHash.String())
}
if (trieRootHash == common.Hash{}) {
log.Error("Empty root hash")
return fmt.Errorf("Empty root hash.")
}
id := trie.StateTrieID(trieRootHash)
theTrie, err := trie.New(id, triedb)
if err != nil {
log.Error("fail to new trie tree", "err", err, "rootHash", err, trieRootHash.String())
return err
}
h2p, err := trie.NewHbss2Pbss(theTrie, triedb, trieRootHash, *blockNumber, jobnum)
if err != nil {
log.Error("fail to new hash2pbss", "err", err, "rootHash", err, trieRootHash.String())
return err
}
h2p.Run()
} else {
log.Info("Convert hbss to pbss success. Nothing to do.")
}
// repair state ancient offset
lastStateID = rawdb.ReadPersistentStateID(db)
if lastStateID == 0 {
log.Error("Convert hbss to pbss trie node error. The last state id is still 0")
}
ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name))
err = rawdb.ResetStateFreezerTableOffset(ancient, lastStateID)
if err != nil {
log.Error("Reset state freezer table offset failed", "error", err)
return err
}
// prune hbss trie node
err = rawdb.PruneHashTrieNodeInDataBase(db)
if err != nil {
log.Error("Prune Hash trie node in database failed", "error", err)
return err
}
return nil
}

View File

@@ -89,7 +89,7 @@ func TestCustomGenesis(t *testing.T) {
// Query the custom genesis block
geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16",
"--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0",
"--datadir", datadir, "--maxpeers", "0", "--port", "0",
"--nodiscover", "--nat", "none", "--ipcdisable",
"--exec", tt.query, "console")
geth.ExpectRegexp(tt.result)
@@ -141,7 +141,7 @@ func TestCustomBackend(t *testing.T) {
}
{ // Exec + query
args := append(tt.execArgs, "--networkid", "1337", "--syncmode=full", "--cache", "16",
"--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0",
"--datadir", datadir, "--maxpeers", "0", "--port", "0",
"--nodiscover", "--nat", "none", "--ipcdisable",
"--exec", "eth.getBlock(0).nonce", "console")
geth := runGeth(t, args...)
@@ -188,7 +188,7 @@ func TestCustomBackend(t *testing.T) {
initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`,
// Since the init fails, this will return the (default) mainnet genesis
// block nonce
execExpect: `0x0000000000000042`,
execExpect: `0x0000000000000000`,
},
} {
if err := testfunc(t, tt); err != nil {

View File

@@ -0,0 +1,147 @@
package main
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"testing"
)
var size int
var basePort int
var configPath string
var genesisPath string
func setup(t *testing.T) {
size = 4
_, filename, _, ok := runtime.Caller(0)
if !ok {
t.Fatalf("error getting current file path")
}
currentDirectory := filepath.Dir(filename)
configPath = filepath.Join(currentDirectory, "testdata/config.toml")
genesisPath = filepath.Join(currentDirectory, "testdata/parlia.json")
basePort = 30311
}
func TestInitNetworkLocalhost(t *testing.T) {
setup(t)
ipStr := ""
testInitNetwork(t, size, basePort, ipStr, configPath, genesisPath)
}
func TestInitNetworkRemoteHosts(t *testing.T) {
setup(t)
ipStr := "192.168.24.103,172.15.67.89,10.0.17.36,203.113.45.76"
testInitNetwork(t, size, basePort, ipStr, configPath, genesisPath)
}
func testInitNetwork(t *testing.T, size, basePort int, ipStr, configPath, genesisPath string) {
dir := t.TempDir()
geth := runGeth(t, "init-network", "--init.dir", dir, "--init.size", strconv.Itoa(size),
"--init.ips", ipStr, "--init.p2p-port", strconv.Itoa(basePort), "--config", configPath,
genesisPath)
// expect the command to complete first
geth.WaitExit()
// Read the output of the command
files, err := os.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
if len(files) != size {
t.Fatalf("expected %d node folders but found %d instead", size, len(files))
}
for i, file := range files {
if file.IsDir() {
expectedNodeDirName := fmt.Sprintf("node%d", i)
if file.Name() != expectedNodeDirName {
t.Fatalf("node dir name is %s but %s was expected", file.Name(), expectedNodeDirName)
}
configFilePath := filepath.Join(dir, file.Name(), "config.toml")
var config gethConfig
err := loadConfig(configFilePath, &config)
if err != nil {
t.Fatalf("failed to load config.toml : %v", err)
}
if ipStr == "" {
verifyConfigFileLocalhost(t, &config, i, basePort, size)
} else {
verifyConfigFileRemoteHosts(t, &config, ipStr, i, basePort, size)
}
}
}
}
func verifyConfigFileRemoteHosts(t *testing.T, config *gethConfig, ipStr string, i, basePort, size int) {
// 1. check ip string
ips := strings.Split(ipStr, ",")
if len(ips) != size {
t.Fatalf("found %d ips in ipStr=%s instead of %d", len(ips), ipStr, size)
}
// 2. check listening port
expectedListenAddr := fmt.Sprintf(":%d", basePort)
if config.Node.P2P.ListenAddr != expectedListenAddr {
t.Fatalf("expected ListenAddr to be %s but it is %s instead", expectedListenAddr, config.Node.P2P.ListenAddr)
}
bootnodes := config.Node.P2P.BootstrapNodes
// 3. check correctness of peers' hosts
for j := 0; j < i; j++ {
ip := bootnodes[j].IP().String()
if ip != ips[j] {
t.Fatalf("expected IP of bootnode to be %s but found %s instead", ips[j], ip)
}
}
for j := i + 1; j < size; j++ {
ip := bootnodes[j-1].IP().String()
if ip != ips[j] {
t.Fatalf("expected IP of bootnode to be %s but found %s instead", ips[j-1], ip)
}
}
// 4. check correctness of peer port numbers
for j := 0; j < size-1; j++ {
if bootnodes[j].UDP() != basePort {
t.Fatalf("expected bootnode port at position %d to be %d but got %d instead", j, basePort, bootnodes[j].UDP())
}
}
}
func verifyConfigFileLocalhost(t *testing.T, config *gethConfig, i int, basePort int, size int) {
// 1. check listening port
expectedListenAddr := fmt.Sprintf(":%d", basePort+i)
if config.Node.P2P.ListenAddr != expectedListenAddr {
t.Fatalf("expected ListenAddr to be %s but it is %s instead", expectedListenAddr, config.Node.P2P.ListenAddr)
}
bootnodes := config.Node.P2P.BootstrapNodes
// 2. check correctness of peers' hosts
localhost := "127.0.0.1"
for j := 0; j < size-1; j++ {
ip := bootnodes[j].IP().String()
if ip != localhost {
t.Fatalf("expected IP of bootnode to be %s but found %s instead", localhost, ip)
}
}
// 3. check correctness of peer port numbers
for j := 0; j < i; j++ {
if bootnodes[j].UDP() != basePort+j {
t.Fatalf("expected bootnode port at position %d to be %d but got %d instead", j, basePort+j, bootnodes[j].UDP())
}
}
for j := i + 1; j < size; j++ {
if bootnodes[j-1].UDP() != basePort+j {
t.Fatalf("expected bootnode port at position %d to be %d but got %d instead", j-1, basePort+j, bootnodes[j-1].UDP())
}
}
}

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.KeyStoreDirFlag,
utils.ExternalSignerFlag,
utils.NoUSBFlag,
utils.NoUSBFlag, // deprecated
utils.DirectBroadcastFlag,
utils.DisableSnapProtocolFlag,
utils.EnableTrustProtocolFlag,
@@ -69,8 +69,12 @@ var (
utils.RangeLimitFlag,
utils.USBFlag,
utils.SmartCardDaemonPathFlag,
utils.RialtoHash,
utils.OverrideShanghai,
utils.OverrideKepler,
utils.OverrideCancun,
utils.OverrideVerkle,
utils.OverrideFeynman,
utils.EnablePersonal,
utils.TxPoolLocalsFlag,
utils.TxPoolNoLocalsFlag,
@@ -93,25 +97,30 @@ var (
utils.ExitWhenSyncedFlag,
utils.GCModeFlag,
utils.SnapshotFlag,
utils.TxLookupLimitFlag,
utils.LightServeFlag,
utils.LightIngressFlag,
utils.LightEgressFlag,
utils.LightMaxPeersFlag,
utils.LightNoPruneFlag,
utils.LightKDFFlag,
utils.LightNoSyncServeFlag,
utils.TxLookupLimitFlag, // deprecated
utils.TransactionHistoryFlag,
utils.StateSchemeFlag,
utils.StateHistoryFlag,
utils.PathDBSyncFlag,
utils.LightServeFlag, // deprecated
utils.LightIngressFlag, // deprecated
utils.LightEgressFlag, // deprecated
utils.LightMaxPeersFlag, // deprecated
utils.LightNoPruneFlag, // deprecated
utils.LightKDFFlag, // deprecated
utils.LightNoSyncServeFlag, // deprecated
utils.EthRequiredBlocksFlag,
utils.LegacyWhitelistFlag,
utils.LegacyWhitelistFlag, // deprecated
utils.BloomFilterSizeFlag,
utils.TriesInMemoryFlag,
utils.CacheFlag,
utils.CacheDatabaseFlag,
utils.CacheTrieFlag,
utils.CacheTrieJournalFlag,
utils.CacheTrieRejournalFlag,
utils.CacheTrieJournalFlag, // deprecated
utils.CacheTrieRejournalFlag, // deprecated
utils.CacheGCFlag,
utils.CacheSnapshotFlag,
// utils.CacheNoPrefetchFlag,
utils.CachePreimagesFlag,
utils.PersistDiffFlag,
utils.DiffBlockFlag,
@@ -131,12 +140,12 @@ var (
utils.MinerExtraDataFlag,
utils.MinerRecommitIntervalFlag,
utils.MinerDelayLeftoverFlag,
utils.MinerNewPayloadTimeout,
// utils.MinerNewPayloadTimeout,
utils.NATFlag,
utils.NoDiscoverFlag,
utils.DiscoveryV4Flag,
utils.DiscoveryV5Flag,
utils.LegacyDiscoveryV5Flag,
utils.LegacyDiscoveryV5Flag, // deprecated
utils.NetrestrictFlag,
utils.NodeKeyFileFlag,
utils.NodeKeyHexFlag,
@@ -169,10 +178,10 @@ var (
utils.HTTPListenAddrFlag,
utils.HTTPPortFlag,
utils.HTTPCORSDomainFlag,
utils.AuthListenFlag,
utils.AuthPortFlag,
utils.AuthVirtualHostsFlag,
utils.JWTSecretFlag,
// utils.AuthListenFlag,
// utils.AuthPortFlag,
// utils.AuthVirtualHostsFlag,
// utils.JWTSecretFlag,
utils.HTTPVirtualHostsFlag,
utils.GraphQLEnabledFlag,
utils.GraphQLCORSDomainFlag,
@@ -231,6 +240,7 @@ func init() {
removedbCommand,
dumpCommand,
dumpGenesisCommand,
dumpRootHashCommand,
// See accountcmd.go:
accountCommand,
walletCommand,
@@ -288,6 +298,9 @@ func main() {
func prepare(ctx *cli.Context) {
// If we're running a known preset, log it for convenience.
switch {
case ctx.IsSet(utils.ChapelFlag.Name):
log.Info("Starting BSC on Chapel testnet...")
case ctx.IsSet(utils.DeveloperFlag.Name):
log.Info("Starting Geth in ephemeral dev mode...")
log.Warn(`You are running Geth in --dev mode. Please note the following:
@@ -307,22 +320,18 @@ func prepare(ctx *cli.Context) {
`)
case !ctx.IsSet(utils.NetworkIdFlag.Name):
log.Info("Starting Geth on Ethereum mainnet...")
log.Info("Starting Geth on BSC mainnet...")
}
// If we're a full node on mainnet without --cache specified, bump default cache allowance
if ctx.String(utils.SyncModeFlag.Name) != "light" && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
// Make sure we're not on any supported preconfigured testnet either
if !ctx.IsSet(utils.DeveloperFlag.Name) {
if !ctx.IsSet(utils.DeveloperFlag.Name) &&
!ctx.IsSet(utils.ChapelFlag.Name) {
// Nope, we're really on mainnet. Bump that cache up!
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096))
}
}
// If we're running a light client on any network, drop the cache to some meaningfully low amount
if ctx.String(utils.SyncModeFlag.Name) == "light" && !ctx.IsSet(utils.CacheFlag.Name) {
log.Info("Dropping default light client cache", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 128)
ctx.Set(utils.CacheFlag.Name, strconv.Itoa(128))
}
}
// geth is the main entry point into the system if no special subcommand is run.

View File

@@ -41,6 +41,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
var (
@@ -136,7 +137,11 @@ func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemai
t.Fatalf("failed to create database with ancient backend")
}
defer db.Close()
genesis := gspec.MustCommit(db)
triedb := trie.NewDatabase(db, nil)
defer triedb.Close()
genesis := gspec.MustCommit(db, triedb)
// Initialize a fresh chain with only a genesis block
blockchain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {

View File

@@ -55,6 +55,15 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
func initGeth(t *testing.T) string {
args := []string{"--networkid=42", "init", "./testdata/clique.json"}
t.Logf("Initializing geth: %v ", args)
g := runGeth(t, args...)
datadir := g.Datadir
g.WaitExit()
return datadir
}
// spawns geth with the given command line args. If the args don't set --datadir, the
// child g gets a temporary data directory.
func runGeth(t *testing.T, args ...string) *testgeth {

View File

@@ -23,6 +23,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/prometheus/tsdb/fileutil"
@@ -71,10 +72,7 @@ two version states are available: genesis and the specific one.
The default pruning target is the HEAD-127 state.
WARNING: It's necessary to delete the trie clean cache after the pruning.
If you specify another directory for the trie clean cache via "--cache.trie.journal"
during the use of Geth, please also specify it here for correct deletion. Otherwise
the trie clean cache with default directory will be deleted.
WARNING: it's only supported in hash mode(--state.scheme=hash)".
`,
},
{
@@ -106,7 +104,9 @@ so it's very necessary to do block data prune, this feature will handle it.
Usage: "Recalculate state hash based on the snapshot for verification",
ArgsUsage: "<root>",
Action: verifyState,
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Flags: flags.Merge([]cli.Flag{
utils.StateSchemeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags),
Description: `
geth snapshot verify-state <state-root>
will traverse the whole accounts and storages set based on the specified
@@ -164,7 +164,9 @@ information about the specified address.
Usage: "Traverse the state with given root hash and perform quick verification",
ArgsUsage: "<root>",
Action: traverseState,
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Flags: flags.Merge([]cli.Flag{
utils.StateSchemeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags),
Description: `
geth snapshot traverse-state <state-root>
will traverse the whole state from the given state root and will abort if any
@@ -179,7 +181,9 @@ It's also usable without snapshot enabled.
Usage: "Traverse the state with given root hash and perform detailed verification",
ArgsUsage: "<root>",
Action: traverseRawState,
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Flags: flags.Merge([]cli.Flag{
utils.StateSchemeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags),
Description: `
geth snapshot traverse-rawstate <state-root>
will traverse the whole state from the given root and will abort if any referenced
@@ -201,6 +205,7 @@ It's also usable without snapshot enabled.
utils.StartKeyFlag,
utils.DumpLimitFlag,
utils.TriesInMemoryFlag,
utils.StateSchemeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags),
Description: `
This command is semantically equivalent to 'geth dump', but uses the snapshots
@@ -235,7 +240,7 @@ func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) {
NoBuild: true,
AsyncBuild: false,
}
snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb), headBlock.Root(), TriesInMemory, false)
snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb, nil), headBlock.Root(), TriesInMemory, false)
if err != nil {
log.Error("snaptree error", "err", err)
return nil, err // The relevant snapshot(s) might not exist
@@ -356,7 +361,21 @@ func pruneBlock(ctx *cli.Context) error {
if path == "" {
return errors.New("prune failed, did not specify the AncientPath")
}
newAncientPath = filepath.Join(path, "ancient_back")
newVersionPath := false
files, err := os.ReadDir(oldAncientPath)
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() && file.Name() == "chain" {
newVersionPath = true
}
}
if newVersionPath && !strings.HasSuffix(oldAncientPath, "geth/chaindata/ancient/chain") {
log.Error("datadir.ancient subdirectory incorrect", "got path", oldAncientPath, "want subdirectory", "geth/chaindata/ancient/chain/")
return errors.New("datadir.ancient subdirectory incorrect")
}
newAncientPath = filepath.Join(path, "chain_back")
blockpruner = pruner.NewBlockPruner(chaindb, stack, oldAncientPath, newAncientPath, blockAmountReserved)
@@ -413,6 +432,9 @@ func pruneState(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, false, false)
defer chaindb.Close()
if rawdb.ReadStateScheme(chaindb) != rawdb.HashScheme {
log.Crit("Offline pruning is not required for path scheme")
}
prunerconfig := pruner.Config{
Datadir: stack.ResolvePath(""),
BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name),
@@ -471,6 +493,7 @@ func pruneAllState(ctx *cli.Context) error {
}
chaindb := utils.MakeChainDatabase(ctx, stack, false, false)
defer chaindb.Close()
pruner, err := pruner.NewAllPruner(chaindb)
if err != nil {
log.Error("Failed to open snapshot tree", "err", err)
@@ -488,18 +511,22 @@ func verifyState(ctx *cli.Context) error {
defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
defer chaindb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
return errors.New("no head block")
}
snapconfig := snapshot.Config{
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
defer triedb.Close()
snapConfig := snapshot.Config{
CacheSize: 256,
Recovery: false,
NoBuild: true,
AsyncBuild: false,
}
snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb), headBlock.Root(), 128, false)
snaptree, err := snapshot.New(snapConfig, chaindb, triedb, headBlock.Root(), 128, false)
if err != nil {
log.Error("Failed to open snapshot tree", "err", err)
return err
@@ -541,6 +568,11 @@ func traverseState(ctx *cli.Context) error {
defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
defer triedb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
@@ -565,7 +597,6 @@ func traverseState(ctx *cli.Context) error {
root = headBlock.Root()
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
}
triedb := trie.NewDatabase(chaindb)
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
if err != nil {
log.Error("Failed to open trie", "root", root, "err", err)
@@ -641,6 +672,11 @@ func traverseRawState(ctx *cli.Context) error {
defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
defer triedb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
@@ -665,7 +701,6 @@ func traverseRawState(ctx *cli.Context) error {
root = headBlock.Root()
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
}
triedb := trie.NewDatabase(chaindb)
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
if err != nil {
log.Error("Failed to open trie", "root", root, "err", err)
@@ -686,6 +721,11 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Failed to open iterator", "root", root, "err", err)
return err
}
reader, err := triedb.Reader(root)
if err != nil {
log.Error("State is non-existent", "root", root)
return nil
}
for accIter.Next(true) {
nodes += 1
node := accIter.Hash()
@@ -693,7 +733,7 @@ func traverseRawState(ctx *cli.Context) error {
// Check the present for non-empty hash node(embedded node doesn't
// have their own hash).
if node != (common.Hash{}) {
blob := rawdb.ReadLegacyTrieNode(chaindb, node)
blob, _ := reader.Node(common.Hash{}, accIter.Path(), node)
if len(blob) == 0 {
log.Error("Missing trie node(account)", "hash", node)
return errors.New("missing account")
@@ -734,7 +774,7 @@ func traverseRawState(ctx *cli.Context) error {
// Check the presence for non-empty hash node(embedded node doesn't
// have their own hash).
if node != (common.Hash{}) {
blob := rawdb.ReadLegacyTrieNode(chaindb, node)
blob, _ := reader.Node(common.BytesToHash(accIter.LeafKey()), storageIter.Path(), node)
if len(blob) == 0 {
log.Error("Missing trie node(storage)", "hash", node)
return errors.New("missing storage")
@@ -794,6 +834,9 @@ func dumpState(ctx *cli.Context) error {
if err != nil {
return err
}
triedb := utils.MakeTrieDatabase(ctx, db, false, true)
defer triedb.Close()
snapConfig := snapshot.Config{
CacheSize: 256,
Recovery: false,
@@ -801,7 +844,7 @@ func dumpState(ctx *cli.Context) error {
AsyncBuild: false,
}
triesInMemory := ctx.Uint64(utils.TriesInMemoryFlag.Name)
snaptree, err := snapshot.New(snapConfig, db, trie.NewDatabase(db), root, int(triesInMemory), false)
snaptree, err := snapshot.New(snapConfig, db, trie.NewDatabase(db, nil), root, int(triesInMemory), false)
if err != nil {
return err
}

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
echo "0. prepare---------------------------------------------------------------------------------"
echo 123abc7890 > bls-password.txt
echo 123abc7891 > bls-password1.txt
basedir=$(cd `dirname $0`; pwd)
workspace=${basedir}/../../../
echo "1. create a bls account--------------------------------------------------------------------"
${workspace}/build/bin/geth bls account new --blspassword ./bls-password.txt --datadir ./bls
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
echo "2. import a bls account by passing file including a private key-----------------------------"
secretKey=`${workspace}/build/bin/geth bls account new --show-private-key --blspassword ./bls-password1.txt --datadir ./bls1 | grep private | awk '{print $NF}'`
echo ${secretKey} > ./bls1/secretKey
${workspace}/build/bin/geth bls account import --blspassword ./bls-password.txt --datadir ./bls ./bls1/secretKey
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
echo "3. delete the imported account above--------------------------------------------------------"
publicKey=`${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls |grep public | tail -1 | awk '{print $NF}'`
${workspace}/build/bin/geth bls account delete --blspassword ./bls-password.txt --datadir ./bls ${publicKey}
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
echo "4. import a bls account by passing a keystore file------------------------------------------"
keystoreFile=`ls bls1/bls/keystore`
${workspace}/build/bin/geth bls account import --importedaccountpassword ./bls-password1.txt --blspassword ./bls-password.txt --datadir ./bls ./bls1/bls/keystore/${keystoreFile}
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls
echo "5. clearup----------------------------------------------------------------------------------"
rm -rf bls
rm -rf bls1
rm -rf bls-password.txt
rm -rf bls-password1.txt

62
cmd/geth/testdata/config.toml vendored Normal file
View File

@@ -0,0 +1,62 @@
[Eth]
NetworkId = 714
SyncMode = "full"
NoPruning = false
NoPrefetch = false
LightPeers = 100
DatabaseCache = 512
DatabaseFreezer = ""
TrieCleanCache = 256
TrieDirtyCache = 256
TriesInMemory = 128
TrieTimeout = 3600000000000
EnablePreimageRecording = false
[Eth.Miner]
GasFloor = 30000000
GasCeil = 40000000
GasPrice = 10000000000
Recommit = 10000000000
[Eth.TxPool]
Locals = []
NoLocals = true
Journal = "transactions.rlp"
Rejournal = 3600000000000
PriceLimit = 10000000000
PriceBump = 10
AccountSlots = 16
GlobalSlots = 4096
AccountQueue = 64
GlobalQueue = 1024
Lifetime = 10800000000000
[Node]
IPCPath = "geth.ipc"
HTTPHost = "0.0.0.0"
NoUSB = true
InsecureUnlockAllowed = true
HTTPPort = 8545
HTTPVirtualHosts = ["*"]
HTTPModules = ["eth", "net", "web3", "txpool", "parlia"]
WSHost = "0.0.0.0"
WSPort = 8545
[Node.P2P]
MaxPeers = 50
NoDiscovery = false
StaticNodes = []
TrustedNodes = []
EnableMsgEvents = false
[Node.HTTPTimeouts]
ReadTimeout = 30000000000
WriteTimeout = 30000000000
IdleTimeout = 120000000000
[Node.LogConfig]
FilePath = "bsc.log"
MaxBytesSize = 10485760
Level = "info"
FileRoot = ""

33
cmd/geth/testdata/parlia.json vendored Normal file
View File

@@ -0,0 +1,33 @@
{
"config": {
"chainId": 714,
"homesteadBlock": 0,
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"ramanujanBlock": 0,
"nielsBlock": 0,
"mirrorSyncBlock":1,
"brunoBlock": 1,
"eulerBlock": 2,
"gibbsBlock": 3,
"parlia": {
"period": 3,
"epoch": 200
}
},
"nonce": "0x0",
"timestamp": "0x5e9da7ce",
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000009fb29aac15b9a4b7f17c3385939b007540f4d7910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x2625a00",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE",
"alloc": {}
}

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

@@ -62,7 +62,6 @@ import (
"github.com/ethereum/go-ethereum/graphql"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/exp"
@@ -75,6 +74,9 @@ import (
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
)
// These are all the command line flags we support.
@@ -93,28 +95,34 @@ var (
Category: flags.EthCategory,
}
DirectBroadcastFlag = &cli.BoolFlag{
Name: "directbroadcast",
Usage: "Enable directly broadcast mined block to all peers",
Name: "directbroadcast",
Usage: "Enable directly broadcast mined block to all peers",
Category: flags.EthCategory,
}
DisableSnapProtocolFlag = &cli.BoolFlag{
Name: "disablesnapprotocol",
Usage: "Disable snap protocol",
Name: "disablesnapprotocol",
Usage: "Disable snap protocol",
Category: flags.EthCategory,
}
EnableTrustProtocolFlag = &cli.BoolFlag{
Name: "enabletrustprotocol",
Usage: "Enable trust protocol",
Name: "enabletrustprotocol",
Usage: "Enable trust protocol",
Category: flags.FastNodeCategory,
}
PipeCommitFlag = &cli.BoolFlag{
Name: "pipecommit",
Usage: "Enable MPT pipeline commit, it will improve syncing performance. It is an experimental feature(default is false)",
Name: "pipecommit",
Usage: "Enable MPT pipeline commit, it will improve syncing performance. It is an experimental feature(default is false)",
Category: flags.DeprecatedCategory,
}
RangeLimitFlag = &cli.BoolFlag{
Name: "rangelimit",
Usage: "Enable 5000 blocks limit for range query",
Name: "rangelimit",
Usage: "Enable 5000 blocks limit for range query",
Category: flags.APICategory,
}
DiffFlag = flags.DirectoryFlag{
Name: "datadir.diff",
Usage: "Data directory for difflayer segments (default = inside chaindata)",
Name: "datadir.diff",
Usage: "Data directory for difflayer segments (default = inside chaindata)",
Category: flags.FastNodeCategory,
}
RemoteDBFlag = &cli.StringFlag{
Name: "remotedb",
@@ -155,18 +163,24 @@ var (
}
NetworkIdFlag = &cli.Uint64Flag{
Name: "networkid",
Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia instead)",
Usage: "Explicitly set network id (integer)(For testnets: use --chapel instead)",
Value: ethconfig.Defaults.NetworkId,
Category: flags.EthCategory,
}
MainnetFlag = &cli.BoolFlag{
BSCMainnetFlag = &cli.BoolFlag{
Name: "mainnet",
Usage: "Ethereum mainnet",
Usage: "BSC mainnet",
Category: flags.EthCategory,
}
ChapelFlag = &cli.BoolFlag{
Name: "chapel",
Usage: "Chapel network: pre-configured Proof-of-Stake-Authority BSC test network",
Category: flags.EthCategory,
}
DeveloperFlag = &cli.BoolFlag{
Name: "dev",
Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
Name: "dev",
Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
Category: flags.DevCategory,
}
DeveloperPeriodFlag = &cli.Uint64Flag{
Name: "dev.period",
@@ -196,7 +210,12 @@ var (
Usage: "Exits after block synchronisation completes",
Category: flags.EthCategory,
}
// hbss2pbss command options
ForceFlag = &cli.BoolFlag{
Name: "force",
Usage: "Force convert hbss trie node to pbss trie node. Ingore any metadata",
Value: false,
}
// Dump command options.
IterativeOutputFlag = &cli.BoolFlag{
Name: "iterative",
@@ -227,30 +246,12 @@ var (
}
defaultSyncMode = ethconfig.Defaults.SyncMode
SyncModeFlag = &flags.TextMarshalerFlag{
Name: "syncmode",
Usage: `Blockchain sync mode ("snap", "full" or "light")`,
Value: &defaultSyncMode,
Category: flags.EthCategory,
}
GCModeFlag = &cli.StringFlag{
Name: "gcmode",
Usage: `Blockchain garbage collection mode ("full", "archive")`,
Value: "full",
Category: flags.EthCategory,
}
SnapshotFlag = &cli.BoolFlag{
SnapshotFlag = &cli.BoolFlag{
Name: "snapshot",
Usage: `Enables snapshot-database mode (default = enable)`,
Value: true,
Category: flags.EthCategory,
}
TxLookupLimitFlag = &cli.Uint64Flag{
Name: "txlookuplimit",
Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
Value: ethconfig.Defaults.TxLookupLimit,
Category: flags.EthCategory,
}
LightKDFFlag = &cli.BoolFlag{
Name: "lightkdf",
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
@@ -268,9 +269,10 @@ var (
Category: flags.EthCategory,
}
TriesInMemoryFlag = &cli.Uint64Flag{
Name: "triesInMemory",
Usage: "The layer of tries trees that keep in memory",
Value: 128,
Name: "triesInMemory",
Usage: "The layer of tries trees that keep in memory",
Value: 128,
Category: flags.PerfCategory,
}
defaultVerifyMode = ethconfig.Defaults.TriesVerifyMode
TriesVerifyModeFlag = &flags.TextMarshalerFlag{
@@ -284,7 +286,23 @@ var (
"none: no merkle state root verification at all, there is no need to setup or connect remote verify node at all,
it is more light comparing to full and insecure mode, but get a very small chance that the state is not consistent
with other peers."`,
Value: &defaultVerifyMode,
Value: &defaultVerifyMode,
Category: flags.FastNodeCategory,
}
RialtoHash = &cli.StringFlag{
Name: "rialtohash",
Usage: "Manually specify the Rialto Genesis Hash, to trigger builtin network logic",
Category: flags.EthCategory,
}
OverrideShanghai = &cli.Uint64Flag{
Name: "override.shanghai",
Usage: "Manually specify the Shanghai fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
OverrideKepler = &cli.Uint64Flag{
Name: "override.kepler",
Usage: "Manually specify the Kepler fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
OverrideCancun = &cli.Uint64Flag{
Name: "override.cancun",
@@ -296,40 +314,45 @@ var (
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
// 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,
OverrideFeynman = &cli.Uint64Flag{
Name: "override.feynman",
Usage: "Manually specify the Feynman fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
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,
SyncModeFlag = &flags.TextMarshalerFlag{
Name: "syncmode",
Usage: `Blockchain sync mode ("snap" or "full")`,
Value: &defaultSyncMode,
Category: flags.StateCategory,
}
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,
GCModeFlag = &cli.StringFlag{
Name: "gcmode",
Usage: `Blockchain garbage collection mode, only relevant in state.scheme=hash ("full", "archive")`,
Value: "full",
Category: flags.StateCategory,
}
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,
StateSchemeFlag = &cli.StringFlag{
Name: "state.scheme",
Usage: "Scheme to use for storing ethereum state ('hash' or 'path')",
Category: flags.StateCategory,
}
LightNoPruneFlag = &cli.BoolFlag{
Name: "light.nopruning",
Usage: "Disable ancient light chain data pruning",
Category: flags.LightCategory,
PathDBSyncFlag = &cli.BoolFlag{
Name: "pathdb.sync",
Usage: "sync flush nodes cache to disk in path schema",
Value: false,
Category: flags.StateCategory,
}
LightNoSyncServeFlag = &cli.BoolFlag{
Name: "light.nosyncserve",
Usage: "Enables serving light clients before syncing",
Category: flags.LightCategory,
StateHistoryFlag = &cli.Uint64Flag{
Name: "history.state",
Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)",
Value: ethconfig.Defaults.StateHistory,
Category: flags.StateCategory,
}
TransactionHistoryFlag = &cli.Uint64Flag{
Name: "history.transactions",
Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
Value: ethconfig.Defaults.TransactionHistory,
Category: flags.StateCategory,
}
// Transaction pool settings
TxPoolLocalsFlag = &cli.StringFlag{
@@ -397,9 +420,10 @@ var (
Category: flags.TxPoolCategory,
}
TxPoolReannounceTimeFlag = &cli.DurationFlag{
Name: "txpool.reannouncetime",
Usage: "Duration for announcing local pending transactions again (default = 10 years, minimum = 1 minute)",
Value: ethconfig.Defaults.TxPool.ReannounceTime,
Name: "txpool.reannouncetime",
Usage: "Duration for announcing local pending transactions again (default = 10 years, minimum = 1 minute)",
Value: ethconfig.Defaults.TxPool.ReannounceTime,
Category: flags.TxPoolCategory,
}
// Blob transaction pool settings
BlobPoolDataDirFlag = &cli.StringFlag{
@@ -462,17 +486,20 @@ var (
Category: flags.PerfCategory,
}
PersistDiffFlag = &cli.BoolFlag{
Name: "persistdiff",
Usage: "Enable persistence of the diff layer",
Name: "persistdiff",
Usage: "Enable persistence of the diff layer",
Category: flags.FastNodeCategory,
}
DiffBlockFlag = &cli.Uint64Flag{
Name: "diffblock",
Usage: "The number of blocks should be persisted in db (default = 86400)",
Value: uint64(86400),
Name: "diffblock",
Usage: "The number of blocks should be persisted in db (default = 86400)",
Value: uint64(86400),
Category: flags.FastNodeCategory,
}
PruneAncientDataFlag = &cli.BoolFlag{
Name: "pruneancient",
Usage: "Prune ancient data, is an optional config and disabled by default. Only keep the latest 9w blocks' data,the older blocks' data will be permanently pruned. Notice:the geth/chaindata/ancient dir will be removed, if restart without the flag, the ancient data will start with the previous point that the oldest unpruned block number. Recommends to the user who don't care about the ancient data.",
Name: "pruneancient",
Usage: "Prune ancient data, is an optional config and disabled by default. Only keep the latest 9w blocks' data,the older blocks' data will be permanently pruned. Notice:the geth/chaindata/ancient dir will be removed, if restart without the flag, the ancient data will start with the previous point that the oldest unpruned block number. Recommends to the user who don't care about the ancient data.",
Category: flags.BlockHistoryCategory,
}
CacheLogSizeFlag = &cli.IntFlag{
Name: "cache.blocklogs",
@@ -527,9 +554,10 @@ var (
Category: flags.MinerCategory,
}
MinerDelayLeftoverFlag = &cli.DurationFlag{
Name: "miner.delayleftover",
Usage: "Time reserved to finalize a block",
Value: ethconfig.Defaults.Miner.DelayLeftOver,
Name: "miner.delayleftover",
Usage: "Time reserved to finalize a block",
Value: ethconfig.Defaults.Miner.DelayLeftOver,
Category: flags.MinerCategory,
}
MinerNewPayloadTimeout = &cli.DurationFlag{
Name: "miner.newpayload-timeout",
@@ -591,27 +619,27 @@ var (
}
// Authenticated RPC HTTP settings
AuthListenFlag = &cli.StringFlag{
Name: "authrpc.addr",
Usage: "Listening address for authenticated APIs",
Value: node.DefaultConfig.AuthAddr,
Category: flags.APICategory,
Name: "authrpc.addr",
Usage: "Listening address for authenticated APIs",
Value: node.DefaultConfig.AuthAddr,
// Category: flags.APICategory,
}
AuthPortFlag = &cli.IntFlag{
Name: "authrpc.port",
Usage: "Listening port for authenticated APIs",
Value: node.DefaultConfig.AuthPort,
Category: flags.APICategory,
Name: "authrpc.port",
Usage: "Listening port for authenticated APIs",
Value: node.DefaultConfig.AuthPort,
// Category: flags.APICategory,
}
AuthVirtualHostsFlag = &cli.StringFlag{
Name: "authrpc.vhosts",
Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
Value: strings.Join(node.DefaultConfig.AuthVirtualHosts, ","),
Category: flags.APICategory,
Name: "authrpc.vhosts",
Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
Value: strings.Join(node.DefaultConfig.AuthVirtualHosts, ","),
// Category: flags.APICategory,
}
JWTSecretFlag = &flags.DirectoryFlag{
Name: "authrpc.jwtsecret",
Usage: "Path to a JWT secret to use for authenticated RPC endpoints",
Category: flags.APICategory,
Name: "authrpc.jwtsecret",
Usage: "Path to a JWT secret to use for authenticated RPC endpoints",
// Category: flags.APICategory,
}
// Logging and debug settings
@@ -780,9 +808,10 @@ var (
}
MaxPeersPerIPFlag = &cli.IntFlag{
Name: "maxpeersperip",
Usage: "Maximum number of network peers from a single IP address, (default used if set to <= 0, which is same as MaxPeers)",
Value: node.DefaultConfig.P2P.MaxPeersPerIP,
Name: "maxpeersperip",
Usage: "Maximum number of network peers from a single IP address, (default used if set to <= 0, which is same as MaxPeers)",
Value: node.DefaultConfig.P2P.MaxPeersPerIP,
Category: flags.NetworkingCategory,
}
MaxPendingPeersFlag = &cli.IntFlag{
@@ -1014,72 +1043,78 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
}
BlockAmountReserved = &cli.Uint64Flag{
Name: "block-amount-reserved",
Usage: "Sets the expected remained amount of blocks for offline block prune",
Name: "block-amount-reserved",
Usage: "Sets the expected remained amount of blocks for offline block prune",
Category: flags.BlockHistoryCategory,
}
CheckSnapshotWithMPT = &cli.BoolFlag{
Name: "check-snapshot-with-mpt",
Usage: "Enable checking between snapshot and MPT ",
Name: "check-snapshot-with-mpt",
Usage: "Enable checking between snapshot and MPT ",
Category: flags.FastNodeCategory,
}
EnableDoubleSignMonitorFlag = &cli.BoolFlag{
Name: "monitor.doublesign",
Usage: "Enable double sign monitor to check whether any validator signs multiple blocks",
Name: "monitor.doublesign",
Usage: "Enable double sign monitor to check whether any validator signs multiple blocks",
Category: flags.MinerCategory,
}
VotingEnabledFlag = &cli.BoolFlag{
Name: "vote",
Usage: "Enable voting when mining",
Name: "vote",
Usage: "Enable voting when mining",
Category: flags.FastFinalityCategory,
}
DisableVoteAttestationFlag = &cli.BoolFlag{
Name: "disablevoteattestation",
Usage: "Disable assembling vote attestation ",
Name: "disablevoteattestation",
Usage: "Disable assembling vote attestation ",
Category: flags.FastFinalityCategory,
}
EnableMaliciousVoteMonitorFlag = &cli.BoolFlag{
Name: "monitor.maliciousvote",
Usage: "Enable malicious vote monitor to check whether any validator violates the voting rules of fast finality",
Name: "monitor.maliciousvote",
Usage: "Enable malicious vote monitor to check whether any validator violates the voting rules of fast finality",
Category: flags.FastFinalityCategory,
}
BLSPasswordFileFlag = &cli.StringFlag{
Name: "blspassword",
Usage: "File path for the BLS password, which contains the password to unlock BLS wallet for managing votes in fast_finality feature",
Name: "blspassword",
Usage: "Password file path for the BLS wallet, which contains the password to unlock BLS wallet for managing votes in fast_finality feature",
Category: flags.AccountCategory,
}
BLSWalletDirFlag = &flags.DirectoryFlag{
Name: "blswallet",
Usage: "Path for the blsWallet dir in fast finality feature (default = inside the datadir)",
Name: "blswallet",
Usage: "Path for the blsWallet dir in fast finality feature (default = inside the datadir)",
Category: flags.AccountCategory,
}
VoteJournalDirFlag = &flags.DirectoryFlag{
Name: "vote-journal-path",
Usage: "Path for the voteJournal dir in fast finality feature (default = inside the datadir)",
Name: "vote-journal-path",
Usage: "Path for the voteJournal dir in fast finality feature (default = inside the datadir)",
Category: flags.FastFinalityCategory,
}
)
var (
// TestnetFlags is the flag group of all built-in supported testnets.
TestnetFlags = []cli.Flag{}
TestnetFlags = []cli.Flag{
ChapelFlag,
}
// NetworkFlags is the flag group of all built-in supported networks.
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
NetworkFlags = append([]cli.Flag{BSCMainnetFlag}, TestnetFlags...)
// DatabasePathFlags is the flag group of all database path flags.
DatabasePathFlags = []cli.Flag{
DataDirFlag,
AncientFlag,
RemoteDBFlag,
DBEngineFlag,
HttpHeaderFlag,
}
)
func init() {
if rawdb.PebbleEnabled {
DatabasePathFlags = append(DatabasePathFlags, DBEngineFlag)
}
}
// MakeDataDir retrieves the currently requested data directory, terminating
// if none (or the empty string) is specified. If the node is starting a testnet,
// then a subdirectory of the specified datadir will be used.
@@ -1209,8 +1244,10 @@ func SplitAndTrim(input string) (ret []string) {
// setHTTP creates the HTTP RPC listener interface string from the set
// command line flags, returning empty if the HTTP endpoint is disabled.
func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.Bool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" {
cfg.HTTPHost = "127.0.0.1"
if ctx.Bool(HTTPEnabledFlag.Name) {
if cfg.HTTPHost == "" {
cfg.HTTPHost = "127.0.0.1"
}
if ctx.IsSet(HTTPListenAddrFlag.Name) {
cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name)
}
@@ -1274,8 +1311,10 @@ func setGraphQL(ctx *cli.Context, cfg *node.Config) {
// setWS creates the WebSocket RPC listener interface string from the set
// command line flags, returning empty if the HTTP endpoint is disabled.
func setWS(ctx *cli.Context, cfg *node.Config) {
if ctx.Bool(WSEnabledFlag.Name) && cfg.WSHost == "" {
cfg.WSHost = "127.0.0.1"
if ctx.Bool(WSEnabledFlag.Name) {
if cfg.WSHost == "" {
cfg.WSHost = "127.0.0.1"
}
if ctx.IsSet(WSListenAddrFlag.Name) {
cfg.WSHost = ctx.String(WSListenAddrFlag.Name)
}
@@ -1309,25 +1348,25 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
}
}
// setLes configures the les server and ultra light client settings from the command line flags.
// setLes shows the deprecation warnings for LES flags.
func setLes(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.IsSet(LightServeFlag.Name) {
cfg.LightServ = ctx.Int(LightServeFlag.Name)
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightServeFlag.Name)
}
if ctx.IsSet(LightIngressFlag.Name) {
cfg.LightIngress = ctx.Int(LightIngressFlag.Name)
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightIngressFlag.Name)
}
if ctx.IsSet(LightEgressFlag.Name) {
cfg.LightEgress = ctx.Int(LightEgressFlag.Name)
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightEgressFlag.Name)
}
if ctx.IsSet(LightMaxPeersFlag.Name) {
cfg.LightPeers = ctx.Int(LightMaxPeersFlag.Name)
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightMaxPeersFlag.Name)
}
if ctx.IsSet(LightNoPruneFlag.Name) {
cfg.LightNoPrune = ctx.Bool(LightNoPruneFlag.Name)
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoPruneFlag.Name)
}
if ctx.IsSet(LightNoSyncServeFlag.Name) {
cfg.LightNoSyncServe = ctx.Bool(LightNoSyncServeFlag.Name)
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoSyncServeFlag.Name)
}
}
@@ -1412,7 +1451,10 @@ func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
// MakePasswordList reads password lines from the file specified by the global --password flag.
func MakePasswordList(ctx *cli.Context) []string {
path := ctx.Path(PasswordFileFlag.Name)
return MakePasswordListFromPath(ctx.Path(PasswordFileFlag.Name))
}
func MakePasswordListFromPath(path string) []string {
if path == "" {
return nil
}
@@ -1435,27 +1477,8 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
setBootstrapNodes(ctx, cfg)
setBootstrapNodesV5(ctx, cfg)
lightClient := ctx.String(SyncModeFlag.Name) == "light"
lightServer := (ctx.Int(LightServeFlag.Name) != 0)
lightPeers := ctx.Int(LightMaxPeersFlag.Name)
if lightClient && !ctx.IsSet(LightMaxPeersFlag.Name) {
// dynamic default - for clients we use 1/10th of the default for servers
lightPeers /= 10
}
if ctx.IsSet(MaxPeersFlag.Name) {
cfg.MaxPeers = ctx.Int(MaxPeersFlag.Name)
if lightServer && !ctx.IsSet(LightMaxPeersFlag.Name) {
cfg.MaxPeers += lightPeers
}
} else {
if lightServer {
cfg.MaxPeers += lightPeers
}
if lightClient && ctx.IsSet(LightMaxPeersFlag.Name) && cfg.MaxPeers < lightPeers {
cfg.MaxPeers = lightPeers
}
}
// if max peers per ip is not set, use max peers
if cfg.MaxPeersPerIP <= 0 {
@@ -1466,36 +1489,21 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
cfg.MaxPeersPerIP = ctx.Int(MaxPeersPerIPFlag.Name)
}
if !(lightClient || lightServer) {
lightPeers = 0
}
ethPeers := cfg.MaxPeers - lightPeers
if lightClient {
ethPeers = 0
}
log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
ethPeers := cfg.MaxPeers
log.Info("Maximum peer count", "ETH", ethPeers, "total", cfg.MaxPeers)
if ctx.IsSet(MaxPendingPeersFlag.Name) {
cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name)
}
if ctx.IsSet(NoDiscoverFlag.Name) || lightClient {
if ctx.IsSet(NoDiscoverFlag.Name) {
cfg.NoDiscovery = true
}
// Disallow --nodiscover when used in conjunction with light mode.
if (lightClient || lightServer) && ctx.Bool(NoDiscoverFlag.Name) {
Fatalf("Cannot use --" + NoDiscoverFlag.Name + " in light client or light server mode")
}
CheckExclusive(ctx, DiscoveryV4Flag, NoDiscoverFlag)
CheckExclusive(ctx, DiscoveryV5Flag, NoDiscoverFlag)
cfg.DiscoveryV4 = ctx.Bool(DiscoveryV4Flag.Name)
cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name)
// If we're running a light client or server, force enable the v5 peer discovery.
if lightClient || lightServer {
cfg.DiscoveryV5 = true
}
if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" {
list, err := netutil.ParseNetlist(netrestrict)
if err != nil {
@@ -1627,12 +1635,7 @@ func setBLSWalletDir(ctx *cli.Context, cfg *node.Config) {
}
}
func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
// If we are running the light client, apply another group
// settings for gas oracle.
if light {
*cfg = ethconfig.LightClientGPO
}
func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
if ctx.IsSet(GpoBlocksFlag.Name) {
cfg.Blocks = ctx.Int(GpoBlocksFlag.Name)
}
@@ -1792,18 +1795,12 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
// SetEthConfig applies eth-related command line flags to the config.
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// Avoid conflicting network flags
CheckExclusive(ctx, MainnetFlag, DeveloperFlag)
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
CheckExclusive(ctx, BSCMainnetFlag, DeveloperFlag)
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
ctx.Set(TxLookupLimitFlag.Name, "0")
log.Warn("Disable transaction unindexing for archive node")
}
if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
}
// Set configurations from CLI flags
setEtherbase(ctx, cfg)
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
setGPO(ctx, &cfg.GPO)
setTxPool(ctx, &cfg.TxPool)
setMiner(ctx, &cfg.Miner)
setRequiredBlocks(ctx, cfg)
@@ -1855,7 +1852,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if cfg.SyncMode == downloader.FullSync {
cfg.PruneAncientData = ctx.Bool(PruneAncientDataFlag.Name)
} else {
log.Crit("pruneancient parameter didn't take effect for current syncmode")
log.Crit("pruneancient parameter can only be used with syncmode=full")
}
}
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
@@ -1874,7 +1871,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.EnableTrustProtocol = ctx.IsSet(EnableTrustProtocolFlag.Name)
}
if ctx.IsSet(PipeCommitFlag.Name) {
cfg.PipeCommit = ctx.Bool(PipeCommitFlag.Name)
log.Warn("The --pipecommit flag is deprecated and could be removed in the future!")
}
if ctx.IsSet(RangeLimitFlag.Name) {
cfg.RangeLimit = ctx.Bool(RangeLimitFlag.Name)
@@ -1888,8 +1885,30 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.Preimages = true
log.Info("Enabling recording of key preimages since archive mode is used")
}
if ctx.IsSet(TxLookupLimitFlag.Name) {
cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name)
if ctx.IsSet(StateHistoryFlag.Name) {
cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name)
}
scheme, err := ParseCLIAndConfigStateScheme(ctx.String(StateSchemeFlag.Name), cfg.StateScheme)
if err != nil {
Fatalf("%v", err)
}
cfg.StateScheme = scheme
// Parse transaction history flag, if user is still using legacy config
// file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'.
if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit {
log.Crit("The config option 'TxLookupLimit' is deprecated and may cause unexpected performance degradation issues, please use 'TransactionHistory' instead")
}
if ctx.IsSet(TransactionHistoryFlag.Name) {
cfg.TransactionHistory = ctx.Uint64(TransactionHistoryFlag.Name)
} else if ctx.IsSet(TxLookupLimitFlag.Name) {
log.Crit("The flag --txlookuplimit is deprecated and may cause unexpected performance degradation issues. Please use --history.transactions instead")
}
if ctx.IsSet(PathDBSyncFlag.Name) {
cfg.PathSyncFlush = true
}
if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 {
cfg.TransactionHistory = 0
log.Warn("Disabled transaction unindexing for archive node")
}
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
@@ -1957,12 +1976,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
}
// Override any default configs for hard coded networks.
switch {
case ctx.Bool(MainnetFlag.Name):
case ctx.Bool(BSCMainnetFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1
cfg.NetworkId = 56
}
cfg.Genesis = core.DefaultGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
cfg.Genesis = core.DefaultBSCGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.BSCGenesisHash)
case ctx.Bool(ChapelFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 97
}
cfg.Genesis = core.DefaultChapelGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.ChapelGenesisHash)
case ctx.Bool(DeveloperFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1337
@@ -2021,7 +2046,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
readonly = false
}
// Check if we have an already initialized chain and fall back to
// that if so. Otherwise we need to generate a new genesis spec.
// that if so. Otherwise, we need to generate a new genesis spec.
chaindb := MakeChainDatabase(ctx, stack, readonly, false)
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
cfg.Genesis = nil // fallback to db content
@@ -2053,9 +2078,6 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
return // already set through flags/config
}
protocol := "all"
if cfg.SyncMode == downloader.LightSync {
protocol = "les"
}
if url := params.KnownDNSNetwork(genesis, protocol); url != "" {
cfg.EthDiscoveryURLs = []string{url}
cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs
@@ -2065,27 +2087,12 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
}
// RegisterEthService adds an Ethereum client to the stack.
// The second return value is the full node instance, which may be nil if the
// node is running as a light client.
// The second return value is the full node instance.
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) {
if cfg.SyncMode == downloader.LightSync {
backend, err := les.New(stack, cfg)
if err != nil {
Fatalf("Failed to register the Ethereum service: %v", err)
}
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
return backend.ApiBackend, nil
}
backend, err := eth.New(stack, cfg)
if err != nil {
Fatalf("Failed to register the Ethereum service: %v", err)
}
if cfg.LightServ > 0 {
_, err := les.NewLesServer(stack, backend, cfg)
if err != nil {
Fatalf("Failed to create the LES server: %v", err)
}
}
stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
return backend.APIBackend, backend
}
@@ -2134,13 +2141,12 @@ func EnableMinerInfo(ctx *cli.Context, minerConfig miner.Config) SetupMetricsOpt
// RegisterFilterAPI adds the eth log filtering RPC API to the node.
func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
isLightClient := ethcfg.SyncMode == downloader.LightSync
filterSystem := filters.NewFilterSystem(backend, filters.Config{
LogCacheSize: ethcfg.FilterLogCacheSize,
})
stack.RegisterAPIs([]rpc.API{{
Namespace: "eth",
Service: filters.NewFilterAPI(filterSystem, isLightClient, ethcfg.RangeLimit),
Service: filters.NewFilterAPI(filterSystem, ethcfg.RangeLimit),
}})
return filterSystem
}
@@ -2273,6 +2279,20 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree
return chainDb
}
// tryMakeReadOnlyDatabase try to open the chain database in read-only mode,
// or fallback to write mode if the database is not initialized.
//
//nolint:unused
func tryMakeReadOnlyDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
// If datadir doesn't exist we need to open db in write-mode
// so database engine can create files.
readonly := true
if !common.FileExist(stack.ResolvePath("chaindata")) || ctx.Bool(PruneAncientDataFlag.Name) {
readonly = false
}
return MakeChainDatabase(ctx, stack, readonly, false)
}
func IsNetworkPreset(ctx *cli.Context) bool {
for _, flag := range NetworkFlags {
bFlag, _ := flag.(*cli.BoolFlag)
@@ -2310,8 +2330,10 @@ func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error)
func MakeGenesis(ctx *cli.Context) *core.Genesis {
var genesis *core.Genesis
switch {
case ctx.Bool(MainnetFlag.Name):
genesis = core.DefaultGenesisBlock()
case ctx.Bool(BSCMainnetFlag.Name):
genesis = core.DefaultBSCGenesisBlock()
case ctx.Bool(ChapelFlag.Name):
genesis = core.DefaultChapelGenesisBlock()
case ctx.Bool(DeveloperFlag.Name):
Fatalf("Developer chains are ephemeral")
}
@@ -2335,14 +2357,21 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}
scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), chainDb)
if err != nil {
Fatalf("%v", err)
}
cache := &core.CacheConfig{
TrieCleanLimit: ethconfig.Defaults.TrieCleanCache,
TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache,
TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive",
TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
TriesInMemory: ethconfig.Defaults.TriesInMemory,
SnapshotLimit: ethconfig.Defaults.SnapshotCache,
Preimages: ctx.Bool(CachePreimagesFlag.Name),
TrieCleanLimit: ethconfig.Defaults.TrieCleanCache,
TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache,
TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive",
TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
TriesInMemory: ethconfig.Defaults.TriesInMemory,
SnapshotLimit: ethconfig.Defaults.SnapshotCache,
Preimages: ctx.Bool(CachePreimagesFlag.Name),
StateScheme: scheme,
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
}
if cache.TrieDirtyDisabled && !cache.Preimages {
cache.Preimages = true
@@ -2390,3 +2419,46 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
}
return preloads
}
// MakeTrieDatabase constructs a trie database based on the configured scheme.
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool) *trie.Database {
config := &trie.Config{
Preimages: preimage,
}
scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk)
if err != nil {
Fatalf("%v", err)
}
if scheme == rawdb.HashScheme {
// Read-only mode is not implemented in hash mode,
// ignore the parameter silently. TODO(rjl493456442)
// please config it if read mode is implemented.
config.HashDB = hashdb.Defaults
return trie.NewDatabase(disk, config)
}
if readOnly {
config.PathDB = pathdb.ReadOnly
} else {
config.PathDB = pathdb.Defaults
}
return trie.NewDatabase(disk, config)
}
// ParseCLIAndConfigStateScheme parses state scheme in CLI and config.
func ParseCLIAndConfigStateScheme(cliScheme, cfgScheme string) (string, error) {
if cliScheme == "" {
if cfgScheme != "" {
log.Info("Use config state scheme", "config", cfgScheme)
}
return cfgScheme, nil
}
if !rawdb.ValidateStateScheme(cliScheme) {
return "", fmt.Errorf("invalid state scheme in CLI: %s", cliScheme)
}
if cfgScheme == "" || cliScheme == cfgScheme {
log.Info("Use CLI state scheme", "CLI", cliScheme)
return cliScheme, nil
}
return "", fmt.Errorf("incompatible state scheme, CLI: %s, config: %s", cliScheme, cfgScheme)
}

View File

@@ -19,6 +19,7 @@ package utils
import (
"fmt"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/urfave/cli/v2"
)
@@ -37,6 +38,13 @@ var DeprecatedFlags = []cli.Flag{
CacheTrieJournalFlag,
CacheTrieRejournalFlag,
LegacyDiscoveryV5Flag,
TxLookupLimitFlag,
LightServeFlag,
LightIngressFlag,
LightEgressFlag,
LightMaxPeersFlag,
LightNoPruneFlag,
LightNoSyncServeFlag,
}
var (
@@ -68,6 +76,48 @@ var (
Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism (deprecated, use --discv5 instead)",
Category: flags.DeprecatedCategory,
}
// Deprecated August 2023
TxLookupLimitFlag = &cli.Uint64Flag{
Name: "txlookuplimit",
Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) (deprecated, use history.transactions instead)",
Value: ethconfig.Defaults.TransactionHistory,
Category: flags.DeprecatedCategory,
}
// Light server and client settings, Deprecated November 2023
LightServeFlag = &cli.IntFlag{
Name: "light.serve",
Usage: "Maximum percentage of time allowed for serving LES requests (deprecated)",
Value: ethconfig.Defaults.LightServ,
Category: flags.LightCategory,
}
LightIngressFlag = &cli.IntFlag{
Name: "light.ingress",
Usage: "Incoming bandwidth limit for serving light clients (deprecated)",
Value: ethconfig.Defaults.LightIngress,
Category: flags.LightCategory,
}
LightEgressFlag = &cli.IntFlag{
Name: "light.egress",
Usage: "Outgoing bandwidth limit for serving light clients (deprecated)",
Value: ethconfig.Defaults.LightEgress,
Category: flags.LightCategory,
}
LightMaxPeersFlag = &cli.IntFlag{
Name: "light.maxpeers",
Usage: "Maximum number of light clients to serve, or light servers to attach to (deprecated)",
Value: ethconfig.Defaults.LightPeers,
Category: flags.LightCategory,
}
LightNoPruneFlag = &cli.BoolFlag{
Name: "light.nopruning",
Usage: "Disable ancient light chain data pruning (deprecated)",
Category: flags.LightCategory,
}
LightNoSyncServeFlag = &cli.BoolFlag{
Name: "light.nosyncserve",
Usage: "Enables serving light clients before syncing (deprecated)",
Category: flags.LightCategory,
}
)
// showDeprecated displays deprecated flags that will be soon removed from the codebase.

View File

@@ -44,6 +44,12 @@ const (
var (
hashT = reflect.TypeOf(Hash{})
addressT = reflect.TypeOf(Address{})
// MaxAddress represents the maximum possible address value.
MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff")
// MaxHash represents the maximum possible hash value.
MaxHash = HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
)
// Hash represents the 32 byte Keccak256 hash of arbitrary data.

View File

@@ -150,7 +150,7 @@ type PoSA interface {
IsSystemContract(to *common.Address) bool
EnoughDistance(chain ChainReader, header *types.Header) bool
IsLocalBlock(header *types.Header) bool
GetJustifiedNumberAndHash(chain ChainHeaderReader, header *types.Header) (uint64, common.Hash, error)
GetJustifiedNumberAndHash(chain ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error)
GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool

View File

@@ -21,6 +21,9 @@ import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
@@ -29,6 +32,16 @@ import (
// - gas limit check
// - basefee check
func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Header) error {
if config.Parlia == nil {
// Verify that the gas limit remains within allowed bounds
parentGasLimit := parent.GasLimit
if !config.IsLondon(parent.Number) {
parentGasLimit = parent.GasLimit * config.ElasticityMultiplier()
}
if err := misc.VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
return err
}
}
// Verify the header is not malformed
if header.BaseFee == nil {
return errors.New("header is missing baseFee")
@@ -45,5 +58,45 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
// CalcBaseFee calculates the basefee of the header.
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
return new(big.Int).SetUint64(params.InitialBaseFee)
if config.Parlia != nil {
return new(big.Int).SetUint64(params.InitialBaseFee)
}
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
if !config.IsLondon(parent.Number) {
return new(big.Int).SetUint64(params.InitialBaseFee)
}
parentGasTarget := parent.GasLimit / config.ElasticityMultiplier()
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
if parent.GasUsed == parentGasTarget {
return new(big.Int).Set(parent.BaseFee)
}
var (
num = new(big.Int)
denom = new(big.Int)
)
if parent.GasUsed > parentGasTarget {
// If the parent block used more gas than its target, the baseFee should increase.
// max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parent.GasUsed - parentGasTarget)
num.Mul(num, parent.BaseFee)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
baseFeeDelta := math.BigMax(num, common.Big1)
return num.Add(parent.BaseFee, baseFeeDelta)
} else {
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parentGasTarget - parent.GasUsed)
num.Mul(num, parent.BaseFee)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
baseFee := num.Sub(parent.BaseFee, num)
return math.BigMax(baseFee, common.Big0)
}
}

View File

@@ -51,6 +51,11 @@ func copyConfig(original *params.ChainConfig) *params.ChainConfig {
func config() *params.ChainConfig {
config := copyConfig(params.TestChainConfig)
config.Ethash = nil
config.Parlia = &params.ParliaConfig{
Period: 3,
Epoch: 200,
}
config.LondonBlock = big.NewInt(5)
return config
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
package parlia
import (
"container/heap"
"context"
"fmt"
"math"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/systemcontracts"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
)
const SecondsPerDay uint64 = 86400
// the params should be two blocks' time(timestamp)
func sameDayInUTC(first, second uint64) bool {
return first/SecondsPerDay == second/SecondsPerDay
}
func isBreatheBlock(lastBlockTime, blockTime uint64) bool {
return lastBlockTime != 0 && !sameDayInUTC(lastBlockTime, blockTime)
}
// initializeFeynmanContract initialize new contracts of Feynman fork
func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
) error {
// method
method := "initialize"
// initialize contracts
contracts := []string{
systemcontracts.StakeHubContract,
systemcontracts.GovernorContract,
systemcontracts.GovTokenContract,
systemcontracts.TimelockContract,
systemcontracts.TokenRecoverPortalContract,
}
// get packed data
data, err := p.stakeHubABI.Pack(method)
if err != nil {
log.Error("Unable to pack tx for initialize feynman contracts", "error", err)
return err
}
for _, c := range contracts {
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0)
// apply message
log.Info("initialize feynman contract", "block number", header.Number.Uint64(), "contract", c)
err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
if err != nil {
return err
}
}
return nil
}
type ValidatorItem struct {
address common.Address
votingPower *big.Int
voteAddress []byte
}
// An ValidatorHeap is a max-heap of validator's votingPower.
type ValidatorHeap []ValidatorItem
func (h *ValidatorHeap) Len() int { return len(*h) }
func (h *ValidatorHeap) Less(i, j int) bool {
// We want topK validators with max voting power, so we need a max-heap
if (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 0 {
return (*h)[i].address.Hex() < (*h)[j].address.Hex()
} else {
return (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 1
}
}
func (h *ValidatorHeap) Swap(i, j int) { (*h)[i], (*h)[j] = (*h)[j], (*h)[i] }
func (h *ValidatorHeap) Push(x interface{}) {
*h = append(*h, x.(ValidatorItem))
}
func (h *ValidatorHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func (p *Parlia) updateValidatorSetV2(state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
) error {
// 1. get all validators and its voting power
blockNr := rpc.BlockNumberOrHashWithHash(header.ParentHash, false)
validatorItems, err := p.getValidatorElectionInfo(blockNr)
if err != nil {
return err
}
maxElectedValidators, err := p.getMaxElectedValidators(blockNr)
if err != nil {
return err
}
// 2. sort by voting power
eValidators, eVotingPowers, eVoteAddrs := getTopValidatorsByVotingPower(validatorItems, maxElectedValidators)
// 3. update validator set to system contract
method := "updateValidatorSetV2"
data, err := p.validatorSetABI.Pack(method, eValidators, eVotingPowers, eVoteAddrs)
if err != nil {
log.Error("Unable to pack tx for updateValidatorSetV2", "error", err)
return err
}
// get system message
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0)
// apply message
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
func (p *Parlia) getValidatorElectionInfo(blockNr rpc.BlockNumberOrHash) ([]ValidatorItem, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
method := "getValidatorElectionInfo"
toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
data, err := p.stakeHubABI.Pack(method, big.NewInt(0), big.NewInt(0))
if err != nil {
log.Error("Unable to pack tx for getValidatorElectionInfo", "error", err)
return nil, err
}
msgData := (hexutil.Bytes)(data)
result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
Gas: &gas,
To: &toAddress,
Data: &msgData,
}, blockNr, nil, nil)
if err != nil {
return nil, err
}
var validators []common.Address
var votingPowers []*big.Int
var voteAddrs [][]byte
var totalLength *big.Int
if err := p.stakeHubABI.UnpackIntoInterface(&[]interface{}{&validators, &votingPowers, &voteAddrs, &totalLength}, method, result); err != nil {
return nil, err
}
if totalLength.Int64() != int64(len(validators)) || totalLength.Int64() != int64(len(votingPowers)) || totalLength.Int64() != int64(len(voteAddrs)) {
return nil, fmt.Errorf("validator length not match")
}
validatorItems := make([]ValidatorItem, len(validators))
for i := 0; i < len(validators); i++ {
validatorItems[i] = ValidatorItem{
address: validators[i],
votingPower: votingPowers[i],
voteAddress: voteAddrs[i],
}
}
return validatorItems, nil
}
func (p *Parlia) getMaxElectedValidators(blockNr rpc.BlockNumberOrHash) (maxElectedValidators *big.Int, err error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
method := "maxElectedValidators"
toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
data, err := p.stakeHubABI.Pack(method)
if err != nil {
log.Error("Unable to pack tx for maxElectedValidators", "error", err)
return nil, err
}
msgData := (hexutil.Bytes)(data)
result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
Gas: &gas,
To: &toAddress,
Data: &msgData,
}, blockNr, nil, nil)
if err != nil {
return nil, err
}
if err := p.stakeHubABI.UnpackIntoInterface(&maxElectedValidators, method, result); err != nil {
return nil, err
}
return maxElectedValidators, nil
}
func getTopValidatorsByVotingPower(validatorItems []ValidatorItem, maxElectedValidators *big.Int) ([]common.Address, []uint64, [][]byte) {
var validatorHeap ValidatorHeap
for i := 0; i < len(validatorItems); i++ {
// only keep validators with voting power > 0
if validatorItems[i].votingPower.Cmp(big.NewInt(0)) == 1 {
validatorHeap = append(validatorHeap, validatorItems[i])
}
}
hp := &validatorHeap
heap.Init(hp)
topN := int(maxElectedValidators.Int64())
if topN > len(validatorHeap) {
topN = len(validatorHeap)
}
eValidators := make([]common.Address, topN)
eVotingPowers := make([]uint64, topN)
eVoteAddrs := make([][]byte, topN)
for i := 0; i < topN; i++ {
item := heap.Pop(hp).(ValidatorItem)
eValidators[i] = item.address
// as the decimal in BNB Beacon Chain is 1e8 and in BNB Smart Chain is 1e18, we need to divide it by 1e10
eVotingPowers[i] = new(big.Int).Div(item.votingPower, big.NewInt(1e10)).Uint64()
eVoteAddrs[i] = item.voteAddress
}
return eValidators, eVotingPowers, eVoteAddrs
}

View File

@@ -0,0 +1,166 @@
package parlia
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
)
func TestValidatorHeap(t *testing.T) {
testCases := []struct {
description string
k int64
validators []ValidatorItem
expected []common.Address
}{
{
description: "normal case",
k: 2,
validators: []ValidatorItem{
{
address: common.HexToAddress("0x1"),
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
voteAddress: []byte("0x1"),
},
{
address: common.HexToAddress("0x2"),
votingPower: new(big.Int).Mul(big.NewInt(200), big.NewInt(1e10)),
voteAddress: []byte("0x2"),
},
{
address: common.HexToAddress("0x3"),
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
voteAddress: []byte("0x3"),
},
},
expected: []common.Address{
common.HexToAddress("0x1"),
common.HexToAddress("0x2"),
},
},
{
description: "same voting power",
k: 2,
validators: []ValidatorItem{
{
address: common.HexToAddress("0x1"),
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
voteAddress: []byte("0x1"),
},
{
address: common.HexToAddress("0x2"),
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
voteAddress: []byte("0x2"),
},
{
address: common.HexToAddress("0x3"),
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
voteAddress: []byte("0x3"),
},
},
expected: []common.Address{
common.HexToAddress("0x1"),
common.HexToAddress("0x2"),
},
},
{
description: "zero voting power and k > len(validators)",
k: 5,
validators: []ValidatorItem{
{
address: common.HexToAddress("0x1"),
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
voteAddress: []byte("0x1"),
},
{
address: common.HexToAddress("0x2"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x2"),
},
{
address: common.HexToAddress("0x3"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x3"),
},
{
address: common.HexToAddress("0x4"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x4"),
},
},
expected: []common.Address{
common.HexToAddress("0x1"),
},
},
{
description: "zero voting power and k < len(validators)",
k: 2,
validators: []ValidatorItem{
{
address: common.HexToAddress("0x1"),
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
voteAddress: []byte("0x1"),
},
{
address: common.HexToAddress("0x2"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x2"),
},
{
address: common.HexToAddress("0x3"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x3"),
},
{
address: common.HexToAddress("0x4"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x4"),
},
},
expected: []common.Address{
common.HexToAddress("0x1"),
},
},
{
description: "all zero voting power",
k: 2,
validators: []ValidatorItem{
{
address: common.HexToAddress("0x1"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x1"),
},
{
address: common.HexToAddress("0x2"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x2"),
},
{
address: common.HexToAddress("0x3"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x3"),
},
{
address: common.HexToAddress("0x4"),
votingPower: big.NewInt(0),
voteAddress: []byte("0x4"),
},
},
expected: []common.Address{},
},
}
for _, tc := range testCases {
eligibleValidators, _, _ := getTopValidatorsByVotingPower(tc.validators, big.NewInt(tc.k))
// check
if len(eligibleValidators) != len(tc.expected) {
t.Errorf("expected %d, got %d", len(tc.expected), len(eligibleValidators))
}
for i := 0; i < len(tc.expected); i++ {
if eligibleValidators[i] != tc.expected[i] {
t.Errorf("expected %s, got %s", tc.expected[i].Hex(), eligibleValidators[i].Hex())
}
}
}
}

View File

@@ -6,7 +6,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"io"
"math"
"math/big"
"math/rand"
@@ -29,6 +28,7 @@ import (
cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/state"
@@ -47,7 +47,7 @@ import (
)
const (
inMemorySnapshots = 128 // Number of recent snapshots to keep in memory
inMemorySnapshots = 256 // Number of recent snapshots to keep in memory
inMemorySignatures = 4096 // Number of recent block signatures to keep in memory
checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database
@@ -90,6 +90,11 @@ var (
common.HexToAddress(systemcontracts.TokenHubContract): true,
common.HexToAddress(systemcontracts.RelayerIncentivizeContract): true,
common.HexToAddress(systemcontracts.CrossChainContract): true,
common.HexToAddress(systemcontracts.StakeHubContract): true,
common.HexToAddress(systemcontracts.GovernorContract): true,
common.HexToAddress(systemcontracts.GovTokenContract): true,
common.HexToAddress(systemcontracts.TimelockContract): true,
common.HexToAddress(systemcontracts.TokenRecoverPortalContract): true,
}
)
@@ -179,7 +184,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
signature := header.Extra[len(header.Extra)-extraSeal:]
// Recover the public key and the Ethereum address
pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature)
pubkey, err := crypto.Ecrecover(types.SealHash(header, chainId).Bytes(), signature)
if err != nil {
return common.Address{}, err
}
@@ -199,7 +204,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
// or not), which could be abused to produce different hashes for the same header.
func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
b := new(bytes.Buffer)
encodeSigHeader(b, header, chainId)
types.EncodeSigHeader(b, header, chainId)
return b.Bytes()
}
@@ -226,6 +231,7 @@ type Parlia struct {
validatorSetABIBeforeLuban abi.ABI
validatorSetABI abi.ABI
slashABI abi.ABI
stakeHubABI abi.ABI
// The fields below are for testing only
fakeDiff bool // Skip difficulty verifications
@@ -240,6 +246,7 @@ func New(
) *Parlia {
// get parlia config
parliaConfig := chainConfig.Parlia
log.Info("Parlia", "chainConfig", chainConfig)
// Set any missing consensus parameters to their defaults
if parliaConfig != nil && parliaConfig.Epoch == 0 {
@@ -267,6 +274,10 @@ func New(
if err != nil {
panic(err)
}
stABI, err := abi.JSON(strings.NewReader(stakeABI))
if err != nil {
panic(err)
}
c := &Parlia{
chainConfig: chainConfig,
config: parliaConfig,
@@ -278,6 +289,7 @@ func New(
validatorSetABIBeforeLuban: vABIBeforeLuban,
validatorSetABI: vABI,
slashABI: sABI,
stakeHubABI: stABI,
signer: types.LatestSigner(chainConfig),
}
@@ -445,7 +457,11 @@ func (p *Parlia) verifyVoteAttestation(chain consensus.ChainHeaderReader, header
// The source block should be the highest justified block.
sourceNumber := attestation.Data.SourceNumber
sourceHash := attestation.Data.SourceHash
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent)
headers := []*types.Header{parent}
if len(parents) > 0 {
headers = parents
}
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, headers)
if err != nil {
return fmt.Errorf("unexpected error when getting the highest justified number and hash")
}
@@ -566,6 +582,24 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
return err
}
// Verify existence / non-existence of withdrawalsHash.
if header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
}
// Verify the existence / non-existence of excessBlobGas
cancun := chain.Config().IsCancun(header.Number, header.Time)
if !cancun && header.ExcessBlobGas != nil {
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
}
if !cancun && header.BlobGasUsed != nil {
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
}
if cancun {
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
return err
}
}
// All basic checks passed, verify cascading fields
return p.verifyCascadingFields(chain, header, parents)
}
@@ -661,7 +695,7 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
// If we're at the genesis, snapshot the initial state. Alternatively if we have
// piled up more headers than allowed to be reorged (chain reinit from a freezer),
// consider the checkpoint trusted and snapshot it.
if number == 0 || (number%p.config.Epoch == 0 && (len(headers) > params.FullImmutabilityThreshold)) {
if number == 0 || (number%p.config.Epoch == 0 && (len(headers) > params.FullImmutabilityThreshold/10)) {
checkpoint := chain.GetHeaderByNumber(number)
if checkpoint != nil {
// get checkpoint data
@@ -675,10 +709,12 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
// new snapshot
snap = newSnapshot(p.config, p.signatures, number, hash, validators, voteAddrs, p.ethAPI)
if err := snap.store(p.db); err != nil {
return nil, err
if snap.Number%checkpointInterval == 0 { // snapshot will only be loaded when snap.Number%checkpointInterval == 0
if err := snap.store(p.db); err != nil {
return nil, err
}
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
}
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
break
}
}
@@ -809,6 +845,13 @@ func (p *Parlia) prepareValidators(header *types.Header) error {
}
} else {
header.Extra = append(header.Extra, byte(len(newValidators)))
if p.chainConfig.IsOnLuban(header.Number) {
voteAddressMap = make(map[common.Address]*types.BLSPublicKey, len(newValidators))
var zeroBlsKey types.BLSPublicKey
for _, validator := range newValidators {
voteAddressMap[validator] = &zeroBlsKey
}
}
for _, validator := range newValidators {
header.Extra = append(header.Extra, validator.Bytes()...)
header.Extra = append(header.Extra, voteAddressMap[validator].Bytes()...)
@@ -842,7 +885,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
// Prepare vote attestation
// Prepare vote data
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent)
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{parent})
if err != nil {
return fmt.Errorf("unexpected error when getting the highest justified number and hash")
}
@@ -875,7 +918,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
// Prepare vote address bitset.
for _, valInfo := range snap.Validators {
if _, ok := voteAddrSet[valInfo.VoteAddress]; ok {
attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) //Index is offset by 1
attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) // Index is offset by 1
}
}
validatorsBitSet := bitset.From([]uint64{uint64(attestation.VoteAddressSet)})
@@ -931,7 +974,7 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header
}
header.Extra = header.Extra[:extraVanity-nextForkHashSize]
nextForkHash := forkid.NewID(p.chainConfig, p.genesisHash, number, header.Time).Hash
nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, number, header.Time)
header.Extra = append(header.Extra, nextForkHash[:]...)
if err := p.prepareValidators(header); err != nil {
@@ -970,6 +1013,13 @@ func (p *Parlia) verifyValidators(header *types.Header) error {
return errMismatchingEpochValidators
}
validatorsBytes = make([]byte, validatorsNumber*validatorBytesLength)
if p.chainConfig.IsOnLuban(header.Number) {
voteAddressMap = make(map[common.Address]*types.BLSPublicKey, len(newValidators))
var zeroBlsKey types.BLSPublicKey
for _, validator := range newValidators {
voteAddressMap[validator] = &zeroBlsKey
}
}
for i, validator := range newValidators {
copy(validatorsBytes[i*validatorBytesLength:], validator.Bytes())
copy(validatorsBytes[i*validatorBytesLength+common.AddressLength:], voteAddressMap[validator].Bytes())
@@ -1065,7 +1115,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
if err != nil {
return err
}
nextForkHash := forkid.NewID(p.chainConfig, p.genesisHash, number, header.Time).Hash
nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, number, header.Time)
if !snap.isMajorityFork(hex.EncodeToString(nextForkHash[:])) {
log.Debug("there is a possible fork, and your client is not the majority. Please check...", "nextForkHash", hex.EncodeToString(nextForkHash[:]))
}
@@ -1077,6 +1127,22 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
cx := chainContext{Chain: chain, parlia: p}
parent := chain.GetHeaderByHash(header.ParentHash)
if parent == nil {
return errors.New("parent not found")
}
if p.chainConfig.IsFeynman(header.Number, header.Time) {
systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
}
if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
if err != nil {
log.Error("init feynman contract failed", "error", err)
}
}
// No block rewards in PoA, so the state remains as is and uncles are dropped
if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
@@ -1118,6 +1184,17 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
return err
}
}
// update validators every day
if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
// we should avoid update validators in the Feynman upgrade block
if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil {
return err
}
}
}
if len(*systemTxs) > 0 {
return errors.New("the length of systemTxs do not match")
}
@@ -1136,6 +1213,23 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
if receipts == nil {
receipts = make([]*types.Receipt, 0)
}
parent := chain.GetHeaderByHash(header.ParentHash)
if parent == nil {
return nil, nil, errors.New("parent not found")
}
if p.chainConfig.IsFeynman(header.Number, header.Time) {
systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
}
if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
err := p.initializeFeynmanContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil {
log.Error("init feynman contract failed", "error", err)
}
}
if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil {
@@ -1180,6 +1274,16 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
}
}
// update validators every day
if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
// we should avoid update validators in the Feynman upgrade block
if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
if err := p.updateValidatorSetV2(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
return nil, nil, err
}
}
}
// should not happen. Once happen, stop the node is better than broadcast the block
if header.GasLimit < header.GasUsed {
return nil, nil, errors.New("gas consumption of system txs exceed the gas limit")
@@ -1230,7 +1334,7 @@ func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteE
return fmt.Errorf("target number mismatch")
}
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, header)
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{header})
if err != nil {
log.Error("failed to get the highest justified number and hash", "headerNumber", header.Number, "headerHash", header.Hash())
return fmt.Errorf("unexpected error when getting the highest justified number and hash")
@@ -1382,7 +1486,7 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
select {
case results <- block.WithSeal(header):
default:
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
log.Warn("Sealing result is not read by miner", "sealhash", types.SealHash(header, p.chainConfig.ChainID))
}
}()
@@ -1456,7 +1560,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
// So it's not the real hash of a block, just used as unique id to distinguish task
func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
encodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
types.EncodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
hasher.Sum(hash[:0])
return hash
}
@@ -1514,19 +1618,18 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNum *big.Int)
var valSet []common.Address
var voteAddrSet []types.BLSPublicKey
if err := p.validatorSetABI.UnpackIntoInterface(&[]interface{}{&valSet, &voteAddrSet}, method, result); err != nil {
return nil, nil, err
}
voteAddrmap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
voteAddrMap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
for i := 0; i < len(valSet); i++ {
voteAddrmap[valSet[i]] = &(voteAddrSet)[i]
voteAddrMap[valSet[i]] = &(voteAddrSet)[i]
}
return valSet, voteAddrmap, nil
return valSet, voteAddrMap, nil
}
// slash spoiled validators
// distributeIncoming distributes system incoming of the block
func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
coinbase := header.Coinbase
@@ -1537,9 +1640,10 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
state.SetBalance(consensus.SystemAddress, big.NewInt(0))
state.AddBalance(coinbase, balance)
doDistributeSysReward := state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) &&
state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
if doDistributeSysReward {
var rewards = new(big.Int)
rewards := new(big.Int)
rewards = rewards.Rsh(balance, systemRewardPercent)
if rewards.Cmp(common.Big0) > 0 {
err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
@@ -1615,7 +1719,7 @@ func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, heade
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
// slash spoiled validators
// distributeToValidator deposits validator reward to validator contract
func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address,
state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
@@ -1710,24 +1814,25 @@ func (p *Parlia) applyTransaction(
receipt.BlockNumber = header.Number
receipt.TransactionIndex = uint(state.TxIndex())
*receipts = append(*receipts, receipt)
state.SetNonce(msg.From(), nonce+1)
return nil
}
// GetJustifiedNumberAndHash returns the highest justified block's number and hash on the branch including and before `header`
func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) {
if chain == nil || header == nil {
// GetJustifiedNumberAndHash retrieves the number and hash of the highest justified block
// within the branch including `headers` and utilizing the latest element as the head.
func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
if chain == nil || len(headers) == 0 || headers[len(headers)-1] == nil {
return 0, common.Hash{}, fmt.Errorf("illegal chain or header")
}
snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil)
head := headers[len(headers)-1]
snap, err := p.snapshot(chain, head.Number.Uint64(), head.Hash(), headers)
if err != nil {
log.Error("Unexpected error when getting snapshot",
"error", err, "blockNumber", header.Number.Uint64(), "blockHash", header.Hash())
"error", err, "blockNumber", head.Number.Uint64(), "blockHash", head.Hash())
return 0, common.Hash{}, err
}
if snap.Attestation == nil {
if p.chainConfig.IsLuban(header.Number) {
if p.chainConfig.IsLuban(head.Number) {
log.Debug("once one attestation generated, attestation of snap would not be nil forever basically")
}
return 0, chain.GetHeaderByNumber(0).Hash(), nil
@@ -1759,62 +1864,6 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t
}
// =========================== utility function ==========================
// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
encodeSigHeader(hasher, header, chainId)
hasher.Sum(hash[:0])
return hash
}
func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
err := rlp.Encode(w, []interface{}{
chainId,
header.ParentHash,
header.UncleHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
header.Difficulty,
header.Number,
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
header.MixDigest,
header.Nonce,
})
if err != nil {
panic("can't encode: " + err.Error())
}
}
func encodeSigHeaderWithoutVoteAttestation(w io.Writer, header *types.Header, chainId *big.Int) {
err := rlp.Encode(w, []interface{}{
chainId,
header.ParentHash,
header.UncleHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
header.Difficulty,
header.Number,
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
header.MixDigest,
header.Nonce,
})
if err != nil {
panic("can't encode: " + err.Error())
}
}
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
if snap.inturn(val) {
return 0
@@ -1924,7 +1973,7 @@ func applyMessage(
chainConfig *params.ChainConfig,
chainContext core.ChainContext,
) (uint64, error) {
// TODO: state.Prepare should be called here, now accessList related EIP not affect systemtxs
// TODO(Nathan): state.Prepare should be called here, now accessList related EIP not affect systemtxs
// EIP1153 may cause a critical issue in the future
// Create a new context to be used in the EVM environment
context := core.NewEVMBlockContext(header, chainContext, nil)
@@ -1932,6 +1981,8 @@ func applyMessage(
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, state, chainConfig, vm.Config{})
// Apply the transaction to the current state (included in the env)
// Increment the nonce for the next transaction
state.SetNonce(msg.From(), state.GetNonce(msg.From())+1)
ret, returnGas, err := vmenv.Call(
vm.AccountRef(msg.From()),
*msg.To(),

View File

@@ -1,8 +1,9 @@
package parlia
import (
"crypto/rand"
"fmt"
"math/rand"
mrand "math/rand"
"testing"
"golang.org/x/crypto/sha3"
@@ -47,7 +48,7 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int) {
validators[i] = true
down[i] = i
}
rand.Shuffle(totalValidators, func(i, j int) {
mrand.Shuffle(totalValidators, func(i, j int) {
down[i], down[j] = down[j], down[i]
})
for i := 0; i < downValidators; i++ {
@@ -125,8 +126,8 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int) {
}
func producerBlockDelay(candidates map[int]bool, height, numOfValidators int) (int, uint64) {
s := rand.NewSource(int64(height))
r := rand.New(s)
s := mrand.NewSource(int64(height))
r := mrand.New(s)
n := numOfValidators
backOffSteps := make([]int, 0, n)
for idx := 0; idx < n; idx++ {

View File

@@ -199,6 +199,9 @@ func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.C
}
// Update attestation
// Two scenarios for s.Attestation being nil:
// 1) The first attestation is assembled.
// 2) The snapshot on disk is missing, prompting the creation of a new snapshot using `newSnapshot`.
if s.Attestation != nil && attestation.Data.SourceNumber+1 != attestation.Data.TargetNumber {
s.Attestation.TargetNumber = attestation.Data.TargetNumber
s.Attestation.TargetHash = attestation.Data.TargetHash

View File

@@ -35,6 +35,11 @@ import (
// Tests that simple header verification works, for both good and bad blocks.
func TestHeaderVerification(t *testing.T) {
testHeaderVerification(t, rawdb.HashScheme)
testHeaderVerification(t, rawdb.PathScheme)
}
func testHeaderVerification(t *testing.T, scheme string) {
// Create a simple chain to verify
var (
gspec = &Genesis{Config: params.TestChainConfig}
@@ -45,7 +50,7 @@ func TestHeaderVerification(t *testing.T) {
headers[i] = block.Header()
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer chain.Stop()
for i := 0; i < len(blocks); i++ {

View File

@@ -24,11 +24,11 @@ import (
"math/big"
"runtime"
"sort"
"strings"
"sync"
"sync/atomic"
"time"
mapset "github.com/deckarep/golang-set/v2"
exlru "github.com/hashicorp/golang-lru"
"golang.org/x/crypto/sha3"
@@ -42,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/systemcontracts"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
@@ -53,10 +54,16 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"golang.org/x/exp/slices"
)
var (
badBlockRecords = mapset.NewSet[common.Hash]()
badBlockRecordslimit = 1000
badBlockGauge = metrics.NewRegisteredGauge("chain/insert/badBlock", nil)
headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil)
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
@@ -141,7 +148,7 @@ const (
)
// CacheConfig contains the configuration values for the trie database
// that's resident in a blockchain.
// and state snapshot these are resident in a blockchain.
type CacheConfig struct {
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
@@ -152,11 +159,37 @@ type CacheConfig struct {
Preimages bool // Whether to store preimage of trie key to the disk
TriesInMemory uint64 // How many tries keeps in memory
NoTries bool // Insecure settings. Do not have any tries in databases if enabled.
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
PathSyncFlush bool // Whether sync flush the trienodebuffer of pathdb to disk.
SnapshotNoBuild bool // Whether the background generation is allowed
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
}
// triedbConfig derives the configures for trie database.
func (c *CacheConfig) triedbConfig() *trie.Config {
config := &trie.Config{
Cache: c.TrieCleanLimit,
Preimages: c.Preimages,
NoTries: c.NoTries,
}
if c.StateScheme == rawdb.HashScheme {
config.HashDB = &hashdb.Config{
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
}
}
if c.StateScheme == rawdb.PathScheme {
config.PathDB = &pathdb.Config{
SyncFlush: c.PathSyncFlush,
StateHistory: c.StateHistory,
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
}
}
return config
}
// defaultCacheConfig are the default caching values if none are specified by the
// user (also used during testing).
var defaultCacheConfig = &CacheConfig{
@@ -166,6 +199,15 @@ var defaultCacheConfig = &CacheConfig{
SnapshotLimit: 256,
TriesInMemory: 128,
SnapshotWait: true,
StateScheme: rawdb.HashScheme,
}
// DefaultCacheConfigWithScheme returns a deep copied default cache config with
// a provided trie node scheme.
func DefaultCacheConfigWithScheme(scheme string) *CacheConfig {
config := *defaultCacheConfig
config.StateScheme = scheme
return &config
}
type BlockChainOption func(*BlockChain) (*BlockChain, error)
@@ -279,11 +321,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
diffLayerChanCache, _ := exlru.New(diffLayerCacheLimit)
// Open trie database with provided config
triedb := trie.NewDatabaseWithConfig(db, &trie.Config{
Cache: cacheConfig.TrieCleanLimit,
Preimages: cacheConfig.Preimages,
NoTries: cacheConfig.NoTries,
})
triedb := trie.NewDatabase(db, cacheConfig.triedbConfig())
// Setup the genesis block, commit the provided genesis specification
// to database if the genesis block is not present yet, or load the
// stored one from database.
@@ -291,13 +329,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr
}
log.Info("")
log.Info(strings.Repeat("-", 153))
for _, line := range strings.Split(chainConfig.Description(), "\n") {
log.Info(line)
}
log.Info(strings.Repeat("-", 153))
log.Info("")
systemcontracts.GenesisHash = genesisHash
log.Info("Initialised chain configuration", "config", chainConfig)
// Description of chainConfig is empty now
/*
log.Info("")
log.Info(strings.Repeat("-", 153))
for _, line := range strings.Split(chainConfig.Description(), "\n") {
log.Info(line)
}
log.Info(strings.Repeat("-", 153))
log.Info("")
*/
bc := &BlockChain{
chainConfig: chainConfig,
@@ -355,7 +398,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
// Make sure the state associated with the block is available
head := bc.CurrentBlock()
if !bc.HasState(head.Root) {
if !bc.stateCache.NoTries() && !bc.HasState(head.Root) {
// Head state is missing, before the state recovery, find out the
// disk layer point of snapshot(if it's enabled). Make sure the
// rewound point is lower than disk layer.
@@ -363,8 +406,14 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if bc.cacheConfig.SnapshotLimit > 0 {
diskRoot = rawdb.ReadSnapshotRoot(bc.db)
}
if bc.triedb.Scheme() == rawdb.PathScheme {
recoverable, _ := bc.triedb.Recoverable(diskRoot)
if !bc.HasState(diskRoot) && !recoverable {
diskRoot = bc.triedb.Head()
}
}
if diskRoot != (common.Hash{}) {
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "snaproot", diskRoot)
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "diskRoot", diskRoot)
snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true)
if err != nil {
@@ -510,7 +559,7 @@ func (bc *BlockChain) GetVMConfig() *vm.Config {
return &bc.vmConfig
}
func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts) {
func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts, block *types.Block) {
// TODO, This is a hot fix for the block hash of logs is `0x0000000000000000000000000000000000000000000000000000000000000000` for system tx
// Please check details in https://github.com/bnb-chain/bsc/issues/443
// This is a temporary fix, the official fix should be a hard fork.
@@ -521,6 +570,16 @@ func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts) {
receipts[i].Logs[j].BlockHash = hash
}
}
txs := block.Transactions()
if len(txs) != len(receipts) {
log.Warn("transaction and receipt count mismatch")
return
}
for i, receipt := range receipts {
receipt.EffectiveGasPrice = txs[i].EffectiveGasTipValue(block.BaseFee()) // basefee is supposed to be nil or zero
}
bc.receiptsCache.Add(hash, receipts)
}
@@ -580,7 +639,7 @@ func (bc *BlockChain) empty() bool {
// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 {
if p, ok := bc.engine.(consensus.PoSA); ok {
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(bc, header)
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{header})
if err == nil {
return justifiedBlockNumber
}
@@ -653,18 +712,18 @@ func (bc *BlockChain) loadLastState() error {
blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64())
)
if headHeader.Hash() != headBlock.Hash() {
log.Info("Loaded most recent local header", "number", headHeader.Number, "hash", headHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(headHeader.Time), 0)))
log.Info("Loaded most recent local header", "number", headHeader.Number, "hash", headHeader.Hash(), "hash", headHeader.Root, "td", headerTd, "age", common.PrettyAge(time.Unix(int64(headHeader.Time), 0)))
}
log.Info("Loaded most recent local block", "number", headBlock.Number(), "hash", headBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0)))
log.Info("Loaded most recent local block", "number", headBlock.Number(), "hash", headBlock.Hash(), "root", headBlock.Root(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0)))
if headBlock.Hash() != currentSnapBlock.Hash() {
snapTd := bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64())
log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "td", snapTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0)))
log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "root", currentSnapBlock.Root, "td", snapTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0)))
}
if posa, ok := bc.engine.(consensus.PoSA); ok {
if currentFinalizedHeader := posa.GetFinalizedHeader(bc, headHeader); currentFinalizedHeader != nil {
if currentFinalizedBlock := bc.GetBlockByHash(currentFinalizedHeader.Hash()); currentFinalizedBlock != nil {
finalTd := bc.GetTd(currentFinalizedBlock.Hash(), currentFinalizedBlock.NumberU64())
log.Info("Loaded most recent local finalized block", "number", currentFinalizedBlock.Number(), "hash", currentFinalizedBlock.Hash(), "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalizedBlock.Time()), 0)))
log.Info("Loaded most recent local finalized block", "number", currentFinalizedBlock.Number(), "hash", currentFinalizedBlock.Hash(), "root", currentFinalizedBlock.Root(), "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalizedBlock.Time()), 0)))
}
}
}
@@ -764,33 +823,48 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
pivot := rawdb.ReadLastPivotNumber(bc.db)
frozen, _ := bc.db.Ancients()
// resetState resets the persistent state to genesis if it's not available.
resetState := func() {
log.Info("Reset to block with genesis state", "number", bc.genesisBlock.NumberU64(), "hash", bc.genesisBlock.Hash())
// Short circuit if the genesis state is already present.
if bc.HasState(bc.genesisBlock.Root()) {
return
}
// Reset the state database to empty for committing genesis state.
// Note, it should only happen in path-based scheme and Reset function
// is also only call-able in this mode.
if bc.triedb.Scheme() == rawdb.PathScheme {
if err := bc.triedb.Reset(types.EmptyRootHash); err != nil {
log.Crit("Failed to clean state", "err", err) // Shouldn't happen
}
}
// Write genesis state into database.
if err := CommitGenesisState(bc.db, bc.triedb, bc.genesisBlock.Hash()); err != nil {
log.Crit("Failed to commit genesis state", "err", err)
}
}
updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (*types.Header, bool) {
// Rewind the blockchain, ensuring we don't end up with a stateless head
// block. Note, depth equality is permitted to allow using SetHead as a
// chain reparation mechanism without deleting any data!
if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.Number.Uint64() {
newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64())
lastBlockNum := header.Number.Uint64()
if newHeadBlock == nil {
log.Error("Gap in the chain, rewinding to genesis", "number", header.Number, "hash", header.Hash())
newHeadBlock = bc.genesisBlock
resetState()
} else {
// Block exists, keep rewinding until we find one with state,
// keeping rewinding until we exceed the optional threshold
// root hash
beyondRoot := (root == common.Hash{}) // Flag whether we're beyond the requested root (no root, always true)
enoughBeyondCount := false
beyondCount := 0
for {
beyondCount++
// If a root threshold was requested but not yet crossed, check
if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root {
beyondRoot, rootNumber = true, newHeadBlock.NumberU64()
}
enoughBeyondCount = beyondCount > maxBeyondBlocks
if !bc.HasState(newHeadBlock.Root()) {
if !bc.HasState(newHeadBlock.Root()) && !bc.stateRecoverable(newHeadBlock.Root()) {
log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
if pivot == nil || newHeadBlock.NumberU64() > *pivot {
parent := bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1)
@@ -801,38 +875,21 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
log.Error("Missing block in the middle, aiming genesis", "number", newHeadBlock.NumberU64()-1, "hash", newHeadBlock.ParentHash())
newHeadBlock = bc.genesisBlock
} else {
log.Trace("Rewind passed pivot, aiming genesis", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "pivot", *pivot)
log.Info("Rewind passed pivot, aiming genesis", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "pivot", *pivot)
newHeadBlock = bc.genesisBlock
}
}
if beyondRoot || (enoughBeyondCount && root != common.Hash{}) || newHeadBlock.NumberU64() == 0 {
if enoughBeyondCount && (root != common.Hash{}) && rootNumber == 0 {
for {
lastBlockNum++
block := bc.GetBlockByNumber(lastBlockNum)
if block == nil {
break
}
if block.Root() == root {
rootNumber = block.NumberU64()
break
}
}
}
if beyondRoot || newHeadBlock.NumberU64() == 0 {
if newHeadBlock.NumberU64() == 0 {
// Recommit the genesis state into disk in case the rewinding destination
// is genesis block and the relevant state is gone. In the future this
// rewinding destination can be the earliest block stored in the chain
// if the historical chain pruning is enabled. In that case the logic
// needs to be improved here.
if !bc.HasState(bc.genesisBlock.Root()) {
if err := CommitGenesisState(bc.db, bc.triedb, bc.genesisBlock.Hash()); err != nil {
log.Crit("Failed to commit genesis state", "err", err)
}
log.Debug("Recommitted genesis state to disk")
resetState()
} else if !bc.HasState(newHeadBlock.Root()) {
// Rewind to a block with recoverable state. If the state is
// missing, run the state recovery here.
if err := bc.triedb.Recover(newHeadBlock.Root()); err != nil {
log.Crit("Failed to rollback state", "err", err) // Shouldn't happen
}
}
log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
log.Info("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
break
}
log.Debug("Skipping block with threshold state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "root", newHeadBlock.Root())
@@ -936,7 +993,13 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
if block == nil {
return fmt.Errorf("non existent block [%x..]", hash[:4])
}
// Reset the trie database with the fresh snap synced state.
root := block.Root()
if bc.triedb.Scheme() == rawdb.PathScheme {
if err := bc.triedb.Reset(root); err != nil {
return err
}
}
if !bc.HasState(root) {
return fmt.Errorf("non existent state [%x..]", root[:4])
}
@@ -959,11 +1022,6 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
return nil
}
// StateAtWithSharedPool returns a new mutable state based on a particular point in time with sharedStorage
func (bc *BlockChain) StateAtWithSharedPool(root common.Hash) (*state.StateDB, error) {
return state.NewWithSharedPool(root, bc.stateCache, bc.snaps)
}
// Reset purges the entire blockchain, restoring it to its genesis state.
func (bc *BlockChain) Reset() error {
return bc.ResetWithGenesisBlock(bc.genesisBlock)
@@ -1112,45 +1170,62 @@ func (bc *BlockChain) Stop() {
log.Error("Failed to journal state snapshot", "err", err)
}
}
// Ensure the state of a recent block is also stored to disk before exiting.
// We're writing three different states to catch different restart scenarios:
// - HEAD: So we don't need to reprocess any blocks in the general case
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
if !bc.cacheConfig.TrieDirtyDisabled {
triedb := bc.triedb
for _, offset := range []uint64{0, 1, bc.triesInMemory - 1} {
if number := bc.CurrentBlock().Number.Uint64(); number > offset {
recent := bc.GetBlockByNumber(number - offset)
log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
if err := triedb.Commit(recent.Root(), true); err != nil {
log.Error("Failed to commit recent state trie", "err", err)
} else {
rawdb.WriteSafePointBlockNumber(bc.db, recent.NumberU64())
if bc.triedb.Scheme() == rawdb.PathScheme {
// Ensure that the in-memory trie nodes are journaled to disk properly.
if err := bc.triedb.Journal(bc.CurrentBlock().Root); err != nil {
log.Info("Failed to journal in-memory trie nodes", "err", err)
}
} else {
// Ensure the state of a recent block is also stored to disk before exiting.
// We're writing three different states to catch different restart scenarios:
// - HEAD: So we don't need to reprocess any blocks in the general case
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
if !bc.cacheConfig.TrieDirtyDisabled {
triedb := bc.triedb
var once sync.Once
for _, offset := range []uint64{0, 1, TriesInMemory - 1} {
if number := bc.CurrentBlock().Number.Uint64(); number > offset {
recent := bc.GetBlockByNumber(number - offset)
log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
if err := triedb.Commit(recent.Root(), true); err != nil {
log.Error("Failed to commit recent state trie", "err", err)
} else {
rawdb.WriteSafePointBlockNumber(bc.db, recent.NumberU64())
once.Do(func() {
rawdb.WriteHeadBlockHash(bc.db, recent.Hash())
})
}
}
}
}
if snapBase != (common.Hash{}) {
log.Info("Writing snapshot state to disk", "root", snapBase)
if err := triedb.Commit(snapBase, true); err != nil {
log.Error("Failed to commit recent state trie", "err", err)
} else {
rawdb.WriteSafePointBlockNumber(bc.db, bc.CurrentBlock().Number.Uint64())
if snapBase != (common.Hash{}) {
log.Info("Writing snapshot state to disk", "root", snapBase)
if err := triedb.Commit(snapBase, true); err != nil {
log.Error("Failed to commit recent state trie", "err", err)
} else {
rawdb.WriteSafePointBlockNumber(bc.db, bc.CurrentBlock().Number.Uint64())
}
}
if snapBase != (common.Hash{}) {
log.Info("Writing snapshot state to disk", "root", snapBase)
if err := bc.triedb.Commit(snapBase, true); err != nil {
log.Error("Failed to commit recent state trie", "err", err)
} else {
rawdb.WriteSafePointBlockNumber(bc.db, bc.CurrentBlock().Number.Uint64())
}
}
for !bc.triegc.Empty() {
triedb.Dereference(bc.triegc.PopItem())
}
if _, size, _, _ := triedb.Size(); size != 0 {
log.Error("Dangling trie nodes after full cleanup")
}
}
for !bc.triegc.Empty() {
go triedb.Dereference(bc.triegc.PopItem())
}
if size, _ := triedb.Size(); size != 0 {
log.Error("Dangling trie nodes after full cleanup")
}
}
// Flush the collected preimages to disk
if err := bc.stateCache.TrieDB().Close(); err != nil {
log.Error("Failed to close trie db", "err", err)
// Close the trie database, release all the held resources as the last step.
if err := bc.triedb.Close(); err != nil {
log.Error("Failed to close trie database", "err", err)
}
log.Info("Blockchain stopped")
}
@@ -1526,6 +1601,12 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
bc.commitLock.Lock()
defer bc.commitLock.Unlock()
// If node is running in path mode, skip explicit gc operation
// which is unnecessary in this mode.
if bc.triedb.Scheme() == rawdb.PathScheme {
return nil
}
triedb := bc.stateCache.TrieDB()
// If we're running an archive node, always flush
if bc.cacheConfig.TrieDirtyDisabled {
@@ -1541,8 +1622,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
if current := block.NumberU64(); current > bc.triesInMemory {
// If we exceeded our memory allowance, flush matured singleton nodes to disk
var (
nodes, imgs = triedb.Size()
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
_, nodes, _, imgs = triedb.Size()
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
)
if nodes > limit || imgs > 4*1024*1024 {
triedb.Cap(limit - ethdb.IdealBatchSize)
@@ -1980,7 +2061,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
vtime := time.Since(vstart)
proctime := time.Since(start) // processing + validation
bc.cacheReceipts(block.Hash(), receipts)
bc.cacheBlock(block.Hash(), block)
// Update the metrics touched during block processing and validation
@@ -2013,6 +2093,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
if err != nil {
return it.index, err
}
bc.cacheReceipts(block.Hash(), receipts, block)
// Update the metrics touched during block commit
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
@@ -2026,8 +2109,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
stats.processed++
stats.usedGas += usedGas
dirty, _ := bc.triedb.Size()
stats.report(chain, it.index, dirty, setHead)
trieDiffNodes, trieBufNodes, trieImmutableBufNodes, _ := bc.triedb.Size()
stats.report(chain, it.index, trieDiffNodes, trieBufNodes, trieImmutableBufNodes, setHead)
if !setHead {
// After merge we expect few side chains. Simply count
@@ -2201,6 +2284,12 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
)
parent := it.previous()
for parent != nil && !bc.HasState(parent.Root) {
if bc.stateRecoverable(parent.Root) {
if err := bc.triedb.Recover(parent.Root); err != nil {
return 0, err
}
break
}
hashes = append(hashes, parent.Hash())
numbers = append(numbers, parent.Number.Uint64())
@@ -2260,6 +2349,12 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
parent = block
)
for parent != nil && !bc.HasState(parent.Root()) {
if bc.stateRecoverable(parent.Root()) {
if err := bc.triedb.Recover(parent.Root()); err != nil {
return common.Hash{}, err
}
break
}
hashes = append(hashes, parent.Hash())
numbers = append(numbers, parent.NumberU64())
parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1)
@@ -2773,6 +2868,7 @@ func (bc *BlockChain) maintainTxIndex() {
return
}
defer sub.Unsubscribe()
log.Info("Initialized transaction indexer", "limit", bc.TxLookupLimit())
for {
select {
@@ -2824,15 +2920,22 @@ func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *pa
if vcs != "" {
vcs = fmt.Sprintf("\nVCS: %s", vcs)
}
if badBlockRecords.Cardinality() < badBlockRecordslimit {
badBlockRecords.Add(block.Hash())
badBlockGauge.Update(int64(badBlockRecords.Cardinality()))
}
return fmt.Sprintf(`
########## BAD BLOCK #########
Block: %v (%#x)
Miner: %v
Error: %v
Platform: %v%v
Chain config: %#v
Receipts: %v
##############################
`, block.Number(), block.Hash(), err, platform, vcs, config, receiptString)
`, block.Number(), block.Hash(), block.Coinbase(), err, platform, vcs, config, receiptString)
}
// InsertHeaderChain attempts to insert the given header chain in to the local

View File

@@ -39,7 +39,7 @@ const statsReportLimit = 8 * time.Second
// report prints statistics if some number of blocks have been processed
// or more than a few seconds have passed since the last message.
func (st *insertStats) report(chain []*types.Block, index int, dirty common.StorageSize, setHead bool) {
func (st *insertStats) report(chain []*types.Block, index int, trieDiffNodes, trieBufNodes, trieImmutableBufNodes common.StorageSize, setHead bool) {
// Fetch the timings for the batch
var (
now = mclock.Now()
@@ -56,14 +56,20 @@ func (st *insertStats) report(chain []*types.Block, index int, dirty common.Stor
// Assemble the log context and send it to the logger
context := []interface{}{
"number", end.Number(), "hash", end.Hash(),
"number", end.Number(), "hash", end.Hash(), "miner", end.Coinbase(),
"blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000,
"elapsed", common.PrettyDuration(elapsed), "mgasps", float64(st.usedGas) * 1000 / float64(elapsed),
}
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
}
context = append(context, []interface{}{"dirty", dirty}...)
if trieDiffNodes != 0 { // pathdb
context = append(context, []interface{}{"triediffs", trieDiffNodes}...)
context = append(context, []interface{}{"triedirty", trieBufNodes}...)
context = append(context, []interface{}{"trieimutabledirty", trieImmutableBufNodes}...)
} else {
context = append(context, []interface{}{"triedirty", trieBufNodes}...)
}
if st.queued > 0 {
context = append(context, []interface{}{"queued", st.queued}...)

View File

@@ -71,7 +71,7 @@ func (bc *BlockChain) CurrentSafeBlock() *types.Header {
if currentHeader == nil {
return nil
}
_, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, currentHeader)
_, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{currentHeader})
if err == nil {
return bc.GetHeaderByHash(justifiedBlockHash)
}
@@ -319,10 +319,16 @@ func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
return bc.HasState(block.Root())
}
// TrieNode retrieves a blob of data associated with a trie node
// either from ephemeral in-memory cache, or from persistent storage.
func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
return bc.stateCache.TrieDB().Node(hash)
// stateRecoverable checks if the specified state is recoverable.
// Note, this function assumes the state is not present, because
// state is not treated as recoverable if it's available, thus
// false will be returned in this case.
func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
if bc.triedb.Scheme() == rawdb.HashScheme {
return false
}
result, _ := bc.triedb.Recoverable(root)
return result
}
// ContractCodeWithPrefix retrieves a blob of data associated with a contract

View File

@@ -22,6 +22,7 @@ package core
import (
"math/big"
"path"
"testing"
"time"
@@ -1749,16 +1750,23 @@ func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
}
func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
testRepairWithScheme(t, tt, snapshots, scheme)
}
}
func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
// It's hard to follow the test case, visualize the input
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
// fmt.Println(tt.dump(true))
// Create a temporary persistent database
datadir := t.TempDir()
ancient := path.Join(datadir, "ancient")
db, err := rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: datadir,
AncientsDirectory: ancient,
})
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
@@ -1777,6 +1785,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, // Disable snapshot by default
StateScheme: scheme,
}
)
defer engine.Close()
@@ -1807,7 +1816,9 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
if tt.commitBlock > 0 {
chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), false)
if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil {
t.Fatalf("Failed to flush trie state: %v", err)
}
if snapshots {
if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err)
@@ -1830,21 +1841,21 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
rawdb.WriteLastPivotNumber(db, *tt.pivotBlock)
}
// Pull the plug on the database, simulating a hard crash
chain.triedb.Close()
db.Close()
chain.stopWithoutSaving()
// Start a new blockchain back up and see where the repair leads us
db, err = rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: datadir,
AncientsDirectory: ancient,
})
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
}
defer db.Close()
newChain, err := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -1887,17 +1898,22 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
// In this case the snapshot layer of B3 is not created because of existent
// state.
func TestIssue23496(t *testing.T) {
testIssue23496(t, rawdb.HashScheme)
testIssue23496(t, rawdb.PathScheme)
}
func testIssue23496(t *testing.T, scheme string) {
// It's hard to follow the test case, visualize the input
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
// Create a temporary persistent database
datadir := t.TempDir()
ancient := path.Join(datadir, "ancient")
db, err := rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: datadir,
AncientsDirectory: ancient,
})
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
}
@@ -1910,16 +1926,8 @@ func TestIssue23496(t *testing.T) {
BaseFee: big.NewInt(params.InitialBaseFee),
}
engine = ethash.NewFullFaker()
config = &CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
TriesInMemory: 128,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 256,
SnapshotWait: true,
}
)
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
@@ -1932,7 +1940,7 @@ func TestIssue23496(t *testing.T) {
if _, err := chain.InsertChain(blocks[:1]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
chain.stateCache.TrieDB().Commit(blocks[0].Root(), false)
chain.triedb.Commit(blocks[0].Root(), false)
// Insert block B2 and commit the snapshot into disk
if _, err := chain.InsertChain(blocks[1:2]); err != nil {
@@ -1946,7 +1954,7 @@ func TestIssue23496(t *testing.T) {
if _, err := chain.InsertChain(blocks[2:3]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
chain.stateCache.TrieDB().Commit(blocks[2].Root(), false)
chain.triedb.Commit(blocks[2].Root(), false)
// Insert the remaining blocks
if _, err := chain.InsertChain(blocks[3:]); err != nil {
@@ -1954,20 +1962,21 @@ func TestIssue23496(t *testing.T) {
}
// Pull the plug on the database, simulating a hard crash
chain.triedb.Close()
db.Close()
chain.stopWithoutSaving()
// Start a new blockchain back up and see where the repair leads us
db, err = rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: datadir,
AncientsDirectory: ancient,
})
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
}
defer db.Close()
chain, err = NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -1979,8 +1988,12 @@ func TestIssue23496(t *testing.T) {
if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4))
}
if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(1) {
t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(1))
expHead := uint64(1)
if scheme == rawdb.PathScheme {
expHead = uint64(2)
}
if head := chain.CurrentBlock(); head.Number.Uint64() != expHead {
t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead)
}
// Reinsert B2-B4

View File

@@ -22,6 +22,7 @@ package core
import (
"fmt"
"math/big"
"path"
"strings"
"testing"
"time"
@@ -29,9 +30,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
)
// rewindTest is a test case for chain rollback upon user request.
@@ -1949,16 +1954,23 @@ func testLongReorgedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) {
}
func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
testSetHeadWithScheme(t, tt, snapshots, scheme)
}
}
func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
// It's hard to follow the test case, visualize the input
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
// fmt.Println(tt.dump(false))
// Create a temporary persistent database
datadir := t.TempDir()
ancient := path.Join(datadir, "ancient")
db, err := rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: datadir,
AncientsDirectory: ancient,
})
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
@@ -1977,6 +1989,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, // Disable snapshot
StateScheme: scheme,
}
)
if snapshots {
@@ -2008,7 +2021,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
t.Fatalf("Failed to import canonical chain start: %v", err)
}
if tt.commitBlock > 0 {
chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), false)
chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false)
if snapshots {
if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err)
@@ -2018,14 +2031,17 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil {
t.Fatalf("Failed to import canonical chain tail: %v", err)
}
// Manually dereference anything not committed to not have to work with 128+ tries
for _, block := range sideblocks {
chain.stateCache.TrieDB().Dereference(block.Root())
// Reopen the trie database without persisting in-memory dirty nodes.
chain.triedb.Close()
dbconfig := &trie.Config{}
if scheme == rawdb.PathScheme {
dbconfig.PathDB = pathdb.Defaults
} else {
dbconfig.HashDB = hashdb.Defaults
}
for _, block := range canonblocks {
chain.stateCache.TrieDB().Dereference(block.Root())
}
chain.stateCache.Purge()
chain.triedb = trie.NewDatabase(chain.db, dbconfig)
chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb)
// Force run a freeze cycle
type freezer interface {
Freeze(threshold uint64) error

View File

@@ -24,6 +24,7 @@ import (
"fmt"
"math/big"
"os"
"path"
"strings"
"testing"
"time"
@@ -39,6 +40,7 @@ import (
// snapshotTestBasic wraps the common testing fields in the snapshot tests.
type snapshotTestBasic struct {
scheme string // Disk scheme used for storing trie nodes
chainBlocks int // Number of blocks to generate for the canonical chain
snapshotBlock uint64 // Block number of the relevant snapshot disk layer
commitBlock uint64 // Block number for which to commit the state to disk
@@ -51,6 +53,7 @@ type snapshotTestBasic struct {
// share fields, set in runtime
datadir string
ancient string
db ethdb.Database
genDb ethdb.Database
engine consensus.Engine
@@ -60,10 +63,11 @@ type snapshotTestBasic struct {
func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Block) {
// Create a temporary persistent database
datadir := t.TempDir()
ancient := path.Join(datadir, "ancient")
db, err := rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: datadir,
AncientsDirectory: ancient,
})
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
@@ -75,13 +79,8 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
Config: params.AllEthashProtocolChanges,
}
engine = ethash.NewFullFaker()
// Snapshot is enabled, the first snapshot is created from the Genesis.
// The snapshot memory allowance is 256MB, it means no snapshot flush
// will happen during the block insertion.
cacheConfig = defaultCacheConfig
)
chain, err := NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(basic.scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
@@ -102,7 +101,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
startPoint = point
if basic.commitBlock > 0 && basic.commitBlock == point {
chain.stateCache.TrieDB().Commit(blocks[point-1].Root(), false)
chain.TrieDB().Commit(blocks[point-1].Root(), false)
}
if basic.snapshotBlock > 0 && basic.snapshotBlock == point {
// Flushing the entire snap tree into the disk, the
@@ -121,6 +120,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
// Set runtime fields
basic.datadir = datadir
basic.ancient = ancient
basic.db = db
basic.genDb = genDb
basic.engine = engine
@@ -210,6 +210,7 @@ func (basic *snapshotTestBasic) teardown() {
basic.db.Close()
basic.genDb.Close()
os.RemoveAll(basic.datadir)
os.RemoveAll(basic.ancient)
}
// snapshotTest is a test case type for normal snapshot recovery.
@@ -226,7 +227,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {
// Restart the chain normally
chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -235,7 +236,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {
snaptest.verify(t, newchain, blocks)
}
// crashSnapshotTest is a test case type for innormal snapshot recovery.
// crashSnapshotTest is a test case type for irregular snapshot recovery.
// It can be used for testing that restart Geth after the crash.
type crashSnapshotTest struct {
snapshotTestBasic
@@ -251,13 +252,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
db := chain.db
db.Close()
chain.stopWithoutSaving()
chain.triedb.Close()
// Start a new blockchain back up and see where the repair leads us
newdb, err := rawdb.Open(rawdb.OpenOptions{
Directory: snaptest.datadir,
AncientsDirectory: snaptest.datadir,
AncientsDirectory: snaptest.ancient,
})
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
}
@@ -267,13 +268,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
// the crash, we do restart twice here: one after the crash and one
// after the normal stop. It's used to ensure the broken snapshot
// can be detected all the time.
newchain, err := NewBlockChain(newdb, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
newchain.Stop()
newchain, err = NewBlockChain(newdb, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err = NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -300,7 +301,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
// Insert blocks without enabling snapshot if gapping is required.
chain.Stop()
gappedBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {})
gappedBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {})
// Insert a few more blocks without enabling snapshot
var cacheConfig = &CacheConfig{
@@ -309,6 +310,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute,
TriesInMemory: 128,
SnapshotLimit: 0,
StateScheme: snaptest.scheme,
}
newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
@@ -318,7 +320,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
newchain.Stop()
// Restart the chain with enabling the snapshot
newchain, err = NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -346,7 +348,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
chain.SetHead(snaptest.setHead)
chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@@ -381,16 +383,17 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0,
TriesInMemory: 128,
StateScheme: snaptest.scheme,
}
newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
newBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.newBlocks, func(i int, b *BlockGen) {})
newBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.newBlocks, func(i int, b *BlockGen) {})
newchain.InsertChain(newBlocks)
newchain.Stop()
// Restart the chain, the wiper should starts working
// Restart the chain, the wiper should start working
config = &CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
@@ -398,6 +401,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
SnapshotLimit: 256,
SnapshotWait: false, // Don't wait rebuild
TriesInMemory: 128,
StateScheme: snaptest.scheme,
}
tmp, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
@@ -405,14 +409,15 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
}
// Simulate the blockchain crash.
tmp.triedb.Close()
tmp.stopWithoutSaving()
newchain, err = NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
defer newchain.Stop()
snaptest.verify(t, newchain, blocks)
newchain.Stop()
}
// Tests a Geth restart with valid snapshot. Before the shutdown, all snapshot
@@ -436,20 +441,23 @@ func TestRestartWithNewSnapshot(t *testing.T) {
// Expected head fast block: C8
// Expected head block : C8
// Expected snapshot disk : G
test := &snapshotTest{
snapshotTestBasic{
chainBlocks: 8,
snapshotBlock: 0,
commitBlock: 0,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: 8,
expSnapshotBottom: 0, // Initial disk layer built from genesis
},
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
test := &snapshotTest{
snapshotTestBasic{
scheme: scheme,
chainBlocks: 8,
snapshotBlock: 0,
commitBlock: 0,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: 8,
expSnapshotBottom: 0, // Initial disk layer built from genesis
},
}
test.test(t)
test.teardown()
}
test.test(t)
test.teardown()
}
// Tests a Geth was crashed and restarts with a broken snapshot. In this case the
@@ -475,20 +483,24 @@ func TestNoCommitCrashWithNewSnapshot(t *testing.T) {
// Expected head fast block: C8
// Expected head block : G
// Expected snapshot disk : C4
test := &crashSnapshotTest{
snapshotTestBasic{
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 0,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: 0,
expSnapshotBottom: 4, // Last committed disk layer, wait recovery
},
//for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
for _, scheme := range []string{rawdb.HashScheme} {
test := &crashSnapshotTest{
snapshotTestBasic{
scheme: scheme,
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 0,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: 0,
expSnapshotBottom: 4, // Last committed disk layer, wait recovery
},
}
test.test(t)
test.teardown()
}
test.test(t)
test.teardown()
}
// Tests a Geth was crashed and restarts with a broken snapshot. In this case the
@@ -514,20 +526,24 @@ func TestLowCommitCrashWithNewSnapshot(t *testing.T) {
// Expected head fast block: C8
// Expected head block : C2
// Expected snapshot disk : C4
test := &crashSnapshotTest{
snapshotTestBasic{
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 2,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: 2,
expSnapshotBottom: 4, // Last committed disk layer, wait recovery
},
//for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
for _, scheme := range []string{rawdb.HashScheme} {
test := &crashSnapshotTest{
snapshotTestBasic{
scheme: scheme,
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 2,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: 2,
expSnapshotBottom: 4, // Last committed disk layer, wait recovery
},
}
test.test(t)
test.teardown()
}
test.test(t)
test.teardown()
}
// Tests a Geth was crashed and restarts with a broken snapshot. In this case
@@ -553,20 +569,27 @@ func TestHighCommitCrashWithNewSnapshot(t *testing.T) {
// Expected head fast block: C8
// Expected head block : G
// Expected snapshot disk : C4
test := &crashSnapshotTest{
snapshotTestBasic{
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 6,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: 0,
expSnapshotBottom: 4, // Last committed disk layer, wait recovery
},
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
expHead := uint64(0)
if scheme == rawdb.PathScheme {
expHead = uint64(4)
}
test := &crashSnapshotTest{
snapshotTestBasic{
scheme: scheme,
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 6,
expCanonicalBlocks: 8,
expHeadHeader: 8,
expHeadFastBlock: 8,
expHeadBlock: expHead,
expSnapshotBottom: 4, // Last committed disk layer, wait recovery
},
}
test.test(t)
test.teardown()
}
test.test(t)
test.teardown()
}
// Tests a Geth was running with snapshot enabled. Then restarts without
@@ -590,21 +613,24 @@ func TestGappedNewSnapshot(t *testing.T) {
// Expected head fast block: C10
// Expected head block : C10
// Expected snapshot disk : C10
test := &gappedSnapshotTest{
snapshotTestBasic: snapshotTestBasic{
chainBlocks: 8,
snapshotBlock: 0,
commitBlock: 0,
expCanonicalBlocks: 10,
expHeadHeader: 10,
expHeadFastBlock: 10,
expHeadBlock: 10,
expSnapshotBottom: 10, // Rebuilt snapshot from the latest HEAD
},
gapped: 2,
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
test := &gappedSnapshotTest{
snapshotTestBasic: snapshotTestBasic{
scheme: scheme,
chainBlocks: 8,
snapshotBlock: 0,
commitBlock: 0,
expCanonicalBlocks: 10,
expHeadHeader: 10,
expHeadFastBlock: 10,
expHeadBlock: 10,
expSnapshotBottom: 10, // Rebuilt snapshot from the latest HEAD
},
gapped: 2,
}
test.test(t)
test.teardown()
}
test.test(t)
test.teardown()
}
// Tests the Geth was running with snapshot enabled and resetHead is applied.
@@ -628,21 +654,24 @@ func TestSetHeadWithNewSnapshot(t *testing.T) {
// Expected head fast block: C4
// Expected head block : C4
// Expected snapshot disk : G
test := &setHeadSnapshotTest{
snapshotTestBasic: snapshotTestBasic{
chainBlocks: 8,
snapshotBlock: 0,
commitBlock: 0,
expCanonicalBlocks: 4,
expHeadHeader: 4,
expHeadFastBlock: 4,
expHeadBlock: 4,
expSnapshotBottom: 0, // The initial disk layer is built from the genesis
},
setHead: 4,
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
test := &setHeadSnapshotTest{
snapshotTestBasic: snapshotTestBasic{
scheme: scheme,
chainBlocks: 8,
snapshotBlock: 0,
commitBlock: 0,
expCanonicalBlocks: 4,
expHeadHeader: 4,
expHeadFastBlock: 4,
expHeadBlock: 4,
expSnapshotBottom: 0, // The initial disk layer is built from the genesis
},
setHead: 4,
}
test.test(t)
test.teardown()
}
test.test(t)
test.teardown()
}
// Tests the Geth was running with a complete snapshot and then imports a few
@@ -666,19 +695,22 @@ func TestRecoverSnapshotFromWipingCrash(t *testing.T) {
// Expected head fast block: C10
// Expected head block : C8
// Expected snapshot disk : C10
test := &wipeCrashSnapshotTest{
snapshotTestBasic: snapshotTestBasic{
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 0,
expCanonicalBlocks: 10,
expHeadHeader: 10,
expHeadFastBlock: 10,
expHeadBlock: 10,
expSnapshotBottom: 10,
},
newBlocks: 2,
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
test := &wipeCrashSnapshotTest{
snapshotTestBasic: snapshotTestBasic{
scheme: scheme,
chainBlocks: 8,
snapshotBlock: 4,
commitBlock: 0,
expCanonicalBlocks: 10,
expHeadHeader: 10,
expHeadFastBlock: 10,
expHeadBlock: 10,
expSnapshotBottom: 10,
},
newBlocks: 2,
}
test.test(t)
test.teardown()
}
test.test(t)
test.teardown()
}

View File

@@ -1807,7 +1807,7 @@ func TestTrieForkGC(t *testing.T) {
chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
}
if nodes, _ := chain.TrieDB().Size(); nodes > 0 {
if _, nodes, _, _ := chain.TrieDB().Size(); nodes > 0 {
t.Fatalf("stale tries still alive after garbase collection")
}
}

View File

@@ -633,13 +633,16 @@ func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan
request <- &Retrieval{Bit: bit, Sections: sections, Context: s.ctx}
result := <-request
// Deliver a result before s.Close() to avoid a deadlock
s.deliverSections(result.Bit, result.Sections, result.Bitsets)
if result.Error != nil {
s.errLock.Lock()
s.err = result.Error
s.errLock.Unlock()
s.Close()
}
s.deliverSections(result.Bit, result.Sections, result.Bitsets)
}
}
}

View File

@@ -205,6 +205,10 @@ func (b *BlockGen) AddUncle(h *types.Header) {
h.GasLimit = parent.GasLimit
if b.config.IsLondon(h.Number) {
h.BaseFee = eip1559.CalcBaseFee(b.config, parent)
if b.config.Parlia == nil && !b.config.IsLondon(parent.Number) {
parentGasLimit := parent.GasLimit * b.config.ElasticityMultiplier()
h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
}
b.uncles = append(b.uncles, h)
}
@@ -280,7 +284,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
chainreader := &fakeChainReader{config: config}
genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) {
genblock := func(i int, parent *types.Block, triedb *trie.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
b.header = makeHeader(chainreader, parent, statedb, b.engine)
@@ -308,7 +312,11 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 {
misc.ApplyDAOHardFork(statedb)
}
systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, statedb)
if !config.IsFeynman(b.header.Number, b.header.Time) {
systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb)
}
// Execute any user modifications to the block
if gen != nil {
gen(i, b)
@@ -324,19 +332,23 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if err != nil {
panic(fmt.Sprintf("state write error: %v", err))
}
if err := statedb.Database().TrieDB().Commit(root, false); err != nil {
if err = triedb.Commit(root, false); err != nil {
panic(fmt.Sprintf("trie write error: %v", err))
}
return block, b.receipts
}
return nil, nil
}
// Forcibly use hash-based state scheme for retaining all nodes in disk.
triedb := trie.NewDatabase(db, trie.HashDefaults)
defer triedb.Close()
for i := 0; i < n; i++ {
statedb, err := state.New(parent.Root(), state.NewDatabase(db), nil)
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil)
if err != nil {
panic(err)
}
block, receipt := genblock(i, parent, statedb)
block, receipt := genblock(i, parent, triedb, statedb)
blocks[i] = block
receipts[i] = receipt
parent = block
@@ -349,7 +361,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
// then generate chain on top.
func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) {
db := rawdb.NewMemoryDatabase()
_, err := genesis.Commit(db, trie.NewDatabase(db))
triedb := trie.NewDatabase(db, trie.HashDefaults)
defer triedb.Close()
_, err := genesis.Commit(db, triedb)
if err != nil {
panic(err)
}
@@ -380,6 +394,10 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
}
if chain.Config().IsLondon(header.Number) {
header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header())
if chain.Config().Parlia == nil && !chain.Config().IsLondon(parent.Number()) {
parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier()
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
}
return header
}

View File

@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
func TestGenerateWithdrawalChain(t *testing.T) {
@@ -74,8 +75,7 @@ func TestGenerateWithdrawalChain(t *testing.T) {
Storage: storage,
Code: common.Hex2Bytes("600154600354"),
}
genesis := gspec.MustCommit(gendb)
genesis := gspec.MustCommit(gendb, trie.NewDatabase(gendb, trie.HashDefaults))
chain, _ := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) {
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(address), address, big.NewInt(1000), params.TxGas, new(big.Int).Add(gen.BaseFee(), common.Big1), nil), signer, key)
@@ -146,6 +146,7 @@ func ExampleGenerateChain() {
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
db = rawdb.NewMemoryDatabase()
genDb = rawdb.NewMemoryDatabase()
)
// Ensure that key1 has some funds in the genesis block.
@@ -153,13 +154,13 @@ func ExampleGenerateChain() {
Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
}
genesis := gspec.MustCommit(db)
genesis := gspec.MustCommit(genDb, trie.NewDatabase(genDb, trie.HashDefaults))
// This call generates a chain of 5 blocks. The function runs for
// each block and adds different features to gen based on the
// block index.
signer := types.HomesteadSigner{}
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) {
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genDb, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
// In block 1, addr1 sends addr2 some ether.
@@ -188,7 +189,7 @@ func ExampleGenerateChain() {
})
// Import the chain. This runs all block validation rules.
blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.HashScheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
if i, err := blockchain.InsertChain(chain); err != nil {

View File

@@ -83,7 +83,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
}
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
}
bc.Stop()
@@ -106,7 +106,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
}
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
}
bc.Stop()
@@ -131,7 +131,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
}
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
}
blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
@@ -149,7 +149,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
}
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
}
blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})

View File

@@ -19,6 +19,7 @@ func preHertzConfig() *params.ChainConfig {
config.LondonBlock = nil
config.BerlinBlock = nil
config.HertzBlock = nil
config.HertzfixBlock = nil
return &config
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
func newGwei(n int64) *big.Int {
@@ -42,7 +43,7 @@ func TestGasUsage(t *testing.T, config *params.ChainConfig, engine consensus.Eng
},
},
}
genesis = gspec.MustCommit(db)
genesis = gspec.MustCommit(db, trie.NewDatabase(db, nil))
)
blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *core.BlockGen) {
@@ -61,7 +62,7 @@ func TestGasUsage(t *testing.T, config *params.ChainConfig, engine consensus.Eng
// Import the canonical chain
diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb)
gspec.MustCommit(diskdb, trie.NewDatabase(diskdb, nil))
chain, err := core.NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {

View File

@@ -137,5 +137,9 @@ func (f *ForkChoice) ReorgNeededWithFastFinality(current *types.Header, header *
return f.ReorgNeeded(current, header)
}
if justifiedNumber > curJustifiedNumber && header.Number.Cmp(current.Number) <= 0 {
log.Info("Chain find higher justifiedNumber", "fromHeight", current.Number, "fromHash", current.Hash(), "fromMiner", current.Coinbase, "fromJustified", curJustifiedNumber,
"toHeight", header.Number, "toHash", header.Hash(), "toMiner", header.Coinbase, "toJustified", justifiedNumber)
}
return justifiedNumber > curJustifiedNumber, nil
}

View File

@@ -98,6 +98,32 @@ func NewID(config *params.ChainConfig, genesis common.Hash, head, time uint64) I
return ID{Hash: checksumToBytes(hash), Next: 0}
}
// NextForkHash calculates the forkHash from genesis to the next fork block number or time
func NextForkHash(config *params.ChainConfig, genesis common.Hash, head uint64, time uint64) [4]byte {
// Calculate the starting checksum from the genesis hash
hash := crc32.ChecksumIEEE(genesis[:])
// Calculate the next fork checksum
forksByBlock, forksByTime := gatherForks(config)
for _, fork := range forksByBlock {
if fork > head {
// Checksum the previous hash and nextFork number and return
return checksumToBytes(checksumUpdate(hash, fork))
}
// Fork already passed, checksum the previous hash and the fork number
hash = checksumUpdate(hash, fork)
}
for _, fork := range forksByTime {
if fork > time {
// Checksum the previous hash and nextFork time and return
return checksumToBytes(checksumUpdate(hash, fork))
}
// Fork already passed, checksum the previous hash and the fork time
hash = checksumUpdate(hash, fork)
}
return checksumToBytes(hash)
}
// NewIDWithChain calculates the Ethereum fork ID from an existing chain instance.
func NewIDWithChain(chain Blockchain) ID {
head := chain.CurrentHeader()

View File

@@ -23,8 +23,6 @@ import (
"errors"
"fmt"
"math/big"
"reflect"
"regexp"
"strings"
"github.com/ethereum/go-ethereum/common"
@@ -32,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/systemcontracts"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
@@ -65,9 +62,9 @@ type Genesis struct {
Number uint64 `json:"number"`
GasUsed uint64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty" toml:",omitempty"` // EIP-4844, TODO: remove tag `omitempty` after cancun fork
BlobGasUsed *uint64 `json:"blobGasUsed,omitempty" toml:",omitempty"` // EIP-4844, TODO: remove tag `omitempty` after cancun fork
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
BlobGasUsed *uint64 `json:"blobGasUsed,omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
}
func ReadGenesis(db ethdb.Database) (*Genesis, error) {
@@ -123,8 +120,8 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
return nil
}
// deriveHash computes the state root according to the genesis specification.
func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
// hash computes the state root according to the genesis specification.
func (ga *GenesisAlloc) hash() (common.Hash, error) {
// Create an ephemeral in-memory database for computing hash,
// all the derived states will be discarded to not pollute disk.
db := state.NewDatabase(rawdb.NewMemoryDatabase())
@@ -145,9 +142,9 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
return root, err
}
// flush is very similar with deriveHash, but the main difference is
// all the generated states will be persisted into the given database.
// Also, the genesis state specification will be flushed as well.
// flush is very similar with hash, but the main difference is all the generated
// states will be persisted into the given database. Also, the genesis state
// specification will be flushed as well.
func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
trieConfig := triedb.Config()
if trieConfig != nil {
@@ -202,8 +199,8 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash comm
// - private network, can't recover
var genesis *Genesis
switch blockhash {
case params.MainnetGenesisHash:
genesis = DefaultGenesisBlock()
case params.BSCGenesisHash:
genesis = DefaultBSCGenesisBlock()
}
if genesis != nil {
alloc = genesis.Alloc
@@ -276,10 +273,15 @@ func (e *GenesisMismatchError) Error() string {
return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
}
// ChainOverrides contains the changes to chain config.
// ChainOverrides contains the changes to chain config
// Typically, these modifications involve hardforks that are not enabled on the BSC mainnet, intended for testing purposes.
type ChainOverrides struct {
OverrideCancun *uint64
OverrideVerkle *uint64
OverrideShanghai *uint64
OverrideKepler *uint64
OverrideCancun *uint64
OverrideVerkle *uint64
OverrideFeynman *uint64
OverrideFeynmanFix *uint64
}
// SetupGenesisBlock writes or updates the genesis block in db.
@@ -305,21 +307,32 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
}
applyOverrides := func(config *params.ChainConfig) {
if config != nil {
if overrides != nil && overrides.OverrideShanghai != nil {
config.ShanghaiTime = overrides.OverrideShanghai
}
if overrides != nil && overrides.OverrideKepler != nil {
config.KeplerTime = overrides.OverrideKepler
}
if overrides != nil && overrides.OverrideCancun != nil {
config.CancunTime = overrides.OverrideCancun
}
if overrides != nil && overrides.OverrideVerkle != nil {
config.VerkleTime = overrides.OverrideVerkle
}
if overrides != nil && overrides.OverrideFeynman != nil {
config.FeynmanTime = overrides.OverrideFeynman
}
if overrides != nil && overrides.OverrideFeynmanFix != nil {
config.FeynmanFixTime = overrides.OverrideFeynmanFix
}
}
}
// Just commit the new block if there is no stored genesis block.
stored := rawdb.ReadCanonicalHash(db, 0)
systemcontracts.GenesisHash = stored
if (stored == common.Hash{}) {
if genesis == nil {
log.Info("Writing default main-net genesis block")
genesis = DefaultGenesisBlock()
log.Info("Writing default BSC mainnet genesis block")
genesis = DefaultBSCGenesisBlock()
} else {
log.Info("Writing custom genesis block")
}
@@ -328,14 +341,17 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
return genesis.Config, common.Hash{}, err
}
applyOverrides(genesis.Config)
log.Info("genesis block hash", "hash", block.Hash())
return genesis.Config, block.Hash(), nil
}
// We have the genesis block in database(perhaps in ancient database)
// but the corresponding state is missing.
// The genesis block is present(perhaps in ancient database) while the
// state database is not initialized yet. It can happen that the node
// is initialized with an external ancient store. Commit genesis state
// in this case.
header := rawdb.ReadHeader(db, stored, 0)
if header.Root != types.EmptyRootHash && !rawdb.HasLegacyTrieNode(db, header.Root) {
if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) {
if genesis == nil {
genesis = DefaultGenesisBlock()
genesis = DefaultBSCGenesisBlock()
}
// Ensure the stored genesis matches with the given one.
hash := genesis.ToBlock().Hash()
@@ -396,14 +412,19 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
return newcfg, stored, nil
}
// LoadChainConfig loads the stored chain config if it is already present in
// database, otherwise, return the config in the provided genesis specification.
// LoadChainConfig retrieves the predefined chain configuration for the built-in network.
// For non-built-in networks, it first attempts to load the stored chain configuration from the database.
// If the configuration is not present, it returns the configuration specified in the provided genesis specification.
func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
// Load the stored chain config from the database. It can be nil
// in case the database is empty. Notably, we only care about the
// chain config corresponds to the canonical chain.
stored := rawdb.ReadCanonicalHash(db, 0)
if stored != (common.Hash{}) {
builtInConf := params.GetBuiltInChainConfig(stored)
if builtInConf != nil {
return builtInConf, stored, nil
}
storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg != nil {
return storedcfg, stored, nil
@@ -429,76 +450,20 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig,
return params.BSCChainConfig, params.BSCGenesisHash, nil
}
// For any block in g.Config which is nil but the same block in defaultConfig is not
// set the block in genesis config to the block in defaultConfig.
// Reflection is used to avoid a long series of if statements with hardcoded block names.
func (g *Genesis) setDefaultBlockValues(defaultConfig *params.ChainConfig) {
// Regex to match block names
blockRegex := regexp.MustCompile(`.*Block$`)
// Get reflect values
gConfigElem := reflect.ValueOf(g.Config).Elem()
defaultConfigElem := reflect.ValueOf(defaultConfig).Elem()
// Iterate over fields in config
for i := 0; i < gConfigElem.NumField(); i++ {
gConfigField := gConfigElem.Field(i)
defaultConfigField := defaultConfigElem.Field(i)
fieldName := gConfigElem.Type().Field(i).Name
// Use the regex to check if the field is a Block field
if gConfigField.Kind() == reflect.Ptr && blockRegex.MatchString(fieldName) {
if gConfigField.IsNil() {
gConfigField.Set(defaultConfigField)
}
}
}
}
// Hard fork block height specified in config.toml has higher priority, but
// if it is not specified in config.toml, use the default height in code.
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
var defaultConfig *params.ChainConfig
switch {
case ghash == params.MainnetGenesisHash:
defaultConfig = params.MainnetChainConfig
case ghash == params.BSCGenesisHash:
defaultConfig = params.BSCChainConfig
case ghash == params.ChapelGenesisHash:
defaultConfig = params.ChapelChainConfig
case ghash == params.RialtoGenesisHash:
defaultConfig = params.RialtoChainConfig
default:
if g != nil {
// it could be a custom config for QA test, just return
return g.Config
}
defaultConfig = params.AllEthashProtocolChanges
conf := params.GetBuiltInChainConfig(ghash)
if conf != nil {
return conf
}
if g == nil || g.Config == nil {
return defaultConfig
if g != nil {
return g.Config // it could be a custom config for QA test, just return
}
g.setDefaultBlockValues(defaultConfig)
// BSC Parlia set up
if g.Config.Parlia == nil {
g.Config.Parlia = defaultConfig.Parlia
} else {
if g.Config.Parlia.Period == 0 {
g.Config.Parlia.Period = defaultConfig.Parlia.Period
}
if g.Config.Parlia.Epoch == 0 {
g.Config.Parlia.Epoch = defaultConfig.Parlia.Epoch
}
}
return g.Config
return params.AllEthashProtocolChanges
}
// ToBlock returns the genesis block according to genesis specification.
func (g *Genesis) ToBlock() *types.Block {
root, err := g.Alloc.deriveHash()
root, err := g.Alloc.hash()
if err != nil {
panic(err)
}
@@ -532,7 +497,7 @@ func (g *Genesis) ToBlock() *types.Block {
var withdrawals []*types.Withdrawal
if conf := g.Config; conf != nil {
num := big.NewInt(int64(g.Number))
if conf.IsShanghai(num, g.Timestamp) {
if conf.Parlia == nil && conf.IsShanghai(num, g.Timestamp) {
head.WithdrawalsHash = &types.EmptyWithdrawalsHash
withdrawals = make([]*types.Withdrawal, 0)
}
@@ -586,10 +551,8 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *trie.Database) (*types.Block
// MustCommit writes the genesis block and state to db, panicking on error.
// The block is committed as the canonical head block.
// Note the state changes will be committed in hash-based scheme, use Commit
// if path-scheme is preferred.
func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
block, err := g.Commit(db, trie.NewDatabase(db))
func (g *Genesis) MustCommit(db ethdb.Database, triedb *trie.Database) *types.Block {
block, err := g.Commit(db, triedb)
if err != nil {
panic(err)
}
@@ -608,6 +571,38 @@ func DefaultGenesisBlock() *Genesis {
}
}
// DefaultBSCGenesisBlock returns the BSC mainnet genesis block.
func DefaultBSCGenesisBlock() *Genesis {
alloc := decodePrealloc(bscMainnetAllocData)
return &Genesis{
Config: params.BSCChainConfig,
Nonce: 0,
ExtraData: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000002a7cdd959bfe8d9487b2a43b33565295a698f7e26488aa4d1955ee33403f8ccb1d4de5fb97c7ade29ef9f4360c606c7ab4db26b016007d3ad0ab86a0ee01c3b1283aa067c58eab4709f85e99d46de5fe685b1ded8013785d6623cc18d214320b6bb6475978f3adfc719c99674c072166708589033e2d9afec2be4ec20253b8642161bc3f444f53679c1f3d472f7be8361c80a4c1e7e9aaf001d0877f1cfde218ce2fd7544e0b2cc94692d4a704debef7bcb61328b8f7166496996a7da21cf1f1b04d9b3e26a3d0772d4c407bbe49438ed859fe965b140dcf1aab71a96bbad7cf34b5fa511d8e963dbba288b1960e75d64430b3230294d12c6ab2aac5c2cd68e80b16b581ea0a6e3c511bbd10f4519ece37dc24887e11b55d7ae2f5b9e386cd1b50a4550696d957cb4900f03a82012708dafc9e1b880fd083b32182b869be8e0922b81f8e175ffde54d797fe11eb03f9e3bf75f1d68bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d8c4d90829ce8f72d0163c1d5cf348a862d55063035e7a025f4da968de7e4d7e4004197917f4070f1d6caa02bbebaebb5d7e581e4b66559e635f805ff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
GasLimit: 40000000,
Difficulty: big.NewInt(1),
Mixhash: common.Hash(hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000")),
Coinbase: common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE"),
Timestamp: 0x5e9da7ce,
Alloc: alloc,
}
}
// DefaultChapelGenesisBlock returns the BSC mainnet genesis block.
func DefaultChapelGenesisBlock() *Genesis {
alloc := decodePrealloc(bscChapelAllocData)
return &Genesis{
Config: params.ChapelChainConfig,
Nonce: 0,
ExtraData: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000001284214b9b9c85549ab3d2b972df0deef66ac2c9b71b214cb885500844365e95cd9942c7276e7fd8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0980a75ecd1309ea12fa2ed87a8744fbfc9b863d535552c16704d214347f29fa77f77da6d75d7c752f474cf03cceff28abc65c9cbae594f725c80e12d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
GasLimit: 40000000,
Difficulty: big.NewInt(1),
Mixhash: common.Hash(hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000")),
Coinbase: common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE"),
Timestamp: 0x5e9da7ce,
Alloc: alloc,
}
}
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
// Override the default period to the user requested one
@@ -635,13 +630,34 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
}
func decodePrealloc(data string) GenesisAlloc {
var p []struct{ Addr, Balance *big.Int }
var p []struct {
Addr *big.Int
Balance *big.Int
Misc *struct {
Nonce uint64
Code []byte
Slots []struct {
Key common.Hash
Val common.Hash
}
} `rlp:"optional"`
}
if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil {
panic(err)
}
ga := make(GenesisAlloc, len(p))
for _, account := range p {
ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance}
acc := GenesisAccount{Balance: account.Balance}
if account.Misc != nil {
acc.Nonce = account.Misc.Nonce
acc.Code = account.Misc.Code
acc.Storage = make(map[common.Hash]common.Hash)
for _, slot := range account.Misc.Slots {
acc.Storage[slot.Key] = slot.Val
}
}
ga[common.BigToAddress(account.Addr)] = acc
}
return ga
}

File diff suppressed because one or more lines are too long

View File

@@ -30,9 +30,15 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
)
func TestSetupGenesis(t *testing.T) {
testSetupGenesis(t, rawdb.HashScheme)
testSetupGenesis(t, rawdb.PathScheme)
}
func testSetupGenesis(t *testing.T, scheme string) {
var (
customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50")
customg = Genesis{
@@ -44,6 +50,7 @@ func TestSetupGenesis(t *testing.T) {
oldcustomg = customg
)
oldcustomg.Config = &params.ChainConfig{HomesteadBlock: big.NewInt(2)}
tests := []struct {
name string
fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error)
@@ -54,7 +61,7 @@ func TestSetupGenesis(t *testing.T) {
{
name: "genesis without ChainConfig",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlock(db, trie.NewDatabase(db), new(Genesis))
return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), new(Genesis))
},
wantErr: errGenesisNoConfig,
wantConfig: params.AllEthashProtocolChanges,
@@ -62,16 +69,16 @@ func TestSetupGenesis(t *testing.T) {
{
name: "no block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlock(db, trie.NewDatabase(db), nil)
return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
},
wantHash: params.MainnetGenesisHash,
wantConfig: params.MainnetChainConfig,
wantHash: params.BSCGenesisHash,
wantConfig: params.BSCChainConfig,
},
{
name: "mainnet block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
DefaultGenesisBlock().MustCommit(db)
return SetupGenesisBlock(db, trie.NewDatabase(db), nil)
DefaultGenesisBlock().MustCommit(db, trie.NewDatabase(db, newDbConfig(scheme)))
return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
},
wantHash: params.MainnetGenesisHash,
wantConfig: params.MainnetChainConfig,
@@ -79,8 +86,9 @@ func TestSetupGenesis(t *testing.T) {
{
name: "custom block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
customg.MustCommit(db)
return SetupGenesisBlock(db, trie.NewDatabase(db), nil)
tdb := trie.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, nil)
},
wantHash: customghash,
wantConfig: customg.Config,
@@ -88,8 +96,9 @@ func TestSetupGenesis(t *testing.T) {
{
name: "compatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
oldcustomg.MustCommit(db)
return SetupGenesisBlock(db, trie.NewDatabase(db), &customg)
tdb := trie.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, &customg)
},
wantHash: customghash,
wantConfig: customg.Config,
@@ -99,16 +108,17 @@ func TestSetupGenesis(t *testing.T) {
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
// Commit the 'old' genesis block with Homestead transition at #2.
// Advance to block #4, past the homestead transition block of customg.
genesis := oldcustomg.MustCommit(db)
tdb := trie.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb)
bc, _ := NewBlockChain(db, nil, &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil)
bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil)
defer bc.Stop()
blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)
_, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil)
bc.InsertChain(blocks)
// This should return a compatibility error.
return SetupGenesisBlock(db, trie.NewDatabase(db), &customg)
return SetupGenesisBlock(db, tdb, &customg)
},
wantHash: customghash,
wantConfig: customg.Config,
@@ -154,7 +164,8 @@ func TestGenesisHashes(t *testing.T) {
{DefaultGenesisBlock(), params.MainnetGenesisHash},
} {
// Test via MustCommit
if have := c.genesis.MustCommit(rawdb.NewMemoryDatabase()).Hash(); have != c.want {
db := rawdb.NewMemoryDatabase()
if have := c.genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)).Hash(); have != c.want {
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
}
// Test via ToBlock
@@ -172,7 +183,7 @@ func TestGenesis_Commit(t *testing.T) {
}
db := rawdb.NewMemoryDatabase()
genesisBlock := genesis.MustCommit(db)
genesisBlock := genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
if genesis.Difficulty != nil {
t.Fatalf("assumption wrong")
@@ -198,7 +209,7 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
{2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
}
hash, _ = alloc.deriveHash()
hash, _ = alloc.hash()
)
blob, _ := json.Marshal(alloc)
rawdb.WriteGenesisStateSpec(db, hash, blob)
@@ -221,6 +232,7 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
}
}
}
func TestConfigOrDefault(t *testing.T) {
defaultGenesis := DefaultGenesisBlock()
if defaultGenesis.Config.PlanckBlock != nil {
@@ -229,12 +241,12 @@ func TestConfigOrDefault(t *testing.T) {
gHash := params.BSCGenesisHash
config := defaultGenesis.configOrDefault(gHash)
if config.ChainID.Cmp(params.MainnetChainConfig.ChainID) != 0 {
if config.ChainID.Cmp(params.BSCChainConfig.ChainID) != 0 {
t.Errorf("ChainID of resulting config should be %v, but is %v instead", params.BSCChainConfig.ChainID, config.ChainID)
}
if config.HomesteadBlock.Cmp(params.MainnetChainConfig.HomesteadBlock) != 0 {
t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.MainnetChainConfig, config.HomesteadBlock)
if config.HomesteadBlock.Cmp(params.BSCChainConfig.HomesteadBlock) != 0 {
t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.BSCChainConfig, config.HomesteadBlock)
}
if config.PlanckBlock == nil {
@@ -246,30 +258,9 @@ 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 {
if scheme == rawdb.HashScheme {
return trie.HashDefaults
}
return &trie.Config{PathDB: pathdb.Defaults}
}

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`.
func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 {
if p, ok := hc.engine.(consensus.PoSA); ok {
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(hc, header)
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(hc, []*types.Header{header})
if err == nil {
return justifiedBlockNumber
}

View File

@@ -73,7 +73,7 @@ func TestHeaderInsertion(t *testing.T) {
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges}
)
gspec.Commit(db, trie.NewDatabase(db))
gspec.Commit(db, trie.NewDatabase(db, nil))
hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false })
if err != nil {
t.Fatal(err)

View File

@@ -32,24 +32,51 @@ import (
"os"
"strconv"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/exp/slices"
)
type allocItem struct{ Addr, Balance *big.Int }
type allocItem struct {
Addr *big.Int
Balance *big.Int
Misc *allocItemMisc `rlp:"optional"`
}
type allocItemMisc struct {
Nonce uint64
Code []byte
Slots []allocItemStorageItem
}
type allocItemStorageItem struct {
Key common.Hash
Val common.Hash
}
func makelist(g *core.Genesis) []allocItem {
items := make([]allocItem, 0, len(g.Alloc))
for addr, account := range g.Alloc {
var misc *allocItemMisc
if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 {
panic(fmt.Sprintf("can't encode account %x", addr))
misc = &allocItemMisc{
Nonce: account.Nonce,
Code: account.Code,
Slots: make([]allocItemStorageItem, 0, len(account.Storage)),
}
for key, val := range account.Storage {
misc.Slots = append(misc.Slots, allocItemStorageItem{key, val})
}
slices.SortFunc(misc.Slots, func(a, b allocItemStorageItem) int {
return a.Key.Cmp(b.Key)
})
}
bigAddr := new(big.Int).SetBytes(addr.Bytes())
items = append(items, allocItem{bigAddr, account.Balance})
items = append(items, allocItem{bigAddr, account.Balance, misc})
}
slices.SortFunc(items, func(a, b allocItem) bool {
return a.Addr.Cmp(b.Addr) < 0
slices.SortFunc(items, func(a, b allocItem) int {
return a.Addr.Cmp(b.Addr)
})
return items
}

View File

@@ -435,12 +435,12 @@ func checkReceiptsRLP(have, want types.Receipts) error {
func TestAncientStorage(t *testing.T) {
// Freezer style fast import the chain.
frdir := t.TempDir()
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false, false)
if err != nil {
t.Fatalf("failed to create database with ancient backend")
}
defer db.Close()
// Create a test block
block := types.NewBlockWithHeader(&types.Header{
Number: big.NewInt(0),

View File

@@ -256,11 +256,31 @@ func ReadStateHistory(db ethdb.AncientReaderOp, id uint64) ([]byte, []byte, []by
// history starts from one(zero for initial state).
func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) {
db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
op.AppendRaw(stateHistoryMeta, id-1, meta)
op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex)
op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex)
op.AppendRaw(stateHistoryAccountData, id-1, accounts)
op.AppendRaw(stateHistoryStorageData, id-1, storages)
err := op.AppendRaw(stateHistoryMeta, id-1, meta)
if err != nil {
log.Error("WriteStateHistory failed", "err", err)
return err
}
err = op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex)
if err != nil {
log.Error("WriteStateHistory failed", "err", err)
return err
}
err = op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex)
if err != nil {
log.Error("WriteStateHistory failed", "err", err)
return err
}
err = op.AppendRaw(stateHistoryAccountData, id-1, accounts)
if err != nil {
log.Error("WriteStateHistory failed", "err", err)
return err
}
err = op.AppendRaw(stateHistoryStorageData, id-1, storages)
if err != nil {
log.Error("WriteStateHistory failed", "err", err)
return err
}
return nil
})
}

View File

@@ -36,7 +36,7 @@ import (
//
// Now this scheme is still kept for backward compatibility, and it will be used
// for archive node and some other tries(e.g. light trie).
const HashScheme = "hashScheme"
const HashScheme = "hash"
// PathScheme is the new path-based state scheme with which trie nodes are stored
// in the disk with node path as the database key. This scheme will only store one
@@ -44,7 +44,7 @@ const HashScheme = "hashScheme"
// is native. At the same time, this scheme will put adjacent trie nodes in the same
// area of the disk with good data locality property. But this scheme needs to rely
// on extra state diffs to survive deep reorg.
const PathScheme = "pathScheme"
const PathScheme = "path"
// hasher is used to compute the sha256 hash of the provided data.
type hasher struct{ sha crypto.KeccakState }
@@ -89,6 +89,16 @@ func HasAccountTrieNode(db ethdb.KeyValueReader, path []byte, hash common.Hash)
return h.hash(data) == hash
}
// ExistsAccountTrieNode checks the presence of the account trie node with the
// specified node path, regardless of the node hash.
func ExistsAccountTrieNode(db ethdb.KeyValueReader, path []byte) bool {
has, err := db.Has(accountTrieNodeKey(path))
if err != nil {
return false
}
return has
}
// WriteAccountTrieNode writes the provided account trie node into database.
func WriteAccountTrieNode(db ethdb.KeyValueWriter, path []byte, node []byte) {
if err := db.Put(accountTrieNodeKey(path), node); err != nil {
@@ -127,6 +137,16 @@ func HasStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path [
return h.hash(data) == hash
}
// ExistsStorageTrieNode checks the presence of the storage trie node with the
// specified account hash and node path, regardless of the node hash.
func ExistsStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte) bool {
has, err := db.Has(storageTrieNodeKey(accountHash, path))
if err != nil {
return false
}
return has
}
// WriteStorageTrieNode writes the provided storage trie node into database.
func WriteStorageTrieNode(db ethdb.KeyValueWriter, accountHash common.Hash, path []byte, node []byte) {
if err := db.Put(storageTrieNodeKey(accountHash, path), node); err != nil {
@@ -263,3 +283,69 @@ func DeleteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, has
panic(fmt.Sprintf("Unknown scheme %v", scheme))
}
}
// ReadStateScheme reads the state scheme of persistent state, or none
// if the state is not present in database.
func ReadStateScheme(db ethdb.Reader) string {
// Check if state in path-based scheme is present
blob, _ := ReadAccountTrieNode(db, nil)
if len(blob) != 0 {
return PathScheme
}
// In a hash-based scheme, the genesis state is consistently stored
// on the disk. To assess the scheme of the persistent state, it
// suffices to inspect the scheme of the genesis state.
header := ReadHeader(db, ReadCanonicalHash(db, 0), 0)
if header == nil {
return "" // empty datadir
}
blob = ReadLegacyTrieNode(db, header.Root)
if len(blob) == 0 {
return "" // no state in disk
}
return HashScheme
}
// ValidateStateScheme used to check state scheme whether is valid.
// Valid state scheme: hash and path.
func ValidateStateScheme(stateScheme string) bool {
if stateScheme == HashScheme || stateScheme == PathScheme {
return true
}
return false
}
// ParseStateScheme checks if the specified state scheme is compatible with
// the stored state.
//
// - If the provided scheme is none, use the scheme consistent with persistent
// state, or fallback to hash-based scheme if state is empty.
//
// - If the provided scheme is hash, use hash-based scheme or error out if not
// compatible with persistent state scheme.
//
// - If the provided scheme is path: use path-based scheme or error out if not
// compatible with persistent state scheme.
func ParseStateScheme(provided string, disk ethdb.Database) (string, error) {
// If state scheme is not specified, use the scheme consistent
// with persistent state, or fallback to hash mode if database
// is empty.
stored := ReadStateScheme(disk)
if provided == "" {
if stored == "" {
// use default scheme for empty database, flip it when
// path mode is chosen as default
log.Info("State scheme set to default", "scheme", "hash")
return HashScheme, nil
}
log.Info("State scheme set to already existing disk db", "scheme", stored)
return stored, nil // reuse scheme of persistent scheme
}
// If state scheme is specified, ensure it's compatible with
// persistent state.
if stored == "" || provided == stored {
log.Info("State scheme set by user", "scheme", provided)
return provided, nil
}
return "", fmt.Errorf("incompatible state scheme, stored: %s, user provided: %s", stored, provided)
}

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

@@ -58,7 +58,7 @@ const (
stateHistoryStorageData = "storage.data"
)
var stateHistoryFreezerNoSnappy = map[string]bool{
var stateFreezerNoSnappy = map[string]bool{
stateHistoryMeta: true,
stateHistoryAccountIndex: false,
stateHistoryStorageIndex: false,
@@ -75,7 +75,7 @@ var (
// freezers the collections of all builtin freezers.
var freezers = []string{chainFreezerName, stateFreezerName}
// NewStateHistoryFreezer initializes the freezer for state history.
func NewStateHistoryFreezer(ancientDir string, readOnly bool, offset uint64) (*ResettableFreezer, error) {
return NewResettableFreezer(filepath.Join(ancientDir, stateFreezerName), "eth/db/state", readOnly, offset, stateHistoryTableSize, stateHistoryFreezerNoSnappy)
// NewStateFreezer initializes the freezer for state history.
func NewStateFreezer(ancientDir string, readOnly bool, offset uint64) (*ResettableFreezer, error) {
return NewResettableFreezer(filepath.Join(ancientDir, stateFreezerName), "eth/db/state", readOnly, offset, stateHistoryTableSize, stateFreezerNoSnappy)
}

View File

@@ -18,9 +18,12 @@ package rawdb
import (
"fmt"
"path/filepath"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
type tableSize struct {
@@ -50,36 +53,61 @@ func (info *freezerInfo) size() common.StorageSize {
return total
}
func inspect(name string, order map[string]bool, reader ethdb.AncientReader) (freezerInfo, error) {
info := freezerInfo{name: name}
for t := range order {
size, err := reader.AncientSize(t)
if err != nil {
return freezerInfo{}, err
}
info.sizes = append(info.sizes, tableSize{name: t, size: common.StorageSize(size)})
}
// Retrieve the number of last stored item
ancients, err := reader.Ancients()
if err != nil {
return freezerInfo{}, err
}
info.head = ancients - 1
// Retrieve the number of first stored item
tail, err := reader.Tail()
if err != nil {
return freezerInfo{}, err
}
info.tail = tail
return info, nil
}
// inspectFreezers inspects all freezers registered in the system.
func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
var infos []freezerInfo
for _, freezer := range freezers {
switch freezer {
case chainFreezerName:
// Chain ancient store is a bit special. It's always opened along
// with the key-value store, inspect the chain store directly.
info := freezerInfo{name: freezer}
// Retrieve storage size of every contained table.
for table := range chainFreezerNoSnappy {
size, err := db.AncientSize(table)
if err != nil {
return nil, err
}
info.sizes = append(info.sizes, tableSize{name: table, size: common.StorageSize(size)})
}
// Retrieve the number of last stored item
ancients, err := db.Ancients()
info, err := inspect(chainFreezerName, chainFreezerNoSnappy, db)
if err != nil {
return nil, err
}
info.head = ancients - 1
infos = append(infos, info)
// Retrieve the number of first stored item
tail, err := db.Tail()
case stateFreezerName:
if ReadStateScheme(db) != PathScheme {
continue
}
datadir, err := db.AncientDatadir()
if err != nil {
return nil, err
}
f, err := NewStateFreezer(datadir, true, 0)
if err != nil {
return nil, err
}
defer f.Close()
info, err := inspect(stateFreezerName, stateFreezerNoSnappy, f)
if err != nil {
return nil, err
}
info.tail = tail
infos = append(infos, info)
default:
@@ -101,6 +129,8 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
switch freezerName {
case chainFreezerName:
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
case stateFreezerName:
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
default:
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
}
@@ -119,3 +149,23 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
table.dumpIndexStdout(start, end)
return nil
}
func ResetStateFreezerTableOffset(ancient string, virtualTail uint64) error {
path, tables := filepath.Join(ancient, stateFreezerName), stateFreezerNoSnappy
for name, disableSnappy := range tables {
log.Info("Handle table", "name", name, "disableSnappy", disableSnappy)
table, err := newTable(path, name, metrics.NilMeter{}, metrics.NilMeter{}, metrics.NilGauge{}, freezerTableSize, disableSnappy, false)
if err != nil {
log.Error("New table failed", "error", err)
return err
}
// Reset the metadata of the freezer table
err = table.ResetItemsOffset(virtualTail)
if err != nil {
log.Error("Reset items offset of the table", "name", name, "error", err)
return err
}
}
return nil
}

View File

@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/leveldb"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/ethdb/pebble"
"github.com/ethereum/go-ethereum/log"
)
@@ -218,25 +219,28 @@ func NewFreezerDb(db ethdb.KeyValueStore, frz, namespace string, readonly bool,
// resolveChainFreezerDir is a helper function which resolves the absolute path
// of chain freezer by considering backward compatibility.
//
// rules:
// 1. in path mode, block data is stored in chain dir and state data is in state dir.
// 2. in hash mode, block data is stored in chain dir or ancient dir(before big merge), no state dir.
func resolveChainFreezerDir(ancient string) string {
// Check if the chain freezer is already present in the specified
// sub folder, if not then two possibilities:
// - chain freezer is not initialized
// - chain freezer exists in legacy location (root ancient folder)
freezer := path.Join(ancient, chainFreezerName)
if !common.FileExist(freezer) {
if !common.FileExist(ancient) {
// The entire ancient store is not initialized, still use the sub
// folder for initialization.
} else {
// Ancient root is already initialized, then we hold the assumption
// that chain freezer is also initialized and located in root folder.
// In this case fallback to legacy location.
freezer = ancient
log.Info("Found legacy ancient chain path", "location", ancient)
}
chain := path.Join(ancient, chainFreezerName)
state := path.Join(ancient, stateFreezerName)
if common.FileExist(chain) {
return chain
}
return freezer
if common.FileExist(state) {
return chain
}
if common.FileExist(ancient) {
log.Info("Found legacy ancient chain path", "location", ancient)
chain = ancient
}
return chain
}
// NewDatabaseWithFreezer creates a high level database on top of a given key-
@@ -263,6 +267,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
WriteAncientType(db, PruneFreezerType)
}
return &freezerdb{
ancientRoot: ancient,
KeyValueStore: db,
AncientStore: frdb,
}, nil
@@ -335,7 +340,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
break
}
}
// We are about to exit on error. Print database metdata beore exiting
// We are about to exit on error. Print database metdata before exiting
printChainMetadata(db)
return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
frozen-1, number, head)
@@ -364,7 +369,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
// freezer.
}
}
// no prune ancinet start success
// no prune ancient start success
if !readonly {
WriteAncientType(db, EntireFreezerType)
}
@@ -425,6 +430,16 @@ func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient
return frdb, nil
}
// NewPebbleDBDatabase creates a persistent key-value database without a freezer
// moving immutable chain segments into cold storage.
func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) {
db, err := pebble.New(file, cache, handles, namespace, readonly)
if err != nil {
return nil, err
}
return NewDatabase(db), nil
}
const (
dbPebble = "pebble"
dbLeveldb = "leveldb"
@@ -480,12 +495,8 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb)
}
if o.Type == dbPebble || existingDb == dbPebble {
if PebbleEnabled {
log.Info("Using pebble as the backing database")
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
} else {
return nil, errors.New("db.engine 'pebble' not supported on this platform")
}
log.Info("Using pebble as the backing database")
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
}
if o.Type == dbLeveldb || existingDb == dbLeveldb {
log.Info("Using leveldb as the backing database")
@@ -493,10 +504,8 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
}
// No pre-existing database, no user-requested one either. Default to Pebble
// on supported platforms and LevelDB on anything else.
// if PebbleEnabled {
// log.Info("Defaulting to pebble as the backing database")
// return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
// }
log.Info("Defaulting to leveldb as the backing database")
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
}
@@ -511,6 +520,11 @@ func Open(o OpenOptions) (ethdb.Database, error) {
if err != nil {
return nil, err
}
if ReadAncientType(kvdb) == PruneFreezerType {
if !o.PruneAncientData {
log.Warn("Disk db is pruned")
}
}
if len(o.AncientsDirectory) == 0 {
return kvdb, nil
}
@@ -551,6 +565,7 @@ func (s *stat) Size() string {
func (s *stat) Count() string {
return s.count.String()
}
func AncientInspect(db ethdb.Database) error {
offset := counter(ReadOffSetOfCurrentAncientFreezer(db))
// Get number of ancient rows inside the freezer.
@@ -581,6 +596,28 @@ func AncientInspect(db ethdb.Database) error {
return nil
}
func PruneHashTrieNodeInDataBase(db ethdb.Database) error {
it := db.NewIterator([]byte{}, []byte{})
defer it.Release()
total_num := 0
for it.Next() {
var key = it.Key()
switch {
case IsLegacyTrieNode(key, it.Value()):
db.Delete(key)
total_num++
if total_num%100000 == 0 {
log.Info("Pruning hash-base state trie nodes", "Complete progress: ", total_num)
}
default:
continue
}
}
log.Info("Pruning hash-base state trie nodes", "Complete progress", total_num)
return nil
}
// InspectDatabase traverses the entire database and checks the size
// of all different categories of data.
func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
@@ -599,7 +636,10 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
tds stat
numHashPairings stat
hashNumPairings stat
tries stat
legacyTries stat
stateLookups stat
accountTries stat
storageTries stat
codes stat
txLookups stat
accountSnaps stat
@@ -640,8 +680,14 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
numHashPairings.Add(size)
case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength):
hashNumPairings.Add(size)
case len(key) == common.HashLength:
tries.Add(size)
case IsLegacyTrieNode(key, it.Value()):
legacyTries.Add(size)
case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength:
stateLookups.Add(size)
case IsAccountTrieNode(key):
accountTries.Add(size)
case IsStorageTrieNode(key):
storageTries.Add(size)
case bytes.HasPrefix(key, CodePrefix) && len(key) == len(CodePrefix)+common.HashLength:
codes.Add(size)
case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength):
@@ -678,7 +724,8 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
databaseVersionKey, headHeaderKey, headBlockKey, headFastBlockKey,
lastPivotKey, fastTrieProgressKey, snapshotDisabledKey, SnapshotRootKey, snapshotJournalKey,
snapshotGeneratorKey, snapshotRecoveryKey, txIndexTailKey, fastTxLookupLimitKey,
uncleanShutdownKey, badBlockKey, transitionStatusKey,
uncleanShutdownKey, badBlockKey, transitionStatusKey, skeletonSyncStatusKey,
persistentStateIDKey, trieJournalKey, snapshotSyncStatusKey,
} {
if bytes.Equal(key, meta) {
metadata.Add(size)
@@ -707,7 +754,10 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
{"Key-Value store", "Transaction index", txLookups.Size(), txLookups.Count()},
{"Key-Value store", "Bloombit index", bloomBits.Size(), bloomBits.Count()},
{"Key-Value store", "Contract codes", codes.Size(), codes.Count()},
{"Key-Value store", "Trie nodes", tries.Size(), tries.Count()},
{"Key-Value store", "Hash trie nodes", legacyTries.Size(), legacyTries.Count()},
{"Key-Value store", "Path trie state lookups", stateLookups.Size(), stateLookups.Count()},
{"Key-Value store", "Path trie account nodes", accountTries.Size(), accountTries.Count()},
{"Key-Value store", "Path trie storage nodes", storageTries.Size(), storageTries.Count()},
{"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()},
{"Key-Value store", "Account snapshot", accountSnaps.Size(), accountSnaps.Count()},
{"Key-Value store", "Storage snapshot", storageSnaps.Size(), storageSnaps.Count()},

View File

@@ -15,3 +15,80 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb
import (
"fmt"
"os"
"testing"
)
const (
mockChainFreezerPath = "/geth/chaindata/ancient/chain"
mockStateFreezerPath = "/geth/chaindata/ancient/state"
mockAncientFreezerPath = "/geth/chaindata/ancient"
)
func Test_resolveChainFreezerDir(t *testing.T) {
tests := []struct {
name string
fn func(dir string) string
ancient string
wantedResult string
}{
{
// chain dir is existent, so it should be returned.
name: "1",
fn: func(dir string) string {
path := fmt.Sprintf("%s%s", dir, mockChainFreezerPath)
if err := os.MkdirAll(path, 0700); err != nil {
t.Fatalf("Failed to mkdir all dirs, error: %v", err)
}
return fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
},
wantedResult: mockChainFreezerPath,
},
{
// chain dir is nonexistent and state dir is existent; so chain
// dir should be returned.
name: "2",
fn: func(dir string) string {
path := fmt.Sprintf("%s%s", dir, mockStateFreezerPath)
if err := os.MkdirAll(path, 0700); err != nil {
t.Fatalf("Failed to mkdir all dirs, error: %v", err)
}
return fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
},
wantedResult: mockChainFreezerPath,
},
{
// both chain dir and state dir are nonexistent, if ancient dir is
// existent, so ancient dir should be returned.
name: "3",
fn: func(dir string) string {
path := fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
if err := os.MkdirAll(path, 0700); err != nil {
t.Fatalf("Failed to mkdir all dirs, error: %v", err)
}
return path
},
wantedResult: mockAncientFreezerPath,
},
{
// ancient dir is nonexistent, so chain dir should be returned.
name: "4",
fn: func(dir string) string {
return fmt.Sprintf("%s%s", dir, mockAncientFreezerPath)
},
wantedResult: mockChainFreezerPath,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tempDir := t.TempDir()
got := resolveChainFreezerDir(tt.fn(tempDir))
if got != fmt.Sprintf("%s%s", tempDir, tt.wantedResult) {
t.Fatalf("resolveChainFreezerDir() = %s, wanted = %s", got, tt.wantedResult)
}
})
}
}

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
// reprensent the absolute number of blocks already frozen.
// represent the absolute number of blocks already frozen.
freezer.frozen.Add(offset)
freezer.tail.Add(offset)

View File

@@ -188,19 +188,27 @@ func (batch *freezerTableBatch) maybeCommit() error {
// commit writes the batched items to the backing freezerTable.
func (batch *freezerTableBatch) commit() error {
// Write data.
// Write data. The head file is fsync'd after write to ensure the
// data is truly transferred to disk.
_, err := batch.t.head.Write(batch.dataBuffer)
if err != nil {
return err
}
if err := batch.t.head.Sync(); err != nil {
return err
}
dataSize := int64(len(batch.dataBuffer))
batch.dataBuffer = batch.dataBuffer[:0]
// Write indices.
// Write indices. The index file is fsync'd after write to ensure the
// data indexes are truly transferred to disk.
_, err = batch.t.index.Write(batch.indexBuffer)
if err != nil {
return err
}
if err := batch.t.index.Sync(); err != nil {
return err
}
indexSize := int64(len(batch.indexBuffer))
batch.indexBuffer = batch.indexBuffer[:0]

View File

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

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