nomad-monorepo icon indicating copy to clipboard operation
nomad-monorepo copied to clipboard

design: unify configuration files into single source of truth

Open yourbuddyconner opened this issue 3 years ago • 11 comments

We currently have several sources of configuration for the various parts of the stack, it makes for a really annoying time when performing housekeeping tasks like updating contracts after a deployment.

Currently we have a web of dependencies starting with the rust configs and contract metadata outputted by nomad-deploy. Tools and applications that get configured based on the output of nomad-deploy are:

  • nomad-sdk
  • nomad-monitor
  • Nomad GUI
  • Nomad Agent Deployment

Proposal:

Build a single config file that acts as the single source of truth for the entire stack. It should contain all necessary data about the shape of a deployment, including fields for:

  • Contract addresses for each component of nomad-core (incl. proxies, upgrade beacon & Implementation)
    • Home addresses on each network
    • Replica addresses corresponding to each home
    • GovernanceRouter addresses
    • BridgeRouter addresses
    • EthHelper addresses
    • TokenRegistry addresses
  • Governor Address(es)
  • RecoveryManager Address(es)
  • Updater and Watcher addresses for each domain
  • Default public RPC Endpoints
  • block times and consensus-related configuration
  • fraud-proof period configuration
  • default agent parameters (?)
  • default agent signers (?)

These config files (one for each environment) would be persisted in the monorepo, referenced by the SDK, and any downstream packages that use the SDK will be automagically configured upon SDK updates.

yourbuddyconner avatar Jan 20 '22 23:01 yourbuddyconner

default agent parameters (?) default agent signers (?)

wdym by this?

anna-carroll avatar Jan 21 '22 12:01 anna-carroll

sketched a flow of what it would look like to automate this process IMG_5526

anna-carroll avatar Jan 21 '22 12:01 anna-carroll

related: https://github.com/nomad-xyz/nomad-monorepo/issues/42

anna-carroll avatar Jan 21 '22 13:01 anna-carroll

default agent parameters (?) default agent signers (?)

wdym by this?

Agent configs currently have placeholders for signer keys, want to ensure this new thing has parity there.

yourbuddyconner avatar Jan 21 '22 20:01 yourbuddyconner

Took a crack at unifying this today, here's an example of that the mainnet config could look like:

{
    "environment": "production",
    "networks": ["ethereum", "moonbeam"],
    "rpcs": {
        "moonbeam": ["https://moonriver.api.onfinality.io/public"],
        "ethereum": ["https://main-light.eth.linkpool.io/"]
    },
    "core": {
        "ethereum": {
            "name": "ethereum",
            "domain": 6648936,
            "connections": ["moonbeam"],
            "consensus": {
                "blockTime": 15,
                "optimisticSeconds": 1800
            },
            "contracts": {
                "upgradeBeaconController": "0xdB378579c2Af11817EEA21474A39F95B5b9DfD7e",
                "xAppConnectionManager": "0xFe8874778f946Ac2990A29eba3CFd50760593B2F",
                "updaterManager": "0x9272C9d5fa902Ef3804EC81e0333Ae420D57f715",
                "governanceRouter": {
                    "implementation": "0x569D80f7FC17316B4C83f072b92EF37B72819DE0",
                    "proxy": "0x3009C99D370B780304D2098196f1EBF779a4777a",
                    "beacon": "0x67833a48b3F509d4252ac2c19cd604556eD6c981"
                },
                "home": {
                    "implementation": "0x8F184D6Aa1977fd2F9d9024317D0ea5cF5815b6f",
                    "proxy": "0x92d3404a7E6c91455BbD81475Cd9fAd96ACFF4c8",
                    "beacon": "0x063e871f8DB991CEAd34B557A00B157B360084cc"
                },
                "remoteReplicas": {
                    "moonbeam": {
                        "implementation": "0x67833a48b3F509d4252ac2c19cd604556eD6c981",
                        "proxy": "0x7F58bb8311DB968AB110889F2Dfa04ab7E8E831B",
                        "beacon": "0x3009C99D370B780304D2098196f1EBF779a4777a"
                    }
                }
            },
            "governance": {
                "governor": {
                    "address": "0x93277b8f5939975b9e6694d5fd2837143afbf68a",
                    "domain": 6648936
                },
                "recoveryManager": "0xda2f881f7f4e9d2b9559f97c7670472a85c1986a",
                "recoveryTimelock": 86400
            },
            "updaters": ["0x71dC76C07E92325e7Cc09117AB94310Da63Fc2b9"],
            "watchers": ["0x9782A3C8128f5D1BD3C9655d03181ba5b420883E"],
            "agents": {
                "rpcStyle": "ethereum",
                "timelag": 20,
                "db": "/path/to/db",
                "logging": {
                    "level": "debug",
                    "fmt": "json"
                },
                "index": {
                    "from": 13983724,
                    "chunk": 2000
                },
                "updater": {
                    "enabled": true,
                    "signers": {
                        "transaction": {},
                        "attestation": ""
                    },
                    "interval": 5
                },
                "relayer": {
                    "enabled": true,
                    "signers": {
                        "transaction": {}
                    },
                    "interval": 10
                },
                "processor": {
                    "enabled": true,
                    "signers": {
                        "transaction": {}
                    },
                    "interval": 5
                },
                "watcher": {
                    "enabled": true,
                    "signers": {
                        "transaction": {},
                        "attestation": ""
                    },
                    "interval": 10
                },
                "kathy": {
                    "enabled": false,
                    "signers": {},
                    "interval": 100
                }
            }
        },
        "moonbeam": {
            "name": "moonbeam",
            "domain": 1650811245,
            "connections": ["ethereum"],
            "consensus": {
                "blockTime": 15,
                "optimisticSeconds": 1800
            },
            "contracts": {
                "upgradeBeaconController": "0xdCe06fFE78AaAc2894109A56BA83C3C33B073F44",
                "xAppConnectionManager": "0xdB378579c2Af11817EEA21474A39F95B5b9DfD7e",
                "updaterManager": "0x2e09EdD238EeaEA6e4da705fbe5922B1979e03aC",
                "governanceRouter": {
                    "implementation": "0x7B39dA90C9eAF87e85C553964BC3CBd674e7CCc1",
                    "proxy": "0x569D80f7FC17316B4C83f072b92EF37B72819DE0",
                    "beacon": "0xA84e233A12b36125A731e1362121d8d4ea030c91"
                },
                "home": {
                    "implementation": "0x9272C9d5fa902Ef3804EC81e0333Ae420D57f715",
                    "proxy": "0x8F184D6Aa1977fd2F9d9024317D0ea5cF5815b6f",
                    "beacon": "0xFe8874778f946Ac2990A29eba3CFd50760593B2F"
                },
                "remoteReplicas": {
                    "ethereum": {
                        "implementation": "0x7F58bb8311DB968AB110889F2Dfa04ab7E8E831B",
                        "proxy": "0x049b51e531Fd8f90da6d92EA83dC4125002F20EF",
                        "beacon": "0x0876dFe4AcAe0e1c0a43302716483f5752298b71"
                    }
                }
            },
            "governance": {
                "governor": {
                    "address": "0x93277b8f5939975b9e6694d5fd2837143afbf68a",
                    "domain": 6648936
                },
                "recoveryManager": "0xea24Ac04DEFb338CA8595C3750E20166F3b4998A",
                "recoveryTimelock": 86400
            },
            "updaters": ["0x40FD91557B318BD5d52D12535795265c88702681"],
            "watchers": ["0x297BBC2F2EAAEB17Ee53F514020bC8173F0570dC"],
            "agents": {
                "rpcStyle": "ethereum",
                "timelag": 20,
                "db": "/path/to/db",
                "logging": {
                    "level": "debug",
                    "fmt": "json"
                },
                "index": {
                    "from": "171256",
                    "chunk": "2000"
                },
                "updater": {
                    "enabled": true,
                    "signers": {
                        "transaction": {},
                        "attestation": ""
                    },
                    "interval": 5
                },
                "relayer": {
                    "enabled": true,
                    "signers": {
                        "transaction": {}
                    },
                    "interval": 10
                },
                "processor": {
                    "enabled": true,
                    "signers": {
                        "transaction": {}
                    },
                    "interval": 5
                },
                "watcher": {
                    "enabled": true,
                    "signers": {
                        "transaction": {},
                        "attestation": ""
                    },
                    "interval": 10
                },
                "kathy": {
                    "enabled": false,
                    "signers": {},
                    "interval": 100
                }
            }
        }
    },
    "bridge": {
        "ethereum": {
            "contracts": {
                "bridgeRouter": {
                    "implementation": "0xD3dfD3eDe74E0DCEBC1AA685e151332857efCe2d",
                    "proxy": "0x88A69B4E698A4B090DF6CF5Bd7B2D47325Ad30A3",
                    "beacon": "0xB70588b1A51F847d13158ff18E9Cac861dF5Fb00"
                },
                "tokenRegistry": {
                    "implementation": "0xa7E4Fea3c1468D6C1A3A77e21e6e43Daed855C1b",
                    "proxy": "0x0A6f564C5c9BeBD66F1595f1B51D1F3de6Ef3b79",
                    "beacon": "0x4D5ff8A01ed833E11Aba43821D2881A5F2911F98"
                },
                "bridgeToken": {
                    "implementation": "0x4ad6444b55729f657A71a82a5448F85aC8aA47ba",
                    "proxy": "0x9f7eA856bA1fB88d35e000c45E75F134A756Ac4F",
                    "beacon": "0x8ca56E6235D83ff2F4E779F0b35A6c856d5a2fb2"
                },
                "ethHelper": "0x2d6775C1673d4cE55e1f827A0D53e62C43d1F304"
            }
        },
        "moonbeam": {
            "contracts": {
                "bridgeRouter": {
                    "implementation": "0x4D5ff8A01ed833E11Aba43821D2881A5F2911F98",
                    "proxy": "0xD3dfD3eDe74E0DCEBC1AA685e151332857efCe2d",
                    "beacon": "0x0A6f564C5c9BeBD66F1595f1B51D1F3de6Ef3b79"
                },
                "tokenRegistry": {
                    "implementation": "0x8ca56E6235D83ff2F4E779F0b35A6c856d5a2fb2",
                    "proxy": "0xa7E4Fea3c1468D6C1A3A77e21e6e43Daed855C1b",
                    "beacon": "0x9f7eA856bA1fB88d35e000c45E75F134A756Ac4F"
                },
                "bridgeToken": {
                    "implementation": "0xEbB99A5B3021C86301dF241d3A32DBEBa5C15801",
                    "proxy": "0x4ad6444b55729f657A71a82a5448F85aC8aA47ba",
                    "beacon": "0x969d515486Ba6133400aC9C73298586426a090F5"
                },
                "ethHelper": "0xB70588b1A51F847d13158ff18E9Cac861dF5Fb00"
            }
        }
    }
}

yourbuddyconner avatar Jan 22 '22 01:01 yourbuddyconner

We should write a tool that validates this config:

  • Ensure core and bridge have keys that are present in networks
  • Ensure core and bridge have no keys that are not present in networks
  • Ensure core.<network>.contracts.remoteReplicas has keys that are present in core.<network>.connections
  • Ensure core.<network>.contracts.remoteReplicas has no keys that are not present in core.<network>.connections
  • Warn if contract address between multiple networks are identical
  • Warn if updater and watcher addresses between multiple networks are identical

yourbuddyconner avatar Jan 22 '22 01:01 yourbuddyconner

Looks good. We also have chainID (https://chainlist.org/) and block explorer url in the GUI configs

ErinHales avatar Jan 22 '22 04:01 ErinHales

Add a connections: [] field to the bridge config to allow for different connection graphs between bridge and core

yourbuddyconner avatar Jan 29 '22 20:01 yourbuddyconner

Take two on unified config, splitting up the files on a logical Home deployment.

https://gist.github.com/yourbuddyconner/f99bb628599a234c1f2d515fe579ed4e

yourbuddyconner avatar Feb 02 '22 18:02 yourbuddyconner

Having a unified file configuration structure consumed by more than one software component (nomad-deploy, nomad-sdk, agent, ....) will introduce some software development and management challenges. I believe, each component should consume configurations from their own config files (i-e: agent.json, nomad-deploy.json,....) with the data structure of their choice. Even if we have duplicated values from one config files to the other, centralizing configuration can be handled at a higher level of our stack instead.

Below are the pros and cons of the current proposal:

Pros:

  • Prevents configuration duplication

Cons:

  • Creates a dependency on the configuration data structure across all stack components.
  • Hard to know what config is consumed by which components without having to look at the code. Over time, we will have stale configuration because it will be hard to cleanup without risking to break other components.
  • When updating configuration we will have to redeploy all components regardless if it's used by the component or not.

I think a solution would be to start refactoring the configuration structure of each component to easily add or remove a network and separate the component specific config. Once done, we should work on a solution to centralize these configurations by engineering or introducing an existing system.

arnaud036 avatar Feb 14 '22 20:02 arnaud036

Creates a dependency on the configuration data structure across all stack components.

this seems better to me than the current state, where there are >=1 struct per component.

other cons I agree with

prestwich avatar Feb 14 '22 23:02 prestwich