Compare commits
15 Commits
v1.4.11
...
merge-tx-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be71d41aa5 | ||
|
|
5b46fe13e7 | ||
|
|
0b1438c3df | ||
|
|
0a2f33946b | ||
|
|
865e1e9f57 | ||
|
|
db4cf69166 | ||
|
|
28d55218f7 | ||
|
|
dbc27a199f | ||
|
|
1883438964 | ||
|
|
9986a69c25 | ||
|
|
5bae14f9df | ||
|
|
49623bd469 | ||
|
|
170fcd80c6 | ||
|
|
02d77c98f9 | ||
|
|
57d2b552c7 |
46
CHANGELOG.md
46
CHANGELOG.md
@@ -1,50 +1,4 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 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
|
## v1.4.8
|
||||||
### FEATURE
|
### FEATURE
|
||||||
* [\#2483](https://github.com/bnb-chain/bsc/pull/2483) core/vm: add secp256r1 into PrecompiledContractsHaber
|
* [\#2483](https://github.com/bnb-chain/bsc/pull/2483) core/vm: add secp256r1 into PrecompiledContractsHaber
|
||||||
|
|||||||
@@ -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/bnb-smart-chain/staking/overview/#system-contracts) 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/docs/learn/system-contract) to achieve liveness slash, revenue distributing and validator set renewing func.
|
||||||
|
|
||||||
|
|
||||||
### Light Client of BNB Beacon Chain
|
### Light Client of BNB Beacon Chain
|
||||||
@@ -183,7 +183,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/bnb-smart-chain/developers/node_operators/full_node/) and [becoming a validator](https://docs.bnbchain.org/bnb-smart-chain/validator/create-val/)
|
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)
|
||||||
|
|
||||||
*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
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ var (
|
|||||||
utils.CachePreimagesFlag,
|
utils.CachePreimagesFlag,
|
||||||
utils.OverrideCancun,
|
utils.OverrideCancun,
|
||||||
utils.OverrideHaber,
|
utils.OverrideHaber,
|
||||||
utils.OverrideBohr,
|
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
}, utils.DatabaseFlags),
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
@@ -262,10 +261,6 @@ func initGenesis(ctx *cli.Context) error {
|
|||||||
v := ctx.Uint64(utils.OverrideHaber.Name)
|
v := ctx.Uint64(utils.OverrideHaber.Name)
|
||||||
overrides.OverrideHaber = &v
|
overrides.OverrideHaber = &v
|
||||||
}
|
}
|
||||||
if ctx.IsSet(utils.OverrideBohr.Name) {
|
|
||||||
v := ctx.Uint64(utils.OverrideBohr.Name)
|
|
||||||
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)
|
||||||
overrides.OverrideVerkle = &v
|
overrides.OverrideVerkle = &v
|
||||||
|
|||||||
@@ -193,10 +193,6 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
|||||||
v := ctx.Uint64(utils.OverrideHaber.Name)
|
v := ctx.Uint64(utils.OverrideHaber.Name)
|
||||||
cfg.Eth.OverrideHaber = &v
|
cfg.Eth.OverrideHaber = &v
|
||||||
}
|
}
|
||||||
if ctx.IsSet(utils.OverrideBohr.Name) {
|
|
||||||
v := ctx.Uint64(utils.OverrideBohr.Name)
|
|
||||||
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
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,26 +417,26 @@ func inspectTrie(ctx *cli.Context) error {
|
|||||||
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 = 10
|
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)
|
topN, err = strconv.ParseUint(ctx.Args().Get(2), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse topn, Args[1]: %v, err: %v", ctx.Args().Get(1), err)
|
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 empty hash")
|
return errors.New("ReadHeadBlockHash empry hash")
|
||||||
}
|
}
|
||||||
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
|
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
|
||||||
trieRootHash = blockHeader.Root
|
trieRootHash = blockHeader.Root
|
||||||
@@ -508,7 +508,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, false)
|
db := utils.MakeChainDatabase(ctx, stack, true, true)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
return rawdb.AncientInspect(db)
|
return rawdb.AncientInspect(db)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ var (
|
|||||||
utils.RialtoHash,
|
utils.RialtoHash,
|
||||||
utils.OverrideCancun,
|
utils.OverrideCancun,
|
||||||
utils.OverrideHaber,
|
utils.OverrideHaber,
|
||||||
utils.OverrideBohr,
|
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
utils.OverrideFullImmutabilityThreshold,
|
utils.OverrideFullImmutabilityThreshold,
|
||||||
utils.OverrideMinBlocksForBlobRequests,
|
utils.OverrideMinBlocksForBlobRequests,
|
||||||
|
|||||||
@@ -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, false)
|
frdb, err := rawdb.NewDatabaseWithFreezer(kvdb, ancient, namespace, readonly, disableFreeze, isLastOffset, pruneAncientData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
kvdb.Close()
|
kvdb.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -178,10 +178,11 @@ func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemai
|
|||||||
|
|
||||||
// Force run a freeze cycle
|
// Force run a freeze cycle
|
||||||
type freezer interface {
|
type freezer interface {
|
||||||
Freeze(threshold uint64) error
|
Freeze() error
|
||||||
Ancients() (uint64, error)
|
Ancients() (uint64, error)
|
||||||
}
|
}
|
||||||
db.(freezer).Freeze(10)
|
blockchain.SetFinalized(blocks[len(blocks)-1].Header())
|
||||||
|
db.(freezer).Freeze()
|
||||||
|
|
||||||
frozen, err := db.Ancients()
|
frozen, err := db.Ancients()
|
||||||
//make sure there're frozen items
|
//make sure there're frozen items
|
||||||
|
|||||||
@@ -43,11 +43,9 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -247,16 +245,7 @@ func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) {
|
|||||||
NoBuild: true,
|
NoBuild: true,
|
||||||
AsyncBuild: false,
|
AsyncBuild: false,
|
||||||
}
|
}
|
||||||
dbScheme := rawdb.ReadStateScheme(chaindb)
|
snaptree, err := snapshot.New(snapconfig, chaindb, triedb.NewDatabase(chaindb, nil), headBlock.Root(), TriesInMemory, false)
|
||||||
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
|
|
||||||
}
|
|
||||||
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
|
||||||
@@ -344,9 +333,6 @@ 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
|
||||||
|
|||||||
@@ -315,11 +315,6 @@ var (
|
|||||||
Usage: "Manually specify the Haber fork timestamp, overriding the bundled setting",
|
Usage: "Manually specify the Haber fork timestamp, overriding the bundled setting",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
OverrideBohr = &cli.Uint64Flag{
|
|
||||||
Name: "override.bohr",
|
|
||||||
Usage: "Manually specify the Bohr fork timestamp, overriding the bundled setting",
|
|
||||||
Category: flags.EthCategory,
|
|
||||||
}
|
|
||||||
OverrideVerkle = &cli.Uint64Flag{
|
OverrideVerkle = &cli.Uint64Flag{
|
||||||
Name: "override.verkle",
|
Name: "override.verkle",
|
||||||
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
||||||
@@ -1087,7 +1082,6 @@ 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{
|
||||||
|
|||||||
@@ -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, false)
|
db2, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false, false, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,7 +301,6 @@ 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
|
||||||
@@ -670,7 +669,7 @@ func (bc *BlockChain) cacheBlock(hash common.Hash, block *types.Block) {
|
|||||||
// into node seamlessly.
|
// into node seamlessly.
|
||||||
func (bc *BlockChain) empty() bool {
|
func (bc *BlockChain) empty() bool {
|
||||||
genesis := bc.genesisBlock.Hash()
|
genesis := bc.genesisBlock.Hash()
|
||||||
for _, hash := range []common.Hash{rawdb.ReadHeadBlockHash(bc.db.BlockStore()), rawdb.ReadHeadHeaderHash(bc.db.BlockStore()), rawdb.ReadHeadFastBlockHash(bc.db.BlockStore())} {
|
for _, hash := range []common.Hash{rawdb.ReadHeadBlockHash(bc.db.BlockStore()), rawdb.ReadHeadHeaderHash(bc.db.BlockStore()), rawdb.ReadHeadFastBlockHash(bc.db)} {
|
||||||
if hash != genesis {
|
if hash != genesis {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -739,7 +738,7 @@ func (bc *BlockChain) loadLastState() error {
|
|||||||
bc.currentSnapBlock.Store(headBlock.Header())
|
bc.currentSnapBlock.Store(headBlock.Header())
|
||||||
headFastBlockGauge.Update(int64(headBlock.NumberU64()))
|
headFastBlockGauge.Update(int64(headBlock.NumberU64()))
|
||||||
|
|
||||||
if head := rawdb.ReadHeadFastBlockHash(bc.db.BlockStore()); head != (common.Hash{}) {
|
if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) {
|
||||||
if block := bc.GetBlockByHash(head); block != nil {
|
if block := bc.GetBlockByHash(head); block != nil {
|
||||||
bc.currentSnapBlock.Store(block.Header())
|
bc.currentSnapBlock.Store(block.Header())
|
||||||
headFastBlockGauge.Update(int64(block.NumberU64()))
|
headFastBlockGauge.Update(int64(block.NumberU64()))
|
||||||
@@ -1138,7 +1137,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.BlockStore(), bc.CurrentBlock()); force {
|
if target, force := updateFn(bc.db, bc.CurrentBlock()); force {
|
||||||
bc.hc.SetHead(target.Number.Uint64(), updateFn, delFn)
|
bc.hc.SetHead(target.Number.Uint64(), updateFn, delFn)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1299,33 +1298,19 @@ 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) {
|
||||||
bc.dbWg.Add(2)
|
// Add the block to the canonical chain number scheme and mark as the head
|
||||||
defer bc.dbWg.Wait()
|
rawdb.WriteCanonicalHash(bc.db.BlockStore(), block.Hash(), block.NumberU64())
|
||||||
go func() {
|
rawdb.WriteHeadHeaderHash(bc.db.BlockStore(), block.Hash())
|
||||||
defer bc.dbWg.Done()
|
rawdb.WriteHeadBlockHash(bc.db.BlockStore(), block.Hash())
|
||||||
// Add the block to the canonical chain number scheme and mark as the head
|
|
||||||
blockBatch := bc.db.BlockStore().NewBatch()
|
|
||||||
rawdb.WriteCanonicalHash(blockBatch, block.Hash(), block.NumberU64())
|
|
||||||
rawdb.WriteHeadHeaderHash(blockBatch, block.Hash())
|
|
||||||
rawdb.WriteHeadBlockHash(blockBatch, block.Hash())
|
|
||||||
rawdb.WriteHeadFastBlockHash(blockBatch, block.Hash())
|
|
||||||
// Flush the whole batch into the disk, exit the node if failed
|
|
||||||
if err := blockBatch.Write(); err != nil {
|
|
||||||
log.Crit("Failed to update chain indexes and markers in block db", "err", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
defer bc.dbWg.Done()
|
|
||||||
|
|
||||||
batch := bc.db.NewBatch()
|
batch := bc.db.NewBatch()
|
||||||
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
rawdb.WriteHeadFastBlockHash(batch, block.Hash())
|
||||||
|
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())
|
||||||
|
|
||||||
@@ -1546,7 +1531,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||||||
} else if !reorg {
|
} else if !reorg {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
rawdb.WriteHeadFastBlockHash(bc.db.BlockStore(), head.Hash())
|
rawdb.WriteHeadFastBlockHash(bc.db, 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
|
||||||
@@ -1789,6 +1774,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() {
|
||||||
|
rawdb.WritePreimages(bc.db, state.Preimages())
|
||||||
blockBatch := bc.db.BlockStore().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)
|
||||||
@@ -1797,11 +1783,7 @@ 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())
|
||||||
}
|
}
|
||||||
if bc.db.StateStore() != nil {
|
rawdb.WritePreimages(blockBatch, state.Preimages())
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1832,10 +1832,14 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
|||||||
}
|
}
|
||||||
// Force run a freeze cycle
|
// Force run a freeze cycle
|
||||||
type freezer interface {
|
type freezer interface {
|
||||||
Freeze(threshold uint64) error
|
Freeze() error
|
||||||
Ancients() (uint64, error)
|
Ancients() (uint64, error)
|
||||||
}
|
}
|
||||||
db.(freezer).Freeze(tt.freezeThreshold)
|
if tt.freezeThreshold < uint64(tt.canonicalBlocks) {
|
||||||
|
final := uint64(tt.canonicalBlocks) - tt.freezeThreshold
|
||||||
|
chain.SetFinalized(canonblocks[int(final)-1].Header())
|
||||||
|
}
|
||||||
|
db.(freezer).Freeze()
|
||||||
|
|
||||||
// Set the simulated pivot block
|
// Set the simulated pivot block
|
||||||
if tt.pivotBlock != nil {
|
if tt.pivotBlock != nil {
|
||||||
|
|||||||
@@ -2045,10 +2045,14 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
|||||||
|
|
||||||
// Force run a freeze cycle
|
// Force run a freeze cycle
|
||||||
type freezer interface {
|
type freezer interface {
|
||||||
Freeze(threshold uint64) error
|
Freeze() error
|
||||||
Ancients() (uint64, error)
|
Ancients() (uint64, error)
|
||||||
}
|
}
|
||||||
db.(freezer).Freeze(tt.freezeThreshold)
|
if tt.freezeThreshold < uint64(tt.canonicalBlocks) {
|
||||||
|
final := uint64(tt.canonicalBlocks) - tt.freezeThreshold
|
||||||
|
chain.SetFinalized(canonblocks[int(final)-1].Header())
|
||||||
|
}
|
||||||
|
db.(freezer).Freeze()
|
||||||
|
|
||||||
// Set the simulated pivot block
|
// Set the simulated pivot block
|
||||||
if tt.pivotBlock != nil {
|
if tt.pivotBlock != nil {
|
||||||
|
|||||||
@@ -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, false)
|
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", 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, false)
|
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", 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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,9 +114,7 @@ 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 ||
|
reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5)
|
||||||
extern.Time < current.Time ||
|
|
||||||
extern.Time == current.Time && f.rand.Float64() < 0.5)
|
|
||||||
}
|
}
|
||||||
return reorg, nil
|
return reorg, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,6 @@ func (e *GenesisMismatchError) Error() string {
|
|||||||
type ChainOverrides struct {
|
type ChainOverrides struct {
|
||||||
OverrideCancun *uint64
|
OverrideCancun *uint64
|
||||||
OverrideHaber *uint64
|
OverrideHaber *uint64
|
||||||
OverrideBohr *uint64
|
|
||||||
OverrideVerkle *uint64
|
OverrideVerkle *uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,9 +250,6 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
|
|||||||
if overrides != nil && overrides.OverrideHaber != nil {
|
if overrides != nil && overrides.OverrideHaber != nil {
|
||||||
config.HaberTime = overrides.OverrideHaber
|
config.HaberTime = overrides.OverrideHaber
|
||||||
}
|
}
|
||||||
if overrides != nil && overrides.OverrideBohr != nil {
|
|
||||||
config.BohrTime = overrides.OverrideBohr
|
|
||||||
}
|
|
||||||
if overrides != nil && overrides.OverrideVerkle != nil {
|
if overrides != nil && overrides.OverrideVerkle != nil {
|
||||||
config.VerkleTime = overrides.OverrideVerkle
|
config.VerkleTime = overrides.OverrideVerkle
|
||||||
}
|
}
|
||||||
@@ -498,7 +494,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
|
|||||||
rawdb.WriteReceipts(db.BlockStore(), block.Hash(), block.NumberU64(), nil)
|
rawdb.WriteReceipts(db.BlockStore(), block.Hash(), block.NumberU64(), nil)
|
||||||
rawdb.WriteCanonicalHash(db.BlockStore(), block.Hash(), block.NumberU64())
|
rawdb.WriteCanonicalHash(db.BlockStore(), block.Hash(), block.NumberU64())
|
||||||
rawdb.WriteHeadBlockHash(db.BlockStore(), block.Hash())
|
rawdb.WriteHeadBlockHash(db.BlockStore(), block.Hash())
|
||||||
rawdb.WriteHeadFastBlockHash(db.BlockStore(), block.Hash())
|
rawdb.WriteHeadFastBlockHash(db, block.Hash())
|
||||||
rawdb.WriteHeadHeaderHash(db.BlockStore(), 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
|
||||||
|
|||||||
@@ -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.BlockStore().NewBatch()
|
markerBatch := hc.chainDb.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)) {
|
||||||
@@ -677,7 +677,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update head header then.
|
// Update head header then.
|
||||||
rawdb.WriteHeadHeaderHash(markerBatch, parentHash)
|
rawdb.WriteHeadHeaderHash(hc.chainDb.BlockStore(), parentHash)
|
||||||
if err := markerBatch.Write(); err != nil {
|
if err := markerBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to update chain markers", "error", err)
|
log.Crit("Failed to update chain markers", "error", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, false)
|
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", 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, false)
|
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", 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, false)
|
db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", 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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ import (
|
|||||||
"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 (
|
||||||
@@ -51,31 +51,25 @@ var (
|
|||||||
// 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.
|
||||||
type chainFreezer struct {
|
type chainFreezer struct {
|
||||||
threshold atomic.Uint64 // Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests)
|
|
||||||
|
|
||||||
*Freezer
|
*Freezer
|
||||||
quit chan struct{}
|
quit chan 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
|
||||||
|
|
||||||
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, multiDatabase bool) (*chainFreezer, error) {
|
func newChainFreezer(datadir string, namespace string, readonly bool, offset uint64) (*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
|
||||||
}
|
}
|
||||||
cf := chainFreezer{
|
return &chainFreezer{
|
||||||
Freezer: freezer,
|
Freezer: freezer,
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
trigger: make(chan chan struct{}),
|
trigger: make(chan chan struct{}),
|
||||||
}
|
}, nil
|
||||||
cf.threshold.Store(params.FullImmutabilityThreshold)
|
|
||||||
return &cf, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the chain freezer instance and terminates the background thread.
|
// Close closes the chain freezer instance and terminates the background thread.
|
||||||
@@ -191,101 +185,29 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
threshold, err := f.freezeThreshold(nfdb)
|
||||||
frozen uint64
|
if err != nil {
|
||||||
threshold uint64
|
backoff = true
|
||||||
first uint64 // the first block to freeze
|
log.Debug("Current full block not old enough to freeze", "err", err)
|
||||||
last uint64 // the last block to freeze
|
continue
|
||||||
|
}
|
||||||
|
frozen := f.frozen.Load()
|
||||||
|
|
||||||
hash common.Hash
|
// Short circuit if the blocks below threshold are already frozen.
|
||||||
number *uint64
|
if frozen != 0 && frozen-1 >= threshold {
|
||||||
head *types.Header
|
backoff = true
|
||||||
)
|
log.Debug("Ancient blocks frozen already", "threshold", threshold, "frozen", frozen)
|
||||||
|
continue
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 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 = frozen // the first block to freeze
|
||||||
|
last = threshold // the last block to freeze
|
||||||
)
|
)
|
||||||
|
if last-first+1 > freezerBatchLimit {
|
||||||
|
last = freezerBatchLimit + first - 1
|
||||||
|
}
|
||||||
|
|
||||||
ancients, err := f.freezeRangeWithBlobs(nfdb, first, last)
|
ancients, err := f.freezeRangeWithBlobs(nfdb, first, last)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -373,6 +295,24 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
|
|||||||
log.Debug("Deep froze chain segment", context...)
|
log.Debug("Deep froze chain segment", context...)
|
||||||
|
|
||||||
env, _ := f.freezeEnv.Load().(*ethdb.FreezerEnv)
|
env, _ := f.freezeEnv.Load().(*ethdb.FreezerEnv)
|
||||||
|
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
|
||||||
|
}
|
||||||
// try prune blob data after cancun fork
|
// try prune blob data after cancun fork
|
||||||
if isCancun(env, head.Number, head.Time) {
|
if isCancun(env, head.Number, head.Time) {
|
||||||
f.tryPruneBlobAncientTable(env, *number)
|
f.tryPruneBlobAncientTable(env, *number)
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
|||||||
batch.Reset()
|
batch.Reset()
|
||||||
|
|
||||||
WriteHeadHeaderHash(db.BlockStore(), hash)
|
WriteHeadHeaderHash(db.BlockStore(), hash)
|
||||||
WriteHeadFastBlockHash(db.BlockStore(), hash)
|
WriteHeadFastBlockHash(db, 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)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ func (frdb *freezerdb) BlockStoreReader() ethdb.Reader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (frdb *freezerdb) BlockStoreWriter() ethdb.Writer {
|
func (frdb *freezerdb) BlockStoreWriter() ethdb.Writer {
|
||||||
// TODO implement me
|
//TODO implement me
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,22 +138,13 @@ func (frdb *freezerdb) SetBlockStore(block ethdb.Database) {
|
|||||||
frdb.blockStore = block
|
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.
|
||||||
func (frdb *freezerdb) Freeze(threshold uint64) error {
|
func (frdb *freezerdb) Freeze() error {
|
||||||
if frdb.AncientStore.(*chainFreezer).readonly {
|
if frdb.AncientStore.(*chainFreezer).readonly {
|
||||||
return errReadOnly
|
return errReadOnly
|
||||||
}
|
}
|
||||||
// Set the freezer threshold to a temporary value
|
|
||||||
defer func(old uint64) {
|
|
||||||
frdb.AncientStore.(*chainFreezer).threshold.Store(old)
|
|
||||||
}(frdb.AncientStore.(*chainFreezer).threshold.Load())
|
|
||||||
frdb.AncientStore.(*chainFreezer).threshold.Store(threshold)
|
|
||||||
// Trigger a freeze cycle and block until it's done
|
// Trigger 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
|
||||||
@@ -193,7 +184,7 @@ func (db *nofreezedb) Ancients() (uint64, error) {
|
|||||||
return 0, errNotSupported
|
return 0, errNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// ItemAmountInAncient returns an error as we don't have a backing chain freezer.
|
// Ancients 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
|
||||||
}
|
}
|
||||||
@@ -272,10 +263,6 @@ func (db *nofreezedb) SetBlockStore(block ethdb.Database) {
|
|||||||
db.blockStore = block
|
db.blockStore = block
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *nofreezedb) HasSeparateBlockStore() bool {
|
|
||||||
return db.blockStore != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *nofreezedb) BlockStoreReader() ethdb.Reader {
|
func (db *nofreezedb) BlockStoreReader() ethdb.Reader {
|
||||||
if db.blockStore != nil {
|
if db.blockStore != nil {
|
||||||
return db.blockStore
|
return db.blockStore
|
||||||
@@ -331,110 +318,6 @@ 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) 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.
|
||||||
@@ -475,7 +358,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, multiDatabase bool) (ethdb.Database, error) {
|
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData 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 {
|
||||||
@@ -484,12 +367,6 @@ 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 {
|
||||||
@@ -517,7 +394,7 @@ 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, multiDatabase)
|
frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printChainMetadata(db)
|
printChainMetadata(db)
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -698,8 +575,6 @@ type OpenOptions struct {
|
|||||||
// 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.
|
||||||
@@ -744,13 +619,13 @@ func Open(o OpenOptions) (ethdb.Database, error) {
|
|||||||
}
|
}
|
||||||
if ReadAncientType(kvdb) == PruneFreezerType {
|
if ReadAncientType(kvdb) == PruneFreezerType {
|
||||||
if !o.PruneAncientData {
|
if !o.PruneAncientData {
|
||||||
log.Warn("NOTICE: You're opening a pruned disk db!")
|
log.Warn("Disk db is pruned")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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, o.MultiDataBase)
|
frdb, err := NewDatabaseWithFreezer(kvdb, o.AncientsDirectory, o.Namespace, o.ReadOnly, o.DisableFreeze, o.IsLastOffset, o.PruneAncientData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
kvdb.Close()
|
kvdb.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -873,7 +748,7 @@ func DataTypeByKey(key []byte) DataType {
|
|||||||
return StateDataType
|
return StateDataType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, meta := range [][]byte{headHeaderKey, headFinalizedBlockKey, headBlockKey, headFastBlockKey} {
|
for _, meta := range [][]byte{headHeaderKey, headFinalizedBlockKey} {
|
||||||
if bytes.Equal(key, meta) {
|
if bytes.Equal(key, meta) {
|
||||||
return BlockDataType
|
return BlockDataType
|
||||||
}
|
}
|
||||||
@@ -894,7 +769,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
|||||||
trieIter = db.StateStore().NewIterator(keyPrefix, nil)
|
trieIter = db.StateStore().NewIterator(keyPrefix, nil)
|
||||||
defer trieIter.Release()
|
defer trieIter.Release()
|
||||||
}
|
}
|
||||||
if db.HasSeparateBlockStore() {
|
if db.BlockStore() != db {
|
||||||
blockIter = db.BlockStore().NewIterator(keyPrefix, nil)
|
blockIter = db.BlockStore().NewIterator(keyPrefix, nil)
|
||||||
defer blockIter.Release()
|
defer blockIter.Release()
|
||||||
}
|
}
|
||||||
@@ -1088,7 +963,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
|||||||
hashNumPairings.Add(size)
|
hashNumPairings.Add(size)
|
||||||
default:
|
default:
|
||||||
var accounted bool
|
var accounted bool
|
||||||
for _, meta := range [][]byte{headHeaderKey, headFinalizedBlockKey, headBlockKey, headFastBlockKey} {
|
for _, meta := range [][]byte{headHeaderKey, headFinalizedBlockKey} {
|
||||||
if bytes.Equal(key, meta) {
|
if bytes.Equal(key, meta) {
|
||||||
metadata.Add(size)
|
metadata.Add(size)
|
||||||
accounted = true
|
accounted = true
|
||||||
@@ -1282,7 +1157,7 @@ func ReadChainMetadataFromMultiDatabase(db ethdb.Database) [][]string {
|
|||||||
data := [][]string{
|
data := [][]string{
|
||||||
{"databaseVersion", pp(ReadDatabaseVersion(db))},
|
{"databaseVersion", pp(ReadDatabaseVersion(db))},
|
||||||
{"headBlockHash", fmt.Sprintf("%v", ReadHeadBlockHash(db.BlockStore()))},
|
{"headBlockHash", fmt.Sprintf("%v", ReadHeadBlockHash(db.BlockStore()))},
|
||||||
{"headFastBlockHash", fmt.Sprintf("%v", ReadHeadFastBlockHash(db.BlockStore()))},
|
{"headFastBlockHash", fmt.Sprintf("%v", ReadHeadFastBlockHash(db))},
|
||||||
{"headHeaderHash", fmt.Sprintf("%v", ReadHeadHeaderHash(db.BlockStore()))},
|
{"headHeaderHash", fmt.Sprintf("%v", ReadHeadHeaderHash(db.BlockStore()))},
|
||||||
{"lastPivotNumber", pp(ReadLastPivotNumber(db))},
|
{"lastPivotNumber", pp(ReadLastPivotNumber(db))},
|
||||||
{"len(snapshotSyncStatus)", fmt.Sprintf("%d bytes", len(ReadSnapshotSyncStatus(db)))},
|
{"len(snapshotSyncStatus)", fmt.Sprintf("%d bytes", len(ReadSnapshotSyncStatus(db)))},
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ func (t *table) SetBlockStore(block ethdb.Database) {
|
|||||||
panic("not implement")
|
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{
|
||||||
|
|||||||
@@ -382,7 +382,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.BlockStore().ItemAmountInAncient()
|
itemsOfAncient, err := chainDb.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.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,19 +0,0 @@
|
|||||||
package haber_fix
|
|
||||||
|
|
||||||
import _ "embed"
|
|
||||||
|
|
||||||
// contract codes for Chapel upgrade
|
|
||||||
var (
|
|
||||||
//go:embed chapel/ValidatorContract
|
|
||||||
ChapelValidatorContract string
|
|
||||||
//go:embed chapel/SlashContract
|
|
||||||
ChapelSlashContract string
|
|
||||||
)
|
|
||||||
|
|
||||||
// contract codes for Mainnet upgrade
|
|
||||||
var (
|
|
||||||
//go:embed mainnet/ValidatorContract
|
|
||||||
MainnetValidatorContract string
|
|
||||||
//go:embed mainnet/SlashContract
|
|
||||||
MainnetSlashContract string
|
|
||||||
)
|
|
||||||
@@ -4,16 +4,17 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/bruno"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/bruno"
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/euler"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/euler"
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/feynman"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/feynman"
|
||||||
feynmanFix "github.com/ethereum/go-ethereum/core/systemcontracts/feynman_fix"
|
feynmanFix "github.com/ethereum/go-ethereum/core/systemcontracts/feynman_fix"
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/gibbs"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/gibbs"
|
||||||
haberFix "github.com/ethereum/go-ethereum/core/systemcontracts/haber_fix"
|
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/kepler"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/kepler"
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/luban"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/luban"
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/mirror"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/mirror"
|
||||||
@@ -22,8 +23,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/planck"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/planck"
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/plato"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/plato"
|
||||||
"github.com/ethereum/go-ethereum/core/systemcontracts/ramanujan"
|
"github.com/ethereum/go-ethereum/core/systemcontracts/ramanujan"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type UpgradeConfig struct {
|
type UpgradeConfig struct {
|
||||||
@@ -76,8 +75,6 @@ var (
|
|||||||
feynmanUpgrade = make(map[string]*Upgrade)
|
feynmanUpgrade = make(map[string]*Upgrade)
|
||||||
|
|
||||||
feynmanFixUpgrade = make(map[string]*Upgrade)
|
feynmanFixUpgrade = make(map[string]*Upgrade)
|
||||||
|
|
||||||
haberFixUpgrade = make(map[string]*Upgrade)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -704,38 +701,6 @@ func init() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
haberFixUpgrade[mainNet] = &Upgrade{
|
|
||||||
UpgradeName: "haberFix",
|
|
||||||
Configs: []*UpgradeConfig{
|
|
||||||
{
|
|
||||||
ContractAddr: common.HexToAddress(ValidatorContract),
|
|
||||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/b743ce3f1f1e94c349b175cd6593bc263463b33b",
|
|
||||||
Code: haberFix.MainnetValidatorContract,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ContractAddr: common.HexToAddress(SlashContract),
|
|
||||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/b743ce3f1f1e94c349b175cd6593bc263463b33b",
|
|
||||||
Code: haberFix.MainnetSlashContract,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
haberFixUpgrade[chapelNet] = &Upgrade{
|
|
||||||
UpgradeName: "haberFix",
|
|
||||||
Configs: []*UpgradeConfig{
|
|
||||||
{
|
|
||||||
ContractAddr: common.HexToAddress(ValidatorContract),
|
|
||||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/b743ce3f1f1e94c349b175cd6593bc263463b33b",
|
|
||||||
Code: haberFix.ChapelValidatorContract,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ContractAddr: common.HexToAddress(SlashContract),
|
|
||||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/b743ce3f1f1e94c349b175cd6593bc263463b33b",
|
|
||||||
Code: haberFix.ChapelSlashContract,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb *state.StateDB) {
|
func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb *state.StateDB) {
|
||||||
@@ -812,10 +777,6 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I
|
|||||||
applySystemContractUpgrade(feynmanFixUpgrade[network], blockNumber, statedb, logger)
|
applySystemContractUpgrade(feynmanFixUpgrade[network], blockNumber, statedb, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.IsOnHaberFix(blockNumber, lastBlockTime, blockTime) {
|
|
||||||
applySystemContractUpgrade(haberFixUpgrade[network], blockNumber, statedb, logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
apply other upgrades
|
apply other upgrades
|
||||||
*/
|
*/
|
||||||
@@ -838,7 +799,7 @@ func applySystemContractUpgrade(upgrade *Upgrade, blockNumber *big.Int, statedb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newContractCode, err := hex.DecodeString(strings.TrimSpace(cfg.Code))
|
newContractCode, err := hex.DecodeString(cfg.Code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("failed to decode new contract code: %s", err.Error()))
|
panic(fmt.Errorf("failed to decode new contract code: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ func TestTxIndexer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
frdir := t.TempDir()
|
frdir := t.TempDir()
|
||||||
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false, false, false)
|
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false, false)
|
||||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), big.NewInt(0))
|
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), big.NewInt(0))
|
||||||
|
|
||||||
// Index the initial blocks from ancient store
|
// Index the initial blocks from ancient store
|
||||||
|
|||||||
@@ -193,7 +193,5 @@ type MevParams struct {
|
|||||||
ValidatorCommission uint64 // 100 means 1%
|
ValidatorCommission uint64 // 100 means 1%
|
||||||
BidSimulationLeftOver time.Duration
|
BidSimulationLeftOver time.Duration
|
||||||
GasCeil uint64
|
GasCeil uint64
|
||||||
GasPrice *big.Int // Minimum avg gas price for bid block
|
|
||||||
BuilderFeeCeil *big.Int
|
BuilderFeeCeil *big.Int
|
||||||
Version string
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -484,10 +484,6 @@ func (b *EthAPIBackend) RemoveBuilder(builder common.Address) error {
|
|||||||
return b.Miner().RemoveBuilder(builder)
|
return b.Miner().RemoveBuilder(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) HasBuilder(builder common.Address) bool {
|
|
||||||
return b.Miner().HasBuilder(builder)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *EthAPIBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) {
|
func (b *EthAPIBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) {
|
||||||
return b.Miner().SendBid(ctx, bid)
|
return b.Miner().SendBid(ctx, bid)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,18 +161,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||||||
// Optimize memory distribution by reallocating surplus allowance from the
|
// Optimize memory distribution by reallocating surplus allowance from the
|
||||||
// dirty cache to the clean cache.
|
// dirty cache to the clean cache.
|
||||||
if config.StateScheme == rawdb.PathScheme && config.TrieDirtyCache > pathdb.MaxDirtyBufferSize/1024/1024 {
|
if config.StateScheme == rawdb.PathScheme && config.TrieDirtyCache > pathdb.MaxDirtyBufferSize/1024/1024 {
|
||||||
log.Info("Capped dirty cache size", "provided", common.StorageSize(config.TrieDirtyCache)*1024*1024,
|
log.Info("Capped dirty cache size", "provided", common.StorageSize(config.TrieDirtyCache)*1024*1024, "adjusted", common.StorageSize(pathdb.MaxDirtyBufferSize))
|
||||||
"adjusted", common.StorageSize(pathdb.MaxDirtyBufferSize))
|
log.Info("Clean cache size", "provided", common.StorageSize(config.TrieCleanCache)*1024*1024)
|
||||||
log.Info("Clean cache size", "provided", common.StorageSize(config.TrieCleanCache)*1024*1024,
|
|
||||||
"adjusted", common.StorageSize(config.TrieCleanCache+config.TrieDirtyCache-pathdb.MaxDirtyBufferSize/1024/1024)*1024*1024)
|
|
||||||
config.TrieCleanCache += config.TrieDirtyCache - pathdb.MaxDirtyBufferSize/1024/1024
|
|
||||||
config.TrieDirtyCache = pathdb.MaxDirtyBufferSize / 1024 / 1024
|
config.TrieDirtyCache = pathdb.MaxDirtyBufferSize / 1024 / 1024
|
||||||
}
|
}
|
||||||
log.Info("Allocated memory caches",
|
log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024)
|
||||||
"state_scheme", config.StateScheme,
|
|
||||||
"trie_clean_cache", common.StorageSize(config.TrieCleanCache)*1024*1024,
|
|
||||||
"trie_dirty_cache", common.StorageSize(config.TrieDirtyCache)*1024*1024,
|
|
||||||
"snapshot_cache", common.StorageSize(config.SnapshotCache)*1024*1024)
|
|
||||||
// Try to recover offline state pruning only in hash-based.
|
// Try to recover offline state pruning only in hash-based.
|
||||||
if config.StateScheme == rawdb.HashScheme {
|
if config.StateScheme == rawdb.HashScheme {
|
||||||
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, config.TriesInMemory); err != nil {
|
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, config.TriesInMemory); err != nil {
|
||||||
@@ -193,10 +187,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||||||
chainConfig.HaberTime = config.OverrideHaber
|
chainConfig.HaberTime = config.OverrideHaber
|
||||||
overrides.OverrideHaber = config.OverrideHaber
|
overrides.OverrideHaber = config.OverrideHaber
|
||||||
}
|
}
|
||||||
if config.OverrideBohr != nil {
|
|
||||||
chainConfig.BohrTime = config.OverrideBohr
|
|
||||||
overrides.OverrideBohr = config.OverrideBohr
|
|
||||||
}
|
|
||||||
if config.OverrideVerkle != nil {
|
if config.OverrideVerkle != nil {
|
||||||
chainConfig.VerkleTime = config.OverrideVerkle
|
chainConfig.VerkleTime = config.OverrideVerkle
|
||||||
overrides.OverrideVerkle = config.OverrideVerkle
|
overrides.OverrideVerkle = config.OverrideVerkle
|
||||||
@@ -324,6 +314,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||||||
// Permit the downloader to use the trie cache allowance during fast sync
|
// Permit the downloader to use the trie cache allowance during fast sync
|
||||||
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
|
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
|
||||||
if eth.handler, err = newHandler(&handlerConfig{
|
if eth.handler, err = newHandler(&handlerConfig{
|
||||||
|
NodeID: eth.p2pServer.Self().ID(),
|
||||||
Database: chainDb,
|
Database: chainDb,
|
||||||
Chain: eth.blockchain,
|
Chain: eth.blockchain,
|
||||||
TxPool: eth.txPool,
|
TxPool: eth.txPool,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func newTester(t *testing.T) *downloadTester {
|
|||||||
// newTester creates a new downloader test mocker.
|
// newTester creates a new downloader test mocker.
|
||||||
func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
|
func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
|
||||||
freezer := t.TempDir()
|
freezer := t.TempDir()
|
||||||
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false, false, false, false, false)
|
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false, false, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,9 +194,6 @@ type Config struct {
|
|||||||
// OverrideHaber (TODO: remove after the fork)
|
// OverrideHaber (TODO: remove after the fork)
|
||||||
OverrideHaber *uint64 `toml:",omitempty"`
|
OverrideHaber *uint64 `toml:",omitempty"`
|
||||||
|
|
||||||
// OverrideBohr (TODO: remove after the fork)
|
|
||||||
OverrideBohr *uint64 `toml:",omitempty"`
|
|
||||||
|
|
||||||
// OverrideVerkle (TODO: remove after the fork)
|
// OverrideVerkle (TODO: remove after the fork)
|
||||||
OverrideVerkle *uint64 `toml:",omitempty"`
|
OverrideVerkle *uint64 `toml:",omitempty"`
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
RPCTxFeeCap float64
|
RPCTxFeeCap float64
|
||||||
OverrideCancun *uint64 `toml:",omitempty"`
|
OverrideCancun *uint64 `toml:",omitempty"`
|
||||||
OverrideHaber *uint64 `toml:",omitempty"`
|
OverrideHaber *uint64 `toml:",omitempty"`
|
||||||
OverrideBohr *uint64 `toml:",omitempty"`
|
|
||||||
OverrideVerkle *uint64 `toml:",omitempty"`
|
OverrideVerkle *uint64 `toml:",omitempty"`
|
||||||
BlobExtraReserve uint64
|
BlobExtraReserve uint64
|
||||||
}
|
}
|
||||||
@@ -132,7 +131,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
enc.RPCTxFeeCap = c.RPCTxFeeCap
|
enc.RPCTxFeeCap = c.RPCTxFeeCap
|
||||||
enc.OverrideCancun = c.OverrideCancun
|
enc.OverrideCancun = c.OverrideCancun
|
||||||
enc.OverrideHaber = c.OverrideHaber
|
enc.OverrideHaber = c.OverrideHaber
|
||||||
enc.OverrideBohr = c.OverrideBohr
|
|
||||||
enc.OverrideVerkle = c.OverrideVerkle
|
enc.OverrideVerkle = c.OverrideVerkle
|
||||||
enc.BlobExtraReserve = c.BlobExtraReserve
|
enc.BlobExtraReserve = c.BlobExtraReserve
|
||||||
return &enc, nil
|
return &enc, nil
|
||||||
@@ -196,7 +194,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
RPCTxFeeCap *float64
|
RPCTxFeeCap *float64
|
||||||
OverrideCancun *uint64 `toml:",omitempty"`
|
OverrideCancun *uint64 `toml:",omitempty"`
|
||||||
OverrideHaber *uint64 `toml:",omitempty"`
|
OverrideHaber *uint64 `toml:",omitempty"`
|
||||||
OverrideBohr *uint64 `toml:",omitempty"`
|
|
||||||
OverrideVerkle *uint64 `toml:",omitempty"`
|
OverrideVerkle *uint64 `toml:",omitempty"`
|
||||||
BlobExtraReserve *uint64
|
BlobExtraReserve *uint64
|
||||||
}
|
}
|
||||||
@@ -369,9 +366,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
if dec.OverrideHaber != nil {
|
if dec.OverrideHaber != nil {
|
||||||
c.OverrideHaber = dec.OverrideHaber
|
c.OverrideHaber = dec.OverrideHaber
|
||||||
}
|
}
|
||||||
if dec.OverrideBohr != nil {
|
|
||||||
c.OverrideBohr = dec.OverrideBohr
|
|
||||||
}
|
|
||||||
if dec.OverrideVerkle != nil {
|
if dec.OverrideVerkle != nil {
|
||||||
c.OverrideVerkle = dec.OverrideVerkle
|
c.OverrideVerkle = dec.OverrideVerkle
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -731,6 +731,9 @@ func (f *BlockFetcher) loop() {
|
|||||||
matched = true
|
matched = true
|
||||||
if f.getBlock(hash) == nil {
|
if f.getBlock(hash) == nil {
|
||||||
block := types.NewBlockWithHeader(announce.header).WithBody(task.transactions[i], task.uncles[i])
|
block := types.NewBlockWithHeader(announce.header).WithBody(task.transactions[i], task.uncles[i])
|
||||||
|
if block.Header().EmptyWithdrawalsHash() {
|
||||||
|
block = block.WithWithdrawals(make([]*types.Withdrawal, 0))
|
||||||
|
}
|
||||||
block = block.WithSidecars(task.sidecars[i])
|
block = block.WithSidecars(task.sidecars[i])
|
||||||
block.ReceivedAt = task.time
|
block.ReceivedAt = task.time
|
||||||
blocks = append(blocks, block)
|
blocks = append(blocks, block)
|
||||||
@@ -916,10 +919,6 @@ func (f *BlockFetcher) importBlocks(op *blockOrHeaderInject) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if block.Header().EmptyWithdrawalsHash() {
|
|
||||||
block = block.WithWithdrawals(make([]*types.Withdrawal, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { f.done <- hash }()
|
defer func() { f.done <- hash }()
|
||||||
// Quickly validate the header and propagate the block if it passes
|
// Quickly validate the header and propagate the block if it passes
|
||||||
switch err := f.verifyHeader(block.Header()); err {
|
switch err := f.verifyHeader(block.Header()); err {
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ func (f *fetcherTester) chainFinalizedHeight() uint64 {
|
|||||||
return f.blocks[f.hashes[len(f.hashes)-3]].NumberU64()
|
return f.blocks[f.hashes[len(f.hashes)-3]].NumberU64()
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertHeaders injects a new headers into the simulated chain.
|
// insertChain injects a new headers into the simulated chain.
|
||||||
func (f *fetcherTester) insertHeaders(headers []*types.Header) (int, error) {
|
func (f *fetcherTester) insertHeaders(headers []*types.Header) (int, error) {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/eth/fetcher"
|
"github.com/ethereum/go-ethereum/eth/fetcher"
|
||||||
"github.com/ethereum/go-ethereum/eth/protocols/bsc"
|
"github.com/ethereum/go-ethereum/eth/protocols/bsc"
|
||||||
@@ -45,6 +46,8 @@ 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/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -111,6 +114,7 @@ type votePool interface {
|
|||||||
// handlerConfig is the collection of initialization parameters to create a full
|
// handlerConfig is the collection of initialization parameters to create a full
|
||||||
// node network handler.
|
// node network handler.
|
||||||
type handlerConfig struct {
|
type handlerConfig struct {
|
||||||
|
NodeID enode.ID // P2P node ID used for tx propagation topology
|
||||||
Database ethdb.Database // Database for direct sync insertions
|
Database ethdb.Database // Database for direct sync insertions
|
||||||
Chain *core.BlockChain // Blockchain to serve data from
|
Chain *core.BlockChain // Blockchain to serve data from
|
||||||
TxPool txPool // Transaction pool to propagate from
|
TxPool txPool // Transaction pool to propagate from
|
||||||
@@ -127,6 +131,7 @@ type handlerConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type handler struct {
|
type handler struct {
|
||||||
|
nodeID enode.ID
|
||||||
networkID uint64
|
networkID uint64
|
||||||
forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node
|
forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node
|
||||||
disablePeerTxBroadcast bool
|
disablePeerTxBroadcast bool
|
||||||
@@ -184,6 +189,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
|
|||||||
config.PeerSet = newPeerSet() // Nicety initialization for tests
|
config.PeerSet = newPeerSet() // Nicety initialization for tests
|
||||||
}
|
}
|
||||||
h := &handler{
|
h := &handler{
|
||||||
|
nodeID: config.NodeID,
|
||||||
networkID: config.Network,
|
networkID: config.Network,
|
||||||
forkFilter: forkid.NewFilter(config.Chain),
|
forkFilter: forkid.NewFilter(config.Chain),
|
||||||
disablePeerTxBroadcast: config.DisablePeerTxBroadcast,
|
disablePeerTxBroadcast: config.DisablePeerTxBroadcast,
|
||||||
@@ -852,25 +858,54 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
|
|||||||
annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce
|
annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce
|
||||||
)
|
)
|
||||||
// Broadcast transactions to a batch of peers not knowing about it
|
// Broadcast transactions to a batch of peers not knowing about it
|
||||||
for _, tx := range txs {
|
direct := big.NewInt(int64(math.Sqrt(float64(h.peers.len())))) // Approximate number of peers to broadcast to
|
||||||
peers := h.peers.peersWithoutTransaction(tx.Hash())
|
if direct.BitLen() == 0 {
|
||||||
|
direct = big.NewInt(1)
|
||||||
|
}
|
||||||
|
total := new(big.Int).Exp(direct, big.NewInt(2), nil) // Stabilise total peer count a bit based on sqrt peers
|
||||||
|
|
||||||
var numDirect int
|
var (
|
||||||
|
signer = types.LatestSignerForChainID(h.chain.Config().ChainID) // Don't care about chain status, we just need *a* sender
|
||||||
|
hasher = sha3.NewLegacyKeccak256().(crypto.KeccakState)
|
||||||
|
hash = make([]byte, 32)
|
||||||
|
)
|
||||||
|
for _, tx := range txs {
|
||||||
|
var maybeDirect bool
|
||||||
switch {
|
switch {
|
||||||
case tx.Type() == types.BlobTxType:
|
case tx.Type() == types.BlobTxType:
|
||||||
blobTxs++
|
blobTxs++
|
||||||
case tx.Size() > txMaxBroadcastSize:
|
case tx.Size() > txMaxBroadcastSize:
|
||||||
largeTxs++
|
largeTxs++
|
||||||
default:
|
default:
|
||||||
numDirect = int(math.Sqrt(float64(len(peers))))
|
maybeDirect = true
|
||||||
}
|
}
|
||||||
// Send the tx unconditionally to a subset of our peers
|
// Send the transaction (if it's small enough) directly to a subset of
|
||||||
for _, peer := range peers[:numDirect] {
|
// the peers that have not received it yet, ensuring that the flow of
|
||||||
txset[peer] = append(txset[peer], tx.Hash())
|
// transactions is groupped by account to (try and) avoid nonce gaps.
|
||||||
}
|
//
|
||||||
// For the remaining peers, send announcement only
|
// To do this, we hash the local enode IW with together with a peer's
|
||||||
for _, peer := range peers[numDirect:] {
|
// enode ID together with the transaction sender and broadcast if
|
||||||
annos[peer] = append(annos[peer], tx.Hash())
|
// `sha(self, peer, sender) mod peers < sqrt(peers)`.
|
||||||
|
for _, peer := range h.peers.peersWithoutTransaction(tx.Hash()) {
|
||||||
|
var broadcast bool
|
||||||
|
if maybeDirect {
|
||||||
|
hasher.Reset()
|
||||||
|
hasher.Write(h.nodeID.Bytes())
|
||||||
|
hasher.Write(peer.Node().ID().Bytes())
|
||||||
|
|
||||||
|
from, _ := types.Sender(signer, tx) // Ignore error, we only use the addr as a propagation target splitter
|
||||||
|
hasher.Write(from.Bytes())
|
||||||
|
|
||||||
|
hasher.Read(hash)
|
||||||
|
if new(big.Int).Mod(new(big.Int).SetBytes(hash), total).Cmp(direct) < 0 {
|
||||||
|
broadcast = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if broadcast {
|
||||||
|
txset[peer] = append(txset[peer], tx.Hash())
|
||||||
|
} else {
|
||||||
|
annos[peer] = append(annos[peer], tx.Hash())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for peer, hashes := range txset {
|
for peer, hashes := range txset {
|
||||||
|
|||||||
@@ -633,9 +633,6 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) {
|
|||||||
go source.handler.runEthPeer(sourcePeer, func(peer *eth.Peer) error {
|
go source.handler.runEthPeer(sourcePeer, func(peer *eth.Peer) error {
|
||||||
return eth.Handle((*ethHandler)(source.handler), peer)
|
return eth.Handle((*ethHandler)(source.handler), peer)
|
||||||
})
|
})
|
||||||
// Wait a bit for the above handlers to start
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
|
|
||||||
if err := sinkPeer.Handshake(1, td, genesis.Hash(), genesis.Hash(), forkid.NewIDWithChain(source.chain), forkid.NewFilter(source.chain), nil); err != nil {
|
if err := sinkPeer.Handshake(1, td, genesis.Hash(), genesis.Hash(), forkid.NewIDWithChain(source.chain), forkid.NewFilter(source.chain), nil); err != nil {
|
||||||
t.Fatalf("failed to run protocol handshake")
|
t.Fatalf("failed to run protocol handshake")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ func (c *mockParlia) CalcDifficulty(chain consensus.ChainHeaderReader, time uint
|
|||||||
func newTestParliaHandlerAfterCancun(t *testing.T, config *params.ChainConfig, mode downloader.SyncMode, preCancunBlks, postCancunBlks uint64) *testHandler {
|
func newTestParliaHandlerAfterCancun(t *testing.T, config *params.ChainConfig, mode downloader.SyncMode, preCancunBlks, postCancunBlks uint64) *testHandler {
|
||||||
// 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, false)
|
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", 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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,8 +151,6 @@ func testChainSyncWithBlobs(t *testing.T, mode downloader.SyncMode, preCancunBlk
|
|||||||
go full.handler.runEthPeer(fullPeerEth, func(peer *eth.Peer) error {
|
go full.handler.runEthPeer(fullPeerEth, func(peer *eth.Peer) error {
|
||||||
return eth.Handle((*ethHandler)(full.handler), peer)
|
return eth.Handle((*ethHandler)(full.handler), peer)
|
||||||
})
|
})
|
||||||
// Wait a bit for the above handlers to start
|
|
||||||
time.Sleep(250 * time.Millisecond)
|
|
||||||
|
|
||||||
emptyPipeSnap, fullPipeSnap := p2p.MsgPipe()
|
emptyPipeSnap, fullPipeSnap := p2p.MsgPipe()
|
||||||
defer emptyPipeSnap.Close()
|
defer emptyPipeSnap.Close()
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumb
|
|||||||
// BlobSidecars return the Sidecars of a given block number or hash.
|
// BlobSidecars return the Sidecars of a given block number or hash.
|
||||||
func (ec *Client) BlobSidecars(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.BlobTxSidecar, error) {
|
func (ec *Client) BlobSidecars(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.BlobTxSidecar, error) {
|
||||||
var r []*types.BlobTxSidecar
|
var r []*types.BlobTxSidecar
|
||||||
err := ec.c.CallContext(ctx, &r, "eth_getBlobSidecars", blockNrOrHash.String())
|
err := ec.c.CallContext(ctx, &r, "eth_getBlobSidecars", blockNrOrHash.String(), true)
|
||||||
if err == nil && r == nil {
|
if err == nil && r == nil {
|
||||||
return nil, ethereum.NotFound
|
return nil, ethereum.NotFound
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ func (ec *Client) BlobSidecars(ctx context.Context, blockNrOrHash rpc.BlockNumbe
|
|||||||
// BlobSidecarByTxHash return a sidecar of a given blob transaction
|
// BlobSidecarByTxHash return a sidecar of a given blob transaction
|
||||||
func (ec *Client) BlobSidecarByTxHash(ctx context.Context, hash common.Hash) (*types.BlobTxSidecar, error) {
|
func (ec *Client) BlobSidecarByTxHash(ctx context.Context, hash common.Hash) (*types.BlobTxSidecar, error) {
|
||||||
var r *types.BlobTxSidecar
|
var r *types.BlobTxSidecar
|
||||||
err := ec.c.CallContext(ctx, &r, "eth_getBlobSidecarByTxHash", hash)
|
err := ec.c.CallContext(ctx, &r, "eth_getBlockSidecarByTxHash", hash, true)
|
||||||
if err == nil && r == nil {
|
if err == nil && r == nil {
|
||||||
return nil, ethereum.NotFound
|
return nil, ethereum.NotFound
|
||||||
}
|
}
|
||||||
@@ -752,13 +752,6 @@ func (ec *Client) MevRunning(ctx context.Context) (bool, error) {
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasBuilder returns whether the builder is registered
|
|
||||||
func (ec *Client) HasBuilder(ctx context.Context, address common.Address) (bool, error) {
|
|
||||||
var result bool
|
|
||||||
err := ec.c.CallContext(ctx, &result, "mev_hasBuilder", address)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendBid sends a bid
|
// SendBid sends a bid
|
||||||
func (ec *Client) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, error) {
|
func (ec *Client) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, error) {
|
||||||
var hash common.Hash
|
var hash common.Hash
|
||||||
|
|||||||
@@ -183,7 +183,6 @@ type StateStoreReader interface {
|
|||||||
type BlockStore interface {
|
type BlockStore interface {
|
||||||
BlockStore() Database
|
BlockStore() Database
|
||||||
SetBlockStore(block Database)
|
SetBlockStore(block Database)
|
||||||
HasSeparateBlockStore() bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockStoreReader interface {
|
type BlockStoreReader interface {
|
||||||
|
|||||||
@@ -44,10 +44,6 @@ func (db *Database) BlockStore() ethdb.Database {
|
|||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) HasSeparateBlockStore() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *Database) SetBlockStore(block ethdb.Database) {
|
func (db *Database) SetBlockStore(block ethdb.Database) {
|
||||||
panic("not supported")
|
panic("not supported")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,10 +87,6 @@ func (m *MevAPI) Params() *types.MevParams {
|
|||||||
return m.b.MevParams()
|
return m.b.MevParams()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MevAPI) HasBuilder(builder common.Address) bool {
|
|
||||||
return m.b.HasBuilder(builder)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Running returns true if mev is running
|
// Running returns true if mev is running
|
||||||
func (m *MevAPI) Running() bool {
|
func (m *MevAPI) Running() bool {
|
||||||
return m.b.MevRunning()
|
return m.b.MevRunning()
|
||||||
|
|||||||
@@ -650,8 +650,7 @@ func (b testBackend) ServiceFilter(ctx context.Context, session *bloombits.Match
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *testBackend) MevRunning() bool { return false }
|
func (b *testBackend) MevRunning() bool { return false }
|
||||||
func (b *testBackend) HasBuilder(builder common.Address) bool { return false }
|
|
||||||
func (b *testBackend) MevParams() *types.MevParams {
|
func (b *testBackend) MevParams() *types.MevParams {
|
||||||
return &types.MevParams{}
|
return &types.MevParams{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ type Backend interface {
|
|||||||
AddBuilder(builder common.Address, builderUrl string) error
|
AddBuilder(builder common.Address, builderUrl string) error
|
||||||
// RemoveBuilder removes a builder from the bid simulator.
|
// RemoveBuilder removes a builder from the bid simulator.
|
||||||
RemoveBuilder(builder common.Address) error
|
RemoveBuilder(builder common.Address) error
|
||||||
// HasBuilder returns true if the builder is in the builder list.
|
|
||||||
HasBuilder(builder common.Address) bool
|
|
||||||
// SendBid receives bid from the builders.
|
// SendBid receives bid from the builders.
|
||||||
SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error)
|
SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error)
|
||||||
// BestBidGasFee returns the gas fee of the best bid for the given parent hash.
|
// BestBidGasFee returns the gas fee of the best bid for the given parent hash.
|
||||||
|
|||||||
@@ -204,8 +204,7 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro
|
|||||||
// Sanity check the EIP-1559 fee parameters if present.
|
// Sanity check the EIP-1559 fee parameters if present.
|
||||||
if args.GasPrice == nil && eip1559ParamsSet {
|
if args.GasPrice == nil && eip1559ParamsSet {
|
||||||
if args.MaxFeePerGas.ToInt().Sign() == 0 {
|
if args.MaxFeePerGas.ToInt().Sign() == 0 {
|
||||||
// return errors.New("maxFeePerGas must be non-zero")
|
return errors.New("maxFeePerGas must be non-zero")
|
||||||
log.Warn("EIP-1559 Tx with zero maxFeePerGas") // BSC accepts zero gas price.
|
|
||||||
}
|
}
|
||||||
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
|
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
|
||||||
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
|
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
|
||||||
@@ -218,8 +217,7 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro
|
|||||||
if args.GasPrice != nil && !eip1559ParamsSet {
|
if args.GasPrice != nil && !eip1559ParamsSet {
|
||||||
// Zero gas-price is not allowed after London fork
|
// Zero gas-price is not allowed after London fork
|
||||||
if args.GasPrice.ToInt().Sign() == 0 && isLondon {
|
if args.GasPrice.ToInt().Sign() == 0 && isLondon {
|
||||||
// return errors.New("gasPrice must be non-zero after london fork")
|
return errors.New("gasPrice must be non-zero after london fork")
|
||||||
log.Warn("non EIP-1559 Tx with zero gasPrice") // BSC accepts zero gas price.
|
|
||||||
}
|
}
|
||||||
return nil // No need to set anything, user already set GasPrice
|
return nil // No need to set anything, user already set GasPrice
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,8 +85,8 @@ func TestSetFeeDefaults(t *testing.T) {
|
|||||||
"legacy tx post-London with zero price",
|
"legacy tx post-London with zero price",
|
||||||
"london",
|
"london",
|
||||||
&TransactionArgs{GasPrice: zero},
|
&TransactionArgs{GasPrice: zero},
|
||||||
&TransactionArgs{GasPrice: zero},
|
nil,
|
||||||
nil, // errors.New("gasPrice must be non-zero after london fork"),
|
errors.New("gasPrice must be non-zero after london fork"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// Access list txs
|
// Access list txs
|
||||||
@@ -180,8 +180,8 @@ func TestSetFeeDefaults(t *testing.T) {
|
|||||||
"dynamic fee tx post-London, explicit gas price",
|
"dynamic fee tx post-London, explicit gas price",
|
||||||
"london",
|
"london",
|
||||||
&TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
|
&TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
|
||||||
&TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
|
nil,
|
||||||
nil, // errors.New("maxFeePerGas must be non-zero"),
|
errors.New("maxFeePerGas must be non-zero"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
@@ -416,8 +416,7 @@ func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent)
|
|||||||
|
|
||||||
func (b *backendMock) Engine() consensus.Engine { return nil }
|
func (b *backendMock) Engine() consensus.Engine { return nil }
|
||||||
|
|
||||||
func (b *backendMock) MevRunning() bool { return false }
|
func (b *backendMock) MevRunning() bool { return false }
|
||||||
func (b *backendMock) HasBuilder(builder common.Address) bool { return false }
|
|
||||||
func (b *backendMock) MevParams() *types.MevParams {
|
func (b *backendMock) MevParams() *types.MevParams {
|
||||||
return &types.MevParams{}
|
return &types.MevParams{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ import (
|
|||||||
const (
|
const (
|
||||||
// maxBidPerBuilderPerBlock is the max bid number per builder
|
// maxBidPerBuilderPerBlock is the max bid number per builder
|
||||||
maxBidPerBuilderPerBlock = 3
|
maxBidPerBuilderPerBlock = 3
|
||||||
|
|
||||||
|
// leftOverTimeRate is the rate of left over time to simulate a bid
|
||||||
|
leftOverTimeRate = 11
|
||||||
|
// leftOverTimeScale is the scale of left over time to simulate a bid
|
||||||
|
leftOverTimeScale = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -313,6 +318,18 @@ func (b *bidSimulator) newBidLoop() {
|
|||||||
|
|
||||||
// commit aborts in-flight bid execution with given signal and resubmits a new one.
|
// commit aborts in-flight bid execution with given signal and resubmits a new one.
|
||||||
commit := func(reason int32, bidRuntime *BidRuntime) {
|
commit := func(reason int32, bidRuntime *BidRuntime) {
|
||||||
|
// if the left time is not enough to do simulation, return
|
||||||
|
var simDuration time.Duration
|
||||||
|
if lastBid := b.GetBestBid(bidRuntime.bid.ParentHash); lastBid != nil && lastBid.duration != 0 {
|
||||||
|
simDuration = lastBid.duration
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Until(b.bidMustBefore(bidRuntime.bid.ParentHash)) <= simDuration*leftOverTimeRate/leftOverTimeScale {
|
||||||
|
log.Debug("BidSimulator: abort commit, not enough time to simulate",
|
||||||
|
"builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if interruptCh != nil {
|
if interruptCh != nil {
|
||||||
// each commit work will have its own interruptCh to stop work with a reason
|
// each commit work will have its own interruptCh to stop work with a reason
|
||||||
interruptCh <- reason
|
interruptCh <- reason
|
||||||
@@ -353,7 +370,6 @@ func (b *bidSimulator) newBidLoop() {
|
|||||||
expectedValidatorReward: expectedValidatorReward,
|
expectedValidatorReward: expectedValidatorReward,
|
||||||
packedBlockReward: big.NewInt(0),
|
packedBlockReward: big.NewInt(0),
|
||||||
packedValidatorReward: big.NewInt(0),
|
packedValidatorReward: big.NewInt(0),
|
||||||
finished: make(chan struct{}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
simulatingBid := b.GetSimulatingBid(newBid.ParentHash)
|
simulatingBid := b.GetSimulatingBid(newBid.ParentHash)
|
||||||
@@ -394,6 +410,11 @@ func (b *bidSimulator) newBidLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *bidSimulator) bidMustBefore(parentHash common.Hash) time.Time {
|
||||||
|
parentHeader := b.chain.GetHeaderByHash(parentHash)
|
||||||
|
return bidutil.BidMustBefore(parentHeader, b.chainConfig.Parlia.Period, b.delayLeftOver)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *bidSimulator) bidBetterBefore(parentHash common.Hash) time.Time {
|
func (b *bidSimulator) bidBetterBefore(parentHash common.Hash) time.Time {
|
||||||
parentHeader := b.chain.GetHeaderByHash(parentHash)
|
parentHeader := b.chain.GetHeaderByHash(parentHash)
|
||||||
return bidutil.BidBetterBefore(parentHeader, b.chainConfig.Parlia.Period, b.delayLeftOver, b.config.BidSimulationLeftOver)
|
return bidutil.BidBetterBefore(parentHeader, b.chainConfig.Parlia.Period, b.delayLeftOver, b.config.BidSimulationLeftOver)
|
||||||
@@ -419,6 +440,10 @@ func (b *bidSimulator) clearLoop() {
|
|||||||
b.bestBidMu.Unlock()
|
b.bestBidMu.Unlock()
|
||||||
|
|
||||||
b.simBidMu.Lock()
|
b.simBidMu.Lock()
|
||||||
|
if bid, ok := b.simulatingBid[parentHash]; ok {
|
||||||
|
bid.env.discard()
|
||||||
|
}
|
||||||
|
delete(b.simulatingBid, parentHash)
|
||||||
for k, v := range b.simulatingBid {
|
for k, v := range b.simulatingBid {
|
||||||
if v.bid.BlockNumber <= blockNumber-core.TriesInMemory {
|
if v.bid.BlockNumber <= blockNumber-core.TriesInMemory {
|
||||||
v.env.discard()
|
v.env.discard()
|
||||||
@@ -505,6 +530,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
|
|||||||
|
|
||||||
// ensure simulation exited then start next simulation
|
// ensure simulation exited then start next simulation
|
||||||
b.SetSimulatingBid(parentHash, bidRuntime)
|
b.SetSimulatingBid(parentHash, bidRuntime)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
defer func(simStart time.Time) {
|
defer func(simStart time.Time) {
|
||||||
logCtx := []any{
|
logCtx := []any{
|
||||||
@@ -530,11 +556,10 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.RemoveSimulatingBid(parentHash)
|
b.RemoveSimulatingBid(parentHash)
|
||||||
close(bidRuntime.finished)
|
bidSimTimer.UpdateSince(start)
|
||||||
|
|
||||||
if success {
|
if success {
|
||||||
bidRuntime.duration = time.Since(simStart)
|
bidRuntime.duration = time.Since(simStart)
|
||||||
bidSimTimer.UpdateSince(simStart)
|
|
||||||
|
|
||||||
// only recommit self bid when newBidCh is empty
|
// only recommit self bid when newBidCh is empty
|
||||||
if len(b.newBidCh) > 0 {
|
if len(b.newBidCh) > 0 {
|
||||||
@@ -558,14 +583,6 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the left time is not enough to do simulation, return
|
|
||||||
delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver)
|
|
||||||
if delay == nil || *delay <= 0 {
|
|
||||||
log.Info("BidSimulator: abort commit, not enough time to simulate",
|
|
||||||
"builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
gasLimit := bidRuntime.env.header.GasLimit
|
gasLimit := bidRuntime.env.header.GasLimit
|
||||||
if bidRuntime.env.gasPool == nil {
|
if bidRuntime.env.gasPool == nil {
|
||||||
bidRuntime.env.gasPool = new(core.GasPool).AddGas(gasLimit)
|
bidRuntime.env.gasPool = new(core.GasPool).AddGas(gasLimit)
|
||||||
@@ -633,12 +650,14 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
|
|||||||
if b.config.GreedyMergeTx {
|
if b.config.GreedyMergeTx {
|
||||||
delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver)
|
delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver)
|
||||||
if delay != nil && *delay > 0 {
|
if delay != nil && *delay > 0 {
|
||||||
|
stopTimer := time.NewTimer(*delay)
|
||||||
|
|
||||||
bidTxsSet := mapset.NewSet[common.Hash]()
|
bidTxsSet := mapset.NewSet[common.Hash]()
|
||||||
for _, tx := range bidRuntime.bid.Txs {
|
for _, tx := range bidRuntime.bid.Txs {
|
||||||
bidTxsSet.Add(tx.Hash())
|
bidTxsSet.Add(tx.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
fillErr := b.bidWorker.fillTransactions(interruptCh, bidRuntime.env, nil, bidTxsSet)
|
fillErr := b.bidWorker.fillTransactions(interruptCh, bidRuntime.env, stopTimer, bidTxsSet)
|
||||||
log.Trace("BidSimulator: greedy merge stopped", "block", bidRuntime.env.header.Number,
|
log.Trace("BidSimulator: greedy merge stopped", "block", bidRuntime.env.header.Number,
|
||||||
"builder", bidRuntime.bid.Builder, "tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr)
|
"builder", bidRuntime.bid.Builder, "tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr)
|
||||||
|
|
||||||
@@ -714,7 +733,6 @@ type BidRuntime struct {
|
|||||||
packedBlockReward *big.Int
|
packedBlockReward *big.Int
|
||||||
packedValidatorReward *big.Int
|
packedValidatorReward *big.Int
|
||||||
|
|
||||||
finished chan struct{}
|
|
||||||
duration time.Duration
|
duration time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"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/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type BuilderConfig struct {
|
type BuilderConfig struct {
|
||||||
@@ -60,11 +59,6 @@ func (miner *Miner) RemoveBuilder(builderAddr common.Address) error {
|
|||||||
return miner.bidSimulator.RemoveBuilder(builderAddr)
|
return miner.bidSimulator.RemoveBuilder(builderAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasBuilder returns true if the builder is in the builder list.
|
|
||||||
func (miner *Miner) HasBuilder(builder common.Address) bool {
|
|
||||||
return miner.bidSimulator.ExistBuilder(builder)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (miner *Miner) SendBid(ctx context.Context, bidArgs *types.BidArgs) (common.Hash, error) {
|
func (miner *Miner) SendBid(ctx context.Context, bidArgs *types.BidArgs) (common.Hash, error) {
|
||||||
builder, err := bidArgs.EcrecoverSender()
|
builder, err := bidArgs.EcrecoverSender()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -123,8 +117,6 @@ func (miner *Miner) MevParams() *types.MevParams {
|
|||||||
ValidatorCommission: miner.worker.config.Mev.ValidatorCommission,
|
ValidatorCommission: miner.worker.config.Mev.ValidatorCommission,
|
||||||
BidSimulationLeftOver: miner.worker.config.Mev.BidSimulationLeftOver,
|
BidSimulationLeftOver: miner.worker.config.Mev.BidSimulationLeftOver,
|
||||||
GasCeil: miner.worker.config.GasCeil,
|
GasCeil: miner.worker.config.GasCeil,
|
||||||
GasPrice: miner.worker.config.GasPrice,
|
|
||||||
BuilderFeeCeil: builderFeeCeil,
|
BuilderFeeCeil: builderFeeCeil,
|
||||||
Version: params.Version,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,9 +67,6 @@ const (
|
|||||||
// the current 4 mining loops could have asynchronous risk of mining block with
|
// the current 4 mining loops could have asynchronous risk of mining block with
|
||||||
// save height, keep recently mined blocks to avoid double sign for safety,
|
// save height, keep recently mined blocks to avoid double sign for safety,
|
||||||
recentMinedCacheLimit = 20
|
recentMinedCacheLimit = 20
|
||||||
|
|
||||||
// the default to wait for the mev miner to finish
|
|
||||||
waitMEVMinerEndTimeLimit = 50 * time.Millisecond
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -174,7 +171,6 @@ type getWorkReq struct {
|
|||||||
|
|
||||||
type bidFetcher interface {
|
type bidFetcher interface {
|
||||||
GetBestBid(parentHash common.Hash) *BidRuntime
|
GetBestBid(parentHash common.Hash) *BidRuntime
|
||||||
GetSimulatingBid(prevBlockHash common.Hash) *BidRuntime
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// worker is the main object which takes care of submitting new work to consensus engine
|
// worker is the main object which takes care of submitting new work to consensus engine
|
||||||
@@ -1340,15 +1336,6 @@ LOOP:
|
|||||||
// when in-turn, compare with remote work.
|
// when in-turn, compare with remote work.
|
||||||
from := bestWork.coinbase
|
from := bestWork.coinbase
|
||||||
if w.bidFetcher != nil && bestWork.header.Difficulty.Cmp(diffInTurn) == 0 {
|
if w.bidFetcher != nil && bestWork.header.Difficulty.Cmp(diffInTurn) == 0 {
|
||||||
if pendingBid := w.bidFetcher.GetSimulatingBid(bestWork.header.ParentHash); pendingBid != nil {
|
|
||||||
waitBidTimer := time.NewTimer(waitMEVMinerEndTimeLimit)
|
|
||||||
defer waitBidTimer.Stop()
|
|
||||||
select {
|
|
||||||
case <-waitBidTimer.C:
|
|
||||||
case <-pendingBid.finished:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bestBid := w.bidFetcher.GetBestBid(bestWork.header.ParentHash)
|
bestBid := w.bidFetcher.GetBestBid(bestWork.header.ParentHash)
|
||||||
|
|
||||||
if bestBid != nil {
|
if bestBid != nil {
|
||||||
|
|||||||
13
node/node.go
13
node/node.go
@@ -773,13 +773,12 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r
|
|||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
} else {
|
} else {
|
||||||
db, err = rawdb.Open(rawdb.OpenOptions{
|
db, err = rawdb.Open(rawdb.OpenOptions{
|
||||||
Type: n.config.DBEngine,
|
Type: n.config.DBEngine,
|
||||||
Directory: n.ResolvePath(name),
|
Directory: n.ResolvePath(name),
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Cache: cache,
|
Cache: cache,
|
||||||
Handles: handles,
|
Handles: handles,
|
||||||
ReadOnly: readonly,
|
ReadOnly: readonly,
|
||||||
MultiDataBase: n.CheckIfMultiDataBase(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,8 +153,6 @@ var (
|
|||||||
FeynmanFixTime: newUint64(1713419340), // 2024-04-18 05:49:00 AM UTC
|
FeynmanFixTime: newUint64(1713419340), // 2024-04-18 05:49:00 AM UTC
|
||||||
CancunTime: newUint64(1718863500), // 2024-06-20 06:05:00 AM UTC
|
CancunTime: newUint64(1718863500), // 2024-06-20 06:05:00 AM UTC
|
||||||
HaberTime: newUint64(1718863500), // 2024-06-20 06:05:00 AM UTC
|
HaberTime: newUint64(1718863500), // 2024-06-20 06:05:00 AM UTC
|
||||||
HaberFixTime: nil, // TBD
|
|
||||||
BohrTime: nil,
|
|
||||||
|
|
||||||
Parlia: &ParliaConfig{
|
Parlia: &ParliaConfig{
|
||||||
Period: 3,
|
Period: 3,
|
||||||
@@ -194,8 +192,6 @@ var (
|
|||||||
FeynmanFixTime: newUint64(1711342800), // 2024-03-25 5:00:00 AM UTC
|
FeynmanFixTime: newUint64(1711342800), // 2024-03-25 5:00:00 AM UTC
|
||||||
CancunTime: newUint64(1713330442), // 2024-04-17 05:07:22 AM UTC
|
CancunTime: newUint64(1713330442), // 2024-04-17 05:07:22 AM UTC
|
||||||
HaberTime: newUint64(1716962820), // 2024-05-29 06:07:00 AM UTC
|
HaberTime: newUint64(1716962820), // 2024-05-29 06:07:00 AM UTC
|
||||||
HaberFixTime: newUint64(1719986788), // 2024-07-03 06:06:28 AM UTC
|
|
||||||
BohrTime: nil,
|
|
||||||
|
|
||||||
Parlia: &ParliaConfig{
|
Parlia: &ParliaConfig{
|
||||||
Period: 3,
|
Period: 3,
|
||||||
@@ -236,8 +232,6 @@ var (
|
|||||||
FeynmanFixTime: newUint64(0),
|
FeynmanFixTime: newUint64(0),
|
||||||
CancunTime: newUint64(0),
|
CancunTime: newUint64(0),
|
||||||
HaberTime: newUint64(0),
|
HaberTime: newUint64(0),
|
||||||
HaberFixTime: newUint64(0),
|
|
||||||
BohrTime: newUint64(0),
|
|
||||||
|
|
||||||
Parlia: &ParliaConfig{
|
Parlia: &ParliaConfig{
|
||||||
Period: 3,
|
Period: 3,
|
||||||
@@ -515,8 +509,6 @@ type ChainConfig struct {
|
|||||||
FeynmanFixTime *uint64 `json:"feynmanFixTime,omitempty"` // FeynmanFix switch time (nil = no fork, 0 = already activated)
|
FeynmanFixTime *uint64 `json:"feynmanFixTime,omitempty"` // FeynmanFix switch time (nil = no fork, 0 = already activated)
|
||||||
CancunTime *uint64 `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun)
|
CancunTime *uint64 `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun)
|
||||||
HaberTime *uint64 `json:"haberTime,omitempty"` // Haber switch time (nil = no fork, 0 = already on haber)
|
HaberTime *uint64 `json:"haberTime,omitempty"` // Haber switch time (nil = no fork, 0 = already on haber)
|
||||||
HaberFixTime *uint64 `json:"haberFixTime,omitempty"` // HaberFix switch time (nil = no fork, 0 = already on haberFix)
|
|
||||||
BohrTime *uint64 `json:"bohrTime,omitempty"` // Bohr switch time (nil = no fork, 0 = already on bohr)
|
|
||||||
PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague)
|
PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague)
|
||||||
VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle)
|
VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle)
|
||||||
|
|
||||||
@@ -627,17 +619,7 @@ func (c *ChainConfig) String() string {
|
|||||||
HaberTime = big.NewInt(0).SetUint64(*c.HaberTime)
|
HaberTime = big.NewInt(0).SetUint64(*c.HaberTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
var HaberFixTime *big.Int
|
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Hertzfix: %v, ShanghaiTime: %v, KeplerTime: %v, FeynmanTime: %v, FeynmanFixTime: %v, CancunTime: %v, HaberTime: %v, Engine: %v}",
|
||||||
if c.HaberFixTime != nil {
|
|
||||||
HaberFixTime = big.NewInt(0).SetUint64(*c.HaberFixTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
var BohrTime *big.Int
|
|
||||||
if c.BohrTime != nil {
|
|
||||||
BohrTime = big.NewInt(0).SetUint64(*c.BohrTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Hertzfix: %v, ShanghaiTime: %v, KeplerTime: %v, FeynmanTime: %v, FeynmanFixTime: %v, CancunTime: %v, HaberTime: %v, HaberFixTime: %v, BohrTime: %v, Engine: %v}",
|
|
||||||
c.ChainID,
|
c.ChainID,
|
||||||
c.HomesteadBlock,
|
c.HomesteadBlock,
|
||||||
c.DAOForkBlock,
|
c.DAOForkBlock,
|
||||||
@@ -675,8 +657,6 @@ func (c *ChainConfig) String() string {
|
|||||||
FeynmanFixTime,
|
FeynmanFixTime,
|
||||||
CancunTime,
|
CancunTime,
|
||||||
HaberTime,
|
HaberTime,
|
||||||
HaberFixTime,
|
|
||||||
BohrTime,
|
|
||||||
engine,
|
engine,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -949,34 +929,6 @@ func (c *ChainConfig) IsHaber(num *big.Int, time uint64) bool {
|
|||||||
return c.IsLondon(num) && isTimestampForked(c.HaberTime, time)
|
return c.IsLondon(num) && isTimestampForked(c.HaberTime, time)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsHaberFix returns whether time is either equal to the HaberFix fork time or greater.
|
|
||||||
func (c *ChainConfig) IsHaberFix(num *big.Int, time uint64) bool {
|
|
||||||
return c.IsLondon(num) && isTimestampForked(c.HaberFixTime, time)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOnHaberFix returns whether currentBlockTime is either equal to the HaberFix fork time or greater firstly.
|
|
||||||
func (c *ChainConfig) IsOnHaberFix(currentBlockNumber *big.Int, lastBlockTime uint64, currentBlockTime uint64) bool {
|
|
||||||
lastBlockNumber := new(big.Int)
|
|
||||||
if currentBlockNumber.Cmp(big.NewInt(1)) >= 0 {
|
|
||||||
lastBlockNumber.Sub(currentBlockNumber, big.NewInt(1))
|
|
||||||
}
|
|
||||||
return !c.IsHaberFix(lastBlockNumber, lastBlockTime) && c.IsHaberFix(currentBlockNumber, currentBlockTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsBohr returns whether time is either equal to the Bohr fork time or greater.
|
|
||||||
func (c *ChainConfig) IsBohr(num *big.Int, time uint64) bool {
|
|
||||||
return c.IsLondon(num) && isTimestampForked(c.BohrTime, time)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOnBohr returns whether currentBlockTime is either equal to the Bohr fork time or greater firstly.
|
|
||||||
func (c *ChainConfig) IsOnBohr(currentBlockNumber *big.Int, lastBlockTime uint64, currentBlockTime uint64) bool {
|
|
||||||
lastBlockNumber := new(big.Int)
|
|
||||||
if currentBlockNumber.Cmp(big.NewInt(1)) >= 0 {
|
|
||||||
lastBlockNumber.Sub(currentBlockNumber, big.NewInt(1))
|
|
||||||
}
|
|
||||||
return !c.IsBohr(lastBlockNumber, lastBlockTime) && c.IsBohr(currentBlockNumber, currentBlockTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPrague returns whether num is either equal to the Prague fork time or greater.
|
// IsPrague returns whether num is either equal to the Prague fork time or greater.
|
||||||
func (c *ChainConfig) IsPrague(num *big.Int, time uint64) bool {
|
func (c *ChainConfig) IsPrague(num *big.Int, time uint64) bool {
|
||||||
return c.IsLondon(num) && isTimestampForked(c.PragueTime, time)
|
return c.IsLondon(num) && isTimestampForked(c.PragueTime, time)
|
||||||
@@ -1041,8 +993,6 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
|
|||||||
{name: "feynmanFixTime", timestamp: c.FeynmanFixTime},
|
{name: "feynmanFixTime", timestamp: c.FeynmanFixTime},
|
||||||
{name: "cancunTime", timestamp: c.CancunTime},
|
{name: "cancunTime", timestamp: c.CancunTime},
|
||||||
{name: "haberTime", timestamp: c.HaberTime},
|
{name: "haberTime", timestamp: c.HaberTime},
|
||||||
{name: "haberFixTime", timestamp: c.HaberFixTime},
|
|
||||||
{name: "bohrTime", timestamp: c.BohrTime},
|
|
||||||
{name: "pragueTime", timestamp: c.PragueTime, optional: true},
|
{name: "pragueTime", timestamp: c.PragueTime, optional: true},
|
||||||
{name: "verkleTime", timestamp: c.VerkleTime, optional: true},
|
{name: "verkleTime", timestamp: c.VerkleTime, optional: true},
|
||||||
} {
|
} {
|
||||||
@@ -1190,15 +1140,6 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int,
|
|||||||
if isForkTimestampIncompatible(c.CancunTime, newcfg.CancunTime, headTimestamp) {
|
if isForkTimestampIncompatible(c.CancunTime, newcfg.CancunTime, headTimestamp) {
|
||||||
return newTimestampCompatError("Cancun fork timestamp", c.CancunTime, newcfg.CancunTime)
|
return newTimestampCompatError("Cancun fork timestamp", c.CancunTime, newcfg.CancunTime)
|
||||||
}
|
}
|
||||||
if isForkTimestampIncompatible(c.HaberTime, newcfg.HaberTime, headTimestamp) {
|
|
||||||
return newTimestampCompatError("Haber fork timestamp", c.HaberTime, newcfg.HaberTime)
|
|
||||||
}
|
|
||||||
if isForkTimestampIncompatible(c.HaberFixTime, newcfg.HaberFixTime, headTimestamp) {
|
|
||||||
return newTimestampCompatError("HaberFix fork timestamp", c.HaberFixTime, newcfg.HaberFixTime)
|
|
||||||
}
|
|
||||||
if isForkTimestampIncompatible(c.BohrTime, newcfg.BohrTime, headTimestamp) {
|
|
||||||
return newTimestampCompatError("Bohr fork timestamp", c.BohrTime, newcfg.BohrTime)
|
|
||||||
}
|
|
||||||
if isForkTimestampIncompatible(c.PragueTime, newcfg.PragueTime, headTimestamp) {
|
if isForkTimestampIncompatible(c.PragueTime, newcfg.PragueTime, headTimestamp) {
|
||||||
return newTimestampCompatError("Prague fork timestamp", c.PragueTime, newcfg.PragueTime)
|
return newTimestampCompatError("Prague fork timestamp", c.PragueTime, newcfg.PragueTime)
|
||||||
}
|
}
|
||||||
@@ -1382,7 +1323,7 @@ type Rules struct {
|
|||||||
IsHertz bool
|
IsHertz bool
|
||||||
IsHertzfix bool
|
IsHertzfix bool
|
||||||
IsShanghai, IsKepler, IsFeynman, IsCancun, IsHaber bool
|
IsShanghai, IsKepler, IsFeynman, IsCancun, IsHaber bool
|
||||||
IsBohr, IsPrague, IsVerkle bool
|
IsPrague, IsVerkle bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rules ensures c's ChainID is not nil.
|
// Rules ensures c's ChainID is not nil.
|
||||||
@@ -1418,7 +1359,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
|
|||||||
IsFeynman: c.IsFeynman(num, timestamp),
|
IsFeynman: c.IsFeynman(num, timestamp),
|
||||||
IsCancun: c.IsCancun(num, timestamp),
|
IsCancun: c.IsCancun(num, timestamp),
|
||||||
IsHaber: c.IsHaber(num, timestamp),
|
IsHaber: c.IsHaber(num, timestamp),
|
||||||
IsBohr: c.IsBohr(num, timestamp),
|
|
||||||
IsPrague: c.IsPrague(num, timestamp),
|
IsPrague: c.IsPrague(num, timestamp),
|
||||||
IsVerkle: c.IsVerkle(num, timestamp),
|
IsVerkle: c.IsVerkle(num, timestamp),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 4 // Minor version component of the current release
|
VersionMinor = 4 // Minor version component of the current release
|
||||||
VersionPatch = 11 // Patch version component of the current release
|
VersionPatch = 8 // Patch version component of the current release
|
||||||
VersionMeta = "" // Version metadata to append to the version string
|
VersionMeta = "" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ type tester struct {
|
|||||||
|
|
||||||
func newTester(t *testing.T, historyLimit uint64) *tester {
|
func newTester(t *testing.T, historyLimit uint64) *tester {
|
||||||
var (
|
var (
|
||||||
disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false, false)
|
disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
|
||||||
db = New(disk, &Config{
|
db = New(disk, &Config{
|
||||||
StateHistory: historyLimit,
|
StateHistory: historyLimit,
|
||||||
CleanCacheSize: 256 * 1024,
|
CleanCacheSize: 256 * 1024,
|
||||||
|
|||||||
@@ -26,106 +26,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RefTrieNode struct {
|
|
||||||
refCount uint32
|
|
||||||
node *trienode.Node
|
|
||||||
}
|
|
||||||
|
|
||||||
type HashNodeCache struct {
|
|
||||||
lock sync.RWMutex
|
|
||||||
cache map[common.Hash]*RefTrieNode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HashNodeCache) length() int {
|
|
||||||
if h == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
h.lock.RLock()
|
|
||||||
defer h.lock.RUnlock()
|
|
||||||
return len(h.cache)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HashNodeCache) set(hash common.Hash, node *trienode.Node) {
|
|
||||||
if h == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h.lock.Lock()
|
|
||||||
defer h.lock.Unlock()
|
|
||||||
if n, ok := h.cache[hash]; ok {
|
|
||||||
n.refCount++
|
|
||||||
} else {
|
|
||||||
h.cache[hash] = &RefTrieNode{1, node}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HashNodeCache) Get(hash common.Hash) *trienode.Node {
|
|
||||||
if h == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
h.lock.RLock()
|
|
||||||
defer h.lock.RUnlock()
|
|
||||||
if n, ok := h.cache[hash]; ok {
|
|
||||||
return n.node
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HashNodeCache) del(hash common.Hash) {
|
|
||||||
if h == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h.lock.Lock()
|
|
||||||
defer h.lock.Unlock()
|
|
||||||
n, ok := h.cache[hash]
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if n.refCount > 0 {
|
|
||||||
n.refCount--
|
|
||||||
}
|
|
||||||
if n.refCount == 0 {
|
|
||||||
delete(h.cache, hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HashNodeCache) Add(ly layer) {
|
|
||||||
if h == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dl, ok := ly.(*diffLayer)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
beforeAdd := h.length()
|
|
||||||
for _, subset := range dl.nodes {
|
|
||||||
for _, node := range subset {
|
|
||||||
h.set(node.Hash, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diffHashCacheLengthGauge.Update(int64(h.length()))
|
|
||||||
log.Debug("Add difflayer to hash map", "root", ly.rootHash(), "block_number", dl.block, "map_len", h.length(), "add_delta", h.length()-beforeAdd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HashNodeCache) Remove(ly layer) {
|
|
||||||
if h == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dl, ok := ly.(*diffLayer)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
beforeDel := h.length()
|
|
||||||
for _, subset := range dl.nodes {
|
|
||||||
for _, node := range subset {
|
|
||||||
h.del(node.Hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diffHashCacheLengthGauge.Update(int64(h.length()))
|
|
||||||
log.Debug("Remove difflayer from hash map", "root", ly.rootHash(), "block_number", dl.block, "map_len", h.length(), "del_delta", beforeDel-h.length())
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// diffLayer represents a collection of modifications made to the in-memory tries
|
// diffLayer represents a collection of modifications made to the in-memory tries
|
||||||
// along with associated state changes after running a block on top.
|
// along with associated state changes after running a block on top.
|
||||||
//
|
//
|
||||||
@@ -139,10 +39,7 @@ type diffLayer struct {
|
|||||||
nodes map[common.Hash]map[string]*trienode.Node // Cached trie nodes indexed by owner and path
|
nodes map[common.Hash]map[string]*trienode.Node // Cached trie nodes indexed by owner and path
|
||||||
states *triestate.Set // Associated state change set for building history
|
states *triestate.Set // Associated state change set for building history
|
||||||
memory uint64 // Approximate guess as to how much memory we use
|
memory uint64 // Approximate guess as to how much memory we use
|
||||||
cache *HashNodeCache // trienode cache by hash key. cache is immutable, but cache's item can be add/del.
|
|
||||||
|
|
||||||
// mutables
|
|
||||||
origin *diskLayer // The current difflayer corresponds to the underlying disklayer and is updated during cap.
|
|
||||||
parent layer // Parent layer modified by this one, never nil, **can be changed**
|
parent layer // Parent layer modified by this one, never nil, **can be changed**
|
||||||
lock sync.RWMutex // Lock used to protect parent
|
lock sync.RWMutex // Lock used to protect parent
|
||||||
}
|
}
|
||||||
@@ -161,20 +58,6 @@ func newDiffLayer(parent layer, root common.Hash, id uint64, block uint64, nodes
|
|||||||
states: states,
|
states: states,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch l := parent.(type) {
|
|
||||||
case *diskLayer:
|
|
||||||
dl.origin = l
|
|
||||||
dl.cache = &HashNodeCache{
|
|
||||||
cache: make(map[common.Hash]*RefTrieNode),
|
|
||||||
}
|
|
||||||
case *diffLayer:
|
|
||||||
dl.origin = l.originDiskLayer()
|
|
||||||
dl.cache = l.cache
|
|
||||||
default:
|
|
||||||
panic("unknown parent type")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, subset := range nodes {
|
for _, subset := range nodes {
|
||||||
for path, n := range subset {
|
for path, n := range subset {
|
||||||
dl.memory += uint64(n.Size() + len(path))
|
dl.memory += uint64(n.Size() + len(path))
|
||||||
@@ -192,12 +75,6 @@ func newDiffLayer(parent layer, root common.Hash, id uint64, block uint64, nodes
|
|||||||
return dl
|
return dl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dl *diffLayer) originDiskLayer() *diskLayer {
|
|
||||||
dl.lock.RLock()
|
|
||||||
defer dl.lock.RUnlock()
|
|
||||||
return dl.origin
|
|
||||||
}
|
|
||||||
|
|
||||||
// rootHash implements the layer interface, returning the root hash of
|
// rootHash implements the layer interface, returning the root hash of
|
||||||
// corresponding state.
|
// corresponding state.
|
||||||
func (dl *diffLayer) rootHash() common.Hash {
|
func (dl *diffLayer) rootHash() common.Hash {
|
||||||
@@ -256,32 +133,6 @@ func (dl *diffLayer) node(owner common.Hash, path []byte, hash common.Hash, dept
|
|||||||
// Node implements the layer interface, retrieving the trie node blob with the
|
// Node implements the layer interface, retrieving the trie node blob with the
|
||||||
// provided node information. No error will be returned if the node is not found.
|
// provided node information. No error will be returned if the node is not found.
|
||||||
func (dl *diffLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
|
func (dl *diffLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
|
||||||
if n := dl.cache.Get(hash); n != nil {
|
|
||||||
// The query from the hash map is fastpath,
|
|
||||||
// avoiding recursive query of 128 difflayers.
|
|
||||||
diffHashCacheHitMeter.Mark(1)
|
|
||||||
diffHashCacheReadMeter.Mark(int64(len(n.Blob)))
|
|
||||||
return n.Blob, nil
|
|
||||||
}
|
|
||||||
diffHashCacheMissMeter.Mark(1)
|
|
||||||
|
|
||||||
persistLayer := dl.originDiskLayer()
|
|
||||||
if persistLayer != nil {
|
|
||||||
blob, err := persistLayer.Node(owner, path, hash)
|
|
||||||
if err != nil {
|
|
||||||
// This is a bad case with a very low probability.
|
|
||||||
// r/w the difflayer cache and r/w the disklayer are not in the same lock,
|
|
||||||
// so in extreme cases, both reading the difflayer cache and reading the disklayer may fail, eg, disklayer is stale.
|
|
||||||
// In this case, fallback to the original 128-layer recursive difflayer query path.
|
|
||||||
diffHashCacheSlowPathMeter.Mark(1)
|
|
||||||
log.Debug("Retry difflayer due to query origin failed", "owner", owner, "path", path, "hash", hash.String(), "error", err)
|
|
||||||
return dl.node(owner, path, hash, 0)
|
|
||||||
} else { // This is the fastpath.
|
|
||||||
return blob, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diffHashCacheSlowPathMeter.Mark(1)
|
|
||||||
log.Debug("Retry difflayer due to origin is nil", "owner", owner, "path", path, "hash", hash.String())
|
|
||||||
return dl.node(owner, path, hash, 0)
|
return dl.node(owner, path, hash, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -286,9 +286,6 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
|
|||||||
}
|
}
|
||||||
log.Debug("Pruned state history", "items", pruned, "tailid", oldest)
|
log.Debug("Pruned state history", "items", pruned, "tailid", oldest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The bottom has been eaten by disklayer, releasing the hash cache of bottom difflayer.
|
|
||||||
bottom.cache.Remove(bottom)
|
|
||||||
return ndl, nil
|
return ndl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -152,13 +152,12 @@ func (kr *JournalKVReader) Close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newJournalWriter(file string, db ethdb.Database, journalType JournalType) JournalWriter {
|
func newJournalWriter(file string, db ethdb.Database, journalType JournalType) JournalWriter {
|
||||||
|
log.Info("New journal writer", "path", file, "journalType", journalType)
|
||||||
if journalType == JournalKVType {
|
if journalType == JournalKVType {
|
||||||
log.Info("New journal writer for journal kv")
|
|
||||||
return &JournalKVWriter{
|
return &JournalKVWriter{
|
||||||
diskdb: db,
|
diskdb: db,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Info("New journal writer for journal file", "path", file)
|
|
||||||
fd, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
fd, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -170,8 +169,8 @@ func newJournalWriter(file string, db ethdb.Database, journalType JournalType) J
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newJournalReader(file string, db ethdb.Database, journalType JournalType) (JournalReader, error) {
|
func newJournalReader(file string, db ethdb.Database, journalType JournalType) (JournalReader, error) {
|
||||||
|
log.Info("New journal reader", "path", file, "journalType", journalType)
|
||||||
if journalType == JournalKVType {
|
if journalType == JournalKVType {
|
||||||
log.Info("New journal reader for journal kv")
|
|
||||||
journal := rawdb.ReadTrieJournal(db)
|
journal := rawdb.ReadTrieJournal(db)
|
||||||
if len(journal) == 0 {
|
if len(journal) == 0 {
|
||||||
return nil, errMissJournal
|
return nil, errMissJournal
|
||||||
@@ -180,7 +179,6 @@ func newJournalReader(file string, db ethdb.Database, journalType JournalType) (
|
|||||||
journalBuf: bytes.NewBuffer(journal),
|
journalBuf: bytes.NewBuffer(journal),
|
||||||
}, nil
|
}, nil
|
||||||
} else {
|
} else {
|
||||||
log.Info("New journal reader for journal file", "path", file)
|
|
||||||
fd, err := os.Open(file)
|
fd, err := os.Open(file)
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
return nil, errMissJournal
|
return nil, errMissJournal
|
||||||
|
|||||||
@@ -51,20 +51,9 @@ func (tree *layerTree) reset(head layer) {
|
|||||||
tree.lock.Lock()
|
tree.lock.Lock()
|
||||||
defer tree.lock.Unlock()
|
defer tree.lock.Unlock()
|
||||||
|
|
||||||
for _, ly := range tree.layers {
|
|
||||||
if dl, ok := ly.(*diffLayer); ok {
|
|
||||||
// Clean up the hash cache of difflayers due to reset.
|
|
||||||
dl.cache.Remove(dl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var layers = make(map[common.Hash]layer)
|
var layers = make(map[common.Hash]layer)
|
||||||
for head != nil {
|
for head != nil {
|
||||||
layers[head.rootHash()] = head
|
layers[head.rootHash()] = head
|
||||||
if dl, ok := head.(*diffLayer); ok {
|
|
||||||
// Add the hash cache of difflayers due to reset.
|
|
||||||
dl.cache.Add(dl)
|
|
||||||
}
|
|
||||||
head = head.parentLayer()
|
head = head.parentLayer()
|
||||||
}
|
}
|
||||||
tree.layers = layers
|
tree.layers = layers
|
||||||
@@ -109,19 +98,12 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6
|
|||||||
if root == parentRoot {
|
if root == parentRoot {
|
||||||
return errors.New("layer cycle")
|
return errors.New("layer cycle")
|
||||||
}
|
}
|
||||||
if tree.get(root) != nil {
|
|
||||||
log.Info("Skip add repeated difflayer", "root", root.String(), "block_id", block)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
parent := tree.get(parentRoot)
|
parent := tree.get(parentRoot)
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
return fmt.Errorf("triedb parent [%#x] layer missing", parentRoot)
|
return fmt.Errorf("triedb parent [%#x] layer missing", parentRoot)
|
||||||
}
|
}
|
||||||
l := parent.update(root, parent.stateID()+1, block, nodes.Flatten(), states)
|
l := parent.update(root, parent.stateID()+1, block, nodes.Flatten(), states)
|
||||||
|
|
||||||
// Before adding layertree, update the hash cache.
|
|
||||||
l.cache.Add(l)
|
|
||||||
|
|
||||||
tree.lock.Lock()
|
tree.lock.Lock()
|
||||||
tree.layers[l.rootHash()] = l
|
tree.layers[l.rootHash()] = l
|
||||||
tree.lock.Unlock()
|
tree.lock.Unlock()
|
||||||
@@ -150,15 +132,8 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, ly := range tree.layers {
|
|
||||||
if dl, ok := ly.(*diffLayer); ok {
|
|
||||||
dl.cache.Remove(dl)
|
|
||||||
log.Debug("Cleanup difflayer hash cache due to cap all", "diff_root", dl.root.String(), "diff_block_number", dl.block)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Replace the entire layer tree with the flat base
|
// Replace the entire layer tree with the flat base
|
||||||
tree.layers = map[common.Hash]layer{base.rootHash(): base}
|
tree.layers = map[common.Hash]layer{base.rootHash(): base}
|
||||||
log.Debug("Cap all difflayers to disklayer", "disk_root", base.rootHash().String())
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Dive until we run out of layers or reach the persistent database
|
// Dive until we run out of layers or reach the persistent database
|
||||||
@@ -171,7 +146,6 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var persisted *diskLayer
|
|
||||||
// We're out of layers, flatten anything below, stopping if it's the disk or if
|
// We're out of layers, flatten anything below, stopping if it's the disk or if
|
||||||
// the memory limit is not yet exceeded.
|
// the memory limit is not yet exceeded.
|
||||||
switch parent := diff.parentLayer().(type) {
|
switch parent := diff.parentLayer().(type) {
|
||||||
@@ -192,7 +166,6 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
|
|||||||
diff.parent = base
|
diff.parent = base
|
||||||
|
|
||||||
diff.lock.Unlock()
|
diff.lock.Unlock()
|
||||||
persisted = base.(*diskLayer)
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unknown data layer in triedb: %T", parent))
|
panic(fmt.Sprintf("unknown data layer in triedb: %T", parent))
|
||||||
@@ -207,13 +180,6 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
|
|||||||
}
|
}
|
||||||
var remove func(root common.Hash)
|
var remove func(root common.Hash)
|
||||||
remove = func(root common.Hash) {
|
remove = func(root common.Hash) {
|
||||||
if df, exist := tree.layers[root]; exist {
|
|
||||||
if dl, ok := df.(*diffLayer); ok {
|
|
||||||
// Clean up the hash cache of the child difflayer corresponding to the stale parent, include the re-org case.
|
|
||||||
dl.cache.Remove(dl)
|
|
||||||
log.Debug("Cleanup difflayer hash cache due to reorg", "diff_root", dl.root.String(), "diff_block_number", dl.block)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete(tree.layers, root)
|
delete(tree.layers, root)
|
||||||
for _, child := range children[root] {
|
for _, child := range children[root] {
|
||||||
remove(child)
|
remove(child)
|
||||||
@@ -223,25 +189,8 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
|
|||||||
for root, layer := range tree.layers {
|
for root, layer := range tree.layers {
|
||||||
if dl, ok := layer.(*diskLayer); ok && dl.isStale() {
|
if dl, ok := layer.(*diskLayer); ok && dl.isStale() {
|
||||||
remove(root)
|
remove(root)
|
||||||
log.Debug("Remove stale the disklayer", "disk_root", dl.root.String())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if persisted != nil {
|
|
||||||
var updateOriginFunc func(root common.Hash)
|
|
||||||
updateOriginFunc = func(root common.Hash) {
|
|
||||||
if diff, ok := tree.layers[root].(*diffLayer); ok {
|
|
||||||
diff.lock.Lock()
|
|
||||||
diff.origin = persisted
|
|
||||||
diff.lock.Unlock()
|
|
||||||
}
|
|
||||||
for _, child := range children[root] {
|
|
||||||
updateOriginFunc(child)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateOriginFunc(persisted.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,10 +47,4 @@ var (
|
|||||||
historyBuildTimeMeter = metrics.NewRegisteredTimer("pathdb/history/time", nil)
|
historyBuildTimeMeter = metrics.NewRegisteredTimer("pathdb/history/time", nil)
|
||||||
historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil)
|
historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil)
|
||||||
historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil)
|
historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil)
|
||||||
|
|
||||||
diffHashCacheHitMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/hit", nil)
|
|
||||||
diffHashCacheReadMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/read", nil)
|
|
||||||
diffHashCacheMissMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/miss", nil)
|
|
||||||
diffHashCacheSlowPathMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/slowpath", nil)
|
|
||||||
diffHashCacheLengthGauge = metrics.NewRegisteredGauge("pathdb/difflayer/hashcache/size", nil)
|
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user