Compare commits

..

3 Commits

Author SHA1 Message Date
emailtovamos
e149161d54 jsutil: correct the division 2024-05-21 15:42:58 +01:00
emailtovamos
cb0b34b7c2 jsutils: update logs 2024-05-16 14:34:11 +01:00
emailtovamos
5b7a71e38e jsutils: faucet balance 2024-05-16 12:25:25 +01:00
67 changed files with 261 additions and 6555 deletions

View File

@@ -1,53 +1,4 @@
# Changelog # Changelog
## v1.4.10
### FEATURE
NA
### IMPROVEMENT
* [\#2512](https://github.com/bnb-chain/bsc/pull/2512) feat: add mev helper params and func
* [\#2508](https://github.com/bnb-chain/bsc/pull/2508) perf: speedup pbss trienode read
* [\#2509](https://github.com/bnb-chain/bsc/pull/2509) perf: optimize chain commit performance for multi-database
* [\#2451](https://github.com/bnb-chain/bsc/pull/2451) core/forkchoice: improve stability when inturn block not generate
### BUGFIX
* [\#2518](https://github.com/bnb-chain/bsc/pull/2518) fix: remove zero gasprice check for BSC
* [\#2519](https://github.com/bnb-chain/bsc/pull/2519) UT: random failure of TestSnapSyncWithBlobs
* [\#2515](https://github.com/bnb-chain/bsc/pull/2515) fix getBlobSidecars by ethclient
* [\#2525](https://github.com/bnb-chain/bsc/pull/2525) fix: ensure empty withdrawals after cancun before broadcast
## v1.4.9
### FEATURE
* [\#2463](https://github.com/bnb-chain/bsc/pull/2463) utils: add check_blobtx.js
* [\#2470](https://github.com/bnb-chain/bsc/pull/2470) jsutils: faucet successful requests within blocks
* [\#2467](https://github.com/bnb-chain/bsc/pull/2467) internal/ethapi: add optional parameter for blobSidecars
### IMPROVEMENT
* [\#2462](https://github.com/bnb-chain/bsc/pull/2462) cmd/utils: add a flag to change breathe block interval for testing
* [\#2497](https://github.com/bnb-chain/bsc/pull/2497) params/config: add Bohr hardfork
* [\#2479](https://github.com/bnb-chain/bsc/pull/2479) dev: ensure consistency in BPS bundle result
### BUGFIX
* [\#2461](https://github.com/bnb-chain/bsc/pull/2461) eth/handler: check lists in body before broadcast blocks
* [\#2455](https://github.com/bnb-chain/bsc/pull/2455) cmd: fix memory leak when big dataset
* [\#2466](https://github.com/bnb-chain/bsc/pull/2466) sync: fix some sync issues caused by prune-block.
* [\#2475](https://github.com/bnb-chain/bsc/pull/2475) fix: move mev op to MinerAPI & add command to console
* [\#2473](https://github.com/bnb-chain/bsc/pull/2473) fix: limit the gas price of the mev bid
* [\#2484](https://github.com/bnb-chain/bsc/pull/2484) fix: fix inspect database error
* [\#2481](https://github.com/bnb-chain/bsc/pull/2481) fix: keep 9W blocks in ancient db when prune block
* [\#2495](https://github.com/bnb-chain/bsc/pull/2495) fix: add an empty freeze db
* [\#2507](https://github.com/bnb-chain/bsc/pull/2507) fix: waiting for the last simulation before pick best bid
## v1.4.8
### FEATURE
* [\#2483](https://github.com/bnb-chain/bsc/pull/2483) core/vm: add secp256r1 into PrecompiledContractsHaber
* [\#2400](https://github.com/bnb-chain/bsc/pull/2400) RIP-7212: Precompile for secp256r1 Curve Support
### IMPROVEMENT
NA
### BUGFIX
NA
## v1.4.7 ## v1.4.7
### FEATURE ### FEATURE
* [\#2439](https://github.com/bnb-chain/bsc/pull/2439) config: setup Mainnet Tycho(Cancun) hardfork date * [\#2439](https://github.com/bnb-chain/bsc/pull/2439) config: setup Mainnet Tycho(Cancun) hardfork date

View File

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

View File

@@ -63,8 +63,6 @@ var (
Flags: flags.Merge([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CachePreimagesFlag, utils.CachePreimagesFlag,
utils.OverrideCancun, utils.OverrideCancun,
utils.OverrideHaber,
utils.OverrideBohr,
utils.OverrideVerkle, utils.OverrideVerkle,
}, utils.DatabaseFlags), }, utils.DatabaseFlags),
Description: ` Description: `
@@ -258,14 +256,6 @@ func initGenesis(ctx *cli.Context) error {
v := ctx.Uint64(utils.OverrideCancun.Name) v := ctx.Uint64(utils.OverrideCancun.Name)
overrides.OverrideCancun = &v overrides.OverrideCancun = &v
} }
if ctx.IsSet(utils.OverrideHaber.Name) {
v := ctx.Uint64(utils.OverrideHaber.Name)
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

View File

@@ -189,14 +189,6 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
v := ctx.Uint64(utils.OverrideCancun.Name) v := ctx.Uint64(utils.OverrideCancun.Name)
cfg.Eth.OverrideCancun = &v cfg.Eth.OverrideCancun = &v
} }
if ctx.IsSet(utils.OverrideHaber.Name) {
v := ctx.Uint64(utils.OverrideHaber.Name)
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

View File

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

View File

@@ -73,8 +73,6 @@ var (
utils.SmartCardDaemonPathFlag, utils.SmartCardDaemonPathFlag,
utils.RialtoHash, utils.RialtoHash,
utils.OverrideCancun, utils.OverrideCancun,
utils.OverrideHaber,
utils.OverrideBohr,
utils.OverrideVerkle, utils.OverrideVerkle,
utils.OverrideFullImmutabilityThreshold, utils.OverrideFullImmutabilityThreshold,
utils.OverrideMinBlocksForBlobRequests, utils.OverrideMinBlocksForBlobRequests,

View File

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

View File

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

View File

@@ -310,16 +310,6 @@ var (
Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting", Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideHaber = &cli.Uint64Flag{
Name: "override.haber",
Usage: "Manually specify the Haber fork timestamp, overriding the bundled setting",
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 +1077,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{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -217,8 +217,6 @@ func (e *GenesisMismatchError) Error() string {
// Typically, these modifications involve hardforks that are not enabled on the BSC mainnet, intended for testing purposes. // Typically, these modifications involve hardforks that are not enabled on the BSC mainnet, intended for testing purposes.
type ChainOverrides struct { type ChainOverrides struct {
OverrideCancun *uint64 OverrideCancun *uint64
OverrideHaber *uint64
OverrideBohr *uint64
OverrideVerkle *uint64 OverrideVerkle *uint64
} }
@@ -248,12 +246,6 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
if overrides != nil && overrides.OverrideCancun != nil { if overrides != nil && overrides.OverrideCancun != nil {
config.CancunTime = overrides.OverrideCancun config.CancunTime = overrides.OverrideCancun
} }
if overrides != nil && overrides.OverrideHaber != nil {
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 +490,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,8 +6,6 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
mapset "github.com/deckarep/golang-set/v2"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@@ -42,12 +40,6 @@ func (b *BidArgs) ToBid(builder common.Address, signer Signer) (*Bid, error) {
return nil, err return nil, err
} }
if len(b.RawBid.UnRevertible) > len(txs) {
return nil, fmt.Errorf("expect NonRevertible no more than %d", len(txs))
}
unRevertibleHashes := mapset.NewThreadUnsafeSetWithSize[common.Hash](len(b.RawBid.UnRevertible))
unRevertibleHashes.Append(b.RawBid.UnRevertible...)
if len(b.PayBidTx) != 0 { if len(b.PayBidTx) != 0 {
var payBidTx = new(Transaction) var payBidTx = new(Transaction)
err = payBidTx.UnmarshalBinary(b.PayBidTx) err = payBidTx.UnmarshalBinary(b.PayBidTx)
@@ -59,15 +51,14 @@ func (b *BidArgs) ToBid(builder common.Address, signer Signer) (*Bid, error) {
} }
bid := &Bid{ bid := &Bid{
Builder: builder, Builder: builder,
BlockNumber: b.RawBid.BlockNumber, BlockNumber: b.RawBid.BlockNumber,
ParentHash: b.RawBid.ParentHash, ParentHash: b.RawBid.ParentHash,
Txs: txs, Txs: txs,
UnRevertible: unRevertibleHashes, GasUsed: b.RawBid.GasUsed + b.PayBidTxGasUsed,
GasUsed: b.RawBid.GasUsed + b.PayBidTxGasUsed, GasFee: b.RawBid.GasFee,
GasFee: b.RawBid.GasFee, BuilderFee: b.RawBid.BuilderFee,
BuilderFee: b.RawBid.BuilderFee, rawBid: *b.RawBid,
rawBid: *b.RawBid,
} }
if bid.BuilderFee == nil { if bid.BuilderFee == nil {
@@ -79,13 +70,12 @@ func (b *BidArgs) ToBid(builder common.Address, signer Signer) (*Bid, error) {
// RawBid represents a raw bid from builder directly. // RawBid represents a raw bid from builder directly.
type RawBid struct { type RawBid struct {
BlockNumber uint64 `json:"blockNumber"` BlockNumber uint64 `json:"blockNumber"`
ParentHash common.Hash `json:"parentHash"` ParentHash common.Hash `json:"parentHash"`
Txs []hexutil.Bytes `json:"txs"` Txs []hexutil.Bytes `json:"txs"`
UnRevertible []common.Hash `json:"unRevertible"` GasUsed uint64 `json:"gasUsed"`
GasUsed uint64 `json:"gasUsed"` GasFee *big.Int `json:"gasFee"`
GasFee *big.Int `json:"gasFee"` BuilderFee *big.Int `json:"builderFee"`
BuilderFee *big.Int `json:"builderFee"`
hash atomic.Value hash atomic.Value
} }
@@ -164,14 +154,13 @@ func (b *RawBid) Hash() common.Hash {
// Bid represents a bid. // Bid represents a bid.
type Bid struct { type Bid struct {
Builder common.Address Builder common.Address
BlockNumber uint64 BlockNumber uint64
ParentHash common.Hash ParentHash common.Hash
Txs Transactions Txs Transactions
UnRevertible mapset.Set[common.Hash] GasUsed uint64
GasUsed uint64 GasFee *big.Int
GasFee *big.Int BuilderFee *big.Int
BuilderFee *big.Int
rawBid RawBid rawBid RawBid
} }
@@ -193,7 +182,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
} }

View File

@@ -36,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/crypto/bn256" "github.com/ethereum/go-ethereum/crypto/bn256"
"github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/crypto/secp256r1"
"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" "github.com/ethereum/go-ethereum/rlp"
@@ -248,36 +247,6 @@ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{}, common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
} }
// PrecompiledContractsHaber contains the default set of pre-compiled Ethereum
// contracts used in the Haber release.
var PrecompiledContractsHaber = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hash{},
common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{9}): &blake2F{},
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidateHertz{},
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}
// PrecompiledContractsP256Verify contains the precompiled Ethereum
// contract specified in EIP-7212. This is exported for testing purposes.
var PrecompiledContractsP256Verify = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum // PrecompiledContractsBLS contains the set of pre-compiled Ethereum
// contracts specified in EIP-2537. These are exported for testing purposes. // contracts specified in EIP-2537. These are exported for testing purposes.
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
@@ -293,7 +262,6 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
} }
var ( var (
PrecompiledAddressesHaber []common.Address
PrecompiledAddressesCancun []common.Address PrecompiledAddressesCancun []common.Address
PrecompiledAddressesFeynman []common.Address PrecompiledAddressesFeynman []common.Address
PrecompiledAddressesHertz []common.Address PrecompiledAddressesHertz []common.Address
@@ -345,16 +313,11 @@ func init() {
for k := range PrecompiledContractsCancun { for k := range PrecompiledContractsCancun {
PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k) PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k)
} }
for k := range PrecompiledContractsHaber {
PrecompiledAddressesHaber = append(PrecompiledAddressesHaber, k)
}
} }
// ActivePrecompiles returns the precompiles enabled with the current configuration. // ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules params.Rules) []common.Address { func ActivePrecompiles(rules params.Rules) []common.Address {
switch { switch {
case rules.IsHaber:
return PrecompiledAddressesHaber
case rules.IsCancun: case rules.IsCancun:
return PrecompiledAddressesCancun return PrecompiledAddressesCancun
case rules.IsFeynman: case rules.IsFeynman:
@@ -1426,40 +1389,6 @@ func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash {
return h return h
} }
// P256VERIFY (secp256r1 signature verification)
// implemented as a native contract
type p256Verify struct{}
// RequiredGas returns the gas required to execute the precompiled contract
func (c *p256Verify) RequiredGas(input []byte) uint64 {
return params.P256VerifyGas
}
// Run executes the precompiled contract with given 160 bytes of param, returning the output and the used gas
func (c *p256Verify) Run(input []byte) ([]byte, error) {
// Required input length is 160 bytes
const p256VerifyInputLength = 160
// Check the input length
if len(input) != p256VerifyInputLength {
// Input length is invalid
return nil, nil
}
// Extract the hash, r, s, x, y from the input
hash := input[0:32]
r, s := new(big.Int).SetBytes(input[32:64]), new(big.Int).SetBytes(input[64:96])
x, y := new(big.Int).SetBytes(input[96:128]), new(big.Int).SetBytes(input[128:160])
// Verify the secp256r1 signature
if secp256r1.Verify(hash, r, s, x, y) {
// Signature is valid
return common.LeftPadBytes(common.Big1.Bytes(), 32), nil
} else {
// Signature is invalid
return nil, nil
}
}
// verifyDoubleSignEvidence implements bsc header verification precompile. // verifyDoubleSignEvidence implements bsc header verification precompile.
type verifyDoubleSignEvidence struct{} type verifyDoubleSignEvidence struct{}

View File

@@ -46,19 +46,17 @@ type precompiledFailureTest struct {
// allPrecompiles does not map to the actual set of precompiles, as it also contains // allPrecompiles does not map to the actual set of precompiles, as it also contains
// repriced versions of precompiles at certain slots // repriced versions of precompiles at certain slots
var allPrecompiles = map[common.Address]PrecompiledContract{ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{},
common.BytesToAddress([]byte{4}): &dataCopy{}, common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
common.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true}, common.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{9}): &blake2F{}, common.BytesToAddress([]byte{9}): &blake2F{},
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
common.BytesToAddress([]byte{0x0f, 0x0a}): &bls12381G1Add{}, common.BytesToAddress([]byte{0x0f, 0x0a}): &bls12381G1Add{},
common.BytesToAddress([]byte{0x0f, 0x0b}): &bls12381G1Mul{}, common.BytesToAddress([]byte{0x0f, 0x0b}): &bls12381G1Mul{},
common.BytesToAddress([]byte{0x0f, 0x0c}): &bls12381G1MultiExp{}, common.BytesToAddress([]byte{0x0f, 0x0c}): &bls12381G1MultiExp{},
@@ -409,18 +407,6 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
benchmarkPrecompiled("0f", testcase, b) benchmarkPrecompiled("0f", testcase, b)
} }
// Benchmarks the sample inputs from the P256VERIFY precompile.
func BenchmarkPrecompiledP256Verify(bench *testing.B) {
t := precompiledTest{
Input: "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e",
Expected: "0000000000000000000000000000000000000000000000000000000000000001",
Name: "p256Verify",
}
benchmarkPrecompiled("100", t, bench)
}
func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "100", t) }
func TestDoubleSignSlash(t *testing.T) { func TestDoubleSignSlash(t *testing.T) {
tc := precompiledTest{ tc := precompiledTest{
Input: "f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000", Input: "f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",

View File

@@ -48,8 +48,6 @@ type (
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
var precompiles map[common.Address]PrecompiledContract var precompiles map[common.Address]PrecompiledContract
switch { switch {
case evm.chainRules.IsHaber:
precompiles = PrecompiledContractsHaber
case evm.chainRules.IsCancun: case evm.chainRules.IsCancun:
precompiles = PrecompiledContractsCancun precompiles = PrecompiledContractsCancun
case evm.chainRules.IsFeynman: case evm.chainRules.IsFeynman:

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +0,0 @@
package secp256r1
import (
"crypto/ecdsa"
"crypto/elliptic"
"math/big"
)
// Generates appropriate public key format from given coordinates
func newPublicKey(x, y *big.Int) *ecdsa.PublicKey {
// Check if the given coordinates are valid
if x == nil || y == nil || !elliptic.P256().IsOnCurve(x, y) {
return nil
}
return &ecdsa.PublicKey{
Curve: elliptic.P256(),
X: x,
Y: y,
}
}

View File

@@ -1,22 +0,0 @@
package secp256r1
import (
"crypto/ecdsa"
"math/big"
)
// Verify verifies the given signature (r, s) for the given hash and public key (x, y).
// It returns true if the signature is valid, false otherwise.
func Verify(hash []byte, r, s, x, y *big.Int) bool {
// Create the public key format
publicKey := newPublicKey(x, y)
// Check if they are invalid public key coordinates
if publicKey == nil {
return false
}
// Verify the signature with the public key,
// then return true if it's valid, false otherwise
return ecdsa.Verify(publicKey, hash, r, s)
}

View File

@@ -24,6 +24,7 @@ import (
"os" "os"
"strings" "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@@ -141,3 +142,31 @@ func (api *AdminAPI) ImportChain(file string) (bool, error) {
} }
return true, nil return true, nil
} }
// MevRunning returns true if the validator accept bids from builder
func (api *AdminAPI) MevRunning() bool {
return api.eth.APIBackend.MevRunning()
}
// StartMev starts mev. It notifies the miner to start to receive bids.
func (api *AdminAPI) StartMev() {
api.eth.APIBackend.StartMev()
}
// StopMev stops mev. It notifies the miner to stop receiving bids from this moment,
// but the bids before this moment would still been taken into consideration by mev.
func (api *AdminAPI) StopMev() {
api.eth.APIBackend.StopMev()
}
// AddBuilder adds a builder to the bid simulator.
// url is the endpoint of the builder, for example, "https://mev-builder.amazonaws.com",
// if validator is equipped with sentry, ignore the url.
func (api *AdminAPI) AddBuilder(builder common.Address, url string) error {
return api.eth.APIBackend.AddBuilder(builder, url)
}
// RemoveBuilder removes a builder from the bid simulator.
func (api *AdminAPI) RemoveBuilder(builder common.Address) error {
return api.eth.APIBackend.RemoveBuilder(builder)
}

View File

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

View File

@@ -89,31 +89,3 @@ func (api *MinerAPI) SetEtherbase(etherbase common.Address) bool {
func (api *MinerAPI) SetRecommitInterval(interval int) { func (api *MinerAPI) SetRecommitInterval(interval int) {
api.e.Miner().SetRecommitInterval(time.Duration(interval) * time.Millisecond) api.e.Miner().SetRecommitInterval(time.Duration(interval) * time.Millisecond)
} }
// MevRunning returns true if the validator accept bids from builder
func (api *MinerAPI) MevRunning() bool {
return api.e.APIBackend.MevRunning()
}
// StartMev starts mev. It notifies the miner to start to receive bids.
func (api *MinerAPI) StartMev() {
api.e.APIBackend.StartMev()
}
// StopMev stops mev. It notifies the miner to stop receiving bids from this moment,
// but the bids before this moment would still been taken into consideration by mev.
func (api *MinerAPI) StopMev() {
api.e.APIBackend.StopMev()
}
// AddBuilder adds a builder to the bid simulator.
// url is the endpoint of the builder, for example, "https://mev-builder.amazonaws.com",
// if validator is equipped with sentry, ignore the url.
func (api *MinerAPI) AddBuilder(builder common.Address, url string) error {
return api.e.APIBackend.AddBuilder(builder, url)
}
// RemoveBuilder removes a builder from the bid simulator.
func (api *MinerAPI) RemoveBuilder(builder common.Address) error {
return api.e.APIBackend.RemoveBuilder(builder)
}

View File

@@ -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 {
@@ -189,14 +183,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
chainConfig.CancunTime = config.OverrideCancun chainConfig.CancunTime = config.OverrideCancun
overrides.OverrideCancun = config.OverrideCancun overrides.OverrideCancun = config.OverrideCancun
} }
if config.OverrideHaber != nil {
chainConfig.HaberTime = 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

View File

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

View File

@@ -191,12 +191,6 @@ type Config struct {
// OverrideCancun (TODO: remove after the fork) // OverrideCancun (TODO: remove after the fork)
OverrideCancun *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"`
// OverrideHaber (TODO: remove after the fork)
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"`

View File

@@ -71,8 +71,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
RPCEVMTimeout time.Duration RPCEVMTimeout time.Duration
RPCTxFeeCap float64 RPCTxFeeCap float64
OverrideCancun *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"`
OverrideHaber *uint64 `toml:",omitempty"`
OverrideBohr *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
BlobExtraReserve uint64 BlobExtraReserve uint64
} }
@@ -131,8 +129,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.RPCEVMTimeout = c.RPCEVMTimeout enc.RPCEVMTimeout = c.RPCEVMTimeout
enc.RPCTxFeeCap = c.RPCTxFeeCap enc.RPCTxFeeCap = c.RPCTxFeeCap
enc.OverrideCancun = c.OverrideCancun enc.OverrideCancun = c.OverrideCancun
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
@@ -195,8 +191,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
RPCEVMTimeout *time.Duration RPCEVMTimeout *time.Duration
RPCTxFeeCap *float64 RPCTxFeeCap *float64
OverrideCancun *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"`
OverrideHaber *uint64 `toml:",omitempty"`
OverrideBohr *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
BlobExtraReserve *uint64 BlobExtraReserve *uint64
} }
@@ -366,12 +360,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.OverrideCancun != nil { if dec.OverrideCancun != nil {
c.OverrideCancun = dec.OverrideCancun c.OverrideCancun = dec.OverrideCancun
} }
if dec.OverrideHaber != nil {
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
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -131,9 +131,9 @@ 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, fullBlob bool) ([]*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(), fullBlob)
if err == nil && r == nil { if err == nil && r == nil {
return nil, ethereum.NotFound return nil, ethereum.NotFound
} }
@@ -141,9 +141,9 @@ 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, fullBlob bool) (*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, fullBlob)
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

View File

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

View File

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

View File

@@ -1010,11 +1010,7 @@ func (s *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.
return result, nil return result, nil
} }
func (s *BlockChainAPI) GetBlobSidecars(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, fullBlob *bool) ([]map[string]interface{}, error) { func (s *BlockChainAPI) GetBlobSidecars(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, fullBlob bool) ([]map[string]interface{}, error) {
showBlob := true
if fullBlob != nil {
showBlob = *fullBlob
}
header, err := s.b.HeaderByNumberOrHash(ctx, blockNrOrHash) header, err := s.b.HeaderByNumberOrHash(ctx, blockNrOrHash)
if header == nil || err != nil { if header == nil || err != nil {
// When the block doesn't exist, the RPC method should return JSON null // When the block doesn't exist, the RPC method should return JSON null
@@ -1027,16 +1023,12 @@ func (s *BlockChainAPI) GetBlobSidecars(ctx context.Context, blockNrOrHash rpc.B
} }
result := make([]map[string]interface{}, len(blobSidecars)) result := make([]map[string]interface{}, len(blobSidecars))
for i, sidecar := range blobSidecars { for i, sidecar := range blobSidecars {
result[i] = marshalBlobSidecar(sidecar, showBlob) result[i] = marshalBlobSidecar(sidecar, fullBlob)
} }
return result, nil return result, nil
} }
func (s *BlockChainAPI) GetBlobSidecarByTxHash(ctx context.Context, hash common.Hash, fullBlob *bool) (map[string]interface{}, error) { func (s *BlockChainAPI) GetBlobSidecarByTxHash(ctx context.Context, hash common.Hash, fullBlob bool) (map[string]interface{}, error) {
showBlob := true
if fullBlob != nil {
showBlob = *fullBlob
}
txTarget, blockHash, _, Index := rawdb.ReadTransaction(s.b.ChainDb(), hash) txTarget, blockHash, _, Index := rawdb.ReadTransaction(s.b.ChainDb(), hash)
if txTarget == nil { if txTarget == nil {
return nil, nil return nil, nil
@@ -1053,7 +1045,7 @@ func (s *BlockChainAPI) GetBlobSidecarByTxHash(ctx context.Context, hash common.
} }
for _, sidecar := range blobSidecars { for _, sidecar := range blobSidecars {
if sidecar.TxIndex == Index { if sidecar.TxIndex == Index {
return marshalBlobSidecar(sidecar, showBlob), nil return marshalBlobSidecar(sidecar, fullBlob), nil
} }
} }

View File

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

View File

@@ -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{}
} }
@@ -2205,7 +2204,7 @@ func TestRPCGetBlobSidecars(t *testing.T) {
result interface{} result interface{}
err error err error
) )
result, err = api.GetBlobSidecars(context.Background(), tt.test, &tt.fullBlob) result, err = api.GetBlobSidecars(context.Background(), tt.test, tt.fullBlob)
if err != nil { if err != nil {
t.Errorf("test %d: want no error, have %v", i, err) t.Errorf("test %d: want no error, have %v", i, err)
continue continue
@@ -2255,7 +2254,7 @@ func TestGetBlobSidecarByTxHash(t *testing.T) {
fullBlob: true, fullBlob: true,
file: "block-with-blobSidecars", file: "block-with-blobSidecars",
}, },
// 5. block show part blobs // 4. block show part blobs
{ {
test: txHashs[6], test: txHashs[6],
fullBlob: false, fullBlob: false,
@@ -2268,7 +2267,7 @@ func TestGetBlobSidecarByTxHash(t *testing.T) {
result interface{} result interface{}
err error err error
) )
result, err = api.GetBlobSidecarByTxHash(context.Background(), tt.test, &tt.fullBlob) result, err = api.GetBlobSidecarByTxHash(context.Background(), tt.test, tt.fullBlob)
if err != nil { if err != nil {
t.Errorf("test %d: want no error, have %v", i, err) t.Errorf("test %d: want no error, have %v", i, err)
continue continue

View File

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

View File

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

View File

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

View File

@@ -659,30 +659,6 @@ web3._extend({
name: 'stop', name: 'stop',
call: 'miner_stop' call: 'miner_stop'
}), }),
new web3._extend.Method({
name: 'mevRunning',
call: 'miner_mevRunning'
}),
new web3._extend.Method({
name: 'startMev',
call: 'miner_startMev'
}),
new web3._extend.Method({
name: 'stopMev',
call: 'miner_stopMev'
}),
new web3._extend.Method({
name: 'addBuilder',
call: 'miner_addBuilder',
params: 2,
inputFormatter: [web3._extend.formatters.inputAddressFormatter, null]
}),
new web3._extend.Method({
name: 'removeBuilder',
call: 'miner_removeBuilder',
params: 1,
inputFormatter: [web3._extend.formatters.inputAddressFormatter]
}),
new web3._extend.Method({ new web3._extend.Method({
name: 'setEtherbase', name: 'setEtherbase',
call: 'miner_setEtherbase', call: 'miner_setEtherbase',

View File

@@ -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 (
@@ -73,7 +78,6 @@ type simBidReq struct {
type bidSimulator struct { type bidSimulator struct {
config *MevConfig config *MevConfig
delayLeftOver time.Duration delayLeftOver time.Duration
minGasPrice *big.Int
chain *core.BlockChain chain *core.BlockChain
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
engine consensus.Engine engine consensus.Engine
@@ -110,7 +114,6 @@ type bidSimulator struct {
func newBidSimulator( func newBidSimulator(
config *MevConfig, config *MevConfig,
delayLeftOver time.Duration, delayLeftOver time.Duration,
minGasPrice *big.Int,
chain *core.BlockChain, chain *core.BlockChain,
chainConfig *params.ChainConfig, chainConfig *params.ChainConfig,
engine consensus.Engine, engine consensus.Engine,
@@ -119,7 +122,6 @@ func newBidSimulator(
b := &bidSimulator{ b := &bidSimulator{
config: config, config: config,
delayLeftOver: delayLeftOver, delayLeftOver: delayLeftOver,
minGasPrice: minGasPrice,
chain: chain, chain: chain,
chainConfig: chainConfig, chainConfig: chainConfig,
engine: engine, engine: engine,
@@ -313,6 +315,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 +367,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 +407,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)
@@ -509,6 +527,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{
@@ -534,11 +553,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 {
@@ -562,14 +580,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)
@@ -582,7 +592,6 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
return return
} }
// commit transactions in bid
for _, tx := range bidRuntime.bid.Txs { for _, tx := range bidRuntime.bid.Txs {
select { select {
case <-interruptCh: case <-interruptCh:
@@ -600,7 +609,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
break break
} }
err = bidRuntime.commitTransaction(b.chain, b.chainConfig, tx, bidRuntime.bid.UnRevertible.Contains(tx.Hash())) err = bidRuntime.commitTransaction(b.chain, b.chainConfig, tx)
if err != nil { if err != nil {
log.Error("BidSimulator: failed to commit tx", "bidHash", bidRuntime.bid.Hash(), "tx", tx.Hash(), "err", err) log.Error("BidSimulator: failed to commit tx", "bidHash", bidRuntime.bid.Hash(), "tx", tx.Hash(), "err", err)
err = fmt.Errorf("invalid tx in bid, %v", err) err = fmt.Errorf("invalid tx in bid, %v", err)
@@ -608,41 +617,26 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
} }
} }
// check if bid reward is valid bidRuntime.packReward(b.config.ValidatorCommission)
{
bidRuntime.packReward(b.config.ValidatorCommission) // return if bid is invalid, reportIssue issue to mev-sentry/builder if simulation is fully done
if !bidRuntime.validReward() { if !bidRuntime.validReward() {
err = errors.New("reward does not achieve the expectation") err = errors.New("reward does not achieve the expectation")
return return
}
} }
// check if bid gas price is lower than min gas price // fill transactions from mempool
{
bidGasUsed := uint64(0)
bidGasFee := bidRuntime.env.state.GetBalance(consensus.SystemAddress)
for _, receipt := range bidRuntime.env.receipts {
bidGasUsed += receipt.GasUsed
}
bidGasPrice := new(big.Int).Div(bidGasFee.ToBig(), new(big.Int).SetUint64(bidGasUsed))
if bidGasPrice.Cmp(b.minGasPrice) < 0 {
err = errors.New("bid gas price is lower than min gas price")
return
}
}
// if enable greedy merge, fill bid env with transactions from mempool
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)
@@ -651,9 +645,8 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
} }
} }
// commit payBidTx at the end of the block
bidRuntime.env.gasPool.AddGas(params.PayBidTxGasLimit) bidRuntime.env.gasPool.AddGas(params.PayBidTxGasLimit)
err = bidRuntime.commitTransaction(b.chain, b.chainConfig, payBidTx, true) err = bidRuntime.commitTransaction(b.chain, b.chainConfig, payBidTx)
if err != nil { if err != nil {
log.Error("BidSimulator: failed to commit tx", "builder", bidRuntime.bid.Builder, log.Error("BidSimulator: failed to commit tx", "builder", bidRuntime.bid.Builder,
"bidHash", bidRuntime.bid.Hash(), "tx", payBidTx.Hash(), "err", err) "bidHash", bidRuntime.bid.Hash(), "tx", payBidTx.Hash(), "err", err)
@@ -718,7 +711,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
} }
@@ -735,10 +727,12 @@ func (r *BidRuntime) packReward(validatorCommission uint64) {
r.packedValidatorReward.Sub(r.packedValidatorReward, r.bid.BuilderFee) r.packedValidatorReward.Sub(r.packedValidatorReward, r.bid.BuilderFee)
} }
func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *params.ChainConfig, tx *types.Transaction, unRevertible bool) error { func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *params.ChainConfig, tx *types.Transaction) error {
var ( var (
env = r.env env = r.env
sc *types.BlobSidecar snap = env.state.Snapshot()
gp = env.gasPool.Gas()
sc *types.BlobSidecar
) )
// Start executing the transaction // Start executing the transaction
@@ -761,9 +755,9 @@ func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *para
receipt, err := core.ApplyTransaction(chainConfig, chain, &env.coinbase, env.gasPool, env.state, env.header, tx, receipt, err := core.ApplyTransaction(chainConfig, chain, &env.coinbase, env.gasPool, env.state, env.header, tx,
&env.header.GasUsed, *chain.GetVMConfig(), core.NewReceiptBloomGenerator()) &env.header.GasUsed, *chain.GetVMConfig(), core.NewReceiptBloomGenerator())
if err != nil { if err != nil {
env.state.RevertToSnapshot(snap)
env.gasPool.SetGas(gp)
return err return err
} else if unRevertible && receipt.Status == types.ReceiptStatusFailed {
return errors.New("no revertible transaction failed")
} }
if tx.Type() == types.BlobTxType { if tx.Type() == types.BlobTxType {

View File

@@ -102,7 +102,7 @@ func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *even
worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, false), worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, false),
} }
miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, config.GasPrice, eth.BlockChain(), chainConfig, engine, miner.worker) miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, eth.BlockChain(), chainConfig, engine, miner.worker)
miner.worker.setBestBidFetcher(miner.bidSimulator) miner.worker.setBestBidFetcher(miner.bidSimulator)
miner.wg.Add(1) miner.wg.Add(1)

View File

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

View File

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

View File

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

View File

@@ -152,8 +152,6 @@ var (
FeynmanTime: newUint64(1713419340), // 2024-04-18 05:49:00 AM UTC FeynmanTime: newUint64(1713419340), // 2024-04-18 05:49:00 AM UTC
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
BohrTime: nil,
Parlia: &ParliaConfig{ Parlia: &ParliaConfig{
Period: 3, Period: 3,
@@ -192,8 +190,6 @@ var (
FeynmanTime: newUint64(1710136800), // 2024-03-11 6:00:00 AM UTC FeynmanTime: newUint64(1710136800), // 2024-03-11 6:00:00 AM UTC
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
BohrTime: nil,
Parlia: &ParliaConfig{ Parlia: &ParliaConfig{
Period: 3, Period: 3,
@@ -233,8 +229,6 @@ var (
FeynmanTime: newUint64(0), FeynmanTime: newUint64(0),
FeynmanFixTime: newUint64(0), FeynmanFixTime: newUint64(0),
CancunTime: newUint64(0), CancunTime: newUint64(0),
HaberTime: newUint64(0),
BohrTime: newUint64(0),
Parlia: &ParliaConfig{ Parlia: &ParliaConfig{
Period: 3, Period: 3,
@@ -273,7 +267,6 @@ var (
FeynmanTime: newUint64(0), FeynmanTime: newUint64(0),
FeynmanFixTime: newUint64(0), FeynmanFixTime: newUint64(0),
CancunTime: newUint64(0), CancunTime: newUint64(0),
Parlia: &ParliaConfig{ Parlia: &ParliaConfig{
Period: 3, Period: 3,
Epoch: 200, Epoch: 200,
@@ -511,8 +504,6 @@ type ChainConfig struct {
FeynmanTime *uint64 `json:"feynmanTime,omitempty"` // Feynman switch time (nil = no fork, 0 = already activated) FeynmanTime *uint64 `json:"feynmanTime,omitempty"` // Feynman switch time (nil = no fork, 0 = already activated)
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)
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)
@@ -618,17 +609,7 @@ func (c *ChainConfig) String() string {
CancunTime = big.NewInt(0).SetUint64(*c.CancunTime) CancunTime = big.NewInt(0).SetUint64(*c.CancunTime)
} }
var HaberTime *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, Engine: %v}",
if c.HaberTime != nil {
HaberTime = big.NewInt(0).SetUint64(*c.HaberTime)
}
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, BohrTime: %v, Engine: %v}",
c.ChainID, c.ChainID,
c.HomesteadBlock, c.HomesteadBlock,
c.DAOForkBlock, c.DAOForkBlock,
@@ -665,8 +646,6 @@ func (c *ChainConfig) String() string {
FeynmanTime, FeynmanTime,
FeynmanFixTime, FeynmanFixTime,
CancunTime, CancunTime,
HaberTime,
BohrTime,
engine, engine,
) )
} }
@@ -934,25 +913,6 @@ func (c *ChainConfig) IsCancun(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.CancunTime, time) return c.IsLondon(num) && isTimestampForked(c.CancunTime, time)
} }
// IsHaber returns whether time is either equal to the Haber fork time or greater.
func (c *ChainConfig) IsHaber(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.HaberTime, time)
}
// 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)
@@ -1016,8 +976,6 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "feynmanTime", timestamp: c.FeynmanTime}, {name: "feynmanTime", timestamp: c.FeynmanTime},
{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: "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},
} { } {
@@ -1347,8 +1305,8 @@ type Rules struct {
IsPlato bool IsPlato bool
IsHertz bool IsHertz bool
IsHertzfix bool IsHertzfix bool
IsShanghai, IsKepler, IsFeynman, IsCancun, IsHaber bool IsShanghai, IsKepler, IsFeynman, IsCancun, IsPrague bool
IsBohr, IsPrague, IsVerkle bool IsVerkle bool
} }
// Rules ensures c's ChainID is not nil. // Rules ensures c's ChainID is not nil.
@@ -1383,8 +1341,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsKepler: c.IsKepler(num, timestamp), IsKepler: c.IsKepler(num, timestamp),
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),
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),
} }

View File

@@ -170,8 +170,6 @@ const (
Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation
Bls12381MapG2Gas uint64 = 110000 // Gas price for BLS12-381 mapping field element to G2 operation Bls12381MapG2Gas uint64 = 110000 // Gas price for BLS12-381 mapping field element to G2 operation
P256VerifyGas uint64 = 3450 // secp256r1 elliptic curve signature verifier gas price
// The Refund Quotient is the cap on how much of the used gas can be refunded. Before EIP-3529, // The Refund Quotient is the cap on how much of the used gas can be refunded. Before EIP-3529,
// up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529 // up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529
RefundQuotient uint64 = 2 RefundQuotient uint64 = 2

View File

@@ -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 = 10 // Patch version component of the current release VersionPatch = 7 // 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
) )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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