Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prepare for v0.5.4 release #237

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## v0.5.4

This is a minor release for opBNB Mainnet and Testnet.

It enables the TxDAG generation feature.
When it's enabled in the sequencer, it will generate TxDAG of the block and append it to the last transaction calldata.
The TxDAG can be used for acceleration of the block execution along with the parallel evm feature released in [v0.5.1-pevm.alpha](https://github.com/bnb-chain/op-geth/releases/tag/v0.5.1-pevm.alpha).

It's optional to upgrade to this version since the new feature only works in the sequencer node.

### What's Changed
* feat: TxDAG generation v0.1 version by @welkin22 in https://github.com/bnb-chain/op-geth/pull/187

### Docker Images
ghcr.io/bnb-chain/op-geth:v0.5.4

**Full Changelog**: https://github.com/bnb-chain/op-geth/compare/v0.5.3...v0.5.4

## v0.5.3

This is a minor release for opBNB Mainnet and Testnet.
Expand Down
12 changes: 12 additions & 0 deletions beacon/engine/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ import (
// building of the payload to commence.
type PayloadVersion byte

const (
GetPayloadStage = "getPayload"
NewPayloadStage = "newPayload"
ForkchoiceUpdatedStage = "forkchoiceUpdated"
)

var (
PayloadV1 PayloadVersion = 0x1
PayloadV2 PayloadVersion = 0x2
Expand Down Expand Up @@ -181,6 +187,12 @@ type ForkchoiceStateV1 struct {
FinalizedBlockHash common.Hash `json:"finalizedBlockHash"`
}

type OpSealPayloadResponse struct {
ErrStage string `json:"errStage"`
PayloadStatus PayloadStatusV1 `json:"payloadStatus"`
Payload *ExecutionPayloadEnvelope `json:"payload"`
}

func encodeTransactions(txs []*types.Transaction) [][]byte {
var enc = make([][]byte, len(txs))
for i, tx := range txs {
Expand Down
2 changes: 1 addition & 1 deletion cmd/evm/blockrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func blockTestCmd(ctx *cli.Context) error {
continue
}
test := tests[name]
if err := test.Run(false, rawdb.HashScheme, tracer, func(res error, chain *core.BlockChain) {
if err := test.Run(false, rawdb.HashScheme, tracer, false, func(res error, chain *core.BlockChain) {
if ctx.Bool(DumpFlag.Name) {
if state, _ := chain.State(); state != nil {
fmt.Println(string(state.Dump(nil)))
Expand Down
2 changes: 2 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ var (
utils.RollupComputePendingBlock,
utils.RollupHaltOnIncompatibleProtocolVersionFlag,
utils.RollupSuperchainUpgradesFlag,
utils.ParallelTxDAGFlag,
utils.ParallelTxDAGSenderPrivFlag,
configFileFlag,
utils.LogDebugFlag,
utils.LogBacktraceAtFlag,
Expand Down
24 changes: 24 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1099,11 +1099,24 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
Category: flags.MetricsCategory,
}

ParallelTxDAGFlag = &cli.BoolFlag{
Name: "parallel.txdag",
Usage: "Enable the experimental parallel TxDAG generation (default = false)",
Category: flags.VMCategory,
}

VMOpcodeOptimizeFlag = &cli.BoolFlag{
Name: "vm.opcode.optimize",
Usage: "enable opcode optimization",
Category: flags.VMCategory,
}

ParallelTxDAGSenderPrivFlag = &cli.StringFlag{
Name: "parallel.txdagsenderpriv",
Usage: "private key of the sender who sends the TxDAG transactions",
Value: "",
Category: flags.VMCategory,
}
)

var (
Expand Down Expand Up @@ -1989,6 +2002,17 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
}

if ctx.IsSet(ParallelTxDAGFlag.Name) {
cfg.EnableParallelTxDAG = ctx.Bool(ParallelTxDAGFlag.Name)
}

if ctx.IsSet(ParallelTxDAGSenderPrivFlag.Name) {
priHex := ctx.String(ParallelTxDAGSenderPrivFlag.Name)
if cfg.Miner.ParallelTxDAGSenderPriv, err = crypto.HexToECDSA(priHex); err != nil {
Fatalf("Failed to parse txdag private key of %s, err: %v", ParallelTxDAGSenderPrivFlag.Name, err)
}
}

if ctx.IsSet(VMOpcodeOptimizeFlag.Name) {
cfg.EnableOpcodeOptimizing = ctx.Bool(VMOpcodeOptimizeFlag.Name)
if cfg.EnableOpcodeOptimizing {
Expand Down
12 changes: 9 additions & 3 deletions consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,17 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
// Finalize and assemble the block.
beacon.Finalize(chain, header, state, txs, uncles, withdrawals)

// Assign the final state root to header.
header.Root = state.IntermediateRoot(true)
rootCh := make(chan common.Hash)
go func() {
rootCh <- state.IntermediateRoot(true)
}()

block := types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil))
headerWithRoot := block.Header()
headerWithRoot.Root = <-rootCh

// Assemble and return the final block.
return types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)), nil
return block.WithSeal(headerWithRoot), nil
}

// Seal generates a new sealing request for the given input block and pushes
Expand Down
8 changes: 5 additions & 3 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {

// ValidateState validates the various changes that happen after a state transition,
// such as amount of used gas, the receipt roots and the state root itself.
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, skipRoot bool) error {
header := block.Header()
if block.GasUsed() != usedGas {
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
Expand All @@ -186,14 +186,16 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
}
return nil
},
func() error {
}
if !skipRoot {
validateFuns = append(validateFuns, func() error {
// Validate the state root against the received state root and throw
// an error if they don't match.
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error())
}
return nil
},
})
}
validateRes := make(chan error, len(validateFuns))
for _, f := range validateFuns {
Expand Down
93 changes: 83 additions & 10 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ var (
triedbCommitExternalTimer = metrics.NewRegisteredTimer("chain/triedb/commit/external", nil)
innerExecutionTimer = metrics.NewRegisteredTimer("chain/inner/execution", nil)

txDAGGenerateTimer = metrics.NewRegisteredTimer("chain/block/txdag/gen", nil)

blockGasUsedGauge = metrics.NewRegisteredGauge("chain/block/gas/used", nil)
mgaspsGauge = metrics.NewRegisteredGauge("chain/mgas/ps", nil)

Expand Down Expand Up @@ -298,6 +300,9 @@ type BlockChain struct {
processor Processor // Block transaction processor interface
forker *ForkChoice
vmConfig vm.Config

// parallel EVM related
enableTxDAG bool
}

// NewBlockChain returns a fully initialised block chain using information
Expand Down Expand Up @@ -1185,6 +1190,13 @@ func (bc *BlockChain) procFutureBlocks() {
}
}

// CacheBlock cache block in memory
func (bc *BlockChain) CacheBlock(hash common.Hash, block *types.Block) {
bc.hc.numberCache.Add(hash, block.NumberU64())
bc.hc.headerCache.Add(hash, block.Header())
bc.blockCache.Add(hash, block)
}

// CacheMiningReceipts cache receipts in memory
func (bc *BlockChain) CacheMiningReceipts(hash common.Hash, receipts types.Receipts) {
bc.miningReceiptsCache.Add(hash, receipts)
Expand Down Expand Up @@ -1731,6 +1743,15 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
return 0, nil
}

minerMode := false
if len(chain) == 1 {
block := chain[0]
_, receiptExist := bc.miningReceiptsCache.Get(block.Hash())
_, logExist := bc.miningTxLogsCache.Get(block.Hash())
_, stateExist := bc.miningStateCache.Get(block.Hash())
minerMode = receiptExist && logExist && stateExist
}

// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)

Expand All @@ -1754,7 +1775,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)

// Peek the error for the first block to decide the directing import logic
it := newInsertIterator(chain, results, bc.validator)
block, err := it.next()
var block *types.Block
var err error
if minerMode {
block = chain[0]
it.index = 0
} else {
block, err = it.next()
}

// Left-trim all the known blocks that don't need to build snapshot
if bc.skipBlock(err, it) {
Expand Down Expand Up @@ -1970,11 +1998,28 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
ptime := time.Since(pstart)

vstart := time.Now()
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
bc.reportBlock(block, receipts, err)
followupInterrupt.Store(true)
return it.index, err
// Async validate if minerMode
asyncValidateStateCh := make(chan error, 1)
if minerMode {
header := block.Header()
// Can not validate root concurrently
if root := statedb.IntermediateRoot(bc.chainConfig.IsEIP158(header.Number)); header.Root != root {
err := fmt.Errorf("self mined block(hash: %x number %v) verify root err(mined: %x expected: %x) dberr: %w", block.Hash(), block.NumberU64(), header.Root, root, statedb.Error())
bc.reportBlock(block, receipts, err)
followupInterrupt.Store(true)
return it.index, err
}
go func() {
asyncValidateStateCh <- bc.validator.ValidateState(block, statedb, receipts, usedGas, true)
}()
} else {
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas, false); err != nil {
bc.reportBlock(block, receipts, err)
followupInterrupt.Store(true)
return it.index, err
}
}

vtime := time.Since(vstart)
proctime := time.Since(start) // processing + validation

Expand All @@ -1987,8 +2032,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete(in validation)
blockExecutionTimer.Update(ptime) // The time spent on block execution
blockValidationTimer.Update(vtime) // The time spent on block validation
txDAGGenerateTimer.Update(statedb.TxDAGGenerate)
blockExecutionTimer.Update(ptime) // The time spent on block execution
blockValidationTimer.Update(vtime) // The time spent on block validation

innerExecutionTimer.Update(DebugInnerExecutionDuration)

Expand All @@ -2009,6 +2055,13 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
if err != nil {
return it.index, err
}
if minerMode {
if err := <-asyncValidateStateCh; err != nil {
panic(fmt.Errorf("self mined block(hash: %x number %v) async verify state err: %w", block.Hash(), block.NumberU64(), err))
}
}
bc.CacheBlock(block.Hash(), block)

// Update the metrics touched during block commit
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
Expand All @@ -2027,10 +2080,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
stats.usedGas += usedGas

var snapDiffItems, snapBufItems common.StorageSize
if bc.snaps != nil {
if bc.snaps != nil && !minerMode {
snapDiffItems, snapBufItems = bc.snaps.Size()
}
trieDiffNodes, trieBufNodes, trieImmutableBufNodes, _ := bc.triedb.Size()

var trieDiffNodes, trieBufNodes, trieImmutableBufNodes common.StorageSize
if !minerMode {
trieDiffNodes, trieBufNodes, trieImmutableBufNodes, _ = bc.triedb.Size()
}
stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, trieImmutableBufNodes, setHead)
blockGasUsedGauge.Update(int64(block.GasUsed()) / 1000000)

Expand Down Expand Up @@ -2530,10 +2587,17 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
return common.Hash{}, err
}
}
bc.writeHeadBlock(head)

wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
bc.writeHeadBlock(head)
}()
// Emit events
logs := bc.collectLogs(head, false)
wg.Wait()

bc.chainFeed.Send(ChainEvent{Block: head, Hash: head.Hash(), Logs: logs})
if len(logs) > 0 {
bc.logsFeed.Send(logs)
Expand Down Expand Up @@ -2758,3 +2822,12 @@ func createDelFn(bc *BlockChain) func(db ethdb.KeyValueWriter, hash common.Hash,
func (bc *BlockChain) HeaderChainForceSetHead(headNumber uint64) {
bc.hc.SetHead(headNumber, nil, createDelFn(bc))
}

func (bc *BlockChain) TxDAGEnabledWhenMine() bool {
return bc.enableTxDAG
}

func (bc *BlockChain) SetupTxDAGGeneration() {
log.Info("node enable TxDAG feature")
bc.enableTxDAG = true
}
2 changes: 1 addition & 1 deletion core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
blockchain.reportBlock(block, receipts, err)
return err
}
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas)
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, false)
if err != nil {
blockchain.reportBlock(block, receipts, err)
return err
Expand Down
2 changes: 1 addition & 1 deletion core/state/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func (ch createObjectChange) dirtied() *common.Address {
func (ch resetObjectChange) revert(s *StateDB) {
s.setStateObject(ch.prev)
if !ch.prevdestruct {
delete(s.stateObjectsDestruct, ch.prev.address)
s.removeStateObjectsDestruct(ch.prev.address)
}
if ch.prevAccount != nil {
s.accounts[ch.prev.addrHash] = ch.prevAccount
Expand Down
11 changes: 7 additions & 4 deletions core/state/snapshot/difflayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var (
// Note, bumping this up might drastically increase the size of the bloom
// filters that's stored in every diff layer. Don't do that without fully
// understanding all the implications.
aggregatorMemoryLimit = uint64(4 * 1024 * 1024)
aggregatorMemoryLimit = uint64(4 * 1024 * 1024 * 3) // opBNB block gas limit is about 3 times to Ethereum

// aggregatorItemLimit is an approximate number of items that will end up
// in the aggregator layer before it's flushed out to disk. A plain account
Expand All @@ -50,23 +50,26 @@ var (
// smaller number to be on the safe side.
aggregatorItemLimit = aggregatorMemoryLimit / 42

// bloomItemLimit is an approximate number of all difflayer items (128 difflayers + 1 aggregatorlayer)
bloomItemLimit = 25*10000*5 + aggregatorItemLimit

// bloomTargetError is the target false positive rate when the aggregator
// layer is at its fullest. The actual value will probably move around up
// and down from this number, it's mostly a ballpark figure.
//
// Note, dropping this down might drastically increase the size of the bloom
// filters that's stored in every diff layer. Don't do that without fully
// understanding all the implications.
bloomTargetError = 0.02
bloomTargetError = 0.01

// bloomSize is the ideal bloom filter size given the maximum number of items
// it's expected to hold and the target false positive error rate.
bloomSize = math.Ceil(float64(aggregatorItemLimit) * math.Log(bloomTargetError) / math.Log(1/math.Pow(2, math.Log(2))))
bloomSize = math.Ceil(float64(bloomItemLimit) * math.Log(bloomTargetError) / math.Log(1/math.Pow(2, math.Log(2))))

// bloomFuncs is the ideal number of bits a single entry should set in the
// bloom filter to keep its size to a minimum (given it's size and maximum
// entry count).
bloomFuncs = math.Round((bloomSize / float64(aggregatorItemLimit)) * math.Log(2))
bloomFuncs = math.Round((bloomSize / float64(bloomItemLimit)) * math.Log(2))

// the bloom offsets are runtime constants which determines which part of the
// account/storage hash the hasher functions looks at, to determine the
Expand Down
Loading
Loading