Skip to content

Commit

Permalink
test(e2e): add netman and staging
Browse files Browse the repository at this point in the history
  • Loading branch information
corverroos committed Jan 29, 2024
1 parent 4f819a6 commit f0b30c6
Show file tree
Hide file tree
Showing 15 changed files with 556 additions and 215 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ devnet-stop: ## Stops devnet1 containers (alias for MANIFEST=devnet1 make e2e-st
e2e-run: ## Run specific e2e manifest (MANIFEST=single, MANIFEST=simple, etc). Note container remain running after the test.
@if [ -z "$(MANIFEST)" ]; then echo "⚠️ Please specify a manifest: MANIFEST=simple make e2e-run" && exit 1; fi
@echo "Using MANIFEST=$(MANIFEST)"
@go run github.com/omni-network/omni/test/e2e/runner -f test/e2e/manifests/$(MANIFEST).toml -p
@go run github.com/omni-network/omni/test/e2e/runner -f test/e2e/manifests/$(MANIFEST).toml

.PHONY: e2e-logs
e2e-logs: ## Print the docker logs of previously ran e2e manifest (single, simple, etc).
Expand Down
6 changes: 6 additions & 0 deletions test/e2e/manifests/staging.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
network="staging"

[node.validator01]
[node.validator02]
[node.validator03]
[node.validator04]
94 changes: 5 additions & 89 deletions test/e2e/runner/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,95 +2,16 @@ package main

import (
"context"
"math/big"
"strings"
"time"

"github.com/omni-network/omni/contracts/bindings"
"github.com/omni-network/omni/lib/errors"
"github.com/omni-network/omni/lib/log"
"github.com/omni-network/omni/lib/netconf"
"github.com/omni-network/omni/test/e2e/runner/netman"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)

const (
// privKeyHex0 of pre-funded anvil account 0.
privKeyHex0 = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
// privKeyHex1 of pre-funded anvil account 1.
privKeyHex1 = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
)

type Portal struct {
Chain netconf.Chain
Client *ethclient.Client
Contract *bindings.OmniPortal
}

func DeployContracts(ctx context.Context, network netconf.Network) (map[uint64]Portal, error) {
log.Info(ctx, "Deploying portal contracts")

resp := make(map[uint64]Portal)
for _, chain := range network.Chains {
ethClient, err := ethclient.Dial(chain.RPCURL)
if err != nil {
return nil, errors.Wrap(err, "dial chain")
}

txOpts, err := newTxOpts(ctx, privKeyHex0, chain.ID)
if err != nil {
return nil, err
}

addr, _, _, err := bindings.DeployOmniPortal(txOpts, ethClient)
if err != nil {
return nil, errors.Wrap(err, "deploy portal")
} else if addr.Hex() != chain.PortalAddress {
return nil, errors.New("portal address mismatch",
"chain", chain.Name,
"expect", chain.PortalAddress,
"actual", addr.Hex(),
)
}

contract, err := bindings.NewOmniPortal(addr, ethClient)
if err != nil {
return nil, errors.Wrap(err, "create portal contract")
}

resp[chain.ID] = Portal{
Chain: chain,
Client: ethClient,
Contract: contract,
}
}

return resp, nil
}

func newTxOpts(ctx context.Context, privKeyHex string, chainID uint64) (*bind.TransactOpts, error) {
pk, err := crypto.HexToECDSA(strings.TrimPrefix(privKeyHex, "0x"))
if err != nil {
return nil, errors.Wrap(err, "parse private key")
}

txOpts, err := bind.NewKeyedTransactorWithChainID(
pk,
big.NewInt(int64(chainID)),
)
if err != nil {
return nil, errors.Wrap(err, "keyed tx ops")
}

txOpts.Context = ctx

return txOpts, nil
}

func StartSendingXMsgs(ctx context.Context, portals map[uint64]Portal) error {
func StartSendingXMsgs(ctx context.Context, portals map[uint64]netman.Portal) error {
log.Info(ctx, "Generating cross chain messages async")
go func() {
for ctx.Err() == nil {
Expand All @@ -109,7 +30,7 @@ func StartSendingXMsgs(ctx context.Context, portals map[uint64]Portal) error {
}

// SendXMsgs sends one xmsg from every chain to every other chain.
func SendXMsgs(ctx context.Context, portals map[uint64]Portal) error {
func SendXMsgs(ctx context.Context, portals map[uint64]netman.Portal) error {
for _, from := range portals {
for _, to := range portals {
if from.Chain.ID == to.Chain.ID {
Expand All @@ -126,13 +47,8 @@ func SendXMsgs(ctx context.Context, portals map[uint64]Portal) error {
}

// xcall sends a ethereum transaction to the portal contract, triggering a xcall.
func xcall(ctx context.Context, from Portal, destChainID uint64) error {
txOpts, err := newTxOpts(ctx, privKeyHex0, from.Chain.ID)
if err != nil {
return err
}

_, err = from.Contract.Xcall(txOpts, destChainID, common.Address{}, nil)
func xcall(ctx context.Context, from netman.Portal, destChainID uint64) error {
_, err := from.Contract.Xcall(from.TxOpts(ctx), destChainID, common.Address{}, nil)
if err != nil {
return errors.Wrap(err, "xcall",
"sourc_chain", from.Chain.ID,
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/runner/docker/compose.yaml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ services:
e2e: true
container_name: chain_a
image: ghcr.io/foundry-rs/foundry:latest
entrypoint: ['anvil','--host','0.0.0.0','--chain-id','100','--block-time','1']
entrypoint: ['anvil','--host','0.0.0.0','--chain-id','100','--block-time','1', "--silent"]
ports:
- "6545:8545"
- "6546:8546"
Expand Down
82 changes: 43 additions & 39 deletions test/e2e/runner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (
libcmd "github.com/omni-network/omni/lib/cmd"
"github.com/omni-network/omni/lib/errors"
"github.com/omni-network/omni/lib/log"
"github.com/omni-network/omni/lib/netconf"
"github.com/omni-network/omni/test/e2e/runner/docker"
"github.com/omni-network/omni/test/e2e/runner/network"
"github.com/omni-network/omni/test/e2e/runner/netman"

k1 "github.com/cometbft/cometbft/crypto/secp256k1"
e2e "github.com/cometbft/cometbft/test/e2e/pkg"
Expand All @@ -26,17 +25,20 @@ func main() {

// CLI is the Cobra-based command-line interface.
type CLI struct {
root *cobra.Command
testnet *e2e.Testnet
preserve bool
skipTests bool
infp infra.Provider
network netconf.Network
root *cobra.Command
testnet *e2e.Testnet
infp infra.Provider
mngr netman.Manager

preserve bool
skipTests bool
deployKeyFile string
relayerKeyFile string
}

// NewCLI sets up the CLI.
func NewCLI() *CLI {
cli := &CLI{network: network.NewE2E()}
cli := &CLI{}
cli.root = &cobra.Command{
Use: "runner",
Short: "End-to-end test runner",
Expand All @@ -47,12 +49,17 @@ func NewCLI() *CLI {
if err != nil {
return errors.Wrap(err, "getting file")
}
m, err := e2e.LoadManifest(file)
m, err := LoadManifest(file)
if err != nil {
return errors.Wrap(err, "loading manifest")
}

ifd, err := e2e.NewDockerInfrastructureData(m)
mngr, err := netman.NewManager(m.Network, cli.deployKeyFile, cli.relayerKeyFile)
if err != nil {
return errors.Wrap(err, "get network")
}

ifd, err := e2e.NewDockerInfrastructureData(m.Manifest)
if err != nil {
return errors.Wrap(err, "creating docker infrastructure data")
}
Expand All @@ -63,7 +70,8 @@ func NewCLI() *CLI {
}

cli.testnet = adaptTestnet(testnet)
cli.infp = docker.NewProvider(testnet, ifd, chainServices(cli.network))
cli.mngr = mngr
cli.infp = docker.NewProvider(testnet, ifd, mngr.AdditionalService())

return nil
},
Expand All @@ -73,22 +81,25 @@ func NewCLI() *CLI {
if err := Cleanup(ctx, cli.testnet); err != nil {
return err
}
if err := Setup(ctx, cli.testnet, cli.infp, cli.network); err != nil {
if err := Setup(ctx, cli.testnet, cli.infp, cli.mngr); err != nil {
return err
}

if err := cli.mngr.DeployPublicPortals(ctx); err != nil {
return err
}

if err := Start(ctx, cli.testnet, cli.infp); err != nil {
return err
}

portals, err := DeployContracts(ctx, cli.network)
if err != nil {
if err := cli.mngr.DeployPrivatePortals(ctx); err != nil {
return err
}

sendCtx, sendCancel := context.WithCancel(ctx)
defer sendCancel()
if err := StartSendingXMsgs(sendCtx, portals); err != nil {
if err := StartSendingXMsgs(sendCtx, cli.mngr.Portals()); err != nil {
return err
}

Expand All @@ -112,21 +123,21 @@ func NewCLI() *CLI {
sendCancel()

if cli.skipTests {
log.Info(ctx, "Skipping tests")
log.Info(ctx, "Skipping tests; --skip-tests=true")
} else {
if err := Test(ctx, cli.testnet, cli.infp.GetInfrastructureData()); err != nil {
if err := Test(ctx, cli.testnet, cli.infp.GetInfrastructureData(), cli.mngr.HostNetwork()); err != nil {
return err
}
}

if err := LogMetrics(ctx, cli.testnet, portals, cli.network); err != nil {
if err := LogMetrics(ctx, cli.testnet, cli.mngr); err != nil {
return err
}

if !cli.preserve {
if err := Cleanup(ctx, cli.testnet); err != nil {
return err
}
if cli.preserve {
log.Warn(ctx, "Docker containers not stopped, --preserve=true", nil)
} else if err := Cleanup(ctx, cli.testnet); err != nil {
return err
}

return nil
Expand All @@ -142,11 +153,17 @@ func NewCLI() *CLI {
cli.root.Flags().BoolVarP(&cli.preserve, "preserve", "p", false,
"Preserves the running of the test net after tests are completed")

cli.root.Flags().StringVar(&cli.deployKeyFile, "deploy-key", "",
"Hex private key used to deploy public chain contracts (needs to be funded)")

cli.root.Flags().StringVar(&cli.deployKeyFile, "relayer-key", "",
"Relayer's hex private key used for submissions on public chains (needs to be funded)")

cli.root.AddCommand(&cobra.Command{
Use: "setup",
Short: "Generates the testnet directory and configuration",
RunE: func(cmd *cobra.Command, args []string) error {
return Setup(cmd.Context(), cli.testnet, cli.infp, cli.network)
return Setup(cmd.Context(), cli.testnet, cli.infp, cli.mngr)
},
})

Expand All @@ -157,7 +174,7 @@ func NewCLI() *CLI {
ctx := cmd.Context()
_, err := os.Stat(cli.testnet.Dir)
if os.IsNotExist(err) {
err = Setup(ctx, cli.testnet, cli.infp, cli.network)
err = Setup(ctx, cli.testnet, cli.infp, cli.mngr)
}
if err != nil {
return errors.Wrap(err, "setup")
Expand Down Expand Up @@ -197,20 +214,7 @@ func NewCLI() *CLI {
Use: "logs",
Short: "Shows the container logs (except anvil)",
RunE: func(cmd *cobra.Command, _ []string) error {
// Get all compose chains and validators
services := chainServices(cli.network)
for _, node := range cli.testnet.Nodes {
services = append(services, node.Name)
}
// Remove all anvils (chain*)
var filtered []string
for _, service := range services {
if !strings.HasPrefix(service, "chain") {
filtered = append(filtered, service)
}
}

args := append([]string{"logs"}, filtered...)
args := append([]string{"logs"}, cli.mngr.AdditionalService()...)

return cmtdocker.ExecComposeVerbose(cmd.Context(), cli.testnet.Dir, args...)
},
Expand Down
27 changes: 27 additions & 0 deletions test/e2e/runner/manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
"github.com/omni-network/omni/lib/errors"

e2e "github.com/cometbft/cometbft/test/e2e/pkg"

"github.com/BurntSushi/toml"
)

// Manifest wraps e2e.Manifest with additional omni-specific fields.
type Manifest struct {
e2e.Manifest

Network string `toml:"network"`
}

// LoadManifest loads a manifest from disk.
func LoadManifest(path string) (Manifest, error) {
manifest := Manifest{}
_, err := toml.DecodeFile(path, &manifest)
if err != nil {
return manifest, errors.Wrap(err, "decode manifest")
}

return manifest, nil
}
9 changes: 5 additions & 4 deletions test/e2e/runner/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,25 @@ import (
"github.com/omni-network/omni/lib/errors"
"github.com/omni-network/omni/lib/log"
"github.com/omni-network/omni/lib/netconf"
"github.com/omni-network/omni/test/e2e/runner/netman"

e2e "github.com/cometbft/cometbft/test/e2e/pkg"
)

func LogMetrics(ctx context.Context, testnet *e2e.Testnet, portals map[uint64]Portal, network netconf.Network) error {
func LogMetrics(ctx context.Context, testnet *e2e.Testnet, mngr netman.Manager) error {
// Just pick the first node for now.
if err := MonitorCProvider(ctx, testnet.Nodes[0], network); err != nil {
if err := MonitorCProvider(ctx, testnet.Nodes[0], mngr.HostNetwork()); err != nil {
return errors.Wrap(err, "monitoring cchain provider")
}

if err := MonitorCursors(ctx, portals, network); err != nil {
if err := MonitorCursors(ctx, mngr.Portals(), mngr.HostNetwork()); err != nil {
return errors.Wrap(err, "monitoring cursors")
}

return nil
}

func MonitorCursors(ctx context.Context, portals map[uint64]Portal, network netconf.Network) error {
func MonitorCursors(ctx context.Context, portals map[uint64]netman.Portal, network netconf.Network) error {
for _, dest := range network.Chains {
for _, src := range network.Chains {
if src.ID == dest.ID {
Expand Down
Loading

0 comments on commit f0b30c6

Please sign in to comment.