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

feat: async ccc checker #971

Merged
merged 3 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
114 changes: 12 additions & 102 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,32 @@
package core

import (
"errors"
"fmt"
"sync"
"time"

"github.com/scroll-tech/go-ethereum/consensus"
"github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/ccc"
"github.com/scroll-tech/go-ethereum/trie"
)

var (
validateL1MessagesTimer = metrics.NewRegisteredTimer("validator/l1msg", nil)
validateRowConsumptionTimer = metrics.NewRegisteredTimer("validator/rowconsumption", nil)
validateTraceTimer = metrics.NewRegisteredTimer("validator/trace", nil)
validateLockTimer = metrics.NewRegisteredTimer("validator/lock", nil)
validateCccTimer = metrics.NewRegisteredTimer("validator/ccc", nil)
validateL1MessagesTimer = metrics.NewRegisteredTimer("validator/l1msg", nil)
)

// BlockValidator is responsible for validating block headers, uncles and
// processed state.
//
// BlockValidator implements Validator.
type BlockValidator struct {
config *params.ChainConfig // Chain configuration options
bc *BlockChain // Canonical block chain
engine consensus.Engine // Consensus engine used for validating

// circuit capacity checker related fields
checkCircuitCapacity bool // whether enable circuit capacity check
cMu sync.Mutex // mutex for circuit capacity checker
tracer tracerWrapper // scroll tracer wrapper
circuitCapacityChecker *ccc.Checker // circuit capacity checker instance
config *params.ChainConfig // Chain configuration options
bc *BlockChain // Canonical block chain
engine consensus.Engine // Consensus engine used for validating
asyncValidator func(*types.Block) error // Asynchronously run a validation task
}

// NewBlockValidator returns a new block validator which is safe for re-use
Expand All @@ -68,15 +55,10 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
return validator
}

type tracerWrapper interface {
CreateTraceEnvAndGetBlockTrace(*params.ChainConfig, ChainContext, consensus.Engine, ethdb.Database, *state.StateDB, *types.Block, *types.Block, bool) (*types.BlockTrace, error)
}

func (v *BlockValidator) SetupTracerAndCircuitCapacityChecker(tracer tracerWrapper) {
v.checkCircuitCapacity = true
v.tracer = tracer
v.circuitCapacityChecker = ccc.NewChecker(true)
log.Info("new CircuitCapacityChecker in BlockValidator", "ID", v.circuitCapacityChecker.ID)
// WithAsyncValidator sets up an async validator to be triggered on each new block
func (v *BlockValidator) WithAsyncValidator(asyncValidator func(*types.Block) error) Validator {
v.asyncValidator = asyncValidator
return v
}

// ValidateBody validates the given block's uncles and verifies the block
Expand Down Expand Up @@ -114,25 +96,11 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if err := v.ValidateL1Messages(block); err != nil {
return err
}
if v.checkCircuitCapacity {
// if a block's RowConsumption has been stored, which means it has been processed before,
// (e.g., in miner/worker.go or in insertChain),
// we simply skip its calculation and validation
if rawdb.ReadBlockRowConsumption(v.bc.db, block.Hash()) != nil {
return nil
}
rowConsumption, err := v.validateCircuitRowConsumption(block)
if err != nil {

if v.asyncValidator != nil {
if err := v.asyncValidator(block); err != nil {
return err
}
log.Trace(
"Validator write block row consumption",
"id", v.circuitCapacityChecker.ID,
"number", block.NumberU64(),
"hash", block.Hash().String(),
"rowConsumption", rowConsumption,
)
rawdb.WriteBlockRowConsumption(v.bc.db, block.Hash(), rowConsumption)
}
return nil
}
Expand Down Expand Up @@ -286,61 +254,3 @@ func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 {
}
return limit
}

func (v *BlockValidator) createTraceEnvAndGetBlockTrace(block *types.Block) (*types.BlockTrace, error) {
parent := v.bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
return nil, errors.New("validateCircuitRowConsumption: no parent block found")
}

statedb, err := v.bc.StateAt(parent.Root())
if err != nil {
return nil, err
}

return v.tracer.CreateTraceEnvAndGetBlockTrace(v.config, v.bc, v.engine, v.bc.db, statedb, parent, block, true)
}

func (v *BlockValidator) validateCircuitRowConsumption(block *types.Block) (*types.RowConsumption, error) {
defer func(t0 time.Time) {
validateRowConsumptionTimer.Update(time.Since(t0))
}(time.Now())

log.Trace(
"Validator apply ccc for block",
"id", v.circuitCapacityChecker.ID,
"number", block.NumberU64(),
"hash", block.Hash().String(),
"len(txs)", block.Transactions().Len(),
)

traceStartTime := time.Now()
traces, err := v.createTraceEnvAndGetBlockTrace(block)
if err != nil {
return nil, err
}
validateTraceTimer.Update(time.Since(traceStartTime))

lockStartTime := time.Now()
v.cMu.Lock()
defer v.cMu.Unlock()
validateLockTimer.Update(time.Since(lockStartTime))

cccStartTime := time.Now()
v.circuitCapacityChecker.Reset()
log.Trace("Validator reset ccc", "id", v.circuitCapacityChecker.ID)
rc, err := v.circuitCapacityChecker.ApplyBlock(traces)
validateCccTimer.Update(time.Since(cccStartTime))

log.Trace(
"Validator apply ccc for block result",
"id", v.circuitCapacityChecker.ID,
"number", block.NumberU64(),
"hash", block.Hash().String(),
"len(txs)", block.Transactions().Len(),
"rc", rc,
"err", err,
)

return rc, err
}
5 changes: 2 additions & 3 deletions core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ type Validator interface {
// gas used.
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error

// SetupTracerAndCircuitCapacityChecker sets up ScrollTracerWrapper and CircuitCapacityChecker for validator,
// to get scroll-related traces and to validate the circuit row consumption
SetupTracerAndCircuitCapacityChecker(tracer tracerWrapper)
// WithAsyncValidator sets up an async validator to be triggered on each new block
WithAsyncValidator(asyncValidator func(*types.Block) error) Validator
}

// Prefetcher is an interface for pre-caching transaction signatures and state.
Expand Down
13 changes: 10 additions & 3 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ import (
"github.com/scroll-tech/go-ethereum/p2p/enode"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rlp"
"github.com/scroll-tech/go-ethereum/rollup/ccc"
"github.com/scroll-tech/go-ethereum/rollup/rollup_sync_service"
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
"github.com/scroll-tech/go-ethereum/rollup/tracing"
"github.com/scroll-tech/go-ethereum/rpc"
)

Expand All @@ -73,6 +73,7 @@ type Ethereum struct {
txPool *core.TxPool
syncService *sync_service.SyncService
rollupSyncService *rollup_sync_service.RollupSyncService
asyncChecker *ccc.AsyncChecker
blockchain *core.BlockChain
handler *handler
ethDialCandidates enode.Iterator
Expand Down Expand Up @@ -199,8 +200,11 @@ func New(stack *node.Node, config *ethconfig.Config, l1Client sync_service.EthCl
return nil, err
}
if config.CheckCircuitCapacity {
tracer := tracing.NewTracerWrapper()
eth.blockchain.Validator().SetupTracerAndCircuitCapacityChecker(tracer)
eth.asyncChecker = ccc.NewAsyncChecker(eth.blockchain, runtime.GOMAXPROCS(0))
eth.asyncChecker.WithOnFailingBlock(func(b *types.Block, err error) {
log.Warn("block failed CCC check, it will most likely be reorged by the sequencer", "hash", b.Hash(), "err", err)
})
eth.blockchain.Validator().WithAsyncValidator(eth.asyncChecker.Check)
}

// Rewind the chain in case of an incompatible config upgrade.
Expand Down Expand Up @@ -594,6 +598,9 @@ func (s *Ethereum) Stop() error {
s.rollupSyncService.Stop()
}
s.miner.Close()
if s.config.CheckCircuitCapacity {
s.asyncChecker.Wait()
}
s.blockchain.Stop()
s.engine.Close()
rawdb.PopUncleanShutdownMarker(s.chainDb)
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ require (
github.com/scroll-tech/da-codec v0.1.1-0.20240718144756-1875fd490923
github.com/scroll-tech/zktrie v0.8.4
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sourcegraph/conc v0.3.0
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
github.com/stretchr/testify v1.9.0
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
Expand Down Expand Up @@ -99,6 +100,8 @@ require (
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/net v0.16.0 // indirect
golang.org/x/term v0.15.0 // indirect
google.golang.org/protobuf v1.23.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
Expand Down Expand Up @@ -450,7 +452,11 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
Expand Down
Loading
Loading