Compare commits
121 Commits
v1.4.5
...
versa_comp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba71e76c55 | ||
|
|
83a9b13771 | ||
|
|
c6cb43b7ca | ||
|
|
222e10810e | ||
|
|
26b236fb5f | ||
|
|
900cf26c65 | ||
|
|
21e6dcfc79 | ||
|
|
a262acfb00 | ||
|
|
87e622e51f | ||
|
|
13d454796f | ||
|
|
c6af48100d | ||
|
|
6d5b4ad64d | ||
|
|
d35b57ae36 | ||
|
|
21fc2d3ac4 | ||
|
|
c96fab04a3 | ||
|
|
27d86948fa | ||
|
|
a04e287cb6 | ||
|
|
c3d6155fff | ||
|
|
a00ffa762c | ||
|
|
863fdea026 | ||
|
|
90e67970ae | ||
|
|
e8456c2d08 | ||
|
|
bc970e5893 | ||
|
|
a5810fefc9 | ||
|
|
971c0fa380 | ||
|
|
88225c1a4b | ||
|
|
51e27f9e3b | ||
|
|
f1a85ec306 | ||
|
|
75d162983a | ||
|
|
727c07116d | ||
|
|
719412551a | ||
|
|
c2226a0c9f | ||
|
|
d52628aa82 | ||
|
|
f7de51f74e | ||
|
|
55cbf31f18 | ||
|
|
f0c7795542 | ||
|
|
1548452def | ||
|
|
f2e7f1dd24 | ||
|
|
27a3ec5d72 | ||
|
|
6094d7157e | ||
|
|
be0fbfb79e | ||
|
|
00f094c37e | ||
|
|
7b08a70a23 | ||
|
|
99d31aeb28 | ||
|
|
f467c6018b | ||
|
|
4566ac7659 | ||
|
|
aab4b8812a | ||
|
|
af7e9b95bd | ||
|
|
1047f0e59a | ||
|
|
9bb4fed1bf | ||
|
|
35e71a769b | ||
|
|
6b02ac7ac5 | ||
|
|
8b9558bb4d | ||
|
|
63e7eac394 | ||
|
|
05543e558d | ||
|
|
b0146261c7 | ||
|
|
d7b9866d3b | ||
|
|
f5ba30ed47 | ||
|
|
f190c49252 | ||
|
|
08769ead2b | ||
|
|
4d0f1e7117 | ||
|
|
c77bb1110d | ||
|
|
c856d21719 | ||
|
|
f45305b1ad | ||
|
|
d16532d678 | ||
|
|
5edd032cdb | ||
|
|
6b8cbbe172 | ||
|
|
5ea2ada0ee | ||
|
|
b230a02006 | ||
|
|
86e3a02490 | ||
|
|
0c0958ff87 | ||
|
|
c577ce3720 | ||
|
|
d436f9e2e8 | ||
|
|
97c3b9b267 | ||
|
|
0560685460 | ||
|
|
bf16a39876 | ||
|
|
2c8720016d | ||
|
|
f2ec3cc6a5 | ||
|
|
0a2e1282d2 | ||
|
|
adb5e8fe86 | ||
|
|
23f6194fad | ||
|
|
691d195526 | ||
|
|
b57c779759 | ||
|
|
4ab1c865b2 | ||
|
|
a7d5b02919 | ||
|
|
1ce9bb044d | ||
|
|
7948950f7a | ||
|
|
0c101e618a | ||
|
|
571ea2c4b9 | ||
|
|
7bc5a3353d | ||
|
|
901ea2e0d2 | ||
|
|
1d81f3316f | ||
|
|
43b2ffa63b | ||
|
|
0567715760 | ||
|
|
e32fcf5b93 | ||
|
|
e55028d788 | ||
|
|
9d8df917b8 | ||
|
|
9e170972f4 | ||
|
|
ba6726325a | ||
|
|
6573254a62 | ||
|
|
31d92c50ad | ||
|
|
7cab9c622c | ||
|
|
2a0e399c38 | ||
|
|
182c841374 | ||
|
|
14023fae6d | ||
|
|
d653cda82e | ||
|
|
4b54601d5c | ||
|
|
3b7f0e4279 | ||
|
|
fe1fff8c77 | ||
|
|
c0afdc9a98 | ||
|
|
fb435eb5f1 | ||
|
|
5cc253a2cd | ||
|
|
cbcd26c9a9 | ||
|
|
90eb5b33e8 | ||
|
|
837de88057 | ||
|
|
b4fb2f6ffc | ||
|
|
11503edeb2 | ||
|
|
3a6e3c67f2 | ||
|
|
335be39905 | ||
|
|
b7972bcd77 | ||
|
|
4bb1bd1a77 |
20
.github/CODEOWNERS
vendored
20
.github/CODEOWNERS
vendored
@@ -1,3 +1,21 @@
|
||||
# Lines starting with '#' are comments.
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
* @zzzckck @zjubfd
|
||||
accounts/usbwallet @karalabe
|
||||
accounts/scwallet @gballet
|
||||
accounts/abi @gballet @MariusVanDerWijden
|
||||
cmd/clef @holiman
|
||||
consensus @karalabe
|
||||
core/ @karalabe @holiman @rjl493456442
|
||||
eth/ @karalabe @holiman @rjl493456442
|
||||
eth/catalyst/ @gballet
|
||||
eth/tracers/ @s1na
|
||||
graphql/ @s1na
|
||||
les/ @zsfelfoldi @rjl493456442
|
||||
light/ @zsfelfoldi @rjl493456442
|
||||
node/ @fjl
|
||||
p2p/ @fjl @zsfelfoldi
|
||||
rpc/ @fjl @holiman
|
||||
p2p/simulations @fjl
|
||||
p2p/protocols @fjl
|
||||
p2p/testing @fjl
|
||||
signer/ @holiman
|
||||
|
||||
2
.nancy-ignore
Normal file
2
.nancy-ignore
Normal file
@@ -0,0 +1,2 @@
|
||||
CVE-2024-34478 # "CWE-754: Improper Check for Unusual or Exceptional Conditions." This vulnerability is BTC only, BSC does not have the issue.
|
||||
CVE-2024-6104 # "CWE-532: Information Exposure Through Log Files" This is caused by the vulnerabilities go-retryablehttp@v0.7.4, it is only used in cmd devp2p, impact is limited. will upgrade to v0.7.7 later
|
||||
130
CHANGELOG.md
130
CHANGELOG.md
@@ -1,4 +1,134 @@
|
||||
# Changelog
|
||||
|
||||
## v1.4.12
|
||||
|
||||
### BUGFIX
|
||||
* [\#2557](https://github.com/bnb-chain/bsc/pull/2557) fix: fix state inspect error after pruned state
|
||||
* [\#2562](https://github.com/bnb-chain/bsc/pull/2562) fix: delete unexpected block
|
||||
* [\#2566](https://github.com/bnb-chain/bsc/pull/2566) core: avoid to cache block before wroten into db
|
||||
* [\#2567](https://github.com/bnb-chain/bsc/pull/2567) fix: fix statedb copy
|
||||
* [\#2574](https://github.com/bnb-chain/bsc/pull/2574) core: adapt highestVerifiedHeader to FastFinality
|
||||
* [\#2542](https://github.com/bnb-chain/bsc/pull/2542) fix: pruneancient freeze from the previous position when the first time
|
||||
* [\#2564](https://github.com/bnb-chain/bsc/pull/2564) fix: the bug of blobsidecars and downloader with multi-database
|
||||
* [\#2582](https://github.com/bnb-chain/bsc/pull/2582) fix: remove delete and dangling side chains in prunefreezer
|
||||
|
||||
### FEATURE
|
||||
* [\#2513](https://github.com/bnb-chain/bsc/pull/2513) cmd/jsutils: add a tool to get performance between a range of blocks
|
||||
* [\#2569](https://github.com/bnb-chain/bsc/pull/2569) cmd/jsutils: add a tool to get slash count
|
||||
* [\#2583](https://github.com/bnb-chain/bsc/pull/2583) cmd/jsutill: add log about validator name
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2546](https://github.com/bnb-chain/bsc/pull/2546) go.mod: update missing dependency
|
||||
* [\#2559](https://github.com/bnb-chain/bsc/pull/2559) nancy: ignore go-retryablehttp@v0.7.4 in .nancy-ignore
|
||||
* [\#2556](https://github.com/bnb-chain/bsc/pull/2556) chore: update greenfield cometbft version
|
||||
* [\#2561](https://github.com/bnb-chain/bsc/pull/2561) tests: fix unstable test
|
||||
* [\#2572](https://github.com/bnb-chain/bsc/pull/2572) core: clearup testflag for Cancun and Haber
|
||||
* [\#2573](https://github.com/bnb-chain/bsc/pull/2573) cmd/utils: support use NetworkId to distinguish chapel when do syncing
|
||||
* [\#2538](https://github.com/bnb-chain/bsc/pull/2538) feat: enhance bid comparison and reply bidding results && detail logs
|
||||
* [\#2568](https://github.com/bnb-chain/bsc/pull/2568) core/vote: not vote if too late for next in turn validator
|
||||
* [\#2576](https://github.com/bnb-chain/bsc/pull/2576) miner/worker: broadcast block immediately once sealed
|
||||
* [\#2580](https://github.com/bnb-chain/bsc/pull/2580) freezer: Opt freezer env checking
|
||||
|
||||
## v1.4.11
|
||||
|
||||
### BUGFIX
|
||||
* [\#2534](https://github.com/bnb-chain/bsc/pull/2534) fix: nil pointer when clear simulating bid
|
||||
* [\#2535](https://github.com/bnb-chain/bsc/pull/2535) upgrade: add HaberFix hardfork
|
||||
|
||||
|
||||
## v1.4.10
|
||||
### FEATURE
|
||||
NA
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2512](https://github.com/bnb-chain/bsc/pull/2512) feat: add mev helper params and func
|
||||
* [\#2508](https://github.com/bnb-chain/bsc/pull/2508) perf: speedup pbss trienode read
|
||||
* [\#2509](https://github.com/bnb-chain/bsc/pull/2509) perf: optimize chain commit performance for multi-database
|
||||
* [\#2451](https://github.com/bnb-chain/bsc/pull/2451) core/forkchoice: improve stability when inturn block not generate
|
||||
|
||||
### BUGFIX
|
||||
* [\#2518](https://github.com/bnb-chain/bsc/pull/2518) fix: remove zero gasprice check for BSC
|
||||
* [\#2519](https://github.com/bnb-chain/bsc/pull/2519) UT: random failure of TestSnapSyncWithBlobs
|
||||
* [\#2515](https://github.com/bnb-chain/bsc/pull/2515) fix getBlobSidecars by ethclient
|
||||
* [\#2525](https://github.com/bnb-chain/bsc/pull/2525) fix: ensure empty withdrawals after cancun before broadcast
|
||||
|
||||
## v1.4.9
|
||||
### FEATURE
|
||||
* [\#2463](https://github.com/bnb-chain/bsc/pull/2463) utils: add check_blobtx.js
|
||||
* [\#2470](https://github.com/bnb-chain/bsc/pull/2470) jsutils: faucet successful requests within blocks
|
||||
* [\#2467](https://github.com/bnb-chain/bsc/pull/2467) internal/ethapi: add optional parameter for blobSidecars
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2462](https://github.com/bnb-chain/bsc/pull/2462) cmd/utils: add a flag to change breathe block interval for testing
|
||||
* [\#2497](https://github.com/bnb-chain/bsc/pull/2497) params/config: add Bohr hardfork
|
||||
* [\#2479](https://github.com/bnb-chain/bsc/pull/2479) dev: ensure consistency in BPS bundle result
|
||||
|
||||
### BUGFIX
|
||||
* [\#2461](https://github.com/bnb-chain/bsc/pull/2461) eth/handler: check lists in body before broadcast blocks
|
||||
* [\#2455](https://github.com/bnb-chain/bsc/pull/2455) cmd: fix memory leak when big dataset
|
||||
* [\#2466](https://github.com/bnb-chain/bsc/pull/2466) sync: fix some sync issues caused by prune-block.
|
||||
* [\#2475](https://github.com/bnb-chain/bsc/pull/2475) fix: move mev op to MinerAPI & add command to console
|
||||
* [\#2473](https://github.com/bnb-chain/bsc/pull/2473) fix: limit the gas price of the mev bid
|
||||
* [\#2484](https://github.com/bnb-chain/bsc/pull/2484) fix: fix inspect database error
|
||||
* [\#2481](https://github.com/bnb-chain/bsc/pull/2481) fix: keep 9W blocks in ancient db when prune block
|
||||
* [\#2495](https://github.com/bnb-chain/bsc/pull/2495) fix: add an empty freeze db
|
||||
* [\#2507](https://github.com/bnb-chain/bsc/pull/2507) fix: waiting for the last simulation before pick best bid
|
||||
|
||||
## v1.4.8
|
||||
### FEATURE
|
||||
* [\#2483](https://github.com/bnb-chain/bsc/pull/2483) core/vm: add secp256r1 into PrecompiledContractsHaber
|
||||
* [\#2400](https://github.com/bnb-chain/bsc/pull/2400) RIP-7212: Precompile for secp256r1 Curve Support
|
||||
|
||||
### IMPROVEMENT
|
||||
NA
|
||||
|
||||
### BUGFIX
|
||||
NA
|
||||
|
||||
## v1.4.7
|
||||
### FEATURE
|
||||
* [\#2439](https://github.com/bnb-chain/bsc/pull/2439) config: setup Mainnet Tycho(Cancun) hardfork date
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2396](https://github.com/bnb-chain/bsc/pull/2396) metrics: add blockInsertMgaspsGauge to trace mgasps
|
||||
* [\#2411](https://github.com/bnb-chain/bsc/pull/2411) build(deps): bump golang.org/x/net from 0.19.0 to 0.23.0
|
||||
* [\#2435](https://github.com/bnb-chain/bsc/pull/2435) txpool: limit max gas when mining is enabled
|
||||
* [\#2438](https://github.com/bnb-chain/bsc/pull/2438) fix: performance issue when load journal
|
||||
* [\#2440](https://github.com/bnb-chain/bsc/pull/2440) nancy: add files .nancy-ignore
|
||||
|
||||
### BUGFIX
|
||||
NA
|
||||
|
||||
## v1.4.6
|
||||
### FEATURE
|
||||
* [\#2227](https://github.com/bnb-chain/bsc/pull/2227) core: separated databases for block data
|
||||
* [\#2404](https://github.com/bnb-chain/bsc/pull/2404) cmd, p2p: filter peers by regex on name
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2201](https://github.com/bnb-chain/bsc/pull/2201) chore: render system bytecode by go:embed
|
||||
* [\#2363](https://github.com/bnb-chain/bsc/pull/2363) feat: greedy merge tx in bid
|
||||
* [\#2389](https://github.com/bnb-chain/bsc/pull/2389) deps: update prsym to solve warning about quic-go version
|
||||
* [\#2341](https://github.com/bnb-chain/bsc/pull/2341) core/trie: persist TrieJournal to journal file instead of kv database
|
||||
* [\#2395](https://github.com/bnb-chain/bsc/pull/2395) fix: trieJournal format compatible old db format
|
||||
* [\#2406](https://github.com/bnb-chain/bsc/pull/2406) feat: adaptive for loading journal file or journal kv during loadJournal
|
||||
* [\#2390](https://github.com/bnb-chain/bsc/pull/2390) chore: fix function names in comment
|
||||
* [\#2399](https://github.com/bnb-chain/bsc/pull/2399) chore: fix some typos in comments
|
||||
* [\#2408](https://github.com/bnb-chain/bsc/pull/2408) chore: fix some typos in comments
|
||||
* [\#2416](https://github.com/bnb-chain/bsc/pull/2416) fix: fix function names
|
||||
* [\#2424](https://github.com/bnb-chain/bsc/pull/2424) feat: recommit bid when newBidCh is empty to maximize mev reward
|
||||
* [\#2430](https://github.com/bnb-chain/bsc/pull/2430) fix: oom caused by non-discarded mev simulation env
|
||||
* [\#2428](https://github.com/bnb-chain/bsc/pull/2428) chore: add metric & log for blobTx
|
||||
* [\#2419](https://github.com/bnb-chain/bsc/pull/2419) metrics: add doublesign counter
|
||||
|
||||
### BUGFIX
|
||||
* [\#2244](https://github.com/bnb-chain/bsc/pull/2244) cmd/geth: fix importBlock
|
||||
* [\#2391](https://github.com/bnb-chain/bsc/pull/2391) fix: print value instead of pointer in ConfigCompatError
|
||||
* [\#2398](https://github.com/bnb-chain/bsc/pull/2398) fix: no import blocks before or equal to the finalized height
|
||||
* [\#2401](https://github.com/bnb-chain/bsc/pull/2401) fix: allow fast node to rewind after abnormal shutdown
|
||||
* [\#2403](https://github.com/bnb-chain/bsc/pull/2403) fix: NPE
|
||||
* [\#2423](https://github.com/bnb-chain/bsc/pull/2423) eth/gasprice: add query limit to defend DDOS attack
|
||||
* [\#2425](https://github.com/bnb-chain/bsc/pull/2425) fix: adapt journal for cmd
|
||||
|
||||
## v1.4.5
|
||||
### FEATURE
|
||||
* [\#2378](https://github.com/bnb-chain/bsc/pull/2378) config: setup Testnet Tycho(Cancun) hardfork date
|
||||
|
||||
@@ -26,7 +26,7 @@ COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/
|
||||
|
||||
EXPOSE 8545 8546 30303 30303/udp
|
||||
|
||||
# Add some metadata labels to help programatic image consumption
|
||||
# Add some metadata labels to help programmatic image consumption
|
||||
ARG COMMIT=""
|
||||
ARG VERSION=""
|
||||
ARG BUILDNUM=""
|
||||
|
||||
@@ -36,7 +36,7 @@ To combine DPoS and PoA for consensus, BNB Smart Chain implement a novel consens
|
||||
2. Validators take turns to produce blocks in a PoA manner, similar to Ethereum's Clique consensus engine.
|
||||
3. Validator set are elected in and out based on a staking based governance on BNB Beacon Chain.
|
||||
4. The validator set change is relayed via a cross-chain communication mechanism.
|
||||
5. Parlia consensus engine will interact with a set of [system contracts](https://docs.bnbchain.org/docs/learn/system-contract) to achieve liveness slash, revenue distributing and validator set renewing func.
|
||||
5. Parlia consensus engine will interact with a set of [system contracts](https://docs.bnbchain.org/bnb-smart-chain/staking/overview/#system-contracts) to achieve liveness slash, revenue distributing and validator set renewing func.
|
||||
|
||||
|
||||
### Light Client of BNB Beacon Chain
|
||||
@@ -149,13 +149,11 @@ 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 encounter difficulties downloading the chaindata snapshot and prefer to synchronize from the genesis block on the Chapel testnet, remember to include the additional flag `--chapel` when initially launching Geth.
|
||||
|
||||
#### 4. Start a full node
|
||||
```shell
|
||||
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0
|
||||
|
||||
## It is recommand to run fullnode with `--tries-verify-mode none` if you want high performance and care little about state consistency
|
||||
## It is recommend to run fullnode with `--tries-verify-mode none` if you want high performance and care little about state consistency
|
||||
## It will run with Hash-Base Storage Scheme by default
|
||||
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0 --tries-verify-mode none
|
||||
|
||||
@@ -183,7 +181,7 @@ This tool is optional and if you leave it out you can always attach to an alread
|
||||
|
||||
#### 7. More
|
||||
|
||||
More details about [running a node](https://docs.bnbchain.org/docs/validator/fullnode) and [becoming a validator](https://docs.bnbchain.org/docs/validator/create-val)
|
||||
More details about [running a node](https://docs.bnbchain.org/bnb-smart-chain/developers/node_operators/full_node/) and [becoming a validator](https://docs.bnbchain.org/bnb-smart-chain/validator/create-val/)
|
||||
|
||||
*Note: Although some internal protective measures prevent transactions from
|
||||
crossing over between the main network and test network, you should always
|
||||
|
||||
@@ -51,7 +51,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// waitWatcherStarts waits up to 1s for the keystore watcher to start.
|
||||
// waitWatcherStart waits up to 1s for the keystore watcher to start.
|
||||
func waitWatcherStart(ks *KeyStore) bool {
|
||||
// On systems where file watch is not supported, just return "ok".
|
||||
if !ks.cache.watcher.enabled() {
|
||||
|
||||
@@ -343,7 +343,7 @@ func TestWalletNotifications(t *testing.T) {
|
||||
checkEvents(t, wantEvents, events)
|
||||
}
|
||||
|
||||
// TestImportExport tests the import functionality of a keystore.
|
||||
// TestImportECDSA tests the import functionality of a keystore.
|
||||
func TestImportECDSA(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, ks := tmpKeyStore(t, true)
|
||||
@@ -362,7 +362,7 @@ func TestImportECDSA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestImportECDSA tests the import and export functionality of a keystore.
|
||||
// TestImportExport tests the import and export functionality of a keystore.
|
||||
func TestImportExport(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, ks := tmpKeyStore(t, true)
|
||||
|
||||
@@ -349,6 +349,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||
}
|
||||
// Re-create statedb instance with new root upon the updated database
|
||||
// for accessing latest states.
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
statedb, err = state.New(root, statedb.Database(), nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
||||
@@ -358,7 +359,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||
}
|
||||
|
||||
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
||||
for addr, a := range accounts {
|
||||
statedb.SetCode(addr, a.Code)
|
||||
@@ -372,6 +375,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
|
||||
statedb.Finalise(false)
|
||||
statedb.AccountsIntermediateRoot()
|
||||
root, _, _ := statedb.Commit(0, nil)
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
statedb, _ = state.New(root, sdb, nil)
|
||||
return statedb
|
||||
}
|
||||
|
||||
@@ -148,12 +148,14 @@ func runCmd(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
// TODO:: ignore cmd, if use versa if should be nil, if triedb is not used later in this func
|
||||
triedb := triedb.NewDatabase(db, &triedb.Config{
|
||||
Preimages: preimages,
|
||||
HashDB: hashdb.Defaults,
|
||||
})
|
||||
defer triedb.Close()
|
||||
genesis := genesisConfig.MustCommit(db, triedb)
|
||||
// TODO:: ignore cmd, internally compatible with versa is sufficient.
|
||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
||||
statedb, _ = state.New(genesis.Root(), sdb, nil)
|
||||
chainConfig = genesisConfig.Config
|
||||
|
||||
@@ -109,6 +109,7 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
|
||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||
}
|
||||
if dump { // Dump any state to aid debugging
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
cpy, _ := state.New(root, tstate.StateDB.Database(), nil)
|
||||
dump := cpy.RawDump(nil)
|
||||
result.State = &dump
|
||||
|
||||
@@ -525,7 +525,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
f.lock.Unlock()
|
||||
|
||||
// Send an error if too frequent funding, othewise a success
|
||||
// Send an error if too frequent funding, otherwise a success
|
||||
if !fund {
|
||||
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(time.Until(timeout)))); err != nil { // nolint: gosimple
|
||||
log.Warn("Failed to send funding error to client", "err", err)
|
||||
@@ -642,7 +642,7 @@ func (f *faucet) loop() {
|
||||
f.lock.RUnlock()
|
||||
}
|
||||
}()
|
||||
// Wait for various events and assing to the appropriate background threads
|
||||
// Wait for various events and assign to the appropriate background threads
|
||||
for {
|
||||
select {
|
||||
case head := <-heads:
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestAttachWithHeaders(t *testing.T) {
|
||||
// This is fixed in a follow-up PR.
|
||||
}
|
||||
|
||||
// TestAttachWithHeaders tests that 'geth db --remotedb' with custom headers works, i.e
|
||||
// TestRemoteDbWithHeaders tests that 'geth db --remotedb' with custom headers works, i.e
|
||||
// that custom headers are forwarded to the target.
|
||||
func TestRemoteDbWithHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -12,16 +12,16 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v4/io/prompt"
|
||||
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"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/wallet"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/keymanager"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/keymanager/local"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/io/prompt"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/accounts"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/accounts/iface"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/accounts/petnames"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/keymanager"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/keymanager/local"
|
||||
"github.com/urfave/cli/v2"
|
||||
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/internal/era"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
@@ -61,8 +62,9 @@ var (
|
||||
ArgsUsage: "<genesisPath>",
|
||||
Flags: flags.Merge([]cli.Flag{
|
||||
utils.CachePreimagesFlag,
|
||||
utils.OverrideCancun,
|
||||
utils.OverrideBohr,
|
||||
utils.OverrideVerkle,
|
||||
utils.MultiDataBaseFlag,
|
||||
}, utils.DatabaseFlags),
|
||||
Description: `
|
||||
The init command initializes a new genesis block and definition for the network.
|
||||
@@ -251,9 +253,9 @@ func initGenesis(ctx *cli.Context) error {
|
||||
defer stack.Close()
|
||||
|
||||
var overrides core.ChainOverrides
|
||||
if ctx.IsSet(utils.OverrideCancun.Name) {
|
||||
v := ctx.Uint64(utils.OverrideCancun.Name)
|
||||
overrides.OverrideCancun = &v
|
||||
if ctx.IsSet(utils.OverrideBohr.Name) {
|
||||
v := ctx.Uint64(utils.OverrideBohr.Name)
|
||||
overrides.OverrideBohr = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||
@@ -267,15 +269,21 @@ func initGenesis(ctx *cli.Context) error {
|
||||
defer chaindb.Close()
|
||||
|
||||
// if the trie data dir has been set, new trie db with a new state database
|
||||
if ctx.IsSet(utils.SeparateDBFlag.Name) {
|
||||
if ctx.IsSet(utils.MultiDataBaseFlag.Name) {
|
||||
statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name+"/state", 0, 0, "", "", false, false, false, false)
|
||||
if dbErr != nil {
|
||||
utils.Fatalf("Failed to open separate trie database: %v", dbErr)
|
||||
}
|
||||
chaindb.SetStateStore(statediskdb)
|
||||
blockdb, err := stack.OpenDatabaseWithFreezer(name+"/block", 0, 0, "", "", false, false, false, false)
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to open separate block database: %v", err)
|
||||
}
|
||||
chaindb.SetBlockStore(blockdb)
|
||||
log.Warn("Multi-database is an experimental feature")
|
||||
}
|
||||
|
||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
||||
defer triedb.Close()
|
||||
|
||||
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||
@@ -473,6 +481,13 @@ func dumpGenesis(ctx *cli.Context) error {
|
||||
}
|
||||
continue
|
||||
}
|
||||
// set the separate state & block database
|
||||
if stack.CheckIfMultiDataBase() && err == nil {
|
||||
stateDiskDb := utils.MakeStateDataBase(ctx, stack, true, false)
|
||||
db.SetStateStore(stateDiskDb)
|
||||
blockDb := utils.MakeBlockDatabase(ctx, stack, true, false)
|
||||
db.SetBlockStore(blockDb)
|
||||
}
|
||||
genesis, err := core.ReadGenesis(db)
|
||||
if err != nil {
|
||||
utils.Fatalf("failed to read genesis: %s", err)
|
||||
@@ -500,10 +515,16 @@ func importChain(ctx *cli.Context) error {
|
||||
// Start system runtime metrics collection
|
||||
go metrics.CollectProcessMetrics(3 * time.Second)
|
||||
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
stack, cfg := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
chain, db := utils.MakeChain(ctx, stack, false)
|
||||
backend, err := eth.New(stack, &cfg.Eth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
chain := backend.BlockChain()
|
||||
db := backend.ChainDb()
|
||||
defer db.Close()
|
||||
|
||||
// Start periodically gathering memory profiles
|
||||
@@ -757,8 +778,9 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
|
||||
}
|
||||
} else {
|
||||
// Use latest
|
||||
// TODO:: if versa, scheme = VersaScheme
|
||||
if scheme == rawdb.PathScheme {
|
||||
triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: pathdb.ReadOnly})
|
||||
triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly)})
|
||||
defer triedb.Close()
|
||||
if stateRoot := triedb.Head(); stateRoot != (common.Hash{}) {
|
||||
header.Root = stateRoot
|
||||
@@ -808,9 +830,11 @@ func dump(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
|
||||
defer db.Close()
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, db, true, true, false) // always enable preimage lookup
|
||||
defer triedb.Close()
|
||||
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -828,7 +852,8 @@ func dumpAllRootHashInPath(ctx *cli.Context) error {
|
||||
defer stack.Close()
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer db.Close()
|
||||
triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: pathdb.ReadOnly})
|
||||
// TODO:: ignore cmd
|
||||
triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly)})
|
||||
defer triedb.Close()
|
||||
|
||||
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db)
|
||||
|
||||
@@ -185,22 +185,14 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||
params.RialtoGenesisHash = common.HexToHash(v)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.OverrideCancun.Name) {
|
||||
v := ctx.Uint64(utils.OverrideCancun.Name)
|
||||
cfg.Eth.OverrideCancun = &v
|
||||
if ctx.IsSet(utils.OverrideBohr.Name) {
|
||||
v := ctx.Uint64(utils.OverrideBohr.Name)
|
||||
cfg.Eth.OverrideBohr = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||
cfg.Eth.OverrideVerkle = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideFeynman.Name) {
|
||||
v := ctx.Uint64(utils.OverrideFeynman.Name)
|
||||
cfg.Eth.OverrideFeynman = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideFeynmanFix.Name) {
|
||||
v := ctx.Uint64(utils.OverrideFeynmanFix.Name)
|
||||
cfg.Eth.OverrideFeynmanFix = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideFullImmutabilityThreshold.Name) {
|
||||
params.FullImmutabilityThreshold = ctx.Uint64(utils.OverrideFullImmutabilityThreshold.Name)
|
||||
downloader.FullMaxForkAncestry = ctx.Uint64(utils.OverrideFullImmutabilityThreshold.Name)
|
||||
@@ -211,9 +203,10 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||
if ctx.IsSet(utils.OverrideDefaultExtraReserveForBlobRequests.Name) {
|
||||
params.DefaultExtraReserveForBlobRequests = ctx.Uint64(utils.OverrideDefaultExtraReserveForBlobRequests.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.SeparateDBFlag.Name) && !stack.IsSeparatedDB() {
|
||||
utils.Fatalf("Failed to locate separate database subdirectory when separatedb parameter has been set")
|
||||
if ctx.IsSet(utils.OverrideBreatheBlockInterval.Name) {
|
||||
params.BreatheBlockInterval = ctx.Uint64(utils.OverrideBreatheBlockInterval.Name)
|
||||
}
|
||||
|
||||
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
||||
|
||||
// Create gauge with geth system and build information
|
||||
|
||||
@@ -106,12 +106,12 @@ Remove blockchain and state databases`,
|
||||
dbInspectTrieCmd = &cli.Command{
|
||||
Action: inspectTrie,
|
||||
Name: "inspect-trie",
|
||||
ArgsUsage: "<blocknum> <jobnum>",
|
||||
ArgsUsage: "<blocknum> <jobnum> <topn>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.SyncModeFlag,
|
||||
},
|
||||
Usage: "Inspect the MPT tree of the account and contract.",
|
||||
Usage: "Inspect the MPT tree of the account and contract. 'blocknum' can be latest/snapshot/number. 'topn' means output the top N storage tries info ranked by the total number of TrieNodes",
|
||||
Description: `This commands iterates the entrie WorldState.`,
|
||||
}
|
||||
dbCheckStateContentCmd = &cli.Command{
|
||||
@@ -386,6 +386,7 @@ func inspectTrie(ctx *cli.Context) error {
|
||||
blockNumber uint64
|
||||
trieRootHash common.Hash
|
||||
jobnum uint64
|
||||
topN uint64
|
||||
)
|
||||
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
@@ -405,24 +406,37 @@ func inspectTrie(ctx *cli.Context) error {
|
||||
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)
|
||||
return fmt.Errorf("failed to parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.NArg() == 1 {
|
||||
jobnum = 1000
|
||||
topN = 10
|
||||
} else if ctx.NArg() == 2 {
|
||||
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)
|
||||
}
|
||||
topN = 10
|
||||
} 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)
|
||||
return fmt.Errorf("failed to parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err)
|
||||
}
|
||||
|
||||
topN, err = strconv.ParseUint(ctx.Args().Get(2), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse topn, Args[1]: %v, err: %v", ctx.Args().Get(1), err)
|
||||
}
|
||||
}
|
||||
|
||||
if blockNumber != math.MaxUint64 {
|
||||
headerBlockHash = rawdb.ReadCanonicalHash(db, blockNumber)
|
||||
if headerBlockHash == (common.Hash{}) {
|
||||
return errors.New("ReadHeadBlockHash empry hash")
|
||||
return errors.New("ReadHeadBlockHash empty hash")
|
||||
}
|
||||
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
|
||||
trieRootHash = blockHeader.Root
|
||||
@@ -436,19 +450,21 @@ func inspectTrie(ctx *cli.Context) error {
|
||||
var config *triedb.Config
|
||||
if dbScheme == rawdb.PathScheme {
|
||||
config = &triedb.Config{
|
||||
PathDB: pathdb.ReadOnly,
|
||||
PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly),
|
||||
Cache: 0,
|
||||
}
|
||||
} else if dbScheme == rawdb.HashScheme {
|
||||
config = triedb.HashDefaults
|
||||
}
|
||||
|
||||
// TODO:: ignore cmd
|
||||
triedb := triedb.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)
|
||||
theInspect, err := trie.NewInspector(theTrie, triedb, trieRootHash, blockNumber, jobnum, int(topN))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -493,7 +509,7 @@ func ancientInspect(ctx *cli.Context) error {
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, true)
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer db.Close()
|
||||
return rawdb.AncientInspect(db)
|
||||
}
|
||||
@@ -519,7 +535,7 @@ func checkStateContent(ctx *cli.Context) error {
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer db.Close()
|
||||
var (
|
||||
it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32)
|
||||
it ethdb.Iterator
|
||||
hasher = crypto.NewKeccakState()
|
||||
got = make([]byte, 32)
|
||||
errs int
|
||||
@@ -527,6 +543,11 @@ func checkStateContent(ctx *cli.Context) error {
|
||||
startTime = time.Now()
|
||||
lastLog = time.Now()
|
||||
)
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
it = rawdb.NewKeyLengthIterator(db.StateStore().NewIterator(prefix, start), 32)
|
||||
} else {
|
||||
it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32)
|
||||
}
|
||||
for it.Next() {
|
||||
count++
|
||||
k := it.Key()
|
||||
@@ -573,9 +594,11 @@ func dbStats(ctx *cli.Context) error {
|
||||
defer db.Close()
|
||||
|
||||
showLeveldbStats(db)
|
||||
if db.StateStore() != nil {
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
fmt.Println("show stats of state store")
|
||||
showLeveldbStats(db.StateStore())
|
||||
fmt.Println("show stats of block store")
|
||||
showLeveldbStats(db.BlockStore())
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -591,10 +614,11 @@ func dbCompact(ctx *cli.Context) error {
|
||||
log.Info("Stats before compaction")
|
||||
showLeveldbStats(db)
|
||||
|
||||
statediskdb := db.StateStore()
|
||||
if statediskdb != nil {
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
fmt.Println("show stats of state store")
|
||||
showLeveldbStats(statediskdb)
|
||||
showLeveldbStats(db.StateStore())
|
||||
fmt.Println("show stats of block store")
|
||||
showLeveldbStats(db.BlockStore())
|
||||
}
|
||||
|
||||
log.Info("Triggering compaction")
|
||||
@@ -603,8 +627,12 @@ func dbCompact(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if statediskdb != nil {
|
||||
if err := statediskdb.Compact(nil, nil); err != nil {
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
if err := db.StateStore().Compact(nil, nil); err != nil {
|
||||
log.Error("Compact err", "error", err)
|
||||
return err
|
||||
}
|
||||
if err := db.BlockStore().Compact(nil, nil); err != nil {
|
||||
log.Error("Compact err", "error", err)
|
||||
return err
|
||||
}
|
||||
@@ -612,9 +640,11 @@ func dbCompact(ctx *cli.Context) error {
|
||||
|
||||
log.Info("Stats after compaction")
|
||||
showLeveldbStats(db)
|
||||
if statediskdb != nil {
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
fmt.Println("show stats of state store after compaction")
|
||||
showLeveldbStats(statediskdb)
|
||||
showLeveldbStats(db.StateStore())
|
||||
fmt.Println("show stats of block store after compaction")
|
||||
showLeveldbStats(db.BlockStore())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -635,18 +665,18 @@ func dbGet(ctx *cli.Context) error {
|
||||
log.Info("Could not decode the key", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
statediskdb := db.StateStore()
|
||||
data, err := db.Get(key)
|
||||
if err != nil {
|
||||
// if separate trie db exist, try to get it from separate db
|
||||
if statediskdb != nil {
|
||||
statedata, dberr := statediskdb.Get(key)
|
||||
if dberr == nil {
|
||||
fmt.Printf("key %#x: %#x\n", key, statedata)
|
||||
return nil
|
||||
}
|
||||
opDb := db
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
keyType := rawdb.DataTypeByKey(key)
|
||||
if keyType == rawdb.StateDataType {
|
||||
opDb = db.StateStore()
|
||||
} else if keyType == rawdb.BlockDataType {
|
||||
opDb = db.BlockStore()
|
||||
}
|
||||
}
|
||||
|
||||
data, err := opDb.Get(key)
|
||||
if err != nil {
|
||||
log.Info("Get operation failed", "key", fmt.Sprintf("%#x", key), "error", err)
|
||||
return err
|
||||
}
|
||||
@@ -809,11 +839,21 @@ func dbDelete(ctx *cli.Context) error {
|
||||
log.Info("Could not decode the key", "error", err)
|
||||
return err
|
||||
}
|
||||
data, err := db.Get(key)
|
||||
opDb := db
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
keyType := rawdb.DataTypeByKey(key)
|
||||
if keyType == rawdb.StateDataType {
|
||||
opDb = db.StateStore()
|
||||
} else if keyType == rawdb.BlockDataType {
|
||||
opDb = db.BlockStore()
|
||||
}
|
||||
}
|
||||
|
||||
data, err := opDb.Get(key)
|
||||
if err == nil {
|
||||
fmt.Printf("Previous value: %#x\n", data)
|
||||
}
|
||||
if err = db.Delete(key); err != nil {
|
||||
if err = opDb.Delete(key); err != nil {
|
||||
log.Info("Delete operation returned an error", "key", fmt.Sprintf("%#x", key), "error", err)
|
||||
return err
|
||||
}
|
||||
@@ -923,11 +963,22 @@ func dbPut(ctx *cli.Context) error {
|
||||
log.Info("Could not decode the value", "error", err)
|
||||
return err
|
||||
}
|
||||
data, err = db.Get(key)
|
||||
|
||||
opDb := db
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
keyType := rawdb.DataTypeByKey(key)
|
||||
if keyType == rawdb.StateDataType {
|
||||
opDb = db.StateStore()
|
||||
} else if keyType == rawdb.BlockDataType {
|
||||
opDb = db.BlockStore()
|
||||
}
|
||||
}
|
||||
|
||||
data, err = opDb.Get(key)
|
||||
if err == nil {
|
||||
fmt.Printf("Previous value: %#x\n", data)
|
||||
}
|
||||
return db.Put(key, value)
|
||||
return opDb.Put(key, value)
|
||||
}
|
||||
|
||||
// dbDumpTrie shows the key-value slots of a given storage trie
|
||||
@@ -940,8 +991,7 @@ func dbDumpTrie(ctx *cli.Context) error {
|
||||
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer db.Close()
|
||||
|
||||
triedb := utils.MakeTrieDatabase(ctx, db, false, true, false)
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, db, false, true, false)
|
||||
defer triedb.Close()
|
||||
|
||||
var (
|
||||
@@ -1019,7 +1069,7 @@ func freezerInspect(ctx *cli.Context) error {
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name))
|
||||
stack.Close()
|
||||
return rawdb.InspectFreezerTable(ancient, freezer, table, start, end)
|
||||
return rawdb.InspectFreezerTable(ancient, freezer, table, start, end, stack.CheckIfMultiDataBase())
|
||||
}
|
||||
|
||||
func importLDBdata(ctx *cli.Context) error {
|
||||
@@ -1159,7 +1209,7 @@ func showMetaData(ctx *cli.Context) error {
|
||||
defer stack.Close()
|
||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer db.Close()
|
||||
ancients, err := db.Ancients()
|
||||
ancients, err := db.BlockStore().Ancients()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
|
||||
}
|
||||
@@ -1206,7 +1256,7 @@ func hbss2pbss(ctx *cli.Context) error {
|
||||
defer stack.Close()
|
||||
|
||||
db := utils.MakeChainDatabase(ctx, stack, false, false)
|
||||
db.Sync()
|
||||
db.BlockStore().Sync()
|
||||
stateDiskDb := db.StateStore()
|
||||
defer db.Close()
|
||||
|
||||
@@ -1219,6 +1269,7 @@ func hbss2pbss(ctx *cli.Context) error {
|
||||
}
|
||||
if lastStateID == 0 || force {
|
||||
config := triedb.HashDefaults
|
||||
// TODO:: ignore cmd
|
||||
triedb := triedb.NewDatabase(db, config)
|
||||
triedb.Cap(0)
|
||||
log.Info("hbss2pbss triedb", "scheme", triedb.Scheme())
|
||||
|
||||
@@ -25,6 +25,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
@@ -70,13 +72,12 @@ var (
|
||||
utils.USBFlag,
|
||||
utils.SmartCardDaemonPathFlag,
|
||||
utils.RialtoHash,
|
||||
utils.OverrideCancun,
|
||||
utils.OverrideBohr,
|
||||
utils.OverrideVerkle,
|
||||
utils.OverrideFeynman,
|
||||
utils.OverrideFeynmanFix,
|
||||
utils.OverrideFullImmutabilityThreshold,
|
||||
utils.OverrideMinBlocksForBlobRequests,
|
||||
utils.OverrideDefaultExtraReserveForBlobRequests,
|
||||
utils.OverrideBreatheBlockInterval,
|
||||
utils.EnablePersonal,
|
||||
utils.TxPoolLocalsFlag,
|
||||
utils.TxPoolNoLocalsFlag,
|
||||
@@ -103,6 +104,7 @@ var (
|
||||
utils.TransactionHistoryFlag,
|
||||
utils.StateHistoryFlag,
|
||||
utils.PathDBSyncFlag,
|
||||
utils.JournalFileFlag,
|
||||
utils.LightServeFlag, // deprecated
|
||||
utils.LightIngressFlag, // deprecated
|
||||
utils.LightEgressFlag, // deprecated
|
||||
@@ -123,6 +125,7 @@ var (
|
||||
utils.CacheSnapshotFlag,
|
||||
// utils.CacheNoPrefetchFlag,
|
||||
utils.CachePreimagesFlag,
|
||||
utils.MultiDataBaseFlag,
|
||||
utils.PersistDiffFlag,
|
||||
utils.DiffBlockFlag,
|
||||
utils.PruneAncientDataFlag,
|
||||
@@ -144,6 +147,7 @@ var (
|
||||
// utils.MinerNewPayloadTimeout,
|
||||
utils.NATFlag,
|
||||
utils.NoDiscoverFlag,
|
||||
utils.PeerFilterPatternsFlag,
|
||||
utils.DiscoveryV4Flag,
|
||||
utils.DiscoveryV5Flag,
|
||||
utils.InstanceFlag,
|
||||
@@ -331,9 +335,6 @@ func prepare(ctx *cli.Context) {
|
||||
5. Networking is disabled; there is no listen-address, the maximum number of peers is set
|
||||
to 0, and discovery is disabled.
|
||||
`)
|
||||
|
||||
case !ctx.IsSet(utils.NetworkIdFlag.Name):
|
||||
log.Info("Starting Geth on BSC mainnet...")
|
||||
}
|
||||
// If we're a full node on mainnet without --cache specified, bump default cache allowance
|
||||
if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||
@@ -454,6 +455,10 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
|
||||
// Set the gas price to the limits from the CLI and start mining
|
||||
gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
|
||||
ethBackend.TxPool().SetGasTip(gasprice)
|
||||
gasCeil := ethBackend.Miner().GasCeil()
|
||||
if gasCeil > params.SystemTxsGas {
|
||||
ethBackend.TxPool().SetMaxGas(gasCeil - params.SystemTxsGas)
|
||||
}
|
||||
if err := ethBackend.StartMining(); err != nil {
|
||||
utils.Fatalf("Failed to start mining: %v", err)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frdb, err := rawdb.NewDatabaseWithFreezer(kvdb, ancient, namespace, readonly, disableFreeze, isLastOffset, pruneAncientData)
|
||||
frdb, err := rawdb.NewDatabaseWithFreezer(kvdb, ancient, namespace, readonly, disableFreeze, isLastOffset, pruneAncientData, false)
|
||||
if err != nil {
|
||||
kvdb.Close()
|
||||
return nil, err
|
||||
@@ -155,6 +155,12 @@ func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemai
|
||||
triedb := triedb.NewDatabase(db, nil)
|
||||
defer triedb.Close()
|
||||
|
||||
if err = db.SetupFreezerEnv(ðdb.FreezerEnv{
|
||||
ChainCfg: gspec.Config,
|
||||
BlobExtraReserve: params.DefaultExtraReserveForBlobRequests,
|
||||
}); err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -43,9 +43,11 @@ import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
cli "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
@@ -245,7 +247,17 @@ func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) {
|
||||
NoBuild: true,
|
||||
AsyncBuild: false,
|
||||
}
|
||||
snaptree, err := snapshot.New(snapconfig, chaindb, triedb.NewDatabase(chaindb, nil), headBlock.Root(), TriesInMemory, false)
|
||||
dbScheme := rawdb.ReadStateScheme(chaindb)
|
||||
var config *triedb.Config
|
||||
if dbScheme == rawdb.PathScheme {
|
||||
config = &triedb.Config{
|
||||
PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly),
|
||||
}
|
||||
} else if dbScheme == rawdb.HashScheme {
|
||||
config = triedb.HashDefaults
|
||||
}
|
||||
// TODO:: ignore snapshot
|
||||
snaptree, err := snapshot.New(snapconfig, chaindb, triedb.NewDatabase(chaindb, config), headBlock.Root(), TriesInMemory, false)
|
||||
if err != nil {
|
||||
log.Error("snaptree error", "err", err)
|
||||
return nil, err // The relevant snapshot(s) might not exist
|
||||
@@ -333,6 +345,9 @@ func pruneBlock(ctx *cli.Context) error {
|
||||
stack, config = makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
blockAmountReserved = ctx.Uint64(utils.BlockAmountReserved.Name)
|
||||
if blockAmountReserved < params.FullImmutabilityThreshold {
|
||||
return fmt.Errorf("block-amount-reserved must be greater than or equal to %d", params.FullImmutabilityThreshold)
|
||||
}
|
||||
chaindb, err = accessDb(ctx, stack)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -355,7 +370,15 @@ func pruneBlock(ctx *cli.Context) error {
|
||||
if !ctx.IsSet(utils.AncientFlag.Name) {
|
||||
return errors.New("datadir.ancient must be set")
|
||||
} else {
|
||||
oldAncientPath = ctx.String(utils.AncientFlag.Name)
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
ancientPath := ctx.String(utils.AncientFlag.Name)
|
||||
index := strings.LastIndex(ancientPath, "/ancient/chain")
|
||||
if index != -1 {
|
||||
oldAncientPath = ancientPath[:index] + "/block/ancient/chain"
|
||||
}
|
||||
} else {
|
||||
oldAncientPath = ctx.String(utils.AncientFlag.Name)
|
||||
}
|
||||
if !filepath.IsAbs(oldAncientPath) {
|
||||
// force absolute paths, which often fail due to the splicing of relative paths
|
||||
return errors.New("datadir.ancient not abs path")
|
||||
@@ -401,7 +424,7 @@ func pruneBlock(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
if _, err := os.Stat(newAncientPath); err == nil {
|
||||
// No file lock found for old ancientDB but new ancientDB exsisted, indicating the geth was interrupted
|
||||
// No file lock found for old ancientDB but new ancientDB existed, indicating the geth was interrupted
|
||||
// after old ancientDB removal, this happened after backup successfully, so just rename the new ancientDB
|
||||
if err := blockpruner.AncientDbReplacer(); err != nil {
|
||||
log.Error("Failed to rename new ancient directory")
|
||||
@@ -524,7 +547,7 @@ func verifyState(ctx *cli.Context) error {
|
||||
log.Error("Failed to load head block")
|
||||
return errors.New("no head block")
|
||||
}
|
||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
|
||||
defer triedb.Close()
|
||||
|
||||
snapConfig := snapshot.Config{
|
||||
@@ -579,7 +602,7 @@ func traverseState(ctx *cli.Context) error {
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer chaindb.Close()
|
||||
|
||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
|
||||
defer triedb.Close()
|
||||
|
||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||
@@ -688,7 +711,7 @@ func traverseRawState(ctx *cli.Context) error {
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer chaindb.Close()
|
||||
|
||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
|
||||
defer triedb.Close()
|
||||
|
||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||
@@ -852,7 +875,8 @@ func dumpState(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
triedb := utils.MakeTrieDatabase(ctx, db, false, true, false)
|
||||
defer db.Close()
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, db, false, true, false)
|
||||
defer triedb.Close()
|
||||
|
||||
snapConfig := snapshot.Config{
|
||||
@@ -935,7 +959,7 @@ func snapshotExportPreimages(ctx *cli.Context) error {
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||
defer chaindb.Close()
|
||||
|
||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
|
||||
defer triedb.Close()
|
||||
|
||||
var root common.Hash
|
||||
|
||||
@@ -24,4 +24,24 @@ testnet validators version
|
||||
### 2.Get Transaction Count
|
||||
```bash
|
||||
node gettxcount.js --rpc ${url} --startNum ${start} --endNum ${end} --miner ${miner} (optional)
|
||||
```
|
||||
```
|
||||
|
||||
### 3. Get Performance
|
||||
```bash
|
||||
node get_perf.js --rpc ${url} --startNum ${start} --endNum ${end}
|
||||
```
|
||||
output as following
|
||||
```bash
|
||||
Get the performance between [ 19470 , 19670 )
|
||||
txCountPerBlock = 3142.81 txCountTotal = 628562 BlockCount = 200 avgBlockTime = 3.005 inturnBlocksRatio = 0.975
|
||||
txCountPerSecond = 1045.8602329450914 avgGasUsedPerBlock = 250.02062627 avgGasUsedPerSecond = 83.20153952412646
|
||||
```
|
||||
|
||||
### 4. Get validators slash count
|
||||
```bash
|
||||
use the latest block
|
||||
node getslashcount.js --Rpc ${ArchiveRpc}
|
||||
use a block number
|
||||
node getslashcount.js --Rpc ${ArchiveRpc} --Num ${blockNum}
|
||||
```
|
||||
|
||||
|
||||
51
cmd/jsutils/check_blobtx.js
Normal file
51
cmd/jsutils/check_blobtx.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
// depends on ethjs v6.11.0+ for 4844, https://github.com/ethers-io/ethers.js/releases/tag/v6.11.0
|
||||
// BSC testnet enabled 4844 on block: 39539137
|
||||
// Usage:
|
||||
// nvm use 20
|
||||
// node check_blobtx.js --rpc https://data-seed-prebsc-1-s1.binance.org:8545 --startNum 39539137
|
||||
// node check_blobtx.js --rpc https://data-seed-prebsc-1-s1.binance.org:8545 --startNum 39539137 --endNum 40345994
|
||||
program.option("--rpc <Rpc>", "Rpc Server URL");
|
||||
program.option("--startNum <Num>", "start block", 0);
|
||||
program.option("--endNum <Num>", "end block", 0);
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.rpc);
|
||||
const main = async () => {
|
||||
var startBlock = parseInt(program.startNum)
|
||||
var endBlock = parseInt(program.endNum)
|
||||
if (isNaN(endBlock) || isNaN(startBlock) || startBlock == 0) {
|
||||
console.error("invalid input, --startNum", program.startNum, "--end", program.endNum)
|
||||
return
|
||||
}
|
||||
// if --endNum is not specified, set it to the latest block number.
|
||||
if (endBlock == 0) {
|
||||
endBlock = await provider.getBlockNumber();
|
||||
}
|
||||
if (startBlock > endBlock) {
|
||||
console.error("invalid input, startBlock:",startBlock, " endBlock:", endBlock);
|
||||
return
|
||||
}
|
||||
|
||||
for (let i = startBlock; i <= endBlock; i++) {
|
||||
let blockData = await provider.getBlock(i);
|
||||
console.log("startBlock:",startBlock, "endBlock:", endBlock, "curBlock", i, "blobGasUsed", blockData.blobGasUsed);
|
||||
if (blockData.blobGasUsed == 0) {
|
||||
continue
|
||||
}
|
||||
for (let txIndex = 0; txIndex<= blockData.transactions.length - 1; txIndex++) {
|
||||
let txHash = blockData.transactions[txIndex]
|
||||
let txData = await provider.getTransaction(txHash);
|
||||
if (txData.type == 3) {
|
||||
console.log("BlobTx in block:",i, " txIndex:", txIndex, " txHash:", txHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
49
cmd/jsutils/faucet_request.js
Normal file
49
cmd/jsutils/faucet_request.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
// Usage:
|
||||
// node faucet_request.js --rpc localhost:8545 --startNum 39539137
|
||||
// node faucet_request.js --rpc localhost:8545 --startNum 39539137 --endNum 40345994
|
||||
|
||||
// node faucet_request.js --rpc https://data-seed-prebsc-1-s1.bnbchain.org:8545 --startNum 39539137 --endNum 40345994
|
||||
program.option("--rpc <Rpc>", "Rpc Server URL");
|
||||
program.option("--startNum <Num>", "start block", 0);
|
||||
program.option("--endNum <Num>", "end block", 0);
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.rpc);
|
||||
const main = async () => {
|
||||
var startBlock = parseInt(program.startNum)
|
||||
var endBlock = parseInt(program.endNum)
|
||||
if (isNaN(endBlock) || isNaN(startBlock) || startBlock == 0) {
|
||||
console.error("invalid input, --startNum", program.startNum, "--end", program.endNum)
|
||||
return
|
||||
}
|
||||
// if --endNum is not specified, set it to the latest block number.
|
||||
if (endBlock == 0) {
|
||||
endBlock = await provider.getBlockNumber();
|
||||
}
|
||||
if (startBlock > endBlock) {
|
||||
console.error("invalid input, startBlock:",startBlock, " endBlock:", endBlock);
|
||||
return
|
||||
}
|
||||
|
||||
let startBalance = await provider.getBalance("0xaa25Aa7a19f9c426E07dee59b12f944f4d9f1DD3", startBlock)
|
||||
let endBalance = await provider.getBalance("0xaa25Aa7a19f9c426E07dee59b12f944f4d9f1DD3", endBlock)
|
||||
const faucetAmount = BigInt(0.3 * 10**18); // Convert 0.3 ether to wei as a BigInt
|
||||
const numFaucetRequest = (startBalance - endBalance) / faucetAmount;
|
||||
|
||||
// Convert BigInt to ether
|
||||
const startBalanceEth = Number(startBalance) / 10**18;
|
||||
const endBalanceEth = Number(endBalance) / 10**18;
|
||||
|
||||
console.log(`Start Balance: ${startBalanceEth} ETH`);
|
||||
console.log(`End Balance: ${endBalanceEth} ETH`);
|
||||
|
||||
console.log("successful faucet request: ",numFaucetRequest);
|
||||
};
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
58
cmd/jsutils/get_perf.js
Normal file
58
cmd/jsutils/get_perf.js
Normal file
@@ -0,0 +1,58 @@
|
||||
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.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.rpc)
|
||||
|
||||
const main = async () => {
|
||||
let txCountTotal = 0;
|
||||
let gasUsedTotal = 0;
|
||||
let inturnBlocks = 0;
|
||||
for (let i = program.startNum; i < program.endNum; i++) {
|
||||
let txCount = await provider.send("eth_getBlockTransactionCountByNumber", [
|
||||
ethers.toQuantity(i)]);
|
||||
txCountTotal += ethers.toNumber(txCount)
|
||||
|
||||
let header = await provider.send("eth_getHeaderByNumber", [
|
||||
ethers.toQuantity(i)]);
|
||||
let gasUsed = eval(eval(header.gasUsed).toString(10))
|
||||
gasUsedTotal += gasUsed
|
||||
let difficulty = eval(eval(header.difficulty).toString(10))
|
||||
if (difficulty == 2) {
|
||||
inturnBlocks += 1
|
||||
}
|
||||
let timestamp = eval(eval(header.timestamp).toString(10))
|
||||
console.log("BlockNumber =", i, "mod =", i%4, "miner =", header.miner , "difficulty =", difficulty, "txCount =", ethers.toNumber(txCount), "gasUsed", gasUsed, "timestamp", timestamp)
|
||||
}
|
||||
|
||||
let blockCount = program.endNum - program.startNum
|
||||
let txCountPerBlock = txCountTotal/blockCount
|
||||
|
||||
let startHeader = await provider.send("eth_getHeaderByNumber", [
|
||||
ethers.toQuantity(program.startNum)]);
|
||||
let startTime = eval(eval(startHeader.timestamp).toString(10))
|
||||
let endHeader = await provider.send("eth_getHeaderByNumber", [
|
||||
ethers.toQuantity(program.endNum)]);
|
||||
let endTime = eval(eval(endHeader.timestamp).toString(10))
|
||||
let timeCost = endTime - startTime
|
||||
let avgBlockTime = timeCost/blockCount
|
||||
let inturnBlocksRatio = inturnBlocks/blockCount
|
||||
let tps = txCountTotal/timeCost
|
||||
let M = 1000000
|
||||
let avgGasUsedPerBlock = gasUsedTotal/blockCount/M
|
||||
let avgGasUsedPerSecond = gasUsedTotal/timeCost/M
|
||||
|
||||
console.log("Get the performance between [", program.startNum, ",", program.endNum, ")");
|
||||
console.log("txCountPerBlock =", txCountPerBlock, "txCountTotal =", txCountTotal, "BlockCount =", blockCount, "avgBlockTime =", avgBlockTime, "inturnBlocksRatio =", inturnBlocksRatio);
|
||||
console.log("txCountPerSecond =", tps, "avgGasUsedPerBlock =", avgGasUsedPerBlock, "avgGasUsedPerSecond =", avgGasUsedPerSecond);
|
||||
};
|
||||
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
119
cmd/jsutils/getslashcount.js
Normal file
119
cmd/jsutils/getslashcount.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
program.option("--Rpc <Rpc>", "Rpc");
|
||||
program.option("--Num <Num>", "num", 0)
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.Rpc);
|
||||
|
||||
const slashAbi = [
|
||||
"function getSlashIndicator(address validatorAddr) external view returns (uint256, uint256)"
|
||||
]
|
||||
const validatorSetAbi = [
|
||||
"function getLivingValidators() external view returns (address[], bytes[])"
|
||||
]
|
||||
const stakeHubAbi = [
|
||||
"function getValidatorDescription(address validatorAddr) external view returns (tuple(string, string, string, string))",
|
||||
"function consensusToOperator(address consensusAddr) public view returns (address)"
|
||||
]
|
||||
const addrValidatorSet = '0x0000000000000000000000000000000000001000';
|
||||
const validatorSet = new ethers.Contract(addrValidatorSet, validatorSetAbi, provider);
|
||||
|
||||
const addrSlash = '0x0000000000000000000000000000000000001001';
|
||||
const slashIndicator = new ethers.Contract(addrSlash, slashAbi, provider)
|
||||
|
||||
const addrStakeHub = '0x0000000000000000000000000000000000002002';
|
||||
const stakeHub = new ethers.Contract(addrStakeHub, stakeHubAbi, provider)
|
||||
|
||||
const validatorMap = new Map([
|
||||
//BSC
|
||||
["0x37e9627A91DD13e453246856D58797Ad6583D762", "LegendII"],
|
||||
["0xB4647b856CB9C3856d559C885Bed8B43e0846a47", "CertiK"],
|
||||
["0x75B851a27D7101438F45fce31816501193239A83", "Figment"],
|
||||
["0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0", "BscScan"],
|
||||
["0xCa503a7eD99eca485da2E875aedf7758472c378C", "InfStones"],
|
||||
["0x5009317FD4F6F8FeEa9dAe41E5F0a4737BB7A7D5", "NodeReal"],
|
||||
["0x1cFDBd2dFf70C6e2e30df5012726F87731F38164", "Tranchess"],
|
||||
["0xF8de5e61322302b2c6e0a525cC842F10332811bf", "Namelix"],
|
||||
["0xCcB42A9b8d6C46468900527Bc741938E78AB4577", "Turing"],
|
||||
["0x9f1b7FAE54BE07F4FEE34Eb1aaCb39A1F7B6FC92", "TWStaking"],
|
||||
["0x7E1FdF03Eb3aC35BF0256694D7fBe6B6d7b3E0c8","LegendIII"],
|
||||
["0x7b501c7944185130DD4aD73293e8Aa84eFfDcee7","MathW"],
|
||||
["0x58567F7A51a58708C8B40ec592A38bA64C0697De","Legend"],
|
||||
["0x460A252B4fEEFA821d3351731220627D7B7d1F3d","Defibit"],
|
||||
["0x8A239732871AdC8829EA2f47e94087C5FBad47b6","The48Club"],
|
||||
["0xD3b0d838cCCEAe7ebF1781D11D1bB741DB7Fe1A7","BNBEve"],
|
||||
["0xF8B99643fAfC79d9404DE68E48C4D49a3936f787","Avengers"],
|
||||
["0x4e5acf9684652BEa56F2f01b7101a225Ee33d23f","HashKey"],
|
||||
["0x9bb56C2B4DBE5a06d79911C9899B6f817696ACFc","Feynman"],
|
||||
["0xbdcc079BBb23C1D9a6F36AA31309676C258aBAC7","Fuji"],
|
||||
["0x38944092685a336CB6B9ea58836436709a2adC89","Shannon"],
|
||||
["0xfC1004C0f296Ec3Df4F6762E9EabfcF20EB304a2","Aoraki"],
|
||||
["0xa0884bb00E5F23fE2427f0E5eC9E51F812848563","Coda"],
|
||||
["0xe7776De78740f28a96412eE5cbbB8f90896b11A5","Ankr"],
|
||||
["0xA2D969E82524001Cb6a2357dBF5922B04aD2FCD8","Pexmons"],
|
||||
["0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","Zen"],
|
||||
["0x4d15D9BCd0c2f33E7510c0de8b42697CA558234a","LegendVII"],
|
||||
["0x1579ca96EBd49A0B173f86C372436ab1AD393380","LegendV"],
|
||||
["0xd1F72d433f362922f6565FC77c25e095B29141c8","LegendVI"],
|
||||
["0xf9814D93b4d904AaA855cBD4266D6Eb0Ec1Aa478","Legend8"],
|
||||
["0x025a4e09Ea947b8d695f53ddFDD48ddB8F9B06b7","Ciscox"],
|
||||
["0xE9436F6F30b4B01b57F2780B2898f3820EbD7B98","LegendIV"],
|
||||
["0xC2d534F079444E6E7Ff9DabB3FD8a26c607932c8","Axion"],
|
||||
["0x9F7110Ba7EdFda83Fc71BeA6BA3c0591117b440D","LegendIX"],
|
||||
["0xB997Bf1E3b96919fBA592c1F61CE507E165Ec030","Seoraksan"],
|
||||
["0x286C1b674d48cFF67b4096b6c1dc22e769581E91","Sigm8"],
|
||||
["0x73A26778ef9509a6E94b55310eE7233795a9EB25","Coinlix"],
|
||||
["0x18c44f4FBEde9826C7f257d500A65a3D5A8edebc","Nozti"],
|
||||
["0xA100FCd08cE722Dc68Ddc3b54237070Cb186f118","Tiollo"],
|
||||
["0x0F28847cfdbf7508B13Ebb9cEb94B2f1B32E9503","Raptas"],
|
||||
["0xfD85346c8C991baC16b9c9157e6bdfDACE1cD7d7","Glorin"],
|
||||
["0x978F05CED39A4EaFa6E8FD045Fe2dd6Da836c7DF","NovaX"],
|
||||
["0xd849d1dF66bFF1c2739B4399425755C2E0fAbbAb","Nexa"],
|
||||
["0xA015d9e9206859c13201BB3D6B324d6634276534","Star"],
|
||||
["0x5ADde0151BfAB27f329e5112c1AeDeed7f0D3692","Veri"],
|
||||
//Chapel
|
||||
["0x08265dA01E1A65d62b903c7B34c08cB389bF3D99","Ararat"],
|
||||
["0x7f5f2cF1aec83bF0c74DF566a41aa7ed65EA84Ea","Kita"],
|
||||
["0x53387F3321FD69d1E030BB921230dFb188826AFF","Fuji"],
|
||||
["0x76D76ee8823dE52A1A431884c2ca930C5e72bff3","Seoraksan"],
|
||||
["0xd447b49CD040D20BC21e49ffEa6487F5638e4346","Everest"],
|
||||
["0x1a3d9D7A717D64e6088aC937d5aAcDD3E20ca963","Elbrus"],
|
||||
["0x40D3256EB0BaBE89f0ea54EDAa398513136612f5","Bloxroute"],
|
||||
["0xF9a1Db0d6f22Bd78ffAECCbc8F47c83Df9FBdbCf","Test"]
|
||||
]);
|
||||
|
||||
|
||||
const main = async () => {
|
||||
let blockNum = ethers.getNumber(program.Num)
|
||||
if (blockNum === 0) {
|
||||
blockNum = await provider.getBlockNumber()
|
||||
}
|
||||
let block = await provider.getBlock(blockNum)
|
||||
console.log("At block", blockNum, "time", block.date)
|
||||
const data = await validatorSet.getLivingValidators({blockTag:blockNum})
|
||||
let totalSlash = 0
|
||||
for (let i = 0; i < data[0].length; i++) {
|
||||
let addr = data[0][i];
|
||||
var val
|
||||
if (!validatorMap.has(addr)) {
|
||||
let opAddr = await stakeHub.consensusToOperator(addr, {blockTag:blockNum})
|
||||
let value = await stakeHub.getValidatorDescription(opAddr, {blockTag:blockNum})
|
||||
val = value[0]
|
||||
console.log(addr, val)
|
||||
} else {
|
||||
val = validatorMap.get(addr)
|
||||
}
|
||||
let info = await slashIndicator.getSlashIndicator(addr, {blockTag:blockNum})
|
||||
let count = ethers.toNumber(info[1])
|
||||
totalSlash += count
|
||||
console.log("Slash:", count, addr, val)
|
||||
}
|
||||
console.log("Total slash count", totalSlash)
|
||||
};
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -93,10 +93,10 @@ var (
|
||||
Value: flags.DirectoryString(node.DefaultDataDir()),
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
SeparateDBFlag = &cli.BoolFlag{
|
||||
Name: "separatedb",
|
||||
Usage: "Enable a separated trie database, it will be created within a subdirectory called state, " +
|
||||
"Users can copy this state directory to another directory or disk, and then create a symbolic link to the state directory under the chaindata",
|
||||
MultiDataBaseFlag = &cli.BoolFlag{
|
||||
Name: "multidatabase",
|
||||
Usage: "Enable a separated state and block database, it will be created within two subdirectory called state and block, " +
|
||||
"Users can copy this state or block directory to another directory or disk, and then create a symbolic link to the state directory under the chaindata",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
DirectBroadcastFlag = &cli.BoolFlag{
|
||||
@@ -224,7 +224,7 @@ var (
|
||||
// hbss2pbss command options
|
||||
ForceFlag = &cli.BoolFlag{
|
||||
Name: "force",
|
||||
Usage: "Force convert hbss trie node to pbss trie node. Ingore any metadata",
|
||||
Usage: "Force convert hbss trie node to pbss trie node. Ignore any metadata",
|
||||
Value: false,
|
||||
}
|
||||
// Dump command options.
|
||||
@@ -305,9 +305,9 @@ var (
|
||||
Usage: "Manually specify the Rialto Genesis Hash, to trigger builtin network logic",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideCancun = &cli.Uint64Flag{
|
||||
Name: "override.cancun",
|
||||
Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting",
|
||||
OverrideBohr = &cli.Uint64Flag{
|
||||
Name: "override.bohr",
|
||||
Usage: "Manually specify the Bohr fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideVerkle = &cli.Uint64Flag{
|
||||
@@ -315,15 +315,6 @@ var (
|
||||
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideFeynman = &cli.Uint64Flag{
|
||||
Name: "override.feynman",
|
||||
Usage: "Manually specify the Feynman fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideFeynmanFix = &cli.Uint64Flag{
|
||||
Name: "override.feynmanfix",
|
||||
Usage: "Manually specify the FeynmanFix fork timestamp, overriding the bundled setting",
|
||||
}
|
||||
OverrideFullImmutabilityThreshold = &cli.Uint64Flag{
|
||||
Name: "override.immutabilitythreshold",
|
||||
Usage: "It is the number of blocks after which a chain segment is considered immutable, only for testing purpose",
|
||||
@@ -342,6 +333,12 @@ var (
|
||||
Value: params.DefaultExtraReserveForBlobRequests,
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideBreatheBlockInterval = &cli.Uint64Flag{
|
||||
Name: "override.breatheblockinterval",
|
||||
Usage: "It changes the interval between breathe blocks, only for testing purpose",
|
||||
Value: params.BreatheBlockInterval,
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
SyncModeFlag = &flags.TextMarshalerFlag{
|
||||
Name: "syncmode",
|
||||
Usage: `Blockchain sync mode ("snap" or "full")`,
|
||||
@@ -365,6 +362,12 @@ var (
|
||||
Value: false,
|
||||
Category: flags.StateCategory,
|
||||
}
|
||||
JournalFileFlag = &cli.BoolFlag{
|
||||
Name: "journalfile",
|
||||
Usage: "Enable using journal file to store the TrieJournal instead of KVDB in pbss (default = false)",
|
||||
Value: false,
|
||||
Category: flags.StateCategory,
|
||||
}
|
||||
StateHistoryFlag = &cli.Uint64Flag{
|
||||
Name: "history.state",
|
||||
Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)",
|
||||
@@ -876,6 +879,11 @@ var (
|
||||
Usage: "Disables the peer discovery mechanism (manual peer addition)",
|
||||
Category: flags.NetworkingCategory,
|
||||
}
|
||||
PeerFilterPatternsFlag = &cli.StringSliceFlag{
|
||||
Name: "peerfilter",
|
||||
Usage: "Disallow peers connection if peer name matches the given regular expressions",
|
||||
Category: flags.NetworkingCategory,
|
||||
}
|
||||
DiscoveryV4Flag = &cli.BoolFlag{
|
||||
Name: "discovery.v4",
|
||||
Aliases: []string{"discv4"},
|
||||
@@ -1069,6 +1077,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||
Name: "block-amount-reserved",
|
||||
Usage: "Sets the expected remained amount of blocks for offline block prune",
|
||||
Category: flags.BlockHistoryCategory,
|
||||
Value: params.FullImmutabilityThreshold,
|
||||
}
|
||||
|
||||
CheckSnapshotWithMPT = &cli.BoolFlag{
|
||||
@@ -1144,7 +1153,6 @@ var (
|
||||
DBEngineFlag,
|
||||
StateSchemeFlag,
|
||||
HttpHeaderFlag,
|
||||
SeparateDBFlag,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1542,6 +1550,9 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
|
||||
if ctx.IsSet(NoDiscoverFlag.Name) {
|
||||
cfg.NoDiscovery = true
|
||||
}
|
||||
if ctx.IsSet(PeerFilterPatternsFlag.Name) {
|
||||
cfg.PeerFilterPatterns = ctx.StringSlice(PeerFilterPatternsFlag.Name)
|
||||
}
|
||||
|
||||
CheckExclusive(ctx, DiscoveryV4Flag, NoDiscoverFlag)
|
||||
CheckExclusive(ctx, DiscoveryV5Flag, NoDiscoverFlag)
|
||||
@@ -1962,6 +1973,10 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
if ctx.IsSet(PathDBSyncFlag.Name) {
|
||||
cfg.PathSyncFlush = true
|
||||
}
|
||||
if ctx.IsSet(JournalFileFlag.Name) {
|
||||
cfg.JournalFileEnabled = true
|
||||
}
|
||||
|
||||
if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 {
|
||||
cfg.TransactionHistory = 0
|
||||
log.Warn("Disabled transaction unindexing for archive node")
|
||||
@@ -2057,7 +2072,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
}
|
||||
cfg.Genesis = core.DefaultBSCGenesisBlock()
|
||||
SetDNSDiscoveryDefaults(cfg, params.BSCGenesisHash)
|
||||
case ctx.Bool(ChapelFlag.Name):
|
||||
case ctx.Bool(ChapelFlag.Name) || cfg.NetworkId == 97:
|
||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||
cfg.NetworkId = 97
|
||||
}
|
||||
@@ -2377,9 +2392,11 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree
|
||||
default:
|
||||
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false)
|
||||
// set the separate state database
|
||||
if stack.IsSeparatedDB() && err == nil {
|
||||
if stack.CheckIfMultiDataBase() && err == nil {
|
||||
stateDiskDb := MakeStateDataBase(ctx, stack, readonly, false)
|
||||
chainDb.SetStateStore(stateDiskDb)
|
||||
blockDb := MakeBlockDatabase(ctx, stack, readonly, false)
|
||||
chainDb.SetBlockStore(blockDb)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@@ -2391,7 +2408,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree
|
||||
// MakeStateDataBase open a separate state database using the flags passed to the client and will hard crash if it fails.
|
||||
func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database {
|
||||
cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
|
||||
handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) / 2
|
||||
handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) * 90 / 100
|
||||
statediskdb, err := stack.OpenDatabaseWithFreezer("chaindata/state", cache, handles, "", "", readonly, disableFreeze, false, false)
|
||||
if err != nil {
|
||||
Fatalf("Failed to open separate trie database: %v", err)
|
||||
@@ -2399,6 +2416,23 @@ func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFree
|
||||
return statediskdb
|
||||
}
|
||||
|
||||
// MakeBlockDatabase open a separate block database using the flags passed to the client and will hard crash if it fails.
|
||||
func MakeBlockDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database {
|
||||
cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
|
||||
handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) / 10
|
||||
blockDb, err := stack.OpenDatabaseWithFreezer("chaindata/block", cache, handles, "", "", readonly, disableFreeze, false, false)
|
||||
if err != nil {
|
||||
Fatalf("Failed to open separate block database: %v", err)
|
||||
}
|
||||
return blockDb
|
||||
}
|
||||
|
||||
func PathDBConfigAddJournalFilePath(stack *node.Node, config *pathdb.Config) *pathdb.Config {
|
||||
path := fmt.Sprintf("%s/%s", stack.ResolvePath("chaindata"), eth.JournalFileName)
|
||||
config.JournalFilePath = path
|
||||
return config
|
||||
}
|
||||
|
||||
// tryMakeReadOnlyDatabase try to open the chain database in read-only mode,
|
||||
// or fallback to write mode if the database is not initialized.
|
||||
//
|
||||
@@ -2541,7 +2575,7 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
|
||||
}
|
||||
|
||||
// MakeTrieDatabase constructs a trie database based on the configured scheme.
|
||||
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database {
|
||||
func MakeTrieDatabase(ctx *cli.Context, stack *node.Node, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database {
|
||||
config := &triedb.Config{
|
||||
Preimages: preimage,
|
||||
IsVerkle: isVerkle,
|
||||
@@ -2555,6 +2589,7 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
|
||||
// ignore the parameter silently. TODO(rjl493456442)
|
||||
// please config it if read mode is implemented.
|
||||
config.HashDB = hashdb.Defaults
|
||||
// TODO::skip MakeTrieDatabase
|
||||
return triedb.NewDatabase(disk, config)
|
||||
}
|
||||
if readOnly {
|
||||
@@ -2562,6 +2597,8 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
|
||||
} else {
|
||||
config.PathDB = pathdb.Defaults
|
||||
}
|
||||
config.PathDB.JournalFilePath = fmt.Sprintf("%s/%s", stack.ResolvePath("chaindata"), eth.JournalFileName)
|
||||
// TODO::skip MakeTrieDatabase
|
||||
return triedb.NewDatabase(disk, config)
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
||||
t.Fatalf("unable to initialize chain: %v", err)
|
||||
}
|
||||
if _, err := chain.InsertChain(blocks); err != nil {
|
||||
t.Fatalf("error insterting chain: %v", err)
|
||||
t.Fatalf("error inserting chain: %v", err)
|
||||
}
|
||||
|
||||
// Make temp directory for era files.
|
||||
@@ -163,7 +163,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
||||
|
||||
// Now import Era.
|
||||
freezer := t.TempDir()
|
||||
db2, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false, false, false, false)
|
||||
db2, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -15,14 +15,13 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
const SecondsPerDay uint64 = 86400
|
||||
|
||||
// the params should be two blocks' time(timestamp)
|
||||
func sameDayInUTC(first, second uint64) bool {
|
||||
return first/SecondsPerDay == second/SecondsPerDay
|
||||
return first/params.BreatheBlockInterval == second/params.BreatheBlockInterval
|
||||
}
|
||||
|
||||
func isBreatheBlock(lastBlockTime, blockTime uint64) bool {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
||||
"github.com/willf/bitset"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
@@ -48,8 +48,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
inMemorySnapshots = 256 // Number of recent snapshots to keep in memory
|
||||
inMemorySignatures = 4096 // Number of recent block signatures 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
|
||||
inMemoryHeaders = 86400 // Number of recent headers to keep in memory for double sign detection,
|
||||
|
||||
checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database
|
||||
defaultEpochLength = uint64(100) // Default number of blocks of checkpoint to update validatorSet from contract
|
||||
@@ -80,6 +81,7 @@ var (
|
||||
verifyVoteAttestationErrorCounter = metrics.NewRegisteredCounter("parlia/verifyVoteAttestation/error", nil)
|
||||
updateAttestationErrorCounter = metrics.NewRegisteredCounter("parlia/updateAttestation/error", nil)
|
||||
validVotesfromSelfCounter = metrics.NewRegisteredCounter("parlia/VerifyVote/self", nil)
|
||||
doubleSignCounter = metrics.NewRegisteredCounter("parlia/doublesign", nil)
|
||||
|
||||
systemContracts = map[common.Address]bool{
|
||||
common.HexToAddress(systemcontracts.ValidatorContract): true,
|
||||
@@ -216,8 +218,11 @@ type Parlia struct {
|
||||
genesisHash common.Hash
|
||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||
|
||||
recentSnaps *lru.ARCCache // Snapshots for recent block to speed up
|
||||
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
||||
recentSnaps *lru.ARCCache // Snapshots for recent block to speed up
|
||||
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
||||
recentHeaders *lru.ARCCache //
|
||||
// Recent headers to check for double signing: key includes block number and miner. value is the block header
|
||||
// If same key's value already exists for different block header roots then double sign is detected
|
||||
|
||||
signer types.Signer
|
||||
|
||||
@@ -263,6 +268,10 @@ func New(
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
recentHeaders, err := lru.NewARC(inMemoryHeaders)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
vABIBeforeLuban, err := abi.JSON(strings.NewReader(validatorSetABIBeforeLuban))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -286,6 +295,7 @@ func New(
|
||||
db: db,
|
||||
ethAPI: ethAPI,
|
||||
recentSnaps: recentSnaps,
|
||||
recentHeaders: recentHeaders,
|
||||
signatures: signatures,
|
||||
validatorSetABIBeforeLuban: vABIBeforeLuban,
|
||||
validatorSetABI: vABI,
|
||||
@@ -297,6 +307,10 @@ func New(
|
||||
return c
|
||||
}
|
||||
|
||||
func (p *Parlia) Period() uint64 {
|
||||
return p.config.Period
|
||||
}
|
||||
|
||||
func (p *Parlia) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) {
|
||||
// deploy a contract
|
||||
if tx.To() == nil {
|
||||
@@ -809,6 +823,17 @@ func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Hea
|
||||
return errCoinBaseMisMatch
|
||||
}
|
||||
|
||||
// check for double sign & add to cache
|
||||
key := proposalKey(*header)
|
||||
preHash, ok := p.recentHeaders.Get(key)
|
||||
if ok && preHash != header.Hash() {
|
||||
doubleSignCounter.Inc(1)
|
||||
log.Warn("DoubleSign detected", " block", header.Number, " miner", header.Coinbase,
|
||||
"hash1", preHash.(common.Hash), "hash2", header.Hash())
|
||||
} else {
|
||||
p.recentHeaders.Add(key, header.Hash())
|
||||
}
|
||||
|
||||
if _, ok := snap.Validators[signer]; !ok {
|
||||
return errUnauthorizedValidator(signer.String())
|
||||
}
|
||||
@@ -2011,3 +2036,8 @@ func applyMessage(
|
||||
}
|
||||
return msg.Gas() - returnGas, err
|
||||
}
|
||||
|
||||
// proposalKey build a key which is a combination of the block number and the proposer address.
|
||||
func proposalKey(header types.Header) string {
|
||||
return header.ParentHash.String() + header.Coinbase.String()
|
||||
}
|
||||
|
||||
@@ -66,6 +66,31 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
|
||||
return validator
|
||||
}
|
||||
|
||||
// ValidateListsInBody validates that UncleHash, WithdrawalsHash, and WithdrawalsHash correspond to the lists in the block body, respectively.
|
||||
func ValidateListsInBody(block *types.Block) error {
|
||||
header := block.Header()
|
||||
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
||||
return fmt.Errorf("uncle root hash mismatch (header value %x, calculated %x)", header.UncleHash, hash)
|
||||
}
|
||||
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
||||
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
|
||||
}
|
||||
// Withdrawals are present after the Shanghai fork.
|
||||
if header.WithdrawalsHash != nil {
|
||||
// Withdrawals list must be present in body after Shanghai.
|
||||
if block.Withdrawals() == nil {
|
||||
return errors.New("missing withdrawals in block body")
|
||||
}
|
||||
if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
|
||||
return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash)
|
||||
}
|
||||
} else if block.Withdrawals() != nil { // Withdrawals turn into empty from nil when BlockBody has Sidecars
|
||||
// Withdrawals are not allowed prior to shanghai fork
|
||||
return errors.New("withdrawals present in block body")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateBody validates the given block's uncles and verifies the block
|
||||
// header's transaction and uncle roots. The headers are assumed to be already
|
||||
// validated at this point.
|
||||
@@ -83,31 +108,12 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||
if err := v.engine.VerifyUncles(v.bc, block); err != nil {
|
||||
return err
|
||||
}
|
||||
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
||||
return fmt.Errorf("uncle root hash mismatch (header value %x, calculated %x)", header.UncleHash, hash)
|
||||
}
|
||||
|
||||
validateFuns := []func() error{
|
||||
func() error {
|
||||
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
||||
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
|
||||
}
|
||||
return nil
|
||||
return ValidateListsInBody(block)
|
||||
},
|
||||
func() error {
|
||||
// Withdrawals are present after the Shanghai fork.
|
||||
if header.WithdrawalsHash != nil {
|
||||
// Withdrawals list must be present in body after Shanghai.
|
||||
if block.Withdrawals() == nil {
|
||||
return errors.New("missing withdrawals in block body")
|
||||
}
|
||||
if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
|
||||
return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash)
|
||||
}
|
||||
} else if block.Withdrawals() != nil { // Withdrawals turn into empty from nil when BlockBody has Sidecars
|
||||
// Withdrawals are not allowed prior to shanghai fork
|
||||
return errors.New("withdrawals present in block body")
|
||||
}
|
||||
// Blob transactions may be present after the Cancun fork.
|
||||
var blobs int
|
||||
for i, tx := range block.Transactions() {
|
||||
|
||||
@@ -71,6 +71,8 @@ var (
|
||||
justifiedBlockGauge = metrics.NewRegisteredGauge("chain/head/justified", nil)
|
||||
finalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
|
||||
|
||||
blockInsertMgaspsGauge = metrics.NewRegisteredGauge("chain/insert/mgasps", nil)
|
||||
|
||||
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
|
||||
|
||||
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
|
||||
@@ -165,6 +167,8 @@ type CacheConfig struct {
|
||||
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.
|
||||
JournalFilePath string
|
||||
JournalFile bool
|
||||
|
||||
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
|
||||
@@ -184,10 +188,12 @@ func (c *CacheConfig) triedbConfig() *triedb.Config {
|
||||
}
|
||||
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,
|
||||
SyncFlush: c.PathSyncFlush,
|
||||
StateHistory: c.StateHistory,
|
||||
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
|
||||
JournalFilePath: c.JournalFilePath,
|
||||
JournalFile: c.JournalFile,
|
||||
}
|
||||
}
|
||||
return config
|
||||
@@ -272,6 +278,7 @@ type BlockChain struct {
|
||||
highestVerifiedHeader atomic.Pointer[types.Header]
|
||||
currentBlock atomic.Pointer[types.Header] // Current head of the chain
|
||||
currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
|
||||
currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block
|
||||
chasingHead atomic.Pointer[types.Header]
|
||||
|
||||
bodyCache *lru.Cache[common.Hash, *types.Body]
|
||||
@@ -294,6 +301,7 @@ type BlockChain struct {
|
||||
diffLayerFreezerBlockLimit uint64
|
||||
|
||||
wg sync.WaitGroup
|
||||
dbWg sync.WaitGroup
|
||||
quit chan struct{} // shutdown signal, closed in Stop.
|
||||
stopping atomic.Bool // false if chain is running, true when stopped
|
||||
procInterrupt atomic.Bool // interrupt signaler for block processing
|
||||
@@ -328,6 +336,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||
diffLayerChanCache, _ := exlru.New(diffLayerCacheLimit)
|
||||
|
||||
// Open trie database with provided config
|
||||
// TODO:: if versa , have its owen init genesis logic
|
||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig())
|
||||
|
||||
// Setup the genesis block, commit the provided genesis specification
|
||||
@@ -376,6 +385,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||
}
|
||||
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
||||
bc.forker = NewForkChoice(bc, shouldPreserve)
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
||||
bc.validator = NewBlockValidator(chainConfig, bc, engine)
|
||||
bc.prefetcher = NewStatePrefetcher(chainConfig, bc, engine)
|
||||
@@ -412,7 +422,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||
// Make sure the state associated with the block is available, or log out
|
||||
// if there is no available state, waiting for state sync.
|
||||
head := bc.CurrentBlock()
|
||||
if !bc.NoTries() && !bc.HasState(head.Root) {
|
||||
if !bc.HasState(head.Root) {
|
||||
if head.Number.Uint64() == 0 {
|
||||
// The genesis state is missing, which is only possible in the path-based
|
||||
// scheme. This situation occurs when the initial state sync is not finished
|
||||
@@ -428,7 +438,7 @@ 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 {
|
||||
if bc.triedb.Scheme() == rawdb.PathScheme && !bc.NoTries() {
|
||||
recoverable, _ := bc.triedb.Recoverable(diskRoot)
|
||||
if !bc.HasState(diskRoot) && !recoverable {
|
||||
diskRoot = bc.triedb.Head()
|
||||
@@ -454,8 +464,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||
}
|
||||
}
|
||||
// Ensure that a previous crash in SetHead doesn't leave extra ancients
|
||||
if frozen, err := bc.db.ItemAmountInAncient(); err == nil && frozen > 0 {
|
||||
frozen, err = bc.db.Ancients()
|
||||
if frozen, err := bc.db.BlockStore().ItemAmountInAncient(); err == nil && frozen > 0 {
|
||||
frozen, err = bc.db.BlockStore().Ancients()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -649,13 +659,6 @@ func (bc *BlockChain) cacheDiffLayer(diffLayer *types.DiffLayer, diffLayerCh cha
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *BlockChain) cacheBlock(hash common.Hash, block *types.Block) {
|
||||
bc.blockCache.Add(hash, block)
|
||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||
bc.sidecarsCache.Add(hash, block.Sidecars())
|
||||
}
|
||||
}
|
||||
|
||||
// empty returns an indicator whether the blockchain is empty.
|
||||
// Note, it's a special case that we connect a non-empty ancient
|
||||
// database with an empty node, so that we can plugin the ancient
|
||||
@@ -991,12 +994,23 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash) (*typ
|
||||
// then block number zero is returned, indicating that snapshot recovery is disabled
|
||||
// and the whole snapshot should be auto-generated in case of head mismatch.
|
||||
func (bc *BlockChain) rewindHead(head *types.Header, root common.Hash) (*types.Header, uint64) {
|
||||
if bc.triedb.Scheme() == rawdb.PathScheme {
|
||||
if bc.triedb.Scheme() == rawdb.PathScheme && !bc.NoTries() {
|
||||
return bc.rewindPathHead(head, root)
|
||||
}
|
||||
return bc.rewindHashHead(head, root)
|
||||
}
|
||||
|
||||
// SetFinalized sets the finalized block.
|
||||
// This function differs slightly from Ethereum; we fine-tune it through the outer-layer setting finalizedBlockGauge.
|
||||
func (bc *BlockChain) SetFinalized(header *types.Header) {
|
||||
bc.currentFinalBlock.Store(header)
|
||||
if header != nil {
|
||||
rawdb.WriteFinalizedBlockHash(bc.db.BlockStore(), header.Hash())
|
||||
} else {
|
||||
rawdb.WriteFinalizedBlockHash(bc.db.BlockStore(), common.Hash{})
|
||||
}
|
||||
}
|
||||
|
||||
// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
|
||||
// that the rewind must pass the specified state root. This method is meant to be
|
||||
// used when rewinding with snapshots enabled to ensure that we go back further than
|
||||
@@ -1028,6 +1042,19 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||
// 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() {
|
||||
// load bc.snaps for the judge `HasState`
|
||||
if bc.NoTries() {
|
||||
if bc.cacheConfig.SnapshotLimit > 0 {
|
||||
snapconfig := snapshot.Config{
|
||||
CacheSize: bc.cacheConfig.SnapshotLimit,
|
||||
NoBuild: bc.cacheConfig.SnapshotNoBuild,
|
||||
AsyncBuild: !bc.cacheConfig.SnapshotWait,
|
||||
}
|
||||
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, header.Root, int(bc.cacheConfig.TriesInMemory), bc.NoTries())
|
||||
}
|
||||
defer func() { bc.snaps = nil }()
|
||||
}
|
||||
|
||||
var newHeadBlock *types.Header
|
||||
newHeadBlock, rootNumber = bc.rewindHead(header, root)
|
||||
rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash())
|
||||
@@ -1075,7 +1102,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||
// intent afterwards is full block importing, delete the chain segment
|
||||
// between the stateful-block and the sethead target.
|
||||
var wipe bool
|
||||
frozen, _ := bc.db.Ancients()
|
||||
frozen, _ := bc.db.BlockStore().Ancients()
|
||||
if headNumber+1 < frozen {
|
||||
wipe = pivot == nil || headNumber >= *pivot
|
||||
}
|
||||
@@ -1084,11 +1111,11 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||
// Rewind the header chain, deleting all block bodies until then
|
||||
delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) {
|
||||
// Ignore the error here since light client won't hit this path
|
||||
frozen, _ := bc.db.Ancients()
|
||||
frozen, _ := bc.db.BlockStore().Ancients()
|
||||
if num+1 <= frozen {
|
||||
// Truncate all relative data(header, total difficulty, body, receipt
|
||||
// and canonical hash) from ancient store.
|
||||
if _, err := bc.db.TruncateHead(num); err != nil {
|
||||
if _, err := bc.db.BlockStore().TruncateHead(num); err != nil {
|
||||
log.Crit("Failed to truncate ancient data", "number", num, "err", err)
|
||||
}
|
||||
// Remove the hash <-> number mapping from the active store.
|
||||
@@ -1106,7 +1133,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||
// If SetHead was only called as a chain reparation method, try to skip
|
||||
// touching the header chain altogether, unless the freezer is broken
|
||||
if repair {
|
||||
if target, force := updateFn(bc.db, bc.CurrentBlock()); force {
|
||||
if target, force := updateFn(bc.db.BlockStore(), bc.CurrentBlock()); force {
|
||||
bc.hc.SetHead(target.Number.Uint64(), updateFn, delFn)
|
||||
}
|
||||
} else {
|
||||
@@ -1129,6 +1156,11 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||
bc.txLookupCache.Purge()
|
||||
bc.futureBlocks.Purge()
|
||||
|
||||
if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() {
|
||||
log.Error("SetHead invalidated finalized block")
|
||||
bc.SetFinalized(nil)
|
||||
}
|
||||
|
||||
return rootNumber, bc.loadLastState()
|
||||
}
|
||||
|
||||
@@ -1197,10 +1229,10 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
|
||||
defer bc.chainmu.Unlock()
|
||||
|
||||
// Prepare the genesis block and reinitialise the chain
|
||||
batch := bc.db.NewBatch()
|
||||
rawdb.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty())
|
||||
rawdb.WriteBlock(batch, genesis)
|
||||
if err := batch.Write(); err != nil {
|
||||
blockBatch := bc.db.BlockStore().NewBatch()
|
||||
rawdb.WriteTd(blockBatch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty())
|
||||
rawdb.WriteBlock(blockBatch, genesis)
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to write genesis block", "err", err)
|
||||
}
|
||||
bc.writeHeadBlock(genesis)
|
||||
@@ -1262,18 +1294,33 @@ func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
|
||||
//
|
||||
// Note, this function assumes that the `mu` mutex is held!
|
||||
func (bc *BlockChain) writeHeadBlock(block *types.Block) {
|
||||
// Add the block to the canonical chain number scheme and mark as the head
|
||||
batch := bc.db.NewBatch()
|
||||
rawdb.WriteHeadHeaderHash(batch, block.Hash())
|
||||
rawdb.WriteHeadFastBlockHash(batch, block.Hash())
|
||||
rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
|
||||
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
||||
rawdb.WriteHeadBlockHash(batch, block.Hash())
|
||||
bc.dbWg.Add(2)
|
||||
defer bc.dbWg.Wait()
|
||||
go func() {
|
||||
defer bc.dbWg.Done()
|
||||
// Add the block to the canonical chain number scheme and mark as the head
|
||||
blockBatch := bc.db.BlockStore().NewBatch()
|
||||
rawdb.WriteCanonicalHash(blockBatch, block.Hash(), block.NumberU64())
|
||||
rawdb.WriteHeadHeaderHash(blockBatch, block.Hash())
|
||||
rawdb.WriteHeadBlockHash(blockBatch, block.Hash())
|
||||
rawdb.WriteHeadFastBlockHash(blockBatch, block.Hash())
|
||||
// Flush the whole batch into the disk, exit the node if failed
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to update chain indexes and markers in block db", "err", err)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer bc.dbWg.Done()
|
||||
|
||||
batch := bc.db.NewBatch()
|
||||
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
||||
|
||||
// Flush the whole batch into the disk, exit the node if failed
|
||||
if err := batch.Write(); err != nil {
|
||||
log.Crit("Failed to update chain indexes in chain db", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Flush the whole batch into the disk, exit the node if failed
|
||||
if err := batch.Write(); err != nil {
|
||||
log.Crit("Failed to update chain indexes and markers", "err", err)
|
||||
}
|
||||
// Update all in-memory chain markers in the last step
|
||||
bc.hc.SetCurrentHeader(block.Header())
|
||||
|
||||
@@ -1354,7 +1401,7 @@ func (bc *BlockChain) Stop() {
|
||||
} else {
|
||||
rawdb.WriteSafePointBlockNumber(bc.db, recent.NumberU64())
|
||||
once.Do(func() {
|
||||
rawdb.WriteHeadBlockHash(bc.db, recent.Hash())
|
||||
rawdb.WriteHeadBlockHash(bc.db.BlockStore(), recent.Hash())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1494,7 +1541,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
} else if !reorg {
|
||||
return false
|
||||
}
|
||||
rawdb.WriteHeadFastBlockHash(bc.db, head.Hash())
|
||||
rawdb.WriteHeadFastBlockHash(bc.db.BlockStore(), head.Hash())
|
||||
bc.currentSnapBlock.Store(head.Header())
|
||||
headFastBlockGauge.Update(int64(head.NumberU64()))
|
||||
return true
|
||||
@@ -1511,9 +1558,9 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
|
||||
// Ensure genesis is in ancients.
|
||||
if first.NumberU64() == 1 {
|
||||
if frozen, _ := bc.db.Ancients(); frozen == 0 {
|
||||
if frozen, _ := bc.db.BlockStore().Ancients(); frozen == 0 {
|
||||
td := bc.genesisBlock.Difficulty()
|
||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td)
|
||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db.BlockStore(), []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td)
|
||||
if err != nil {
|
||||
log.Error("Error writing genesis to ancients", "err", err)
|
||||
return 0, err
|
||||
@@ -1531,7 +1578,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
|
||||
// Write all chain data to ancients.
|
||||
td := bc.GetTd(first.Hash(), first.NumberU64())
|
||||
writeSize, err := rawdb.WriteAncientBlocksWithBlobs(bc.db, blockChain, receiptChain, td)
|
||||
writeSize, err := rawdb.WriteAncientBlocksWithBlobs(bc.db.BlockStore(), blockChain, receiptChain, td)
|
||||
if err != nil {
|
||||
log.Error("Error importing chain data to ancients", "err", err)
|
||||
return 0, err
|
||||
@@ -1539,7 +1586,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
size += writeSize
|
||||
|
||||
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
|
||||
if err := bc.db.Sync(); err != nil {
|
||||
if err := bc.db.BlockStore().Sync(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Update the current snap block because all block data is now present in DB.
|
||||
@@ -1547,7 +1594,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
if !updateHead(blockChain[len(blockChain)-1]) {
|
||||
// We end up here if the header chain has reorg'ed, and the blocks/receipts
|
||||
// don't match the canonical chain.
|
||||
if _, err := bc.db.TruncateHead(previousSnapBlock + 1); err != nil {
|
||||
if _, err := bc.db.BlockStore().TruncateHead(previousSnapBlock + 1); err != nil {
|
||||
log.Error("Can't truncate ancient store after failed insert", "err", err)
|
||||
}
|
||||
return 0, errSideChainReceipts
|
||||
@@ -1555,24 +1602,24 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
|
||||
// Delete block data from the main database.
|
||||
var (
|
||||
batch = bc.db.NewBatch()
|
||||
canonHashes = make(map[common.Hash]struct{})
|
||||
blockBatch = bc.db.BlockStore().NewBatch()
|
||||
)
|
||||
for _, block := range blockChain {
|
||||
canonHashes[block.Hash()] = struct{}{}
|
||||
if block.NumberU64() == 0 {
|
||||
continue
|
||||
}
|
||||
rawdb.DeleteCanonicalHash(batch, block.NumberU64())
|
||||
rawdb.DeleteBlockWithoutNumber(batch, block.Hash(), block.NumberU64())
|
||||
rawdb.DeleteCanonicalHash(blockBatch, block.NumberU64())
|
||||
rawdb.DeleteBlockWithoutNumber(blockBatch, block.Hash(), block.NumberU64())
|
||||
}
|
||||
// Delete side chain hash-to-number mappings.
|
||||
for _, nh := range rawdb.ReadAllHashesInRange(bc.db, first.NumberU64(), last.NumberU64()) {
|
||||
for _, nh := range rawdb.ReadAllHashesInRange(bc.db.BlockStore(), first.NumberU64(), last.NumberU64()) {
|
||||
if _, canon := canonHashes[nh.Hash]; !canon {
|
||||
rawdb.DeleteHeader(batch, nh.Hash, nh.Number)
|
||||
rawdb.DeleteHeader(blockBatch, nh.Hash, nh.Number)
|
||||
}
|
||||
}
|
||||
if err := batch.Write(); err != nil {
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
stats.processed += int32(len(blockChain))
|
||||
@@ -1584,6 +1631,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
var (
|
||||
skipPresenceCheck = false
|
||||
batch = bc.db.NewBatch()
|
||||
blockBatch = bc.db.BlockStore().NewBatch()
|
||||
)
|
||||
for i, block := range blockChain {
|
||||
// Short circuit insertion if shutting down or processing failed
|
||||
@@ -1607,10 +1655,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
}
|
||||
}
|
||||
// Write all the data out into the database
|
||||
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
|
||||
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
|
||||
rawdb.WriteBody(blockBatch, block.Hash(), block.NumberU64(), block.Body())
|
||||
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receiptChain[i])
|
||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||
rawdb.WriteBlobSidecars(batch, block.Hash(), block.NumberU64(), block.Sidecars())
|
||||
rawdb.WriteBlobSidecars(blockBatch, block.Hash(), block.NumberU64(), block.Sidecars())
|
||||
}
|
||||
|
||||
// Write everything belongs to the blocks into the database. So that
|
||||
@@ -1623,6 +1671,13 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
size += int64(batch.ValueSize())
|
||||
batch.Reset()
|
||||
}
|
||||
if blockBatch.ValueSize() >= ethdb.IdealBatchSize {
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += int64(blockBatch.ValueSize())
|
||||
blockBatch.Reset()
|
||||
}
|
||||
stats.processed++
|
||||
}
|
||||
// Write everything belongs to the blocks into the database. So that
|
||||
@@ -1634,6 +1689,12 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
if blockBatch.ValueSize() > 0 {
|
||||
size += int64(blockBatch.ValueSize())
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
updateHead(blockChain[len(blockChain)-1])
|
||||
return 0, nil
|
||||
}
|
||||
@@ -1678,14 +1739,14 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
|
||||
if bc.insertStopped() {
|
||||
return errInsertionInterrupted
|
||||
}
|
||||
batch := bc.db.NewBatch()
|
||||
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
|
||||
rawdb.WriteBlock(batch, block)
|
||||
blockBatch := bc.db.BlockStore().NewBatch()
|
||||
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), td)
|
||||
rawdb.WriteBlock(blockBatch, block)
|
||||
// if cancun is enabled, here need to write sidecars too
|
||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||
rawdb.WriteBlobSidecars(batch, block.Hash(), block.NumberU64(), block.Sidecars())
|
||||
rawdb.WriteBlobSidecars(blockBatch, block.Hash(), block.NumberU64(), block.Sidecars())
|
||||
}
|
||||
if err := batch.Write(); err != nil {
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to write block into disk", "err", err)
|
||||
}
|
||||
return nil
|
||||
@@ -1723,7 +1784,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
blockBatch := bc.db.NewBatch()
|
||||
blockBatch := bc.db.BlockStore().NewBatch()
|
||||
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
|
||||
rawdb.WriteBlock(blockBatch, block)
|
||||
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
|
||||
@@ -1731,10 +1792,20 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||
rawdb.WriteBlobSidecars(blockBatch, block.Hash(), block.NumberU64(), block.Sidecars())
|
||||
}
|
||||
rawdb.WritePreimages(blockBatch, state.Preimages())
|
||||
if bc.db.StateStore() != nil {
|
||||
rawdb.WritePreimages(bc.db.StateStore(), state.Preimages())
|
||||
} else {
|
||||
rawdb.WritePreimages(blockBatch, state.Preimages())
|
||||
}
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to write block into disk", "err", err)
|
||||
}
|
||||
bc.hc.tdCache.Add(block.Hash(), externTd)
|
||||
bc.blockCache.Add(block.Hash(), block)
|
||||
bc.receiptsCache.Add(block.Hash(), receipts)
|
||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||
bc.sidecarsCache.Add(block.Hash(), block.Sidecars())
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
@@ -1892,12 +1963,16 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
||||
// we will fire an accumulated ChainHeadEvent and disable fire
|
||||
// event here.
|
||||
var finalizedHeader *types.Header
|
||||
if posa, ok := bc.Engine().(consensus.PoSA); ok {
|
||||
if finalizedHeader = posa.GetFinalizedHeader(bc, block.Header()); finalizedHeader != nil {
|
||||
bc.SetFinalized(finalizedHeader)
|
||||
}
|
||||
}
|
||||
if emitHeadEvent {
|
||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||
if posa, ok := bc.Engine().(consensus.PoSA); ok {
|
||||
if finalizedHeader := posa.GetFinalizedHeader(bc, block.Header()); finalizedHeader != nil {
|
||||
bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
|
||||
}
|
||||
if finalizedHeader != nil {
|
||||
bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -2136,7 +2211,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||
// state, but if it's this special case here(skip reexecution) we will lose
|
||||
// the empty receipt entry.
|
||||
if len(block.Transactions()) == 0 {
|
||||
rawdb.WriteReceipts(bc.db, block.Hash(), block.NumberU64(), nil)
|
||||
rawdb.WriteReceipts(bc.db.BlockStore(), block.Hash(), block.NumberU64(), nil)
|
||||
} else {
|
||||
log.Error("Please file an issue, skip known block execution without receipt",
|
||||
"hash", block.Hash(), "number", block.NumberU64())
|
||||
@@ -2159,6 +2234,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
||||
}
|
||||
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
statedb, err := state.NewWithSharedPool(parent.Root, bc.stateCache, bc.snaps)
|
||||
if err != nil {
|
||||
return it.index, err
|
||||
@@ -2208,8 +2284,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||
vtime := time.Since(vstart)
|
||||
proctime := time.Since(start) // processing + validation
|
||||
|
||||
bc.cacheBlock(block.Hash(), block)
|
||||
|
||||
// Update the metrics touched during block processing and validation
|
||||
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
||||
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
|
||||
@@ -2322,26 +2396,11 @@ func (bc *BlockChain) updateHighestVerifiedHeader(header *types.Header) {
|
||||
if header == nil || header.Number == nil {
|
||||
return
|
||||
}
|
||||
currentHeader := bc.highestVerifiedHeader.Load()
|
||||
if currentHeader == nil {
|
||||
currentBlock := bc.CurrentBlock()
|
||||
reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, header)
|
||||
if err == nil && reorg {
|
||||
bc.highestVerifiedHeader.Store(types.CopyHeader(header))
|
||||
return
|
||||
}
|
||||
|
||||
newParentTD := bc.GetTd(header.ParentHash, header.Number.Uint64()-1)
|
||||
if newParentTD == nil {
|
||||
newParentTD = big.NewInt(0)
|
||||
}
|
||||
oldParentTD := bc.GetTd(currentHeader.ParentHash, currentHeader.Number.Uint64()-1)
|
||||
if oldParentTD == nil {
|
||||
oldParentTD = big.NewInt(0)
|
||||
}
|
||||
newTD := big.NewInt(0).Add(newParentTD, header.Difficulty)
|
||||
oldTD := big.NewInt(0).Add(oldParentTD, currentHeader.Difficulty)
|
||||
|
||||
if newTD.Cmp(oldTD) > 0 {
|
||||
bc.highestVerifiedHeader.Store(types.CopyHeader(header))
|
||||
return
|
||||
log.Trace("updateHighestVerifiedHeader", "number", header.Number.Uint64(), "hash", header.Hash())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2681,6 +2740,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||
var (
|
||||
indexesBatch = bc.db.NewBatch()
|
||||
diffs = types.HashDifference(deletedTxs, addedTxs)
|
||||
blockBatch = bc.db.BlockStore().NewBatch()
|
||||
)
|
||||
for _, tx := range diffs {
|
||||
rawdb.DeleteTxLookupEntry(indexesBatch, tx)
|
||||
@@ -2697,11 +2757,14 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||
if hash == (common.Hash{}) {
|
||||
break
|
||||
}
|
||||
rawdb.DeleteCanonicalHash(indexesBatch, i)
|
||||
rawdb.DeleteCanonicalHash(blockBatch, i)
|
||||
}
|
||||
if err := indexesBatch.Write(); err != nil {
|
||||
log.Crit("Failed to delete useless indexes", "err", err)
|
||||
}
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to delete useless indexes use block batch", "err", err)
|
||||
}
|
||||
|
||||
// Send out events for logs from the old canon chain, and 'reborn'
|
||||
// logs from the new canon chain. The number of logs can be very
|
||||
|
||||
@@ -48,18 +48,23 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn
|
||||
// If we're at the last block of the batch or report period reached, log
|
||||
if index == len(chain)-1 || elapsed >= statsReportLimit {
|
||||
// Count the number of transactions in this segment
|
||||
var txs int
|
||||
var txs, blobs int
|
||||
for _, block := range chain[st.lastIndex : index+1] {
|
||||
txs += len(block.Transactions())
|
||||
for _, sidecar := range block.Sidecars() {
|
||||
blobs += len(sidecar.Blobs)
|
||||
}
|
||||
}
|
||||
end := chain[index]
|
||||
|
||||
// Assemble the log context and send it to the logger
|
||||
mgasps := float64(st.usedGas) * 1000 / float64(elapsed)
|
||||
context := []interface{}{
|
||||
"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),
|
||||
"blocks", st.processed, "txs", txs, "blobs", blobs, "mgas", float64(st.usedGas) / 1000000,
|
||||
"elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps,
|
||||
}
|
||||
blockInsertMgaspsGauge.Update(int64(mgasps))
|
||||
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
|
||||
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
||||
}
|
||||
|
||||
@@ -396,6 +396,7 @@ func (bc *BlockChain) State() (*state.StateDB, error) {
|
||||
|
||||
// StateAt returns a new mutable state based on a particular point in time.
|
||||
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
stateDb, err := state.New(root, bc.stateCache, bc.snaps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -511,3 +512,12 @@ func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscr
|
||||
func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEvent) event.Subscription {
|
||||
return bc.scope.Track(bc.finalizedHeaderFeed.Subscribe(ch))
|
||||
}
|
||||
|
||||
// AncientTail retrieves the tail the ancients blocks
|
||||
func (bc *BlockChain) AncientTail() (uint64, error) {
|
||||
tail, err := bc.db.BlockStore().Tail()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return tail, nil
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
@@ -1795,6 +1797,13 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||
config.SnapshotWait = true
|
||||
}
|
||||
config.TriesInMemory = 128
|
||||
|
||||
if err = db.SetupFreezerEnv(ðdb.FreezerEnv{
|
||||
ChainCfg: gspec.Config,
|
||||
BlobExtraReserve: params.DefaultExtraReserveForBlobRequests,
|
||||
}); err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
}
|
||||
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
|
||||
@@ -27,6 +27,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
@@ -1998,6 +2000,13 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
||||
config.SnapshotWait = true
|
||||
}
|
||||
config.TriesInMemory = 128
|
||||
|
||||
if err = db.SetupFreezerEnv(ðdb.FreezerEnv{
|
||||
ChainCfg: gspec.Config,
|
||||
BlobExtraReserve: params.DefaultExtraReserveForBlobRequests,
|
||||
}); err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
}
|
||||
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
|
||||
@@ -974,7 +974,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||
t.Fatalf("failed to insert receipt %d: %v", n, err)
|
||||
}
|
||||
// Freezer style fast import the chain.
|
||||
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||
}
|
||||
@@ -1069,7 +1069,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||
|
||||
// makeDb creates a db instance for testing.
|
||||
makeDb := func() ethdb.Database {
|
||||
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||
}
|
||||
@@ -1957,7 +1957,7 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) {
|
||||
competitor, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
|
||||
|
||||
// Import the shared chain and the original canonical one
|
||||
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
defer db.Close()
|
||||
|
||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
||||
@@ -2026,7 +2026,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
|
||||
_, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(height), nil)
|
||||
|
||||
// Import the chain as a ancient-first node and ensure all pointers are updated
|
||||
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||
}
|
||||
@@ -2097,7 +2097,7 @@ func testInsertReceiptChainRollback(t *testing.T, scheme string) {
|
||||
}
|
||||
|
||||
// Set up a BlockChain that uses the ancient store.
|
||||
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||
}
|
||||
@@ -2167,7 +2167,7 @@ func testLowDiffLongChain(t *testing.T, scheme string) {
|
||||
})
|
||||
|
||||
// Import the canonical chain
|
||||
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
defer diskdb.Close()
|
||||
|
||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
||||
@@ -2384,7 +2384,7 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) {
|
||||
b.OffsetTime(-9) // A higher difficulty
|
||||
})
|
||||
// Import the shared chain and the original canonical one
|
||||
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||
}
|
||||
@@ -2555,7 +2555,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
||||
}
|
||||
})
|
||||
// Import the shared chain and the original canonical one
|
||||
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||
}
|
||||
@@ -3858,7 +3858,7 @@ func testSetCanonical(t *testing.T, scheme string) {
|
||||
}
|
||||
gen.AddTx(tx)
|
||||
})
|
||||
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
||||
defer diskdb.Close()
|
||||
|
||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
||||
@@ -4483,7 +4483,7 @@ func (c *mockParlia) CalcDifficulty(chain consensus.ChainHeaderReader, time uint
|
||||
func TestParliaBlobFeeReward(t *testing.T) {
|
||||
// Have N headers in the freezer
|
||||
frdir := t.TempDir()
|
||||
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false, false)
|
||||
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create database with ancient backend")
|
||||
}
|
||||
|
||||
@@ -397,10 +397,12 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||
}
|
||||
|
||||
// Forcibly use hash-based state scheme for retaining all nodes in disk.
|
||||
// TODO:: ignore, only use to UT
|
||||
triedb := triedb.NewDatabase(db, triedb.HashDefaults)
|
||||
defer triedb.Close()
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// @TODO:: ignore, it used to UT, state.NewDatabase internally compatible with versa is sufficient.
|
||||
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -5,6 +5,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/gopool"
|
||||
@@ -14,6 +17,10 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
var (
|
||||
daCheckTimer = metrics.NewRegisteredTimer("chain/dacheck", nil)
|
||||
)
|
||||
|
||||
// validateBlobSidecar it is same as validateBlobSidecar in core/txpool/validation.go
|
||||
func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobSidecar) error {
|
||||
if len(sidecar.Blobs) != len(hashes) {
|
||||
@@ -46,6 +53,10 @@ func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobSidecar) error
|
||||
|
||||
// IsDataAvailable it checks that the blobTx block has available blob data
|
||||
func IsDataAvailable(chain consensus.ChainHeaderReader, block *types.Block) (err error) {
|
||||
defer func(start time.Time) {
|
||||
daCheckTimer.Update(time.Since(start))
|
||||
}(time.Now())
|
||||
|
||||
// refer logic in ValidateBody
|
||||
if !chain.Config().IsCancun(block.Number(), block.Time()) {
|
||||
if block.Sidecars() != nil {
|
||||
|
||||
@@ -86,9 +86,16 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b
|
||||
localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64())
|
||||
externTd = f.chain.GetTd(extern.Hash(), extern.Number.Uint64())
|
||||
)
|
||||
if localTD == nil || externTd == nil {
|
||||
if localTD == nil {
|
||||
return false, errors.New("missing td")
|
||||
}
|
||||
if externTd == nil {
|
||||
ptd := f.chain.GetTd(extern.ParentHash, extern.Number.Uint64()-1)
|
||||
if ptd == nil {
|
||||
return false, consensus.ErrUnknownAncestor
|
||||
}
|
||||
externTd = new(big.Int).Add(ptd, extern.Difficulty)
|
||||
}
|
||||
// Accept the new header as the chain head if the transition
|
||||
// is already triggered. We assume all the headers after the
|
||||
// transition come from the trusted consensus layer.
|
||||
@@ -114,7 +121,9 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b
|
||||
if f.preserve != nil {
|
||||
currentPreserve, externPreserve = f.preserve(current), f.preserve(extern)
|
||||
}
|
||||
reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5)
|
||||
reorg = !currentPreserve && (externPreserve ||
|
||||
extern.Time < current.Time ||
|
||||
extern.Time == current.Time && f.rand.Float64() < 0.5)
|
||||
}
|
||||
return reorg, nil
|
||||
}
|
||||
|
||||
@@ -126,7 +126,9 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
|
||||
}
|
||||
// Create an ephemeral in-memory database for computing hash,
|
||||
// all the derived states will be discarded to not pollute disk.
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
statedb, err := state.New(types.EmptyRootHash, db, nil)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
@@ -154,6 +156,7 @@ func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Databa
|
||||
if triedbConfig != nil {
|
||||
triedbConfig.NoTries = false
|
||||
}
|
||||
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -216,10 +219,8 @@ func (e *GenesisMismatchError) Error() string {
|
||||
// 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
|
||||
OverrideFeynman *uint64
|
||||
OverrideFeynmanFix *uint64
|
||||
OverrideBohr *uint64
|
||||
OverrideVerkle *uint64
|
||||
}
|
||||
|
||||
// SetupGenesisBlock writes or updates the genesis block in db.
|
||||
@@ -245,18 +246,12 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
|
||||
}
|
||||
applyOverrides := func(config *params.ChainConfig) {
|
||||
if config != nil {
|
||||
if overrides != nil && overrides.OverrideCancun != nil {
|
||||
config.CancunTime = overrides.OverrideCancun
|
||||
if overrides != nil && overrides.OverrideBohr != nil {
|
||||
config.BohrTime = overrides.OverrideBohr
|
||||
}
|
||||
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.
|
||||
@@ -493,13 +488,13 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
|
||||
if err := flushAlloc(&g.Alloc, db, triedb, block.Hash()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
|
||||
rawdb.WriteBlock(db, block)
|
||||
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
|
||||
rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
|
||||
rawdb.WriteHeadBlockHash(db, block.Hash())
|
||||
rawdb.WriteHeadFastBlockHash(db, block.Hash())
|
||||
rawdb.WriteHeadHeaderHash(db, block.Hash())
|
||||
rawdb.WriteTd(db.BlockStore(), block.Hash(), block.NumberU64(), block.Difficulty())
|
||||
rawdb.WriteBlock(db.BlockStore(), block)
|
||||
rawdb.WriteReceipts(db.BlockStore(), block.Hash(), block.NumberU64(), nil)
|
||||
rawdb.WriteCanonicalHash(db.BlockStore(), block.Hash(), block.NumberU64())
|
||||
rawdb.WriteHeadBlockHash(db.BlockStore(), block.Hash())
|
||||
rawdb.WriteHeadFastBlockHash(db.BlockStore(), block.Hash())
|
||||
rawdb.WriteHeadHeaderHash(db.BlockStore(), block.Hash())
|
||||
rawdb.WriteChainConfig(db, block.Hash(), config)
|
||||
return block, nil
|
||||
}
|
||||
|
||||
@@ -172,9 +172,9 @@ func (hc *HeaderChain) Reorg(headers []*types.Header) error {
|
||||
// pile them onto the existing chain. Otherwise, do the necessary
|
||||
// reorgs.
|
||||
var (
|
||||
first = headers[0]
|
||||
last = headers[len(headers)-1]
|
||||
batch = hc.chainDb.NewBatch()
|
||||
first = headers[0]
|
||||
last = headers[len(headers)-1]
|
||||
blockBatch = hc.chainDb.BlockStore().NewBatch()
|
||||
)
|
||||
if first.ParentHash != hc.currentHeaderHash {
|
||||
// Delete any canonical number assignments above the new head
|
||||
@@ -183,7 +183,7 @@ func (hc *HeaderChain) Reorg(headers []*types.Header) error {
|
||||
if hash == (common.Hash{}) {
|
||||
break
|
||||
}
|
||||
rawdb.DeleteCanonicalHash(batch, i)
|
||||
rawdb.DeleteCanonicalHash(blockBatch, i)
|
||||
}
|
||||
// Overwrite any stale canonical number assignments, going
|
||||
// backwards from the first header in this import until the
|
||||
@@ -194,7 +194,7 @@ func (hc *HeaderChain) Reorg(headers []*types.Header) error {
|
||||
headHash = header.Hash()
|
||||
)
|
||||
for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash {
|
||||
rawdb.WriteCanonicalHash(batch, headHash, headNumber)
|
||||
rawdb.WriteCanonicalHash(blockBatch, headHash, headNumber)
|
||||
if headNumber == 0 {
|
||||
break // It shouldn't be reached
|
||||
}
|
||||
@@ -209,16 +209,16 @@ func (hc *HeaderChain) Reorg(headers []*types.Header) error {
|
||||
for i := 0; i < len(headers)-1; i++ {
|
||||
hash := headers[i+1].ParentHash // Save some extra hashing
|
||||
num := headers[i].Number.Uint64()
|
||||
rawdb.WriteCanonicalHash(batch, hash, num)
|
||||
rawdb.WriteHeadHeaderHash(batch, hash)
|
||||
rawdb.WriteCanonicalHash(blockBatch, hash, num)
|
||||
rawdb.WriteHeadHeaderHash(blockBatch, hash)
|
||||
}
|
||||
// Write the last header
|
||||
hash := headers[len(headers)-1].Hash()
|
||||
num := headers[len(headers)-1].Number.Uint64()
|
||||
rawdb.WriteCanonicalHash(batch, hash, num)
|
||||
rawdb.WriteHeadHeaderHash(batch, hash)
|
||||
rawdb.WriteCanonicalHash(blockBatch, hash, num)
|
||||
rawdb.WriteHeadHeaderHash(blockBatch, hash)
|
||||
|
||||
if err := batch.Write(); err != nil {
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Last step update all in-memory head header markers
|
||||
@@ -244,7 +244,7 @@ func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) {
|
||||
newTD = new(big.Int).Set(ptd) // Total difficulty of inserted chain
|
||||
inserted []rawdb.NumberHash // Ephemeral lookup of number/hash for the chain
|
||||
parentKnown = true // Set to true to force hc.HasHeader check the first iteration
|
||||
batch = hc.chainDb.NewBatch()
|
||||
blockBatch = hc.chainDb.BlockStore().NewBatch()
|
||||
)
|
||||
for i, header := range headers {
|
||||
var hash common.Hash
|
||||
@@ -264,10 +264,10 @@ func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) {
|
||||
alreadyKnown := parentKnown && hc.HasHeader(hash, number)
|
||||
if !alreadyKnown {
|
||||
// Irrelevant of the canonical status, write the TD and header to the database.
|
||||
rawdb.WriteTd(batch, hash, number, newTD)
|
||||
rawdb.WriteTd(blockBatch, hash, number, newTD)
|
||||
hc.tdCache.Add(hash, new(big.Int).Set(newTD))
|
||||
|
||||
rawdb.WriteHeader(batch, header)
|
||||
rawdb.WriteHeader(blockBatch, header)
|
||||
inserted = append(inserted, rawdb.NumberHash{Number: number, Hash: hash})
|
||||
hc.headerCache.Add(hash, header)
|
||||
hc.numberCache.Add(hash, number)
|
||||
@@ -280,7 +280,7 @@ func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) {
|
||||
return 0, errors.New("aborted")
|
||||
}
|
||||
// Commit to disk!
|
||||
if err := batch.Write(); err != nil {
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to write headers", "error", err)
|
||||
}
|
||||
return len(inserted), nil
|
||||
@@ -642,7 +642,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
||||
}
|
||||
var (
|
||||
parentHash common.Hash
|
||||
batch = hc.chainDb.NewBatch()
|
||||
blockBatch = hc.chainDb.BlockStore().NewBatch()
|
||||
origin = true
|
||||
)
|
||||
done := func(header *types.Header) bool {
|
||||
@@ -668,7 +668,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
||||
// first then remove the relative data from the database.
|
||||
//
|
||||
// Update head first(head fast block, head full block) before deleting the data.
|
||||
markerBatch := hc.chainDb.NewBatch()
|
||||
markerBatch := hc.chainDb.BlockStore().NewBatch()
|
||||
if updateFn != nil {
|
||||
newHead, force := updateFn(markerBatch, parent)
|
||||
if force && ((headTime > 0 && newHead.Time < headTime) || (headTime == 0 && newHead.Number.Uint64() < headBlock)) {
|
||||
@@ -691,7 +691,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
||||
// we don't end up with dangling daps in the database
|
||||
var nums []uint64
|
||||
if origin {
|
||||
for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb, n)) > 0; n++ {
|
||||
for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb.BlockStore(), n)) > 0; n++ {
|
||||
nums = append([]uint64{n}, nums...) // suboptimal, but we don't really expect this path
|
||||
}
|
||||
origin = false
|
||||
@@ -701,23 +701,23 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
||||
// Remove the related data from the database on all sidechains
|
||||
for _, num := range nums {
|
||||
// Gather all the side fork hashes
|
||||
hashes := rawdb.ReadAllHashes(hc.chainDb, num)
|
||||
hashes := rawdb.ReadAllHashes(hc.chainDb.BlockStore(), num)
|
||||
if len(hashes) == 0 {
|
||||
// No hashes in the database whatsoever, probably frozen already
|
||||
hashes = append(hashes, hdr.Hash())
|
||||
}
|
||||
for _, hash := range hashes {
|
||||
if delFn != nil {
|
||||
delFn(batch, hash, num)
|
||||
delFn(blockBatch, hash, num)
|
||||
}
|
||||
rawdb.DeleteHeader(batch, hash, num)
|
||||
rawdb.DeleteTd(batch, hash, num)
|
||||
rawdb.DeleteHeader(blockBatch, hash, num)
|
||||
rawdb.DeleteTd(blockBatch, hash, num)
|
||||
}
|
||||
rawdb.DeleteCanonicalHash(batch, num)
|
||||
rawdb.DeleteCanonicalHash(blockBatch, num)
|
||||
}
|
||||
}
|
||||
// Flush all accumulated deletions.
|
||||
if err := batch.Write(); err != nil {
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to rewind block", "error", err)
|
||||
}
|
||||
// Clear out any stale content from the caches
|
||||
|
||||
@@ -34,14 +34,23 @@ import (
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// Support Multi-Database Based on Data Pattern, the Chaindata will be divided into three stores: BlockStore, StateStore, and ChainStore,
|
||||
// according to data schema and read/write behavior. When using the following data interfaces, you should take note of the following:
|
||||
//
|
||||
// 1) Block-Related Data: For CanonicalHash, Header, Body, Td, Receipts, and BlobSidecars, the Write, Delete, and Iterator
|
||||
// operations should carefully ensure that the database being used is BlockStore.
|
||||
// 2) Meta-Related Data: For HeaderNumber, HeadHeaderHash, HeadBlockHash, HeadFastBlockHash, and FinalizedBlockHash, the
|
||||
// Write and Delete operations should carefully ensure that the database being used is BlockStore.
|
||||
// 3) Ancient Data: When using a multi-database, Ancient data will use the BlockStore.
|
||||
|
||||
// ReadCanonicalHash retrieves the hash assigned to a canonical block number.
|
||||
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(ChainFreezerHashTable, number)
|
||||
if len(data) == 0 {
|
||||
// Get it by hash from leveldb
|
||||
data, _ = db.Get(headerHashKey(number))
|
||||
data, _ = db.BlockStoreReader().Get(headerHashKey(number))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -144,8 +153,8 @@ func ReadAllCanonicalHashes(db ethdb.Iteratee, from uint64, to uint64, limit int
|
||||
}
|
||||
|
||||
// ReadHeaderNumber returns the header number assigned to a hash.
|
||||
func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 {
|
||||
data, _ := db.Get(headerNumberKey(hash))
|
||||
func ReadHeaderNumber(db ethdb.MultiDatabaseReader, hash common.Hash) *uint64 {
|
||||
data, _ := db.BlockStoreReader().Get(headerNumberKey(hash))
|
||||
if len(data) != 8 {
|
||||
return nil
|
||||
}
|
||||
@@ -170,8 +179,8 @@ func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) {
|
||||
}
|
||||
|
||||
// ReadHeadHeaderHash retrieves the hash of the current canonical head header.
|
||||
func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash {
|
||||
data, _ := db.Get(headHeaderKey)
|
||||
func ReadHeadHeaderHash(db ethdb.MultiDatabaseReader) common.Hash {
|
||||
data, _ := db.BlockStoreReader().Get(headHeaderKey)
|
||||
if len(data) == 0 {
|
||||
return common.Hash{}
|
||||
}
|
||||
@@ -186,8 +195,8 @@ func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) {
|
||||
}
|
||||
|
||||
// ReadHeadBlockHash retrieves the hash of the current canonical head block.
|
||||
func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash {
|
||||
data, _ := db.Get(headBlockKey)
|
||||
func ReadHeadBlockHash(db ethdb.MultiDatabaseReader) common.Hash {
|
||||
data, _ := db.BlockStoreReader().Get(headBlockKey)
|
||||
if len(data) == 0 {
|
||||
return common.Hash{}
|
||||
}
|
||||
@@ -202,8 +211,8 @@ func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) {
|
||||
}
|
||||
|
||||
// ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block.
|
||||
func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash {
|
||||
data, _ := db.Get(headFastBlockKey)
|
||||
func ReadHeadFastBlockHash(db ethdb.MultiDatabaseReader) common.Hash {
|
||||
data, _ := db.BlockStoreReader().Get(headFastBlockKey)
|
||||
if len(data) == 0 {
|
||||
return common.Hash{}
|
||||
}
|
||||
@@ -217,6 +226,22 @@ func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFinalizedBlockHash retrieves the hash of the finalized block.
|
||||
func ReadFinalizedBlockHash(db ethdb.MultiDatabaseReader) common.Hash {
|
||||
data, _ := db.BlockStoreReader().Get(headFinalizedBlockKey)
|
||||
if len(data) == 0 {
|
||||
return common.Hash{}
|
||||
}
|
||||
return common.BytesToHash(data)
|
||||
}
|
||||
|
||||
// WriteFinalizedBlockHash stores the hash of the finalized block.
|
||||
func WriteFinalizedBlockHash(db ethdb.KeyValueWriter, hash common.Hash) {
|
||||
if err := db.Put(headFinalizedBlockKey, hash.Bytes()); err != nil {
|
||||
log.Crit("Failed to store last finalized block's hash", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ReadLastPivotNumber retrieves the number of the last pivot block. If the node
|
||||
// full synced, the last pivot will always be nil.
|
||||
func ReadLastPivotNumber(db ethdb.KeyValueReader) *uint64 {
|
||||
@@ -281,13 +306,13 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
|
||||
// It's ok to request block 0, 1 item
|
||||
count = number + 1
|
||||
}
|
||||
limit, _ := db.Ancients()
|
||||
limit, _ := db.BlockStoreReader().Ancients()
|
||||
// First read live blocks
|
||||
if i >= limit {
|
||||
// If we need to read live blocks, we need to figure out the hash first
|
||||
hash := ReadCanonicalHash(db, number)
|
||||
for ; i >= limit && count > 0; i-- {
|
||||
if data, _ := db.Get(headerKey(i, hash)); len(data) > 0 {
|
||||
if data, _ := db.BlockStoreReader().Get(headerKey(i, hash)); len(data) > 0 {
|
||||
rlpHeaders = append(rlpHeaders, data)
|
||||
// Get the parent hash for next query
|
||||
hash = types.HeaderParentHashFromRLP(data)
|
||||
@@ -300,8 +325,8 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
|
||||
if count == 0 {
|
||||
return rlpHeaders
|
||||
}
|
||||
// read remaining from ancients
|
||||
data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, 0)
|
||||
// read remaining from ancients, cap at 2M
|
||||
data, err := db.BlockStoreReader().AncientRange(ChainFreezerHeaderTable, i+1-count, count, 2*1024*1024)
|
||||
if err != nil {
|
||||
log.Error("Failed to read headers from freezer", "err", err)
|
||||
return rlpHeaders
|
||||
@@ -320,7 +345,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
|
||||
// ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
|
||||
func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// First try to look up the data in ancient database. Extra hash
|
||||
// comparison is necessary since ancient database only maintains
|
||||
// the canonical data.
|
||||
@@ -329,7 +354,7 @@ func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValu
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
data, _ = db.Get(headerKey(number, hash))
|
||||
data, _ = db.BlockStoreReader().Get(headerKey(number, hash))
|
||||
return nil
|
||||
})
|
||||
return data
|
||||
@@ -337,10 +362,10 @@ func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValu
|
||||
|
||||
// HasHeader verifies the existence of a block header corresponding to the hash.
|
||||
func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||
if isCanon(db, number, hash) {
|
||||
if isCanon(db.BlockStoreReader(), number, hash) {
|
||||
return true
|
||||
}
|
||||
if has, err := db.Has(headerKey(number, hash)); !has || err != nil {
|
||||
if has, err := db.BlockStoreReader().Has(headerKey(number, hash)); !has || err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -427,14 +452,14 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
|
||||
// comparison is necessary since ancient database only maintains
|
||||
// the canonical data.
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
data, _ = db.Get(blockBodyKey(number, hash))
|
||||
data, _ = db.BlockStoreReader().Get(blockBodyKey(number, hash))
|
||||
return nil
|
||||
})
|
||||
return data
|
||||
@@ -444,7 +469,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
|
||||
// block at number, in RLP encoding.
|
||||
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
||||
if len(data) > 0 {
|
||||
return nil
|
||||
@@ -452,8 +477,8 @@ func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
|
||||
// Block is not in ancients, read from leveldb by hash and number.
|
||||
// Note: ReadCanonicalHash cannot be used here because it also
|
||||
// calls ReadAncients internally.
|
||||
hash, _ := db.Get(headerHashKey(number))
|
||||
data, _ = db.Get(blockBodyKey(number, common.BytesToHash(hash)))
|
||||
hash, _ := db.BlockStoreReader().Get(headerHashKey(number))
|
||||
data, _ = db.BlockStoreReader().Get(blockBodyKey(number, common.BytesToHash(hash)))
|
||||
return nil
|
||||
})
|
||||
return data
|
||||
@@ -468,10 +493,10 @@ func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp
|
||||
|
||||
// HasBody verifies the existence of a block body corresponding to the hash.
|
||||
func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||
if isCanon(db, number, hash) {
|
||||
if isCanon(db.BlockStoreReader(), number, hash) {
|
||||
return true
|
||||
}
|
||||
if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
|
||||
if has, err := db.BlockStoreReader().Has(blockBodyKey(number, hash)); !has || err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -500,6 +525,13 @@ func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *t
|
||||
WriteBodyRLP(db, hash, number, data)
|
||||
}
|
||||
|
||||
// DeleteBody removes all block body data associated with a hash.
|
||||
func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||
if err := db.Delete(blockBodyKey(number, hash)); err != nil {
|
||||
log.Crit("Failed to delete block body", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
func WriteDiffLayer(db ethdb.KeyValueWriter, hash common.Hash, layer *types.DiffLayer) {
|
||||
data, err := rlp.EncodeToBytes(layer)
|
||||
if err != nil {
|
||||
@@ -538,24 +570,17 @@ func DeleteDiffLayer(db ethdb.KeyValueWriter, blockHash common.Hash) {
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteBody removes all block body data associated with a hash.
|
||||
func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||
if err := db.Delete(blockBodyKey(number, hash)); err != nil {
|
||||
log.Crit("Failed to delete block body", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
|
||||
func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(ChainFreezerDifficultyTable, number)
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
data, _ = db.Get(headerTDKey(number, hash))
|
||||
data, _ = db.BlockStoreReader().Get(headerTDKey(number, hash))
|
||||
return nil
|
||||
})
|
||||
return data
|
||||
@@ -596,10 +621,10 @@ func DeleteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||
// HasReceipts verifies the existence of all the transaction receipts belonging
|
||||
// to a block.
|
||||
func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||
if isCanon(db, number, hash) {
|
||||
if isCanon(db.BlockStoreReader(), number, hash) {
|
||||
return true
|
||||
}
|
||||
if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
|
||||
if has, err := db.BlockStoreReader().Has(blockReceiptsKey(number, hash)); !has || err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -608,14 +633,14 @@ func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||
// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
|
||||
func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(ChainFreezerReceiptTable, number)
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
data, _ = db.Get(blockReceiptsKey(number, hash))
|
||||
data, _ = db.BlockStoreReader().Get(blockReceiptsKey(number, hash))
|
||||
return nil
|
||||
})
|
||||
return data
|
||||
@@ -868,14 +893,14 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
|
||||
// ReadBlobSidecarsRLP retrieves all the transaction blobs belonging to a block in RLP encoding.
|
||||
func ReadBlobSidecarsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(ChainFreezerBlobSidecarTable, number)
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
data, _ = db.Get(blockBlobSidecarsKey(number, hash))
|
||||
data, _ = db.BlockStoreReader().Get(blockBlobSidecarsKey(number, hash))
|
||||
return nil
|
||||
})
|
||||
return data
|
||||
|
||||
@@ -518,7 +518,7 @@ func checkBlobSidecarsRLP(have, want types.BlobSidecars) error {
|
||||
func TestAncientStorage(t *testing.T) {
|
||||
// Freezer style fast import the chain.
|
||||
frdir := t.TempDir()
|
||||
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false, false)
|
||||
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create database with ancient backend")
|
||||
}
|
||||
@@ -657,7 +657,7 @@ func TestHashesInRange(t *testing.T) {
|
||||
func BenchmarkWriteAncientBlocks(b *testing.B) {
|
||||
// Open freezer database.
|
||||
frdir := b.TempDir()
|
||||
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false, false)
|
||||
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to create database with ancient backend")
|
||||
}
|
||||
@@ -1001,7 +1001,7 @@ func TestHeadersRLPStorage(t *testing.T) {
|
||||
// Have N headers in the freezer
|
||||
frdir := t.TempDir()
|
||||
|
||||
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false, false)
|
||||
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create database with ancient backend")
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package rawdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@@ -98,6 +100,18 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, err := os.Open(filepath.Join(datadir, StateFreezerName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
// if state freezer folder has been pruned, there is no need for inspection
|
||||
_, err = file.Readdirnames(1)
|
||||
if err == io.EOF {
|
||||
continue
|
||||
}
|
||||
|
||||
f, err := NewStateFreezer(datadir, true, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -121,16 +135,25 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||
// ancient indicates the path of root ancient directory where the chain freezer can
|
||||
// be opened. Start and end specify the range for dumping out indexes.
|
||||
// Note this function can only be used for debugging purposes.
|
||||
func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error {
|
||||
func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64, multiDatabase bool) error {
|
||||
var (
|
||||
path string
|
||||
tables map[string]bool
|
||||
)
|
||||
switch freezerName {
|
||||
case ChainFreezerName:
|
||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||
if multiDatabase {
|
||||
path, tables = resolveChainFreezerDir(filepath.Dir(ancient)+"/block/ancient"), chainFreezerNoSnappy
|
||||
} else {
|
||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||
}
|
||||
|
||||
case StateFreezerName:
|
||||
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
||||
if multiDatabase {
|
||||
path, tables = filepath.Join(filepath.Dir(ancient)+"/state/ancient", freezerName), stateFreezerNoSnappy
|
||||
} else {
|
||||
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -58,11 +58,14 @@ type chainFreezer struct {
|
||||
wg sync.WaitGroup
|
||||
trigger chan chan struct{} // Manual blocking freeze trigger, test determinism
|
||||
|
||||
freezeEnv atomic.Value
|
||||
freezeEnv atomic.Value
|
||||
waitEnvTimes int
|
||||
|
||||
multiDatabase bool
|
||||
}
|
||||
|
||||
// newChainFreezer initializes the freezer for ancient chain data.
|
||||
func newChainFreezer(datadir string, namespace string, readonly bool, offset uint64) (*chainFreezer, error) {
|
||||
func newChainFreezer(datadir string, namespace string, readonly bool, offset uint64, multiDatabase bool) (*chainFreezer, error) {
|
||||
freezer, err := NewChainFreezer(datadir, namespace, readonly, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -87,6 +90,57 @@ func (f *chainFreezer) Close() error {
|
||||
return f.Freezer.Close()
|
||||
}
|
||||
|
||||
// readHeadNumber returns the number of chain head block. 0 is returned if the
|
||||
// block is unknown or not available yet.
|
||||
func (f *chainFreezer) readHeadNumber(db ethdb.Reader) uint64 {
|
||||
hash := ReadHeadBlockHash(db)
|
||||
if hash == (common.Hash{}) {
|
||||
log.Error("Head block is not reachable")
|
||||
return 0
|
||||
}
|
||||
number := ReadHeaderNumber(db, hash)
|
||||
if number == nil {
|
||||
log.Error("Number of head block is missing")
|
||||
return 0
|
||||
}
|
||||
return *number
|
||||
}
|
||||
|
||||
// readFinalizedNumber returns the number of finalized block. 0 is returned
|
||||
// if the block is unknown or not available yet.
|
||||
func (f *chainFreezer) readFinalizedNumber(db ethdb.Reader) uint64 {
|
||||
hash := ReadFinalizedBlockHash(db)
|
||||
if hash == (common.Hash{}) {
|
||||
return 0
|
||||
}
|
||||
number := ReadHeaderNumber(db, hash)
|
||||
if number == nil {
|
||||
log.Error("Number of finalized block is missing")
|
||||
return 0
|
||||
}
|
||||
return *number
|
||||
}
|
||||
|
||||
// freezeThreshold returns the threshold for chain freezing. It's determined
|
||||
// by formula: max(finality, HEAD-params.FullImmutabilityThreshold).
|
||||
func (f *chainFreezer) freezeThreshold(db ethdb.Reader) (uint64, error) {
|
||||
var (
|
||||
head = f.readHeadNumber(db)
|
||||
final = f.readFinalizedNumber(db)
|
||||
headLimit uint64
|
||||
)
|
||||
if head > params.FullImmutabilityThreshold {
|
||||
headLimit = head - params.FullImmutabilityThreshold
|
||||
}
|
||||
if final == 0 && headLimit == 0 {
|
||||
return 0, errors.New("freezing threshold is not available")
|
||||
}
|
||||
if final > headLimit {
|
||||
return final, nil
|
||||
}
|
||||
return headLimit, nil
|
||||
}
|
||||
|
||||
// freeze is a background thread that periodically checks the blockchain for any
|
||||
// import progress and moves ancient data from the fast database into the freezer.
|
||||
//
|
||||
@@ -125,74 +179,125 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
|
||||
}
|
||||
}
|
||||
|
||||
// check freezer env first, it must wait a while when the env is necessary
|
||||
err := f.checkFreezerEnv()
|
||||
if err == missFreezerEnvErr {
|
||||
log.Warn("Freezer need related env, may wait for a while", "err", err)
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("Freezer check FreezerEnv err", "err", err)
|
||||
backoff = true
|
||||
continue
|
||||
var (
|
||||
frozen uint64
|
||||
threshold uint64
|
||||
first uint64 // the first block to freeze
|
||||
last uint64 // the last block to freeze
|
||||
|
||||
hash common.Hash
|
||||
number *uint64
|
||||
head *types.Header
|
||||
err error
|
||||
)
|
||||
|
||||
// use finalized block as the chain freeze indicator was used for multiDatabase feature, if multiDatabase is false, keep 9W blocks in db
|
||||
if f.multiDatabase {
|
||||
threshold, err = f.freezeThreshold(nfdb)
|
||||
if err != nil {
|
||||
backoff = true
|
||||
log.Debug("Current full block not old enough to freeze", "err", err)
|
||||
continue
|
||||
}
|
||||
frozen = f.frozen.Load()
|
||||
|
||||
// Short circuit if the blocks below threshold are already frozen.
|
||||
if frozen != 0 && frozen-1 >= threshold {
|
||||
backoff = true
|
||||
log.Debug("Ancient blocks frozen already", "threshold", threshold, "frozen", frozen)
|
||||
continue
|
||||
}
|
||||
|
||||
hash = ReadHeadBlockHash(nfdb)
|
||||
if hash == (common.Hash{}) {
|
||||
log.Debug("Current full block hash unavailable") // new chain, empty database
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
number = ReadHeaderNumber(nfdb, hash)
|
||||
if number == nil {
|
||||
log.Error("Current full block number unavailable", "hash", hash)
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
head = ReadHeader(nfdb, hash, *number)
|
||||
if head == nil {
|
||||
log.Error("Current full block unavailable", "number", *number, "hash", hash)
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
|
||||
first = frozen
|
||||
last = threshold
|
||||
if last-first+1 > freezerBatchLimit {
|
||||
last = freezerBatchLimit + first - 1
|
||||
}
|
||||
} else {
|
||||
// Retrieve the freezing threshold.
|
||||
hash = ReadHeadBlockHash(nfdb)
|
||||
if hash == (common.Hash{}) {
|
||||
log.Debug("Current full block hash unavailable") // new chain, empty database
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
number = ReadHeaderNumber(nfdb, hash)
|
||||
threshold = f.threshold.Load()
|
||||
frozen = f.frozen.Load()
|
||||
switch {
|
||||
case number == nil:
|
||||
log.Error("Current full block number unavailable", "hash", hash)
|
||||
backoff = true
|
||||
continue
|
||||
|
||||
case *number < threshold:
|
||||
log.Debug("Current full block not old enough to freeze", "number", *number, "hash", hash, "delay", threshold)
|
||||
backoff = true
|
||||
continue
|
||||
|
||||
case *number-threshold <= frozen:
|
||||
log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", frozen)
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
head = ReadHeader(nfdb, hash, *number)
|
||||
if head == nil {
|
||||
log.Error("Current full block unavailable", "number", *number, "hash", hash)
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
first, _ = f.Ancients()
|
||||
last = *number - threshold
|
||||
if last-first > freezerBatchLimit {
|
||||
last = first + freezerBatchLimit
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the freezing threshold.
|
||||
hash := ReadHeadBlockHash(nfdb)
|
||||
if hash == (common.Hash{}) {
|
||||
log.Debug("Current full block hash unavailable") // new chain, empty database
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
number := ReadHeaderNumber(nfdb, hash)
|
||||
threshold := f.threshold.Load()
|
||||
frozen := f.frozen.Load()
|
||||
switch {
|
||||
case number == nil:
|
||||
log.Error("Current full block number unavailable", "hash", hash)
|
||||
backoff = true
|
||||
continue
|
||||
|
||||
case *number < threshold:
|
||||
log.Debug("Current full block not old enough to freeze", "number", *number, "hash", hash, "delay", threshold)
|
||||
backoff = true
|
||||
continue
|
||||
|
||||
case *number-threshold <= frozen:
|
||||
log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", frozen)
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
head := ReadHeader(nfdb, hash, *number)
|
||||
if head == nil {
|
||||
log.Error("Current full block unavailable", "number", *number, "hash", hash)
|
||||
// check env first before chain freeze, it must wait when the env is necessary
|
||||
if err := f.checkFreezerEnv(); err != nil {
|
||||
f.waitEnvTimes++
|
||||
if f.waitEnvTimes%30 == 0 {
|
||||
log.Warn("Freezer need related env, may wait for a while, and it's not a issue when non-import block", "err", err)
|
||||
return
|
||||
}
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Seems we have data ready to be frozen, process in usable batches
|
||||
var (
|
||||
start = time.Now()
|
||||
first, _ = f.Ancients()
|
||||
limit = *number - threshold
|
||||
start = time.Now()
|
||||
)
|
||||
if limit-first > freezerBatchLimit {
|
||||
limit = first + freezerBatchLimit
|
||||
}
|
||||
|
||||
ancients, err := f.freezeRangeWithBlobs(nfdb, first, limit)
|
||||
ancients, err := f.freezeRangeWithBlobs(nfdb, first, last)
|
||||
if err != nil {
|
||||
log.Error("Error in block freeze operation", "err", err)
|
||||
backoff = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Batch of blocks have been frozen, flush them before wiping from leveldb
|
||||
if err := f.Sync(); err != nil {
|
||||
log.Crit("Failed to flush frozen tables", "err", err)
|
||||
}
|
||||
|
||||
// Wipe out all data from the active database
|
||||
batch := db.NewBatch()
|
||||
for i := 0; i < len(ancients); i++ {
|
||||
@@ -358,13 +463,16 @@ func (f *chainFreezer) freezeRangeWithBlobs(nfdb *nofreezedb, number, limit uint
|
||||
return hashes, err
|
||||
}
|
||||
|
||||
// freezeRange moves a batch of chain segments from the fast database to the freezer.
|
||||
// The parameters (number, limit) specify the relevant block range, both of which
|
||||
// are included.
|
||||
func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) {
|
||||
if number > limit {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
env, _ := f.freezeEnv.Load().(*ethdb.FreezerEnv)
|
||||
hashes = make([]common.Hash, 0, limit-number)
|
||||
hashes = make([]common.Hash, 0, limit-number+1)
|
||||
_, err = f.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
||||
for ; number <= limit; number++ {
|
||||
// Retrieve all the components of the canonical block.
|
||||
@@ -437,14 +545,7 @@ func (f *chainFreezer) checkFreezerEnv() error {
|
||||
if exist {
|
||||
return nil
|
||||
}
|
||||
blobFrozen, err := f.TableAncients(ChainFreezerBlobSidecarTable)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if blobFrozen > 0 {
|
||||
return missFreezerEnvErr
|
||||
}
|
||||
return nil
|
||||
return missFreezerEnvErr
|
||||
}
|
||||
|
||||
func isCancun(env *ethdb.FreezerEnv, num *big.Int, time uint64) bool {
|
||||
|
||||
@@ -35,16 +35,16 @@ import (
|
||||
// injects into the database the block hash->number mappings.
|
||||
func InitDatabaseFromFreezer(db ethdb.Database) {
|
||||
// If we can't access the freezer or it's empty, abort
|
||||
frozen, err := db.ItemAmountInAncient()
|
||||
frozen, err := db.BlockStore().ItemAmountInAncient()
|
||||
if err != nil || frozen == 0 {
|
||||
return
|
||||
}
|
||||
var (
|
||||
batch = db.NewBatch()
|
||||
batch = db.BlockStore().NewBatch()
|
||||
start = time.Now()
|
||||
logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log
|
||||
hash common.Hash
|
||||
offset = db.AncientOffSet()
|
||||
offset = db.BlockStore().AncientOffSet()
|
||||
)
|
||||
for i := uint64(0) + offset; i < frozen+offset; i++ {
|
||||
// We read 100K hashes at a time, for a total of 3.2M
|
||||
@@ -52,7 +52,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
||||
if i+count > frozen+offset {
|
||||
count = frozen + offset - i
|
||||
}
|
||||
data, err := db.AncientRange(ChainFreezerHashTable, i, count, 32*count)
|
||||
data, err := db.BlockStore().AncientRange(ChainFreezerHashTable, i, count, 32*count)
|
||||
if err != nil {
|
||||
log.Crit("Failed to init database from freezer", "err", err)
|
||||
}
|
||||
@@ -80,8 +80,8 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
||||
}
|
||||
batch.Reset()
|
||||
|
||||
WriteHeadHeaderHash(db, hash)
|
||||
WriteHeadFastBlockHash(db, hash)
|
||||
WriteHeadHeaderHash(db.BlockStore(), hash)
|
||||
WriteHeadFastBlockHash(db.BlockStore(), hash)
|
||||
log.Info("Initialized database from freezer", "blocks", frozen, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
|
||||
number uint64
|
||||
rlp rlp.RawValue
|
||||
}
|
||||
if offset := db.AncientOffSet(); offset > from {
|
||||
if offset := db.BlockStore().AncientOffSet(); offset > from {
|
||||
from = offset
|
||||
}
|
||||
if to <= from {
|
||||
@@ -187,7 +187,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
|
||||
// signal received.
|
||||
func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
||||
// short circuit for invalid range
|
||||
if offset := db.AncientOffSet(); offset > from {
|
||||
if offset := db.BlockStore().AncientOffSet(); offset > from {
|
||||
from = offset
|
||||
}
|
||||
if from >= to {
|
||||
@@ -286,7 +286,7 @@ func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, inte
|
||||
// signal received.
|
||||
func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
||||
// short circuit for invalid range
|
||||
if offset := db.AncientOffSet(); offset > from {
|
||||
if offset := db.BlockStore().AncientOffSet(); offset > from {
|
||||
from = offset
|
||||
}
|
||||
if from >= to {
|
||||
|
||||
@@ -26,14 +26,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
)
|
||||
|
||||
// freezerdb is a database wrapper that enables freezer data retrievals.
|
||||
@@ -44,6 +43,7 @@ type freezerdb struct {
|
||||
ethdb.AncientFreezer
|
||||
diffStore ethdb.KeyValueStore
|
||||
stateStore ethdb.Database
|
||||
blockStore ethdb.Database
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) StateStoreReader() ethdb.Reader {
|
||||
@@ -53,6 +53,20 @@ func (frdb *freezerdb) StateStoreReader() ethdb.Reader {
|
||||
return frdb.stateStore
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) BlockStoreReader() ethdb.Reader {
|
||||
if frdb.blockStore == nil {
|
||||
return frdb
|
||||
}
|
||||
return frdb.blockStore
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) BlockStoreWriter() ethdb.Writer {
|
||||
if frdb.blockStore == nil {
|
||||
return frdb
|
||||
}
|
||||
return frdb.blockStore
|
||||
}
|
||||
|
||||
// AncientDatadir returns the path of root ancient directory.
|
||||
func (frdb *freezerdb) AncientDatadir() (string, error) {
|
||||
return frdb.ancientRoot, nil
|
||||
@@ -78,6 +92,11 @@ func (frdb *freezerdb) Close() error {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if frdb.blockStore != nil {
|
||||
if err := frdb.blockStore.Close(); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if len(errs) != 0 {
|
||||
return fmt.Errorf("%v", errs)
|
||||
}
|
||||
@@ -99,6 +118,13 @@ func (frdb *freezerdb) StateStore() ethdb.Database {
|
||||
return frdb.stateStore
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) GetStateStore() ethdb.Database {
|
||||
if frdb.stateStore != nil {
|
||||
return frdb.stateStore
|
||||
}
|
||||
return frdb
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) SetStateStore(state ethdb.Database) {
|
||||
if frdb.stateStore != nil {
|
||||
frdb.stateStore.Close()
|
||||
@@ -106,6 +132,25 @@ func (frdb *freezerdb) SetStateStore(state ethdb.Database) {
|
||||
frdb.stateStore = state
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) BlockStore() ethdb.Database {
|
||||
if frdb.blockStore != nil {
|
||||
return frdb.blockStore
|
||||
} else {
|
||||
return frdb
|
||||
}
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) SetBlockStore(block ethdb.Database) {
|
||||
if frdb.blockStore != nil {
|
||||
frdb.blockStore.Close()
|
||||
}
|
||||
frdb.blockStore = block
|
||||
}
|
||||
|
||||
func (frdb *freezerdb) HasSeparateBlockStore() bool {
|
||||
return frdb.blockStore != nil
|
||||
}
|
||||
|
||||
// Freeze is a helper method used for external testing to trigger and block until
|
||||
// a freeze cycle completes, without having to sleep for a minute to trigger the
|
||||
// automatic background run.
|
||||
@@ -118,7 +163,6 @@ func (frdb *freezerdb) Freeze(threshold uint64) error {
|
||||
frdb.AncientStore.(*chainFreezer).threshold.Store(old)
|
||||
}(frdb.AncientStore.(*chainFreezer).threshold.Load())
|
||||
frdb.AncientStore.(*chainFreezer).threshold.Store(threshold)
|
||||
|
||||
// Trigger a freeze cycle and block until it's done
|
||||
trigger := make(chan struct{}, 1)
|
||||
frdb.AncientStore.(*chainFreezer).trigger <- trigger
|
||||
@@ -135,6 +179,7 @@ type nofreezedb struct {
|
||||
ethdb.KeyValueStore
|
||||
diffStore ethdb.KeyValueStore
|
||||
stateStore ethdb.Database
|
||||
blockStore ethdb.Database
|
||||
}
|
||||
|
||||
// HasAncient returns an error as we don't have a backing chain freezer.
|
||||
@@ -157,7 +202,7 @@ func (db *nofreezedb) Ancients() (uint64, error) {
|
||||
return 0, errNotSupported
|
||||
}
|
||||
|
||||
// Ancients returns an error as we don't have a backing chain freezer.
|
||||
// ItemAmountInAncient returns an error as we don't have a backing chain freezer.
|
||||
func (db *nofreezedb) ItemAmountInAncient() (uint64, error) {
|
||||
return 0, errNotSupported
|
||||
}
|
||||
@@ -218,6 +263,13 @@ func (db *nofreezedb) SetStateStore(state ethdb.Database) {
|
||||
db.stateStore = state
|
||||
}
|
||||
|
||||
func (db *nofreezedb) GetStateStore() ethdb.Database {
|
||||
if db.stateStore != nil {
|
||||
return db.stateStore
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func (db *nofreezedb) StateStoreReader() ethdb.Reader {
|
||||
if db.stateStore != nil {
|
||||
return db.stateStore
|
||||
@@ -225,6 +277,35 @@ func (db *nofreezedb) StateStoreReader() ethdb.Reader {
|
||||
return db
|
||||
}
|
||||
|
||||
func (db *nofreezedb) BlockStore() ethdb.Database {
|
||||
if db.blockStore != nil {
|
||||
return db.blockStore
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func (db *nofreezedb) SetBlockStore(block ethdb.Database) {
|
||||
db.blockStore = block
|
||||
}
|
||||
|
||||
func (db *nofreezedb) HasSeparateBlockStore() bool {
|
||||
return db.blockStore != nil
|
||||
}
|
||||
|
||||
func (db *nofreezedb) BlockStoreReader() ethdb.Reader {
|
||||
if db.blockStore != nil {
|
||||
return db.blockStore
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func (db *nofreezedb) BlockStoreWriter() ethdb.Writer {
|
||||
if db.blockStore != nil {
|
||||
return db.blockStore
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) {
|
||||
// Unlike other ancient-related methods, this method does not return
|
||||
// errNotSupported when invoked.
|
||||
@@ -266,6 +347,111 @@ func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
|
||||
return &nofreezedb{KeyValueStore: db}
|
||||
}
|
||||
|
||||
type emptyfreezedb struct {
|
||||
ethdb.KeyValueStore
|
||||
}
|
||||
|
||||
// HasAncient returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) HasAncient(kind string, number uint64) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Ancient returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) Ancient(kind string, number uint64) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// AncientRange returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) AncientRange(kind string, start, max, maxByteSize uint64) ([][]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Ancients returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) Ancients() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// ItemAmountInAncient returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) ItemAmountInAncient() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Tail returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) Tail() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// AncientSize returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) AncientSize(kind string) (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// ModifyAncients returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) ModifyAncients(func(ethdb.AncientWriteOp) error) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// TruncateHead returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) TruncateHead(items uint64) (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// TruncateTail returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) TruncateTail(items uint64) (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// TruncateTableTail returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) TruncateTableTail(kind string, tail uint64) (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// ResetTable returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) ResetTable(kind string, startAt uint64, onlyEmpty bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sync returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) Sync() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *emptyfreezedb) DiffStore() ethdb.KeyValueStore { return db }
|
||||
func (db *emptyfreezedb) SetDiffStore(diff ethdb.KeyValueStore) {}
|
||||
func (db *emptyfreezedb) StateStore() ethdb.Database { return db }
|
||||
func (db *emptyfreezedb) GetStateStore() ethdb.Database { return db }
|
||||
func (db *emptyfreezedb) SetStateStore(state ethdb.Database) {}
|
||||
func (db *emptyfreezedb) StateStoreReader() ethdb.Reader { return db }
|
||||
func (db *emptyfreezedb) BlockStore() ethdb.Database { return db }
|
||||
func (db *emptyfreezedb) SetBlockStore(block ethdb.Database) {}
|
||||
func (db *emptyfreezedb) HasSeparateBlockStore() bool { return false }
|
||||
func (db *emptyfreezedb) BlockStoreReader() ethdb.Reader { return db }
|
||||
func (db *emptyfreezedb) BlockStoreWriter() ethdb.Writer { return db }
|
||||
func (db *emptyfreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) {
|
||||
return nil
|
||||
}
|
||||
func (db *emptyfreezedb) AncientOffSet() uint64 { return 0 }
|
||||
|
||||
// MigrateTable returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) MigrateTable(kind string, convert convertLegacyFn) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AncientDatadir returns nil for pruned db that we don't have a backing chain freezer.
|
||||
func (db *emptyfreezedb) AncientDatadir() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
func (db *emptyfreezedb) SetupFreezerEnv(env *ethdb.FreezerEnv) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewEmptyFreezeDB is used for CLI such as `geth db inspect` in pruned db that we don't
|
||||
// have a backing chain freezer.
|
||||
// WARNING: it must be only used in the above case.
|
||||
func NewEmptyFreezeDB(db ethdb.KeyValueStore) ethdb.Database {
|
||||
return &emptyfreezedb{KeyValueStore: db}
|
||||
}
|
||||
|
||||
// NewFreezerDb only create a freezer without statedb.
|
||||
func NewFreezerDb(db ethdb.KeyValueStore, frz, namespace string, readonly bool, newOffSet uint64) (*Freezer, error) {
|
||||
// Create the idle freezer instance, this operation should be atomic to avoid mismatch between offset and acientDB.
|
||||
@@ -306,7 +492,7 @@ func resolveChainFreezerDir(ancient string) string {
|
||||
// value data store with a freezer moving immutable chain segments into cold
|
||||
// storage. The passed ancient indicates the path of root ancient directory
|
||||
// where the chain freezer can be opened.
|
||||
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) {
|
||||
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData, multiDatabase bool) (ethdb.Database, error) {
|
||||
var offset uint64
|
||||
// The offset of ancientDB should be handled differently in different scenarios.
|
||||
if isLastOffset {
|
||||
@@ -315,6 +501,12 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
offset = ReadOffSetOfCurrentAncientFreezer(db)
|
||||
}
|
||||
|
||||
// This case is used for someone who wants to execute geth db inspect CLI in a pruned db
|
||||
if !disableFreeze && readonly && ReadAncientType(db) == PruneFreezerType {
|
||||
log.Warn("Disk db is pruned, using an empty freezer db for CLI")
|
||||
return NewEmptyFreezeDB(db), nil
|
||||
}
|
||||
|
||||
if pruneAncientData && !disableFreeze && !readonly {
|
||||
frdb, err := newPrunedFreezer(resolveChainFreezerDir(ancient), db, offset)
|
||||
if err != nil {
|
||||
@@ -342,9 +534,18 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
}
|
||||
|
||||
// Create the idle freezer instance
|
||||
frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, offset)
|
||||
frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, offset, multiDatabase)
|
||||
|
||||
// We are creating the freezerdb here because the validation logic for db and freezer below requires certain interfaces
|
||||
// that need a database type. Therefore, we are pre-creating it for subsequent use.
|
||||
freezerDb := &freezerdb{
|
||||
ancientRoot: ancient,
|
||||
KeyValueStore: db,
|
||||
AncientStore: frdb,
|
||||
AncientFreezer: frdb,
|
||||
}
|
||||
if err != nil {
|
||||
printChainMetadata(db)
|
||||
printChainMetadata(freezerDb)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -380,10 +581,10 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
// the freezer and the key-value store.
|
||||
frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
|
||||
if err != nil {
|
||||
printChainMetadata(db)
|
||||
printChainMetadata(freezerDb)
|
||||
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
|
||||
} else if !bytes.Equal(kvgenesis, frgenesis) {
|
||||
printChainMetadata(db)
|
||||
printChainMetadata(freezerDb)
|
||||
return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis)
|
||||
}
|
||||
// Key-value store and freezer belong to the same network. Ensure that they
|
||||
@@ -391,7 +592,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 {
|
||||
// Subsequent header after the freezer limit is missing from the database.
|
||||
// Reject startup if the database has a more recent head.
|
||||
if head := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 {
|
||||
if head := *ReadHeaderNumber(freezerDb, ReadHeadHeaderHash(freezerDb)); head > frozen-1 {
|
||||
// Find the smallest block stored in the key-value store
|
||||
// in range of [frozen, head]
|
||||
var number uint64
|
||||
@@ -401,7 +602,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
}
|
||||
}
|
||||
// We are about to exit on error. Print database metadata before exiting
|
||||
printChainMetadata(db)
|
||||
printChainMetadata(freezerDb)
|
||||
return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
|
||||
frozen-1, number, head)
|
||||
}
|
||||
@@ -416,11 +617,11 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
// store, otherwise we'll end up missing data. We check block #1 to decide
|
||||
// if we froze anything previously or not, but do take care of databases with
|
||||
// only the genesis block.
|
||||
if ReadHeadHeaderHash(db) != common.BytesToHash(kvgenesis) {
|
||||
if ReadHeadHeaderHash(freezerDb) != common.BytesToHash(kvgenesis) {
|
||||
// Key-value store contains more data than the genesis block, make sure we
|
||||
// didn't freeze anything yet.
|
||||
if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 {
|
||||
printChainMetadata(db)
|
||||
printChainMetadata(freezerDb)
|
||||
return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path")
|
||||
}
|
||||
// Block #1 is still in the database, we're allowed to init a new freezer
|
||||
@@ -429,6 +630,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
// freezer.
|
||||
}
|
||||
}
|
||||
|
||||
// no prune ancient start success
|
||||
if !readonly {
|
||||
WriteAncientType(db, EntireFreezerType)
|
||||
@@ -441,12 +643,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
frdb.wg.Done()
|
||||
}()
|
||||
}
|
||||
return &freezerdb{
|
||||
ancientRoot: ancient,
|
||||
KeyValueStore: db,
|
||||
AncientStore: frdb,
|
||||
AncientFreezer: frdb,
|
||||
}, nil
|
||||
return freezerDb, nil
|
||||
}
|
||||
|
||||
// NewMemoryDatabase creates an ephemeral in-memory key-value database without a
|
||||
@@ -518,9 +715,12 @@ type OpenOptions struct {
|
||||
DisableFreeze bool
|
||||
IsLastOffset bool
|
||||
PruneAncientData bool
|
||||
|
||||
// Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of
|
||||
// a crash is not important. This option should typically be used in tests.
|
||||
Ephemeral bool
|
||||
|
||||
MultiDataBase bool
|
||||
}
|
||||
|
||||
// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble.
|
||||
@@ -565,13 +765,13 @@ func Open(o OpenOptions) (ethdb.Database, error) {
|
||||
}
|
||||
if ReadAncientType(kvdb) == PruneFreezerType {
|
||||
if !o.PruneAncientData {
|
||||
log.Warn("Disk db is pruned")
|
||||
log.Warn("NOTICE: You're opening a pruned disk db!")
|
||||
}
|
||||
}
|
||||
if len(o.AncientsDirectory) == 0 {
|
||||
return kvdb, nil
|
||||
}
|
||||
frdb, err := NewDatabaseWithFreezer(kvdb, o.AncientsDirectory, o.Namespace, o.ReadOnly, o.DisableFreeze, o.IsLastOffset, o.PruneAncientData)
|
||||
frdb, err := NewDatabaseWithFreezer(kvdb, o.AncientsDirectory, o.Namespace, o.ReadOnly, o.DisableFreeze, o.IsLastOffset, o.PruneAncientData, o.MultiDataBase)
|
||||
if err != nil {
|
||||
kvdb.Close()
|
||||
return nil, err
|
||||
@@ -613,7 +813,7 @@ func AncientInspect(db ethdb.Database) error {
|
||||
offset := counter(ReadOffSetOfCurrentAncientFreezer(db))
|
||||
// Get number of ancient rows inside the freezer.
|
||||
ancients := counter(0)
|
||||
if count, err := db.ItemAmountInAncient(); err != nil {
|
||||
if count, err := db.BlockStore().ItemAmountInAncient(); err != nil {
|
||||
log.Error("failed to get the items amount in ancientDB", "err", err)
|
||||
return err
|
||||
} else {
|
||||
@@ -661,6 +861,48 @@ func PruneHashTrieNodeInDataBase(db ethdb.Database) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type DataType int
|
||||
|
||||
const (
|
||||
StateDataType DataType = iota
|
||||
BlockDataType
|
||||
ChainDataType
|
||||
Unknown
|
||||
)
|
||||
|
||||
func DataTypeByKey(key []byte) DataType {
|
||||
switch {
|
||||
// state
|
||||
case IsLegacyTrieNode(key, key),
|
||||
bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength,
|
||||
IsAccountTrieNode(key),
|
||||
IsStorageTrieNode(key):
|
||||
return StateDataType
|
||||
|
||||
// block
|
||||
case bytes.HasPrefix(key, headerPrefix) && len(key) == (len(headerPrefix)+8+common.HashLength),
|
||||
bytes.HasPrefix(key, blockBodyPrefix) && len(key) == (len(blockBodyPrefix)+8+common.HashLength),
|
||||
bytes.HasPrefix(key, blockReceiptsPrefix) && len(key) == (len(blockReceiptsPrefix)+8+common.HashLength),
|
||||
bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerTDSuffix),
|
||||
bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerHashSuffix),
|
||||
bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength):
|
||||
return BlockDataType
|
||||
default:
|
||||
for _, meta := range [][]byte{
|
||||
fastTrieProgressKey, persistentStateIDKey, trieJournalKey, snapSyncStatusFlagKey} {
|
||||
if bytes.Equal(key, meta) {
|
||||
return StateDataType
|
||||
}
|
||||
}
|
||||
for _, meta := range [][]byte{headHeaderKey, headFinalizedBlockKey, headBlockKey, headFastBlockKey} {
|
||||
if bytes.Equal(key, meta) {
|
||||
return BlockDataType
|
||||
}
|
||||
}
|
||||
return ChainDataType
|
||||
}
|
||||
}
|
||||
|
||||
// InspectDatabase traverses the entire database and checks the size
|
||||
// of all different categories of data.
|
||||
func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||
@@ -668,10 +910,15 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||
defer it.Release()
|
||||
|
||||
var trieIter ethdb.Iterator
|
||||
var blockIter ethdb.Iterator
|
||||
if db.StateStore() != nil {
|
||||
trieIter = db.StateStore().NewIterator(keyPrefix, nil)
|
||||
defer trieIter.Release()
|
||||
}
|
||||
if db.HasSeparateBlockStore() {
|
||||
blockIter = db.BlockStore().NewIterator(keyPrefix, nil)
|
||||
defer blockIter.Release()
|
||||
}
|
||||
var (
|
||||
count int64
|
||||
start = time.Now()
|
||||
@@ -801,6 +1048,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||
value = trieIter.Value()
|
||||
size = common.StorageSize(len(key) + len(value))
|
||||
)
|
||||
total += size
|
||||
|
||||
switch {
|
||||
case IsLegacyTrieNode(key, value):
|
||||
@@ -814,9 +1062,10 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||
default:
|
||||
var accounted bool
|
||||
for _, meta := range [][]byte{
|
||||
fastTrieProgressKey, persistentStateIDKey, trieJournalKey} {
|
||||
fastTrieProgressKey, persistentStateIDKey, trieJournalKey, snapSyncStatusFlagKey} {
|
||||
if bytes.Equal(key, meta) {
|
||||
metadata.Add(size)
|
||||
accounted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -830,6 +1079,54 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||
logged = time.Now()
|
||||
}
|
||||
}
|
||||
log.Info("Inspecting separate state database", "count", count, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
}
|
||||
// inspect separate block db
|
||||
if blockIter != nil {
|
||||
count = 0
|
||||
logged = time.Now()
|
||||
|
||||
for blockIter.Next() {
|
||||
var (
|
||||
key = blockIter.Key()
|
||||
value = blockIter.Value()
|
||||
size = common.StorageSize(len(key) + len(value))
|
||||
)
|
||||
total += size
|
||||
|
||||
switch {
|
||||
case bytes.HasPrefix(key, headerPrefix) && len(key) == (len(headerPrefix)+8+common.HashLength):
|
||||
headers.Add(size)
|
||||
case bytes.HasPrefix(key, blockBodyPrefix) && len(key) == (len(blockBodyPrefix)+8+common.HashLength):
|
||||
bodies.Add(size)
|
||||
case bytes.HasPrefix(key, blockReceiptsPrefix) && len(key) == (len(blockReceiptsPrefix)+8+common.HashLength):
|
||||
receipts.Add(size)
|
||||
case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerTDSuffix):
|
||||
tds.Add(size)
|
||||
case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerHashSuffix):
|
||||
numHashPairings.Add(size)
|
||||
case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength):
|
||||
hashNumPairings.Add(size)
|
||||
default:
|
||||
var accounted bool
|
||||
for _, meta := range [][]byte{headHeaderKey, headFinalizedBlockKey, headBlockKey, headFastBlockKey} {
|
||||
if bytes.Equal(key, meta) {
|
||||
metadata.Add(size)
|
||||
accounted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !accounted {
|
||||
unaccounted.Add(size)
|
||||
}
|
||||
}
|
||||
count++
|
||||
if count%1000 == 0 && time.Since(logged) > 8*time.Second {
|
||||
log.Info("Inspecting separate block database", "count", count, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
logged = time.Now()
|
||||
}
|
||||
}
|
||||
log.Info("Inspecting separate block database", "count", count, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
}
|
||||
// Display the database statistic of key-value store.
|
||||
stats := [][]string{
|
||||
@@ -856,7 +1153,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||
{"Light client", "Bloom trie nodes", bloomTrieNodes.Size(), bloomTrieNodes.Count()},
|
||||
}
|
||||
// Inspect all registered append-only file store then.
|
||||
ancients, err := inspectFreezers(db)
|
||||
ancients, err := inspectFreezers(db.BlockStore())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -962,7 +1259,7 @@ func DeleteTrieState(db ethdb.Database) error {
|
||||
}
|
||||
|
||||
// printChainMetadata prints out chain metadata to stderr.
|
||||
func printChainMetadata(db ethdb.KeyValueStore) {
|
||||
func printChainMetadata(db ethdb.Reader) {
|
||||
fmt.Fprintf(os.Stderr, "Chain metadata\n")
|
||||
for _, v := range ReadChainMetadata(db) {
|
||||
fmt.Fprintf(os.Stderr, " %s\n", strings.Join(v, ": "))
|
||||
@@ -973,7 +1270,7 @@ func printChainMetadata(db ethdb.KeyValueStore) {
|
||||
// ReadChainMetadata returns a set of key/value pairs that contains information
|
||||
// about the database chain status. This can be used for diagnostic purposes
|
||||
// when investigating the state of the node.
|
||||
func ReadChainMetadata(db ethdb.KeyValueStore) [][]string {
|
||||
func ReadChainMetadata(db ethdb.Reader) [][]string {
|
||||
pp := func(val *uint64) string {
|
||||
if val == nil {
|
||||
return "<nil>"
|
||||
|
||||
@@ -239,7 +239,7 @@ func (f *Freezer) Ancient(kind string, number uint64) ([]byte, error) {
|
||||
// - if maxBytes is not specified, 'count' items will be returned if they are present.
|
||||
func (f *Freezer) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) {
|
||||
if table := f.tables[kind]; table != nil {
|
||||
return table.RetrieveItems(start, count, maxBytes)
|
||||
return table.RetrieveItems(start-f.offset, count, maxBytes)
|
||||
}
|
||||
return nil, errUnknownTable
|
||||
}
|
||||
@@ -252,7 +252,7 @@ func (f *Freezer) Ancients() (uint64, error) {
|
||||
func (f *Freezer) TableAncients(kind string) (uint64, error) {
|
||||
f.writeLock.RLock()
|
||||
defer f.writeLock.RUnlock()
|
||||
return f.tables[kind].items.Load(), nil
|
||||
return f.tables[kind].items.Load() + f.offset, nil
|
||||
}
|
||||
|
||||
// ItemAmountInAncient returns the actual length of current ancientDB.
|
||||
@@ -541,41 +541,6 @@ func gcKvStore(db ethdb.KeyValueStore, ancients []common.Hash, first uint64, fro
|
||||
}
|
||||
batch.Reset()
|
||||
|
||||
// Step into the future and delete and dangling side chains
|
||||
if frozen > 0 {
|
||||
tip := frozen
|
||||
nfdb := &nofreezedb{KeyValueStore: db}
|
||||
for len(dangling) > 0 {
|
||||
drop := make(map[common.Hash]struct{})
|
||||
for _, hash := range dangling {
|
||||
log.Debug("Dangling parent from freezer", "number", tip-1, "hash", hash)
|
||||
drop[hash] = struct{}{}
|
||||
}
|
||||
children := ReadAllHashes(db, tip)
|
||||
for i := 0; i < len(children); i++ {
|
||||
// Dig up the child and ensure it's dangling
|
||||
child := ReadHeader(nfdb, children[i], tip)
|
||||
if child == nil {
|
||||
log.Error("Missing dangling header", "number", tip, "hash", children[i])
|
||||
continue
|
||||
}
|
||||
if _, ok := drop[child.ParentHash]; !ok {
|
||||
children = append(children[:i], children[i+1:]...)
|
||||
i--
|
||||
continue
|
||||
}
|
||||
// Delete all block data associated with the child
|
||||
log.Debug("Deleting dangling block", "number", tip, "hash", children[i], "parent", child.ParentHash)
|
||||
DeleteBlock(batch, children[i], tip)
|
||||
}
|
||||
dangling = children
|
||||
tip++
|
||||
}
|
||||
if err := batch.Write(); err != nil {
|
||||
log.Crit("Failed to delete dangling side blocks", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Log something friendly for the user
|
||||
context := []interface{}{
|
||||
"blocks", frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", frozen - 1,
|
||||
|
||||
@@ -127,6 +127,11 @@ func newFreezerTable(path, name string, disableSnappy, readonly bool) (*freezerT
|
||||
return newTable(path, name, metrics.NilMeter{}, metrics.NilMeter{}, metrics.NilGauge{}, freezerTableSize, disableSnappy, readonly)
|
||||
}
|
||||
|
||||
// newAdditionTable opens the given path as a addition table.
|
||||
func newAdditionTable(path, name string, disableSnappy, readonly bool) (*freezerTable, error) {
|
||||
return openAdditionTable(path, name, metrics.NilMeter{}, metrics.NilMeter{}, metrics.NilGauge{}, freezerTableSize, disableSnappy, readonly)
|
||||
}
|
||||
|
||||
// newTable opens a freezer table, creating the data and index files if they are
|
||||
// non-existent. Both files are truncated to the shortest common length to ensure
|
||||
// they don't go out of sync.
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
@@ -66,28 +68,49 @@ func newPrunedFreezer(datadir string, db ethdb.KeyValueStore, offset uint64) (*p
|
||||
|
||||
// repair init frozen , compatible disk-ancientdb and pruner-block-tool.
|
||||
func (f *prunedfreezer) repair(datadir string) error {
|
||||
offset := atomic.LoadUint64(&f.frozen)
|
||||
// compatible freezer
|
||||
min := uint64(math.MaxUint64)
|
||||
minItems := uint64(math.MaxUint64)
|
||||
for name, disableSnappy := range chainFreezerNoSnappy {
|
||||
table, err := newFreezerTable(datadir, name, disableSnappy, false)
|
||||
var (
|
||||
table *freezerTable
|
||||
err error
|
||||
)
|
||||
if slices.Contains(additionTables, name) {
|
||||
table, err = newAdditionTable(datadir, name, disableSnappy, false)
|
||||
} else {
|
||||
table, err = newFreezerTable(datadir, name, disableSnappy, false)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// addition tables only align head
|
||||
if slices.Contains(additionTables, name) {
|
||||
if EmptyTable(table) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
items := table.items.Load()
|
||||
if min > items {
|
||||
min = items
|
||||
if minItems > items {
|
||||
minItems = items
|
||||
}
|
||||
table.Close()
|
||||
}
|
||||
log.Info("Read ancientdb item counts", "items", min)
|
||||
offset += min
|
||||
|
||||
if frozen := ReadFrozenOfAncientFreezer(f.db); frozen > offset {
|
||||
offset = frozen
|
||||
// If minItems is non-zero, it indicates that the chain freezer was previously enabled, and we should use minItems as the current frozen value.
|
||||
// If minItems is zero, it indicates that the pruneAncient was previously enabled, and we should continue using frozen
|
||||
// (retrieved from CurrentAncientFreezer) as the current frozen value.
|
||||
offset := minItems
|
||||
if offset == 0 {
|
||||
// no item in ancientDB, init `offset` to the `f.frozen`
|
||||
offset = atomic.LoadUint64(&f.frozen)
|
||||
}
|
||||
log.Info("Read ancientdb item counts", "items", minItems, "offset", offset)
|
||||
|
||||
atomic.StoreUint64(&f.frozen, offset)
|
||||
// FrozenOfAncientFreezer is the progress of the last prune-freezer freeze.
|
||||
frozenInDB := ReadFrozenOfAncientFreezer(f.db)
|
||||
maxOffset := max(offset, frozenInDB)
|
||||
|
||||
atomic.StoreUint64(&f.frozen, maxOffset)
|
||||
if err := f.Sync(); err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -299,9 +322,8 @@ func (f *prunedfreezer) freeze() {
|
||||
log.Error("Append ancient err", "number", f.frozen, "hash", hash, "err", err)
|
||||
break
|
||||
}
|
||||
if hash != (common.Hash{}) {
|
||||
ancients = append(ancients, hash)
|
||||
}
|
||||
// may include common.Hash{}, will be delete in gcKvStore
|
||||
ancients = append(ancients, hash)
|
||||
}
|
||||
// Batch of blocks have been frozen, flush them before wiping from leveldb
|
||||
if err := f.Sync(); err != nil {
|
||||
|
||||
@@ -40,6 +40,9 @@ var (
|
||||
// headFastBlockKey tracks the latest known incomplete block's hash during fast sync.
|
||||
headFastBlockKey = []byte("LastFast")
|
||||
|
||||
// headFinalizedBlockKey tracks the latest known finalized block hash.
|
||||
headFinalizedBlockKey = []byte("LastFinalized")
|
||||
|
||||
// persistentStateIDKey tracks the id of latest stored state(for path-based only).
|
||||
persistentStateIDKey = []byte("LastStateID")
|
||||
|
||||
|
||||
@@ -27,6 +27,26 @@ type table struct {
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (t *table) BlockStoreReader() ethdb.Reader {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *table) BlockStoreWriter() ethdb.Writer {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *table) BlockStore() ethdb.Database {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *table) SetBlockStore(block ethdb.Database) {
|
||||
panic("not implement")
|
||||
}
|
||||
|
||||
func (t *table) HasSeparateBlockStore() bool {
|
||||
panic("not implement")
|
||||
}
|
||||
|
||||
// NewTable returns a database object that prefixes all keys with a given string.
|
||||
func NewTable(db ethdb.Database, prefix string) ethdb.Database {
|
||||
return &table{
|
||||
@@ -231,6 +251,10 @@ func (t *table) SetStateStore(state ethdb.Database) {
|
||||
panic("not implement")
|
||||
}
|
||||
|
||||
func (t *table) GetStateStore() ethdb.Database {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *table) StateStoreReader() ethdb.Reader {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -232,6 +232,7 @@ func pruneAll(maindb ethdb.Database, g *core.Genesis) error {
|
||||
}
|
||||
log.Info("Database compaction finished", "elapsed", common.PrettyDuration(time.Since(cstart)))
|
||||
}
|
||||
// TODO:: ignore, versa has its own prunner
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(maindb), nil)
|
||||
for addr, account := range g.Alloc {
|
||||
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
|
||||
@@ -382,7 +383,7 @@ func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace str
|
||||
log.Info("chainDB opened successfully")
|
||||
|
||||
// Get the number of items in old ancient db.
|
||||
itemsOfAncient, err := chainDb.ItemAmountInAncient()
|
||||
itemsOfAncient, err := chainDb.BlockStore().ItemAmountInAncient()
|
||||
log.Info("the number of items in ancientDB is ", "itemsOfAncient", itemsOfAncient)
|
||||
|
||||
// If we can't access the freezer or it's empty, abort.
|
||||
@@ -402,7 +403,7 @@ func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace str
|
||||
|
||||
var oldOffSet uint64
|
||||
if interrupt {
|
||||
// The interrupt scecario within this function is specific for old and new ancientDB exsisted concurrently,
|
||||
// The interrupt scecario within this function is specific for old and new ancientDB existed concurrently,
|
||||
// should use last version of offset for oldAncientDB, because current offset is
|
||||
// actually of the new ancientDB_Backup, but what we want is the offset of ancientDB being backup.
|
||||
oldOffSet = rawdb.ReadOffSetOfLastAncientFreezer(chainDb)
|
||||
|
||||
@@ -205,6 +205,8 @@ type Tree struct {
|
||||
// state trie.
|
||||
// - otherwise, the entire snapshot is considered invalid and will be recreated on
|
||||
// a background thread.
|
||||
//
|
||||
// TODO:: if use versa, set SnapshotLimit == 0, will forbidden to use
|
||||
func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, root common.Hash, cap int, withoutTrie bool) (*Tree, error) {
|
||||
snap := &Tree{
|
||||
config: config,
|
||||
|
||||
@@ -933,8 +933,8 @@ func (s *StateDB) copyInternal(doPrefetch bool) *StateDB {
|
||||
// along with their original values.
|
||||
state.accounts = copySet(s.accounts)
|
||||
state.storages = copy2DSet(s.storages)
|
||||
state.accountsOrigin = copySet(state.accountsOrigin)
|
||||
state.storagesOrigin = copy2DSet(state.storagesOrigin)
|
||||
state.accountsOrigin = copySet(s.accountsOrigin)
|
||||
state.storagesOrigin = copy2DSet(s.storagesOrigin)
|
||||
|
||||
// Deep copy the logs occurred in the scope of block
|
||||
for hash, logs := range s.logs {
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
// NewStateSync creates a new state trie download scheduler.
|
||||
func NewStateSync(root common.Hash, database ethdb.KeyValueReader, onLeaf func(keys [][]byte, leaf []byte) error, scheme string) *trie.Sync {
|
||||
func NewStateSync(root common.Hash, database ethdb.Database, onLeaf func(keys [][]byte, leaf []byte) error, scheme string) *trie.Sync {
|
||||
// Register the storage slot callback if the external callback is specified.
|
||||
var onSlot func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error
|
||||
if onLeaf != nil {
|
||||
|
||||
@@ -268,7 +268,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, s
|
||||
}
|
||||
}
|
||||
batch := dstDb.NewBatch()
|
||||
if err := sched.Commit(batch); err != nil {
|
||||
if err := sched.Commit(batch, nil); err != nil {
|
||||
t.Fatalf("failed to commit data: %v", err)
|
||||
}
|
||||
batch.Write()
|
||||
@@ -369,7 +369,7 @@ func testIterativeDelayedStateSync(t *testing.T, scheme string) {
|
||||
nodeProcessed = len(nodeResults)
|
||||
}
|
||||
batch := dstDb.NewBatch()
|
||||
if err := sched.Commit(batch); err != nil {
|
||||
if err := sched.Commit(batch, nil); err != nil {
|
||||
t.Fatalf("failed to commit data: %v", err)
|
||||
}
|
||||
batch.Write()
|
||||
@@ -469,7 +469,7 @@ func testIterativeRandomStateSync(t *testing.T, count int, scheme string) {
|
||||
}
|
||||
}
|
||||
batch := dstDb.NewBatch()
|
||||
if err := sched.Commit(batch); err != nil {
|
||||
if err := sched.Commit(batch, nil); err != nil {
|
||||
t.Fatalf("failed to commit data: %v", err)
|
||||
}
|
||||
batch.Write()
|
||||
@@ -575,7 +575,7 @@ func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) {
|
||||
}
|
||||
}
|
||||
batch := dstDb.NewBatch()
|
||||
if err := sched.Commit(batch); err != nil {
|
||||
if err := sched.Commit(batch, nil); err != nil {
|
||||
t.Fatalf("failed to commit data: %v", err)
|
||||
}
|
||||
batch.Write()
|
||||
@@ -688,7 +688,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) {
|
||||
}
|
||||
}
|
||||
batch := dstDb.NewBatch()
|
||||
if err := sched.Commit(batch); err != nil {
|
||||
if err := sched.Commit(batch, nil); err != nil {
|
||||
t.Fatalf("failed to commit data: %v", err)
|
||||
}
|
||||
batch.Write()
|
||||
|
||||
1
core/systemcontracts/bruno/chapel/ValidatorContract
Normal file
1
core/systemcontracts/bruno/chapel/ValidatorContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/bruno/mainnet/ValidatorContract
Normal file
1
core/systemcontracts/bruno/mainnet/ValidatorContract
Normal file
File diff suppressed because one or more lines are too long
15
core/systemcontracts/bruno/types.go
Normal file
15
core/systemcontracts/bruno/types.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package bruno
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// contract codes for Mainnet upgrade
|
||||
var (
|
||||
//go:embed mainnet/ValidatorContract
|
||||
MainnetValidatorContract string
|
||||
)
|
||||
|
||||
// contract codes for Chapel upgrade
|
||||
var (
|
||||
//go:embed chapel/ValidatorContract
|
||||
ChapelValidatorContract string
|
||||
)
|
||||
1
core/systemcontracts/euler/chapel/SlashContract
Normal file
1
core/systemcontracts/euler/chapel/SlashContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/euler/chapel/ValidatorContract
Normal file
1
core/systemcontracts/euler/chapel/ValidatorContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/euler/mainnet/SlashContract
Normal file
1
core/systemcontracts/euler/mainnet/SlashContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/euler/mainnet/ValidatorContract
Normal file
1
core/systemcontracts/euler/mainnet/ValidatorContract
Normal file
File diff suppressed because one or more lines are too long
19
core/systemcontracts/euler/types.go
Normal file
19
core/systemcontracts/euler/types.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package euler
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// contract codes for Mainnet upgrade
|
||||
var (
|
||||
//go:embed mainnet/ValidatorContract
|
||||
MainnetValidatorContract string
|
||||
//go:embed mainnet/SlashContract
|
||||
MainnetSlashContract string
|
||||
)
|
||||
|
||||
// contract codes for Chapel upgrade
|
||||
var (
|
||||
//go:embed chapel/ValidatorContract
|
||||
ChapelValidatorContract string
|
||||
//go:embed chapel/SlashContract
|
||||
ChapelSlashContract string
|
||||
)
|
||||
1
core/systemcontracts/feynman/chapel/CrossChainContract
Normal file
1
core/systemcontracts/feynman/chapel/CrossChainContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/GovHubContract
Normal file
1
core/systemcontracts/feynman/chapel/GovHubContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/GovTokenContract
Normal file
1
core/systemcontracts/feynman/chapel/GovTokenContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/GovernorContract
Normal file
1
core/systemcontracts/feynman/chapel/GovernorContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/SlashContract
Normal file
1
core/systemcontracts/feynman/chapel/SlashContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/StakeCreditContract
Normal file
1
core/systemcontracts/feynman/chapel/StakeCreditContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/StakeHubContract
Normal file
1
core/systemcontracts/feynman/chapel/StakeHubContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/StakingContract
Normal file
1
core/systemcontracts/feynman/chapel/StakingContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/TimelockContract
Normal file
1
core/systemcontracts/feynman/chapel/TimelockContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/TokenHubContract
Normal file
1
core/systemcontracts/feynman/chapel/TokenHubContract
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/chapel/ValidatorContract
Normal file
1
core/systemcontracts/feynman/chapel/ValidatorContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/CrossChainContract
Normal file
1
core/systemcontracts/feynman/mainnet/CrossChainContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/GovHubContract
Normal file
1
core/systemcontracts/feynman/mainnet/GovHubContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/GovTokenContract
Normal file
1
core/systemcontracts/feynman/mainnet/GovTokenContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/GovernorContract
Normal file
1
core/systemcontracts/feynman/mainnet/GovernorContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/SlashContract
Normal file
1
core/systemcontracts/feynman/mainnet/SlashContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/StakeCreditContract
Normal file
1
core/systemcontracts/feynman/mainnet/StakeCreditContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/StakeHubContract
Normal file
1
core/systemcontracts/feynman/mainnet/StakeHubContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/StakingContract
Normal file
1
core/systemcontracts/feynman/mainnet/StakingContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/TimelockContract
Normal file
1
core/systemcontracts/feynman/mainnet/TimelockContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/TokenHubContract
Normal file
1
core/systemcontracts/feynman/mainnet/TokenHubContract
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
core/systemcontracts/feynman/mainnet/ValidatorContract
Normal file
1
core/systemcontracts/feynman/mainnet/ValidatorContract
Normal file
File diff suppressed because one or more lines are too long
59
core/systemcontracts/feynman/types.go
Normal file
59
core/systemcontracts/feynman/types.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package feynman
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// contract codes for Mainnet upgrade
|
||||
var (
|
||||
//go:embed mainnet/ValidatorContract
|
||||
MainnetValidatorContract string
|
||||
//go:embed mainnet/SlashContract
|
||||
MainnetSlashContract string
|
||||
//go:embed mainnet/TokenHubContract
|
||||
MainnetTokenHubContract string
|
||||
//go:embed mainnet/GovHubContract
|
||||
MainnetGovHubContract string
|
||||
//go:embed mainnet/CrossChainContract
|
||||
MainnetCrossChainContract string
|
||||
//go:embed mainnet/StakingContract
|
||||
MainnetStakingContract string
|
||||
//go:embed mainnet/StakeHubContract
|
||||
MainnetStakeHubContract string
|
||||
//go:embed mainnet/StakeCreditContract
|
||||
MainnetStakeCreditContract string
|
||||
//go:embed mainnet/GovernorContract
|
||||
MainnetGovernorContract string
|
||||
//go:embed mainnet/GovTokenContract
|
||||
MainnetGovTokenContract string
|
||||
//go:embed mainnet/TimelockContract
|
||||
MainnetTimelockContract string
|
||||
//go:embed mainnet/TokenRecoverPortalContract
|
||||
MainnetTokenRecoverPortalContract string
|
||||
)
|
||||
|
||||
// contract codes for Chapel upgrade
|
||||
var (
|
||||
//go:embed chapel/ValidatorContract
|
||||
ChapelValidatorContract string
|
||||
//go:embed chapel/SlashContract
|
||||
ChapelSlashContract string
|
||||
//go:embed chapel/TokenHubContract
|
||||
ChapelTokenHubContract string
|
||||
//go:embed chapel/GovHubContract
|
||||
ChapelGovHubContract string
|
||||
//go:embed chapel/CrossChainContract
|
||||
ChapelCrossChainContract string
|
||||
//go:embed chapel/StakingContract
|
||||
ChapelStakingContract string
|
||||
//go:embed chapel/StakeHubContract
|
||||
ChapelStakeHubContract string
|
||||
//go:embed chapel/StakeCreditContract
|
||||
ChapelStakeCreditContract string
|
||||
//go:embed chapel/GovernorContract
|
||||
ChapelGovernorContract string
|
||||
//go:embed chapel/GovTokenContract
|
||||
ChapelGovTokenContract string
|
||||
//go:embed chapel/TimelockContract
|
||||
ChapelTimelockContract string
|
||||
//go:embed chapel/TokenRecoverPortalContract
|
||||
ChapelTokenRecoverPortalContract string
|
||||
)
|
||||
1
core/systemcontracts/feynman_fix/chapel/StakeHubContract
Normal file
1
core/systemcontracts/feynman_fix/chapel/StakeHubContract
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
11
core/systemcontracts/feynman_fix/types.go
Normal file
11
core/systemcontracts/feynman_fix/types.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package feynman_fix
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// contract codes for Chapel upgrade
|
||||
var (
|
||||
//go:embed chapel/ValidatorContract
|
||||
ChapelValidatorContract string
|
||||
//go:embed chapel/StakeHubContract
|
||||
ChapelStakeHubContract string
|
||||
)
|
||||
1
core/systemcontracts/gibbs/chapel/StakingContract
Normal file
1
core/systemcontracts/gibbs/chapel/StakingContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/gibbs/chapel/TokenHubContract
Normal file
1
core/systemcontracts/gibbs/chapel/TokenHubContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/gibbs/mainnet/StakingContract
Normal file
1
core/systemcontracts/gibbs/mainnet/StakingContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/gibbs/mainnet/TokenHubContract
Normal file
1
core/systemcontracts/gibbs/mainnet/TokenHubContract
Normal file
File diff suppressed because one or more lines are too long
19
core/systemcontracts/gibbs/types.go
Normal file
19
core/systemcontracts/gibbs/types.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package gibbs
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// contract codes for Chapel upgrade
|
||||
var (
|
||||
//go:embed chapel/TokenHubContract
|
||||
ChapelTokenHubContract string
|
||||
//go:embed chapel/StakingContract
|
||||
ChapelStakingContract string
|
||||
)
|
||||
|
||||
// contract codes for Mainnet upgrade
|
||||
var (
|
||||
//go:embed mainnet/TokenHubContract
|
||||
MainnetTokenHubContract string
|
||||
//go:embed mainnet/StakingContract
|
||||
MainnetStakingContract string
|
||||
)
|
||||
1
core/systemcontracts/haber_fix/chapel/SlashContract
Normal file
1
core/systemcontracts/haber_fix/chapel/SlashContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/haber_fix/chapel/ValidatorContract
Normal file
1
core/systemcontracts/haber_fix/chapel/ValidatorContract
Normal file
File diff suppressed because one or more lines are too long
1
core/systemcontracts/haber_fix/mainnet/SlashContract
Normal file
1
core/systemcontracts/haber_fix/mainnet/SlashContract
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user