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

Pullupstream/v0.5.12 #80

Merged
merged 15 commits into from
Feb 20, 2024
Merged
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
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ services:
zkevm-prover:
container_name: zkevm-prover
restart: unless-stopped
image: hermeznetwork/zkevm-prover:v4.0.4
image: hermeznetwork/zkevm-prover:v4.0.14
depends_on:
zkevm-state-db:
condition: service_healthy
Expand Down
6,722 changes: 5,131 additions & 1,591 deletions docs/diff/diff.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/diff/diff.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,4 @@ Add a test specific for DAC, this requires new containers configured in a way to

### Upstream Version

v0.5.10
v0.5.12
3 changes: 3 additions & 0 deletions event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const (
EventID_SynchronizerHalt EventID = "SYNCHRONIZER HALT"
// EventID_SequenceSenderHalt is triggered when the SequenceSender halts
EventID_SequenceSenderHalt EventID = "SEQUENCESENDER HALT"
// EventID_UnsupportedPrecompile is triggered when the executor returns an unsupported precompile error
EventID_UnsupportedPrecompile EventID = "UNSUPPORTED PRECOMPILE"

// EventID_NodeOOC is triggered when an OOC at node level is detected
EventID_NodeOOC EventID = "NODE OOC"
// Source_Node is the source of the event
Expand Down
2 changes: 1 addition & 1 deletion jsonrpc/endpoints_eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (e *EthEndpoints) Call(arg *types.TxArgs, blockArg *types.BlockNumberOrHash
result, err := e.state.ProcessUnsignedTransaction(ctx, tx, sender, blockToProcess, true, dbTx)
if err != nil {
errMsg := fmt.Sprintf("failed to execute the unsigned transaction: %v", err.Error())
logError := !executor.IsROMOutOfCountersError(executor.RomErrorCode(err)) && !errors.Is(err, runtime.ErrOutOfGas)
logError := !executor.IsROMOutOfCountersError(executor.RomErrorCode(err)) && !(errors.Is(err, runtime.ErrOutOfGas) || errors.Is(err, runtime.ErrExecutorErrorOOG2))
return RPCErrorResponse(types.DefaultErrorCode, errMsg, nil, logError)
}

Expand Down
4 changes: 2 additions & 2 deletions pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ func (p *Pool) preExecuteTx(ctx context.Context, tx types.Transaction) (preExecu
processBatchResponse, err := p.state.PreProcessTransaction(ctx, &tx, nil)
if err != nil {
isOOC := executor.IsROMOutOfCountersError(executor.RomErrorCode(err))
isOOG := errors.Is(err, runtime.ErrOutOfGas)
isOOG := errors.Is(err, runtime.ErrOutOfGas) || errors.Is(err, runtime.ErrExecutorErrorOOG2)
if !isOOC && !isOOG {
return response, err
} else {
Expand All @@ -331,7 +331,7 @@ func (p *Pool) preExecuteTx(ctx context.Context, tx types.Transaction) (preExecu
if executor.IsROMOutOfCountersError(executor.RomErrorCode(errorToCheck)) {
response.OOCError = err
}
if errors.Is(errorToCheck, runtime.ErrOutOfGas) {
if errors.Is(errorToCheck, runtime.ErrOutOfGas) || errors.Is(errorToCheck, runtime.ErrExecutorErrorOOG2) {
response.OOGError = err
}
} else {
Expand Down
15 changes: 15 additions & 0 deletions proto/src/proto/executor/v1/executor.proto
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ message ProcessBatchRequestV2 {
// prior to executing the call.
map<string, OverrideAccountV2> state_override = 23;
DebugV2 debug = 24;
uint64 execution_mode = 25;
}

message L1DataV2 {
Expand Down Expand Up @@ -854,4 +855,18 @@ enum ExecutorError {
EXECUTOR_ERROR_INVALID_L1_INFO_TREE_INDEX = 111;
// EXECUTOR_ERROR_INVALID_L1_INFO_TREE_SMT_PROOF_VALUE indicates that the ROM asked for an L1InfoTree SMT proof that was not present in the input
EXECUTOR_ERROR_INVALID_L1_INFO_TREE_SMT_PROOF_VALUE = 112;
// EXECUTOR_ERROR_INVALID_WITNESS indicates that the provided witness data is invalid
EXECUTOR_ERROR_INVALID_WITNESS = 113;
// EXECUTOR_ERROR_INVALID_CBOR indicates that the provided CBOR data is invalid
EXECUTOR_ERROR_INVALID_CBOR = 114;
// EXECUTOR_ERROR_INVALID_DATA_STREAM indicates that the provided data stream data is invalid
EXECUTOR_ERROR_INVALID_DATA_STREAM = 115;
// EXECUTOR_ERROR_INVALID_UPDATE_MERKLE_TREE indicates that the provided update merkle tree is invalid, e.g. because the executor is configured not to write to database
EXECUTOR_ERROR_INVALID_UPDATE_MERKLE_TREE = 116;
// EXECUTOR_ERROR_UNSUPPORTED_PRECOMPILED indicates that an unsupported precompiled has been used
EXECUTOR_ERROR_UNSUPPORTED_PRECOMPILED = 117;
// EXECUTOR_ERROR_OOG_2 indicates that an out of gas has occurred
EXECUTOR_ERROR_OOG_2 = 118;
// EXECUTOR_ERROR_CLOSE_BATCH indicates that batch must be closed
EXECUTOR_ERROR_CLOSE_BATCH = 119;
}
25 changes: 19 additions & 6 deletions sequencer/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package sequencer
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"

Expand All @@ -11,6 +12,8 @@ import (
"github.com/0xPolygonHermez/zkevm-node/sequencer/metrics"
"github.com/0xPolygonHermez/zkevm-node/state"
stateMetrics "github.com/0xPolygonHermez/zkevm-node/state/metrics"
"github.com/0xPolygonHermez/zkevm-node/state/runtime"
"github.com/0xPolygonHermez/zkevm-node/state/runtime/executor"
"github.com/ethereum/go-ethereum/common"
)

Expand Down Expand Up @@ -305,6 +308,11 @@ func (f *finalizer) openNewWIPBatch(ctx context.Context, batchNumber uint64, sta

// closeWIPBatch closes the current batch in the state
func (f *finalizer) closeWIPBatch(ctx context.Context) error {
// Sanity check: batch must not be empty (should have L2 blocks)
if f.wipBatch.isEmpty() {
f.Halt(ctx, fmt.Errorf("closing WIP batch %d without L2 blocks and should have at least 1", f.wipBatch.batchNumber), false)
}

usedResources := getUsedBatchResources(f.batchConstraints, f.wipBatch.imRemainingResources)
receipt := state.ProcessingReceipt{
BatchNumber: f.wipBatch.batchNumber,
Expand Down Expand Up @@ -346,12 +354,16 @@ func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initi

// Log batch detailed info
log.Errorf("batch %d sanity check error: initialStateRoot: %s, expectedNewStateRoot: %s", batch.BatchNumber, initialStateRoot, expectedNewStateRoot)
for i, rawL2block := range rawL2Blocks.Blocks {
log.Infof("block[%d], txs: %d, deltaTimestamp: %d, l1InfoTreeIndex: %d", i, len(rawL2block.Transactions), rawL2block.DeltaTimestamp, rawL2block.IndexL1InfoTree)
for j, rawTx := range rawL2block.Transactions {
log.Infof("block[%d].tx[%d]: %s, egpPct: %d", batch.BatchNumber, i, j, rawTx.Tx.Hash(), rawTx.EfficiencyPercentage)
batchLog := ""
totalTxs := 0
for blockIdx, rawL2block := range rawL2Blocks.Blocks {
totalTxs += len(rawL2block.Transactions)
batchLog += fmt.Sprintf("block[%d], txs: %d, deltaTimestamp: %d, l1InfoTreeIndex: %d\n", blockIdx, len(rawL2block.Transactions), rawL2block.DeltaTimestamp, rawL2block.IndexL1InfoTree)
for txIdx, rawTx := range rawL2block.Transactions {
batchLog += fmt.Sprintf(" tx[%d]: %s, egpPct: %d\n", txIdx, rawTx.Tx.Hash(), rawTx.EfficiencyPercentage)
}
}
log.Infof("DUMP batch %d, blocks: %d, txs: %d\n%s", batch.BatchNumber, len(rawL2Blocks.Blocks), totalTxs, batchLog)

f.Halt(ctx, fmt.Errorf("batch sanity check error. Check previous errors in logs to know which was the cause"), false)
}
Expand All @@ -371,14 +383,15 @@ func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initi

batchRequest := state.ProcessRequest{
BatchNumber: batch.BatchNumber,
L1InfoRoot_V2: mockL1InfoRoot,
L1InfoRoot_V2: state.GetMockL1InfoRoot(),
OldStateRoot: initialStateRoot,
Transactions: batch.BatchL2Data,
Coinbase: batch.Coinbase,
TimestampLimit_V2: uint64(time.Now().Unix()),
ForkID: f.stateIntf.GetForkIDByBatchNumber(batch.BatchNumber),
SkipVerifyL1InfoRoot_V2: true,
Caller: caller,
ExecutionMode: executor.ExecutionMode0,
}
batchRequest.L1InfoTreeData_V2, _, _, err = f.stateIntf.GetL1InfoTreeDataFromBatchL2Data(ctx, batch.BatchL2Data, nil)
if err != nil {
Expand All @@ -399,7 +412,7 @@ func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initi
return nil, ErrProcessBatch
}

if batchResponse.ExecutorError != nil {
if batchResponse.ExecutorError != nil && !errors.Is(batchResponse.ExecutorError, runtime.ErrExecutorErrorCloseBatch) {
log.Errorf("executor error when reprocessing batch %d, error: %v", batch.BatchNumber, batchResponse.ExecutorError)
reprocessError(batch)
return nil, ErrExecutorError
Expand Down
81 changes: 55 additions & 26 deletions sequencer/finalizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sequencer

import (
"context"
"encoding/json"
"errors"
"fmt"
"math/big"
Expand All @@ -28,8 +29,7 @@ const (
)

var (
now = time.Now
mockL1InfoRoot = common.Hash{}
now = time.Now
)

// finalizer represents the finalizer component of the sequencer.
Expand Down Expand Up @@ -138,11 +138,6 @@ func newFinalizer(

// Start starts the finalizer.
func (f *finalizer) Start(ctx context.Context) {
// Init mockL1InfoRoot to a mock value since it must be different to {0,0,...,0}
for i := 0; i < len(mockL1InfoRoot); i++ {
mockL1InfoRoot[i] = byte(i)
}

// Do sanity check for batches closed but pending to be checked
f.processBatchesPendingtoCheck(ctx)

Expand Down Expand Up @@ -283,14 +278,16 @@ func (f *finalizer) finalizeBatches(ctx context.Context) {
continue
}

closeWIPBatch := false
metrics.WorkerProcessingTime(time.Since(start))
if tx != nil {
showNotFoundTxLog = true

firstTxProcess := true

for {
_, err := f.processTransaction(ctx, tx, firstTxProcess)
var err error
_, closeWIPBatch, err = f.processTransaction(ctx, tx, firstTxProcess)
if err != nil {
if err == ErrEffectiveGasPriceReprocess {
firstTxProcess = false
Expand Down Expand Up @@ -325,7 +322,11 @@ func (f *finalizer) finalizeBatches(ctx context.Context) {
}

// Check if we must finalize the batch due to a closing reason (resources exhausted, max txs, timestamp resolution, forced batches deadline)
if finalize, closeReason := f.checkIfFinalizeBatch(); finalize {
finalize, closeReason := f.checkIfFinalizeBatch()
if closeWIPBatch || finalize {
if closeWIPBatch {
closeReason = "Executor close batch"
}
f.finalizeWIPBatch(ctx, closeReason)
}

Expand All @@ -337,7 +338,7 @@ func (f *finalizer) finalizeBatches(ctx context.Context) {
}

// processTransaction processes a single transaction.
func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, firstTxProcess bool) (errWg *sync.WaitGroup, err error) {
func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, firstTxProcess bool) (errWg *sync.WaitGroup, closeWIPBatch bool, err error) {
start := time.Now()
defer func() {
metrics.ProcessingTime(time.Since(start))
Expand All @@ -350,7 +351,7 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
BatchNumber: f.wipBatch.batchNumber,
OldStateRoot: f.wipBatch.imStateRoot,
Coinbase: f.wipBatch.coinbase,
L1InfoRoot_V2: mockL1InfoRoot,
L1InfoRoot_V2: state.GetMockL1InfoRoot(),
TimestampLimit_V2: f.wipL2Block.timestamp,
Caller: stateMetrics.SequencerCallerLabel,
ForkID: f.stateIntf.GetForkIDByBatchNumber(f.wipBatch.batchNumber),
Expand All @@ -359,6 +360,7 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
SkipWriteBlockInfoRoot_V2: true,
SkipVerifyL1InfoRoot_V2: true,
L1InfoTreeData_V2: map[uint32]state.L1DataV2{},
ExecutionMode: executor.ExecutionMode0,
}

txGasPrice := tx.GasPrice
Expand All @@ -380,7 +382,7 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
egp, err := f.effectiveGasPrice.CalculateEffectiveGasPrice(tx.RawTx, txGasPrice, tx.BatchResources.ZKCounters.GasUsed, tx.L1GasPrice, txL2GasPrice)
if err != nil {
if f.effectiveGasPrice.IsEnabled() {
return nil, err
return nil, false, err
} else {
log.Warnf("effectiveGasPrice is disabled, but failed to calculate effectiveGasPrice for tx %s, error: %v", tx.HashStr, err)
tx.EGPLog.Error = fmt.Sprintf("CalculateEffectiveGasPrice#1: %s", err)
Expand Down Expand Up @@ -408,7 +410,7 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
egpPercentage, err := f.effectiveGasPrice.CalculateEffectiveGasPricePercentage(txGasPrice, tx.EffectiveGasPrice)
if err != nil {
if f.effectiveGasPrice.IsEnabled() {
return nil, err
return nil, false, err
} else {
log.Warnf("effectiveGasPrice is disabled, but failed to to calculate efftive gas price percentage (#1), error: %v", err)
tx.EGPLog.Error = fmt.Sprintf("%s; CalculateEffectiveGasPricePercentage#1: %s", tx.EGPLog.Error, err)
Expand All @@ -428,7 +430,7 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first

effectivePercentageAsDecodedHex, err := hex.DecodeHex(fmt.Sprintf("%x", tx.EGPPercentage))
if err != nil {
return nil, err
return nil, false, err
}

batchRequest.Transactions = append(batchRequest.Transactions, effectivePercentageAsDecodedHex...)
Expand All @@ -437,12 +439,34 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first

if err != nil && (errors.Is(err, runtime.ErrExecutorDBError) || errors.Is(err, runtime.ErrInvalidTxChangeL2BlockMinTimestamp)) {
log.Errorf("failed to process tx %s, error: %v", tx.HashStr, err)
return nil, err
return nil, false, err
} else if err == nil && !batchResponse.IsRomLevelError && len(batchResponse.BlockResponses) == 0 {
err = fmt.Errorf("executor returned no errors and no responses for tx %s", tx.HashStr)
f.Halt(ctx, err, false)
} else if err != nil {
log.Errorf("error received from executor, error: %v", err)

if errors.Is(err, runtime.ErrExecutorErrorUnsupportedPrecompile) {
payload, err := json.Marshal(batchRequest)
if err != nil {
log.Errorf("error marshaling payload, error: %v", err)
} else {
event := &event.Event{
ReceivedAt: time.Now(),
Source: event.Source_Node,
Component: event.Component_Sequencer,
Level: event.Level_Warning,
EventID: event.EventID_UnsupportedPrecompile,
Description: string(payload),
Json: batchRequest,
}
err = f.eventLog.LogEvent(ctx, event)
if err != nil {
log.Errorf("error storing payload, error: %v", err)
}
}
}

// Delete tx from the worker
f.workerIntf.DeleteTx(tx.Hash, tx.From)

Expand All @@ -454,14 +478,15 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
} else {
metrics.TxProcessed(metrics.TxProcessedLabelInvalid, 1)
}
return nil, err
return nil, false, err
}

closeBatch := false
oldStateRoot := f.wipBatch.imStateRoot
if len(batchResponse.BlockResponses) > 0 {
errWg, err = f.handleProcessTransactionResponse(ctx, tx, batchResponse, oldStateRoot)
errWg, closeBatch, err = f.handleProcessTransactionResponse(ctx, tx, batchResponse, oldStateRoot)
if err != nil {
return errWg, err
return errWg, false, err
}
}

Expand All @@ -471,17 +496,17 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
log.Infof("processed tx %s, batchNumber: %d, l2Block: [%d], newStateRoot: %s, oldStateRoot: %s, used counters: %s",
tx.HashStr, batchRequest.BatchNumber, f.wipL2Block.trackingNum, batchResponse.NewStateRoot.String(), batchRequest.OldStateRoot.String(), f.logZKCounters(batchResponse.UsedZkCounters))

return nil, nil
return nil, closeBatch, nil
}

// handleProcessTransactionResponse handles the response of transaction processing.
func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *TxTracker, result *state.ProcessBatchResponse, oldStateRoot common.Hash) (errWg *sync.WaitGroup, err error) {
func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *TxTracker, result *state.ProcessBatchResponse, oldStateRoot common.Hash) (errWg *sync.WaitGroup, closeWIPBatch bool, err error) {
// Handle Transaction Error
errorCode := executor.RomErrorCode(result.BlockResponses[0].TransactionResponses[0].RomError)
if !state.IsStateRootChanged(errorCode) {
// If intrinsic error or OOC error, we skip adding the transaction to the batch
errWg = f.handleProcessTransactionError(ctx, result, tx)
return errWg, result.BlockResponses[0].TransactionResponses[0].RomError
return errWg, false, result.BlockResponses[0].TransactionResponses[0].RomError
}

egpEnabled := f.effectiveGasPrice.IsEnabled()
Expand All @@ -496,7 +521,7 @@ func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *Tx
if err != nil {
if egpEnabled {
log.Errorf("failed to calculate effective gas price with new gasUsed for tx %s, error: %v", tx.HashStr, err.Error())
return nil, err
return nil, false, err
} else {
log.Warnf("effectiveGasPrice is disabled, but failed to calculate effective gas price with new gasUsed for tx %s, error: %v", tx.HashStr, err.Error())
tx.EGPLog.Error = fmt.Sprintf("%s; CalculateEffectiveGasPrice#2: %s", tx.EGPLog.Error, err)
Expand All @@ -521,7 +546,7 @@ func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *Tx
}

if errCompare != nil && egpEnabled {
return nil, errCompare
return nil, false, errCompare
}
}
}
Expand Down Expand Up @@ -557,12 +582,12 @@ func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *Tx
log.Errorf("failed to update status to invalid in the pool for tx %s, error: %v", tx.Hash.String(), err)
}

return nil, ErrBatchResourceUnderFlow
return nil, false, ErrBatchResourceUnderFlow
} else {
start := time.Now()
f.workerIntf.UpdateTxZKCounters(result.BlockResponses[0].TransactionResponses[0].TxHash, tx.From, result.UsedZkCounters)
metrics.WorkerProcessingTime(time.Since(start))
return nil, ErrBatchResourceUnderFlow
return nil, false, ErrBatchResourceUnderFlow
}
}

Expand All @@ -583,7 +608,11 @@ func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *Tx

f.updateWorkerAfterSuccessfulProcessing(ctx, tx.Hash, tx.From, false, result)

return nil, nil
if result.CloseBatch_V2 {
return nil, true, nil
}

return nil, false, nil
}

// compareTxEffectiveGasPrice compares newEffectiveGasPrice with tx.EffectiveGasPrice.
Expand Down
Loading
Loading