Skip to content

Commit

Permalink
Pullupstream/v0.5.12 (#80)
Browse files Browse the repository at this point in the history
* check unsupported precompiles  (0xPolygonHermez#3264)

* check unsupported precompiles

* downgrade prover

* restore solc version

* update SC

* new errors

* fix as workaround to close batch on tx oog (0xPolygonHermez#3271)

Co-authored-by: agnusmor <agnusmor@gmail.com>

* handle executor close batch

* added sanity check closing an empty batch

* change log

---------

Co-authored-by: agnusmor <agnusmor@gmail.com>

* fix RPC closebatch executor error (0xPolygonHermez#3272)

* fix RPC closebatch executor error

* fix close batch

* fix close batch

* fix close batch

* fix close batch

* fix close batch

---------

Co-authored-by: agnusmor <agnusmor@gmail.com>

* fix executor error closebatch (0xPolygonHermez#3276)

* fix executor error closebatch

* fix linter

---------

Co-authored-by: agnusmor <agnusmor@gmail.com>

* add oog2 checks for all the oog cheks (0xPolygonHermez#3277)

* fix oog2 in internal gas estimation (0xPolygonHermez#3280)

* fix oog2

* fix oog2 for estimateGas

---------

Co-authored-by: tclemos <thiago@polygon.technology>

* execution mode (0xPolygonHermez#3285)

* execution mode

* execution mode

* execution mode

* update prover image (0xPolygonHermez#3286)

* fix log when error on batch sanity check (0xPolygonHermez#3287)

* update prover image to v4.0.13 (0xPolygonHermez#3289)

* update prover image (0xPolygonHermez#3290)

* fix deltaTimestamp when debug tx (0xPolygonHermez#3291)

* fix deltaTimestamp when debug tx

* fix deltaTimeStamp for unsigned txs execution for specific block

* fix deltaTimeStamp for unsigned txs execution for specific block

* Revert "fix deltaTimeStamp for unsigned txs execution for specific block"

This reverts commit eb77e04.

* Revert "fix deltaTimeStamp for unsigned txs execution for specific block"

This reverts commit d2cfa78.

* fix debug trace l1 info tree index and add l1 info tree data

* move MockL1InfoRoot from sequencer to state to allow multiple components to use the same value

---------

Co-authored-by: agnusmor <agnusmor@gmail.com>

* fix checkStateInconsistency when starting sequencer (0xPolygonHermez#3294)

* disable delete addrQueue if empty as a workaround (0xPolygonHermez#3295)

* update docs

---------

Co-authored-by: Toni Ramírez <58293609+ToniRamirezM@users.noreply.github.com>
Co-authored-by: agnusmor <agnusmor@gmail.com>
Co-authored-by: Joan Esteban <129153821+joanestebanr@users.noreply.github.com>
Co-authored-by: Thiago Coimbra Lemos <tclemos@users.noreply.github.com>
Co-authored-by: tclemos <thiago@polygon.technology>
Co-authored-by: agnusmor <100322135+agnusmor@users.noreply.github.com>
  • Loading branch information
7 people authored Feb 20, 2024
1 parent 3bf50ba commit 023710f
Show file tree
Hide file tree
Showing 32 changed files with 6,364 additions and 2,398 deletions.
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

0 comments on commit 023710f

Please sign in to comment.