Compare commits
133 Commits
v1.4.4-bet
...
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 | ||
|
|
a05724588f | ||
|
|
009df5a121 | ||
|
|
d7836bfe98 | ||
|
|
f4bad20447 | ||
|
|
a75e82367d | ||
|
|
26f50099f4 | ||
|
|
060e5c6b34 | ||
|
|
4e9f699068 | ||
|
|
42a0236587 | ||
|
|
48f58a50bb | ||
|
|
e4688e4e7a | ||
|
|
75a03f420f |
20
.github/CODEOWNERS
vendored
20
.github/CODEOWNERS
vendored
@@ -1,3 +1,21 @@
|
|||||||
# Lines starting with '#' are comments.
|
# Lines starting with '#' are comments.
|
||||||
# Each line is a file pattern followed by one or more owners.
|
# 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
|
||||||
141
CHANGELOG.md
141
CHANGELOG.md
@@ -1,4 +1,145 @@
|
|||||||
# Changelog
|
# 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
|
||||||
|
|
||||||
|
### IMPROVEMENT
|
||||||
|
* [\#2333](https://github.com/bnb-chain/bsc/pull/2333) remove code that will not be executed
|
||||||
|
* [\#2369](https://github.com/bnb-chain/bsc/pull/2369) core: stateDb has no trie and no snap return err
|
||||||
|
|
||||||
|
### BUGFIX
|
||||||
|
* [\#2359](https://github.com/bnb-chain/bsc/pull/2359) triedb: do not open state freezer under notries
|
||||||
|
|
||||||
## v1.4.4
|
## v1.4.4
|
||||||
### FEATURE
|
### FEATURE
|
||||||
* [\#2279](https://github.com/bnb-chain/bsc/pull/2279) BlobTx: implement EIP-4844 on BSC
|
* [\#2279](https://github.com/bnb-chain/bsc/pull/2279) BlobTx: implement EIP-4844 on BSC
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/
|
|||||||
|
|
||||||
EXPOSE 8545 8546 30303 30303/udp
|
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 COMMIT=""
|
||||||
ARG VERSION=""
|
ARG VERSION=""
|
||||||
ARG BUILDNUM=""
|
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.
|
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.
|
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.
|
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
|
### Light Client of BNB Beacon Chain
|
||||||
@@ -149,13 +149,11 @@ unzip testnet.zip
|
|||||||
#### 3. Download snapshot
|
#### 3. Download snapshot
|
||||||
Download latest chaindata snapshot from [here](https://github.com/bnb-chain/bsc-snapshots). Follow the guide to structure your files.
|
Download latest chaindata snapshot from [here](https://github.com/bnb-chain/bsc-snapshots). Follow the guide to structure your files.
|
||||||
|
|
||||||
Note: If you 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
|
#### 4. Start a full node
|
||||||
```shell
|
```shell
|
||||||
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0
|
./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --history.transactions 0
|
||||||
|
|
||||||
## 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
|
## 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
|
./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
|
#### 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
|
*Note: Although some internal protective measures prevent transactions from
|
||||||
crossing over between the main network and test network, you should always
|
crossing over between the main network and test network, you should always
|
||||||
|
|||||||
2
accounts/external/backend.go
vendored
2
accounts/external/backend.go
vendored
@@ -163,7 +163,7 @@ func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, d
|
|||||||
hexutil.Encode(data)); err != nil {
|
hexutil.Encode(data)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// If V is on 27/28-form, convert to to 0/1 for Clique and Parlia
|
// If V is on 27/28-form, convert to 0/1 for Clique and Parlia
|
||||||
if (mimeType == accounts.MimetypeClique || mimeType == accounts.MimetypeParlia) && (res[64] == 27 || res[64] == 28) {
|
if (mimeType == accounts.MimetypeClique || mimeType == accounts.MimetypeParlia) && (res[64] == 27 || res[64] == 28) {
|
||||||
res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique and Parlia use
|
res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique and Parlia use
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
func waitWatcherStart(ks *KeyStore) bool {
|
||||||
// On systems where file watch is not supported, just return "ok".
|
// On systems where file watch is not supported, just return "ok".
|
||||||
if !ks.cache.watcher.enabled() {
|
if !ks.cache.watcher.enabled() {
|
||||||
@@ -358,7 +358,6 @@ func TestUpdatedKeyfileContents(t *testing.T) {
|
|||||||
// Now replace file contents
|
// Now replace file contents
|
||||||
if err := forceCopyFile(file, cachetestAccounts[1].URL.Path); err != nil {
|
if err := forceCopyFile(file, cachetestAccounts[1].URL.Path); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
wantAccounts = []accounts.Account{cachetestAccounts[1]}
|
wantAccounts = []accounts.Account{cachetestAccounts[1]}
|
||||||
wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file}
|
wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file}
|
||||||
@@ -374,7 +373,6 @@ func TestUpdatedKeyfileContents(t *testing.T) {
|
|||||||
// Now replace file contents again
|
// Now replace file contents again
|
||||||
if err := forceCopyFile(file, cachetestAccounts[2].URL.Path); err != nil {
|
if err := forceCopyFile(file, cachetestAccounts[2].URL.Path); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
wantAccounts = []accounts.Account{cachetestAccounts[2]}
|
wantAccounts = []accounts.Account{cachetestAccounts[2]}
|
||||||
wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file}
|
wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file}
|
||||||
@@ -390,7 +388,6 @@ func TestUpdatedKeyfileContents(t *testing.T) {
|
|||||||
// Now replace file contents with crap
|
// Now replace file contents with crap
|
||||||
if err := os.WriteFile(file, []byte("foo"), 0600); err != nil {
|
if err := os.WriteFile(file, []byte("foo"), 0600); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if err := waitForAccounts([]accounts.Account{}, ks); err != nil {
|
if err := waitForAccounts([]accounts.Account{}, ks); err != nil {
|
||||||
t.Errorf("Emptying account file failed")
|
t.Errorf("Emptying account file failed")
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ func TestWalletNotifications(t *testing.T) {
|
|||||||
checkEvents(t, wantEvents, events)
|
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) {
|
func TestImportECDSA(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, ks := tmpKeyStore(t, true)
|
_, 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) {
|
func TestImportExport(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, ks := tmpKeyStore(t, true)
|
_, 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
|
// Re-create statedb instance with new root upon the updated database
|
||||||
// for accessing latest states.
|
// for accessing latest states.
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
statedb, err = state.New(root, statedb.Database(), nil)
|
statedb, err = state.New(root, statedb.Database(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
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 {
|
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})
|
sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
||||||
for addr, a := range accounts {
|
for addr, a := range accounts {
|
||||||
statedb.SetCode(addr, a.Code)
|
statedb.SetCode(addr, a.Code)
|
||||||
@@ -372,6 +375,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
|
|||||||
statedb.Finalise(false)
|
statedb.Finalise(false)
|
||||||
statedb.AccountsIntermediateRoot()
|
statedb.AccountsIntermediateRoot()
|
||||||
root, _, _ := statedb.Commit(0, nil)
|
root, _, _ := statedb.Commit(0, nil)
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
statedb, _ = state.New(root, sdb, nil)
|
statedb, _ = state.New(root, sdb, nil)
|
||||||
return statedb
|
return statedb
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,12 +148,14 @@ func runCmd(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
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{
|
triedb := triedb.NewDatabase(db, &triedb.Config{
|
||||||
Preimages: preimages,
|
Preimages: preimages,
|
||||||
HashDB: hashdb.Defaults,
|
HashDB: hashdb.Defaults,
|
||||||
})
|
})
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
genesis := genesisConfig.MustCommit(db, triedb)
|
genesis := genesisConfig.MustCommit(db, triedb)
|
||||||
|
// TODO:: ignore cmd, internally compatible with versa is sufficient.
|
||||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
||||||
statedb, _ = state.New(genesis.Root(), sdb, nil)
|
statedb, _ = state.New(genesis.Root(), sdb, nil)
|
||||||
chainConfig = genesisConfig.Config
|
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)
|
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||||
}
|
}
|
||||||
if dump { // Dump any state to aid debugging
|
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)
|
cpy, _ := state.New(root, tstate.StateDB.Database(), nil)
|
||||||
dump := cpy.RawDump(nil)
|
dump := cpy.RawDump(nil)
|
||||||
result.State = &dump
|
result.State = &dump
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
f.lock.Unlock()
|
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 !fund {
|
||||||
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(time.Until(timeout)))); err != nil { // nolint: gosimple
|
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)
|
log.Warn("Failed to send funding error to client", "err", err)
|
||||||
@@ -642,7 +642,7 @@ func (f *faucet) loop() {
|
|||||||
f.lock.RUnlock()
|
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 {
|
for {
|
||||||
select {
|
select {
|
||||||
case head := <-heads:
|
case head := <-heads:
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func TestAttachWithHeaders(t *testing.T) {
|
|||||||
// This is fixed in a follow-up PR.
|
// 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.
|
// that custom headers are forwarded to the target.
|
||||||
func TestRemoteDbWithHeaders(t *testing.T) {
|
func TestRemoteDbWithHeaders(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ import (
|
|||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/logrusorgru/aurora"
|
"github.com/logrusorgru/aurora"
|
||||||
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
||||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/v4/io/prompt"
|
"github.com/prysmaticlabs/prysm/v5/io/prompt"
|
||||||
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
|
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts"
|
"github.com/prysmaticlabs/prysm/v5/validator/accounts"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
|
"github.com/prysmaticlabs/prysm/v5/validator/accounts/iface"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/petnames"
|
"github.com/prysmaticlabs/prysm/v5/validator/accounts/petnames"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/wallet"
|
"github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/keymanager"
|
"github.com/prysmaticlabs/prysm/v5/validator/keymanager"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/keymanager/local"
|
"github.com/prysmaticlabs/prysm/v5/validator/keymanager/local"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
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/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/era"
|
"github.com/ethereum/go-ethereum/internal/era"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
@@ -61,8 +62,9 @@ var (
|
|||||||
ArgsUsage: "<genesisPath>",
|
ArgsUsage: "<genesisPath>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CachePreimagesFlag,
|
utils.CachePreimagesFlag,
|
||||||
utils.OverrideCancun,
|
utils.OverrideBohr,
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
|
utils.MultiDataBaseFlag,
|
||||||
}, utils.DatabaseFlags),
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The init command initializes a new genesis block and definition for the network.
|
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()
|
defer stack.Close()
|
||||||
|
|
||||||
var overrides core.ChainOverrides
|
var overrides core.ChainOverrides
|
||||||
if ctx.IsSet(utils.OverrideCancun.Name) {
|
if ctx.IsSet(utils.OverrideBohr.Name) {
|
||||||
v := ctx.Uint64(utils.OverrideCancun.Name)
|
v := ctx.Uint64(utils.OverrideBohr.Name)
|
||||||
overrides.OverrideCancun = &v
|
overrides.OverrideBohr = &v
|
||||||
}
|
}
|
||||||
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
||||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||||
@@ -267,15 +269,21 @@ func initGenesis(ctx *cli.Context) error {
|
|||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
// if the trie data dir has been set, new trie db with a new state database
|
// 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)
|
statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name+"/state", 0, 0, "", "", false, false, false, false)
|
||||||
if dbErr != nil {
|
if dbErr != nil {
|
||||||
utils.Fatalf("Failed to open separate trie database: %v", dbErr)
|
utils.Fatalf("Failed to open separate trie database: %v", dbErr)
|
||||||
}
|
}
|
||||||
chaindb.SetStateStore(statediskdb)
|
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()
|
defer triedb.Close()
|
||||||
|
|
||||||
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||||
@@ -473,6 +481,13 @@ func dumpGenesis(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
continue
|
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)
|
genesis, err := core.ReadGenesis(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("failed to read genesis: %s", err)
|
utils.Fatalf("failed to read genesis: %s", err)
|
||||||
@@ -500,10 +515,16 @@ func importChain(ctx *cli.Context) error {
|
|||||||
// Start system runtime metrics collection
|
// Start system runtime metrics collection
|
||||||
go metrics.CollectProcessMetrics(3 * time.Second)
|
go metrics.CollectProcessMetrics(3 * time.Second)
|
||||||
|
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, cfg := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
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()
|
defer db.Close()
|
||||||
|
|
||||||
// Start periodically gathering memory profiles
|
// Start periodically gathering memory profiles
|
||||||
@@ -757,8 +778,9 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Use latest
|
// Use latest
|
||||||
|
// TODO:: if versa, scheme = VersaScheme
|
||||||
if scheme == rawdb.PathScheme {
|
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()
|
defer triedb.Close()
|
||||||
if stateRoot := triedb.Head(); stateRoot != (common.Hash{}) {
|
if stateRoot := triedb.Head(); stateRoot != (common.Hash{}) {
|
||||||
header.Root = stateRoot
|
header.Root = stateRoot
|
||||||
@@ -808,9 +830,11 @@ func dump(ctx *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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()
|
defer triedb.Close()
|
||||||
|
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -828,7 +852,8 @@ func dumpAllRootHashInPath(ctx *cli.Context) error {
|
|||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer db.Close()
|
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()
|
defer triedb.Close()
|
||||||
|
|
||||||
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db)
|
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)
|
params.RialtoGenesisHash = common.HexToHash(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(utils.OverrideCancun.Name) {
|
if ctx.IsSet(utils.OverrideBohr.Name) {
|
||||||
v := ctx.Uint64(utils.OverrideCancun.Name)
|
v := ctx.Uint64(utils.OverrideBohr.Name)
|
||||||
cfg.Eth.OverrideCancun = &v
|
cfg.Eth.OverrideBohr = &v
|
||||||
}
|
}
|
||||||
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
||||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||||
cfg.Eth.OverrideVerkle = &v
|
cfg.Eth.OverrideVerkle = &v
|
||||||
}
|
}
|
||||||
if ctx.IsSet(utils.OverrideFeynman.Name) {
|
|
||||||
v := ctx.Uint64(utils.OverrideFeynman.Name)
|
|
||||||
cfg.Eth.OverrideFeynman = &v
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.OverrideFeynmanFix.Name) {
|
|
||||||
v := ctx.Uint64(utils.OverrideFeynmanFix.Name)
|
|
||||||
cfg.Eth.OverrideFeynmanFix = &v
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.OverrideFullImmutabilityThreshold.Name) {
|
if ctx.IsSet(utils.OverrideFullImmutabilityThreshold.Name) {
|
||||||
params.FullImmutabilityThreshold = ctx.Uint64(utils.OverrideFullImmutabilityThreshold.Name)
|
params.FullImmutabilityThreshold = ctx.Uint64(utils.OverrideFullImmutabilityThreshold.Name)
|
||||||
downloader.FullMaxForkAncestry = 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) {
|
if ctx.IsSet(utils.OverrideDefaultExtraReserveForBlobRequests.Name) {
|
||||||
params.DefaultExtraReserveForBlobRequests = ctx.Uint64(utils.OverrideDefaultExtraReserveForBlobRequests.Name)
|
params.DefaultExtraReserveForBlobRequests = ctx.Uint64(utils.OverrideDefaultExtraReserveForBlobRequests.Name)
|
||||||
}
|
}
|
||||||
if ctx.IsSet(utils.SeparateDBFlag.Name) && !stack.IsSeparatedDB() {
|
if ctx.IsSet(utils.OverrideBreatheBlockInterval.Name) {
|
||||||
utils.Fatalf("Failed to locate separate database subdirectory when separatedb parameter has been set")
|
params.BreatheBlockInterval = ctx.Uint64(utils.OverrideBreatheBlockInterval.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
||||||
|
|
||||||
// Create gauge with geth system and build information
|
// Create gauge with geth system and build information
|
||||||
|
|||||||
@@ -106,12 +106,12 @@ Remove blockchain and state databases`,
|
|||||||
dbInspectTrieCmd = &cli.Command{
|
dbInspectTrieCmd = &cli.Command{
|
||||||
Action: inspectTrie,
|
Action: inspectTrie,
|
||||||
Name: "inspect-trie",
|
Name: "inspect-trie",
|
||||||
ArgsUsage: "<blocknum> <jobnum>",
|
ArgsUsage: "<blocknum> <jobnum> <topn>",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.SyncModeFlag,
|
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.`,
|
Description: `This commands iterates the entrie WorldState.`,
|
||||||
}
|
}
|
||||||
dbCheckStateContentCmd = &cli.Command{
|
dbCheckStateContentCmd = &cli.Command{
|
||||||
@@ -386,6 +386,7 @@ func inspectTrie(ctx *cli.Context) error {
|
|||||||
blockNumber uint64
|
blockNumber uint64
|
||||||
trieRootHash common.Hash
|
trieRootHash common.Hash
|
||||||
jobnum uint64
|
jobnum uint64
|
||||||
|
topN uint64
|
||||||
)
|
)
|
||||||
|
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
@@ -405,24 +406,37 @@ func inspectTrie(ctx *cli.Context) error {
|
|||||||
var err error
|
var err error
|
||||||
blockNumber, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
|
blockNumber, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
|
||||||
if err != nil {
|
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 {
|
if ctx.NArg() == 1 {
|
||||||
jobnum = 1000
|
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 {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
jobnum, err = strconv.ParseUint(ctx.Args().Get(1), 10, 64)
|
jobnum, err = strconv.ParseUint(ctx.Args().Get(1), 10, 64)
|
||||||
if err != nil {
|
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 {
|
if blockNumber != math.MaxUint64 {
|
||||||
headerBlockHash = rawdb.ReadCanonicalHash(db, blockNumber)
|
headerBlockHash = rawdb.ReadCanonicalHash(db, blockNumber)
|
||||||
if headerBlockHash == (common.Hash{}) {
|
if headerBlockHash == (common.Hash{}) {
|
||||||
return errors.New("ReadHeadBlockHash empry hash")
|
return errors.New("ReadHeadBlockHash empty hash")
|
||||||
}
|
}
|
||||||
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
|
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
|
||||||
trieRootHash = blockHeader.Root
|
trieRootHash = blockHeader.Root
|
||||||
@@ -436,19 +450,21 @@ func inspectTrie(ctx *cli.Context) error {
|
|||||||
var config *triedb.Config
|
var config *triedb.Config
|
||||||
if dbScheme == rawdb.PathScheme {
|
if dbScheme == rawdb.PathScheme {
|
||||||
config = &triedb.Config{
|
config = &triedb.Config{
|
||||||
PathDB: pathdb.ReadOnly,
|
PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly),
|
||||||
|
Cache: 0,
|
||||||
}
|
}
|
||||||
} else if dbScheme == rawdb.HashScheme {
|
} else if dbScheme == rawdb.HashScheme {
|
||||||
config = triedb.HashDefaults
|
config = triedb.HashDefaults
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO:: ignore cmd
|
||||||
triedb := triedb.NewDatabase(db, config)
|
triedb := triedb.NewDatabase(db, config)
|
||||||
theTrie, err := trie.New(trie.TrieID(trieRootHash), triedb)
|
theTrie, err := trie.New(trie.TrieID(trieRootHash), triedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("fail to new trie tree, err: %v, rootHash: %v\n", err, trieRootHash.String())
|
fmt.Printf("fail to new trie tree, err: %v, rootHash: %v\n", err, trieRootHash.String())
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -493,7 +509,7 @@ func ancientInspect(ctx *cli.Context) error {
|
|||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true, true)
|
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
return rawdb.AncientInspect(db)
|
return rawdb.AncientInspect(db)
|
||||||
}
|
}
|
||||||
@@ -519,7 +535,7 @@ func checkStateContent(ctx *cli.Context) error {
|
|||||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
var (
|
var (
|
||||||
it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32)
|
it ethdb.Iterator
|
||||||
hasher = crypto.NewKeccakState()
|
hasher = crypto.NewKeccakState()
|
||||||
got = make([]byte, 32)
|
got = make([]byte, 32)
|
||||||
errs int
|
errs int
|
||||||
@@ -527,6 +543,11 @@ func checkStateContent(ctx *cli.Context) error {
|
|||||||
startTime = time.Now()
|
startTime = time.Now()
|
||||||
lastLog = 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() {
|
for it.Next() {
|
||||||
count++
|
count++
|
||||||
k := it.Key()
|
k := it.Key()
|
||||||
@@ -573,9 +594,11 @@ func dbStats(ctx *cli.Context) error {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
showLeveldbStats(db)
|
showLeveldbStats(db)
|
||||||
if db.StateStore() != nil {
|
if stack.CheckIfMultiDataBase() {
|
||||||
fmt.Println("show stats of state store")
|
fmt.Println("show stats of state store")
|
||||||
showLeveldbStats(db.StateStore())
|
showLeveldbStats(db.StateStore())
|
||||||
|
fmt.Println("show stats of block store")
|
||||||
|
showLeveldbStats(db.BlockStore())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -591,10 +614,11 @@ func dbCompact(ctx *cli.Context) error {
|
|||||||
log.Info("Stats before compaction")
|
log.Info("Stats before compaction")
|
||||||
showLeveldbStats(db)
|
showLeveldbStats(db)
|
||||||
|
|
||||||
statediskdb := db.StateStore()
|
if stack.CheckIfMultiDataBase() {
|
||||||
if statediskdb != nil {
|
|
||||||
fmt.Println("show stats of state store")
|
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")
|
log.Info("Triggering compaction")
|
||||||
@@ -603,8 +627,12 @@ func dbCompact(ctx *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if statediskdb != nil {
|
if stack.CheckIfMultiDataBase() {
|
||||||
if err := statediskdb.Compact(nil, nil); err != nil {
|
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)
|
log.Error("Compact err", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -612,9 +640,11 @@ func dbCompact(ctx *cli.Context) error {
|
|||||||
|
|
||||||
log.Info("Stats after compaction")
|
log.Info("Stats after compaction")
|
||||||
showLeveldbStats(db)
|
showLeveldbStats(db)
|
||||||
if statediskdb != nil {
|
if stack.CheckIfMultiDataBase() {
|
||||||
fmt.Println("show stats of state store after compaction")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@@ -635,18 +665,18 @@ func dbGet(ctx *cli.Context) error {
|
|||||||
log.Info("Could not decode the key", "error", err)
|
log.Info("Could not decode the key", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
opDb := db
|
||||||
statediskdb := db.StateStore()
|
if stack.CheckIfMultiDataBase() {
|
||||||
data, err := db.Get(key)
|
keyType := rawdb.DataTypeByKey(key)
|
||||||
if err != nil {
|
if keyType == rawdb.StateDataType {
|
||||||
// if separate trie db exist, try to get it from separate db
|
opDb = db.StateStore()
|
||||||
if statediskdb != nil {
|
} else if keyType == rawdb.BlockDataType {
|
||||||
statedata, dberr := statediskdb.Get(key)
|
opDb = db.BlockStore()
|
||||||
if dberr == nil {
|
|
||||||
fmt.Printf("key %#x: %#x\n", key, statedata)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := opDb.Get(key)
|
||||||
|
if err != nil {
|
||||||
log.Info("Get operation failed", "key", fmt.Sprintf("%#x", key), "error", err)
|
log.Info("Get operation failed", "key", fmt.Sprintf("%#x", key), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -809,11 +839,21 @@ func dbDelete(ctx *cli.Context) error {
|
|||||||
log.Info("Could not decode the key", "error", err)
|
log.Info("Could not decode the key", "error", err)
|
||||||
return 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 {
|
if err == nil {
|
||||||
fmt.Printf("Previous value: %#x\n", data)
|
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)
|
log.Info("Delete operation returned an error", "key", fmt.Sprintf("%#x", key), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -923,11 +963,22 @@ func dbPut(ctx *cli.Context) error {
|
|||||||
log.Info("Could not decode the value", "error", err)
|
log.Info("Could not decode the value", "error", err)
|
||||||
return 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 {
|
if err == nil {
|
||||||
fmt.Printf("Previous value: %#x\n", data)
|
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
|
// 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)
|
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
triedb := utils.MakeTrieDatabase(ctx, stack, db, false, true, false)
|
||||||
triedb := utils.MakeTrieDatabase(ctx, db, false, true, false)
|
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1019,7 +1069,7 @@ func freezerInspect(ctx *cli.Context) error {
|
|||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name))
|
ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name))
|
||||||
stack.Close()
|
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 {
|
func importLDBdata(ctx *cli.Context) error {
|
||||||
@@ -1159,7 +1209,7 @@ func showMetaData(ctx *cli.Context) error {
|
|||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
db := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
ancients, err := db.Ancients()
|
ancients, err := db.BlockStore().Ancients()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
|
fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
|
||||||
}
|
}
|
||||||
@@ -1206,7 +1256,7 @@ func hbss2pbss(ctx *cli.Context) error {
|
|||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
db := utils.MakeChainDatabase(ctx, stack, false, false)
|
db := utils.MakeChainDatabase(ctx, stack, false, false)
|
||||||
db.Sync()
|
db.BlockStore().Sync()
|
||||||
stateDiskDb := db.StateStore()
|
stateDiskDb := db.StateStore()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
@@ -1219,6 +1269,7 @@ func hbss2pbss(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
if lastStateID == 0 || force {
|
if lastStateID == 0 || force {
|
||||||
config := triedb.HashDefaults
|
config := triedb.HashDefaults
|
||||||
|
// TODO:: ignore cmd
|
||||||
triedb := triedb.NewDatabase(db, config)
|
triedb := triedb.NewDatabase(db, config)
|
||||||
triedb.Cap(0)
|
triedb.Cap(0)
|
||||||
log.Info("hbss2pbss triedb", "scheme", triedb.Scheme())
|
log.Info("hbss2pbss triedb", "scheme", triedb.Scheme())
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
@@ -70,13 +72,12 @@ var (
|
|||||||
utils.USBFlag,
|
utils.USBFlag,
|
||||||
utils.SmartCardDaemonPathFlag,
|
utils.SmartCardDaemonPathFlag,
|
||||||
utils.RialtoHash,
|
utils.RialtoHash,
|
||||||
utils.OverrideCancun,
|
utils.OverrideBohr,
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
utils.OverrideFeynman,
|
|
||||||
utils.OverrideFeynmanFix,
|
|
||||||
utils.OverrideFullImmutabilityThreshold,
|
utils.OverrideFullImmutabilityThreshold,
|
||||||
utils.OverrideMinBlocksForBlobRequests,
|
utils.OverrideMinBlocksForBlobRequests,
|
||||||
utils.OverrideDefaultExtraReserveForBlobRequests,
|
utils.OverrideDefaultExtraReserveForBlobRequests,
|
||||||
|
utils.OverrideBreatheBlockInterval,
|
||||||
utils.EnablePersonal,
|
utils.EnablePersonal,
|
||||||
utils.TxPoolLocalsFlag,
|
utils.TxPoolLocalsFlag,
|
||||||
utils.TxPoolNoLocalsFlag,
|
utils.TxPoolNoLocalsFlag,
|
||||||
@@ -103,6 +104,7 @@ var (
|
|||||||
utils.TransactionHistoryFlag,
|
utils.TransactionHistoryFlag,
|
||||||
utils.StateHistoryFlag,
|
utils.StateHistoryFlag,
|
||||||
utils.PathDBSyncFlag,
|
utils.PathDBSyncFlag,
|
||||||
|
utils.JournalFileFlag,
|
||||||
utils.LightServeFlag, // deprecated
|
utils.LightServeFlag, // deprecated
|
||||||
utils.LightIngressFlag, // deprecated
|
utils.LightIngressFlag, // deprecated
|
||||||
utils.LightEgressFlag, // deprecated
|
utils.LightEgressFlag, // deprecated
|
||||||
@@ -123,6 +125,7 @@ var (
|
|||||||
utils.CacheSnapshotFlag,
|
utils.CacheSnapshotFlag,
|
||||||
// utils.CacheNoPrefetchFlag,
|
// utils.CacheNoPrefetchFlag,
|
||||||
utils.CachePreimagesFlag,
|
utils.CachePreimagesFlag,
|
||||||
|
utils.MultiDataBaseFlag,
|
||||||
utils.PersistDiffFlag,
|
utils.PersistDiffFlag,
|
||||||
utils.DiffBlockFlag,
|
utils.DiffBlockFlag,
|
||||||
utils.PruneAncientDataFlag,
|
utils.PruneAncientDataFlag,
|
||||||
@@ -144,6 +147,7 @@ var (
|
|||||||
// utils.MinerNewPayloadTimeout,
|
// utils.MinerNewPayloadTimeout,
|
||||||
utils.NATFlag,
|
utils.NATFlag,
|
||||||
utils.NoDiscoverFlag,
|
utils.NoDiscoverFlag,
|
||||||
|
utils.PeerFilterPatternsFlag,
|
||||||
utils.DiscoveryV4Flag,
|
utils.DiscoveryV4Flag,
|
||||||
utils.DiscoveryV5Flag,
|
utils.DiscoveryV5Flag,
|
||||||
utils.InstanceFlag,
|
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
|
5. Networking is disabled; there is no listen-address, the maximum number of peers is set
|
||||||
to 0, and discovery is disabled.
|
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 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) {
|
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
|
// Set the gas price to the limits from the CLI and start mining
|
||||||
gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
|
gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
|
||||||
ethBackend.TxPool().SetGasTip(gasprice)
|
ethBackend.TxPool().SetGasTip(gasprice)
|
||||||
|
gasCeil := ethBackend.Miner().GasCeil()
|
||||||
|
if gasCeil > params.SystemTxsGas {
|
||||||
|
ethBackend.TxPool().SetMaxGas(gasCeil - params.SystemTxsGas)
|
||||||
|
}
|
||||||
if err := ethBackend.StartMining(); err != nil {
|
if err := ethBackend.StartMining(); err != nil {
|
||||||
utils.Fatalf("Failed to start mining: %v", err)
|
utils.Fatalf("Failed to start mining: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
kvdb.Close()
|
kvdb.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -155,6 +155,12 @@ func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemai
|
|||||||
triedb := triedb.NewDatabase(db, nil)
|
triedb := triedb.NewDatabase(db, nil)
|
||||||
defer triedb.Close()
|
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)
|
genesis := gspec.MustCommit(db, triedb)
|
||||||
// Initialize a fresh chain with only a genesis block
|
// Initialize a fresh chain with only a genesis block
|
||||||
blockchain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
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/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||||
cli "github.com/urfave/cli/v2"
|
cli "github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@ WARNING: it's only supported in hash mode(--state.scheme=hash)".
|
|||||||
geth offline prune-block for block data in ancientdb.
|
geth offline prune-block for block data in ancientdb.
|
||||||
The amount of blocks expected for remaining after prune can be specified via block-amount-reserved in this command,
|
The amount of blocks expected for remaining after prune can be specified via block-amount-reserved in this command,
|
||||||
will prune and only remain the specified amount of old block data in ancientdb.
|
will prune and only remain the specified amount of old block data in ancientdb.
|
||||||
the brief workflow is to backup the the number of this specified amount blocks backward in original ancientdb
|
the brief workflow is to backup the number of this specified amount blocks backward in original ancientdb
|
||||||
into new ancient_backup, then delete the original ancientdb dir and rename the ancient_backup to original one for replacement,
|
into new ancient_backup, then delete the original ancientdb dir and rename the ancient_backup to original one for replacement,
|
||||||
finally assemble the statedb and new ancientDb together.
|
finally assemble the statedb and new ancientDb together.
|
||||||
The purpose of doing it is because the block data will be moved into the ancient store when it
|
The purpose of doing it is because the block data will be moved into the ancient store when it
|
||||||
@@ -245,7 +247,17 @@ func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) {
|
|||||||
NoBuild: true,
|
NoBuild: true,
|
||||||
AsyncBuild: false,
|
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 {
|
if err != nil {
|
||||||
log.Error("snaptree error", "err", err)
|
log.Error("snaptree error", "err", err)
|
||||||
return nil, err // The relevant snapshot(s) might not exist
|
return nil, err // The relevant snapshot(s) might not exist
|
||||||
@@ -333,6 +345,9 @@ func pruneBlock(ctx *cli.Context) error {
|
|||||||
stack, config = makeConfigNode(ctx)
|
stack, config = makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
blockAmountReserved = ctx.Uint64(utils.BlockAmountReserved.Name)
|
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)
|
chaindb, err = accessDb(ctx, stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -355,7 +370,15 @@ func pruneBlock(ctx *cli.Context) error {
|
|||||||
if !ctx.IsSet(utils.AncientFlag.Name) {
|
if !ctx.IsSet(utils.AncientFlag.Name) {
|
||||||
return errors.New("datadir.ancient must be set")
|
return errors.New("datadir.ancient must be set")
|
||||||
} else {
|
} 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) {
|
if !filepath.IsAbs(oldAncientPath) {
|
||||||
// force absolute paths, which often fail due to the splicing of relative paths
|
// force absolute paths, which often fail due to the splicing of relative paths
|
||||||
return errors.New("datadir.ancient not abs path")
|
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 {
|
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
|
// after old ancientDB removal, this happened after backup successfully, so just rename the new ancientDB
|
||||||
if err := blockpruner.AncientDbReplacer(); err != nil {
|
if err := blockpruner.AncientDbReplacer(); err != nil {
|
||||||
log.Error("Failed to rename new ancient directory")
|
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")
|
log.Error("Failed to load head block")
|
||||||
return errors.New("no 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()
|
defer triedb.Close()
|
||||||
|
|
||||||
snapConfig := snapshot.Config{
|
snapConfig := snapshot.Config{
|
||||||
@@ -579,7 +602,7 @@ func traverseState(ctx *cli.Context) error {
|
|||||||
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
|
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||||
@@ -688,7 +711,7 @@ func traverseRawState(ctx *cli.Context) error {
|
|||||||
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
|
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||||
@@ -852,7 +875,8 @@ func dumpState(ctx *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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()
|
defer triedb.Close()
|
||||||
|
|
||||||
snapConfig := snapshot.Config{
|
snapConfig := snapshot.Config{
|
||||||
@@ -935,7 +959,7 @@ func snapshotExportPreimages(ctx *cli.Context) error {
|
|||||||
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
|
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
var root common.Hash
|
var root common.Hash
|
||||||
|
|||||||
@@ -25,3 +25,23 @@ testnet validators version
|
|||||||
```bash
|
```bash
|
||||||
node gettxcount.js --rpc ${url} --startNum ${start} --endNum ${end} --miner ${miner} (optional)
|
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()),
|
Value: flags.DirectoryString(node.DefaultDataDir()),
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
SeparateDBFlag = &cli.BoolFlag{
|
MultiDataBaseFlag = &cli.BoolFlag{
|
||||||
Name: "separatedb",
|
Name: "multidatabase",
|
||||||
Usage: "Enable a separated trie database, it will be created within a subdirectory called state, " +
|
Usage: "Enable a separated state and block database, it will be created within two subdirectory called state and block, " +
|
||||||
"Users can copy this state directory to another directory or disk, and then create a symbolic link to the state directory under the chaindata",
|
"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,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
DirectBroadcastFlag = &cli.BoolFlag{
|
DirectBroadcastFlag = &cli.BoolFlag{
|
||||||
@@ -224,7 +224,7 @@ var (
|
|||||||
// hbss2pbss command options
|
// hbss2pbss command options
|
||||||
ForceFlag = &cli.BoolFlag{
|
ForceFlag = &cli.BoolFlag{
|
||||||
Name: "force",
|
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,
|
Value: false,
|
||||||
}
|
}
|
||||||
// Dump command options.
|
// Dump command options.
|
||||||
@@ -305,9 +305,9 @@ var (
|
|||||||
Usage: "Manually specify the Rialto Genesis Hash, to trigger builtin network logic",
|
Usage: "Manually specify the Rialto Genesis Hash, to trigger builtin network logic",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
OverrideCancun = &cli.Uint64Flag{
|
OverrideBohr = &cli.Uint64Flag{
|
||||||
Name: "override.cancun",
|
Name: "override.bohr",
|
||||||
Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting",
|
Usage: "Manually specify the Bohr fork timestamp, overriding the bundled setting",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
OverrideVerkle = &cli.Uint64Flag{
|
OverrideVerkle = &cli.Uint64Flag{
|
||||||
@@ -315,15 +315,6 @@ var (
|
|||||||
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
OverrideFeynman = &cli.Uint64Flag{
|
|
||||||
Name: "override.feynman",
|
|
||||||
Usage: "Manually specify the Feynman fork timestamp, overriding the bundled setting",
|
|
||||||
Category: flags.EthCategory,
|
|
||||||
}
|
|
||||||
OverrideFeynmanFix = &cli.Uint64Flag{
|
|
||||||
Name: "override.feynmanfix",
|
|
||||||
Usage: "Manually specify the FeynmanFix fork timestamp, overriding the bundled setting",
|
|
||||||
}
|
|
||||||
OverrideFullImmutabilityThreshold = &cli.Uint64Flag{
|
OverrideFullImmutabilityThreshold = &cli.Uint64Flag{
|
||||||
Name: "override.immutabilitythreshold",
|
Name: "override.immutabilitythreshold",
|
||||||
Usage: "It is the number of blocks after which a chain segment is considered immutable, only for testing purpose",
|
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,
|
Value: params.DefaultExtraReserveForBlobRequests,
|
||||||
Category: flags.EthCategory,
|
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{
|
SyncModeFlag = &flags.TextMarshalerFlag{
|
||||||
Name: "syncmode",
|
Name: "syncmode",
|
||||||
Usage: `Blockchain sync mode ("snap" or "full")`,
|
Usage: `Blockchain sync mode ("snap" or "full")`,
|
||||||
@@ -365,6 +362,12 @@ var (
|
|||||||
Value: false,
|
Value: false,
|
||||||
Category: flags.StateCategory,
|
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{
|
StateHistoryFlag = &cli.Uint64Flag{
|
||||||
Name: "history.state",
|
Name: "history.state",
|
||||||
Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)",
|
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)",
|
Usage: "Disables the peer discovery mechanism (manual peer addition)",
|
||||||
Category: flags.NetworkingCategory,
|
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{
|
DiscoveryV4Flag = &cli.BoolFlag{
|
||||||
Name: "discovery.v4",
|
Name: "discovery.v4",
|
||||||
Aliases: []string{"discv4"},
|
Aliases: []string{"discv4"},
|
||||||
@@ -1069,6 +1077,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
|||||||
Name: "block-amount-reserved",
|
Name: "block-amount-reserved",
|
||||||
Usage: "Sets the expected remained amount of blocks for offline block prune",
|
Usage: "Sets the expected remained amount of blocks for offline block prune",
|
||||||
Category: flags.BlockHistoryCategory,
|
Category: flags.BlockHistoryCategory,
|
||||||
|
Value: params.FullImmutabilityThreshold,
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckSnapshotWithMPT = &cli.BoolFlag{
|
CheckSnapshotWithMPT = &cli.BoolFlag{
|
||||||
@@ -1144,7 +1153,6 @@ var (
|
|||||||
DBEngineFlag,
|
DBEngineFlag,
|
||||||
StateSchemeFlag,
|
StateSchemeFlag,
|
||||||
HttpHeaderFlag,
|
HttpHeaderFlag,
|
||||||
SeparateDBFlag,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1542,6 +1550,9 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
|
|||||||
if ctx.IsSet(NoDiscoverFlag.Name) {
|
if ctx.IsSet(NoDiscoverFlag.Name) {
|
||||||
cfg.NoDiscovery = true
|
cfg.NoDiscovery = true
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(PeerFilterPatternsFlag.Name) {
|
||||||
|
cfg.PeerFilterPatterns = ctx.StringSlice(PeerFilterPatternsFlag.Name)
|
||||||
|
}
|
||||||
|
|
||||||
CheckExclusive(ctx, DiscoveryV4Flag, NoDiscoverFlag)
|
CheckExclusive(ctx, DiscoveryV4Flag, NoDiscoverFlag)
|
||||||
CheckExclusive(ctx, DiscoveryV5Flag, 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) {
|
if ctx.IsSet(PathDBSyncFlag.Name) {
|
||||||
cfg.PathSyncFlush = true
|
cfg.PathSyncFlush = true
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(JournalFileFlag.Name) {
|
||||||
|
cfg.JournalFileEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 {
|
if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 {
|
||||||
cfg.TransactionHistory = 0
|
cfg.TransactionHistory = 0
|
||||||
log.Warn("Disabled transaction unindexing for archive node")
|
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()
|
cfg.Genesis = core.DefaultBSCGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.BSCGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.BSCGenesisHash)
|
||||||
case ctx.Bool(ChapelFlag.Name):
|
case ctx.Bool(ChapelFlag.Name) || cfg.NetworkId == 97:
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
cfg.NetworkId = 97
|
cfg.NetworkId = 97
|
||||||
}
|
}
|
||||||
@@ -2377,9 +2392,11 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree
|
|||||||
default:
|
default:
|
||||||
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false)
|
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false)
|
||||||
// set the separate state database
|
// set the separate state database
|
||||||
if stack.IsSeparatedDB() && err == nil {
|
if stack.CheckIfMultiDataBase() && err == nil {
|
||||||
stateDiskDb := MakeStateDataBase(ctx, stack, readonly, false)
|
stateDiskDb := MakeStateDataBase(ctx, stack, readonly, false)
|
||||||
chainDb.SetStateStore(stateDiskDb)
|
chainDb.SetStateStore(stateDiskDb)
|
||||||
|
blockDb := MakeBlockDatabase(ctx, stack, readonly, false)
|
||||||
|
chainDb.SetBlockStore(blockDb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
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.
|
// 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 {
|
func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database {
|
||||||
cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
|
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)
|
statediskdb, err := stack.OpenDatabaseWithFreezer("chaindata/state", cache, handles, "", "", readonly, disableFreeze, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Failed to open separate trie database: %v", err)
|
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
|
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,
|
// tryMakeReadOnlyDatabase try to open the chain database in read-only mode,
|
||||||
// or fallback to write mode if the database is not initialized.
|
// or fallback to write mode if the database is not initialized.
|
||||||
//
|
//
|
||||||
@@ -2541,7 +2575,7 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MakeTrieDatabase constructs a trie database based on the configured scheme.
|
// MakeTrieDatabase constructs a trie database based on the configured scheme.
|
||||||
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, 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{
|
config := &triedb.Config{
|
||||||
Preimages: preimage,
|
Preimages: preimage,
|
||||||
IsVerkle: isVerkle,
|
IsVerkle: isVerkle,
|
||||||
@@ -2555,6 +2589,7 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
|
|||||||
// ignore the parameter silently. TODO(rjl493456442)
|
// ignore the parameter silently. TODO(rjl493456442)
|
||||||
// please config it if read mode is implemented.
|
// please config it if read mode is implemented.
|
||||||
config.HashDB = hashdb.Defaults
|
config.HashDB = hashdb.Defaults
|
||||||
|
// TODO::skip MakeTrieDatabase
|
||||||
return triedb.NewDatabase(disk, config)
|
return triedb.NewDatabase(disk, config)
|
||||||
}
|
}
|
||||||
if readOnly {
|
if readOnly {
|
||||||
@@ -2562,6 +2597,8 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
|
|||||||
} else {
|
} else {
|
||||||
config.PathDB = pathdb.Defaults
|
config.PathDB = pathdb.Defaults
|
||||||
}
|
}
|
||||||
|
config.PathDB.JournalFilePath = fmt.Sprintf("%s/%s", stack.ResolvePath("chaindata"), eth.JournalFileName)
|
||||||
|
// TODO::skip MakeTrieDatabase
|
||||||
return triedb.NewDatabase(disk, config)
|
return triedb.NewDatabase(disk, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
|||||||
t.Fatalf("unable to initialize chain: %v", err)
|
t.Fatalf("unable to initialize chain: %v", err)
|
||||||
}
|
}
|
||||||
if _, err := chain.InsertChain(blocks); err != nil {
|
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.
|
// Make temp directory for era files.
|
||||||
@@ -163,7 +163,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
|||||||
|
|
||||||
// Now import Era.
|
// Now import Era.
|
||||||
freezer := t.TempDir()
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,7 +467,6 @@ func (tt *cliqueTest) run(t *testing.T) {
|
|||||||
for j := 0; j < len(batches)-1; j++ {
|
for j := 0; j < len(batches)-1; j++ {
|
||||||
if k, err := chain.InsertChain(batches[j]); err != nil {
|
if k, err := chain.InsertChain(batches[j]); err != nil {
|
||||||
t.Fatalf("failed to import batch %d, block %d: %v", j, k, err)
|
t.Fatalf("failed to import batch %d, block %d: %v", j, k, err)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure {
|
if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure {
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SecondsPerDay uint64 = 86400
|
|
||||||
|
|
||||||
// the params should be two blocks' time(timestamp)
|
// the params should be two blocks' time(timestamp)
|
||||||
func sameDayInUTC(first, second uint64) bool {
|
func sameDayInUTC(first, second uint64) bool {
|
||||||
return first/SecondsPerDay == second/SecondsPerDay
|
return first/params.BreatheBlockInterval == second/params.BreatheBlockInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
func isBreatheBlock(lastBlockTime, blockTime uint64) bool {
|
func isBreatheBlock(lastBlockTime, blockTime uint64) bool {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
||||||
"github.com/willf/bitset"
|
"github.com/willf/bitset"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
|
|
||||||
@@ -48,8 +48,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
inMemorySnapshots = 256 // Number of recent snapshots to keep in memory
|
inMemorySnapshots = 256 // Number of recent snapshots to keep in memory
|
||||||
inMemorySignatures = 4096 // Number of recent block signatures to keep in memory
|
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
|
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
|
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)
|
verifyVoteAttestationErrorCounter = metrics.NewRegisteredCounter("parlia/verifyVoteAttestation/error", nil)
|
||||||
updateAttestationErrorCounter = metrics.NewRegisteredCounter("parlia/updateAttestation/error", nil)
|
updateAttestationErrorCounter = metrics.NewRegisteredCounter("parlia/updateAttestation/error", nil)
|
||||||
validVotesfromSelfCounter = metrics.NewRegisteredCounter("parlia/VerifyVote/self", nil)
|
validVotesfromSelfCounter = metrics.NewRegisteredCounter("parlia/VerifyVote/self", nil)
|
||||||
|
doubleSignCounter = metrics.NewRegisteredCounter("parlia/doublesign", nil)
|
||||||
|
|
||||||
systemContracts = map[common.Address]bool{
|
systemContracts = map[common.Address]bool{
|
||||||
common.HexToAddress(systemcontracts.ValidatorContract): true,
|
common.HexToAddress(systemcontracts.ValidatorContract): true,
|
||||||
@@ -216,8 +218,11 @@ type Parlia struct {
|
|||||||
genesisHash common.Hash
|
genesisHash common.Hash
|
||||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||||
|
|
||||||
recentSnaps *lru.ARCCache // Snapshots for recent block to speed up
|
recentSnaps *lru.ARCCache // Snapshots for recent block to speed up
|
||||||
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
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
|
signer types.Signer
|
||||||
|
|
||||||
@@ -263,6 +268,10 @@ func New(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
recentHeaders, err := lru.NewARC(inMemoryHeaders)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
vABIBeforeLuban, err := abi.JSON(strings.NewReader(validatorSetABIBeforeLuban))
|
vABIBeforeLuban, err := abi.JSON(strings.NewReader(validatorSetABIBeforeLuban))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -286,6 +295,7 @@ func New(
|
|||||||
db: db,
|
db: db,
|
||||||
ethAPI: ethAPI,
|
ethAPI: ethAPI,
|
||||||
recentSnaps: recentSnaps,
|
recentSnaps: recentSnaps,
|
||||||
|
recentHeaders: recentHeaders,
|
||||||
signatures: signatures,
|
signatures: signatures,
|
||||||
validatorSetABIBeforeLuban: vABIBeforeLuban,
|
validatorSetABIBeforeLuban: vABIBeforeLuban,
|
||||||
validatorSetABI: vABI,
|
validatorSetABI: vABI,
|
||||||
@@ -297,6 +307,10 @@ func New(
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Parlia) Period() uint64 {
|
||||||
|
return p.config.Period
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Parlia) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) {
|
func (p *Parlia) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) {
|
||||||
// deploy a contract
|
// deploy a contract
|
||||||
if tx.To() == nil {
|
if tx.To() == nil {
|
||||||
@@ -599,9 +613,7 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
|
|||||||
switch {
|
switch {
|
||||||
case header.ParentBeaconRoot != nil:
|
case header.ParentBeaconRoot != nil:
|
||||||
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
|
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
|
||||||
// types.EmptyWithdrawalsHash represents a empty value when EIP-4895 enabled,
|
case !header.EmptyWithdrawalsHash():
|
||||||
// here, EIP-4895 still be disabled, value expected to be `types.EmptyWithdrawalsHash` is only to feet the demand of rlp encode/decode
|
|
||||||
case header.WithdrawalsHash == nil || *header.WithdrawalsHash != types.EmptyWithdrawalsHash:
|
|
||||||
return errors.New("header has wrong WithdrawalsHash")
|
return errors.New("header has wrong WithdrawalsHash")
|
||||||
}
|
}
|
||||||
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
|
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
|
||||||
@@ -811,6 +823,17 @@ func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Hea
|
|||||||
return errCoinBaseMisMatch
|
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 {
|
if _, ok := snap.Validators[signer]; !ok {
|
||||||
return errUnauthorizedValidator(signer.String())
|
return errUnauthorizedValidator(signer.String())
|
||||||
}
|
}
|
||||||
@@ -2013,3 +2036,8 @@ func applyMessage(
|
|||||||
}
|
}
|
||||||
return msg.Gas() - returnGas, err
|
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
|
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
|
// ValidateBody validates the given block's uncles and verifies the block
|
||||||
// header's transaction and uncle roots. The headers are assumed to be already
|
// header's transaction and uncle roots. The headers are assumed to be already
|
||||||
// validated at this point.
|
// 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 {
|
if err := v.engine.VerifyUncles(v.bc, block); err != nil {
|
||||||
return err
|
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{
|
validateFuns := []func() error{
|
||||||
func() error {
|
func() error {
|
||||||
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
return ValidateListsInBody(block)
|
||||||
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
func() error {
|
func() error {
|
||||||
// Withdrawals are present after the Shanghai fork.
|
|
||||||
if !header.EmptyWithdrawalsHash() {
|
|
||||||
// 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 len(block.Withdrawals()) != 0 { // 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.
|
// Blob transactions may be present after the Cancun fork.
|
||||||
var blobs int
|
var blobs int
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ var (
|
|||||||
justifiedBlockGauge = metrics.NewRegisteredGauge("chain/head/justified", nil)
|
justifiedBlockGauge = metrics.NewRegisteredGauge("chain/head/justified", nil)
|
||||||
finalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
|
finalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
|
||||||
|
|
||||||
|
blockInsertMgaspsGauge = metrics.NewRegisteredGauge("chain/insert/mgasps", nil)
|
||||||
|
|
||||||
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
|
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
|
||||||
|
|
||||||
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", 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.
|
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
|
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.
|
PathSyncFlush bool // Whether sync flush the trienodebuffer of pathdb to disk.
|
||||||
|
JournalFilePath string
|
||||||
|
JournalFile bool
|
||||||
|
|
||||||
SnapshotNoBuild bool // Whether the background generation is allowed
|
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
|
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 {
|
if c.StateScheme == rawdb.PathScheme {
|
||||||
config.PathDB = &pathdb.Config{
|
config.PathDB = &pathdb.Config{
|
||||||
SyncFlush: c.PathSyncFlush,
|
SyncFlush: c.PathSyncFlush,
|
||||||
StateHistory: c.StateHistory,
|
StateHistory: c.StateHistory,
|
||||||
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||||
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
|
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
|
||||||
|
JournalFilePath: c.JournalFilePath,
|
||||||
|
JournalFile: c.JournalFile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
@@ -272,6 +278,7 @@ type BlockChain struct {
|
|||||||
highestVerifiedHeader atomic.Pointer[types.Header]
|
highestVerifiedHeader atomic.Pointer[types.Header]
|
||||||
currentBlock atomic.Pointer[types.Header] // Current head of the chain
|
currentBlock atomic.Pointer[types.Header] // Current head of the chain
|
||||||
currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
|
currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
|
||||||
|
currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block
|
||||||
chasingHead atomic.Pointer[types.Header]
|
chasingHead atomic.Pointer[types.Header]
|
||||||
|
|
||||||
bodyCache *lru.Cache[common.Hash, *types.Body]
|
bodyCache *lru.Cache[common.Hash, *types.Body]
|
||||||
@@ -294,6 +301,7 @@ type BlockChain struct {
|
|||||||
diffLayerFreezerBlockLimit uint64
|
diffLayerFreezerBlockLimit uint64
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
dbWg sync.WaitGroup
|
||||||
quit chan struct{} // shutdown signal, closed in Stop.
|
quit chan struct{} // shutdown signal, closed in Stop.
|
||||||
stopping atomic.Bool // false if chain is running, true when stopped
|
stopping atomic.Bool // false if chain is running, true when stopped
|
||||||
procInterrupt atomic.Bool // interrupt signaler for block processing
|
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)
|
diffLayerChanCache, _ := exlru.New(diffLayerCacheLimit)
|
||||||
|
|
||||||
// Open trie database with provided config
|
// Open trie database with provided config
|
||||||
|
// TODO:: if versa , have its owen init genesis logic
|
||||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig())
|
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig())
|
||||||
|
|
||||||
// Setup the genesis block, commit the provided genesis specification
|
// 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.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
||||||
bc.forker = NewForkChoice(bc, shouldPreserve)
|
bc.forker = NewForkChoice(bc, shouldPreserve)
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
||||||
bc.validator = NewBlockValidator(chainConfig, bc, engine)
|
bc.validator = NewBlockValidator(chainConfig, bc, engine)
|
||||||
bc.prefetcher = NewStatePrefetcher(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
|
// Make sure the state associated with the block is available, or log out
|
||||||
// if there is no available state, waiting for state sync.
|
// if there is no available state, waiting for state sync.
|
||||||
head := bc.CurrentBlock()
|
head := bc.CurrentBlock()
|
||||||
if !bc.NoTries() && !bc.HasState(head.Root) {
|
if !bc.HasState(head.Root) {
|
||||||
if head.Number.Uint64() == 0 {
|
if head.Number.Uint64() == 0 {
|
||||||
// The genesis state is missing, which is only possible in the path-based
|
// 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
|
// 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 {
|
if bc.cacheConfig.SnapshotLimit > 0 {
|
||||||
diskRoot = rawdb.ReadSnapshotRoot(bc.db)
|
diskRoot = rawdb.ReadSnapshotRoot(bc.db)
|
||||||
}
|
}
|
||||||
if bc.triedb.Scheme() == rawdb.PathScheme {
|
if bc.triedb.Scheme() == rawdb.PathScheme && !bc.NoTries() {
|
||||||
recoverable, _ := bc.triedb.Recoverable(diskRoot)
|
recoverable, _ := bc.triedb.Recoverable(diskRoot)
|
||||||
if !bc.HasState(diskRoot) && !recoverable {
|
if !bc.HasState(diskRoot) && !recoverable {
|
||||||
diskRoot = bc.triedb.Head()
|
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
|
// Ensure that a previous crash in SetHead doesn't leave extra ancients
|
||||||
if frozen, err := bc.db.ItemAmountInAncient(); err == nil && frozen > 0 {
|
if frozen, err := bc.db.BlockStore().ItemAmountInAncient(); err == nil && frozen > 0 {
|
||||||
frozen, err = bc.db.Ancients()
|
frozen, err = bc.db.BlockStore().Ancients()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// empty returns an indicator whether the blockchain is empty.
|
||||||
// Note, it's a special case that we connect a non-empty ancient
|
// 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
|
// 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
|
// 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.
|
// 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) {
|
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.rewindPathHead(head, root)
|
||||||
}
|
}
|
||||||
return bc.rewindHashHead(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
|
// 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
|
// 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
|
// 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
|
// block. Note, depth equality is permitted to allow using SetHead as a
|
||||||
// chain reparation mechanism without deleting any data!
|
// chain reparation mechanism without deleting any data!
|
||||||
if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.Number.Uint64() {
|
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
|
var newHeadBlock *types.Header
|
||||||
newHeadBlock, rootNumber = bc.rewindHead(header, root)
|
newHeadBlock, rootNumber = bc.rewindHead(header, root)
|
||||||
rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash())
|
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
|
// intent afterwards is full block importing, delete the chain segment
|
||||||
// between the stateful-block and the sethead target.
|
// between the stateful-block and the sethead target.
|
||||||
var wipe bool
|
var wipe bool
|
||||||
frozen, _ := bc.db.Ancients()
|
frozen, _ := bc.db.BlockStore().Ancients()
|
||||||
if headNumber+1 < frozen {
|
if headNumber+1 < frozen {
|
||||||
wipe = pivot == nil || headNumber >= *pivot
|
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
|
// Rewind the header chain, deleting all block bodies until then
|
||||||
delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) {
|
delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) {
|
||||||
// Ignore the error here since light client won't hit this path
|
// 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 {
|
if num+1 <= frozen {
|
||||||
// Truncate all relative data(header, total difficulty, body, receipt
|
// Truncate all relative data(header, total difficulty, body, receipt
|
||||||
// and canonical hash) from ancient store.
|
// 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)
|
log.Crit("Failed to truncate ancient data", "number", num, "err", err)
|
||||||
}
|
}
|
||||||
// Remove the hash <-> number mapping from the active store.
|
// 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
|
// If SetHead was only called as a chain reparation method, try to skip
|
||||||
// touching the header chain altogether, unless the freezer is broken
|
// touching the header chain altogether, unless the freezer is broken
|
||||||
if repair {
|
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)
|
bc.hc.SetHead(target.Number.Uint64(), updateFn, delFn)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1129,6 +1156,11 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
|||||||
bc.txLookupCache.Purge()
|
bc.txLookupCache.Purge()
|
||||||
bc.futureBlocks.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()
|
return rootNumber, bc.loadLastState()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1197,10 +1229,10 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
|
|||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
|
|
||||||
// Prepare the genesis block and reinitialise the chain
|
// Prepare the genesis block and reinitialise the chain
|
||||||
batch := bc.db.NewBatch()
|
blockBatch := bc.db.BlockStore().NewBatch()
|
||||||
rawdb.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty())
|
rawdb.WriteTd(blockBatch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty())
|
||||||
rawdb.WriteBlock(batch, genesis)
|
rawdb.WriteBlock(blockBatch, genesis)
|
||||||
if err := batch.Write(); err != nil {
|
if err := blockBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to write genesis block", "err", err)
|
log.Crit("Failed to write genesis block", "err", err)
|
||||||
}
|
}
|
||||||
bc.writeHeadBlock(genesis)
|
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!
|
// Note, this function assumes that the `mu` mutex is held!
|
||||||
func (bc *BlockChain) writeHeadBlock(block *types.Block) {
|
func (bc *BlockChain) writeHeadBlock(block *types.Block) {
|
||||||
// Add the block to the canonical chain number scheme and mark as the head
|
bc.dbWg.Add(2)
|
||||||
batch := bc.db.NewBatch()
|
defer bc.dbWg.Wait()
|
||||||
rawdb.WriteHeadHeaderHash(batch, block.Hash())
|
go func() {
|
||||||
rawdb.WriteHeadFastBlockHash(batch, block.Hash())
|
defer bc.dbWg.Done()
|
||||||
rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
|
// Add the block to the canonical chain number scheme and mark as the head
|
||||||
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
blockBatch := bc.db.BlockStore().NewBatch()
|
||||||
rawdb.WriteHeadBlockHash(batch, block.Hash())
|
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
|
// Update all in-memory chain markers in the last step
|
||||||
bc.hc.SetCurrentHeader(block.Header())
|
bc.hc.SetCurrentHeader(block.Header())
|
||||||
|
|
||||||
@@ -1354,7 +1401,7 @@ func (bc *BlockChain) Stop() {
|
|||||||
} else {
|
} else {
|
||||||
rawdb.WriteSafePointBlockNumber(bc.db, recent.NumberU64())
|
rawdb.WriteSafePointBlockNumber(bc.db, recent.NumberU64())
|
||||||
once.Do(func() {
|
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 {
|
} else if !reorg {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
rawdb.WriteHeadFastBlockHash(bc.db, head.Hash())
|
rawdb.WriteHeadFastBlockHash(bc.db.BlockStore(), head.Hash())
|
||||||
bc.currentSnapBlock.Store(head.Header())
|
bc.currentSnapBlock.Store(head.Header())
|
||||||
headFastBlockGauge.Update(int64(head.NumberU64()))
|
headFastBlockGauge.Update(int64(head.NumberU64()))
|
||||||
return true
|
return true
|
||||||
@@ -1511,9 +1558,9 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||||||
|
|
||||||
// Ensure genesis is in ancients.
|
// Ensure genesis is in ancients.
|
||||||
if first.NumberU64() == 1 {
|
if first.NumberU64() == 1 {
|
||||||
if frozen, _ := bc.db.Ancients(); frozen == 0 {
|
if frozen, _ := bc.db.BlockStore().Ancients(); frozen == 0 {
|
||||||
td := bc.genesisBlock.Difficulty()
|
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 {
|
if err != nil {
|
||||||
log.Error("Error writing genesis to ancients", "err", err)
|
log.Error("Error writing genesis to ancients", "err", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -1531,7 +1578,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||||||
|
|
||||||
// Write all chain data to ancients.
|
// Write all chain data to ancients.
|
||||||
td := bc.GetTd(first.Hash(), first.NumberU64())
|
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 {
|
if err != nil {
|
||||||
log.Error("Error importing chain data to ancients", "err", err)
|
log.Error("Error importing chain data to ancients", "err", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -1539,7 +1586,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||||||
size += writeSize
|
size += writeSize
|
||||||
|
|
||||||
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
|
// 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
|
return 0, err
|
||||||
}
|
}
|
||||||
// Update the current snap block because all block data is now present in DB.
|
// 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]) {
|
if !updateHead(blockChain[len(blockChain)-1]) {
|
||||||
// We end up here if the header chain has reorg'ed, and the blocks/receipts
|
// We end up here if the header chain has reorg'ed, and the blocks/receipts
|
||||||
// don't match the canonical chain.
|
// 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)
|
log.Error("Can't truncate ancient store after failed insert", "err", err)
|
||||||
}
|
}
|
||||||
return 0, errSideChainReceipts
|
return 0, errSideChainReceipts
|
||||||
@@ -1555,24 +1602,24 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||||||
|
|
||||||
// Delete block data from the main database.
|
// Delete block data from the main database.
|
||||||
var (
|
var (
|
||||||
batch = bc.db.NewBatch()
|
|
||||||
canonHashes = make(map[common.Hash]struct{})
|
canonHashes = make(map[common.Hash]struct{})
|
||||||
|
blockBatch = bc.db.BlockStore().NewBatch()
|
||||||
)
|
)
|
||||||
for _, block := range blockChain {
|
for _, block := range blockChain {
|
||||||
canonHashes[block.Hash()] = struct{}{}
|
canonHashes[block.Hash()] = struct{}{}
|
||||||
if block.NumberU64() == 0 {
|
if block.NumberU64() == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rawdb.DeleteCanonicalHash(batch, block.NumberU64())
|
rawdb.DeleteCanonicalHash(blockBatch, block.NumberU64())
|
||||||
rawdb.DeleteBlockWithoutNumber(batch, block.Hash(), block.NumberU64())
|
rawdb.DeleteBlockWithoutNumber(blockBatch, block.Hash(), block.NumberU64())
|
||||||
}
|
}
|
||||||
// Delete side chain hash-to-number mappings.
|
// 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 {
|
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
|
return 0, err
|
||||||
}
|
}
|
||||||
stats.processed += int32(len(blockChain))
|
stats.processed += int32(len(blockChain))
|
||||||
@@ -1584,6 +1631,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||||||
var (
|
var (
|
||||||
skipPresenceCheck = false
|
skipPresenceCheck = false
|
||||||
batch = bc.db.NewBatch()
|
batch = bc.db.NewBatch()
|
||||||
|
blockBatch = bc.db.BlockStore().NewBatch()
|
||||||
)
|
)
|
||||||
for i, block := range blockChain {
|
for i, block := range blockChain {
|
||||||
// Short circuit insertion if shutting down or processing failed
|
// 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
|
// Write all the data out into the database
|
||||||
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
|
rawdb.WriteBody(blockBatch, block.Hash(), block.NumberU64(), block.Body())
|
||||||
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
|
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receiptChain[i])
|
||||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
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
|
// 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())
|
size += int64(batch.ValueSize())
|
||||||
batch.Reset()
|
batch.Reset()
|
||||||
}
|
}
|
||||||
|
if blockBatch.ValueSize() >= ethdb.IdealBatchSize {
|
||||||
|
if err := blockBatch.Write(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
size += int64(blockBatch.ValueSize())
|
||||||
|
blockBatch.Reset()
|
||||||
|
}
|
||||||
stats.processed++
|
stats.processed++
|
||||||
}
|
}
|
||||||
// Write everything belongs to the blocks into the database. So that
|
// 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
|
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])
|
updateHead(blockChain[len(blockChain)-1])
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@@ -1678,14 +1739,14 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
|
|||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
return errInsertionInterrupted
|
return errInsertionInterrupted
|
||||||
}
|
}
|
||||||
batch := bc.db.NewBatch()
|
blockBatch := bc.db.BlockStore().NewBatch()
|
||||||
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
|
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), td)
|
||||||
rawdb.WriteBlock(batch, block)
|
rawdb.WriteBlock(blockBatch, block)
|
||||||
// if cancun is enabled, here need to write sidecars too
|
// if cancun is enabled, here need to write sidecars too
|
||||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
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)
|
log.Crit("Failed to write block into disk", "err", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -1723,7 +1784,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
blockBatch := bc.db.NewBatch()
|
blockBatch := bc.db.BlockStore().NewBatch()
|
||||||
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
|
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
|
||||||
rawdb.WriteBlock(blockBatch, block)
|
rawdb.WriteBlock(blockBatch, block)
|
||||||
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
|
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()) {
|
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||||
rawdb.WriteBlobSidecars(blockBatch, block.Hash(), block.NumberU64(), block.Sidecars())
|
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 {
|
if err := blockBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to write block into disk", "err", err)
|
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()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -1892,12 +1963,16 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
|||||||
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
||||||
// we will fire an accumulated ChainHeadEvent and disable fire
|
// we will fire an accumulated ChainHeadEvent and disable fire
|
||||||
// event here.
|
// 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 {
|
if emitHeadEvent {
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||||
if posa, ok := bc.Engine().(consensus.PoSA); ok {
|
if finalizedHeader != nil {
|
||||||
if finalizedHeader := posa.GetFinalizedHeader(bc, block.Header()); finalizedHeader != nil {
|
bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
|
||||||
bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
// state, but if it's this special case here(skip reexecution) we will lose
|
||||||
// the empty receipt entry.
|
// the empty receipt entry.
|
||||||
if len(block.Transactions()) == 0 {
|
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 {
|
} else {
|
||||||
log.Error("Please file an issue, skip known block execution without receipt",
|
log.Error("Please file an issue, skip known block execution without receipt",
|
||||||
"hash", block.Hash(), "number", block.NumberU64())
|
"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)
|
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)
|
statedb, err := state.NewWithSharedPool(parent.Root, bc.stateCache, bc.snaps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return it.index, err
|
||||||
@@ -2208,8 +2284,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
|||||||
vtime := time.Since(vstart)
|
vtime := time.Since(vstart)
|
||||||
proctime := time.Since(start) // processing + validation
|
proctime := time.Since(start) // processing + validation
|
||||||
|
|
||||||
bc.cacheBlock(block.Hash(), block)
|
|
||||||
|
|
||||||
// Update the metrics touched during block processing and validation
|
// Update the metrics touched during block processing and validation
|
||||||
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
||||||
storageReadTimer.Update(statedb.StorageReads) // Storage 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 {
|
if header == nil || header.Number == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currentHeader := bc.highestVerifiedHeader.Load()
|
currentBlock := bc.CurrentBlock()
|
||||||
if currentHeader == nil {
|
reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, header)
|
||||||
|
if err == nil && reorg {
|
||||||
bc.highestVerifiedHeader.Store(types.CopyHeader(header))
|
bc.highestVerifiedHeader.Store(types.CopyHeader(header))
|
||||||
return
|
log.Trace("updateHighestVerifiedHeader", "number", header.Number.Uint64(), "hash", header.Hash())
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2681,6 +2740,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
|||||||
var (
|
var (
|
||||||
indexesBatch = bc.db.NewBatch()
|
indexesBatch = bc.db.NewBatch()
|
||||||
diffs = types.HashDifference(deletedTxs, addedTxs)
|
diffs = types.HashDifference(deletedTxs, addedTxs)
|
||||||
|
blockBatch = bc.db.BlockStore().NewBatch()
|
||||||
)
|
)
|
||||||
for _, tx := range diffs {
|
for _, tx := range diffs {
|
||||||
rawdb.DeleteTxLookupEntry(indexesBatch, tx)
|
rawdb.DeleteTxLookupEntry(indexesBatch, tx)
|
||||||
@@ -2697,11 +2757,14 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
|||||||
if hash == (common.Hash{}) {
|
if hash == (common.Hash{}) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
rawdb.DeleteCanonicalHash(indexesBatch, i)
|
rawdb.DeleteCanonicalHash(blockBatch, i)
|
||||||
}
|
}
|
||||||
if err := indexesBatch.Write(); err != nil {
|
if err := indexesBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to delete useless indexes", "err", err)
|
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'
|
// 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
|
// 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 we're at the last block of the batch or report period reached, log
|
||||||
if index == len(chain)-1 || elapsed >= statsReportLimit {
|
if index == len(chain)-1 || elapsed >= statsReportLimit {
|
||||||
// Count the number of transactions in this segment
|
// Count the number of transactions in this segment
|
||||||
var txs int
|
var txs, blobs int
|
||||||
for _, block := range chain[st.lastIndex : index+1] {
|
for _, block := range chain[st.lastIndex : index+1] {
|
||||||
txs += len(block.Transactions())
|
txs += len(block.Transactions())
|
||||||
|
for _, sidecar := range block.Sidecars() {
|
||||||
|
blobs += len(sidecar.Blobs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end := chain[index]
|
end := chain[index]
|
||||||
|
|
||||||
// Assemble the log context and send it to the logger
|
// Assemble the log context and send it to the logger
|
||||||
|
mgasps := float64(st.usedGas) * 1000 / float64(elapsed)
|
||||||
context := []interface{}{
|
context := []interface{}{
|
||||||
"number", end.Number(), "hash", end.Hash(), "miner", end.Coinbase(),
|
"number", end.Number(), "hash", end.Hash(), "miner", end.Coinbase(),
|
||||||
"blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000,
|
"blocks", st.processed, "txs", txs, "blobs", blobs, "mgas", float64(st.usedGas) / 1000000,
|
||||||
"elapsed", common.PrettyDuration(elapsed), "mgasps", float64(st.usedGas) * 1000 / float64(elapsed),
|
"elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps,
|
||||||
}
|
}
|
||||||
|
blockInsertMgaspsGauge.Update(int64(mgasps))
|
||||||
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
|
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
|
||||||
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -396,7 +396,21 @@ func (bc *BlockChain) State() (*state.StateDB, error) {
|
|||||||
|
|
||||||
// StateAt returns a new mutable state based on a particular point in time.
|
// StateAt returns a new mutable state based on a particular point in time.
|
||||||
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
|
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
|
||||||
return state.New(root, bc.stateCache, bc.snaps)
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
|
stateDb, err := state.New(root, bc.stateCache, bc.snaps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no trie and the specified snapshot is not available, getting
|
||||||
|
// any state will by default return nil.
|
||||||
|
// Instead of that, it will be more useful to return an error to indicate
|
||||||
|
// the state is not available.
|
||||||
|
if stateDb.NoTrie() && stateDb.GetSnap() == nil {
|
||||||
|
return nil, errors.New("state is not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
return stateDb, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config retrieves the chain's fork configuration.
|
// Config retrieves the chain's fork configuration.
|
||||||
@@ -498,3 +512,12 @@ func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscr
|
|||||||
func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEvent) event.Subscription {
|
func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEvent) event.Subscription {
|
||||||
return bc.scope.Track(bc.finalizedHeaderFeed.Subscribe(ch))
|
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"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"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.SnapshotWait = true
|
||||||
}
|
}
|
||||||
config.TriesInMemory = 128
|
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)
|
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"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.SnapshotWait = true
|
||||||
}
|
}
|
||||||
config.TriesInMemory = 128
|
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)
|
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
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)
|
t.Fatalf("failed to insert receipt %d: %v", n, err)
|
||||||
}
|
}
|
||||||
// Freezer style fast import the chain.
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
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 creates a db instance for testing.
|
||||||
makeDb := func() ethdb.Database {
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
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}) })
|
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
|
// 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()
|
defer db.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
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)
|
_, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(height), nil)
|
||||||
|
|
||||||
// Import the chain as a ancient-first node and ensure all pointers are updated
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
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.
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
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
|
// 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()
|
defer diskdb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
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
|
b.OffsetTime(-9) // A higher difficulty
|
||||||
})
|
})
|
||||||
// Import the shared chain and the original canonical one
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
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
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||||
}
|
}
|
||||||
@@ -3858,7 +3858,7 @@ func testSetCanonical(t *testing.T, scheme string) {
|
|||||||
}
|
}
|
||||||
gen.AddTx(tx)
|
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()
|
defer diskdb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
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) {
|
func TestParliaBlobFeeReward(t *testing.T) {
|
||||||
// Have N headers in the freezer
|
// Have N headers in the freezer
|
||||||
frdir := t.TempDir()
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create database with ancient backend")
|
t.Fatalf("failed to create database with ancient backend")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,6 +372,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
if block.Header().EmptyWithdrawalsHash() {
|
||||||
|
block = block.WithWithdrawals(make([]*types.Withdrawal, 0))
|
||||||
|
}
|
||||||
if config.IsCancun(block.Number(), block.Time()) {
|
if config.IsCancun(block.Number(), block.Time()) {
|
||||||
for _, s := range b.sidecars {
|
for _, s := range b.sidecars {
|
||||||
s.BlockNumber = block.Number()
|
s.BlockNumber = block.Number()
|
||||||
@@ -394,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.
|
// Forcibly use hash-based state scheme for retaining all nodes in disk.
|
||||||
|
// TODO:: ignore, only use to UT
|
||||||
triedb := triedb.NewDatabase(db, triedb.HashDefaults)
|
triedb := triedb.NewDatabase(db, triedb.HashDefaults)
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
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)
|
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/gopool"
|
"github.com/ethereum/go-ethereum/common/gopool"
|
||||||
@@ -14,6 +17,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
daCheckTimer = metrics.NewRegisteredTimer("chain/dacheck", nil)
|
||||||
|
)
|
||||||
|
|
||||||
// validateBlobSidecar it is same as validateBlobSidecar in core/txpool/validation.go
|
// validateBlobSidecar it is same as validateBlobSidecar in core/txpool/validation.go
|
||||||
func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobSidecar) error {
|
func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobSidecar) error {
|
||||||
if len(sidecar.Blobs) != len(hashes) {
|
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
|
// IsDataAvailable it checks that the blobTx block has available blob data
|
||||||
func IsDataAvailable(chain consensus.ChainHeaderReader, block *types.Block) (err error) {
|
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
|
// refer logic in ValidateBody
|
||||||
if !chain.Config().IsCancun(block.Number(), block.Time()) {
|
if !chain.Config().IsCancun(block.Number(), block.Time()) {
|
||||||
if block.Sidecars() != nil {
|
if block.Sidecars() != nil {
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
|
||||||
|
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
@@ -247,6 +250,49 @@ func TestCheckDataAvailableInBatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkEmptySidecarDAChecking(b *testing.B) {
|
||||||
|
hr := NewMockDAHeaderReader(params.ParliaTestChainConfig)
|
||||||
|
block := types.NewBlockWithHeader(&types.Header{
|
||||||
|
Number: big.NewInt(1),
|
||||||
|
}).WithBody(types.Transactions{
|
||||||
|
createMockDATx(hr.Config(), emptySidecar()),
|
||||||
|
createMockDATx(hr.Config(), emptySidecar()),
|
||||||
|
createMockDATx(hr.Config(), emptySidecar()),
|
||||||
|
createMockDATx(hr.Config(), emptySidecar()),
|
||||||
|
createMockDATx(hr.Config(), emptySidecar()),
|
||||||
|
createMockDATx(hr.Config(), emptySidecar()),
|
||||||
|
}, nil)
|
||||||
|
block = block.WithSidecars(collectBlobsFromTxs(block.Header(), block.Transactions()))
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
IsDataAvailable(hr, block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRandomSidecarDAChecking(b *testing.B) {
|
||||||
|
hr := NewMockDAHeaderReader(params.ParliaTestChainConfig)
|
||||||
|
const count = 10
|
||||||
|
blocks := make([]*types.Block, count)
|
||||||
|
for i := 0; i < len(blocks); i++ {
|
||||||
|
block := types.NewBlockWithHeader(&types.Header{
|
||||||
|
Number: big.NewInt(1),
|
||||||
|
}).WithBody(types.Transactions{
|
||||||
|
createMockDATx(hr.Config(), randomSidecar()),
|
||||||
|
createMockDATx(hr.Config(), randomSidecar()),
|
||||||
|
createMockDATx(hr.Config(), randomSidecar()),
|
||||||
|
createMockDATx(hr.Config(), randomSidecar()),
|
||||||
|
createMockDATx(hr.Config(), randomSidecar()),
|
||||||
|
createMockDATx(hr.Config(), randomSidecar()),
|
||||||
|
}, nil)
|
||||||
|
block = block.WithSidecars(collectBlobsFromTxs(block.Header(), block.Transactions()))
|
||||||
|
blocks[i] = block
|
||||||
|
}
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
IsDataAvailable(hr, blocks[i%count])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func collectBlobsFromTxs(header *types.Header, txs types.Transactions) types.BlobSidecars {
|
func collectBlobsFromTxs(header *types.Header, txs types.Transactions) types.BlobSidecars {
|
||||||
sidecars := make(types.BlobSidecars, 0, len(txs))
|
sidecars := make(types.BlobSidecars, 0, len(txs))
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
@@ -348,3 +394,43 @@ func createMockDATx(config *params.ChainConfig, sidecar *types.BlobTxSidecar) *t
|
|||||||
}
|
}
|
||||||
return types.NewTx(tx)
|
return types.NewTx(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func randFieldElement() [32]byte {
|
||||||
|
bytes := make([]byte, 32)
|
||||||
|
_, err := rand.Read(bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to get random field element")
|
||||||
|
}
|
||||||
|
var r fr.Element
|
||||||
|
r.SetBytes(bytes)
|
||||||
|
|
||||||
|
return gokzg4844.SerializeScalar(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func randBlob() kzg4844.Blob {
|
||||||
|
var blob kzg4844.Blob
|
||||||
|
for i := 0; i < len(blob); i += gokzg4844.SerializedScalarSize {
|
||||||
|
fieldElementBytes := randFieldElement()
|
||||||
|
copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:])
|
||||||
|
}
|
||||||
|
return blob
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomSidecar() *types.BlobTxSidecar {
|
||||||
|
blob := randBlob()
|
||||||
|
commitment, _ := kzg4844.BlobToCommitment(blob)
|
||||||
|
proof, _ := kzg4844.ComputeBlobProof(blob, commitment)
|
||||||
|
return &types.BlobTxSidecar{
|
||||||
|
Blobs: []kzg4844.Blob{blob},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment},
|
||||||
|
Proofs: []kzg4844.Proof{proof},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func emptySidecar() *types.BlobTxSidecar {
|
||||||
|
return &types.BlobTxSidecar{
|
||||||
|
Blobs: []kzg4844.Blob{emptyBlob},
|
||||||
|
Commitments: []kzg4844.Commitment{emptyBlobCommit},
|
||||||
|
Proofs: []kzg4844.Proof{emptyBlobProof},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,9 +86,16 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b
|
|||||||
localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64())
|
localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64())
|
||||||
externTd = f.chain.GetTd(extern.Hash(), extern.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")
|
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
|
// Accept the new header as the chain head if the transition
|
||||||
// is already triggered. We assume all the headers after the
|
// is already triggered. We assume all the headers after the
|
||||||
// transition come from the trusted consensus layer.
|
// 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 {
|
if f.preserve != nil {
|
||||||
currentPreserve, externPreserve = f.preserve(current), f.preserve(extern)
|
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
|
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,
|
// Create an ephemeral in-memory database for computing hash,
|
||||||
// all the derived states will be discarded to not pollute disk.
|
// all the derived states will be discarded to not pollute disk.
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
|
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
statedb, err := state.New(types.EmptyRootHash, db, nil)
|
statedb, err := state.New(types.EmptyRootHash, db, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
@@ -154,6 +156,7 @@ func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Databa
|
|||||||
if triedbConfig != nil {
|
if triedbConfig != nil {
|
||||||
triedbConfig.NoTries = false
|
triedbConfig.NoTries = false
|
||||||
}
|
}
|
||||||
|
// TODO:: state.NewDatabase internally compatible with versa is sufficient.
|
||||||
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -216,10 +219,8 @@ func (e *GenesisMismatchError) Error() string {
|
|||||||
// ChainOverrides contains the changes to chain config
|
// ChainOverrides contains the changes to chain config
|
||||||
// Typically, these modifications involve hardforks that are not enabled on the BSC mainnet, intended for testing purposes.
|
// Typically, these modifications involve hardforks that are not enabled on the BSC mainnet, intended for testing purposes.
|
||||||
type ChainOverrides struct {
|
type ChainOverrides struct {
|
||||||
OverrideCancun *uint64
|
OverrideBohr *uint64
|
||||||
OverrideVerkle *uint64
|
OverrideVerkle *uint64
|
||||||
OverrideFeynman *uint64
|
|
||||||
OverrideFeynmanFix *uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupGenesisBlock writes or updates the genesis block in db.
|
// 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) {
|
applyOverrides := func(config *params.ChainConfig) {
|
||||||
if config != nil {
|
if config != nil {
|
||||||
if overrides != nil && overrides.OverrideCancun != nil {
|
if overrides != nil && overrides.OverrideBohr != nil {
|
||||||
config.CancunTime = overrides.OverrideCancun
|
config.BohrTime = overrides.OverrideBohr
|
||||||
}
|
}
|
||||||
if overrides != nil && overrides.OverrideVerkle != nil {
|
if overrides != nil && overrides.OverrideVerkle != nil {
|
||||||
config.VerkleTime = overrides.OverrideVerkle
|
config.VerkleTime = overrides.OverrideVerkle
|
||||||
}
|
}
|
||||||
if overrides != nil && overrides.OverrideFeynman != nil {
|
|
||||||
config.FeynmanTime = overrides.OverrideFeynman
|
|
||||||
}
|
|
||||||
if overrides != nil && overrides.OverrideFeynmanFix != nil {
|
|
||||||
config.FeynmanFixTime = overrides.OverrideFeynmanFix
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Just commit the new block if there is no stored genesis block.
|
// 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 {
|
if err := flushAlloc(&g.Alloc, db, triedb, block.Hash()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
|
rawdb.WriteTd(db.BlockStore(), block.Hash(), block.NumberU64(), block.Difficulty())
|
||||||
rawdb.WriteBlock(db, block)
|
rawdb.WriteBlock(db.BlockStore(), block)
|
||||||
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
|
rawdb.WriteReceipts(db.BlockStore(), block.Hash(), block.NumberU64(), nil)
|
||||||
rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
|
rawdb.WriteCanonicalHash(db.BlockStore(), block.Hash(), block.NumberU64())
|
||||||
rawdb.WriteHeadBlockHash(db, block.Hash())
|
rawdb.WriteHeadBlockHash(db.BlockStore(), block.Hash())
|
||||||
rawdb.WriteHeadFastBlockHash(db, block.Hash())
|
rawdb.WriteHeadFastBlockHash(db.BlockStore(), block.Hash())
|
||||||
rawdb.WriteHeadHeaderHash(db, block.Hash())
|
rawdb.WriteHeadHeaderHash(db.BlockStore(), block.Hash())
|
||||||
rawdb.WriteChainConfig(db, block.Hash(), config)
|
rawdb.WriteChainConfig(db, block.Hash(), config)
|
||||||
return block, nil
|
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
|
// pile them onto the existing chain. Otherwise, do the necessary
|
||||||
// reorgs.
|
// reorgs.
|
||||||
var (
|
var (
|
||||||
first = headers[0]
|
first = headers[0]
|
||||||
last = headers[len(headers)-1]
|
last = headers[len(headers)-1]
|
||||||
batch = hc.chainDb.NewBatch()
|
blockBatch = hc.chainDb.BlockStore().NewBatch()
|
||||||
)
|
)
|
||||||
if first.ParentHash != hc.currentHeaderHash {
|
if first.ParentHash != hc.currentHeaderHash {
|
||||||
// Delete any canonical number assignments above the new head
|
// 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{}) {
|
if hash == (common.Hash{}) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
rawdb.DeleteCanonicalHash(batch, i)
|
rawdb.DeleteCanonicalHash(blockBatch, i)
|
||||||
}
|
}
|
||||||
// Overwrite any stale canonical number assignments, going
|
// Overwrite any stale canonical number assignments, going
|
||||||
// backwards from the first header in this import until the
|
// 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()
|
headHash = header.Hash()
|
||||||
)
|
)
|
||||||
for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash {
|
for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash {
|
||||||
rawdb.WriteCanonicalHash(batch, headHash, headNumber)
|
rawdb.WriteCanonicalHash(blockBatch, headHash, headNumber)
|
||||||
if headNumber == 0 {
|
if headNumber == 0 {
|
||||||
break // It shouldn't be reached
|
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++ {
|
for i := 0; i < len(headers)-1; i++ {
|
||||||
hash := headers[i+1].ParentHash // Save some extra hashing
|
hash := headers[i+1].ParentHash // Save some extra hashing
|
||||||
num := headers[i].Number.Uint64()
|
num := headers[i].Number.Uint64()
|
||||||
rawdb.WriteCanonicalHash(batch, hash, num)
|
rawdb.WriteCanonicalHash(blockBatch, hash, num)
|
||||||
rawdb.WriteHeadHeaderHash(batch, hash)
|
rawdb.WriteHeadHeaderHash(blockBatch, hash)
|
||||||
}
|
}
|
||||||
// Write the last header
|
// Write the last header
|
||||||
hash := headers[len(headers)-1].Hash()
|
hash := headers[len(headers)-1].Hash()
|
||||||
num := headers[len(headers)-1].Number.Uint64()
|
num := headers[len(headers)-1].Number.Uint64()
|
||||||
rawdb.WriteCanonicalHash(batch, hash, num)
|
rawdb.WriteCanonicalHash(blockBatch, hash, num)
|
||||||
rawdb.WriteHeadHeaderHash(batch, hash)
|
rawdb.WriteHeadHeaderHash(blockBatch, hash)
|
||||||
|
|
||||||
if err := batch.Write(); err != nil {
|
if err := blockBatch.Write(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Last step update all in-memory head header markers
|
// 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
|
newTD = new(big.Int).Set(ptd) // Total difficulty of inserted chain
|
||||||
inserted []rawdb.NumberHash // Ephemeral lookup of number/hash for the 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
|
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 {
|
for i, header := range headers {
|
||||||
var hash common.Hash
|
var hash common.Hash
|
||||||
@@ -264,10 +264,10 @@ func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) {
|
|||||||
alreadyKnown := parentKnown && hc.HasHeader(hash, number)
|
alreadyKnown := parentKnown && hc.HasHeader(hash, number)
|
||||||
if !alreadyKnown {
|
if !alreadyKnown {
|
||||||
// Irrelevant of the canonical status, write the TD and header to the database.
|
// 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))
|
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})
|
inserted = append(inserted, rawdb.NumberHash{Number: number, Hash: hash})
|
||||||
hc.headerCache.Add(hash, header)
|
hc.headerCache.Add(hash, header)
|
||||||
hc.numberCache.Add(hash, number)
|
hc.numberCache.Add(hash, number)
|
||||||
@@ -280,7 +280,7 @@ func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) {
|
|||||||
return 0, errors.New("aborted")
|
return 0, errors.New("aborted")
|
||||||
}
|
}
|
||||||
// Commit to disk!
|
// Commit to disk!
|
||||||
if err := batch.Write(); err != nil {
|
if err := blockBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to write headers", "error", err)
|
log.Crit("Failed to write headers", "error", err)
|
||||||
}
|
}
|
||||||
return len(inserted), nil
|
return len(inserted), nil
|
||||||
@@ -642,7 +642,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
|||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
parentHash common.Hash
|
parentHash common.Hash
|
||||||
batch = hc.chainDb.NewBatch()
|
blockBatch = hc.chainDb.BlockStore().NewBatch()
|
||||||
origin = true
|
origin = true
|
||||||
)
|
)
|
||||||
done := func(header *types.Header) bool {
|
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.
|
// first then remove the relative data from the database.
|
||||||
//
|
//
|
||||||
// Update head first(head fast block, head full block) before deleting the data.
|
// 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 {
|
if updateFn != nil {
|
||||||
newHead, force := updateFn(markerBatch, parent)
|
newHead, force := updateFn(markerBatch, parent)
|
||||||
if force && ((headTime > 0 && newHead.Time < headTime) || (headTime == 0 && newHead.Number.Uint64() < headBlock)) {
|
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
|
// we don't end up with dangling daps in the database
|
||||||
var nums []uint64
|
var nums []uint64
|
||||||
if origin {
|
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
|
nums = append([]uint64{n}, nums...) // suboptimal, but we don't really expect this path
|
||||||
}
|
}
|
||||||
origin = false
|
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
|
// Remove the related data from the database on all sidechains
|
||||||
for _, num := range nums {
|
for _, num := range nums {
|
||||||
// Gather all the side fork hashes
|
// Gather all the side fork hashes
|
||||||
hashes := rawdb.ReadAllHashes(hc.chainDb, num)
|
hashes := rawdb.ReadAllHashes(hc.chainDb.BlockStore(), num)
|
||||||
if len(hashes) == 0 {
|
if len(hashes) == 0 {
|
||||||
// No hashes in the database whatsoever, probably frozen already
|
// No hashes in the database whatsoever, probably frozen already
|
||||||
hashes = append(hashes, hdr.Hash())
|
hashes = append(hashes, hdr.Hash())
|
||||||
}
|
}
|
||||||
for _, hash := range hashes {
|
for _, hash := range hashes {
|
||||||
if delFn != nil {
|
if delFn != nil {
|
||||||
delFn(batch, hash, num)
|
delFn(blockBatch, hash, num)
|
||||||
}
|
}
|
||||||
rawdb.DeleteHeader(batch, hash, num)
|
rawdb.DeleteHeader(blockBatch, hash, num)
|
||||||
rawdb.DeleteTd(batch, hash, num)
|
rawdb.DeleteTd(blockBatch, hash, num)
|
||||||
}
|
}
|
||||||
rawdb.DeleteCanonicalHash(batch, num)
|
rawdb.DeleteCanonicalHash(blockBatch, num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Flush all accumulated deletions.
|
// Flush all accumulated deletions.
|
||||||
if err := batch.Write(); err != nil {
|
if err := blockBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to rewind block", "error", err)
|
log.Crit("Failed to rewind block", "error", err)
|
||||||
}
|
}
|
||||||
// Clear out any stale content from the caches
|
// Clear out any stale content from the caches
|
||||||
|
|||||||
@@ -34,14 +34,23 @@ import (
|
|||||||
"golang.org/x/exp/slices"
|
"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.
|
// ReadCanonicalHash retrieves the hash assigned to a canonical block number.
|
||||||
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
|
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
|
||||||
var data []byte
|
var data []byte
|
||||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||||
data, _ = reader.Ancient(ChainFreezerHashTable, number)
|
data, _ = reader.Ancient(ChainFreezerHashTable, number)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
// Get it by hash from leveldb
|
// Get it by hash from leveldb
|
||||||
data, _ = db.Get(headerHashKey(number))
|
data, _ = db.BlockStoreReader().Get(headerHashKey(number))
|
||||||
}
|
}
|
||||||
return nil
|
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.
|
// ReadHeaderNumber returns the header number assigned to a hash.
|
||||||
func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 {
|
func ReadHeaderNumber(db ethdb.MultiDatabaseReader, hash common.Hash) *uint64 {
|
||||||
data, _ := db.Get(headerNumberKey(hash))
|
data, _ := db.BlockStoreReader().Get(headerNumberKey(hash))
|
||||||
if len(data) != 8 {
|
if len(data) != 8 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -170,8 +179,8 @@ func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadHeadHeaderHash retrieves the hash of the current canonical head header.
|
// ReadHeadHeaderHash retrieves the hash of the current canonical head header.
|
||||||
func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash {
|
func ReadHeadHeaderHash(db ethdb.MultiDatabaseReader) common.Hash {
|
||||||
data, _ := db.Get(headHeaderKey)
|
data, _ := db.BlockStoreReader().Get(headHeaderKey)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return common.Hash{}
|
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.
|
// ReadHeadBlockHash retrieves the hash of the current canonical head block.
|
||||||
func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash {
|
func ReadHeadBlockHash(db ethdb.MultiDatabaseReader) common.Hash {
|
||||||
data, _ := db.Get(headBlockKey)
|
data, _ := db.BlockStoreReader().Get(headBlockKey)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return common.Hash{}
|
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.
|
// ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block.
|
||||||
func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash {
|
func ReadHeadFastBlockHash(db ethdb.MultiDatabaseReader) common.Hash {
|
||||||
data, _ := db.Get(headFastBlockKey)
|
data, _ := db.BlockStoreReader().Get(headFastBlockKey)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return common.Hash{}
|
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
|
// ReadLastPivotNumber retrieves the number of the last pivot block. If the node
|
||||||
// full synced, the last pivot will always be nil.
|
// full synced, the last pivot will always be nil.
|
||||||
func ReadLastPivotNumber(db ethdb.KeyValueReader) *uint64 {
|
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
|
// It's ok to request block 0, 1 item
|
||||||
count = number + 1
|
count = number + 1
|
||||||
}
|
}
|
||||||
limit, _ := db.Ancients()
|
limit, _ := db.BlockStoreReader().Ancients()
|
||||||
// First read live blocks
|
// First read live blocks
|
||||||
if i >= limit {
|
if i >= limit {
|
||||||
// If we need to read live blocks, we need to figure out the hash first
|
// If we need to read live blocks, we need to figure out the hash first
|
||||||
hash := ReadCanonicalHash(db, number)
|
hash := ReadCanonicalHash(db, number)
|
||||||
for ; i >= limit && count > 0; i-- {
|
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)
|
rlpHeaders = append(rlpHeaders, data)
|
||||||
// Get the parent hash for next query
|
// Get the parent hash for next query
|
||||||
hash = types.HeaderParentHashFromRLP(data)
|
hash = types.HeaderParentHashFromRLP(data)
|
||||||
@@ -300,8 +325,8 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
|
|||||||
if count == 0 {
|
if count == 0 {
|
||||||
return rlpHeaders
|
return rlpHeaders
|
||||||
}
|
}
|
||||||
// read remaining from ancients
|
// read remaining from ancients, cap at 2M
|
||||||
data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, 0)
|
data, err := db.BlockStoreReader().AncientRange(ChainFreezerHeaderTable, i+1-count, count, 2*1024*1024)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to read headers from freezer", "err", err)
|
log.Error("Failed to read headers from freezer", "err", err)
|
||||||
return rlpHeaders
|
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.
|
// ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
|
||||||
func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
var data []byte
|
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
|
// First try to look up the data in ancient database. Extra hash
|
||||||
// comparison is necessary since ancient database only maintains
|
// comparison is necessary since ancient database only maintains
|
||||||
// the canonical data.
|
// the canonical data.
|
||||||
@@ -329,7 +354,7 @@ func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValu
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If not, try reading from leveldb
|
// If not, try reading from leveldb
|
||||||
data, _ = db.Get(headerKey(number, hash))
|
data, _ = db.BlockStoreReader().Get(headerKey(number, hash))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return data
|
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.
|
// HasHeader verifies the existence of a block header corresponding to the hash.
|
||||||
func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||||
if isCanon(db, number, hash) {
|
if isCanon(db.BlockStoreReader(), number, hash) {
|
||||||
return true
|
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 false
|
||||||
}
|
}
|
||||||
return true
|
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
|
// comparison is necessary since ancient database only maintains
|
||||||
// the canonical data.
|
// the canonical data.
|
||||||
var data []byte
|
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
|
// Check if the data is in ancients
|
||||||
if isCanon(reader, number, hash) {
|
if isCanon(reader, number, hash) {
|
||||||
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If not, try reading from leveldb
|
// If not, try reading from leveldb
|
||||||
data, _ = db.Get(blockBodyKey(number, hash))
|
data, _ = db.BlockStoreReader().Get(blockBodyKey(number, hash))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return data
|
return data
|
||||||
@@ -444,7 +469,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
|
|||||||
// block at number, in RLP encoding.
|
// block at number, in RLP encoding.
|
||||||
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
|
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
|
||||||
var data []byte
|
var data []byte
|
||||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||||
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
return nil
|
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.
|
// Block is not in ancients, read from leveldb by hash and number.
|
||||||
// Note: ReadCanonicalHash cannot be used here because it also
|
// Note: ReadCanonicalHash cannot be used here because it also
|
||||||
// calls ReadAncients internally.
|
// calls ReadAncients internally.
|
||||||
hash, _ := db.Get(headerHashKey(number))
|
hash, _ := db.BlockStoreReader().Get(headerHashKey(number))
|
||||||
data, _ = db.Get(blockBodyKey(number, common.BytesToHash(hash)))
|
data, _ = db.BlockStoreReader().Get(blockBodyKey(number, common.BytesToHash(hash)))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return data
|
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.
|
// HasBody verifies the existence of a block body corresponding to the hash.
|
||||||
func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||||
if isCanon(db, number, hash) {
|
if isCanon(db.BlockStoreReader(), number, hash) {
|
||||||
return true
|
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 false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -500,6 +525,13 @@ func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *t
|
|||||||
WriteBodyRLP(db, hash, number, data)
|
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) {
|
func WriteDiffLayer(db ethdb.KeyValueWriter, hash common.Hash, layer *types.DiffLayer) {
|
||||||
data, err := rlp.EncodeToBytes(layer)
|
data, err := rlp.EncodeToBytes(layer)
|
||||||
if err != nil {
|
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.
|
// 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 {
|
func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
var data []byte
|
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
|
// Check if the data is in ancients
|
||||||
if isCanon(reader, number, hash) {
|
if isCanon(reader, number, hash) {
|
||||||
data, _ = reader.Ancient(ChainFreezerDifficultyTable, number)
|
data, _ = reader.Ancient(ChainFreezerDifficultyTable, number)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If not, try reading from leveldb
|
// If not, try reading from leveldb
|
||||||
data, _ = db.Get(headerTDKey(number, hash))
|
data, _ = db.BlockStoreReader().Get(headerTDKey(number, hash))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return data
|
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
|
// HasReceipts verifies the existence of all the transaction receipts belonging
|
||||||
// to a block.
|
// to a block.
|
||||||
func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||||
if isCanon(db, number, hash) {
|
if isCanon(db.BlockStoreReader(), number, hash) {
|
||||||
return true
|
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 false
|
||||||
}
|
}
|
||||||
return true
|
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.
|
// 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 {
|
func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
var data []byte
|
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
|
// Check if the data is in ancients
|
||||||
if isCanon(reader, number, hash) {
|
if isCanon(reader, number, hash) {
|
||||||
data, _ = reader.Ancient(ChainFreezerReceiptTable, number)
|
data, _ = reader.Ancient(ChainFreezerReceiptTable, number)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If not, try reading from leveldb
|
// If not, try reading from leveldb
|
||||||
data, _ = db.Get(blockReceiptsKey(number, hash))
|
data, _ = db.BlockStoreReader().Get(blockReceiptsKey(number, hash))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return data
|
return data
|
||||||
@@ -808,7 +833,7 @@ func WriteAncientBlocksWithBlobs(db ethdb.AncientWriter, blocks []*types.Block,
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Info("WriteAncientBlocks", "startAt", blocks[0].Number(), "cancunIndex", cancunIndex, "len", len(blocks))
|
log.Debug("WriteAncientBlocks", "startAt", blocks[0].Number(), "cancunIndex", cancunIndex, "len", len(blocks))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tdSum = new(big.Int).Set(td)
|
tdSum = new(big.Int).Set(td)
|
||||||
@@ -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.
|
// 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 {
|
func ReadBlobSidecarsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
var data []byte
|
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
|
// Check if the data is in ancients
|
||||||
if isCanon(reader, number, hash) {
|
if isCanon(reader, number, hash) {
|
||||||
data, _ = reader.Ancient(ChainFreezerBlobSidecarTable, number)
|
data, _ = reader.Ancient(ChainFreezerBlobSidecarTable, number)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If not, try reading from leveldb
|
// If not, try reading from leveldb
|
||||||
data, _ = db.Get(blockBlobSidecarsKey(number, hash))
|
data, _ = db.BlockStoreReader().Get(blockBlobSidecarsKey(number, hash))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return data
|
return data
|
||||||
|
|||||||
@@ -518,7 +518,7 @@ func checkBlobSidecarsRLP(have, want types.BlobSidecars) error {
|
|||||||
func TestAncientStorage(t *testing.T) {
|
func TestAncientStorage(t *testing.T) {
|
||||||
// Freezer style fast import the chain.
|
// Freezer style fast import the chain.
|
||||||
frdir := t.TempDir()
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create database with ancient backend")
|
t.Fatalf("failed to create database with ancient backend")
|
||||||
}
|
}
|
||||||
@@ -657,7 +657,7 @@ func TestHashesInRange(t *testing.T) {
|
|||||||
func BenchmarkWriteAncientBlocks(b *testing.B) {
|
func BenchmarkWriteAncientBlocks(b *testing.B) {
|
||||||
// Open freezer database.
|
// Open freezer database.
|
||||||
frdir := b.TempDir()
|
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 {
|
if err != nil {
|
||||||
b.Fatalf("failed to create database with ancient backend")
|
b.Fatalf("failed to create database with ancient backend")
|
||||||
}
|
}
|
||||||
@@ -1001,7 +1001,7 @@ func TestHeadersRLPStorage(t *testing.T) {
|
|||||||
// Have N headers in the freezer
|
// Have N headers in the freezer
|
||||||
frdir := t.TempDir()
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to create database with ancient backend")
|
t.Fatalf("failed to create database with ancient backend")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package rawdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@@ -98,6 +100,18 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
f, err := NewStateFreezer(datadir, true, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// 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.
|
// be opened. Start and end specify the range for dumping out indexes.
|
||||||
// Note this function can only be used for debugging purposes.
|
// 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 (
|
var (
|
||||||
path string
|
path string
|
||||||
tables map[string]bool
|
tables map[string]bool
|
||||||
)
|
)
|
||||||
switch freezerName {
|
switch freezerName {
|
||||||
case ChainFreezerName:
|
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:
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,19 @@
|
|||||||
package rawdb
|
package rawdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -42,6 +43,10 @@ const (
|
|||||||
freezerBatchLimit = 30000
|
freezerBatchLimit = 30000
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
missFreezerEnvErr = errors.New("missing freezer env error")
|
||||||
|
)
|
||||||
|
|
||||||
// chainFreezer is a wrapper of freezer with additional chain freezing feature.
|
// chainFreezer is a wrapper of freezer with additional chain freezing feature.
|
||||||
// The background thread will keep moving ancient chain segments from key-value
|
// The background thread will keep moving ancient chain segments from key-value
|
||||||
// database to flat files for saving space on live database.
|
// database to flat files for saving space on live database.
|
||||||
@@ -53,11 +58,14 @@ type chainFreezer struct {
|
|||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
trigger chan chan struct{} // Manual blocking freeze trigger, test determinism
|
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.
|
// 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)
|
freezer, err := NewChainFreezer(datadir, namespace, readonly, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -82,6 +90,57 @@ func (f *chainFreezer) Close() error {
|
|||||||
return f.Freezer.Close()
|
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
|
// 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.
|
// import progress and moves ancient data from the fast database into the freezer.
|
||||||
//
|
//
|
||||||
@@ -119,61 +178,126 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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:
|
var (
|
||||||
log.Debug("Current full block not old enough to freeze", "number", *number, "hash", hash, "delay", threshold)
|
frozen uint64
|
||||||
backoff = true
|
threshold uint64
|
||||||
continue
|
first uint64 // the first block to freeze
|
||||||
|
last uint64 // the last block to freeze
|
||||||
|
|
||||||
case *number-threshold <= frozen:
|
hash common.Hash
|
||||||
log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", frozen)
|
number *uint64
|
||||||
backoff = true
|
head *types.Header
|
||||||
continue
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
head := ReadHeader(nfdb, hash, *number)
|
|
||||||
if head == nil {
|
// check env first before chain freeze, it must wait when the env is necessary
|
||||||
log.Error("Current full block unavailable", "number", *number, "hash", hash)
|
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
|
backoff = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seems we have data ready to be frozen, process in usable batches
|
// Seems we have data ready to be frozen, process in usable batches
|
||||||
var (
|
var (
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
first, _ = f.Ancients()
|
|
||||||
limit = *number - threshold
|
|
||||||
)
|
)
|
||||||
if limit-first > freezerBatchLimit {
|
|
||||||
limit = first + freezerBatchLimit
|
|
||||||
}
|
|
||||||
|
|
||||||
ancients, err := f.freezeRangeWithBlobs(nfdb, first, limit)
|
ancients, err := f.freezeRangeWithBlobs(nfdb, first, last)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error in block freeze operation", "err", err)
|
log.Error("Error in block freeze operation", "err", err)
|
||||||
backoff = true
|
backoff = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Batch of blocks have been frozen, flush them before wiping from leveldb
|
// Batch of blocks have been frozen, flush them before wiping from leveldb
|
||||||
if err := f.Sync(); err != nil {
|
if err := f.Sync(); err != nil {
|
||||||
log.Crit("Failed to flush frozen tables", "err", err)
|
log.Crit("Failed to flush frozen tables", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wipe out all data from the active database
|
// Wipe out all data from the active database
|
||||||
batch := db.NewBatch()
|
batch := db.NewBatch()
|
||||||
for i := 0; i < len(ancients); i++ {
|
for i := 0; i < len(ancients); i++ {
|
||||||
@@ -278,7 +402,7 @@ func (f *chainFreezer) tryPruneBlobAncientTable(env *ethdb.FreezerEnv, num uint6
|
|||||||
log.Error("Cannot prune blob ancient", "block", num, "expectTail", expectTail, "err", err)
|
log.Error("Cannot prune blob ancient", "block", num, "expectTail", expectTail, "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("Chain freezer prune useless blobs, now ancient data is", "from", expectTail, "to", num, "cost", common.PrettyDuration(time.Since(start)))
|
log.Debug("Chain freezer prune useless blobs, now ancient data is", "from", expectTail, "to", num, "cost", common.PrettyDuration(time.Since(start)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBlobExtraReserveFromEnv(env *ethdb.FreezerEnv) uint64 {
|
func getBlobExtraReserveFromEnv(env *ethdb.FreezerEnv) uint64 {
|
||||||
@@ -290,7 +414,7 @@ func getBlobExtraReserveFromEnv(env *ethdb.FreezerEnv) uint64 {
|
|||||||
|
|
||||||
func (f *chainFreezer) freezeRangeWithBlobs(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) {
|
func (f *chainFreezer) freezeRangeWithBlobs(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
log.Info("freezeRangeWithBlobs", "from", number, "to", limit, "err", err)
|
log.Debug("freezeRangeWithBlobs", "from", number, "to", limit, "err", err)
|
||||||
}()
|
}()
|
||||||
lastHash := ReadCanonicalHash(nfdb, limit)
|
lastHash := ReadCanonicalHash(nfdb, limit)
|
||||||
if lastHash == (common.Hash{}) {
|
if lastHash == (common.Hash{}) {
|
||||||
@@ -339,13 +463,16 @@ func (f *chainFreezer) freezeRangeWithBlobs(nfdb *nofreezedb, number, limit uint
|
|||||||
return hashes, err
|
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) {
|
func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) {
|
||||||
if number > limit {
|
if number > limit {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
env, _ := f.freezeEnv.Load().(*ethdb.FreezerEnv)
|
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 {
|
_, err = f.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
||||||
for ; number <= limit; number++ {
|
for ; number <= limit; number++ {
|
||||||
// Retrieve all the components of the canonical block.
|
// Retrieve all the components of the canonical block.
|
||||||
@@ -413,6 +540,14 @@ func (f *chainFreezer) SetupFreezerEnv(env *ethdb.FreezerEnv) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *chainFreezer) checkFreezerEnv() error {
|
||||||
|
_, exist := f.freezeEnv.Load().(*ethdb.FreezerEnv)
|
||||||
|
if exist {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return missFreezerEnvErr
|
||||||
|
}
|
||||||
|
|
||||||
func isCancun(env *ethdb.FreezerEnv, num *big.Int, time uint64) bool {
|
func isCancun(env *ethdb.FreezerEnv, num *big.Int, time uint64) bool {
|
||||||
if env == nil || env.ChainCfg == nil {
|
if env == nil || env.ChainCfg == nil {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -35,16 +35,16 @@ import (
|
|||||||
// injects into the database the block hash->number mappings.
|
// injects into the database the block hash->number mappings.
|
||||||
func InitDatabaseFromFreezer(db ethdb.Database) {
|
func InitDatabaseFromFreezer(db ethdb.Database) {
|
||||||
// If we can't access the freezer or it's empty, abort
|
// 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 {
|
if err != nil || frozen == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
batch = db.NewBatch()
|
batch = db.BlockStore().NewBatch()
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log
|
logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log
|
||||||
hash common.Hash
|
hash common.Hash
|
||||||
offset = db.AncientOffSet()
|
offset = db.BlockStore().AncientOffSet()
|
||||||
)
|
)
|
||||||
for i := uint64(0) + offset; i < frozen+offset; i++ {
|
for i := uint64(0) + offset; i < frozen+offset; i++ {
|
||||||
// We read 100K hashes at a time, for a total of 3.2M
|
// 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 {
|
if i+count > frozen+offset {
|
||||||
count = frozen + offset - i
|
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 {
|
if err != nil {
|
||||||
log.Crit("Failed to init database from freezer", "err", err)
|
log.Crit("Failed to init database from freezer", "err", err)
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,8 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
|||||||
}
|
}
|
||||||
batch.Reset()
|
batch.Reset()
|
||||||
|
|
||||||
WriteHeadHeaderHash(db, hash)
|
WriteHeadHeaderHash(db.BlockStore(), hash)
|
||||||
WriteHeadFastBlockHash(db, hash)
|
WriteHeadFastBlockHash(db.BlockStore(), hash)
|
||||||
log.Info("Initialized database from freezer", "blocks", frozen, "elapsed", common.PrettyDuration(time.Since(start)))
|
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
|
number uint64
|
||||||
rlp rlp.RawValue
|
rlp rlp.RawValue
|
||||||
}
|
}
|
||||||
if offset := db.AncientOffSet(); offset > from {
|
if offset := db.BlockStore().AncientOffSet(); offset > from {
|
||||||
from = offset
|
from = offset
|
||||||
}
|
}
|
||||||
if to <= from {
|
if to <= from {
|
||||||
@@ -187,7 +187,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
|
|||||||
// signal received.
|
// signal received.
|
||||||
func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
||||||
// short circuit for invalid range
|
// short circuit for invalid range
|
||||||
if offset := db.AncientOffSet(); offset > from {
|
if offset := db.BlockStore().AncientOffSet(); offset > from {
|
||||||
from = offset
|
from = offset
|
||||||
}
|
}
|
||||||
if from >= to {
|
if from >= to {
|
||||||
@@ -286,7 +286,7 @@ func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, inte
|
|||||||
// signal received.
|
// signal received.
|
||||||
func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
||||||
// short circuit for invalid range
|
// short circuit for invalid range
|
||||||
if offset := db.AncientOffSet(); offset > from {
|
if offset := db.BlockStore().AncientOffSet(); offset > from {
|
||||||
from = offset
|
from = offset
|
||||||
}
|
}
|
||||||
if from >= to {
|
if from >= to {
|
||||||
|
|||||||
@@ -26,14 +26,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/olekukonko/tablewriter"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/leveldb"
|
"github.com/ethereum/go-ethereum/ethdb/leveldb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/olekukonko/tablewriter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// freezerdb is a database wrapper that enables freezer data retrievals.
|
// freezerdb is a database wrapper that enables freezer data retrievals.
|
||||||
@@ -44,6 +43,7 @@ type freezerdb struct {
|
|||||||
ethdb.AncientFreezer
|
ethdb.AncientFreezer
|
||||||
diffStore ethdb.KeyValueStore
|
diffStore ethdb.KeyValueStore
|
||||||
stateStore ethdb.Database
|
stateStore ethdb.Database
|
||||||
|
blockStore ethdb.Database
|
||||||
}
|
}
|
||||||
|
|
||||||
func (frdb *freezerdb) StateStoreReader() ethdb.Reader {
|
func (frdb *freezerdb) StateStoreReader() ethdb.Reader {
|
||||||
@@ -53,6 +53,20 @@ func (frdb *freezerdb) StateStoreReader() ethdb.Reader {
|
|||||||
return frdb.stateStore
|
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.
|
// AncientDatadir returns the path of root ancient directory.
|
||||||
func (frdb *freezerdb) AncientDatadir() (string, error) {
|
func (frdb *freezerdb) AncientDatadir() (string, error) {
|
||||||
return frdb.ancientRoot, nil
|
return frdb.ancientRoot, nil
|
||||||
@@ -78,6 +92,11 @@ func (frdb *freezerdb) Close() error {
|
|||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if frdb.blockStore != nil {
|
||||||
|
if err := frdb.blockStore.Close(); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
return fmt.Errorf("%v", errs)
|
return fmt.Errorf("%v", errs)
|
||||||
}
|
}
|
||||||
@@ -99,6 +118,13 @@ func (frdb *freezerdb) StateStore() ethdb.Database {
|
|||||||
return frdb.stateStore
|
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) {
|
func (frdb *freezerdb) SetStateStore(state ethdb.Database) {
|
||||||
if frdb.stateStore != nil {
|
if frdb.stateStore != nil {
|
||||||
frdb.stateStore.Close()
|
frdb.stateStore.Close()
|
||||||
@@ -106,6 +132,25 @@ func (frdb *freezerdb) SetStateStore(state ethdb.Database) {
|
|||||||
frdb.stateStore = state
|
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
|
// 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
|
// a freeze cycle completes, without having to sleep for a minute to trigger the
|
||||||
// automatic background run.
|
// automatic background run.
|
||||||
@@ -118,7 +163,6 @@ func (frdb *freezerdb) Freeze(threshold uint64) error {
|
|||||||
frdb.AncientStore.(*chainFreezer).threshold.Store(old)
|
frdb.AncientStore.(*chainFreezer).threshold.Store(old)
|
||||||
}(frdb.AncientStore.(*chainFreezer).threshold.Load())
|
}(frdb.AncientStore.(*chainFreezer).threshold.Load())
|
||||||
frdb.AncientStore.(*chainFreezer).threshold.Store(threshold)
|
frdb.AncientStore.(*chainFreezer).threshold.Store(threshold)
|
||||||
|
|
||||||
// Trigger a freeze cycle and block until it's done
|
// Trigger a freeze cycle and block until it's done
|
||||||
trigger := make(chan struct{}, 1)
|
trigger := make(chan struct{}, 1)
|
||||||
frdb.AncientStore.(*chainFreezer).trigger <- trigger
|
frdb.AncientStore.(*chainFreezer).trigger <- trigger
|
||||||
@@ -135,6 +179,7 @@ type nofreezedb struct {
|
|||||||
ethdb.KeyValueStore
|
ethdb.KeyValueStore
|
||||||
diffStore ethdb.KeyValueStore
|
diffStore ethdb.KeyValueStore
|
||||||
stateStore ethdb.Database
|
stateStore ethdb.Database
|
||||||
|
blockStore ethdb.Database
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasAncient returns an error as we don't have a backing chain freezer.
|
// 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
|
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) {
|
func (db *nofreezedb) ItemAmountInAncient() (uint64, error) {
|
||||||
return 0, errNotSupported
|
return 0, errNotSupported
|
||||||
}
|
}
|
||||||
@@ -218,6 +263,13 @@ func (db *nofreezedb) SetStateStore(state ethdb.Database) {
|
|||||||
db.stateStore = state
|
db.stateStore = state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *nofreezedb) GetStateStore() ethdb.Database {
|
||||||
|
if db.stateStore != nil {
|
||||||
|
return db.stateStore
|
||||||
|
}
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|
||||||
func (db *nofreezedb) StateStoreReader() ethdb.Reader {
|
func (db *nofreezedb) StateStoreReader() ethdb.Reader {
|
||||||
if db.stateStore != nil {
|
if db.stateStore != nil {
|
||||||
return db.stateStore
|
return db.stateStore
|
||||||
@@ -225,6 +277,35 @@ func (db *nofreezedb) StateStoreReader() ethdb.Reader {
|
|||||||
return db
|
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) {
|
func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) {
|
||||||
// Unlike other ancient-related methods, this method does not return
|
// Unlike other ancient-related methods, this method does not return
|
||||||
// errNotSupported when invoked.
|
// errNotSupported when invoked.
|
||||||
@@ -266,6 +347,111 @@ func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
|
|||||||
return &nofreezedb{KeyValueStore: db}
|
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.
|
// NewFreezerDb only create a freezer without statedb.
|
||||||
func NewFreezerDb(db ethdb.KeyValueStore, frz, namespace string, readonly bool, newOffSet uint64) (*Freezer, error) {
|
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.
|
// 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
|
// value data store with a freezer moving immutable chain segments into cold
|
||||||
// storage. The passed ancient indicates the path of root ancient directory
|
// storage. The passed ancient indicates the path of root ancient directory
|
||||||
// where the chain freezer can be opened.
|
// 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
|
var offset uint64
|
||||||
// The offset of ancientDB should be handled differently in different scenarios.
|
// The offset of ancientDB should be handled differently in different scenarios.
|
||||||
if isLastOffset {
|
if isLastOffset {
|
||||||
@@ -315,6 +501,12 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
|||||||
offset = ReadOffSetOfCurrentAncientFreezer(db)
|
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 {
|
if pruneAncientData && !disableFreeze && !readonly {
|
||||||
frdb, err := newPrunedFreezer(resolveChainFreezerDir(ancient), db, offset)
|
frdb, err := newPrunedFreezer(resolveChainFreezerDir(ancient), db, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -342,9 +534,18 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the idle freezer instance
|
// 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 {
|
if err != nil {
|
||||||
printChainMetadata(db)
|
printChainMetadata(freezerDb)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,10 +581,10 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
|||||||
// the freezer and the key-value store.
|
// the freezer and the key-value store.
|
||||||
frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
|
frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printChainMetadata(db)
|
printChainMetadata(freezerDb)
|
||||||
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
|
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
|
||||||
} else if !bytes.Equal(kvgenesis, frgenesis) {
|
} else if !bytes.Equal(kvgenesis, frgenesis) {
|
||||||
printChainMetadata(db)
|
printChainMetadata(freezerDb)
|
||||||
return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis)
|
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
|
// 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 {
|
if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 {
|
||||||
// Subsequent header after the freezer limit is missing from the database.
|
// Subsequent header after the freezer limit is missing from the database.
|
||||||
// Reject startup if the database has a more recent head.
|
// 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
|
// Find the smallest block stored in the key-value store
|
||||||
// in range of [frozen, head]
|
// in range of [frozen, head]
|
||||||
var number uint64
|
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
|
// 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] ",
|
return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
|
||||||
frozen-1, number, head)
|
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
|
// 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
|
// if we froze anything previously or not, but do take care of databases with
|
||||||
// only the genesis block.
|
// 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
|
// Key-value store contains more data than the genesis block, make sure we
|
||||||
// didn't freeze anything yet.
|
// didn't freeze anything yet.
|
||||||
if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 {
|
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")
|
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
|
// 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.
|
// freezer.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no prune ancient start success
|
// no prune ancient start success
|
||||||
if !readonly {
|
if !readonly {
|
||||||
WriteAncientType(db, EntireFreezerType)
|
WriteAncientType(db, EntireFreezerType)
|
||||||
@@ -441,12 +643,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
|||||||
frdb.wg.Done()
|
frdb.wg.Done()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
return &freezerdb{
|
return freezerDb, nil
|
||||||
ancientRoot: ancient,
|
|
||||||
KeyValueStore: db,
|
|
||||||
AncientStore: frdb,
|
|
||||||
AncientFreezer: frdb,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMemoryDatabase creates an ephemeral in-memory key-value database without a
|
// NewMemoryDatabase creates an ephemeral in-memory key-value database without a
|
||||||
@@ -518,9 +715,12 @@ type OpenOptions struct {
|
|||||||
DisableFreeze bool
|
DisableFreeze bool
|
||||||
IsLastOffset bool
|
IsLastOffset bool
|
||||||
PruneAncientData bool
|
PruneAncientData bool
|
||||||
|
|
||||||
// Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of
|
// 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.
|
// a crash is not important. This option should typically be used in tests.
|
||||||
Ephemeral bool
|
Ephemeral bool
|
||||||
|
|
||||||
|
MultiDataBase bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble.
|
// 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 ReadAncientType(kvdb) == PruneFreezerType {
|
||||||
if !o.PruneAncientData {
|
if !o.PruneAncientData {
|
||||||
log.Warn("Disk db is pruned")
|
log.Warn("NOTICE: You're opening a pruned disk db!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(o.AncientsDirectory) == 0 {
|
if len(o.AncientsDirectory) == 0 {
|
||||||
return kvdb, nil
|
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 {
|
if err != nil {
|
||||||
kvdb.Close()
|
kvdb.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -613,7 +813,7 @@ func AncientInspect(db ethdb.Database) error {
|
|||||||
offset := counter(ReadOffSetOfCurrentAncientFreezer(db))
|
offset := counter(ReadOffSetOfCurrentAncientFreezer(db))
|
||||||
// Get number of ancient rows inside the freezer.
|
// Get number of ancient rows inside the freezer.
|
||||||
ancients := counter(0)
|
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)
|
log.Error("failed to get the items amount in ancientDB", "err", err)
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@@ -661,6 +861,48 @@ func PruneHashTrieNodeInDataBase(db ethdb.Database) error {
|
|||||||
return nil
|
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
|
// InspectDatabase traverses the entire database and checks the size
|
||||||
// of all different categories of data.
|
// of all different categories of data.
|
||||||
func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
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()
|
defer it.Release()
|
||||||
|
|
||||||
var trieIter ethdb.Iterator
|
var trieIter ethdb.Iterator
|
||||||
|
var blockIter ethdb.Iterator
|
||||||
if db.StateStore() != nil {
|
if db.StateStore() != nil {
|
||||||
trieIter = db.StateStore().NewIterator(keyPrefix, nil)
|
trieIter = db.StateStore().NewIterator(keyPrefix, nil)
|
||||||
defer trieIter.Release()
|
defer trieIter.Release()
|
||||||
}
|
}
|
||||||
|
if db.HasSeparateBlockStore() {
|
||||||
|
blockIter = db.BlockStore().NewIterator(keyPrefix, nil)
|
||||||
|
defer blockIter.Release()
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
count int64
|
count int64
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
@@ -801,6 +1048,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
|||||||
value = trieIter.Value()
|
value = trieIter.Value()
|
||||||
size = common.StorageSize(len(key) + len(value))
|
size = common.StorageSize(len(key) + len(value))
|
||||||
)
|
)
|
||||||
|
total += size
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case IsLegacyTrieNode(key, value):
|
case IsLegacyTrieNode(key, value):
|
||||||
@@ -814,9 +1062,10 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
|||||||
default:
|
default:
|
||||||
var accounted bool
|
var accounted bool
|
||||||
for _, meta := range [][]byte{
|
for _, meta := range [][]byte{
|
||||||
fastTrieProgressKey, persistentStateIDKey, trieJournalKey} {
|
fastTrieProgressKey, persistentStateIDKey, trieJournalKey, snapSyncStatusFlagKey} {
|
||||||
if bytes.Equal(key, meta) {
|
if bytes.Equal(key, meta) {
|
||||||
metadata.Add(size)
|
metadata.Add(size)
|
||||||
|
accounted = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -830,6 +1079,54 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
|||||||
logged = time.Now()
|
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.
|
// Display the database statistic of key-value store.
|
||||||
stats := [][]string{
|
stats := [][]string{
|
||||||
@@ -856,7 +1153,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
|||||||
{"Light client", "Bloom trie nodes", bloomTrieNodes.Size(), bloomTrieNodes.Count()},
|
{"Light client", "Bloom trie nodes", bloomTrieNodes.Size(), bloomTrieNodes.Count()},
|
||||||
}
|
}
|
||||||
// Inspect all registered append-only file store then.
|
// Inspect all registered append-only file store then.
|
||||||
ancients, err := inspectFreezers(db)
|
ancients, err := inspectFreezers(db.BlockStore())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -962,7 +1259,7 @@ func DeleteTrieState(db ethdb.Database) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// printChainMetadata prints out chain metadata to stderr.
|
// printChainMetadata prints out chain metadata to stderr.
|
||||||
func printChainMetadata(db ethdb.KeyValueStore) {
|
func printChainMetadata(db ethdb.Reader) {
|
||||||
fmt.Fprintf(os.Stderr, "Chain metadata\n")
|
fmt.Fprintf(os.Stderr, "Chain metadata\n")
|
||||||
for _, v := range ReadChainMetadata(db) {
|
for _, v := range ReadChainMetadata(db) {
|
||||||
fmt.Fprintf(os.Stderr, " %s\n", strings.Join(v, ": "))
|
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
|
// ReadChainMetadata returns a set of key/value pairs that contains information
|
||||||
// about the database chain status. This can be used for diagnostic purposes
|
// about the database chain status. This can be used for diagnostic purposes
|
||||||
// when investigating the state of the node.
|
// when investigating the state of the node.
|
||||||
func ReadChainMetadata(db ethdb.KeyValueStore) [][]string {
|
func ReadChainMetadata(db ethdb.Reader) [][]string {
|
||||||
pp := func(val *uint64) string {
|
pp := func(val *uint64) string {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return "<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.
|
// - 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) {
|
func (f *Freezer) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) {
|
||||||
if table := f.tables[kind]; table != nil {
|
if table := f.tables[kind]; table != nil {
|
||||||
return table.RetrieveItems(start, count, maxBytes)
|
return table.RetrieveItems(start-f.offset, count, maxBytes)
|
||||||
}
|
}
|
||||||
return nil, errUnknownTable
|
return nil, errUnknownTable
|
||||||
}
|
}
|
||||||
@@ -252,7 +252,7 @@ func (f *Freezer) Ancients() (uint64, error) {
|
|||||||
func (f *Freezer) TableAncients(kind string) (uint64, error) {
|
func (f *Freezer) TableAncients(kind string) (uint64, error) {
|
||||||
f.writeLock.RLock()
|
f.writeLock.RLock()
|
||||||
defer f.writeLock.RUnlock()
|
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.
|
// 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()
|
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
|
// Log something friendly for the user
|
||||||
context := []interface{}{
|
context := []interface{}{
|
||||||
"blocks", frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", frozen - 1,
|
"blocks", frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", frozen - 1,
|
||||||
@@ -765,7 +730,7 @@ func (f *Freezer) ResetTable(kind string, startAt uint64, onlyEmpty bool) error
|
|||||||
f.frozen.Add(f.offset)
|
f.frozen.Add(f.offset)
|
||||||
f.tail.Add(f.offset)
|
f.tail.Add(f.offset)
|
||||||
f.writeBatch = newFreezerBatch(f)
|
f.writeBatch = newFreezerBatch(f)
|
||||||
log.Info("Reset Table", "kind", kind, "tail", f.tables[kind].itemHidden.Load(), "frozen", f.tables[kind].items.Load())
|
log.Debug("Reset Table", "kind", kind, "tail", f.tables[kind].itemHidden.Load(), "frozen", f.tables[kind].items.Load())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
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
|
// 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
|
// non-existent. Both files are truncated to the shortest common length to ensure
|
||||||
// they don't go out of sync.
|
// they don't go out of sync.
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"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.
|
// repair init frozen , compatible disk-ancientdb and pruner-block-tool.
|
||||||
func (f *prunedfreezer) repair(datadir string) error {
|
func (f *prunedfreezer) repair(datadir string) error {
|
||||||
offset := atomic.LoadUint64(&f.frozen)
|
|
||||||
// compatible freezer
|
// compatible freezer
|
||||||
min := uint64(math.MaxUint64)
|
minItems := uint64(math.MaxUint64)
|
||||||
for name, disableSnappy := range chainFreezerNoSnappy {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// addition tables only align head
|
||||||
|
if slices.Contains(additionTables, name) {
|
||||||
|
if EmptyTable(table) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
items := table.items.Load()
|
items := table.items.Load()
|
||||||
if min > items {
|
if minItems > items {
|
||||||
min = items
|
minItems = items
|
||||||
}
|
}
|
||||||
table.Close()
|
table.Close()
|
||||||
}
|
}
|
||||||
log.Info("Read ancientdb item counts", "items", min)
|
|
||||||
offset += min
|
|
||||||
|
|
||||||
if frozen := ReadFrozenOfAncientFreezer(f.db); frozen > offset {
|
// If minItems is non-zero, it indicates that the chain freezer was previously enabled, and we should use minItems as the current frozen value.
|
||||||
offset = frozen
|
// 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 {
|
if err := f.Sync(); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -299,9 +322,8 @@ func (f *prunedfreezer) freeze() {
|
|||||||
log.Error("Append ancient err", "number", f.frozen, "hash", hash, "err", err)
|
log.Error("Append ancient err", "number", f.frozen, "hash", hash, "err", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if hash != (common.Hash{}) {
|
// may include common.Hash{}, will be delete in gcKvStore
|
||||||
ancients = append(ancients, hash)
|
ancients = append(ancients, hash)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Batch of blocks have been frozen, flush them before wiping from leveldb
|
// Batch of blocks have been frozen, flush them before wiping from leveldb
|
||||||
if err := f.Sync(); err != nil {
|
if err := f.Sync(); err != nil {
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ var (
|
|||||||
// headFastBlockKey tracks the latest known incomplete block's hash during fast sync.
|
// headFastBlockKey tracks the latest known incomplete block's hash during fast sync.
|
||||||
headFastBlockKey = []byte("LastFast")
|
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 tracks the id of latest stored state(for path-based only).
|
||||||
persistentStateIDKey = []byte("LastStateID")
|
persistentStateIDKey = []byte("LastStateID")
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,26 @@ type table struct {
|
|||||||
prefix string
|
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.
|
// NewTable returns a database object that prefixes all keys with a given string.
|
||||||
func NewTable(db ethdb.Database, prefix string) ethdb.Database {
|
func NewTable(db ethdb.Database, prefix string) ethdb.Database {
|
||||||
return &table{
|
return &table{
|
||||||
@@ -231,6 +251,10 @@ func (t *table) SetStateStore(state ethdb.Database) {
|
|||||||
panic("not implement")
|
panic("not implement")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *table) GetStateStore() ethdb.Database {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *table) StateStoreReader() ethdb.Reader {
|
func (t *table) StateStoreReader() ethdb.Reader {
|
||||||
return nil
|
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)))
|
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)
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(maindb), nil)
|
||||||
for addr, account := range g.Alloc {
|
for addr, account := range g.Alloc {
|
||||||
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
|
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")
|
log.Info("chainDB opened successfully")
|
||||||
|
|
||||||
// Get the number of items in old ancient db.
|
// 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)
|
log.Info("the number of items in ancientDB is ", "itemsOfAncient", itemsOfAncient)
|
||||||
|
|
||||||
// If we can't access the freezer or it's empty, abort.
|
// 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
|
var oldOffSet uint64
|
||||||
if interrupt {
|
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
|
// 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.
|
// actually of the new ancientDB_Backup, but what we want is the offset of ancientDB being backup.
|
||||||
oldOffSet = rawdb.ReadOffSetOfLastAncientFreezer(chainDb)
|
oldOffSet = rawdb.ReadOffSetOfLastAncientFreezer(chainDb)
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ type Tree struct {
|
|||||||
// state trie.
|
// state trie.
|
||||||
// - otherwise, the entire snapshot is considered invalid and will be recreated on
|
// - otherwise, the entire snapshot is considered invalid and will be recreated on
|
||||||
// a background thread.
|
// 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) {
|
func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, root common.Hash, cap int, withoutTrie bool) (*Tree, error) {
|
||||||
snap := &Tree{
|
snap := &Tree{
|
||||||
config: config,
|
config: config,
|
||||||
|
|||||||
@@ -933,8 +933,8 @@ func (s *StateDB) copyInternal(doPrefetch bool) *StateDB {
|
|||||||
// along with their original values.
|
// along with their original values.
|
||||||
state.accounts = copySet(s.accounts)
|
state.accounts = copySet(s.accounts)
|
||||||
state.storages = copy2DSet(s.storages)
|
state.storages = copy2DSet(s.storages)
|
||||||
state.accountsOrigin = copySet(state.accountsOrigin)
|
state.accountsOrigin = copySet(s.accountsOrigin)
|
||||||
state.storagesOrigin = copy2DSet(state.storagesOrigin)
|
state.storagesOrigin = copy2DSet(s.storagesOrigin)
|
||||||
|
|
||||||
// Deep copy the logs occurred in the scope of block
|
// Deep copy the logs occurred in the scope of block
|
||||||
for hash, logs := range s.logs {
|
for hash, logs := range s.logs {
|
||||||
@@ -1896,6 +1896,10 @@ func (s *StateDB) convertAccountSet(set map[common.Address]*types.StateAccount)
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *StateDB) GetSnap() snapshot.Snapshot {
|
||||||
|
return s.snap
|
||||||
|
}
|
||||||
|
|
||||||
// copySet returns a deep-copied set.
|
// copySet returns a deep-copied set.
|
||||||
func copySet[k comparable](set map[k][]byte) map[k][]byte {
|
func copySet[k comparable](set map[k][]byte) map[k][]byte {
|
||||||
copied := make(map[k][]byte, len(set))
|
copied := make(map[k][]byte, len(set))
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewStateSync creates a new state trie download scheduler.
|
// 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.
|
// 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
|
var onSlot func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error
|
||||||
if onLeaf != nil {
|
if onLeaf != nil {
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch := dstDb.NewBatch()
|
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)
|
t.Fatalf("failed to commit data: %v", err)
|
||||||
}
|
}
|
||||||
batch.Write()
|
batch.Write()
|
||||||
@@ -369,7 +369,7 @@ func testIterativeDelayedStateSync(t *testing.T, scheme string) {
|
|||||||
nodeProcessed = len(nodeResults)
|
nodeProcessed = len(nodeResults)
|
||||||
}
|
}
|
||||||
batch := dstDb.NewBatch()
|
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)
|
t.Fatalf("failed to commit data: %v", err)
|
||||||
}
|
}
|
||||||
batch.Write()
|
batch.Write()
|
||||||
@@ -469,7 +469,7 @@ func testIterativeRandomStateSync(t *testing.T, count int, scheme string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch := dstDb.NewBatch()
|
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)
|
t.Fatalf("failed to commit data: %v", err)
|
||||||
}
|
}
|
||||||
batch.Write()
|
batch.Write()
|
||||||
@@ -575,7 +575,7 @@ func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch := dstDb.NewBatch()
|
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)
|
t.Fatalf("failed to commit data: %v", err)
|
||||||
}
|
}
|
||||||
batch.Write()
|
batch.Write()
|
||||||
@@ -688,7 +688,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch := dstDb.NewBatch()
|
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)
|
t.Fatalf("failed to commit data: %v", err)
|
||||||
}
|
}
|
||||||
batch.Write()
|
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
|
||||||
|
)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user