From 5ea271c5d6478b4e858f89e1e5e028f70935067d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Thu, 26 Dec 2024 09:36:08 +0100 Subject: [PATCH] improve Rust build perf and cleanup --- Makefile | 2 +- bridgesync/e2e_test.go | 28 ++-- claimsponsor/e2e_test.go | 36 ++--- docs/SUMMARY.md | 1 - docs/non_evm_integration.md | 69 ---------- lastgersync/e2e_test.go | 24 ++-- sequencesender/mocks/mock_ethtxmanager.go | 63 +++++++++ sequencesender/sequencesender.go | 7 + test/Makefile | 7 +- test/helpers/e2e.go | 22 +-- test/helpers/mock_ethtxmanager.go | 155 +++++++++++++++++----- 11 files changed, 248 insertions(+), 166 deletions(-) delete mode 100644 docs/non_evm_integration.md diff --git a/Makefile b/Makefile index fad3c3950..b397985d6 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ build: build-rust build-go build-tools## Builds the binaries locally into ./tar .PHONY: build-rust build-rust: - export BUILD_SCRIPT_DISABLED=1 && cargo build --release + export BUILD_SCRIPT_DISABLED=1 && cargo build --release --jobs=$(shell nproc) .PHONY: build-go build-go: diff --git a/bridgesync/e2e_test.go b/bridgesync/e2e_test.go index 4b1fc94ae..57a32b6c8 100644 --- a/bridgesync/e2e_test.go +++ b/bridgesync/e2e_test.go @@ -22,7 +22,7 @@ func TestBridgeEventE2E(t *testing.T) { maxReorgDepth = 2 reorgEveryXIterations = 4 // every X blocks go back [1,maxReorgDepth] blocks ) - setup := helpers.NewE2EEnvWithEVML2(t) + l1Env, _ := helpers.NewL1EnvWithL2EVM(t) ctx := context.Background() // Send bridge txs bridgesSent := 0 @@ -39,8 +39,8 @@ func TestBridgeEventE2E(t *testing.T) { Metadata: []byte{}, } lastDepositCount++ - tx, err := setup.L1Environment.BridgeContract.BridgeAsset( - setup.L1Environment.Auth, + tx, err := l1Env.BridgeContract.BridgeAsset( + l1Env.Auth, bridge.DestinationNetwork, bridge.DestinationAddress, bridge.Amount, @@ -48,11 +48,11 @@ func TestBridgeEventE2E(t *testing.T) { true, nil, ) require.NoError(t, err) - helpers.CommitBlocks(t, setup.L1Environment.SimBackend, 1, blockTime) - bn, err := setup.L1Environment.SimBackend.Client().BlockNumber(ctx) + helpers.CommitBlocks(t, l1Env.SimBackend, 1, blockTime) + bn, err := l1Env.SimBackend.Client().BlockNumber(ctx) require.NoError(t, err) bridge.BlockNum = bn - receipt, err := setup.L1Environment.SimBackend.Client().TransactionReceipt(ctx, tx.Hash()) + receipt, err := l1Env.SimBackend.Client().TransactionReceipt(ctx, tx.Hash()) require.NoError(t, err) require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) expectedBridges = append(expectedBridges, bridge) @@ -61,9 +61,9 @@ func TestBridgeEventE2E(t *testing.T) { // Trigger reorg if i%reorgEveryXIterations == 0 { blocksToReorg := 1 + i%maxReorgDepth - bn, err := setup.L1Environment.SimBackend.Client().BlockNumber(ctx) + bn, err := l1Env.SimBackend.Client().BlockNumber(ctx) require.NoError(t, err) - helpers.Reorg(t, setup.L1Environment.SimBackend, uint64(blocksToReorg)) + helpers.Reorg(t, l1Env.SimBackend, uint64(blocksToReorg)) // Clean expected bridges lastValidBlock := bn - uint64(blocksToReorg) reorgEffective := false @@ -90,20 +90,20 @@ func TestBridgeEventE2E(t *testing.T) { // Wait for syncer to catch up time.Sleep(time.Second * 2) // sleeping since the processor could be up to date, but have pending reorgs - lb, err := setup.L1Environment.SimBackend.Client().BlockNumber(ctx) + lb, err := l1Env.SimBackend.Client().BlockNumber(ctx) require.NoError(t, err) - helpers.RequireProcessorUpdated(t, setup.L1Environment.BridgeSync, lb) + helpers.RequireProcessorUpdated(t, l1Env.BridgeSync, lb) // Get bridges - lastBlock, err := setup.L1Environment.SimBackend.Client().BlockNumber(ctx) + lastBlock, err := l1Env.SimBackend.Client().BlockNumber(ctx) require.NoError(t, err) - actualBridges, err := setup.L1Environment.BridgeSync.GetBridges(ctx, 0, lastBlock) + actualBridges, err := l1Env.BridgeSync.GetBridges(ctx, 0, lastBlock) require.NoError(t, err) // Assert bridges - expectedRoot, err := setup.L1Environment.BridgeContract.GetRoot(nil) + expectedRoot, err := l1Env.BridgeContract.GetRoot(nil) require.NoError(t, err) - root, err := setup.L1Environment.BridgeSync.GetExitRootByIndex(ctx, expectedBridges[len(expectedBridges)-1].DepositCount) + root, err := l1Env.BridgeSync.GetExitRootByIndex(ctx, expectedBridges[len(expectedBridges)-1].DepositCount) require.NoError(t, err) require.Equal(t, common.Hash(expectedRoot).Hex(), root.Hash.Hex()) require.Equal(t, expectedBridges, actualBridges) diff --git a/claimsponsor/e2e_test.go b/claimsponsor/e2e_test.go index d62568aca..f64b6aa71 100644 --- a/claimsponsor/e2e_test.go +++ b/claimsponsor/e2e_test.go @@ -21,19 +21,19 @@ import ( func TestE2EL1toEVML2(t *testing.T) { // start other needed components ctx := context.Background() - setup := helpers.NewE2EEnvWithEVML2(t) + l1Env, l2Env := helpers.NewL1EnvWithL2EVM(t) // start claim sponsor dbPathClaimSponsor := path.Join(t.TempDir(), "claimsponsorTestE2EL1toEVML2_cs.sqlite") claimer, err := claimsponsor.NewEVMClaimSponsor( log.GetDefaultLogger(), dbPathClaimSponsor, - setup.L2Environment.SimBackend.Client(), - setup.L2Environment.BridgeAddr, - setup.L2Environment.Auth.From, + l2Env.SimBackend.Client(), + l2Env.BridgeAddr, + l2Env.Auth.From, 200_000, 0, - setup.EthTxManagerMock, + l2Env.EthTxManagerMock, 0, 0, time.Millisecond*10, time.Millisecond*10, ) require.NoError(t, err) @@ -43,29 +43,29 @@ func TestE2EL1toEVML2(t *testing.T) { for i := uint32(0); i < 3; i++ { // Send bridges to L2, wait for GER to be injected on L2 amount := new(big.Int).SetUint64(uint64(i) + 1) - setup.L1Environment.Auth.Value = amount - _, err := setup.L1Environment.BridgeContract.BridgeAsset(setup.L1Environment.Auth, setup.NetworkIDL2, setup.L2Environment.Auth.From, amount, common.Address{}, true, nil) + l1Env.Auth.Value = amount + _, err := l1Env.BridgeContract.BridgeAsset(l1Env.Auth, l2Env.NetworkID, l2Env.Auth.From, amount, common.Address{}, true, nil) require.NoError(t, err) - setup.L1Environment.SimBackend.Commit() + l1Env.SimBackend.Commit() time.Sleep(time.Millisecond * 300) - expectedGER, err := setup.L1Environment.GERContract.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) + expectedGER, err := l1Env.GERContract.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) require.NoError(t, err) - _, err = setup.L2Environment.GERContract.InsertGlobalExitRoot(setup.L2Environment.Auth, expectedGER) + _, err = l2Env.GERContract.InsertGlobalExitRoot(l2Env.Auth, expectedGER) require.NoError(t, err) - setup.L2Environment.SimBackend.Commit() - gerIndex, err := setup.L2Environment.GERContract.GlobalExitRootMap(nil, expectedGER) + l2Env.SimBackend.Commit() + gerIndex, err := l2Env.GERContract.GlobalExitRootMap(nil, expectedGER) require.NoError(t, err) require.Equal(t, big.NewInt(int64(i)+1), gerIndex, fmt.Sprintf("iteration %d, GER: %s is not updated on L2", i, common.Bytes2Hex(expectedGER[:]))) // Build MP using bridgeSyncL1 & env.InfoTreeSync - info, err := setup.L1Environment.InfoTreeSync.GetInfoByIndex(ctx, i) + info, err := l1Env.InfoTreeSync.GetInfoByIndex(ctx, i) require.NoError(t, err) - localProof, err := setup.L1Environment.BridgeSync.GetProof(ctx, i, info.MainnetExitRoot) + localProof, err := l1Env.BridgeSync.GetProof(ctx, i, info.MainnetExitRoot) require.NoError(t, err) - rollupProof, err := setup.L1Environment.InfoTreeSync.GetRollupExitTreeMerkleProof(ctx, 0, common.Hash{}) + rollupProof, err := l1Env.InfoTreeSync.GetRollupExitTreeMerkleProof(ctx, 0, common.Hash{}) require.NoError(t, err) // Request to sponsor claim @@ -79,8 +79,8 @@ func TestE2EL1toEVML2(t *testing.T) { RollupExitRoot: info.RollupExitRoot, OriginNetwork: 0, OriginTokenAddress: common.Address{}, - DestinationNetwork: setup.NetworkIDL2, - DestinationAddress: setup.L2Environment.Auth.From, + DestinationNetwork: l2Env.NetworkID, + DestinationAddress: l2Env.Auth.From, Amount: amount, Metadata: nil, }) @@ -103,7 +103,7 @@ func TestE2EL1toEVML2(t *testing.T) { require.True(t, succeed) // Check on contract that is claimed - isClaimed, err := setup.L2Environment.BridgeContract.IsClaimed(&bind.CallOpts{Pending: false}, i, 0) + isClaimed, err := l2Env.BridgeContract.IsClaimed(&bind.CallOpts{Pending: false}, i, 0) require.NoError(t, err) require.True(t, isClaimed) } diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 3bc963188..04254646d 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -3,4 +3,3 @@ - [Getting Started](./getting_started.md) - [Local Debug](./local_debug.md) - [DA Integration](./da_integration.md) -- [Non-EVM integrations](./non_evm_integration.md) diff --git a/docs/non_evm_integration.md b/docs/non_evm_integration.md deleted file mode 100644 index ed304ea58..000000000 --- a/docs/non_evm_integration.md +++ /dev/null @@ -1,69 +0,0 @@ -# Integrating non-EVM systems - -This guide explains how to connect a third-party execution environment to the AggLayer using the CDK. - -## Important note - -The following information is experimental, and there aren't any working examples of non-EVM integrations with the AggLayer yet. While we know what needs to be done conceptually, the implementation details are likely to evolve. Think of this as a rough overview of the effort involved, rather than a step-by-step guide towards a production deployment. - -## Key Concepts - -Any system (chain or not chain) should be able to interact with the [unified LxLy bridge](https://docs.polygon.technology/zkEVM/architecture/unified-LxLy) and settle using the [AggLayer](https://docs.polygon.technology/learn/agglayer/overview/); especially when using the [Pessimistic Proof](https://docs.polygon.technology/learn/agglayer/pessimistic_proof/) option. Support for additional proofs, such as consensus, execution, or data availability are planned for the future. But, for now, this guide is based solely on using the Pessimistic Proof for settlement. - -The CDK client handles the integration with both the unified LxLy bridge and AggLayer. Think of it as an SDK to bring your project into the AggLayer ecosystem. You'll need to write some custom code in an adapter/plugin style so that the CDK client can connect with your service. - -In some cases, you might need to write code in `Go`. When that happens, the code should be in a separate repo and imported into the CDK as a dependency. The goal is to provide implementations that can interact with the *smart contracts* of the system being integrated, allowing the CDK client to reuse the same logic across different systems. Basically, you’ll need to create some *adapters* for the new system, while the existing code handles the rest. - -## Components for integration - -### Smart contracts - -For EVM-based integrations, there are two relevant smart contracts: - -- [Global exit root](https://github.com/0xPolygonHermez/zkevm-contracts/blob/feature/sovereign-bridge/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol) -- [Bridge](https://github.com/0xPolygonHermez/zkevm-contracts/blob/feature/sovereign-bridge/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol) - -The integrated system needs to implement similar functionality. It doesn't have to be a smart contract per se, and it doesn't need to be split into two parts, but it should perform the functions that we list here: - -- Bridge assets and messages to other networks. -- Handle incoming asset/message claims. -- Export local exit roots (a hash needed for other networks to claim assets). -- Import global exit roots (a hash needed for processing bridge claims). - -### AggOracle - -This component imports global exit roots into the smart contract(s). It should be implemented as a `Go` package, using the [EVM example](../aggoracle/chaingersender/evm.go) as a reference. It should implement the `ChainSender` interface defined [here](../aggoracle/oracle.go). - -### BridgeSync - -BridgeSync synchronizes information about bridges and claims originating from the L2 service attached to the CDK client. In other words, it monitors what's happening with the bridge smart contract, collects the necessary data for interacting with the AggLayer, and feeds the bridge service to enable claims on destination networks. - -> **Heads up:** These interfaces may change. - -To process events from non-EVM systems, you'll need a `downloader` and `driver`. The current setup needs some tweaks to support custom implementations. In short, you need to work with the [`Processor`](../bridgesync/processor.go), particularly the `ProcessorInterface` found [here](../sync/driver.go). The `Events` in `Block` are just interfaces, which should be parsed as `Event` structs defined in the [`Processor`](../bridgesync/processor.go). - -### Claim sponsor - -This component performs claims on behalf of users, which is crucial for systems with "gas" fees (transaction costs). Without it, gas-based systems could face a chicken/egg situation: How can users pay for a claim if they need a previous claim to get the funds to pay for it? - -The claim sponsor is optional and may not be needed in some setups. The [bridge RPC](../rpc/bridge.go) includes a config parameter to enable or disable it. To implement a claim sponsor that can perform claim transactions on the bridge smart contract, you'll need to implement the `ClaimSender` interface, defined [here](../claimsponsor/claimsponsor.go). - -### Last GER sync - -> **Warning:** These interfaces may also change. - -This component tracks which global exit roots have been imported. It helps the bridge service know when incoming bridges are ready to be claimed. The work needed is similar to that for the bridge sync: Implement the [`ProcessorInterface`](../sync/driver.go), with events of type `Event` defined [here](../lastgersync/processor.go). - -## Additional considerations - -### Bridge - -Once all components are implemented, the network should be connected to the unified LxLy bridge. However, keep in mind: - -- Outgoing bridges should work with current tools and UIs, but incoming bridges may not. When using the claim sponsor, things should just work. However, the claim sponsor is optional... The point being that the existing UIs are built to send EVM transactions to make the claim in the absence of claim sponsor. So any claim interaction beyond the auto-claim functionality will need UIs and tooling that are out of the sope of the CDK. -- Bridging assets/messages to another network is specific to the integrated system. You'll need to create mechanisms to interact with the *bridge smart contract* of your service for these actions. -- We’re moving towards an *in-CDK* bridge service (spec [here](https://hackmd.io/0vA-XU2BRHmH3Ab0j4ouZw)), replacing the current separate service ([here](https://github.com/0xPolygonHermez/zkevm-bridge-service)). There's no stable API yet, and SDKs/UIs are still in development. - -### AggLayer - -AggLayer integration will work once the components are ready, but initially, it will only support Pessimistic Proof. Later updates will add more security features like execution proofs, consensus proofs, data availability, and forced transactions. These will be optional, while Pessimistic Proof will remain mandatory. \ No newline at end of file diff --git a/lastgersync/e2e_test.go b/lastgersync/e2e_test.go index 88036ee84..2ec7eadfd 100644 --- a/lastgersync/e2e_test.go +++ b/lastgersync/e2e_test.go @@ -19,15 +19,15 @@ import ( func TestE2E(t *testing.T) { ctx := context.Background() - setup := helpers.NewE2EEnvWithEVML2(t) + l1Env, l2Env := helpers.NewL1EnvWithL2EVM(t) dbPathSyncer := path.Join(t.TempDir(), "lastgersyncTestE2E.sqlite") syncer, err := lastgersync.New( ctx, dbPathSyncer, - setup.L2Environment.ReorgDetector, - setup.L2Environment.SimBackend.Client(), - setup.L2Environment.GERAddr, - setup.InfoTreeSync, + l2Env.ReorgDetector, + l2Env.SimBackend.Client(), + l2Env.GERAddr, + l1Env.InfoTreeSync, 0, 0, etherman.LatestBlock, @@ -39,21 +39,21 @@ func TestE2E(t *testing.T) { for i := 0; i < 10; i++ { // Update GER on L1 - _, err := setup.L1Environment.GERContract.UpdateExitRoot(setup.L1Environment.Auth, common.HexToHash(strconv.Itoa(i))) + _, err := l1Env.GERContract.UpdateExitRoot(l1Env.Auth, common.HexToHash(strconv.Itoa(i))) require.NoError(t, err) - setup.L1Environment.SimBackend.Commit() + l1Env.SimBackend.Commit() time.Sleep(time.Millisecond * 150) - expectedGER, err := setup.L1Environment.GERContract.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) + expectedGER, err := l1Env.GERContract.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) require.NoError(t, err) - _, err = setup.L2Environment.GERContract.InsertGlobalExitRoot(setup.L2Environment.Auth, expectedGER) + _, err = l2Env.GERContract.InsertGlobalExitRoot(l2Env.Auth, expectedGER) require.NoError(t, err) - setup.L2Environment.SimBackend.Commit() - gerIndex, err := setup.L2Environment.GERContract.GlobalExitRootMap(nil, expectedGER) + l2Env.SimBackend.Commit() + gerIndex, err := l2Env.GERContract.GlobalExitRootMap(nil, expectedGER) require.NoError(t, err) require.Equal(t, big.NewInt(int64(i+1)), gerIndex, fmt.Sprintf("iteration %d, GER: %s is not updated on L2", i, common.Bytes2Hex(expectedGER[:]))) // Wait for syncer to catch up - lb, err := setup.L2Environment.SimBackend.Client().BlockNumber(ctx) + lb, err := l2Env.SimBackend.Client().BlockNumber(ctx) require.NoError(t, err) helpers.RequireProcessorUpdated(t, syncer, lb) diff --git a/sequencesender/mocks/mock_ethtxmanager.go b/sequencesender/mocks/mock_ethtxmanager.go index b8a58d0d2..3d0ebebcd 100644 --- a/sequencesender/mocks/mock_ethtxmanager.go +++ b/sequencesender/mocks/mock_ethtxmanager.go @@ -28,6 +28,69 @@ func (_m *EthTxManagerMock) EXPECT() *EthTxManagerMock_Expecter { return &EthTxManagerMock_Expecter{mock: &_m.Mock} } +// Add provides a mock function with given fields: ctx, to, value, data, gasOffset, sidecar +func (_m *EthTxManagerMock) Add(ctx context.Context, to *common.Address, value *big.Int, data []byte, gasOffset uint64, sidecar *types.BlobTxSidecar) (common.Hash, error) { + ret := _m.Called(ctx, to, value, data, gasOffset, sidecar) + + if len(ret) == 0 { + panic("no return value specified for Add") + } + + var r0 common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar) (common.Hash, error)); ok { + return rf(ctx, to, value, data, gasOffset, sidecar) + } + if rf, ok := ret.Get(0).(func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar) common.Hash); ok { + r0 = rf(ctx, to, value, data, gasOffset, sidecar) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Hash) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar) error); ok { + r1 = rf(ctx, to, value, data, gasOffset, sidecar) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EthTxManagerMock_Add_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Add' +type EthTxManagerMock_Add_Call struct { + *mock.Call +} + +// Add is a helper method to define mock.On call +// - ctx context.Context +// - to *common.Address +// - value *big.Int +// - data []byte +// - gasOffset uint64 +// - sidecar *types.BlobTxSidecar +func (_e *EthTxManagerMock_Expecter) Add(ctx interface{}, to interface{}, value interface{}, data interface{}, gasOffset interface{}, sidecar interface{}) *EthTxManagerMock_Add_Call { + return &EthTxManagerMock_Add_Call{Call: _e.mock.On("Add", ctx, to, value, data, gasOffset, sidecar)} +} + +func (_c *EthTxManagerMock_Add_Call) Run(run func(ctx context.Context, to *common.Address, value *big.Int, data []byte, gasOffset uint64, sidecar *types.BlobTxSidecar)) *EthTxManagerMock_Add_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*common.Address), args[2].(*big.Int), args[3].([]byte), args[4].(uint64), args[5].(*types.BlobTxSidecar)) + }) + return _c +} + +func (_c *EthTxManagerMock_Add_Call) Return(_a0 common.Hash, _a1 error) *EthTxManagerMock_Add_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EthTxManagerMock_Add_Call) RunAndReturn(run func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar) (common.Hash, error)) *EthTxManagerMock_Add_Call { + _c.Call.Return(run) + return _c +} + // AddWithGas provides a mock function with given fields: ctx, to, value, data, gasOffset, sidecar, gas func (_m *EthTxManagerMock) AddWithGas(ctx context.Context, to *common.Address, value *big.Int, data []byte, gasOffset uint64, sidecar *types.BlobTxSidecar, gas uint64) (common.Hash, error) { ret := _m.Called(ctx, to, value, data, gasOffset, sidecar, gas) diff --git a/sequencesender/sequencesender.go b/sequencesender/sequencesender.go index 432b37779..590c97980 100644 --- a/sequencesender/sequencesender.go +++ b/sequencesender/sequencesender.go @@ -29,6 +29,13 @@ const ten = 10 // EthTxManager represents the eth tx manager interface type EthTxManager interface { Start() + Add(ctx context.Context, + to *common.Address, + value *big.Int, + data []byte, + gasOffset uint64, + sidecar *ethtypes.BlobTxSidecar, + ) (common.Hash, error) AddWithGas( ctx context.Context, to *common.Address, diff --git a/test/Makefile b/test/Makefile index 2e81a453a..4cbedecb7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -36,12 +36,7 @@ generate-mocks-l1infotreesync: ## Generates mocks for l1infotreesync, using mock .PHONY: generate-mocks-helpers generate-mocks-helpers: ## Generates mocks for helpers, using mockery tool - export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=EthTxManager --dir=../aggoracle/chaingersender --output=./helpers --outpkg=helpers --structname=EthTxManagerMock --filename=mock_ethtxmanager.go ${COMMON_MOCKERY_PARAMS} - -.PHONY: generate-mocks-aggoracle -generate-mocks-aggoracle: ## Generates mocks for aggoracle, using mockery tool - export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=EthTxManager --dir ../aggoracle/chaingersender --output ../aggoracle/mocks --outpkg mocks --structname=EthTxManagerMock --filename=mock_ethtxmanager.go ${COMMON_MOCKERY_PARAMS} - export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=L2GERManager --dir ../aggoracle/chaingersender --output ../aggoracle/mocks --outpkg mocks --structname=L2GERManagerMock --filename=mock_l2germanager.go ${COMMON_MOCKERY_PARAMS} + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=EthTxManager --dir=../sequencesender --output=./helpers --outpkg=helpers --structname=EthTxManagerMock --filename=mock_ethtxmanager.go ${COMMON_MOCKERY_PARAMS} .PHONY: generate-mocks-sync generate-mocks-sync: ## Generates mocks for sync, using mockery tool diff --git a/test/helpers/e2e.go b/test/helpers/e2e.go index 42d81463d..8f5f30740 100644 --- a/test/helpers/e2e.go +++ b/test/helpers/e2e.go @@ -30,12 +30,6 @@ const ( periodRetry = time.Millisecond * 100 ) -type AggoracleWithEVMChain struct { - L1Environment - L2Environment - NetworkIDL2 uint32 -} - // CommonEnvironment contains common setup results used in both L1 and L2 network setups. type CommonEnvironment struct { SimBackend *simulated.Backend @@ -59,23 +53,20 @@ type L2Environment struct { CommonEnvironment GERContract *globalexitrootmanagerl2sovereignchain.Globalexitrootmanagerl2sovereignchain EthTxManagerMock *EthTxManagerMock + NetworkID uint32 } -// NewE2EEnvWithEVML2 creates a new E2E environment with EVM L1 and L2 chains. -func NewE2EEnvWithEVML2(t *testing.T) *AggoracleWithEVMChain { +// NewL1EnvWithL2EVM creates a new E2E environment with EVM L1 and L2 chains. +func NewL1EnvWithL2EVM(t *testing.T) (*L1Environment, *L2Environment) { t.Helper() // Setup L1 environment l1Setup := L1Setup(t) // Setup L2 environment - l2Setup := L2Setup(t) + l2Setup := L2Setup(t, rollupID) - return &AggoracleWithEVMChain{ - L1Environment: *l1Setup, - L2Environment: *l2Setup, - NetworkIDL2: rollupID, - } + return l1Setup, l2Setup } // L1Setup creates a new L1 environment. @@ -144,7 +135,7 @@ func L1Setup(t *testing.T) *L1Environment { } // L2Setup creates a new L2 environment. -func L2Setup(t *testing.T) *L2Environment { +func L2Setup(t *testing.T, networkID uint32) *L2Environment { t.Helper() l2Client, authL2, gerL2Addr, gerL2Contract, @@ -194,6 +185,7 @@ func L2Setup(t *testing.T) *L2Environment { }, GERContract: gerL2Contract, EthTxManagerMock: ethTxManagerMock, + NetworkID: networkID, } } diff --git a/test/helpers/mock_ethtxmanager.go b/test/helpers/mock_ethtxmanager.go index ac10be2a8..7937bf1d1 100644 --- a/test/helpers/mock_ethtxmanager.go +++ b/test/helpers/mock_ethtxmanager.go @@ -3,12 +3,11 @@ package helpers import ( + context "context" big "math/big" common "github.com/ethereum/go-ethereum/common" - context "context" - mock "github.com/stretchr/testify/mock" types "github.com/ethereum/go-ethereum/core/types" @@ -92,9 +91,73 @@ func (_c *EthTxManagerMock_Add_Call) RunAndReturn(run func(context.Context, *com return _c } -// Remove provides a mock function with given fields: ctx, id -func (_m *EthTxManagerMock) Remove(ctx context.Context, id common.Hash) error { - ret := _m.Called(ctx, id) +// AddWithGas provides a mock function with given fields: ctx, to, value, data, gasOffset, sidecar, gas +func (_m *EthTxManagerMock) AddWithGas(ctx context.Context, to *common.Address, value *big.Int, data []byte, gasOffset uint64, sidecar *types.BlobTxSidecar, gas uint64) (common.Hash, error) { + ret := _m.Called(ctx, to, value, data, gasOffset, sidecar, gas) + + if len(ret) == 0 { + panic("no return value specified for AddWithGas") + } + + var r0 common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar, uint64) (common.Hash, error)); ok { + return rf(ctx, to, value, data, gasOffset, sidecar, gas) + } + if rf, ok := ret.Get(0).(func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar, uint64) common.Hash); ok { + r0 = rf(ctx, to, value, data, gasOffset, sidecar, gas) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Hash) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar, uint64) error); ok { + r1 = rf(ctx, to, value, data, gasOffset, sidecar, gas) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EthTxManagerMock_AddWithGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddWithGas' +type EthTxManagerMock_AddWithGas_Call struct { + *mock.Call +} + +// AddWithGas is a helper method to define mock.On call +// - ctx context.Context +// - to *common.Address +// - value *big.Int +// - data []byte +// - gasOffset uint64 +// - sidecar *types.BlobTxSidecar +// - gas uint64 +func (_e *EthTxManagerMock_Expecter) AddWithGas(ctx interface{}, to interface{}, value interface{}, data interface{}, gasOffset interface{}, sidecar interface{}, gas interface{}) *EthTxManagerMock_AddWithGas_Call { + return &EthTxManagerMock_AddWithGas_Call{Call: _e.mock.On("AddWithGas", ctx, to, value, data, gasOffset, sidecar, gas)} +} + +func (_c *EthTxManagerMock_AddWithGas_Call) Run(run func(ctx context.Context, to *common.Address, value *big.Int, data []byte, gasOffset uint64, sidecar *types.BlobTxSidecar, gas uint64)) *EthTxManagerMock_AddWithGas_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*common.Address), args[2].(*big.Int), args[3].([]byte), args[4].(uint64), args[5].(*types.BlobTxSidecar), args[6].(uint64)) + }) + return _c +} + +func (_c *EthTxManagerMock_AddWithGas_Call) Return(_a0 common.Hash, _a1 error) *EthTxManagerMock_AddWithGas_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EthTxManagerMock_AddWithGas_Call) RunAndReturn(run func(context.Context, *common.Address, *big.Int, []byte, uint64, *types.BlobTxSidecar, uint64) (common.Hash, error)) *EthTxManagerMock_AddWithGas_Call { + _c.Call.Return(run) + return _c +} + +// Remove provides a mock function with given fields: ctx, hash +func (_m *EthTxManagerMock) Remove(ctx context.Context, hash common.Hash) error { + ret := _m.Called(ctx, hash) if len(ret) == 0 { panic("no return value specified for Remove") @@ -102,7 +165,7 @@ func (_m *EthTxManagerMock) Remove(ctx context.Context, id common.Hash) error { var r0 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash) error); ok { - r0 = rf(ctx, id) + r0 = rf(ctx, hash) } else { r0 = ret.Error(0) } @@ -117,12 +180,12 @@ type EthTxManagerMock_Remove_Call struct { // Remove is a helper method to define mock.On call // - ctx context.Context -// - id common.Hash -func (_e *EthTxManagerMock_Expecter) Remove(ctx interface{}, id interface{}) *EthTxManagerMock_Remove_Call { - return &EthTxManagerMock_Remove_Call{Call: _e.mock.On("Remove", ctx, id)} +// - hash common.Hash +func (_e *EthTxManagerMock_Expecter) Remove(ctx interface{}, hash interface{}) *EthTxManagerMock_Remove_Call { + return &EthTxManagerMock_Remove_Call{Call: _e.mock.On("Remove", ctx, hash)} } -func (_c *EthTxManagerMock_Remove_Call) Run(run func(ctx context.Context, id common.Hash)) *EthTxManagerMock_Remove_Call { +func (_c *EthTxManagerMock_Remove_Call) Run(run func(ctx context.Context, hash common.Hash)) *EthTxManagerMock_Remove_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(common.Hash)) }) @@ -139,9 +202,9 @@ func (_c *EthTxManagerMock_Remove_Call) RunAndReturn(run func(context.Context, c return _c } -// Result provides a mock function with given fields: ctx, id -func (_m *EthTxManagerMock) Result(ctx context.Context, id common.Hash) (zkevm_ethtx_managertypes.MonitoredTxResult, error) { - ret := _m.Called(ctx, id) +// Result provides a mock function with given fields: ctx, hash +func (_m *EthTxManagerMock) Result(ctx context.Context, hash common.Hash) (zkevm_ethtx_managertypes.MonitoredTxResult, error) { + ret := _m.Called(ctx, hash) if len(ret) == 0 { panic("no return value specified for Result") @@ -150,16 +213,16 @@ func (_m *EthTxManagerMock) Result(ctx context.Context, id common.Hash) (zkevm_e var r0 zkevm_ethtx_managertypes.MonitoredTxResult var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (zkevm_ethtx_managertypes.MonitoredTxResult, error)); ok { - return rf(ctx, id) + return rf(ctx, hash) } if rf, ok := ret.Get(0).(func(context.Context, common.Hash) zkevm_ethtx_managertypes.MonitoredTxResult); ok { - r0 = rf(ctx, id) + r0 = rf(ctx, hash) } else { r0 = ret.Get(0).(zkevm_ethtx_managertypes.MonitoredTxResult) } if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, id) + r1 = rf(ctx, hash) } else { r1 = ret.Error(1) } @@ -174,12 +237,12 @@ type EthTxManagerMock_Result_Call struct { // Result is a helper method to define mock.On call // - ctx context.Context -// - id common.Hash -func (_e *EthTxManagerMock_Expecter) Result(ctx interface{}, id interface{}) *EthTxManagerMock_Result_Call { - return &EthTxManagerMock_Result_Call{Call: _e.mock.On("Result", ctx, id)} +// - hash common.Hash +func (_e *EthTxManagerMock_Expecter) Result(ctx interface{}, hash interface{}) *EthTxManagerMock_Result_Call { + return &EthTxManagerMock_Result_Call{Call: _e.mock.On("Result", ctx, hash)} } -func (_c *EthTxManagerMock_Result_Call) Run(run func(ctx context.Context, id common.Hash)) *EthTxManagerMock_Result_Call { +func (_c *EthTxManagerMock_Result_Call) Run(run func(ctx context.Context, hash common.Hash)) *EthTxManagerMock_Result_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(common.Hash)) }) @@ -196,9 +259,9 @@ func (_c *EthTxManagerMock_Result_Call) RunAndReturn(run func(context.Context, c return _c } -// ResultsByStatus provides a mock function with given fields: ctx, statuses -func (_m *EthTxManagerMock) ResultsByStatus(ctx context.Context, statuses []zkevm_ethtx_managertypes.MonitoredTxStatus) ([]zkevm_ethtx_managertypes.MonitoredTxResult, error) { - ret := _m.Called(ctx, statuses) +// ResultsByStatus provides a mock function with given fields: ctx, status +func (_m *EthTxManagerMock) ResultsByStatus(ctx context.Context, status []zkevm_ethtx_managertypes.MonitoredTxStatus) ([]zkevm_ethtx_managertypes.MonitoredTxResult, error) { + ret := _m.Called(ctx, status) if len(ret) == 0 { panic("no return value specified for ResultsByStatus") @@ -207,10 +270,10 @@ func (_m *EthTxManagerMock) ResultsByStatus(ctx context.Context, statuses []zkev var r0 []zkevm_ethtx_managertypes.MonitoredTxResult var r1 error if rf, ok := ret.Get(0).(func(context.Context, []zkevm_ethtx_managertypes.MonitoredTxStatus) ([]zkevm_ethtx_managertypes.MonitoredTxResult, error)); ok { - return rf(ctx, statuses) + return rf(ctx, status) } if rf, ok := ret.Get(0).(func(context.Context, []zkevm_ethtx_managertypes.MonitoredTxStatus) []zkevm_ethtx_managertypes.MonitoredTxResult); ok { - r0 = rf(ctx, statuses) + r0 = rf(ctx, status) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]zkevm_ethtx_managertypes.MonitoredTxResult) @@ -218,7 +281,7 @@ func (_m *EthTxManagerMock) ResultsByStatus(ctx context.Context, statuses []zkev } if rf, ok := ret.Get(1).(func(context.Context, []zkevm_ethtx_managertypes.MonitoredTxStatus) error); ok { - r1 = rf(ctx, statuses) + r1 = rf(ctx, status) } else { r1 = ret.Error(1) } @@ -233,12 +296,12 @@ type EthTxManagerMock_ResultsByStatus_Call struct { // ResultsByStatus is a helper method to define mock.On call // - ctx context.Context -// - statuses []zkevm_ethtx_managertypes.MonitoredTxStatus -func (_e *EthTxManagerMock_Expecter) ResultsByStatus(ctx interface{}, statuses interface{}) *EthTxManagerMock_ResultsByStatus_Call { - return &EthTxManagerMock_ResultsByStatus_Call{Call: _e.mock.On("ResultsByStatus", ctx, statuses)} +// - status []zkevm_ethtx_managertypes.MonitoredTxStatus +func (_e *EthTxManagerMock_Expecter) ResultsByStatus(ctx interface{}, status interface{}) *EthTxManagerMock_ResultsByStatus_Call { + return &EthTxManagerMock_ResultsByStatus_Call{Call: _e.mock.On("ResultsByStatus", ctx, status)} } -func (_c *EthTxManagerMock_ResultsByStatus_Call) Run(run func(ctx context.Context, statuses []zkevm_ethtx_managertypes.MonitoredTxStatus)) *EthTxManagerMock_ResultsByStatus_Call { +func (_c *EthTxManagerMock_ResultsByStatus_Call) Run(run func(ctx context.Context, status []zkevm_ethtx_managertypes.MonitoredTxStatus)) *EthTxManagerMock_ResultsByStatus_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].([]zkevm_ethtx_managertypes.MonitoredTxStatus)) }) @@ -255,6 +318,38 @@ func (_c *EthTxManagerMock_ResultsByStatus_Call) RunAndReturn(run func(context.C return _c } +// Start provides a mock function with no fields +func (_m *EthTxManagerMock) Start() { + _m.Called() +} + +// EthTxManagerMock_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type EthTxManagerMock_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +func (_e *EthTxManagerMock_Expecter) Start() *EthTxManagerMock_Start_Call { + return &EthTxManagerMock_Start_Call{Call: _e.mock.On("Start")} +} + +func (_c *EthTxManagerMock_Start_Call) Run(run func()) *EthTxManagerMock_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *EthTxManagerMock_Start_Call) Return() *EthTxManagerMock_Start_Call { + _c.Call.Return() + return _c +} + +func (_c *EthTxManagerMock_Start_Call) RunAndReturn(run func()) *EthTxManagerMock_Start_Call { + _c.Run(run) + return _c +} + // NewEthTxManagerMock creates a new instance of EthTxManagerMock. 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 NewEthTxManagerMock(t interface {