mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
feat: introduce encode stage (#822)
* Reapply "feat: introduce encode stage (#814)"
This reverts commit 0b6cdbdbe2.
* reintroduced nullifying txnQueue
This commit is contained in:
parent
69aae68b2f
commit
1ebde6d893
4 changed files with 179 additions and 77 deletions
|
|
@ -24,7 +24,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 5 // Major version component of the current release
|
VersionMajor = 5 // 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 = 2 // Patch version component of the current release
|
VersionPatch = 3 // Patch version component of the current release
|
||||||
VersionMeta = "mainnet" // Version metadata to append to the version string
|
VersionMeta = "mainnet" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,19 +73,7 @@ func (ccc *CircuitCapacityChecker) ApplyTransaction(traces *types.BlockTrace) (*
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeStart := time.Now()
|
encodeStart := time.Now()
|
||||||
ccc.jsonBuffer.Reset()
|
rustTrace := MakeRustTrace(traces, &ccc.jsonBuffer)
|
||||||
err := json.NewEncoder(&ccc.jsonBuffer).Encode(traces)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("fail to json marshal traces in ApplyTransaction", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash, "err", err)
|
|
||||||
return nil, ErrUnknown
|
|
||||||
}
|
|
||||||
|
|
||||||
tracesStr := C.CString(string(ccc.jsonBuffer.Bytes()))
|
|
||||||
defer func() {
|
|
||||||
C.free(unsafe.Pointer(tracesStr))
|
|
||||||
}()
|
|
||||||
|
|
||||||
rustTrace := C.parse_json_to_rust_trace(tracesStr)
|
|
||||||
if rustTrace == nil {
|
if rustTrace == nil {
|
||||||
log.Error("fail to parse json in to rust trace", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash)
|
log.Error("fail to parse json in to rust trace", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash)
|
||||||
return nil, ErrUnknown
|
return nil, ErrUnknown
|
||||||
|
|
@ -93,26 +81,34 @@ func (ccc *CircuitCapacityChecker) ApplyTransaction(traces *types.BlockTrace) (*
|
||||||
encodeTimer.UpdateSince(encodeStart)
|
encodeTimer.UpdateSince(encodeStart)
|
||||||
|
|
||||||
log.Debug("start to check circuit capacity for tx", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash)
|
log.Debug("start to check circuit capacity for tx", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash)
|
||||||
|
return ccc.applyTransactionRustTrace(rustTrace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ccc *CircuitCapacityChecker) ApplyTransactionRustTrace(rustTrace unsafe.Pointer) (*types.RowConsumption, error) {
|
||||||
|
ccc.Lock()
|
||||||
|
defer ccc.Unlock()
|
||||||
|
return ccc.applyTransactionRustTrace(rustTrace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ccc *CircuitCapacityChecker) applyTransactionRustTrace(rustTrace unsafe.Pointer) (*types.RowConsumption, error) {
|
||||||
rawResult := C.apply_tx(C.uint64_t(ccc.ID), rustTrace)
|
rawResult := C.apply_tx(C.uint64_t(ccc.ID), rustTrace)
|
||||||
defer func() {
|
defer func() {
|
||||||
C.free_c_chars(rawResult)
|
C.free_c_chars(rawResult)
|
||||||
}()
|
}()
|
||||||
log.Debug("check circuit capacity for tx done", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash)
|
|
||||||
|
|
||||||
result := &WrappedRowUsage{}
|
result := &WrappedRowUsage{}
|
||||||
if err = json.Unmarshal([]byte(C.GoString(rawResult)), result); err != nil {
|
if err := json.Unmarshal([]byte(C.GoString(rawResult)), result); err != nil {
|
||||||
log.Error("fail to json unmarshal apply_tx result", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash, "err", err)
|
log.Error("fail to json unmarshal apply_tx result", "id", ccc.ID, "err", err)
|
||||||
return nil, ErrUnknown
|
return nil, ErrUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Error != "" {
|
if result.Error != "" {
|
||||||
log.Error("fail to apply_tx in CircuitCapacityChecker", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash, "err", result.Error)
|
log.Error("fail to apply_tx in CircuitCapacityChecker", "id", ccc.ID, "err", result.Error)
|
||||||
return nil, ErrUnknown
|
return nil, ErrUnknown
|
||||||
}
|
}
|
||||||
if result.AccRowUsage == nil {
|
if result.AccRowUsage == nil {
|
||||||
log.Error("fail to apply_tx in CircuitCapacityChecker",
|
log.Error("fail to apply_tx in CircuitCapacityChecker",
|
||||||
"id", ccc.ID, "TxHash", traces.Transactions[0].TxHash,
|
"id", ccc.ID, "result.AccRowUsage == nil", result.AccRowUsage == nil,
|
||||||
"result.AccRowUsage == nil", result.AccRowUsage == nil,
|
|
||||||
"err", "AccRowUsage is empty unexpectedly")
|
"err", "AccRowUsage is empty unexpectedly")
|
||||||
return nil, ErrUnknown
|
return nil, ErrUnknown
|
||||||
}
|
}
|
||||||
|
|
@ -128,19 +124,7 @@ func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types.
|
||||||
defer ccc.Unlock()
|
defer ccc.Unlock()
|
||||||
|
|
||||||
encodeStart := time.Now()
|
encodeStart := time.Now()
|
||||||
ccc.jsonBuffer.Reset()
|
rustTrace := MakeRustTrace(traces, &ccc.jsonBuffer)
|
||||||
err := json.NewEncoder(&ccc.jsonBuffer).Encode(traces)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("fail to json marshal traces in ApplyBlock", "id", ccc.ID, "blockNumber", traces.Header.Number, "blockHash", traces.Header.Hash(), "err", err)
|
|
||||||
return nil, ErrUnknown
|
|
||||||
}
|
|
||||||
|
|
||||||
tracesStr := C.CString(string(ccc.jsonBuffer.Bytes()))
|
|
||||||
defer func() {
|
|
||||||
C.free(unsafe.Pointer(tracesStr))
|
|
||||||
}()
|
|
||||||
|
|
||||||
rustTrace := C.parse_json_to_rust_trace(tracesStr)
|
|
||||||
if rustTrace == nil {
|
if rustTrace == nil {
|
||||||
log.Error("fail to parse json in to rust trace", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash)
|
log.Error("fail to parse json in to rust trace", "id", ccc.ID, "TxHash", traces.Transactions[0].TxHash)
|
||||||
return nil, ErrUnknown
|
return nil, ErrUnknown
|
||||||
|
|
@ -155,7 +139,7 @@ func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types.
|
||||||
log.Debug("check circuit capacity for block done", "id", ccc.ID, "blockNumber", traces.Header.Number, "blockHash", traces.Header.Hash())
|
log.Debug("check circuit capacity for block done", "id", ccc.ID, "blockNumber", traces.Header.Number, "blockHash", traces.Header.Hash())
|
||||||
|
|
||||||
result := &WrappedRowUsage{}
|
result := &WrappedRowUsage{}
|
||||||
if err = json.Unmarshal([]byte(C.GoString(rawResult)), result); err != nil {
|
if err := json.Unmarshal([]byte(C.GoString(rawResult)), result); err != nil {
|
||||||
log.Error("fail to json unmarshal apply_block result", "id", ccc.ID, "blockNumber", traces.Header.Number, "blockHash", traces.Header.Hash(), "err", err)
|
log.Error("fail to json unmarshal apply_block result", "id", ccc.ID, "blockNumber", traces.Header.Number, "blockHash", traces.Header.Hash(), "err", err)
|
||||||
return nil, ErrUnknown
|
return nil, ErrUnknown
|
||||||
}
|
}
|
||||||
|
|
@ -219,3 +203,23 @@ func (ccc *CircuitCapacityChecker) SetLightMode(lightMode bool) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeRustTrace(trace *types.BlockTrace, buffer *bytes.Buffer) unsafe.Pointer {
|
||||||
|
if buffer == nil {
|
||||||
|
buffer = new(bytes.Buffer)
|
||||||
|
}
|
||||||
|
buffer.Reset()
|
||||||
|
|
||||||
|
err := json.NewEncoder(buffer).Encode(trace)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("fail to json marshal traces in MakeRustTrace", "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tracesStr := C.CString(string(buffer.Bytes()))
|
||||||
|
defer func() {
|
||||||
|
C.free(unsafe.Pointer(tracesStr))
|
||||||
|
}()
|
||||||
|
|
||||||
|
return C.parse_json_to_rust_trace(tracesStr)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
package circuitcapacitychecker
|
package circuitcapacitychecker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/scroll-tech/go-ethereum/common"
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
"github.com/scroll-tech/go-ethereum/core/types"
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
|
@ -51,6 +53,10 @@ func (ccc *CircuitCapacityChecker) ApplyTransaction(traces *types.BlockTrace) (*
|
||||||
}}, nil
|
}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ccc *CircuitCapacityChecker) ApplyTransactionRustTrace(rustTrace unsafe.Pointer) (*types.RowConsumption, error) {
|
||||||
|
return ccc.ApplyTransaction(goTraces[rustTrace])
|
||||||
|
}
|
||||||
|
|
||||||
// ApplyBlock gets a block's RowConsumption.
|
// ApplyBlock gets a block's RowConsumption.
|
||||||
// Will only return a dummy value in mock_ccc.
|
// Will only return a dummy value in mock_ccc.
|
||||||
func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types.RowConsumption, error) {
|
func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types.RowConsumption, error) {
|
||||||
|
|
@ -82,3 +88,11 @@ func (ccc *CircuitCapacityChecker) Skip(txnHash common.Hash, err error) {
|
||||||
ccc.skipHash = txnHash.String()
|
ccc.skipHash = txnHash.String()
|
||||||
ccc.skipError = err
|
ccc.skipError = err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var goTraces = make(map[unsafe.Pointer]*types.BlockTrace)
|
||||||
|
|
||||||
|
func MakeRustTrace(trace *types.BlockTrace, buffer *bytes.Buffer) unsafe.Pointer {
|
||||||
|
rustTrace := new(struct{})
|
||||||
|
goTraces[unsafe.Pointer(rustTrace)] = trace
|
||||||
|
return unsafe.Pointer(rustTrace)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
package pipeline
|
package pipeline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/scroll-tech/go-ethereum/common"
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
"github.com/scroll-tech/go-ethereum/core"
|
"github.com/scroll-tech/go-ethereum/core"
|
||||||
|
|
@ -30,7 +34,7 @@ func (e *ErrorWithTrace) Unwrap() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrApplyStageDone = errors.New("apply stage is done")
|
ErrPipelineDone = errors.New("pipeline is done")
|
||||||
ErrUnexpectedL1MessageIndex = errors.New("unexpected L1 message index")
|
ErrUnexpectedL1MessageIndex = errors.New("unexpected L1 message index")
|
||||||
|
|
||||||
lifetimeTimer = func() metrics.Timer {
|
lifetimeTimer = func() metrics.Timer {
|
||||||
|
|
@ -41,6 +45,9 @@ var (
|
||||||
applyTimer = metrics.NewRegisteredTimer("pipeline/apply", nil)
|
applyTimer = metrics.NewRegisteredTimer("pipeline/apply", nil)
|
||||||
applyIdleTimer = metrics.NewRegisteredTimer("pipeline/apply_idle", nil)
|
applyIdleTimer = metrics.NewRegisteredTimer("pipeline/apply_idle", nil)
|
||||||
applyStallTimer = metrics.NewRegisteredTimer("pipeline/apply_stall", nil)
|
applyStallTimer = metrics.NewRegisteredTimer("pipeline/apply_stall", nil)
|
||||||
|
encodeTimer = metrics.NewRegisteredTimer("pipeline/encode", nil)
|
||||||
|
encodeIdleTimer = metrics.NewRegisteredTimer("pipeline/encode_idle", nil)
|
||||||
|
encodeStallTimer = metrics.NewRegisteredTimer("pipeline/encode_stall", nil)
|
||||||
cccTimer = metrics.NewRegisteredTimer("pipeline/ccc", nil)
|
cccTimer = metrics.NewRegisteredTimer("pipeline/ccc", nil)
|
||||||
cccIdleTimer = metrics.NewRegisteredTimer("pipeline/ccc_idle", nil)
|
cccIdleTimer = metrics.NewRegisteredTimer("pipeline/ccc_idle", nil)
|
||||||
)
|
)
|
||||||
|
|
@ -50,6 +57,9 @@ type Pipeline struct {
|
||||||
vmConfig vm.Config
|
vmConfig vm.Config
|
||||||
parent *types.Block
|
parent *types.Block
|
||||||
start time.Time
|
start time.Time
|
||||||
|
wg sync.WaitGroup
|
||||||
|
ctx context.Context
|
||||||
|
cancelCtx context.CancelFunc
|
||||||
|
|
||||||
// accumulators
|
// accumulators
|
||||||
ccc *circuitcapacitychecker.CircuitCapacityChecker
|
ccc *circuitcapacitychecker.CircuitCapacityChecker
|
||||||
|
|
@ -83,6 +93,8 @@ func NewPipeline(
|
||||||
// make sure we are not sharing a tracer with the caller and not in debug mode
|
// make sure we are not sharing a tracer with the caller and not in debug mode
|
||||||
vmConfig.Tracer = nil
|
vmConfig.Tracer = nil
|
||||||
vmConfig.Debug = false
|
vmConfig.Debug = false
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
return &Pipeline{
|
return &Pipeline{
|
||||||
chain: chain,
|
chain: chain,
|
||||||
vmConfig: vmConfig,
|
vmConfig: vmConfig,
|
||||||
|
|
@ -92,6 +104,8 @@ func NewPipeline(
|
||||||
ccc: ccc,
|
ccc: ccc,
|
||||||
state: state,
|
state: state,
|
||||||
gasPool: new(core.GasPool).AddGas(header.GasLimit),
|
gasPool: new(core.GasPool).AddGas(header.GasLimit),
|
||||||
|
ctx: ctx,
|
||||||
|
cancelCtx: cancel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,13 +117,14 @@ func (p *Pipeline) WithBeforeTxHook(beforeTxHook func()) *Pipeline {
|
||||||
func (p *Pipeline) Start(deadline time.Time) error {
|
func (p *Pipeline) Start(deadline time.Time) error {
|
||||||
p.start = time.Now()
|
p.start = time.Now()
|
||||||
p.txnQueue = make(chan *types.Transaction)
|
p.txnQueue = make(chan *types.Transaction)
|
||||||
applyStageRespCh, candidateCh, err := p.traceAndApplyStage(p.txnQueue)
|
applyStageRespCh, applyToEncodeCh, err := p.traceAndApplyStage(p.txnQueue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed starting traceAndApplyStage", "err", err)
|
log.Error("Failed starting traceAndApplyStage", "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.applyStageRespCh = applyStageRespCh
|
p.applyStageRespCh = applyStageRespCh
|
||||||
p.ResultCh = p.cccStage(candidateCh, deadline)
|
encodeToCccCh := p.encodeStage(applyToEncodeCh)
|
||||||
|
p.ResultCh = p.cccStage(encodeToCccCh, deadline)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,7 +152,7 @@ func (p *Pipeline) TryPushTxns(txs types.OrderedTransactionSet, onFailingTxn fun
|
||||||
case err == nil, errors.Is(err, core.ErrNonceTooLow):
|
case err == nil, errors.Is(err, core.ErrNonceTooLow):
|
||||||
txs.Shift()
|
txs.Shift()
|
||||||
default:
|
default:
|
||||||
if errors.Is(err, ErrApplyStageDone) || onFailingTxn(p.txs.Len(), tx, err) {
|
if errors.Is(err, ErrPipelineDone) || onFailingTxn(p.txs.Len(), tx, err) {
|
||||||
p.Stop()
|
p.Stop()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -155,11 +170,13 @@ func (p *Pipeline) TryPushTxns(txs types.OrderedTransactionSet, onFailingTxn fun
|
||||||
|
|
||||||
func (p *Pipeline) TryPushTxn(tx *types.Transaction) (*Result, error) {
|
func (p *Pipeline) TryPushTxn(tx *types.Transaction) (*Result, error) {
|
||||||
if p.txnQueue == nil {
|
if p.txnQueue == nil {
|
||||||
return nil, ErrApplyStageDone
|
return nil, ErrPipelineDone
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case p.txnQueue <- tx:
|
case p.txnQueue <- tx:
|
||||||
|
case <-p.ctx.Done():
|
||||||
|
return nil, ErrPipelineDone
|
||||||
case res := <-p.ResultCh:
|
case res := <-p.ResultCh:
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +184,7 @@ func (p *Pipeline) TryPushTxn(tx *types.Transaction) (*Result, error) {
|
||||||
select {
|
select {
|
||||||
case err, valid := <-p.applyStageRespCh:
|
case err, valid := <-p.applyStageRespCh:
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, ErrApplyStageDone
|
return nil, ErrPipelineDone
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
case res := <-p.ResultCh:
|
case res := <-p.ResultCh:
|
||||||
|
|
@ -177,18 +194,13 @@ func (p *Pipeline) TryPushTxn(tx *types.Transaction) (*Result, error) {
|
||||||
|
|
||||||
// Release releases all resources related to the pipeline
|
// Release releases all resources related to the pipeline
|
||||||
func (p *Pipeline) Release() {
|
func (p *Pipeline) Release() {
|
||||||
p.Stop()
|
p.cancelCtx()
|
||||||
|
p.wg.Wait()
|
||||||
select {
|
|
||||||
case <-p.applyStageRespCh:
|
|
||||||
<-p.ResultCh
|
|
||||||
case <-p.ResultCh:
|
|
||||||
<-p.applyStageRespCh
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockCandidate struct {
|
type BlockCandidate struct {
|
||||||
LastTrace *types.BlockTrace
|
LastTrace *types.BlockTrace
|
||||||
|
RustTrace unsafe.Pointer
|
||||||
NextL1MsgIndex uint64
|
NextL1MsgIndex uint64
|
||||||
|
|
||||||
// accumulated state
|
// accumulated state
|
||||||
|
|
@ -199,25 +211,47 @@ type BlockCandidate struct {
|
||||||
CoalescedLogs []*types.Log
|
CoalescedLogs []*types.Log
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendCancellable tries to send msg to resCh but allows send operation to be cancelled
|
||||||
|
// by closing cancelCh. Returns true if cancelled.
|
||||||
|
func sendCancellable[T any, C comparable](resCh chan T, msg T, cancelCh <-chan C) bool {
|
||||||
|
var zeroC C
|
||||||
|
|
||||||
|
select {
|
||||||
|
case resCh <- msg:
|
||||||
|
return false
|
||||||
|
case cancelSignal := <-cancelCh:
|
||||||
|
if cancelSignal != zeroC {
|
||||||
|
panic("shouldn't have happened")
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Pipeline) traceAndApplyStage(txsIn <-chan *types.Transaction) (<-chan error, <-chan *BlockCandidate, error) {
|
func (p *Pipeline) traceAndApplyStage(txsIn <-chan *types.Transaction) (<-chan error, <-chan *BlockCandidate, error) {
|
||||||
p.state.StartPrefetcher("miner")
|
p.state.StartPrefetcher("miner")
|
||||||
newCandidateCh := make(chan *BlockCandidate)
|
downstreamCh := make(chan *BlockCandidate, p.downstreamChCapacity())
|
||||||
resCh := make(chan error)
|
resCh := make(chan error)
|
||||||
|
p.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
close(newCandidateCh)
|
close(downstreamCh)
|
||||||
close(resCh)
|
close(resCh)
|
||||||
p.state.StopPrefetcher()
|
p.state.StopPrefetcher()
|
||||||
|
p.wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var tx *types.Transaction
|
var tx *types.Transaction
|
||||||
for {
|
for {
|
||||||
applyIdleTimer.Time(func() {
|
idleStart := time.Now()
|
||||||
tx = <-txsIn
|
select {
|
||||||
})
|
case tx = <-txsIn:
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case <-p.ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
applyIdleTimer.UpdateSince(idleStart)
|
||||||
|
|
||||||
applyStart := time.Now()
|
applyStart := time.Now()
|
||||||
|
|
||||||
|
|
@ -234,13 +268,13 @@ func (p *Pipeline) traceAndApplyStage(txsIn <-chan *types.Transaction) (<-chan e
|
||||||
|
|
||||||
if tx.IsL1MessageTx() && tx.AsL1MessageTx().QueueIndex != p.nextL1MsgIndex {
|
if tx.IsL1MessageTx() && tx.AsL1MessageTx().QueueIndex != p.nextL1MsgIndex {
|
||||||
// Continue, we might still be able to include some L2 messages
|
// Continue, we might still be able to include some L2 messages
|
||||||
resCh <- ErrUnexpectedL1MessageIndex
|
sendCancellable(resCh, ErrUnexpectedL1MessageIndex, p.ctx.Done())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !tx.IsL1MessageTx() && !p.chain.Config().Scroll.IsValidBlockSize(p.blockSize+tx.Size()) {
|
if !tx.IsL1MessageTx() && !p.chain.Config().Scroll.IsValidBlockSize(p.blockSize+tx.Size()) {
|
||||||
// can't fit this txn in this block, silently ignore and continue looking for more txns
|
// can't fit this txn in this block, silently ignore and continue looking for more txns
|
||||||
resCh <- nil
|
sendCancellable(resCh, nil, p.ctx.Done())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -267,21 +301,16 @@ func (p *Pipeline) traceAndApplyStage(txsIn <-chan *types.Transaction) (<-chan e
|
||||||
}
|
}
|
||||||
|
|
||||||
stallStart := time.Now()
|
stallStart := time.Now()
|
||||||
select {
|
if sendCancellable(downstreamCh, &BlockCandidate{
|
||||||
case newCandidateCh <- &BlockCandidate{
|
|
||||||
LastTrace: trace,
|
|
||||||
NextL1MsgIndex: p.nextL1MsgIndex,
|
NextL1MsgIndex: p.nextL1MsgIndex,
|
||||||
|
LastTrace: trace,
|
||||||
|
|
||||||
Header: types.CopyHeader(&p.Header),
|
Header: types.CopyHeader(&p.Header),
|
||||||
State: p.state.Copy(),
|
State: p.state.Copy(),
|
||||||
Txs: p.txs,
|
Txs: p.txs,
|
||||||
Receipts: p.receipts,
|
Receipts: p.receipts,
|
||||||
CoalescedLogs: p.coalescedLogs,
|
CoalescedLogs: p.coalescedLogs,
|
||||||
}:
|
}, p.ctx.Done()) {
|
||||||
case tx = <-txsIn:
|
|
||||||
if tx != nil {
|
|
||||||
panic("shouldn't have happened")
|
|
||||||
}
|
|
||||||
// next stage terminated and caller terminated us as well
|
// next stage terminated and caller terminated us as well
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -294,10 +323,10 @@ func (p *Pipeline) traceAndApplyStage(txsIn <-chan *types.Transaction) (<-chan e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
applyTimer.UpdateSince(applyStart)
|
applyTimer.UpdateSince(applyStart)
|
||||||
resCh <- err
|
sendCancellable(resCh, err, p.ctx.Done())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return resCh, newCandidateCh, nil
|
return resCh, downstreamCh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
|
|
@ -309,25 +338,70 @@ type Result struct {
|
||||||
FinalBlock *BlockCandidate
|
FinalBlock *BlockCandidate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) encodeStage(traces <-chan *BlockCandidate) <-chan *BlockCandidate {
|
||||||
|
downstreamCh := make(chan *BlockCandidate, p.downstreamChCapacity())
|
||||||
|
p.wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
close(downstreamCh)
|
||||||
|
p.wg.Done()
|
||||||
|
}()
|
||||||
|
buffer := new(bytes.Buffer)
|
||||||
|
for {
|
||||||
|
idleStart := time.Now()
|
||||||
|
select {
|
||||||
|
case trace := <-traces:
|
||||||
|
if trace == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
encodeIdleTimer.UpdateSince(idleStart)
|
||||||
|
|
||||||
|
encodeStart := time.Now()
|
||||||
|
if p.ccc != nil {
|
||||||
|
trace.RustTrace = circuitcapacitychecker.MakeRustTrace(trace.LastTrace, buffer)
|
||||||
|
if trace.RustTrace == nil {
|
||||||
|
log.Error("making rust trace", "txHash", trace.LastTrace.Transactions[0].TxHash)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
encodeTimer.UpdateSince(encodeStart)
|
||||||
|
|
||||||
|
stallStart := time.Now()
|
||||||
|
sendCancellable(downstreamCh, trace, p.ctx.Done())
|
||||||
|
encodeStallTimer.UpdateSince(stallStart)
|
||||||
|
case <-p.ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return downstreamCh
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Pipeline) cccStage(candidates <-chan *BlockCandidate, deadline time.Time) <-chan *Result {
|
func (p *Pipeline) cccStage(candidates <-chan *BlockCandidate, deadline time.Time) <-chan *Result {
|
||||||
if p.ccc != nil {
|
if p.ccc != nil {
|
||||||
p.ccc.Reset()
|
p.ccc.Reset()
|
||||||
}
|
}
|
||||||
resultCh := make(chan *Result)
|
resultCh := make(chan *Result, 1)
|
||||||
var lastCandidate *BlockCandidate
|
var lastCandidate *BlockCandidate
|
||||||
var lastAccRows *types.RowConsumption
|
var lastAccRows *types.RowConsumption
|
||||||
var deadlineReached bool
|
var deadlineReached bool
|
||||||
|
|
||||||
|
p.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
deadlineTimer := time.NewTimer(time.Until(deadline))
|
deadlineTimer := time.NewTimer(time.Until(deadline))
|
||||||
defer func() {
|
defer func() {
|
||||||
close(resultCh)
|
close(resultCh)
|
||||||
deadlineTimer.Stop()
|
deadlineTimer.Stop()
|
||||||
lifetimeTimer.UpdateSince(p.start)
|
lifetimeTimer.UpdateSince(p.start)
|
||||||
|
p.wg.Done()
|
||||||
}()
|
}()
|
||||||
for {
|
for {
|
||||||
idleStart := time.Now()
|
idleStart := time.Now()
|
||||||
select {
|
select {
|
||||||
|
case <-p.ctx.Done():
|
||||||
|
return
|
||||||
case <-deadlineTimer.C:
|
case <-deadlineTimer.C:
|
||||||
cccIdleTimer.UpdateSince(idleStart)
|
cccIdleTimer.UpdateSince(idleStart)
|
||||||
// note: currently we don't allow empty blocks, but if we ever do; make sure to CCC check it first
|
// note: currently we don't allow empty blocks, but if we ever do; make sure to CCC check it first
|
||||||
|
|
@ -345,7 +419,7 @@ func (p *Pipeline) cccStage(candidates <-chan *BlockCandidate, deadline time.Tim
|
||||||
var accRows *types.RowConsumption
|
var accRows *types.RowConsumption
|
||||||
var err error
|
var err error
|
||||||
if candidate != nil && p.ccc != nil {
|
if candidate != nil && p.ccc != nil {
|
||||||
accRows, err = p.ccc.ApplyTransaction(candidate.LastTrace)
|
accRows, err = p.ccc.ApplyTransactionRustTrace(candidate.RustTrace)
|
||||||
lastTxn := candidate.Txs[candidate.Txs.Len()-1]
|
lastTxn := candidate.Txs[candidate.Txs.Len()-1]
|
||||||
cccTimer.UpdateSince(cccStart)
|
cccTimer.UpdateSince(cccStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -427,3 +501,13 @@ func (p *Pipeline) traceAndApply(tx *types.Transaction) (*types.Receipt, *types.
|
||||||
}
|
}
|
||||||
return receipt, trace, nil
|
return receipt, trace, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// downstreamChCapacity returns the channel capacity that should be used for downstream channels.
|
||||||
|
// It aims to minimize stalls caused by different computational costs of different transactions
|
||||||
|
func (p *Pipeline) downstreamChCapacity() int {
|
||||||
|
cap := 1
|
||||||
|
if p.chain.Config().Scroll.MaxTxPerBlock != nil {
|
||||||
|
cap = *p.chain.Config().Scroll.MaxTxPerBlock
|
||||||
|
}
|
||||||
|
return cap
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue