diff --git a/e2e/app/create3.go b/e2e/app/create3.go index f683b1ee5..473ee09b1 100644 --- a/e2e/app/create3.go +++ b/e2e/app/create3.go @@ -40,31 +40,11 @@ func Create3Deploy(ctx context.Context, def Definition, cfg Create3DeployConfig) return nil } -func deployPrivateCreate3(ctx context.Context, def Definition) error { - for _, c := range def.Testnet.AnvilChains { - _, _, err := deployCreate3(ctx, def, c.Chain.ChainID) +func deployAllCreate3(ctx context.Context, def Definition) error { + for _, chain := range def.Testnet.EVMChains() { + _, _, err := deployCreate3(ctx, def, chain.ChainID) if err != nil { - return errors.Wrap(err, "deploy create3") - } - } - - // only deploy to omni evm once - if len(def.Testnet.OmniEVMs) > 0 { - c := def.Testnet.OmniEVMs[0] - _, _, err := deployCreate3(ctx, def, c.Chain.ChainID) - if err != nil { - return errors.Wrap(err, "deploy create3") - } - } - - return nil -} - -func deployPublicCreate3(ctx context.Context, def Definition) error { - for _, c := range def.Testnet.PublicChains { - _, _, err := deployCreate3(ctx, def, c.Chain().ChainID) - if err != nil { - return errors.Wrap(err, "deploy create3") + return errors.Wrap(err, "deploy create3", "chain", chain.Name) } } diff --git a/e2e/app/definition.go b/e2e/app/definition.go index 3e0ef183b..3cae67d86 100644 --- a/e2e/app/definition.go +++ b/e2e/app/definition.go @@ -93,8 +93,13 @@ func (d Definition) Netman() netman.Manager { func (d Definition) DeployInfos() types.DeployInfos { resp := make(types.DeployInfos) - for chainID, info := range d.Netman().DeployInfo() { - resp.Set(chainID, types.ContractPortal, info.PortalAddress, info.DeployHeight) + for chainID, portal := range d.Netman().Portals() { + resp.Set( + chainID, + types.ContractPortal, + portal.DeployInfo.PortalAddress, + portal.DeployInfo.DeployHeight, + ) } return resp @@ -512,15 +517,15 @@ func NetworkFromDef(def Definition) netconf.Network { var chains []netconf.Chain newChain := func(chain types.EVMChain) netconf.Chain { - depInfo := def.DeployInfos()[chain.ChainID] + portal := def.Netman().Portals()[chain.ChainID] return netconf.Chain{ ID: chain.ChainID, Name: chain.Name, BlockPeriod: chain.BlockPeriod, Shards: chain.Shards, AttestInterval: chain.AttestInterval(def.Testnet.Network), - PortalAddress: depInfo[types.ContractPortal].Address, - DeployHeight: depInfo[types.ContractPortal].Height, + PortalAddress: portal.DeployInfo.PortalAddress, + DeployHeight: portal.DeployInfo.DeployHeight, } } diff --git a/e2e/app/fund.go b/e2e/app/fund.go index b7ee9df6d..fc4c21166 100644 --- a/e2e/app/fund.go +++ b/e2e/app/fund.go @@ -47,8 +47,8 @@ func accountsToFund(network netconf.ID) []common.Address { } } -// fundAccounts funds the EOAs that need funding (just on anvil chains, for now). -func fundAccounts(ctx context.Context, def Definition) error { +// fundAnvilAccounts funds the EOAs on anvil that need funding. +func fundAnvilAccounts(ctx context.Context, def Definition) error { accounts := accountsToFund(def.Testnet.Network) eth100 := new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(100)) for _, chain := range def.Testnet.AnvilChains { diff --git a/e2e/app/gaspump.go b/e2e/app/gaspump.go index dadadaee9..dcdaa7b2e 100644 --- a/e2e/app/gaspump.go +++ b/e2e/app/gaspump.go @@ -179,6 +179,7 @@ var ( } ) +// TODO(corver): Move this to actual tests package. func testGasPumps(ctx context.Context, def Definition) error { networkID := def.Testnet.Network network := NetworkFromDef(def) diff --git a/e2e/app/portalregistry.go b/e2e/app/portalregistry.go index a0d1e3338..d11dbfccd 100644 --- a/e2e/app/portalregistry.go +++ b/e2e/app/portalregistry.go @@ -140,13 +140,12 @@ func evmChains(def Definition) ([]types.EVMChain, error) { // toPortalDepls converts EVM chains to portal registry deployments. func toPortalDepls(def Definition, chains []types.EVMChain) (map[uint64]bindings.PortalRegistryDeployment, error) { - infos := def.DeployInfos() deps := make(map[uint64]bindings.PortalRegistryDeployment) for _, chain := range chains { - info, ok := infos[chain.ChainID][types.ContractPortal] + portal, ok := def.Netman().Portals()[chain.ChainID] if !ok { - return nil, errors.New("missing info", "chain", chain.ChainID) + return nil, errors.New("missing portal", "chain", chain.ChainID) } blockPeriodNs, err := umath.ToUint64(chain.BlockPeriod.Nanoseconds()) @@ -157,10 +156,10 @@ func toPortalDepls(def Definition, chains []types.EVMChain) (map[uint64]bindings deps[chain.ChainID] = bindings.PortalRegistryDeployment{ Name: chain.Name, ChainId: chain.ChainID, - Addr: info.Address, + Addr: portal.DeployInfo.PortalAddress, BlockPeriodNs: blockPeriodNs, AttestInterval: chain.AttestInterval(def.Testnet.Network), - DeployHeight: info.Height, + DeployHeight: portal.DeployInfo.DeployHeight, Shards: chain.ShardsUint64(), } } diff --git a/e2e/app/run.go b/e2e/app/run.go index 900eb5f78..53ab4f6a7 100644 --- a/e2e/app/run.go +++ b/e2e/app/run.go @@ -79,30 +79,21 @@ func Deploy(ctx context.Context, def Definition, cfg DeployConfig) (*pingpong.XD return nil, err } - if err := waitForEVMs(ctx, NetworkFromDef(def), def.Backends()); err != nil { + if err := waitForEVMs(ctx, def.Testnet.EVMChains(), def.Backends()); err != nil { return nil, err } contracts.UseStagingOmniRPC(def.Testnet.BroadcastOmniEVM().ExternalRPC) - if err := deployPublicCreate3(ctx, def); err != nil { + if err := fundAnvilAccounts(ctx, def); err != nil { return nil, err } - // Deploy public portals first so their addresses are available for setup. - if err := def.Netman().DeployPublicPortals(ctx, genesisValSetID, genesisVals); err != nil { + if err := deployAllCreate3(ctx, def); err != nil { return nil, err } - if err := fundAccounts(ctx, def); err != nil { - return nil, err - } - - if err := deployPrivateCreate3(ctx, def); err != nil { - return nil, err - } - - if err := def.Netman().DeployPrivatePortals(ctx, genesisValSetID, genesisVals); err != nil { + if err := def.Netman().DeployPortals(ctx, genesisValSetID, genesisVals); err != nil { return nil, err } logRPCs(ctx, def) diff --git a/e2e/app/start.go b/e2e/app/start.go index 8d817434c..2c81fddcc 100644 --- a/e2e/app/start.go +++ b/e2e/app/start.go @@ -8,11 +8,11 @@ import ( "sync" "time" + "github.com/omni-network/omni/e2e/types" "github.com/omni-network/omni/lib/errors" "github.com/omni-network/omni/lib/ethclient/ethbackend" "github.com/omni-network/omni/lib/expbackoff" "github.com/omni-network/omni/lib/log" - "github.com/omni-network/omni/lib/netconf" e2e "github.com/cometbft/cometbft/test/e2e/pkg" "github.com/cometbft/cometbft/test/e2e/pkg/infra" @@ -176,9 +176,9 @@ func getSortedNodes(testnet *e2e.Testnet) ([]*e2e.Node, error) { // waitForEVMs waits for EVMs to be available. // This mitigates any issues if starting anvils or omni evms is slow. // It also ensures the public RPCs are accessible. -func waitForEVMs(ctx context.Context, network netconf.Network, backends ethbackend.Backends) error { - for _, chain := range network.EVMChains() { - backend, err := backends.Backend(chain.ID) +func waitForEVMs(ctx context.Context, chains []types.EVMChain, backends ethbackend.Backends) error { + for _, chain := range chains { + backend, err := backends.Backend(chain.ChainID) if err != nil { return errors.Wrap(err, "backend") } diff --git a/e2e/app/tokenbridge.go b/e2e/app/tokenbridge.go index 7866c2f77..12ddb60dc 100644 --- a/e2e/app/tokenbridge.go +++ b/e2e/app/tokenbridge.go @@ -143,6 +143,7 @@ var ToL1BridgeTests = []BridgeTest{ // testBridge bridges some tokens from L1 to OmniEVM, and some from OmniEVM to L1. // Tokens must be bridged to OmniEVM first, before the native bridge contract will allow bridging back to L1. +// TODO(corver): Move this to actual tests package. func testBridge(ctx context.Context, def Definition) error { networkID := def.Testnet.Network network := NetworkFromDef(def) diff --git a/e2e/netman/manager.go b/e2e/netman/manager.go index 4dd4d183f..420e7b507 100644 --- a/e2e/netman/manager.go +++ b/e2e/netman/manager.go @@ -16,18 +16,10 @@ import ( "github.com/ethereum/go-ethereum/common" ) -// Manager abstract logic to deploy and bootstrap a network. -// TODO(corver): No need to split public vs private portal deploys anymore. +// Manager abstract logic to deploy portal contracts. type Manager interface { - // DeployPublicPortals deploys portals to public chains, like arb-goerli. - DeployPublicPortals(ctx context.Context, valSetID uint64, validators []bindings.Validator) error - - // DeployInfo returns the deployed network information by chain ID. - // Note that the private chains has to be deterministic, since this is called before deploying private portals. - DeployInfo() map[uint64]DeployInfo - - // DeployPrivatePortals deploys portals to private (docker) chains. - DeployPrivatePortals(ctx context.Context, valSetID uint64, validators []bindings.Validator) error + // DeployPortals deploys portals to all chains. + DeployPortals(ctx context.Context, valSetID uint64, validators []bindings.Validator) error // Portals returns the deployed portals from both public and private chains. Portals() map[uint64]Portal @@ -35,8 +27,8 @@ type Manager interface { func NewManager(testnet types.Testnet, backends ethbackend.Backends) (Manager, error) { if testnet.OnlyMonitor { - if !netconf.IsAny(testnet.Network, netconf.Omega, netconf.Mainnet) { - return nil, errors.New("monitor-only only supported for testnet and mainnet") + if !netconf.IsAny(testnet.Network, netconf.Mainnet) { + return nil, errors.New("monitor-only only supported for mainnet") } return &manager{ @@ -44,70 +36,11 @@ func NewManager(testnet types.Testnet, backends ethbackend.Backends) (Manager, e }, nil } - network := testnet.Network - - // Create partial portals. This will be updated by Deploy*Portals. - portals := make(map[uint64]Portal) - - // Private chains have deterministic deploy height and addresses. - privateChainDeployInfo := DeployInfo{ - DeployHeight: 0, - } - - if testnet.HasOmniEVM() { - // Just use the first omni evm instance for now. - omniEVM := testnet.OmniEVMs[0] - portals[omniEVM.Chain.ChainID] = Portal{ - Chain: omniEVM.Chain, - DeployInfo: privateChainDeployInfo, - } - } - - // Add all portals - for _, anvil := range testnet.AnvilChains { - portals[anvil.Chain.ChainID] = Portal{ - Chain: anvil.Chain, - DeployInfo: privateChainDeployInfo, - } - } - // Add all public chains - for _, public := range testnet.PublicChains { - // Public chain deploy height and address may be statically populated. - staticDeploy, _ := testnet.Network.Static().PortalDeployment(public.Chain().ChainID) - portals[public.Chain().ChainID] = Portal{ - Chain: public.Chain(), - DeployInfo: DeployInfo{ - PortalAddress: staticDeploy.Address, - DeployHeight: staticDeploy.DeployHeight, - }, - } - } - - switch testnet.Network { - case netconf.Devnet: - return &manager{ - portals: portals, - omniChainID: netconf.Devnet.Static().OmniExecutionChainID, - backends: backends, - network: netconf.Devnet, - }, nil - case netconf.Staging: - return &manager{ - portals: portals, - omniChainID: netconf.Staging.Static().OmniExecutionChainID, - backends: backends, - network: netconf.Staging, - }, nil - case netconf.Omega: - return &manager{ - portals: portals, - omniChainID: netconf.Omega.Static().OmniExecutionChainID, - backends: backends, - network: netconf.Omega, - }, nil - default: - return nil, errors.New("unknown network", "network", network) - } + return &manager{ + backends: backends, + network: testnet.Network, + chains: testnet.EVMChains(), + }, nil } // DeployInfo contains the deployed portal address and height. @@ -126,144 +59,70 @@ type Portal struct { var _ Manager = (*manager)(nil) type manager struct { - portals map[uint64]Portal // Note that this is mutable, Portals are updated by Deploy*Portals. - omniChainID uint64 - backends ethbackend.Backends - network netconf.ID + chains []types.EVMChain + portals map[uint64]Portal // This is nil until populated by DeployPortals. + backends ethbackend.Backends + network netconf.ID } -func (m *manager) DeployInfo() map[uint64]DeployInfo { - resp := make(map[uint64]DeployInfo) - for _, portal := range m.portals { - resp[portal.Chain.ChainID] = portal.DeployInfo +func (m *manager) DeployPortals(ctx context.Context, valSetID uint64, validators []bindings.Validator, +) error { + if m.portals != nil { + return errors.New("portals already deployed") } - return resp -} - -func (m *manager) DeployPublicPortals(ctx context.Context, valSetID uint64, validators []bindings.Validator, -) error { - log.Info(ctx, "Deploying public portal contracts") + log.Info(ctx, "Deploying portal contracts") // Define a forkjoin work function that will deploy the omni contracts for each chain - deployFunc := func(ctx context.Context, p Portal) (*deployResult, error) { - log.Debug(ctx, "Deploying to", "chain", p.Chain.Name) + deployFunc := func(ctx context.Context, chain types.EVMChain) (Portal, error) { + ctx = log.WithCtx(ctx, "chain", chain.Name) + log.Debug(ctx, "Deploying portal") - backend, err := m.backends.Backend(p.Chain.ChainID) + backend, err := m.backends.Backend(chain.ChainID) if err != nil { - return nil, errors.Wrap(err, "deploy opts", "chain", p.Chain.Name) + return Portal{}, errors.Wrap(err, "deploy opts") } - addr, deployHeight, err := m.deployIfNeeded(ctx, p.Chain, backend, valSetID, validators) + addr, deployHeight, err := m.deployIfNeeded(ctx, chain, backend, valSetID, validators) if err != nil { - return nil, errors.Wrap(err, "deploy public portals", "chain", p.Chain.Name) + return Portal{}, errors.Wrap(err, "deploy public portals") } contract, err := bindings.NewOmniPortal(addr, backend) if err != nil { - return nil, errors.Wrap(err, "bind contract", "chain", p.Chain.Name) + return Portal{}, errors.Wrap(err, "bind contract") } - return &deployResult{ + return Portal{ + Chain: chain, + DeployInfo: DeployInfo{ + PortalAddress: addr, + DeployHeight: deployHeight, + }, Contract: contract, - Addr: addr, - Height: deployHeight, }, nil } - fork, join, cancel := forkjoin.New(ctx, deployFunc) + results, cancel := forkjoin.NewWithInputs(ctx, deployFunc, m.chains) defer cancel() - for chainID := range m.portals { - portal := m.portals[chainID] - if !portal.Chain.IsPublic { - continue // Only public chains are deployed here. - } - - fork(portal) - } - - for res := range join() { + m.portals = make(map[uint64]Portal) + for res := range results { if res.Err != nil { - return errors.Wrap(res.Err, "fork join") - } - - portal := m.portals[res.Input.Chain.ChainID] - - portal.DeployInfo = DeployInfo{ - PortalAddress: res.Output.Addr, - DeployHeight: res.Output.Height, + return errors.Wrap(res.Err, "fork join", "chain", res.Input.Name) } - portal.Contract = res.Output.Contract - m.portals[res.Input.Chain.ChainID] = portal + m.portals[res.Output.Chain.ChainID] = res.Output } return nil } -func (m *manager) DeployPrivatePortals(ctx context.Context, valSetID uint64, validators []bindings.Validator, -) error { - log.Info(ctx, "Deploying private portal contracts") - - // Define a forkjoin work function that will deploy the omni contracts for each chain - deployFunc := func(ctx context.Context, p Portal) (deployResult, error) { - backend, err := m.backends.Backend(p.Chain.ChainID) - if err != nil { - return deployResult{}, errors.Wrap(err, "deploy opts", "chain", p.Chain.Name) - } - - addr, height, err := m.deployIfNeeded(ctx, p.Chain, backend, valSetID, validators) - if err != nil { - return deployResult{}, errors.Wrap(err, "deploy private portals", "chain", p.Chain.Name) - } - - contract, err := bindings.NewOmniPortal(addr, backend) - if err != nil { - return deployResult{}, errors.Wrap(err, "bind contract", "chain", p.Chain.Name) - } - - return deployResult{ - Contract: contract, - Addr: addr, - Height: height, - }, nil - } - - // Start the forkjoin - fork, join, cancel := forkjoin.New(ctx, deployFunc) - defer cancel() - for chainID := range m.portals { - portal := m.portals[chainID] - if portal.Chain.IsPublic { - continue // Public chains are already deployed. - } - - fork(portal) - } - - // Join the results - for res := range join() { - if res.Err != nil { - return errors.Wrap(res.Err, "fork join") - } - - // Update the portal with the deployed contract, height and address - portal := m.portals[res.Input.Chain.ChainID] - - portal.Contract = res.Output.Contract - portal.DeployInfo = DeployInfo{ - PortalAddress: res.Output.Addr, - DeployHeight: res.Output.Height, - } - - m.portals[res.Input.Chain.ChainID] = portal +func (m *manager) Portals() map[uint64]Portal { + if m.portals == nil { + panic("portals not deployed yet") } - return nil -} - -func (m *manager) Portals() map[uint64]Portal { return m.portals } @@ -306,7 +165,7 @@ func (m *manager) deployIfNeeded(ctx context.Context, chain types.EVMChain, back return staticDeploy.Address, staticDeploy.DeployHeight, nil } - feeOracle, _, err := feeoraclev1.Deploy(ctx, m.network, chain.ChainID, m.allChainIDs(), m.backends) + feeOracle, _, err := feeoraclev1.Deploy(ctx, m.network, chain.ChainID, m.chainIDs(), m.backends) if err != nil { return common.Address{}, 0, errors.Wrap(err, "deploy fee oracle", "chain", chain.Name) } @@ -323,19 +182,12 @@ func (m *manager) deployIfNeeded(ctx context.Context, chain types.EVMChain, back return addr, receipt.BlockNumber.Uint64(), nil } -// allChainIDs returns all configured destination chain ids. -func (m *manager) allChainIDs() []uint64 { - var destChainIDs []uint64 - - for id := range m.Portals() { - destChainIDs = append(destChainIDs, id) +// chainIDs returns all chain ids. +func (m *manager) chainIDs() []uint64 { + ids := make([]uint64, 0, len(m.chains)) + for _, chain := range m.chains { + ids = append(ids, chain.ChainID) } - return destChainIDs -} - -type deployResult struct { - Contract *bindings.OmniPortal - Addr common.Address - Height uint64 + return ids } diff --git a/e2e/types/testnet.go b/e2e/types/testnet.go index 60ec9ebc5..decf40ca0 100644 --- a/e2e/types/testnet.go +++ b/e2e/types/testnet.go @@ -133,6 +133,26 @@ func (t Testnet) HasOmniEVM() bool { return len(t.OmniEVMs) > 0 } +// EVMChains returns all EVM chains in the network. +func (t Testnet) EVMChains() []EVMChain { + var chains []EVMChain + + for _, c := range t.PublicChains { + chains = append(chains, c.Chain()) + } + + for _, c := range t.AnvilChains { + chains = append(chains, c.Chain) + } + + for _, c := range t.OmniEVMs { + chains = append(chains, c.Chain) + break + } + + return chains +} + // EVMChain represents a EVM chain in a omni network. type EVMChain struct { evmchain.Metadata