From d4d198a9cb11b33cd061f35ab85629909df252ed Mon Sep 17 00:00:00 2001 From: Dan Kanefsky Date: Fri, 19 Jan 2024 21:39:31 -0800 Subject: [PATCH] fix config parsing --- cmd/process.go | 4 +-- cmd/process_test.go | 4 +-- cmd/root.go | 51 +++++++++++++++++++++++++++++++++++-- cmd/root_test.go | 25 ++++++++++++++++++ config/sample.yaml | 43 +++++++++++++++++++++++++++++++ ethereum/chain.go | 2 -- ethereum/config.go | 14 +++++----- ethereum/listener_test.go | 5 ++-- ethereum/util_test.go | 3 ++- integration/config.go | 14 +++++----- noble/chain.go | 5 ++++ noble/listener_test.go | 5 ++-- types/config.go | 25 +++++++++--------- types/message_state_test.go | 7 ++--- 14 files changed, 165 insertions(+), 42 deletions(-) create mode 100644 cmd/root_test.go create mode 100644 config/sample.yaml diff --git a/cmd/process.go b/cmd/process.go index 7c4f91d..f9be5de 100644 --- a/cmd/process.go +++ b/cmd/process.go @@ -70,7 +70,7 @@ func Start(cmd *cobra.Command, args []string) { // StartProcessor is the main processing pipeline. func StartProcessor( ctx context.Context, - cfg types.Config, + cfg *types.Config, logger log.Logger, registeredDomains map[types.Domain]types.Chain, processingQueue chan *types.TxState, @@ -159,7 +159,7 @@ func StartProcessor( } // filterDisabledCCTPRoutes returns true if we haven't enabled relaying from a source domain to a destination domain -func filterDisabledCCTPRoutes(cfg types.Config, logger log.Logger, msg *types.MessageState) bool { +func filterDisabledCCTPRoutes(cfg *types.Config, logger log.Logger, msg *types.MessageState) bool { val, ok := cfg.EnabledRoutes[msg.SourceDomain] result := !(ok && val == msg.DestDomain) if result { diff --git a/cmd/process_test.go b/cmd/process_test.go index 3f56198..afb98a1 100644 --- a/cmd/process_test.go +++ b/cmd/process_test.go @@ -14,14 +14,14 @@ import ( "github.com/stretchr/testify/require" ) -var cfg types.Config +var cfg *types.Config var logger log.Logger var processingQueue chan *types.TxState var sequenceMap *types.SequenceMap func setupTest(t *testing.T) map[types.Domain]types.Chain { var err error - cfg, err = types.Parse("../.ignore/unit_tests.yaml") + cfg, err = cmd.Parse("../.ignore/unit_tests.yaml") require.NoError(t, err, "Error parsing config") logger = log.NewLogger(os.Stdout, log.LevelOption(zerolog.DebugLevel)) diff --git a/cmd/root.go b/cmd/root.go index 95385a4..f21a545 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,12 +1,16 @@ package cmd import ( + "fmt" "net/http" "os" "strconv" "github.com/gin-gonic/gin" + "github.com/strangelove-ventures/noble-cctp-relayer/ethereum" + "github.com/strangelove-ventures/noble-cctp-relayer/noble" "github.com/strangelove-ventures/noble-cctp-relayer/types" + "gopkg.in/yaml.v2" "cosmossdk.io/log" "github.com/rs/zerolog" @@ -14,7 +18,7 @@ import ( ) var ( - Cfg types.Config + Cfg *types.Config cfgFile string verbose bool @@ -47,7 +51,7 @@ func init() { } var err error - Cfg, err = types.Parse(cfgFile) + Cfg, err = Parse(cfgFile) if err != nil { Logger.Error("unable to parse config file", "location", cfgFile, "err", err) os.Exit(1) @@ -89,3 +93,46 @@ func getTxByHash(c *gin.Context) { c.JSON(http.StatusNotFound, gin.H{"message": "message not found"}) } + +func Parse(file string) (*types.Config, error) { + data, err := os.ReadFile(file) + if err != nil { + return nil, fmt.Errorf("failed to read file %w", err) + } + + var cfg types.ConfigWrapper + if err := yaml.Unmarshal(data, &cfg); err != nil { + return nil, fmt.Errorf("error unmarshalling config: %w", err) + } + + c := types.Config{ + EnabledRoutes: cfg.EnabledRoutes, + Circle: cfg.Circle, + ProcessorWorkerCount: cfg.ProcessorWorkerCount, + Api: cfg.Api, + Chains: make(map[string]types.ChainConfig), + } + + for name, chain := range cfg.Chains { + yamlbz, err := yaml.Marshal(chain) + if err != nil { + return nil, err + } + + switch name { + case "noble": + var cc noble.ChainConfig + if err := yaml.Unmarshal(yamlbz, &cc); err != nil { + return nil, err + } + c.Chains[name] = &cc + default: + var cc ethereum.ChainConfig + if err := yaml.Unmarshal(yamlbz, &cc); err != nil { + return nil, err + } + c.Chains[name] = &cc + } + } + return &c, err +} diff --git a/cmd/root_test.go b/cmd/root_test.go new file mode 100644 index 0000000..6e4388c --- /dev/null +++ b/cmd/root_test.go @@ -0,0 +1,25 @@ +package cmd_test + +import ( + "testing" + + "github.com/strangelove-ventures/noble-cctp-relayer/cmd" + "github.com/strangelove-ventures/noble-cctp-relayer/ethereum" + "github.com/strangelove-ventures/noble-cctp-relayer/noble" + "github.com/stretchr/testify/require" +) + +func TestConfig(t *testing.T) { + file, err := cmd.Parse("../config/sample.yaml") + require.NoError(t, err, "Error parsing config") + + // assert noble chainConfig correctly parsed + var nobleType interface{} = file.Chains["noble"] + _, ok := nobleType.(*noble.ChainConfig) + require.True(t, ok) + + // assert ethereum chainConfig correctly parsed + var ethType interface{} = file.Chains["ethereum"] + _, ok = ethType.(*ethereum.ChainConfig) + require.True(t, ok) +} diff --git a/config/sample.yaml b/config/sample.yaml new file mode 100644 index 0000000..1c8bd1d --- /dev/null +++ b/config/sample.yaml @@ -0,0 +1,43 @@ +chains: + ethereum: + chain-id: 5 + rpc: "https://goerli.infura.io/v3/apiKey" + ws: "wss://goerli.infura.io/ws/v3/apiKey" + message-transmitter: "0x26413e8157CD32011E726065a5462e97dD4d03D9" + + start-block: 9737196 + lookback-period: 5 # historical blocks to look back on launch + + broadcast-retries: 5 # number of times to attempt the broadcast + broadcast-retry-interval: 10 # time between retries in seconds + + minter-private-key: "privateKey" + + + noble: + rpc: "https://rpc.testnet.noble.strange.love:443" + chain-id: "grand-1" + + start-block: 0 # set to 0 to default to latest block + lookback-period: 5 # historical blocks to look back on launch + workers: 8 + + tx-memo: "Relayed by Strangelove" + gas-limit: 200000 + broadcast-retries: 5 # number of times to attempt the broadcast + broadcast-retry-interval: 5 # time between retries in seconds + + # hex encoded + minter-private-key: "hexEncodedPrivateKey" + +# source domain id -> destination domain id +enabled-routes: + 0: 4 # ethereum to noble + 4: 0 # noble to ethereum + +circle: + attestation-base-url: "https://iris-api-sandbox.circle.com/attestations/" + fetch-retries: 0 # additional times to fetch an attestation + fetch-retry-interval: 3 # time between retries in seconds + +processor-worker-count: 16 diff --git a/ethereum/chain.go b/ethereum/chain.go index 8722217..b228102 100644 --- a/ethereum/chain.go +++ b/ethereum/chain.go @@ -53,7 +53,6 @@ type Ethereum struct { func NewChain( name string, chainID int64, - domain types.Domain, rpcURL string, wsURL string, messageTransmitterAddress string, @@ -70,7 +69,6 @@ func NewChain( return &Ethereum{ name: name, chainID: chainID, - domain: domain, rpcURL: rpcURL, wsURL: wsURL, messageTransmitterAddress: messageTransmitterAddress, diff --git a/ethereum/config.go b/ethereum/config.go index 2be09d1..1dc2558 100644 --- a/ethereum/config.go +++ b/ethereum/config.go @@ -1,15 +1,16 @@ package ethereum -import "github.com/strangelove-ventures/noble-cctp-relayer/types" +import ( + "github.com/strangelove-ventures/noble-cctp-relayer/types" +) var _ types.ChainConfig = (*ChainConfig)(nil) type ChainConfig struct { - DomainID types.Domain `yaml:"domain-id"` - ChainID int64 `yaml:"chain-id"` - RPC string `yaml:"rpc"` - WS string `yaml:"ws"` - MessageTransmitter string `yaml:"message-transmitter"` + RPC string `yaml:"rpc"` + WS string `yaml:"ws"` + ChainID int64 `yaml:"chain-id"` + MessageTransmitter string `yaml:"message-transmitter"` StartBlock uint64 `yaml:"start-block"` LookbackPeriod uint64 `yaml:"lookback-period"` @@ -25,7 +26,6 @@ func (c *ChainConfig) Chain(name string) (types.Chain, error) { return NewChain( name, c.ChainID, - c.DomainID, c.RPC, c.WS, c.MessageTransmitter, diff --git a/ethereum/listener_test.go b/ethereum/listener_test.go index 1418e06..4548a8c 100644 --- a/ethereum/listener_test.go +++ b/ethereum/listener_test.go @@ -8,18 +8,19 @@ import ( "cosmossdk.io/log" "github.com/rs/zerolog" + "github.com/strangelove-ventures/noble-cctp-relayer/cmd" "github.com/strangelove-ventures/noble-cctp-relayer/ethereum" "github.com/strangelove-ventures/noble-cctp-relayer/types" "github.com/stretchr/testify/require" ) -var cfg types.Config +var cfg *types.Config var logger log.Logger var processingQueue chan *types.TxState func init() { var err error - cfg, err = types.Parse("../../.ignore/unit_tests.yaml") + cfg, err = cmd.Parse("../.ignore/unit_tests.yaml") if err != nil { panic(err) } diff --git a/ethereum/util_test.go b/ethereum/util_test.go index 4406b82..e4e8f83 100644 --- a/ethereum/util_test.go +++ b/ethereum/util_test.go @@ -6,6 +6,7 @@ import ( "cosmossdk.io/log" "github.com/rs/zerolog" + "github.com/strangelove-ventures/noble-cctp-relayer/cmd" "github.com/strangelove-ventures/noble-cctp-relayer/ethereum" "github.com/strangelove-ventures/noble-cctp-relayer/types" "github.com/stretchr/testify/require" @@ -13,7 +14,7 @@ import ( func init() { var err error - cfg, err = types.Parse("../../.ignore/unit_tests.yaml") + cfg, err = cmd.Parse("../.ignore/unit_tests.yaml") if err != nil { panic(err) } diff --git a/integration/config.go b/integration/config.go index 8ddec3d..cb6e600 100644 --- a/integration/config.go +++ b/integration/config.go @@ -1,19 +1,21 @@ package integration_testing import ( + "os" + "cosmossdk.io/log" "github.com/rs/zerolog" + "github.com/strangelove-ventures/noble-cctp-relayer/cmd" "github.com/strangelove-ventures/noble-cctp-relayer/cmd/noble" - "github.com/strangelove-ventures/noble-cctp-relayer/config" "github.com/strangelove-ventures/noble-cctp-relayer/types" - "os" "gopkg.in/yaml.v3" ) -var testCfg Config // for testing secrets -var cfg config.Config // app config +var testCfg *types.Config // for testing secrets +var cfg *types.Config // app config var logger log.Logger +var err error // goerli const TokenMessengerAddress = "0xd0c3da58f55358142b8d3e06c1c30c5c6114efe8" @@ -24,8 +26,8 @@ var sequenceMap *types.SequenceMap func setupTest() func() { // setup - testCfg = Parse("../.ignore/integration.yaml") - cfg = config.Parse("../.ignore/testnet.yaml") + testCfg, err = cmd.Parse("../.ignore/integration.yaml") + cfg, err = cmd.Parse("../.ignore/testnet.yaml") logger = log.NewLogger(os.Stdout, log.LevelOption(zerolog.DebugLevel)) _, nextMinterSequence, err := noble.GetNobleAccountNumberSequence( diff --git a/noble/chain.go b/noble/chain.go index cebe3a2..67ca19b 100644 --- a/noble/chain.go +++ b/noble/chain.go @@ -286,6 +286,9 @@ func (n *Noble) Broadcast( // sign and broadcast txn for attempt := 0; attempt <= n.maxRetries; attempt++ { + //TODO: MOVE EVERYTHING IN FOR LOOP TO FUNCTION. Same for ETH. + // see todo below. + var receiveMsgs []sdk.Msg for _, msg := range msgs { @@ -327,6 +330,8 @@ func (n *Noble) Broadcast( txBuilder.SetMemo(n.txMemo) n.mu.Lock() + // TODO: uncomment this & remove all remainin n.mu.Unlock() 's after moving loop body to its own function + // defer n.mu.Unlock() accountSequence := sequenceMap.Next(n.Domain()) diff --git a/noble/listener_test.go b/noble/listener_test.go index 108f982..9de5bd1 100644 --- a/noble/listener_test.go +++ b/noble/listener_test.go @@ -8,18 +8,19 @@ import ( "cosmossdk.io/log" "github.com/rs/zerolog" + "github.com/strangelove-ventures/noble-cctp-relayer/cmd" "github.com/strangelove-ventures/noble-cctp-relayer/noble" "github.com/strangelove-ventures/noble-cctp-relayer/types" "github.com/stretchr/testify/require" ) -var cfg types.Config +var cfg *types.Config var logger log.Logger var processingQueue chan *types.TxState func init() { var err error - cfg, err = types.Parse("../../.ignore/unit_tests.yaml") + cfg, err = cmd.Parse("../../.ignore/unit_tests.yaml") if err != nil { panic(err) } diff --git a/types/config.go b/types/config.go index 2da8dcb..92d2c09 100644 --- a/types/config.go +++ b/types/config.go @@ -1,11 +1,5 @@ package types -import ( - "os" - - "gopkg.in/yaml.v3" -) - type Config struct { Chains map[string]ChainConfig `yaml:"chains"` EnabledRoutes map[Domain]Domain `yaml:"enabled-routes"` @@ -20,13 +14,18 @@ type Config struct { } `yaml:"api"` } -func Parse(file string) (cfg Config, err error) { - data, err := os.ReadFile(file) - if err != nil { - return - } - err = yaml.Unmarshal(data, &cfg) - return cfg, err +type ConfigWrapper struct { + Chains map[string]map[string]any `yaml:"chains"` + EnabledRoutes map[Domain]Domain `yaml:"enabled-routes"` + Circle struct { + AttestationBaseUrl string `yaml:"attestation-base-url"` + FetchRetries int `yaml:"fetch-retries"` + FetchRetryInterval int `yaml:"fetch-retry-interval"` + } `yaml:"circle"` + ProcessorWorkerCount uint32 `yaml:"processor-worker-count"` + Api struct { + TrustedProxies []string `yaml:"trusted-proxies"` + } `yaml:"api"` } type ChainConfig interface { diff --git a/types/message_state_test.go b/types/message_state_test.go index 2036c3b..348959c 100644 --- a/types/message_state_test.go +++ b/types/message_state_test.go @@ -12,16 +12,17 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/pascaldekloe/etherstream" + "github.com/strangelove-ventures/noble-cctp-relayer/cmd" ethinternal "github.com/strangelove-ventures/noble-cctp-relayer/ethereum" "github.com/strangelove-ventures/noble-cctp-relayer/types" "github.com/stretchr/testify/require" ) -var cfg types.Config +var cfg *types.Config func init() { var err error - cfg, err = types.Parse("../../.ignore/unit_tests.yaml") + cfg, err = cmd.Parse("../.ignore/unit_tests.yaml") if err != nil { panic(err) } @@ -29,7 +30,7 @@ func init() { func TestToMessageStateSuccess(t *testing.T) { - messageTransmitter, err := os.Open("../cmd/ethereum/abi/MessageTransmitter.json") + messageTransmitter, err := os.Open("../ethereum/abi/MessageTransmitter.json") require.Nil(t, err) messageTransmitterABI, err := abi.JSON(messageTransmitter)