From c2ad91df4a9695b40188d21867dc0d49df8dd5bd Mon Sep 17 00:00:00 2001 From: corver Date: Thu, 17 Oct 2024 19:26:03 +0200 Subject: [PATCH] ci(e2e): add mainnet manifest (#2211) Adds mainnet manifest including keys created by `e2e key-create-all` issue: #2079 --- e2e/cmd/cmd.go | 85 +------------ e2e/cmd/keys.go | 252 +++++++++++++++++++++++++++++++++++++ e2e/manifests/mainnet.toml | 83 +++++++++++- 3 files changed, 334 insertions(+), 86 deletions(-) create mode 100644 e2e/cmd/keys.go diff --git a/e2e/cmd/cmd.go b/e2e/cmd/cmd.go index 3cd083509..5f7fcff06 100644 --- a/e2e/cmd/cmd.go +++ b/e2e/cmd/cmd.go @@ -6,8 +6,6 @@ import ( "regexp" "github.com/omni-network/omni/e2e/app" - "github.com/omni-network/omni/e2e/app/eoa" - "github.com/omni-network/omni/e2e/app/key" "github.com/omni-network/omni/e2e/docker" "github.com/omni-network/omni/e2e/types" libcmd "github.com/omni-network/omni/lib/cmd" @@ -15,8 +13,6 @@ import ( "github.com/omni-network/omni/lib/log" "github.com/omni-network/omni/lib/netconf" - "github.com/ethereum/go-ethereum/common" - "github.com/spf13/cobra" ) @@ -82,6 +78,7 @@ func New() *cobra.Command { newUpgradeCmd(&def), newRestartCmd(&def), newKeyCreate(&def), + newKeyCreateAll(&def), newAdminCmd(&def), newERC20FaucetCmd(&def), newDeployGasAppCmd(&def), @@ -208,35 +205,6 @@ func newCreate3DeployCmd(def *app.Definition) *cobra.Command { return cmd } - -func newKeyCreate(def *app.Definition) *cobra.Command { - cfg := key.UploadConfig{} - - cmd := &cobra.Command{ - Use: "key-create", - Short: "Creates a private key in GCP secret manager for a node in a manifest", - RunE: func(cmd *cobra.Command, _ []string) error { - if def.Testnet.Network == netconf.Simnet || def.Testnet.Network == netconf.Devnet { - return errors.New("cannot create keys for simnet or devnet") - } - - cfg.Network = def.Testnet.Network - - if err := verifyKeyNodeType(*def, cfg); err != nil { - return err - } - - _, err := key.UploadNew(cmd.Context(), cfg) - - return err - }, - } - - bindKeyCreateFlags(cmd, &cfg) - - return cmd -} - func fundAccounts(def *app.Definition) *cobra.Command { var dryRun bool @@ -291,54 +259,3 @@ func newDeployGasAppCmd(def *app.Definition) *cobra.Command { return cmd } - -// verifyKeyNodeType checks if the node exists in the manifest and if the key type is allowed for the node. -func verifyKeyNodeType(def app.Definition, cfg key.UploadConfig) error { - if err := cfg.Type.Verify(); err != nil { - return err - } - - if cfg.Type == key.EOA { - eoaRole := eoa.Role(cfg.Name) - if err := eoaRole.Verify(); err != nil { - return errors.Wrap(err, "verifying name as eoa type") - } - - account, ok := eoa.AccountForRole(def.Testnet.Network, eoaRole) - if !ok { - return errors.New("eoa account not found", "role", eoaRole) - } - - if account.Type != eoa.TypeSecret { - return errors.New("cannot create eoa key for non secret account") - } - - if account.Address != (common.Address{}) { - return errors.New("cannot create eoa key already defined", "addr", account.Address.Hex()) - } - - return nil - } - - for _, node := range def.Testnet.Nodes { - if node.Name == cfg.Name { - if cfg.Type == key.P2PExecution { - return errors.New("cannot create execution key for halo node") - } - - return nil - } - } - - for _, evm := range def.Testnet.OmniEVMs { - if evm.InstanceName == cfg.Name { - if cfg.Type != key.P2PExecution { - return errors.New("only execution keys allowed for evm nodes") - } - - return nil - } - } - - return errors.New("node not found", "name", cfg.Name) -} diff --git a/e2e/cmd/keys.go b/e2e/cmd/keys.go new file mode 100644 index 000000000..c60317003 --- /dev/null +++ b/e2e/cmd/keys.go @@ -0,0 +1,252 @@ +package cmd + +import ( + "bytes" + "fmt" + "io" + "reflect" + + "github.com/omni-network/omni/e2e/app" + "github.com/omni-network/omni/e2e/app/eoa" + "github.com/omni-network/omni/e2e/app/key" + "github.com/omni-network/omni/e2e/types" + "github.com/omni-network/omni/lib/errors" + "github.com/omni-network/omni/lib/log" + "github.com/omni-network/omni/lib/netconf" + + "github.com/ethereum/go-ethereum/common" + + "github.com/naoina/toml" + "github.com/spf13/cobra" +) + +func newKeyCreate(def *app.Definition) *cobra.Command { + cfg := key.UploadConfig{} + + cmd := &cobra.Command{ + Use: "key-create", + Short: "Creates a private key in GCP secret manager for a node in a manifest", + RunE: func(cmd *cobra.Command, _ []string) error { + if def.Testnet.Network == netconf.Simnet || def.Testnet.Network == netconf.Devnet { + return errors.New("cannot create keys for simnet or devnet") + } + + cfg.Network = def.Testnet.Network + + if err := verifyKeyNodeType(*def, cfg); err != nil { + return errors.Wrap(err, "verify cfg", "name", cfg.Name, "type", cfg.Type) + } + + _, err := key.UploadNew(cmd.Context(), cfg) + + return err + }, + } + + bindKeyCreateFlags(cmd, &cfg) + + return cmd +} + +func newKeyCreateAll(def *app.Definition) *cobra.Command { + cmd := &cobra.Command{ + Use: "key-create-all", + Short: "Creates (if required) all private keys in GCP secret manager for nodes in a manifest", + RunE: func(cmd *cobra.Command, _ []string) error { + if def.Testnet.Network == netconf.Simnet || def.Testnet.Network == netconf.Devnet { + return errors.New("cannot create keys for simnet or devnet") + } + + ctx := cmd.Context() + network := def.Testnet.Network + manifest := def.Manifest + if manifest.Keys == nil { + manifest.Keys = make(map[string]map[key.Type]string) + } + + for _, cfg := range allKeyConfigs(*def) { + log.Debug(ctx, "Checking key", "name", cfg.Name, "type", cfg.Type) + + // Check if key already defined + if cfg.Type == key.EOA { + _, ok := eoa.Address(network, eoa.Role(cfg.Name)) + if ok { + log.Info(ctx, "Skipping eoa key already defined", "name", cfg.Name) + continue + } + } else { + _, ok := def.Manifest.Keys[cfg.Name][cfg.Type] + if ok { + log.Info(ctx, "Skipping secret key already in manifest", "name", cfg.Name, "type", cfg.Type) + continue + } + } + + if err := verifyKeyNodeType(*def, cfg); err != nil { + return errors.Wrap(err, "verify cfg", "name", cfg.Name, "type", cfg.Type) + } + + privkey, err := key.UploadNew(ctx, cfg) + if err != nil { + return errors.Wrap(err, "upload key", "name", cfg.Name, "type", cfg.Type) + } + + addr, err := privkey.Addr() + if err != nil { + return err + } + + if cfg.Type != key.EOA { + if _, ok := manifest.Keys[cfg.Name]; !ok { + manifest.Keys[cfg.Name] = make(map[key.Type]string) + } + manifest.Keys[cfg.Name][cfg.Type] = addr + } + } + + if err := printKeysToml(manifest.Keys, cmd.OutOrStdout()); err != nil { + return errors.Wrap(err, "write keys toml") + } + + return nil + }, + } + + return cmd +} + +// verifyKeyNodeType checks if the node exists in the manifest and if the key type is allowed for the node. +func verifyKeyNodeType(def app.Definition, cfg key.UploadConfig) error { + if err := cfg.Type.Verify(); err != nil { + return err + } + + if cfg.Type != key.EOA { + // Non-EOA keys must be not already defined in the manifest. + _, ok := def.Manifest.Keys[cfg.Name][cfg.Type] + if ok { + return errors.New("key already exists in manifest") + } + } + + if cfg.Type == key.EOA { + eoaRole := eoa.Role(cfg.Name) + if err := eoaRole.Verify(); err != nil { + return errors.Wrap(err, "verifying name as eoa type") + } + + account, ok := eoa.AccountForRole(def.Testnet.Network, eoaRole) + if !ok { + return errors.New("eoa account not found") + } + + if account.Type != eoa.TypeSecret { + return errors.New("cannot create eoa key for non secret account") + } + + if account.Address != (common.Address{}) { + return errors.New("cannot create eoa key already defined", "addr", account.Address.Hex()) + } + + return nil + } + + for _, node := range def.Testnet.Nodes { + if node.Name == cfg.Name { + if cfg.Type == key.P2PExecution { + return errors.New("cannot create execution key for halo node") + } + + return nil + } + } + + for _, evm := range def.Testnet.OmniEVMs { + if evm.InstanceName == cfg.Name { + if cfg.Type != key.P2PExecution { + return errors.New("only execution keys allowed for evm nodes") + } + + return nil + } + } + + return errors.New("node not found") +} + +// allKeyConfigs returns all key configurations for a given manifest. +func allKeyConfigs(def app.Definition) []key.UploadConfig { + var cfgs []key.UploadConfig + + // We need a relayer and monitor EOA key + cfgs = append(cfgs, + key.UploadConfig{ + Network: def.Testnet.Network, + Name: string(eoa.RoleRelayer), + Type: key.EOA, + }, key.UploadConfig{ + Network: def.Testnet.Network, + Name: string(eoa.RoleMonitor), + Type: key.EOA, + }, + ) + + // All evm's need execution P2P keys + for _, evm := range def.Testnet.OmniEVMs { + cfgs = append(cfgs, key.UploadConfig{ + Network: def.Testnet.Network, + Name: evm.InstanceName, + Type: key.P2PExecution, + }) + } + + for _, node := range def.Testnet.Nodes { + // All halo's need consensus P2P keys + cfgs = append(cfgs, key.UploadConfig{ + Network: def.Testnet.Network, + Name: node.Name, + Type: key.P2PConsensus, + }) + + // Validators need validator keys + if node.Mode == types.ModeValidator { + cfgs = append(cfgs, key.UploadConfig{ + Network: def.Testnet.Network, + Name: node.Name, + Type: key.Validator, + }) + } + } + + return cfgs +} + +// printKeysToml prints the keys to as toml. +func printKeysToml(keys map[string]map[key.Type]string, w io.Writer) error { + keysOnly := struct { + Keys map[string]map[key.Type]string `toml:"keys"` + }{ + Keys: keys, + } + var buf bytes.Buffer + + tomlSettings := toml.Config{ + NormFieldName: func(_ reflect.Type, key string) string { + return key + }, + FieldToKey: func(_ reflect.Type, field string) string { + return field + }, + MissingField: func(rt reflect.Type, field string) error { + return errors.New("field not defined", "field", field, "type", rt.String()) + }, + } + err := tomlSettings.NewEncoder(&buf).Encode(keysOnly) + if err != nil { + return errors.Wrap(err, "encode manifest") + } + + _, _ = fmt.Fprint(w, buf.String()) + + return nil +} diff --git a/e2e/manifests/mainnet.toml b/e2e/manifests/mainnet.toml index 17fb3a83a..eb8917daf 100644 --- a/e2e/manifests/mainnet.toml +++ b/e2e/manifests/mainnet.toml @@ -1,5 +1,84 @@ network = "mainnet" -public_chains = ["ethereum"] +public_chains = [] # TBD -only_monitor = true +multi_omni_evms = true prometheus = true + + +[node.validator01] +[node.validator02] +[node.validator03] +[node.validator04] + +[node.seed01] +mode = "seed" +[node.seed02] +mode = "seed" + +[node.fullnode01] +mode = "full" +[node.fullnode02] +mode = "full" + +[node.archive01] +mode = "archive" +[node.archive02] +mode = "archive" +[node.archive03] +mode = "archive" + +# Validator Keys +[keys.validator01] +p2p_consensus = "47AEAB2672A084F27CE04BDED0BC1DB608501070" +validator = "0x58D2A4e3880635B7682A1BB7Ed8a43F5ac6cFD3d" +[keys.validator01_evm] +p2p_execution = "0x1eAf646255aE66164e5F366397FE94Ea0345e140" +[keys.validator02] +p2p_consensus = "0093BBC5D625A10D560101C4F3AD763B16A6A608" +validator = "0x19a4Cb685af95A96BEd67C764b6dB137978a5B17" +[keys.validator02_evm] +p2p_execution = "0x683d5892729d5fC9670e68b3e3bABFdb4d01b7c9" +[keys.validator03] +p2p_consensus = "BD8B56EDE6AE5475671B39155D5EE8E674F48D5A" +validator = "0xB007d2A7e4C27CECF62c1cEc7517550ab599c6c8" +[keys.validator03_evm] +p2p_execution = "0x30251DdFBEbB7809D2137EDA7dc70cA2ed18a056" +[keys.validator04] +p2p_consensus = "1A48E18DDBF09C5D0605592CE406B0F9A5D1842D" +validator = "0x1B169F0Da80B6A074EC261C0e18e43109b151553" +[keys.validator04_evm] +p2p_execution = "0x18311881059D7F4A6DA363f45737259Fc541AbFF" + +# Seed keys +[keys.seed01] +p2p_consensus = "D0A9109801C7F78759A20765C30B00D06A6C2A8F" +[keys.seed01_evm] +p2p_execution = "0xcCA3DA71A9dd6ddB33Ff02dF1f4b75297D0aE8de" +[keys.seed02] +p2p_consensus = "C84E6A5E3C29F1B59B225613BE056E82AB5663C7" +[keys.seed02_evm] +p2p_execution = "0x1421b7476c3ba42E46D9D03781b6D8a3DCf4fCA1" + +# Archive keys +[keys.archive01] +p2p_consensus = "EAE99C1F0FAABA9AD96C943F17DE350566B028DD" +[keys.archive01_evm] +p2p_execution = "0x16a4e1D05518Be06313FAF02CC26D4c0715B8265" +[keys.archive02] +p2p_consensus = "95F7A9277E3FFB37B81E0653F23CE8C57F9DFBC0" +[keys.archive02_evm] +p2p_execution = "0xC7D4e560E05eaE9ba44769BF5f5B56e8d59eC98F" +[keys.archive03] +p2p_consensus = "A0451A082279BDB8971A964CB12FA3C8D1AD8BE4" +[keys.archive03_evm] +p2p_execution = "0x19363Da98cdAEE3E213cd803D43cCee237b67F4F" + +# Fullnode keys +[keys.fullnode01] +p2p_consensus = "87A9BD0A36CD04B5E6A445487D673AA1EF3A9D79" +[keys.fullnode01_evm] +p2p_execution = "0x6d6625acf358CdE192b840815050a90D43Dbb611" +[keys.fullnode02] +p2p_consensus = "D96BEBCD33EBC6224575E45C33E3CBB34707E384" +[keys.fullnode02_evm] +p2p_execution = "0x0391b4FA7f776e486F247363F5ADC0804Fe70C45"