From 8ffd1dc6ebe7bb8434f02a090fa75e9ae86be92e Mon Sep 17 00:00:00 2001 From: Joan Esteban <129153821+joanestebanr@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:42:04 +0100 Subject: [PATCH] Synchronizer accept forkids that are the same as in database (#3452) * #3451 accept same forkid from L1 * if same forkid recived and is the last one and same FromBatchNumber update blockNumber --- state/interfaces.go | 3 +- state/mocks/mock_storage.go | 82 +++- state/pgstatestorage/forkid.go | 23 +- state/pgstatestorage/pgstatestorage_test.go | 2 +- .../actions/incaberry/processor_l1_forkid.go | 162 +++++-- .../incaberry/processor_l1_forkid_test.go | 147 +++++++ .../mocks/state_full_interface.go | 50 +++ synchronizer/common/syncinterfaces/state.go | 1 + synchronizer/mocks/mock_dbtx.go | 410 +++++++++++++++++- test/Makefile | 2 +- 10 files changed, 822 insertions(+), 60 deletions(-) create mode 100644 synchronizer/actions/incaberry/processor_l1_forkid_test.go diff --git a/state/interfaces.go b/state/interfaces.go index 17264098be..bbd47d1ba5 100644 --- a/state/interfaces.go +++ b/state/interfaces.go @@ -121,7 +121,8 @@ type storage interface { GetBatchByForcedBatchNum(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (*Batch, error) AddForkID(ctx context.Context, forkID ForkIDInterval, dbTx pgx.Tx) error GetForkIDs(ctx context.Context, dbTx pgx.Tx) ([]ForkIDInterval, error) - UpdateForkID(ctx context.Context, forkID ForkIDInterval, dbTx pgx.Tx) error + UpdateForkIDToBatchNumber(ctx context.Context, forkID ForkIDInterval, dbTx pgx.Tx) error + UpdateForkIDBlockNumber(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx) error GetNativeBlockHashesInRange(ctx context.Context, fromBlock, toBlock uint64, dbTx pgx.Tx) ([]common.Hash, error) GetDSGenesisBlock(ctx context.Context, dbTx pgx.Tx) (*DSL2Block, error) GetDSBatches(ctx context.Context, firstBatchNumber, lastBatchNumber uint64, readWIPBatch bool, dbTx pgx.Tx) ([]*DSBatch, error) diff --git a/state/mocks/mock_storage.go b/state/mocks/mock_storage.go index b07d5de4cc..2574697028 100644 --- a/state/mocks/mock_storage.go +++ b/state/mocks/mock_storage.go @@ -8152,17 +8152,17 @@ func (_c *StorageMock_UpdateBatchL2Data_Call) RunAndReturn(run func(context.Cont return _c } -// UpdateForkID provides a mock function with given fields: ctx, forkID, dbTx -func (_m *StorageMock) UpdateForkID(ctx context.Context, forkID state.ForkIDInterval, dbTx pgx.Tx) error { - ret := _m.Called(ctx, forkID, dbTx) +// UpdateForkIDBlockNumber provides a mock function with given fields: ctx, forkdID, newBlockNumber, updateMemCache, dbTx +func (_m *StorageMock) UpdateForkIDBlockNumber(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx) error { + ret := _m.Called(ctx, forkdID, newBlockNumber, updateMemCache, dbTx) if len(ret) == 0 { - panic("no return value specified for UpdateForkID") + panic("no return value specified for UpdateForkIDBlockNumber") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, state.ForkIDInterval, pgx.Tx) error); ok { - r0 = rf(ctx, forkID, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, bool, pgx.Tx) error); ok { + r0 = rf(ctx, forkdID, newBlockNumber, updateMemCache, dbTx) } else { r0 = ret.Error(0) } @@ -8170,32 +8170,34 @@ func (_m *StorageMock) UpdateForkID(ctx context.Context, forkID state.ForkIDInte return r0 } -// StorageMock_UpdateForkID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateForkID' -type StorageMock_UpdateForkID_Call struct { +// StorageMock_UpdateForkIDBlockNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateForkIDBlockNumber' +type StorageMock_UpdateForkIDBlockNumber_Call struct { *mock.Call } -// UpdateForkID is a helper method to define mock.On call +// UpdateForkIDBlockNumber is a helper method to define mock.On call // - ctx context.Context -// - forkID state.ForkIDInterval +// - forkdID uint64 +// - newBlockNumber uint64 +// - updateMemCache bool // - dbTx pgx.Tx -func (_e *StorageMock_Expecter) UpdateForkID(ctx interface{}, forkID interface{}, dbTx interface{}) *StorageMock_UpdateForkID_Call { - return &StorageMock_UpdateForkID_Call{Call: _e.mock.On("UpdateForkID", ctx, forkID, dbTx)} +func (_e *StorageMock_Expecter) UpdateForkIDBlockNumber(ctx interface{}, forkdID interface{}, newBlockNumber interface{}, updateMemCache interface{}, dbTx interface{}) *StorageMock_UpdateForkIDBlockNumber_Call { + return &StorageMock_UpdateForkIDBlockNumber_Call{Call: _e.mock.On("UpdateForkIDBlockNumber", ctx, forkdID, newBlockNumber, updateMemCache, dbTx)} } -func (_c *StorageMock_UpdateForkID_Call) Run(run func(ctx context.Context, forkID state.ForkIDInterval, dbTx pgx.Tx)) *StorageMock_UpdateForkID_Call { +func (_c *StorageMock_UpdateForkIDBlockNumber_Call) Run(run func(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx)) *StorageMock_UpdateForkIDBlockNumber_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(state.ForkIDInterval), args[2].(pgx.Tx)) + run(args[0].(context.Context), args[1].(uint64), args[2].(uint64), args[3].(bool), args[4].(pgx.Tx)) }) return _c } -func (_c *StorageMock_UpdateForkID_Call) Return(_a0 error) *StorageMock_UpdateForkID_Call { +func (_c *StorageMock_UpdateForkIDBlockNumber_Call) Return(_a0 error) *StorageMock_UpdateForkIDBlockNumber_Call { _c.Call.Return(_a0) return _c } -func (_c *StorageMock_UpdateForkID_Call) RunAndReturn(run func(context.Context, state.ForkIDInterval, pgx.Tx) error) *StorageMock_UpdateForkID_Call { +func (_c *StorageMock_UpdateForkIDBlockNumber_Call) RunAndReturn(run func(context.Context, uint64, uint64, bool, pgx.Tx) error) *StorageMock_UpdateForkIDBlockNumber_Call { _c.Call.Return(run) return _c } @@ -8233,6 +8235,54 @@ func (_c *StorageMock_UpdateForkIDIntervalsInMemory_Call) RunAndReturn(run func( return _c } +// UpdateForkIDToBatchNumber provides a mock function with given fields: ctx, forkID, dbTx +func (_m *StorageMock) UpdateForkIDToBatchNumber(ctx context.Context, forkID state.ForkIDInterval, dbTx pgx.Tx) error { + ret := _m.Called(ctx, forkID, dbTx) + + if len(ret) == 0 { + panic("no return value specified for UpdateForkIDToBatchNumber") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, state.ForkIDInterval, pgx.Tx) error); ok { + r0 = rf(ctx, forkID, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// StorageMock_UpdateForkIDToBatchNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateForkIDToBatchNumber' +type StorageMock_UpdateForkIDToBatchNumber_Call struct { + *mock.Call +} + +// UpdateForkIDToBatchNumber is a helper method to define mock.On call +// - ctx context.Context +// - forkID state.ForkIDInterval +// - dbTx pgx.Tx +func (_e *StorageMock_Expecter) UpdateForkIDToBatchNumber(ctx interface{}, forkID interface{}, dbTx interface{}) *StorageMock_UpdateForkIDToBatchNumber_Call { + return &StorageMock_UpdateForkIDToBatchNumber_Call{Call: _e.mock.On("UpdateForkIDToBatchNumber", ctx, forkID, dbTx)} +} + +func (_c *StorageMock_UpdateForkIDToBatchNumber_Call) Run(run func(ctx context.Context, forkID state.ForkIDInterval, dbTx pgx.Tx)) *StorageMock_UpdateForkIDToBatchNumber_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(state.ForkIDInterval), args[2].(pgx.Tx)) + }) + return _c +} + +func (_c *StorageMock_UpdateForkIDToBatchNumber_Call) Return(_a0 error) *StorageMock_UpdateForkIDToBatchNumber_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *StorageMock_UpdateForkIDToBatchNumber_Call) RunAndReturn(run func(context.Context, state.ForkIDInterval, pgx.Tx) error) *StorageMock_UpdateForkIDToBatchNumber_Call { + _c.Call.Return(run) + return _c +} + // UpdateGERInOpenBatch provides a mock function with given fields: ctx, ger, dbTx func (_m *StorageMock) UpdateGERInOpenBatch(ctx context.Context, ger common.Hash, dbTx pgx.Tx) error { ret := _m.Called(ctx, ger, dbTx) diff --git a/state/pgstatestorage/forkid.go b/state/pgstatestorage/forkid.go index f31fc26f14..dbe865bc4f 100644 --- a/state/pgstatestorage/forkid.go +++ b/state/pgstatestorage/forkid.go @@ -51,7 +51,7 @@ func (p *PostgresStorage) GetForkIDs(ctx context.Context, dbTx pgx.Tx) ([]state. } // UpdateForkID updates the forkID stored in db -func (p *PostgresStorage) UpdateForkID(ctx context.Context, forkID state.ForkIDInterval, dbTx pgx.Tx) error { +func (p *PostgresStorage) UpdateForkIDToBatchNumber(ctx context.Context, forkID state.ForkIDInterval, dbTx pgx.Tx) error { const updateForkIDSQL = "UPDATE state.fork_id SET to_batch_num = $1 WHERE fork_id = $2" e := p.getExecQuerier(dbTx) if _, err := e.Exec(ctx, updateForkIDSQL, forkID.ToBatchNumber, forkID.ForkId); err != nil { @@ -60,6 +60,25 @@ func (p *PostgresStorage) UpdateForkID(ctx context.Context, forkID state.ForkIDI return nil } +// UpdateForkID updates the forkID stored in db +func (p *PostgresStorage) UpdateForkIDBlockNumber(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx) error { + const sql = "UPDATE state.fork_id SET block_num = $1 WHERE fork_id = $2" + e := p.getExecQuerier(dbTx) + if _, err := e.Exec(ctx, sql, forkdID, newBlockNumber); err != nil { + return err + } + if updateMemCache { + log.Debugf("Updating forkID %d in memory", forkdID) + forkIDs, err := p.GetForkIDs(ctx, dbTx) + if err != nil { + log.Error("error getting oldForkIDs. Error: ", err) + return err + } + p.UpdateForkIDIntervalsInMemory(forkIDs) + } + return nil +} + // UpdateForkIDIntervalsInMemory updates the forkID intervals in memory func (p *PostgresStorage) UpdateForkIDIntervalsInMemory(intervals []state.ForkIDInterval) { log.Infof("Updating forkIDs. Setting %d forkIDs", len(intervals)) @@ -88,7 +107,7 @@ func (p *PostgresStorage) AddForkIDInterval(ctx context.Context, newForkID state return err } forkIDs[len(forkIDs)-1].ToBatchNumber = newForkID.FromBatchNumber - 1 - err := p.UpdateForkID(ctx, forkIDs[len(forkIDs)-1], dbTx) + err := p.UpdateForkIDToBatchNumber(ctx, forkIDs[len(forkIDs)-1], dbTx) if err != nil { log.Errorf("error updating forkID: %d. Error: %v", forkIDs[len(forkIDs)-1].ForkId, err) return err diff --git a/state/pgstatestorage/pgstatestorage_test.go b/state/pgstatestorage/pgstatestorage_test.go index 08a9fe8a7a..29b7f67717 100644 --- a/state/pgstatestorage/pgstatestorage_test.go +++ b/state/pgstatestorage/pgstatestorage_test.go @@ -658,7 +658,7 @@ func TestForkIDs(t *testing.T) { require.Equal(t, forks[i].Version, forkId.Version) } forkID3.ToBatchNumber = 18446744073709551615 - err = testState.UpdateForkID(ctx, forkID3, dbTx) + err = testState.UpdateForkIDToBatchNumber(ctx, forkID3, dbTx) require.NoError(t, err) forkIDs, err = testState.GetForkIDs(ctx, dbTx) diff --git a/synchronizer/actions/incaberry/processor_l1_forkid.go b/synchronizer/actions/incaberry/processor_l1_forkid.go index 4e82cdce31..baeeff6d5e 100644 --- a/synchronizer/actions/incaberry/processor_l1_forkid.go +++ b/synchronizer/actions/incaberry/processor_l1_forkid.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "math" + "sort" "github.com/0xPolygonHermez/zkevm-node/etherman" "github.com/0xPolygonHermez/zkevm-node/log" @@ -18,6 +19,7 @@ type stateProcessorForkIdInterface interface { GetForkIDs(ctx context.Context, dbTx pgx.Tx) ([]state.ForkIDInterval, error) AddForkIDInterval(ctx context.Context, newForkID state.ForkIDInterval, dbTx pgx.Tx) error ResetForkID(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error + UpdateForkIDBlockNumber(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx) error } type syncProcessorForkIdInterface interface { @@ -44,9 +46,86 @@ func NewProcessorForkId(state stateProcessorForkIdInterface, sync syncProcessorF // Process process event func (p *ProcessorForkId) Process(ctx context.Context, order etherman.Order, l1Block *etherman.Block, dbTx pgx.Tx) error { + if l1Block == nil { + return errors.New("nil l1Block") + } + if len(l1Block.ForkIDs) <= order.Pos { + return fmt.Errorf("ForkIDsOrder index out of range. BlockNumber: %d, ForkIDsOrder index: %d", l1Block.BlockNumber, order.Pos) + } return p.processForkID(ctx, l1Block.ForkIDs[order.Pos], l1Block.BlockNumber, dbTx) } +func getForkdFromSlice(fIds []state.ForkIDInterval, forkId uint64) (bool, state.ForkIDInterval) { + if len(fIds) == 0 { + return false, state.ForkIDInterval{} + } + for _, f := range fIds { + if f.ForkId == forkId { + return true, f + } + } + return false, state.ForkIDInterval{} +} + +func isForksSameFromBatchNumber(f1, f2 state.ForkIDInterval) bool { + return f1.ForkId == f2.ForkId && f1.FromBatchNumber == f2.FromBatchNumber +} + +func isIncommingForkIdGreatestThanLastOne(incommingForkID state.ForkIDInterval, fIds []state.ForkIDInterval) bool { + if len(fIds) == 0 { + return true + } + last := lastForkID(fIds) + // Must be greater than the last one + return incommingForkID.ForkId > last +} + +func lastForkID(fIds []state.ForkIDInterval) uint64 { + if len(fIds) == 0 { + return 0 + } + sort.Slice(fIds, func(i, j int) bool { + return fIds[i].ForkId > fIds[j].ForkId + }) + return fIds[0].ForkId +} + +// return true if have been update or false if it's a new one +func (s *ProcessorForkId) updateForkIDIfNeeded(ctx context.Context, forkIDincomming state.ForkIDInterval, forkIDsInState []state.ForkIDInterval, dbTx pgx.Tx) (bool, error) { + found, dbForkID := getForkdFromSlice(forkIDsInState, forkIDincomming.ForkId) + if !found { + // Is a new forkid + return false, nil + } + if isForksSameFromBatchNumber(forkIDincomming, dbForkID) { + if forkIDincomming.BlockNumber != dbForkID.BlockNumber { + isLastForkId := lastForkID(forkIDsInState) == forkIDincomming.ForkId + log.Infof("ForkID: %d, received again: same fork_id but different blockNumber old: %d, new: %d", forkIDincomming.ForkId, dbForkID.BlockNumber, forkIDincomming.BlockNumber) + if isLastForkId { + log.Warnf("ForkID: %d is the last one in the state. Updating BlockNumber from %d to %d", forkIDincomming.ForkId, dbForkID.BlockNumber, forkIDincomming.BlockNumber) + err := s.state.UpdateForkIDBlockNumber(ctx, forkIDincomming.ForkId, forkIDincomming.BlockNumber, true, dbTx) + if err != nil { + log.Errorf("error updating forkID: %d blocknumber. Error: %v", forkIDincomming.ForkId, err) + return true, err + } + return true, nil + } + err := fmt.Errorf("ForkID: %d, already in the state but with different blockNumber and is not last ForkID, so can't update BlockNumber. DB ForkID: %+v. New ForkID: %+v", forkIDincomming.ForkId, dbForkID, forkIDincomming) + log.Error(err.Error()) + return true, err + } + log.Infof("ForkID: %d, already in the state. Skipping . ForkID: %+v.", forkIDincomming.ForkId, forkIDincomming) + return true, nil + } + err := fmt.Errorf("ForkID: %d, already in the state but with different starting BatchNumber. DB ForkID: %+v. New ForkID: %+v", forkIDincomming.ForkId, dbForkID, forkIDincomming) + log.Error(err.Error()) + return true, err +} + +func isForkIdAffectingOnlyFuturesBatches(fID state.ForkIDInterval, latestBatchNumber uint64) bool { + return latestBatchNumber < fID.FromBatchNumber +} + func (s *ProcessorForkId) processForkID(ctx context.Context, forkID etherman.ForkID, blockNumber uint64, dbTx pgx.Tx) error { fID := state.ForkIDInterval{ FromBatchNumber: forkID.BatchNumber + 1, @@ -55,74 +134,81 @@ func (s *ProcessorForkId) processForkID(ctx context.Context, forkID etherman.For Version: forkID.Version, BlockNumber: blockNumber, } - + debugPrefix := fmt.Sprintf("ForkID: %d, BlockNumber:%d, ", forkID.ForkID, blockNumber) // If forkID affects to a batch from the past. State must be reseted. - log.Debugf("ForkID: %d, synchronization must use the new forkID since batch: %d", forkID.ForkID, forkID.BatchNumber+1) + log.Debugf("%s synchronization must use the new forkID since batch: %d", debugPrefix, forkID.BatchNumber+1) fIds, err := s.state.GetForkIDs(ctx, dbTx) if err != nil { - log.Error("error getting ForkIDTrustedReorg. Error: ", err) - rollbackErr := dbTx.Rollback(ctx) - if rollbackErr != nil { - log.Errorf("error rolling back state get forkID trusted state. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) - return rollbackErr - } + log.Errorf("error getting forkIDs. Error: %v", err) return err } - if len(fIds) != 0 && fIds[len(fIds)-1].ForkId == fID.ForkId { // If the forkID reset was already done - return nil + isUpdate, err := s.updateForkIDIfNeeded(ctx, fID, fIds, dbTx) + if err != nil { + log.Errorf("%s error updating forkID . Error: %v", debugPrefix, err) + return err } + if isUpdate { + return nil // The calling function is doing the commit + } + + if !isIncommingForkIdGreatestThanLastOne(fID, fIds) { + err = fmt.Errorf("%s received don't fit sequence, last forkid:%d ", debugPrefix, lastForkID(fIds)) + log.Error(err.Error()) + return err + } + //If the forkID.batchnumber is a future batch latestBatchNumber, err := s.state.GetLastBatchNumber(ctx, dbTx) if err != nil && !errors.Is(err, state.ErrStateNotSynchronized) { - log.Error("error getting last batch number. Error: ", err) - rollbackErr := dbTx.Rollback(ctx) - if rollbackErr != nil { - log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) - return rollbackErr - } + log.Errorf("%s error getting last batch number. Error: %v", debugPrefix, err) return err } - // Add new forkID to the state + // Add new forkID to the state. This function take care of chaning previous ForkID ToBatchNumber err = s.state.AddForkIDInterval(ctx, fID, dbTx) if err != nil { - log.Error("error adding new forkID interval to the state. Error: ", err) - rollbackErr := dbTx.Rollback(ctx) - if rollbackErr != nil { - log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) - return rollbackErr - } + log.Errorf("%s error adding new forkID interval to state. Error: %v", debugPrefix, err) return err } - if latestBatchNumber <= forkID.BatchNumber || s.sync.IsTrustedSequencer() { //If the forkID will start in a future batch or isTrustedSequencer - log.Infof("Just adding forkID. Skipping reset forkID. ForkID: %+v.", fID) + if isForkIdAffectingOnlyFuturesBatches(fID, latestBatchNumber) { + log.Infof("%s Just adding forkID for future batches. Skipping reset forkID. ForkID: %+v.", debugPrefix, fID) return nil } - log.Info("ForkID received in the permissionless node that affects to a batch from the past") + if s.sync.IsTrustedSequencer() { //If the forkID will start in a future batch and IsTrustedSequencer + log.Warnf("%s received forkid that affects to a batch from the past %d, last Batch: %d. Is a trusted Node, so we accept it with no modifications", debugPrefix, fID.FromBatchNumber, latestBatchNumber) + return nil + } + + log.Warnf("%s received in the permissionless node that affects to a batch from the past %d, last Batch: %d. Reverting state", debugPrefix, fID.FromBatchNumber, latestBatchNumber) //Reset DB only if permissionless node - log.Debugf("ForkID: %d, Reverting synchronization to batch: %d", forkID.ForkID, forkID.BatchNumber+1) + log.Debugf("%s Reverting synchronization to batch: %d", debugPrefix, forkID.BatchNumber+1) err = s.state.ResetForkID(ctx, forkID.BatchNumber+1, dbTx) if err != nil { - log.Error("error resetting the state. Error: ", err) - rollbackErr := dbTx.Rollback(ctx) - if rollbackErr != nil { - log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) - return rollbackErr - } + log.Errorf("%s error resetting forkID. Error: %v", debugPrefix, err) return err } // Commit because it returns an error to force the resync - err = dbTx.Commit(ctx) + err = s.commit(ctx, debugPrefix, dbTx) + if err != nil { + log.Errorf("%s error committing forkId. Error: %v", debugPrefix, err) + return err + } + log.Infof("%s new ForkID detected, committed reverting state", debugPrefix) + + return fmt.Errorf("new ForkID detected, reseting synchronizarion") +} + +func (s *ProcessorForkId) commit(ctx context.Context, debugPrefix string, dbTx pgx.Tx) error { + err := dbTx.Commit(ctx) if err != nil { - log.Error("error committing the resetted state. Error: ", err) + log.Errorf("%s error committing forkId. Error: %s", debugPrefix, err.Error()) rollbackErr := dbTx.Rollback(ctx) if rollbackErr != nil { - log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + log.Errorf("%s error rolling back state to store block. rollbackErr: %s, error : %v", debugPrefix, rollbackErr.Error(), err) return rollbackErr } return err } - - return fmt.Errorf("new ForkID detected, reseting synchronizarion") + return nil } diff --git a/synchronizer/actions/incaberry/processor_l1_forkid_test.go b/synchronizer/actions/incaberry/processor_l1_forkid_test.go new file mode 100644 index 0000000000..ecaad1c6a7 --- /dev/null +++ b/synchronizer/actions/incaberry/processor_l1_forkid_test.go @@ -0,0 +1,147 @@ +package incaberry_test + +import ( + "context" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/etherman" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/synchronizer/actions/incaberry" + mock_syncinterfaces "github.com/0xPolygonHermez/zkevm-node/synchronizer/common/syncinterfaces/mocks" + syncMocks "github.com/0xPolygonHermez/zkevm-node/synchronizer/mocks" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +type mockForkdIdTest struct { + mockState *mock_syncinterfaces.StateFullInterface + mockSync *mock_syncinterfaces.SynchronizerIsTrustedSequencer + mockDbTx *syncMocks.DbTxMock +} + +func newMockForkdIdTest(t *testing.T) *mockForkdIdTest { + mockState := mock_syncinterfaces.NewStateFullInterface(t) + mockSync := mock_syncinterfaces.NewSynchronizerIsTrustedSequencer(t) + mockDbTx := syncMocks.NewDbTxMock(t) + return &mockForkdIdTest{mockState, mockSync, mockDbTx} +} + +func newL1Block(blockNumber uint64, forkId uint64, fromBatchNumber uint64, version string) *etherman.Block { + return ðerman.Block{ + SequencedBatches: [][]etherman.SequencedBatch{}, + BlockNumber: blockNumber, + ForkIDs: []etherman.ForkID{{ForkID: forkId, BatchNumber: fromBatchNumber, Version: version}}, + } +} + +func TestReceiveExistingForkIdAnotherFromBatchNumber(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 1, ToBatchNumber: 100, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 101, ToBatchNumber: 200, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(123, 6, 500, "1.0.0"), mocks.mockDbTx) + require.Error(t, err) +} + +func TestReceiveExistsForkIdSameBatchNumberSameBlockNumber(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 1, ToBatchNumber: 100, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 101, ToBatchNumber: 200, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(123, 6, 0, "1.0.0"), mocks.mockDbTx) + require.NoError(t, err) +} + +func TestReceiveExistsForkIdSameBatchNumberAnotherBlockNumberAndNotLastForkId(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 1, ToBatchNumber: 100, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 101, ToBatchNumber: 200, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + //mocks.mockDbTx.EXPECT().Rollback(mock.Anything).Return(nil) + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(456, 6, 0, "1.0.0"), mocks.mockDbTx) + require.Error(t, err) +} + +func TestReceiveAForkIdWithIdPreviousToCurrentOnState(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 100, ToBatchNumber: 200, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 201, ToBatchNumber: 300, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(456, 5, 0, "1.0.0"), mocks.mockDbTx) + require.Error(t, err) +} + +func TestReceiveExistsForkIdSameBatchNumberAnotherBlockNumberAndLastForkId(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 1, ToBatchNumber: 100, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 101, ToBatchNumber: 200, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + mocks.mockState.EXPECT().UpdateForkIDBlockNumber(mock.Anything, uint64(7), uint64(456), true, mock.Anything).Return(nil) + //mocks.mockDbTx.EXPECT().Commit(mock.Anything).Return(nil) + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(456, 7, 100, "1.0.0"), mocks.mockDbTx) + require.NoError(t, err) +} + +func TestReceiveNewForkIdAffectFutureBatch(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 1, ToBatchNumber: 100, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 101, ToBatchNumber: 200, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + mocks.mockState.EXPECT().GetLastBatchNumber(mock.Anything, mock.Anything).Return(uint64(101), nil) + mocks.mockState.EXPECT().AddForkIDInterval(mock.Anything, state.ForkIDInterval{FromBatchNumber: 102, ToBatchNumber: ^uint64(0), ForkId: 8, Version: "2.0.0", BlockNumber: 456}, mock.Anything).Return(nil) + //mocks.mockDbTx.EXPECT().Commit(mock.Anything).Return(nil) + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(456, 8, 101, "2.0.0"), mocks.mockDbTx) + require.NoError(t, err) +} + +func TestReceiveNewForkIdAffectPastBatchTrustedNode(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 1, ToBatchNumber: 100, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 101, ToBatchNumber: 200, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + mocks.mockState.EXPECT().GetLastBatchNumber(mock.Anything, mock.Anything).Return(uint64(101), nil) + mocks.mockState.EXPECT().AddForkIDInterval(mock.Anything, state.ForkIDInterval{FromBatchNumber: 101, ToBatchNumber: ^uint64(0), ForkId: 8, Version: "2.0.0", BlockNumber: 456}, mock.Anything).Return(nil) + mocks.mockSync.EXPECT().IsTrustedSequencer().Return(true) + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(456, 8, 100, "2.0.0"), mocks.mockDbTx) + require.NoError(t, err) +} + +func TestReceiveNewForkIdAffectPastBatchPermissionlessNode(t *testing.T) { + mocks := newMockForkdIdTest(t) + sut := incaberry.NewProcessorForkId(mocks.mockState, mocks.mockSync) + forkIdsOnState := []state.ForkIDInterval{ + {FromBatchNumber: 1, ToBatchNumber: 100, ForkId: 6, Version: "1.0.0", BlockNumber: 123}, + {FromBatchNumber: 101, ToBatchNumber: 200, ForkId: 7, Version: "1.0.0", BlockNumber: 123}, + } + mocks.mockState.EXPECT().GetForkIDs(mock.Anything, mock.Anything).Return(forkIdsOnState, nil) + mocks.mockState.EXPECT().GetLastBatchNumber(mock.Anything, mock.Anything).Return(uint64(101), nil) + mocks.mockState.EXPECT().AddForkIDInterval(mock.Anything, state.ForkIDInterval{FromBatchNumber: 101, ToBatchNumber: ^uint64(0), ForkId: 8, Version: "2.0.0", BlockNumber: 456}, mock.Anything).Return(nil) + mocks.mockSync.EXPECT().IsTrustedSequencer().Return(false) + mocks.mockState.EXPECT().ResetForkID(mock.Anything, uint64(101), mock.Anything).Return(nil) + mocks.mockDbTx.EXPECT().Commit(mock.Anything).Return(nil) + err := sut.Process(context.Background(), etherman.Order{Pos: 0}, newL1Block(456, 8, 100, "2.0.0"), mocks.mockDbTx) + require.Error(t, err) + require.Equal(t, "new ForkID detected, reseting synchronizarion", err.Error()) +} diff --git a/synchronizer/common/syncinterfaces/mocks/state_full_interface.go b/synchronizer/common/syncinterfaces/mocks/state_full_interface.go index aba0bf5db3..f41e906728 100644 --- a/synchronizer/common/syncinterfaces/mocks/state_full_interface.go +++ b/synchronizer/common/syncinterfaces/mocks/state_full_interface.go @@ -2715,6 +2715,56 @@ func (_c *StateFullInterface_UpdateBatchL2Data_Call) RunAndReturn(run func(conte return _c } +// UpdateForkIDBlockNumber provides a mock function with given fields: ctx, forkdID, newBlockNumber, updateMemCache, dbTx +func (_m *StateFullInterface) UpdateForkIDBlockNumber(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx) error { + ret := _m.Called(ctx, forkdID, newBlockNumber, updateMemCache, dbTx) + + if len(ret) == 0 { + panic("no return value specified for UpdateForkIDBlockNumber") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, bool, pgx.Tx) error); ok { + r0 = rf(ctx, forkdID, newBlockNumber, updateMemCache, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// StateFullInterface_UpdateForkIDBlockNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateForkIDBlockNumber' +type StateFullInterface_UpdateForkIDBlockNumber_Call struct { + *mock.Call +} + +// UpdateForkIDBlockNumber is a helper method to define mock.On call +// - ctx context.Context +// - forkdID uint64 +// - newBlockNumber uint64 +// - updateMemCache bool +// - dbTx pgx.Tx +func (_e *StateFullInterface_Expecter) UpdateForkIDBlockNumber(ctx interface{}, forkdID interface{}, newBlockNumber interface{}, updateMemCache interface{}, dbTx interface{}) *StateFullInterface_UpdateForkIDBlockNumber_Call { + return &StateFullInterface_UpdateForkIDBlockNumber_Call{Call: _e.mock.On("UpdateForkIDBlockNumber", ctx, forkdID, newBlockNumber, updateMemCache, dbTx)} +} + +func (_c *StateFullInterface_UpdateForkIDBlockNumber_Call) Run(run func(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx)) *StateFullInterface_UpdateForkIDBlockNumber_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(uint64), args[3].(bool), args[4].(pgx.Tx)) + }) + return _c +} + +func (_c *StateFullInterface_UpdateForkIDBlockNumber_Call) Return(_a0 error) *StateFullInterface_UpdateForkIDBlockNumber_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *StateFullInterface_UpdateForkIDBlockNumber_Call) RunAndReturn(run func(context.Context, uint64, uint64, bool, pgx.Tx) error) *StateFullInterface_UpdateForkIDBlockNumber_Call { + _c.Call.Return(run) + return _c +} + // UpdateWIPBatch provides a mock function with given fields: ctx, receipt, dbTx func (_m *StateFullInterface) UpdateWIPBatch(ctx context.Context, receipt state.ProcessingReceipt, dbTx pgx.Tx) error { ret := _m.Called(ctx, receipt, dbTx) diff --git a/synchronizer/common/syncinterfaces/state.go b/synchronizer/common/syncinterfaces/state.go index 54796fe1c2..2895eb0903 100644 --- a/synchronizer/common/syncinterfaces/state.go +++ b/synchronizer/common/syncinterfaces/state.go @@ -70,6 +70,7 @@ type StateFullInterface interface { GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*state.GlobalExitRoot, error) GetForkIDInMemory(forkId uint64) *state.ForkIDInterval GetLastL2BlockByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.L2Block, error) + UpdateForkIDBlockNumber(ctx context.Context, forkdID uint64, newBlockNumber uint64, updateMemCache bool, dbTx pgx.Tx) error GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) GetL2BlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*state.L2Block, error) } diff --git a/synchronizer/mocks/mock_dbtx.go b/synchronizer/mocks/mock_dbtx.go index f870cd5704..76dcc7e792 100644 --- a/synchronizer/mocks/mock_dbtx.go +++ b/synchronizer/mocks/mock_dbtx.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.39.0. DO NOT EDIT. +// Code generated by mockery. DO NOT EDIT. package mocks @@ -16,6 +16,14 @@ type DbTxMock struct { mock.Mock } +type DbTxMock_Expecter struct { + mock *mock.Mock +} + +func (_m *DbTxMock) EXPECT() *DbTxMock_Expecter { + return &DbTxMock_Expecter{mock: &_m.Mock} +} + // Begin provides a mock function with given fields: ctx func (_m *DbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { ret := _m.Called(ctx) @@ -46,6 +54,34 @@ func (_m *DbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { return r0, r1 } +// DbTxMock_Begin_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Begin' +type DbTxMock_Begin_Call struct { + *mock.Call +} + +// Begin is a helper method to define mock.On call +// - ctx context.Context +func (_e *DbTxMock_Expecter) Begin(ctx interface{}) *DbTxMock_Begin_Call { + return &DbTxMock_Begin_Call{Call: _e.mock.On("Begin", ctx)} +} + +func (_c *DbTxMock_Begin_Call) Run(run func(ctx context.Context)) *DbTxMock_Begin_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *DbTxMock_Begin_Call) Return(_a0 pgx.Tx, _a1 error) *DbTxMock_Begin_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DbTxMock_Begin_Call) RunAndReturn(run func(context.Context) (pgx.Tx, error)) *DbTxMock_Begin_Call { + _c.Call.Return(run) + return _c +} + // BeginFunc provides a mock function with given fields: ctx, f func (_m *DbTxMock) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { ret := _m.Called(ctx, f) @@ -64,6 +100,35 @@ func (_m *DbTxMock) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { return r0 } +// DbTxMock_BeginFunc_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BeginFunc' +type DbTxMock_BeginFunc_Call struct { + *mock.Call +} + +// BeginFunc is a helper method to define mock.On call +// - ctx context.Context +// - f func(pgx.Tx) error +func (_e *DbTxMock_Expecter) BeginFunc(ctx interface{}, f interface{}) *DbTxMock_BeginFunc_Call { + return &DbTxMock_BeginFunc_Call{Call: _e.mock.On("BeginFunc", ctx, f)} +} + +func (_c *DbTxMock_BeginFunc_Call) Run(run func(ctx context.Context, f func(pgx.Tx) error)) *DbTxMock_BeginFunc_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(func(pgx.Tx) error)) + }) + return _c +} + +func (_c *DbTxMock_BeginFunc_Call) Return(err error) *DbTxMock_BeginFunc_Call { + _c.Call.Return(err) + return _c +} + +func (_c *DbTxMock_BeginFunc_Call) RunAndReturn(run func(context.Context, func(pgx.Tx) error) error) *DbTxMock_BeginFunc_Call { + _c.Call.Return(run) + return _c +} + // Commit provides a mock function with given fields: ctx func (_m *DbTxMock) Commit(ctx context.Context) error { ret := _m.Called(ctx) @@ -82,6 +147,34 @@ func (_m *DbTxMock) Commit(ctx context.Context) error { return r0 } +// DbTxMock_Commit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Commit' +type DbTxMock_Commit_Call struct { + *mock.Call +} + +// Commit is a helper method to define mock.On call +// - ctx context.Context +func (_e *DbTxMock_Expecter) Commit(ctx interface{}) *DbTxMock_Commit_Call { + return &DbTxMock_Commit_Call{Call: _e.mock.On("Commit", ctx)} +} + +func (_c *DbTxMock_Commit_Call) Run(run func(ctx context.Context)) *DbTxMock_Commit_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *DbTxMock_Commit_Call) Return(_a0 error) *DbTxMock_Commit_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DbTxMock_Commit_Call) RunAndReturn(run func(context.Context) error) *DbTxMock_Commit_Call { + _c.Call.Return(run) + return _c +} + // Conn provides a mock function with given fields: func (_m *DbTxMock) Conn() *pgx.Conn { ret := _m.Called() @@ -102,6 +195,33 @@ func (_m *DbTxMock) Conn() *pgx.Conn { return r0 } +// DbTxMock_Conn_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Conn' +type DbTxMock_Conn_Call struct { + *mock.Call +} + +// Conn is a helper method to define mock.On call +func (_e *DbTxMock_Expecter) Conn() *DbTxMock_Conn_Call { + return &DbTxMock_Conn_Call{Call: _e.mock.On("Conn")} +} + +func (_c *DbTxMock_Conn_Call) Run(run func()) *DbTxMock_Conn_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *DbTxMock_Conn_Call) Return(_a0 *pgx.Conn) *DbTxMock_Conn_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DbTxMock_Conn_Call) RunAndReturn(run func() *pgx.Conn) *DbTxMock_Conn_Call { + _c.Call.Return(run) + return _c +} + // CopyFrom provides a mock function with given fields: ctx, tableName, columnNames, rowSrc func (_m *DbTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) { ret := _m.Called(ctx, tableName, columnNames, rowSrc) @@ -130,6 +250,37 @@ func (_m *DbTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, colu return r0, r1 } +// DbTxMock_CopyFrom_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CopyFrom' +type DbTxMock_CopyFrom_Call struct { + *mock.Call +} + +// CopyFrom is a helper method to define mock.On call +// - ctx context.Context +// - tableName pgx.Identifier +// - columnNames []string +// - rowSrc pgx.CopyFromSource +func (_e *DbTxMock_Expecter) CopyFrom(ctx interface{}, tableName interface{}, columnNames interface{}, rowSrc interface{}) *DbTxMock_CopyFrom_Call { + return &DbTxMock_CopyFrom_Call{Call: _e.mock.On("CopyFrom", ctx, tableName, columnNames, rowSrc)} +} + +func (_c *DbTxMock_CopyFrom_Call) Run(run func(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource)) *DbTxMock_CopyFrom_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(pgx.Identifier), args[2].([]string), args[3].(pgx.CopyFromSource)) + }) + return _c +} + +func (_c *DbTxMock_CopyFrom_Call) Return(_a0 int64, _a1 error) *DbTxMock_CopyFrom_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DbTxMock_CopyFrom_Call) RunAndReturn(run func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) (int64, error)) *DbTxMock_CopyFrom_Call { + _c.Call.Return(run) + return _c +} + // Exec provides a mock function with given fields: ctx, sql, arguments func (_m *DbTxMock) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error) { var _ca []interface{} @@ -163,6 +314,43 @@ func (_m *DbTxMock) Exec(ctx context.Context, sql string, arguments ...interface return r0, r1 } +// DbTxMock_Exec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Exec' +type DbTxMock_Exec_Call struct { + *mock.Call +} + +// Exec is a helper method to define mock.On call +// - ctx context.Context +// - sql string +// - arguments ...interface{} +func (_e *DbTxMock_Expecter) Exec(ctx interface{}, sql interface{}, arguments ...interface{}) *DbTxMock_Exec_Call { + return &DbTxMock_Exec_Call{Call: _e.mock.On("Exec", + append([]interface{}{ctx, sql}, arguments...)...)} +} + +func (_c *DbTxMock_Exec_Call) Run(run func(ctx context.Context, sql string, arguments ...interface{})) *DbTxMock_Exec_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(context.Context), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *DbTxMock_Exec_Call) Return(commandTag pgconn.CommandTag, err error) *DbTxMock_Exec_Call { + _c.Call.Return(commandTag, err) + return _c +} + +func (_c *DbTxMock_Exec_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (pgconn.CommandTag, error)) *DbTxMock_Exec_Call { + _c.Call.Return(run) + return _c +} + // LargeObjects provides a mock function with given fields: func (_m *DbTxMock) LargeObjects() pgx.LargeObjects { ret := _m.Called() @@ -181,6 +369,33 @@ func (_m *DbTxMock) LargeObjects() pgx.LargeObjects { return r0 } +// DbTxMock_LargeObjects_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LargeObjects' +type DbTxMock_LargeObjects_Call struct { + *mock.Call +} + +// LargeObjects is a helper method to define mock.On call +func (_e *DbTxMock_Expecter) LargeObjects() *DbTxMock_LargeObjects_Call { + return &DbTxMock_LargeObjects_Call{Call: _e.mock.On("LargeObjects")} +} + +func (_c *DbTxMock_LargeObjects_Call) Run(run func()) *DbTxMock_LargeObjects_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *DbTxMock_LargeObjects_Call) Return(_a0 pgx.LargeObjects) *DbTxMock_LargeObjects_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DbTxMock_LargeObjects_Call) RunAndReturn(run func() pgx.LargeObjects) *DbTxMock_LargeObjects_Call { + _c.Call.Return(run) + return _c +} + // Prepare provides a mock function with given fields: ctx, name, sql func (_m *DbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgconn.StatementDescription, error) { ret := _m.Called(ctx, name, sql) @@ -211,6 +426,36 @@ func (_m *DbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgco return r0, r1 } +// DbTxMock_Prepare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Prepare' +type DbTxMock_Prepare_Call struct { + *mock.Call +} + +// Prepare is a helper method to define mock.On call +// - ctx context.Context +// - name string +// - sql string +func (_e *DbTxMock_Expecter) Prepare(ctx interface{}, name interface{}, sql interface{}) *DbTxMock_Prepare_Call { + return &DbTxMock_Prepare_Call{Call: _e.mock.On("Prepare", ctx, name, sql)} +} + +func (_c *DbTxMock_Prepare_Call) Run(run func(ctx context.Context, name string, sql string)) *DbTxMock_Prepare_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string)) + }) + return _c +} + +func (_c *DbTxMock_Prepare_Call) Return(_a0 *pgconn.StatementDescription, _a1 error) *DbTxMock_Prepare_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DbTxMock_Prepare_Call) RunAndReturn(run func(context.Context, string, string) (*pgconn.StatementDescription, error)) *DbTxMock_Prepare_Call { + _c.Call.Return(run) + return _c +} + // Query provides a mock function with given fields: ctx, sql, args func (_m *DbTxMock) Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error) { var _ca []interface{} @@ -244,6 +489,43 @@ func (_m *DbTxMock) Query(ctx context.Context, sql string, args ...interface{}) return r0, r1 } +// DbTxMock_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' +type DbTxMock_Query_Call struct { + *mock.Call +} + +// Query is a helper method to define mock.On call +// - ctx context.Context +// - sql string +// - args ...interface{} +func (_e *DbTxMock_Expecter) Query(ctx interface{}, sql interface{}, args ...interface{}) *DbTxMock_Query_Call { + return &DbTxMock_Query_Call{Call: _e.mock.On("Query", + append([]interface{}{ctx, sql}, args...)...)} +} + +func (_c *DbTxMock_Query_Call) Run(run func(ctx context.Context, sql string, args ...interface{})) *DbTxMock_Query_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(context.Context), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *DbTxMock_Query_Call) Return(_a0 pgx.Rows, _a1 error) *DbTxMock_Query_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DbTxMock_Query_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (pgx.Rows, error)) *DbTxMock_Query_Call { + _c.Call.Return(run) + return _c +} + // QueryFunc provides a mock function with given fields: ctx, sql, args, scans, f func (_m *DbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{}, scans []interface{}, f func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error) { ret := _m.Called(ctx, sql, args, scans, f) @@ -274,6 +556,38 @@ func (_m *DbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{ return r0, r1 } +// DbTxMock_QueryFunc_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryFunc' +type DbTxMock_QueryFunc_Call struct { + *mock.Call +} + +// QueryFunc is a helper method to define mock.On call +// - ctx context.Context +// - sql string +// - args []interface{} +// - scans []interface{} +// - f func(pgx.QueryFuncRow) error +func (_e *DbTxMock_Expecter) QueryFunc(ctx interface{}, sql interface{}, args interface{}, scans interface{}, f interface{}) *DbTxMock_QueryFunc_Call { + return &DbTxMock_QueryFunc_Call{Call: _e.mock.On("QueryFunc", ctx, sql, args, scans, f)} +} + +func (_c *DbTxMock_QueryFunc_Call) Run(run func(ctx context.Context, sql string, args []interface{}, scans []interface{}, f func(pgx.QueryFuncRow) error)) *DbTxMock_QueryFunc_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].([]interface{}), args[3].([]interface{}), args[4].(func(pgx.QueryFuncRow) error)) + }) + return _c +} + +func (_c *DbTxMock_QueryFunc_Call) Return(_a0 pgconn.CommandTag, _a1 error) *DbTxMock_QueryFunc_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DbTxMock_QueryFunc_Call) RunAndReturn(run func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error)) *DbTxMock_QueryFunc_Call { + _c.Call.Return(run) + return _c +} + // QueryRow provides a mock function with given fields: ctx, sql, args func (_m *DbTxMock) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row { var _ca []interface{} @@ -297,6 +611,43 @@ func (_m *DbTxMock) QueryRow(ctx context.Context, sql string, args ...interface{ return r0 } +// DbTxMock_QueryRow_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryRow' +type DbTxMock_QueryRow_Call struct { + *mock.Call +} + +// QueryRow is a helper method to define mock.On call +// - ctx context.Context +// - sql string +// - args ...interface{} +func (_e *DbTxMock_Expecter) QueryRow(ctx interface{}, sql interface{}, args ...interface{}) *DbTxMock_QueryRow_Call { + return &DbTxMock_QueryRow_Call{Call: _e.mock.On("QueryRow", + append([]interface{}{ctx, sql}, args...)...)} +} + +func (_c *DbTxMock_QueryRow_Call) Run(run func(ctx context.Context, sql string, args ...interface{})) *DbTxMock_QueryRow_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(context.Context), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *DbTxMock_QueryRow_Call) Return(_a0 pgx.Row) *DbTxMock_QueryRow_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DbTxMock_QueryRow_Call) RunAndReturn(run func(context.Context, string, ...interface{}) pgx.Row) *DbTxMock_QueryRow_Call { + _c.Call.Return(run) + return _c +} + // Rollback provides a mock function with given fields: ctx func (_m *DbTxMock) Rollback(ctx context.Context) error { ret := _m.Called(ctx) @@ -315,6 +666,34 @@ func (_m *DbTxMock) Rollback(ctx context.Context) error { return r0 } +// DbTxMock_Rollback_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Rollback' +type DbTxMock_Rollback_Call struct { + *mock.Call +} + +// Rollback is a helper method to define mock.On call +// - ctx context.Context +func (_e *DbTxMock_Expecter) Rollback(ctx interface{}) *DbTxMock_Rollback_Call { + return &DbTxMock_Rollback_Call{Call: _e.mock.On("Rollback", ctx)} +} + +func (_c *DbTxMock_Rollback_Call) Run(run func(ctx context.Context)) *DbTxMock_Rollback_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *DbTxMock_Rollback_Call) Return(_a0 error) *DbTxMock_Rollback_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DbTxMock_Rollback_Call) RunAndReturn(run func(context.Context) error) *DbTxMock_Rollback_Call { + _c.Call.Return(run) + return _c +} + // SendBatch provides a mock function with given fields: ctx, b func (_m *DbTxMock) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { ret := _m.Called(ctx, b) @@ -335,6 +714,35 @@ func (_m *DbTxMock) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResult return r0 } +// DbTxMock_SendBatch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendBatch' +type DbTxMock_SendBatch_Call struct { + *mock.Call +} + +// SendBatch is a helper method to define mock.On call +// - ctx context.Context +// - b *pgx.Batch +func (_e *DbTxMock_Expecter) SendBatch(ctx interface{}, b interface{}) *DbTxMock_SendBatch_Call { + return &DbTxMock_SendBatch_Call{Call: _e.mock.On("SendBatch", ctx, b)} +} + +func (_c *DbTxMock_SendBatch_Call) Run(run func(ctx context.Context, b *pgx.Batch)) *DbTxMock_SendBatch_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pgx.Batch)) + }) + return _c +} + +func (_c *DbTxMock_SendBatch_Call) Return(_a0 pgx.BatchResults) *DbTxMock_SendBatch_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DbTxMock_SendBatch_Call) RunAndReturn(run func(context.Context, *pgx.Batch) pgx.BatchResults) *DbTxMock_SendBatch_Call { + _c.Call.Return(run) + return _c +} + // NewDbTxMock creates a new instance of DbTxMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewDbTxMock(t interface { diff --git a/test/Makefile b/test/Makefile index c43d56b4c9..7b6df67f6d 100644 --- a/test/Makefile +++ b/test/Makefile @@ -709,7 +709,7 @@ generate-mocks-synchronizer: ## Generates mocks for synchronizer , using mockery - export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=../synchronizer/mocks --structname=DbTxMock --filename=mock_dbtx.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=../synchronizer/mocks --structname=DbTxMock --filename=mock_dbtx.go ${COMMON_MOCKERY_PARAMS} .PHONY: generate-mocks-etherman generate-mocks-etherman: ## Generates mocks for etherman , using mockery tool