From e2fdb65a6727d13aaa268d24ceeebf3f6b04daa1 Mon Sep 17 00:00:00 2001 From: tclemos Date: Mon, 5 Feb 2024 14:57:39 -0300 Subject: [PATCH 1/2] allow GetL2TxHashByTxHash to return null for txs prior to Etrog --- jsonrpc/endpoints_eth.go | 6 +-- jsonrpc/endpoints_zkevm.go | 4 +- jsonrpc/mocks/mock_state.go | 10 ++--- jsonrpc/types/interfaces.go | 2 +- jsonrpc/types/types.go | 4 +- state/interfaces.go | 2 +- state/mocks/mock_storage.go | 63 ++++------------------------- state/pgstatestorage/transaction.go | 16 +++++--- 8 files changed, 31 insertions(+), 76 deletions(-) diff --git a/jsonrpc/endpoints_eth.go b/jsonrpc/endpoints_eth.go index a8b403a723..4d9ffe0270 100644 --- a/jsonrpc/endpoints_eth.go +++ b/jsonrpc/endpoints_eth.go @@ -586,7 +586,7 @@ func (e *EthEndpoints) GetTransactionByBlockHashAndIndex(hash types.ArgHash, ind if err != nil { return RPCErrorResponse(types.DefaultErrorCode, "failed to get l2 transaction hash", err, true) } - l2Hash = &l2h + l2Hash = l2h } res, err := types.NewTransaction(*tx, receipt, false, l2Hash) @@ -628,7 +628,7 @@ func (e *EthEndpoints) GetTransactionByBlockNumberAndIndex(number *types.BlockNu if err != nil { return RPCErrorResponse(types.DefaultErrorCode, "failed to get l2 transaction hash", err, true) } - l2Hash = &l2h + l2Hash = l2h } res, err := types.NewTransaction(*tx, receipt, false, l2Hash) @@ -662,7 +662,7 @@ func (e *EthEndpoints) GetTransactionByHash(hash types.ArgHash, includeExtraInfo if err != nil { return RPCErrorResponse(types.DefaultErrorCode, "failed to get l2 transaction hash", err, true) } - l2Hash = &l2h + l2Hash = l2h } res, err := types.NewTransaction(*tx, receipt, false, l2Hash) diff --git a/jsonrpc/endpoints_zkevm.go b/jsonrpc/endpoints_zkevm.go index 8fffa106a9..ab82cc476f 100644 --- a/jsonrpc/endpoints_zkevm.go +++ b/jsonrpc/endpoints_zkevm.go @@ -329,7 +329,7 @@ func (z *ZKEVMEndpoints) GetTransactionByL2Hash(hash types.ArgHash) (interface{} return RPCErrorResponse(types.DefaultErrorCode, "failed to get l2 transaction hash", err, true) } - res, err := types.NewTransaction(*tx, receipt, false, &l2Hash) + res, err := types.NewTransaction(*tx, receipt, false, l2Hash) if err != nil { return RPCErrorResponse(types.DefaultErrorCode, "failed to build transaction response", err, true) } @@ -381,7 +381,7 @@ func (z *ZKEVMEndpoints) GetTransactionReceiptByL2Hash(hash types.ArgHash) (inte return RPCErrorResponse(types.DefaultErrorCode, "failed to get l2 transaction hash", err, true) } - receipt, err := types.NewReceipt(*tx, r, &l2Hash) + receipt, err := types.NewReceipt(*tx, r, l2Hash) if err != nil { return RPCErrorResponse(types.DefaultErrorCode, "failed to build the receipt response", err, true) } diff --git a/jsonrpc/mocks/mock_state.go b/jsonrpc/mocks/mock_state.go index a01634ace7..daac411aa3 100644 --- a/jsonrpc/mocks/mock_state.go +++ b/jsonrpc/mocks/mock_state.go @@ -508,23 +508,23 @@ func (_m *StateMock) GetL2BlocksByBatchNumber(ctx context.Context, batchNumber u } // GetL2TxHashByTxHash provides a mock function with given fields: ctx, hash, dbTx -func (_m *StateMock) GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (common.Hash, error) { +func (_m *StateMock) GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*common.Hash, error) { ret := _m.Called(ctx, hash, dbTx) if len(ret) == 0 { panic("no return value specified for GetL2TxHashByTxHash") } - var r0 common.Hash + var r0 *common.Hash var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (common.Hash, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (*common.Hash, error)); ok { return rf(ctx, hash, dbTx) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) common.Hash); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *common.Hash); ok { r0 = rf(ctx, hash, dbTx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Hash) + r0 = ret.Get(0).(*common.Hash) } } diff --git a/jsonrpc/types/interfaces.go b/jsonrpc/types/interfaces.go index 651034bba2..3485eeef0f 100644 --- a/jsonrpc/types/interfaces.go +++ b/jsonrpc/types/interfaces.go @@ -75,7 +75,7 @@ type StateInterface interface { GetLastVerifiedBatchNumberUntilL1Block(ctx context.Context, l1BlockNumber uint64, dbTx pgx.Tx) (uint64, error) GetBatchTimestamp(ctx context.Context, batchNumber uint64, forcedForkId *uint64, dbTx pgx.Tx) (*time.Time, error) GetLatestBatchGlobalExitRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) - GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (common.Hash, error) + GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*common.Hash, error) } // EthermanInterface provides integration with L1 diff --git a/jsonrpc/types/types.go b/jsonrpc/types/types.go index 8f3745c7b7..0c3bec6db9 100644 --- a/jsonrpc/types/types.go +++ b/jsonrpc/types/types.go @@ -329,7 +329,7 @@ func NewBlock(ctx context.Context, st StateInterface, hash *common.Hash, b *stat if err != nil { return nil, err } - l2Hash = &l2h + l2Hash = l2h } rpcTx, err := NewTransaction(*tx, receiptPtr, includeReceipts, l2Hash) @@ -422,7 +422,7 @@ func NewBatch(ctx context.Context, st StateInterface, batch *state.Batch, virtua if err != nil { return nil, err } - rpcTx, err := NewTransaction(tx, receiptPtr, includeReceipts, &l2Hash) + rpcTx, err := NewTransaction(tx, receiptPtr, includeReceipts, l2Hash) if err != nil { return nil, err } diff --git a/state/interfaces.go b/state/interfaces.go index 871f2e702d..d677d510fe 100644 --- a/state/interfaces.go +++ b/state/interfaces.go @@ -149,7 +149,7 @@ type storage interface { GetVirtualBatchParentHash(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (common.Hash, error) GetForcedBatchParentHash(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (common.Hash, error) GetLatestBatchGlobalExitRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) - GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (common.Hash, error) + GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*common.Hash, error) GetSyncInfoData(ctx context.Context, dbTx pgx.Tx) (SyncInfoDataOnStorage, error) GetFirstL2BlockNumberForBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (uint64, error) GetForkIDInMemory(forkId uint64) *ForkIDInterval diff --git a/state/mocks/mock_storage.go b/state/mocks/mock_storage.go index 7771e69c08..f9b3c52d0f 100644 --- a/state/mocks/mock_storage.go +++ b/state/mocks/mock_storage.go @@ -874,55 +874,6 @@ func (_c *StorageMock_Begin_Call) RunAndReturn(run func(context.Context) (pgx.Tx return _c } -// BuildChangeL2Block provides a mock function with given fields: deltaTimestamp, l1InfoTreeIndex -func (_m *StorageMock) BuildChangeL2Block(deltaTimestamp uint32, l1InfoTreeIndex uint32) []byte { - ret := _m.Called(deltaTimestamp, l1InfoTreeIndex) - - if len(ret) == 0 { - panic("no return value specified for BuildChangeL2Block") - } - - var r0 []byte - if rf, ok := ret.Get(0).(func(uint32, uint32) []byte); ok { - r0 = rf(deltaTimestamp, l1InfoTreeIndex) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - return r0 -} - -// StorageMock_BuildChangeL2Block_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BuildChangeL2Block' -type StorageMock_BuildChangeL2Block_Call struct { - *mock.Call -} - -// BuildChangeL2Block is a helper method to define mock.On call -// - deltaTimestamp uint32 -// - l1InfoTreeIndex uint32 -func (_e *StorageMock_Expecter) BuildChangeL2Block(deltaTimestamp interface{}, l1InfoTreeIndex interface{}) *StorageMock_BuildChangeL2Block_Call { - return &StorageMock_BuildChangeL2Block_Call{Call: _e.mock.On("BuildChangeL2Block", deltaTimestamp, l1InfoTreeIndex)} -} - -func (_c *StorageMock_BuildChangeL2Block_Call) Run(run func(deltaTimestamp uint32, l1InfoTreeIndex uint32)) *StorageMock_BuildChangeL2Block_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(uint32), args[1].(uint32)) - }) - return _c -} - -func (_c *StorageMock_BuildChangeL2Block_Call) Return(_a0 []byte) *StorageMock_BuildChangeL2Block_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *StorageMock_BuildChangeL2Block_Call) RunAndReturn(run func(uint32, uint32) []byte) *StorageMock_BuildChangeL2Block_Call { - _c.Call.Return(run) - return _c -} - // CheckProofContainsCompleteSequences provides a mock function with given fields: ctx, proof, dbTx func (_m *StorageMock) CheckProofContainsCompleteSequences(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) (bool, error) { ret := _m.Called(ctx, proof, dbTx) @@ -3411,23 +3362,23 @@ func (_c *StorageMock_GetL2BlocksByBatchNumber_Call) RunAndReturn(run func(conte } // GetL2TxHashByTxHash provides a mock function with given fields: ctx, hash, dbTx -func (_m *StorageMock) GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (common.Hash, error) { +func (_m *StorageMock) GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*common.Hash, error) { ret := _m.Called(ctx, hash, dbTx) if len(ret) == 0 { panic("no return value specified for GetL2TxHashByTxHash") } - var r0 common.Hash + var r0 *common.Hash var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (common.Hash, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (*common.Hash, error)); ok { return rf(ctx, hash, dbTx) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) common.Hash); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *common.Hash); ok { r0 = rf(ctx, hash, dbTx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Hash) + r0 = ret.Get(0).(*common.Hash) } } @@ -3460,12 +3411,12 @@ func (_c *StorageMock_GetL2TxHashByTxHash_Call) Run(run func(ctx context.Context return _c } -func (_c *StorageMock_GetL2TxHashByTxHash_Call) Return(_a0 common.Hash, _a1 error) *StorageMock_GetL2TxHashByTxHash_Call { +func (_c *StorageMock_GetL2TxHashByTxHash_Call) Return(_a0 *common.Hash, _a1 error) *StorageMock_GetL2TxHashByTxHash_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *StorageMock_GetL2TxHashByTxHash_Call) RunAndReturn(run func(context.Context, common.Hash, pgx.Tx) (common.Hash, error)) *StorageMock_GetL2TxHashByTxHash_Call { +func (_c *StorageMock_GetL2TxHashByTxHash_Call) RunAndReturn(run func(context.Context, common.Hash, pgx.Tx) (*common.Hash, error)) *StorageMock_GetL2TxHashByTxHash_Call { _c.Call.Return(run) return _c } diff --git a/state/pgstatestorage/transaction.go b/state/pgstatestorage/transaction.go index 9d8fe15efa..43185894ab 100644 --- a/state/pgstatestorage/transaction.go +++ b/state/pgstatestorage/transaction.go @@ -562,19 +562,23 @@ func (p *PostgresStorage) GetTransactionEGPLogByHash(ctx context.Context, transa } // GetL2TxHashByTxHash gets the L2 Hash from the tx found by the provided tx hash -func (p *PostgresStorage) GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (common.Hash, error) { +func (p *PostgresStorage) GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*common.Hash, error) { const getTransactionByHashSQL = "SELECT transaction.l2_hash FROM state.transaction WHERE hash = $1" - var l2HashHex string + var l2HashHex *string q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getTransactionByHashSQL, hash.String()).Scan(&l2HashHex) if errors.Is(err, pgx.ErrNoRows) { - return common.Hash{}, state.ErrNotFound + return nil, state.ErrNotFound } else if err != nil { - return common.Hash{}, err + return nil, err + } + + if l2HashHex == nil { + return nil, nil } - l2Hash := common.HexToHash(l2HashHex) - return l2Hash, nil + l2Hash := common.HexToHash(*l2HashHex) + return &l2Hash, nil } From 68efeb5bc59fb6bbb53e7d18b2081c8e12965501 Mon Sep 17 00:00:00 2001 From: tclemos Date: Mon, 5 Feb 2024 15:23:36 -0300 Subject: [PATCH 2/2] fix mock and tests --- jsonrpc/endpoints_eth_test.go | 4 +-- jsonrpc/endpoints_zkevm_test.go | 10 +++---- state/mocks/mock_storage.go | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/jsonrpc/endpoints_eth_test.go b/jsonrpc/endpoints_eth_test.go index b2a2510785..efa876fb21 100644 --- a/jsonrpc/endpoints_eth_test.go +++ b/jsonrpc/endpoints_eth_test.go @@ -1309,7 +1309,7 @@ func TestGetL2BlockByNumber(t *testing.T) { for _, signedTx := range signedTransactions { m.State. On("GetL2TxHashByTxHash", context.Background(), signedTx.Hash(), m.DbTx). - Return(signedTx.Hash(), nil). + Return(state.Ptr(signedTx.Hash()), nil). Once() } }, @@ -1349,7 +1349,7 @@ func TestGetL2BlockByNumber(t *testing.T) { for _, signedTx := range signedTransactions { m.State. On("GetL2TxHashByTxHash", context.Background(), signedTx.Hash(), m.DbTx). - Return(signedTx.Hash(), nil). + Return(state.Ptr(signedTx.Hash()), nil). Once() } }, diff --git a/jsonrpc/endpoints_zkevm_test.go b/jsonrpc/endpoints_zkevm_test.go index 9983455d67..4293a2d7ae 100644 --- a/jsonrpc/endpoints_zkevm_test.go +++ b/jsonrpc/endpoints_zkevm_test.go @@ -777,7 +777,7 @@ func TestGetBatchByNumber(t *testing.T) { Once() m.State. On("GetL2TxHashByTxHash", context.Background(), tx.Hash(), m.DbTx). - Return(tx.Hash(), nil). + Return(state.Ptr(tx.Hash()), nil). Once() } m.State. @@ -1063,7 +1063,7 @@ func TestGetBatchByNumber(t *testing.T) { m.State. On("GetL2TxHashByTxHash", context.Background(), tx.Hash(), m.DbTx). - Return(tx.Hash(), nil). + Return(state.Ptr(tx.Hash()), nil). Once() } @@ -1980,7 +1980,7 @@ func TestGetTransactionByL2Hash(t *testing.T) { m.State. On("GetL2TxHashByTxHash", context.Background(), signedTx.Hash(), m.DbTx). - Return(l2Hash, nil). + Return(&l2Hash, nil). Once() }, }, @@ -2296,7 +2296,7 @@ func TestGetTransactionReceiptByL2Hash(t *testing.T) { m.State. On("GetL2TxHashByTxHash", context.Background(), signedTx.Hash(), m.DbTx). - Return(l2Hash, nil). + Return(&l2Hash, nil). Once() }, }, @@ -2426,7 +2426,7 @@ func TestGetTransactionReceiptByL2Hash(t *testing.T) { m.State. On("GetL2TxHashByTxHash", context.Background(), tx.Hash(), m.DbTx). - Return(l2Hash, nil). + Return(&l2Hash, nil). Once() }, }, diff --git a/state/mocks/mock_storage.go b/state/mocks/mock_storage.go index f9b3c52d0f..4a9ddac5ec 100644 --- a/state/mocks/mock_storage.go +++ b/state/mocks/mock_storage.go @@ -874,6 +874,55 @@ func (_c *StorageMock_Begin_Call) RunAndReturn(run func(context.Context) (pgx.Tx return _c } +// BuildChangeL2Block provides a mock function with given fields: deltaTimestamp, l1InfoTreeIndex +func (_m *StorageMock) BuildChangeL2Block(deltaTimestamp uint32, l1InfoTreeIndex uint32) []byte { + ret := _m.Called(deltaTimestamp, l1InfoTreeIndex) + + if len(ret) == 0 { + panic("no return value specified for BuildChangeL2Block") + } + + var r0 []byte + if rf, ok := ret.Get(0).(func(uint32, uint32) []byte); ok { + r0 = rf(deltaTimestamp, l1InfoTreeIndex) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + return r0 +} + +// StorageMock_BuildChangeL2Block_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BuildChangeL2Block' +type StorageMock_BuildChangeL2Block_Call struct { + *mock.Call +} + +// BuildChangeL2Block is a helper method to define mock.On call +// - deltaTimestamp uint32 +// - l1InfoTreeIndex uint32 +func (_e *StorageMock_Expecter) BuildChangeL2Block(deltaTimestamp interface{}, l1InfoTreeIndex interface{}) *StorageMock_BuildChangeL2Block_Call { + return &StorageMock_BuildChangeL2Block_Call{Call: _e.mock.On("BuildChangeL2Block", deltaTimestamp, l1InfoTreeIndex)} +} + +func (_c *StorageMock_BuildChangeL2Block_Call) Run(run func(deltaTimestamp uint32, l1InfoTreeIndex uint32)) *StorageMock_BuildChangeL2Block_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint32), args[1].(uint32)) + }) + return _c +} + +func (_c *StorageMock_BuildChangeL2Block_Call) Return(_a0 []byte) *StorageMock_BuildChangeL2Block_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *StorageMock_BuildChangeL2Block_Call) RunAndReturn(run func(uint32, uint32) []byte) *StorageMock_BuildChangeL2Block_Call { + _c.Call.Return(run) + return _c +} + // CheckProofContainsCompleteSequences provides a mock function with given fields: ctx, proof, dbTx func (_m *StorageMock) CheckProofContainsCompleteSequences(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) (bool, error) { ret := _m.Called(ctx, proof, dbTx)