From f44f16f2fdbb98e7b31768551bd835b7860873b7 Mon Sep 17 00:00:00 2001 From: rachid Date: Thu, 9 Nov 2023 10:33:05 +0100 Subject: [PATCH 1/7] chore: refactor the flags to base package and allow usage of reference config --- cmd/blobstream/base/config.go | 186 ++++++++++++++++++++++++++ cmd/blobstream/deploy/cmd.go | 2 +- cmd/blobstream/deploy/config.go | 132 +++++++++--------- cmd/blobstream/orchestrator/cmd.go | 2 +- cmd/blobstream/orchestrator/config.go | 111 +++++++-------- cmd/blobstream/query/config.go | 25 ++-- cmd/blobstream/relayer/cmd.go | 2 +- cmd/blobstream/relayer/config.go | 166 ++++++++++++----------- 8 files changed, 409 insertions(+), 217 deletions(-) diff --git a/cmd/blobstream/base/config.go b/cmd/blobstream/base/config.go index b2a3583c..b00ce6fb 100644 --- a/cmd/blobstream/base/config.go +++ b/cmd/blobstream/base/config.go @@ -5,6 +5,8 @@ import ( "os" "strings" + "github.com/celestiaorg/orchestrator-relayer/evm" + "github.com/spf13/cobra" "github.com/pkg/errors" @@ -24,6 +26,19 @@ type Config struct { EVMPassphrase string } +func AddEVMPassphraseFlag(cmd *cobra.Command) { + cmd.Flags().String(FlagEVMPassphrase, "", "the evm account passphrase (if not specified as a flag, it will be asked interactively)") +} + +func GetEVMPassphraseFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagEVMPassphrase) + val, err := cmd.Flags().GetString(FlagEVMPassphrase) + if err != nil { + return "", changed, err + } + return val, changed, err +} + // DefaultServicePath constructs the default Blobstream store path for // the provided service. // It tries to get the home directory from an environment variable @@ -47,20 +62,191 @@ const ( FlagP2PListenAddress = "p2p.listen-addr" FlagP2PNickname = "p2p.nickname" FlagGRPCInsecure = "grpc.insecure" + + FlagEVMAccAddress = "evm.account" + FlagEVMChainID = "evm.chain-id" + FlagEVMRPC = "evm.rpc" + FlagEVMGasLimit = "evm.gas-limit" + FlagEVMContractAddress = "evm.contract-address" + + FlagCoreGRPC = "core.grpc" + FlagCoreRPC = "core.rpc" + + FlagStartingNonce = "starting-nonce" ) +func AddStartingNonceFlag(cmd *cobra.Command) { + cmd.Flags().String( + FlagStartingNonce, + "latest", + "Specify the nonce to start the Blobstream contract from. "+ + "\"earliest\": for genesis, "+ + "\"latest\": for latest nonce, "+ + "\"nonce\": for a specific nonce.", + ) +} + +func GetStartingNonceFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagStartingNonce) + val, err := cmd.Flags().GetString(FlagStartingNonce) + if err != nil { + return "", changed, err + } + return val, changed, err +} + func AddP2PNicknameFlag(cmd *cobra.Command) { cmd.Flags().String(FlagP2PNickname, "", "Nickname of the p2p private key to use (if not provided, an existing one from the p2p store or a newly generated one will be used)") } +func GetP2PNicknameFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagP2PNickname) + val, err := cmd.Flags().GetString(FlagP2PNickname) + if err != nil { + return "", changed, err + } + return val, changed, err +} + func AddP2PListenAddressFlag(cmd *cobra.Command) { cmd.Flags().String(FlagP2PListenAddress, "/ip4/0.0.0.0/tcp/30000", "MultiAddr for the p2p peer to listen on") } +func GetP2PListenAddressFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagP2PListenAddress) + val, err := cmd.Flags().GetString(FlagP2PListenAddress) + if err != nil { + return "", changed, err + } + return val, changed, err +} + func AddBootstrappersFlag(cmd *cobra.Command) { cmd.Flags().String(FlagBootstrappers, "", "Comma-separated multiaddresses of p2p peers to connect to") } +func GetBootstrappersFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagBootstrappers) + val, err := cmd.Flags().GetString(FlagBootstrappers) + if err != nil { + return "", changed, err + } + return val, changed, err +} + func AddGRPCInsecureFlag(cmd *cobra.Command) { cmd.Flags().Bool(FlagGRPCInsecure, false, "allow gRPC over insecure channels, if not TLS the server must use TLS") } + +func GetGRPCInsecureFlag(cmd *cobra.Command) (bool, bool, error) { + changed := cmd.Flags().Changed(FlagGRPCInsecure) + val, err := cmd.Flags().GetBool(FlagGRPCInsecure) + if err != nil { + return false, changed, err + } + return val, changed, err +} + +func AddCoreGRPCFlag(cmd *cobra.Command) { + cmd.Flags().String(FlagCoreGRPC, "localhost:9090", "Specify the celestia app grpc address") +} + +func GetCoreGRPCFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagCoreGRPC) + val, err := cmd.Flags().GetString(FlagCoreGRPC) + if err != nil { + return "", changed, err + } + return val, changed, err +} + +func AddEVMChainIDFlag(cmd *cobra.Command) { + cmd.Flags().Uint64(FlagEVMChainID, 5, "Specify the evm chain id") +} + +func GetEVMChainIDFlag(cmd *cobra.Command) (uint64, bool, error) { + changed := cmd.Flags().Changed(FlagEVMChainID) + val, err := cmd.Flags().GetUint64(FlagEVMChainID) + if err != nil { + return 0, changed, err + } + return val, changed, err +} + +func AddCoreRPCFlag(cmd *cobra.Command) { + cmd.Flags().String(FlagCoreRPC, "tcp://localhost:26657", "Specify the celestia app rest rpc address") +} + +func GetCoreRPCFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagCoreRPC) + val, err := cmd.Flags().GetString(FlagCoreRPC) + if err != nil { + return "", changed, err + } + return val, changed, err +} + +func AddEVMRPCFlag(cmd *cobra.Command) { + cmd.Flags().String(FlagEVMRPC, "http://localhost:8545", "Specify the ethereum rpc address") +} + +func GetEVMRPCFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagEVMRPC) + val, err := cmd.Flags().GetString(FlagEVMRPC) + if err != nil { + return "", changed, err + } + return val, changed, err +} + +func AddEVMContractAddressFlag(cmd *cobra.Command) { + cmd.Flags().String(FlagEVMContractAddress, "", "Specify the contract at which the Blobstream is deployed") +} + +func GetEVMContractAddressFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagEVMContractAddress) + val, err := cmd.Flags().GetString(FlagEVMContractAddress) + if err != nil { + return "", changed, err + } + return val, changed, err +} + +func AddEVMGasLimitFlag(cmd *cobra.Command) { + cmd.Flags().Uint64(FlagEVMGasLimit, evm.DefaultEVMGasLimit, "Specify the evm gas limit") +} + +func GetEVMGasLimitFlag(cmd *cobra.Command) (uint64, bool, error) { + changed := cmd.Flags().Changed(FlagEVMGasLimit) + val, err := cmd.Flags().GetUint64(FlagEVMGasLimit) + if err != nil { + return 0, changed, err + } + return val, changed, err +} + +func AddHomeFlag(cmd *cobra.Command, serviceName string, defaultHomeDir string) { + cmd.Flags().String(FlagHome, defaultHomeDir, fmt.Sprintf("The Blobstream %s home directory", serviceName)) +} + +func GetHomeFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagHome) + val, err := cmd.Flags().GetString(FlagHome) + if err != nil { + return "", changed, err + } + return val, changed, err +} + +func AddEVMAccAddressFlag(cmd *cobra.Command) { + cmd.Flags().String(FlagEVMAccAddress, "", "Specify the EVM account address to use for signing (Note: the private key should be in the keystore)") +} + +func GetEVMAccAddressFlag(cmd *cobra.Command) (string, bool, error) { + changed := cmd.Flags().Changed(FlagEVMAccAddress) + val, err := cmd.Flags().GetString(FlagEVMAccAddress) + if err != nil { + return "", changed, err + } + return val, changed, err +} diff --git a/cmd/blobstream/deploy/cmd.go b/cmd/blobstream/deploy/cmd.go index 68d214b8..3a1bd955 100644 --- a/cmd/blobstream/deploy/cmd.go +++ b/cmd/blobstream/deploy/cmd.go @@ -27,7 +27,7 @@ func Command() *cobra.Command { Use: "deploy ", Short: "Deploys the Blobstream contract and initializes it using the provided Celestia chain", RunE: func(cmd *cobra.Command, args []string) error { - config, err := parseDeployFlags(cmd) + config, err := parseDeployFlags(cmd, &deployConfig{}) if err != nil { return err } diff --git a/cmd/blobstream/deploy/config.go b/cmd/blobstream/deploy/config.go index c3ac1b52..30bf4da0 100644 --- a/cmd/blobstream/deploy/config.go +++ b/cmd/blobstream/deploy/config.go @@ -3,55 +3,37 @@ package deploy import ( "errors" "fmt" + "strings" "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" - "github.com/celestiaorg/orchestrator-relayer/evm" "github.com/spf13/cobra" ) const ( - FlagEVMAccAddress = "evm.account" - FlagEVMChainID = "evm.chain-id" - FlagEVMRPC = "evm.rpc" - FlagEVMGasLimit = "evm.gas-limit" - FlagCoreGRPCHost = "core.grpc.host" - FlagCoreGRPCPort = "core.grpc.port" - FlagCoreRPCHost = "core.rpc.host" - FlagCoreRPCPort = "core.rpc.port" - FlagStartingNonce = "starting-nonce" ServiceNameDeployer = "deployer" ) func addDeployFlags(cmd *cobra.Command) *cobra.Command { - cmd.Flags().String(FlagEVMAccAddress, "", "Specify the EVM account address to use for signing (Note: the private key should be in the keystore)") - cmd.Flags().Uint64(FlagEVMChainID, 5, "Specify the evm chain id") - cmd.Flags().String(FlagCoreGRPCHost, "localhost", "Specify the grpc address host") - cmd.Flags().Uint(FlagCoreGRPCPort, 9090, "Specify the grpc address port") - cmd.Flags().String(FlagCoreRPCHost, "localhost", "Specify the rpc address host") - cmd.Flags().Uint(FlagCoreRPCPort, 26657, "Specify the rpc address port") - cmd.Flags().String(FlagEVMRPC, "http://localhost:8545", "Specify the ethereum rpc address") - cmd.Flags().String( - FlagStartingNonce, - "latest", - "Specify the nonce to start the Blobstream contract from. "+ - "\"earliest\": for genesis, "+ - "\"latest\": for latest valset nonce, "+ - "\"nonce\": for the latest valset before the provided nonce, provided nonce included.", - ) - cmd.Flags().Uint64(FlagEVMGasLimit, evm.DefaultEVMGasLimit, "Specify the evm gas limit") + base.AddEVMAccAddressFlag(cmd) + base.AddEVMChainIDFlag(cmd) + base.AddCoreGRPCFlag(cmd) + base.AddCoreRPCFlag(cmd) + base.AddEVMRPCFlag(cmd) + base.AddStartingNonceFlag(cmd) + base.AddEVMGasLimitFlag(cmd) + base.AddEVMPassphraseFlag(cmd) homeDir, err := base.DefaultServicePath(ServiceNameDeployer) if err != nil { panic(err) } - cmd.Flags().String(base.FlagHome, homeDir, "The Blobstream deployer home directory") - cmd.Flags().String(base.FlagEVMPassphrase, "", "the evm account passphrase (if not specified as a flag, it will be asked interactively)") + base.AddHomeFlag(cmd, ServiceNameDeployer, homeDir) base.AddGRPCInsecureFlag(cmd) return cmd } type deployConfig struct { - *base.Config + base.Config evmRPC string coreRPC, coreGRPC string evmChainID uint64 @@ -61,78 +43,92 @@ type deployConfig struct { grpcInsecure bool } -func parseDeployFlags(cmd *cobra.Command) (deployConfig, error) { - evmAccAddr, err := cmd.Flags().GetString(FlagEVMAccAddress) +func parseDeployFlags(cmd *cobra.Command, fileConfig *deployConfig) (deployConfig, error) { + evmAccAddr, changed, err := base.GetEVMAccAddressFlag(cmd) if err != nil { return deployConfig{}, err } - if evmAccAddr == "" { - return deployConfig{}, errors.New("the evm account address should be specified") + if changed { + if evmAccAddr == "" && fileConfig.evmAccAddress == "" { + return deployConfig{}, errors.New("the evm account address should be specified") + } + fileConfig.evmAccAddress = evmAccAddr } - evmChainID, err := cmd.Flags().GetUint64(FlagEVMChainID) + + evmChainID, changed, err := base.GetEVMChainIDFlag(cmd) if err != nil { return deployConfig{}, err } - coreGRPCHost, err := cmd.Flags().GetString(FlagCoreGRPCHost) - if err != nil { - return deployConfig{}, err + if changed { + fileConfig.evmChainID = evmChainID } - coreGRPCPort, err := cmd.Flags().GetUint(FlagCoreGRPCPort) + + coreRPC, changed, err := base.GetCoreRPCFlag(cmd) if err != nil { return deployConfig{}, err } - coreRPCHost, err := cmd.Flags().GetString(FlagCoreRPCHost) - if err != nil { - return deployConfig{}, err + if changed { + if !strings.HasPrefix(coreRPC, "tcp://") { + coreRPC = fmt.Sprintf("tcp://%s", coreRPC) + } + fileConfig.coreRPC = coreRPC } - coreRPCPort, err := cmd.Flags().GetUint(FlagCoreRPCPort) + + coreGRPC, changed, err := base.GetCoreGRPCFlag(cmd) if err != nil { return deployConfig{}, err } - evmRPC, err := cmd.Flags().GetString(FlagEVMRPC) + if changed { + fileConfig.coreGRPC = coreGRPC + } + + evmRPC, changed, err := base.GetEVMRPCFlag(cmd) if err != nil { return deployConfig{}, err } - startingNonce, err := cmd.Flags().GetString(FlagStartingNonce) + if changed { + fileConfig.evmRPC = evmRPC + } + + startingNonce, changed, err := base.GetStartingNonceFlag(cmd) if err != nil { return deployConfig{}, err } - evmGasLimit, err := cmd.Flags().GetUint64(FlagEVMGasLimit) + if changed { + fileConfig.startingNonce = startingNonce + } + + evmGasLimit, changed, err := base.GetEVMGasLimitFlag(cmd) if err != nil { return deployConfig{}, err } - homeDir, err := cmd.Flags().GetString(base.FlagHome) + if changed { + fileConfig.evmGasLimit = evmGasLimit + } + + homeDir, changed, err := base.GetHomeFlag(cmd) if err != nil { return deployConfig{}, err } - if homeDir == "" { - var err error - homeDir, err = base.DefaultServicePath(ServiceNameDeployer) - if err != nil { - return deployConfig{}, err - } + if changed { + fileConfig.Home = homeDir } - passphrase, err := cmd.Flags().GetString(base.FlagEVMPassphrase) + + passphrase, changed, err := base.GetEVMPassphraseFlag(cmd) if err != nil { return deployConfig{}, err } - grpcInsecure, err := cmd.Flags().GetBool(base.FlagGRPCInsecure) + if changed { + fileConfig.EVMPassphrase = passphrase + } + + grpcInsecure, changed, err := base.GetGRPCInsecureFlag(cmd) if err != nil { return deployConfig{}, err } + if changed { + fileConfig.grpcInsecure = grpcInsecure + } - return deployConfig{ - evmAccAddress: evmAccAddr, - evmChainID: evmChainID, - coreGRPC: fmt.Sprintf("%s:%d", coreGRPCHost, coreGRPCPort), - coreRPC: fmt.Sprintf("tcp://%s:%d", coreRPCHost, coreRPCPort), - evmRPC: evmRPC, - startingNonce: startingNonce, - evmGasLimit: evmGasLimit, - Config: &base.Config{ - Home: homeDir, - EVMPassphrase: passphrase, - }, - grpcInsecure: grpcInsecure, - }, nil + return *fileConfig, nil } diff --git a/cmd/blobstream/orchestrator/cmd.go b/cmd/blobstream/orchestrator/cmd.go index 091a43d0..a9bbf2cd 100644 --- a/cmd/blobstream/orchestrator/cmd.go +++ b/cmd/blobstream/orchestrator/cmd.go @@ -44,7 +44,7 @@ func Start() *cobra.Command { Use: "start ", Short: "Starts the Blobstream orchestrator to sign attestations", RunE: func(cmd *cobra.Command, args []string) error { - config, err := parseOrchestratorFlags(cmd) + config, err := parseOrchestratorFlags(cmd, &StartConfig{}) if err != nil { return err } diff --git a/cmd/blobstream/orchestrator/config.go b/cmd/blobstream/orchestrator/config.go index 5747b940..175c294e 100644 --- a/cmd/blobstream/orchestrator/config.go +++ b/cmd/blobstream/orchestrator/config.go @@ -3,6 +3,7 @@ package orchestrator import ( "errors" "fmt" + "strings" "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" "github.com/cosmos/cosmos-sdk/client/flags" @@ -10,30 +11,19 @@ import ( ) const ( - FlagCoreGRPCHost = "core.grpc.host" - FlagCoreGRPCPort = "core.grpc.port" - FlagEVMAccAddress = "evm.account" - FlagCoreRPCHost = "core.rpc.host" - FlagCoreRPCPort = "core.rpc.port" ServiceNameOrchestrator = "orchestrator" ) func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { - cmd.Flags().String(FlagCoreRPCHost, "localhost", "Specify the rest rpc address host") - cmd.Flags().Uint(FlagCoreRPCPort, 26657, "Specify the rest rpc address port") - cmd.Flags().String(FlagCoreGRPCHost, "localhost", "Specify the grpc address host") - cmd.Flags().Uint(FlagCoreGRPCPort, 9090, "Specify the grpc address port") - cmd.Flags().String( - FlagEVMAccAddress, - "", - "Specify the EVM account address to use for signing (Note: the private key should be in the keystore)", - ) + base.AddCoreRPCFlag(cmd) + base.AddCoreGRPCFlag(cmd) + base.AddEVMAccAddressFlag(cmd) + base.AddEVMPassphraseFlag(cmd) homeDir, err := base.DefaultServicePath(ServiceNameOrchestrator) if err != nil { panic(err) } - cmd.Flags().String(base.FlagHome, homeDir, "The Blobstream orchestrator home directory") - cmd.Flags().String(base.FlagEVMPassphrase, "", "the evm account passphrase (if not specified as a flag, it will be asked interactively)") + base.AddHomeFlag(cmd, ServiceNameOrchestrator, homeDir) base.AddP2PNicknameFlag(cmd) base.AddP2PListenAddressFlag(cmd) base.AddBootstrappersFlag(cmd) @@ -42,7 +32,7 @@ func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { } type StartConfig struct { - *base.Config + base.Config coreGRPC, coreRPC string evmAccAddress string bootstrappers, p2pListenAddr string @@ -50,75 +40,86 @@ type StartConfig struct { grpcInsecure bool } -func parseOrchestratorFlags(cmd *cobra.Command) (StartConfig, error) { - evmAccAddr, err := cmd.Flags().GetString(FlagEVMAccAddress) +func parseOrchestratorFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartConfig, error) { + evmAccAddr, changed, err := base.GetEVMAccAddressFlag(cmd) if err != nil { return StartConfig{}, err } - if evmAccAddr == "" { - return StartConfig{}, errors.New("the evm account address should be specified") + if changed { + if evmAccAddr == "" && fileConfig.evmAccAddress == "" { + return StartConfig{}, errors.New("the evm account address should be specified") + } + fileConfig.evmAccAddress = evmAccAddr } - coreRPCHost, err := cmd.Flags().GetString(FlagCoreRPCHost) + + coreRPC, changed, err := base.GetCoreRPCFlag(cmd) if err != nil { return StartConfig{}, err } - coreRPCPort, err := cmd.Flags().GetUint(FlagCoreRPCPort) - if err != nil { - return StartConfig{}, err + if changed { + if !strings.HasPrefix(coreRPC, "tcp://") { + coreRPC = fmt.Sprintf("tcp://%s", coreRPC) + } + fileConfig.coreRPC = coreRPC } - coreGRPCHost, err := cmd.Flags().GetString(FlagCoreGRPCHost) + + coreGRPC, changed, err := base.GetCoreGRPCFlag(cmd) if err != nil { return StartConfig{}, err } - coreGRPCPort, err := cmd.Flags().GetUint(FlagCoreGRPCPort) - if err != nil { - return StartConfig{}, err + if changed { + fileConfig.coreGRPC = coreGRPC } - bootstrappers, err := cmd.Flags().GetString(base.FlagBootstrappers) + + bootstrappers, changed, err := base.GetBootstrappersFlag(cmd) if err != nil { return StartConfig{}, err } - p2pListenAddress, err := cmd.Flags().GetString(base.FlagP2PListenAddress) + if changed { + fileConfig.bootstrappers = bootstrappers + } + + p2pListenAddress, changed, err := base.GetP2PListenAddressFlag(cmd) if err != nil { return StartConfig{}, err } - p2pNickname, err := cmd.Flags().GetString(base.FlagP2PNickname) + if changed { + fileConfig.p2pListenAddr = p2pListenAddress + } + + p2pNickname, changed, err := base.GetP2PNicknameFlag(cmd) if err != nil { return StartConfig{}, err } - homeDir, err := cmd.Flags().GetString(base.FlagHome) + if changed { + fileConfig.p2pNickname = p2pNickname + } + + homeDir, changed, err := base.GetHomeFlag(cmd) if err != nil { return StartConfig{}, err } - if homeDir == "" { - var err error - homeDir, err = base.DefaultServicePath(ServiceNameOrchestrator) - if err != nil { - return StartConfig{}, err - } + if changed { + fileConfig.Home = homeDir } - passphrase, err := cmd.Flags().GetString(base.FlagEVMPassphrase) + + passphrase, changed, err := base.GetEVMPassphraseFlag(cmd) if err != nil { return StartConfig{}, err } - grpcInsecure, err := cmd.Flags().GetBool(base.FlagGRPCInsecure) + if changed { + fileConfig.EVMPassphrase = passphrase + } + + grpcInsecure, changed, err := base.GetGRPCInsecureFlag(cmd) if err != nil { return StartConfig{}, err } + if changed { + fileConfig.grpcInsecure = grpcInsecure + } - return StartConfig{ - evmAccAddress: evmAccAddr, - coreGRPC: fmt.Sprintf("%s:%d", coreGRPCHost, coreGRPCPort), - coreRPC: fmt.Sprintf("tcp://%s:%d", coreRPCHost, coreRPCPort), - bootstrappers: bootstrappers, - p2pNickname: p2pNickname, - p2pListenAddr: p2pListenAddress, - Config: &base.Config{ - Home: homeDir, - EVMPassphrase: passphrase, - }, - grpcInsecure: grpcInsecure, - }, nil + return *fileConfig, nil } func addInitFlags(cmd *cobra.Command) *cobra.Command { @@ -126,7 +127,7 @@ func addInitFlags(cmd *cobra.Command) *cobra.Command { if err != nil { panic(err) } - cmd.Flags().String(base.FlagHome, homeDir, "The Blobstream orchestrator home directory") + base.AddHomeFlag(cmd, ServiceNameOrchestrator, homeDir) return cmd } diff --git a/cmd/blobstream/query/config.go b/cmd/blobstream/query/config.go index 56a73ed9..530bab99 100644 --- a/cmd/blobstream/query/config.go +++ b/cmd/blobstream/query/config.go @@ -2,10 +2,10 @@ package query import ( "fmt" + "strings" "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" - "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/relayer" "github.com/spf13/cobra" ) @@ -15,10 +15,8 @@ const ( ) func addFlags(cmd *cobra.Command) *cobra.Command { - cmd.Flags().String(relayer.FlagCoreGRPCHost, "localhost", "Specify the grpc address host") - cmd.Flags().Uint(relayer.FlagCoreGRPCPort, 9090, "Specify the grpc address port") - cmd.Flags().String(relayer.FlagCoreRPCHost, "localhost", "Specify the rest rpc address host") - cmd.Flags().Uint(relayer.FlagCoreRPCPort, 26657, "Specify the rest rpc address") + base.AddCoreGRPCFlag(cmd) + base.AddCoreRPCFlag(cmd) cmd.Flags().String(FlagP2PNode, "", "P2P target node multiaddress (eg. /ip4/127.0.0.1/tcp/30000/p2p/12D3KooWBSMasWzRSRKXREhediFUwABNZwzJbkZcYz5rYr9Zdmfn)") cmd.Flags().String(FlagOutputFile, "", "Path to an output file path if the results need to be written to a json file. Leaving it as empty will result in printing the result to stdout") base.AddGRPCInsecureFlag(cmd) @@ -34,19 +32,14 @@ type Config struct { } func parseFlags(cmd *cobra.Command) (Config, error) { - coreRPCHost, err := cmd.Flags().GetString(relayer.FlagCoreRPCHost) + coreRPC, err := cmd.Flags().GetString(base.FlagCoreRPC) if err != nil { return Config{}, err } - coreRPCPort, err := cmd.Flags().GetUint(relayer.FlagCoreRPCPort) - if err != nil { - return Config{}, err - } - coreGRPCHost, err := cmd.Flags().GetString(relayer.FlagCoreGRPCHost) - if err != nil { - return Config{}, err + if !strings.HasPrefix(coreRPC, "tcp://") { + coreRPC = fmt.Sprintf("tcp://%s", coreRPC) } - coreGRPCPort, err := cmd.Flags().GetUint(relayer.FlagCoreGRPCPort) + coreGRPC, err := cmd.Flags().GetString(base.FlagCoreGRPC) if err != nil { return Config{}, err } @@ -63,8 +56,8 @@ func parseFlags(cmd *cobra.Command) (Config, error) { return Config{}, err } return Config{ - coreGRPC: fmt.Sprintf("%s:%d", coreGRPCHost, coreGRPCPort), - coreRPC: fmt.Sprintf("tcp://%s:%d", coreRPCHost, coreRPCPort), + coreGRPC: coreGRPC, + coreRPC: coreRPC, targetNode: targetNode, outputFile: outputFile, grpcInsecure: grpcInsecure, diff --git a/cmd/blobstream/relayer/cmd.go b/cmd/blobstream/relayer/cmd.go index 48cfe795..c6bd90f1 100644 --- a/cmd/blobstream/relayer/cmd.go +++ b/cmd/blobstream/relayer/cmd.go @@ -83,7 +83,7 @@ func Start() *cobra.Command { Use: "start ", Short: "Runs the Blobstream relayer to submit attestations to the target EVM chain", RunE: func(cmd *cobra.Command, args []string) error { - config, err := parseRelayerStartFlags(cmd) + config, err := parseRelayerStartFlags(cmd, &StartConfig{}) if err != nil { return err } diff --git a/cmd/blobstream/relayer/config.go b/cmd/blobstream/relayer/config.go index 630a2bd7..37445a64 100644 --- a/cmd/blobstream/relayer/config.go +++ b/cmd/blobstream/relayer/config.go @@ -3,46 +3,35 @@ package relayer import ( "errors" "fmt" + "strings" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" - "github.com/celestiaorg/orchestrator-relayer/evm" "github.com/spf13/cobra" ethcmn "github.com/ethereum/go-ethereum/common" ) const ( - FlagEVMAccAddress = "evm.account" - FlagEVMChainID = "evm.chain-id" - FlagCoreGRPCHost = "core.grpc.host" - FlagCoreGRPCPort = "core.grpc.port" - FlagCoreRPCHost = "core.rpc.host" - FlagCoreRPCPort = "core.rpc.port" - FlagEVMRPC = "evm.rpc" - FlagContractAddress = "evm.contract-address" - FlagEVMGasLimit = "evm.gas-limit" - ServiceNameRelayer = "relayer" + ServiceNameRelayer = "relayer" ) func addRelayerStartFlags(cmd *cobra.Command) *cobra.Command { - cmd.Flags().String(FlagEVMAccAddress, "", "Specify the EVM account address to use for signing (Note: the private key should be in the keystore)") - cmd.Flags().Uint64(FlagEVMChainID, 5, "Specify the evm chain id") - cmd.Flags().String(FlagCoreGRPCHost, "localhost", "Specify the grpc address host") - cmd.Flags().Uint(FlagCoreGRPCPort, 9090, "Specify the grpc address port") - cmd.Flags().String(FlagCoreRPCHost, "localhost", "Specify the rest rpc address host") - cmd.Flags().Uint(FlagCoreRPCPort, 26657, "Specify the rest rpc address port") - cmd.Flags().String(FlagEVMRPC, "http://localhost:8545", "Specify the ethereum rpc address") - cmd.Flags().String(FlagContractAddress, "", "Specify the contract at which the Blobstream is deployed") - cmd.Flags().Uint64(FlagEVMGasLimit, evm.DefaultEVMGasLimit, "Specify the evm gas limit") homeDir, err := base.DefaultServicePath(ServiceNameRelayer) if err != nil { panic(err) } - cmd.Flags().String(base.FlagHome, homeDir, "The Blobstream relayer home directory") - cmd.Flags().String(base.FlagEVMPassphrase, "", "the evm account passphrase (if not specified as a flag, it will be asked interactively)") + base.AddHomeFlag(cmd, ServiceNameRelayer, homeDir) + base.AddEVMAccAddressFlag(cmd) + base.AddEVMChainIDFlag(cmd) + base.AddCoreGRPCFlag(cmd) + base.AddCoreRPCFlag(cmd) + base.AddEVMRPCFlag(cmd) + base.AddEVMContractAddressFlag(cmd) + base.AddEVMGasLimitFlag(cmd) + base.AddEVMPassphraseFlag(cmd) base.AddP2PNicknameFlag(cmd) base.AddP2PListenAddressFlag(cmd) base.AddBootstrappersFlag(cmd) @@ -52,7 +41,7 @@ func addRelayerStartFlags(cmd *cobra.Command) *cobra.Command { } type StartConfig struct { - *base.Config + base.Config evmChainID uint64 evmRPC, coreGRPC, coreRPC string evmAccAddress string @@ -63,102 +52,129 @@ type StartConfig struct { grpcInsecure bool } -func parseRelayerStartFlags(cmd *cobra.Command) (StartConfig, error) { - evmAccAddr, err := cmd.Flags().GetString(FlagEVMAccAddress) +// TODO add a validate basics + +func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartConfig, error) { + evmAccAddr, changed, err := base.GetEVMAccAddressFlag(cmd) if err != nil { return StartConfig{}, err } - if evmAccAddr == "" { - return StartConfig{}, errors.New("the evm account address should be specified") + if changed { + if evmAccAddr == "" && fileConfig.evmAccAddress == "" { + return StartConfig{}, errors.New("the evm account address should be specified") + } + fileConfig.evmAccAddress = evmAccAddr } - evmChainID, err := cmd.Flags().GetUint64(FlagEVMChainID) + + evmChainID, changed, err := base.GetEVMChainIDFlag(cmd) if err != nil { return StartConfig{}, err } - coreRPCHost, err := cmd.Flags().GetString(FlagCoreRPCHost) - if err != nil { - return StartConfig{}, err + if changed { + fileConfig.evmChainID = evmChainID } - coreRPCPort, err := cmd.Flags().GetUint(FlagCoreRPCPort) + + coreRPC, changed, err := base.GetCoreRPCFlag(cmd) if err != nil { return StartConfig{}, err } - coreGRPCHost, err := cmd.Flags().GetString(FlagCoreGRPCHost) - if err != nil { - return StartConfig{}, err + if changed { + if !strings.HasPrefix(coreRPC, "tcp://") { + coreRPC = fmt.Sprintf("tcp://%s", coreRPC) + } + fileConfig.coreRPC = coreRPC } - coreGRPCPort, err := cmd.Flags().GetUint(FlagCoreGRPCPort) + + coreGRPC, changed, err := base.GetCoreGRPCFlag(cmd) if err != nil { return StartConfig{}, err } - contractAddr, err := cmd.Flags().GetString(FlagContractAddress) + if changed { + fileConfig.coreGRPC = coreGRPC + } + + contractAddr, changed, err := base.GetEVMContractAddressFlag(cmd) if err != nil { return StartConfig{}, err } - if contractAddr == "" { - return StartConfig{}, fmt.Errorf("contract address flag is required: %s", FlagContractAddress) - } - if !ethcmn.IsHexAddress(contractAddr) { - return StartConfig{}, fmt.Errorf("valid contract address flag is required: %s", FlagContractAddress) + if changed { + if contractAddr == "" { + // TODO fix + return StartConfig{}, fmt.Errorf("contract address flag is required: %s", base.FlagEVMContractAddress) + } + if !ethcmn.IsHexAddress(contractAddr) { + // TODO probably not the right place + return StartConfig{}, fmt.Errorf("valid contract address flag is required: %s", base.FlagEVMContractAddress) + } + address := ethcmn.HexToAddress(contractAddr) + fileConfig.contractAddr = address } - address := ethcmn.HexToAddress(contractAddr) - evmRPC, err := cmd.Flags().GetString(FlagEVMRPC) + + evmRPC, changed, err := base.GetEVMRPCFlag(cmd) if err != nil { return StartConfig{}, err } - evmGasLimit, err := cmd.Flags().GetUint64(FlagEVMGasLimit) + if changed { + fileConfig.evmRPC = evmRPC + } + + evmGasLimit, changed, err := base.GetEVMGasLimitFlag(cmd) if err != nil { return StartConfig{}, err } - bootstrappers, err := cmd.Flags().GetString(base.FlagBootstrappers) + if changed { + fileConfig.evmGasLimit = evmGasLimit + } + + bootstrappers, changed, err := base.GetBootstrappersFlag(cmd) if err != nil { return StartConfig{}, err } - p2pListenAddress, err := cmd.Flags().GetString(base.FlagP2PListenAddress) + if changed { + fileConfig.bootstrappers = bootstrappers + } + + p2pListenAddress, changed, err := base.GetP2PListenAddressFlag(cmd) if err != nil { return StartConfig{}, err } - p2pNickname, err := cmd.Flags().GetString(base.FlagP2PNickname) + if changed { + fileConfig.p2pListenAddr = p2pListenAddress + } + + p2pNickname, changed, err := base.GetP2PNicknameFlag(cmd) if err != nil { return StartConfig{}, err } - homeDir, err := cmd.Flags().GetString(base.FlagHome) + if changed { + fileConfig.p2pNickname = p2pNickname + } + + homeDir, changed, err := base.GetHomeFlag(cmd) if err != nil { return StartConfig{}, err } - if homeDir == "" { - var err error - homeDir, err = base.DefaultServicePath(ServiceNameRelayer) - if err != nil { - return StartConfig{}, err - } + if changed { + fileConfig.Home = homeDir } - passphrase, err := cmd.Flags().GetString(base.FlagEVMPassphrase) + + passphrase, changed, err := base.GetEVMPassphraseFlag(cmd) if err != nil { return StartConfig{}, err } - grpcInsecure, err := cmd.Flags().GetBool(base.FlagGRPCInsecure) + if changed { + fileConfig.EVMPassphrase = passphrase + } + + grpcInsecure, changed, err := base.GetGRPCInsecureFlag(cmd) if err != nil { return StartConfig{}, err } + if changed { + fileConfig.grpcInsecure = grpcInsecure + } - return StartConfig{ - evmAccAddress: evmAccAddr, - evmChainID: evmChainID, - coreGRPC: fmt.Sprintf("%s:%d", coreGRPCHost, coreGRPCPort), - coreRPC: fmt.Sprintf("tcp://%s:%d", coreRPCHost, coreRPCPort), - contractAddr: address, - evmRPC: evmRPC, - evmGasLimit: evmGasLimit, - bootstrappers: bootstrappers, - p2pListenAddr: p2pListenAddress, - p2pNickname: p2pNickname, - Config: &base.Config{ - Home: homeDir, - EVMPassphrase: passphrase, - }, - grpcInsecure: grpcInsecure, - }, nil + return *fileConfig, nil } func addInitFlags(cmd *cobra.Command) *cobra.Command { @@ -166,7 +182,7 @@ func addInitFlags(cmd *cobra.Command) *cobra.Command { if err != nil { panic(err) } - cmd.Flags().String(base.FlagHome, homeDir, "The Blobstream relayer home directory") + base.AddHomeFlag(cmd, ServiceNameRelayer, homeDir) return cmd } From 776c918811f9c476baed78098df2c38c5ff59b92 Mon Sep 17 00:00:00 2001 From: rachid Date: Thu, 9 Nov 2023 13:57:59 +0100 Subject: [PATCH 2/7] feat: trying to parse the config file --- cmd/blobstream/base/config.go | 11 +++ cmd/blobstream/orchestrator/cmd.go | 111 ++++++++++++++++++++++++-- cmd/blobstream/orchestrator/config.go | 86 ++++++++++++++------ go.mod | 2 +- 4 files changed, 176 insertions(+), 34 deletions(-) diff --git a/cmd/blobstream/base/config.go b/cmd/blobstream/base/config.go index b00ce6fb..ac156c6a 100644 --- a/cmd/blobstream/base/config.go +++ b/cmd/blobstream/base/config.go @@ -238,6 +238,17 @@ func GetHomeFlag(cmd *cobra.Command) (string, bool, error) { return val, changed, err } +func GetHomeDirectory(cmd *cobra.Command, service string) (string, error) { + homeDir, changed, err := GetHomeFlag(cmd) + if err != nil { + return "", err + } + if changed && homeDir != "" { + return homeDir, nil + } + return DefaultServicePath(service) +} + func AddEVMAccAddressFlag(cmd *cobra.Command) { cmd.Flags().String(FlagEVMAccAddress, "", "Specify the EVM account address to use for signing (Note: the private key should be in the keystore)") } diff --git a/cmd/blobstream/orchestrator/cmd.go b/cmd/blobstream/orchestrator/cmd.go index a9bbf2cd..4431f7bc 100644 --- a/cmd/blobstream/orchestrator/cmd.go +++ b/cmd/blobstream/orchestrator/cmd.go @@ -1,8 +1,14 @@ package orchestrator import ( + "bytes" "context" + "fmt" + "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" + "github.com/spf13/viper" "os" + "path/filepath" + "text/template" "time" "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/common" @@ -44,20 +50,29 @@ func Start() *cobra.Command { Use: "start ", Short: "Starts the Blobstream orchestrator to sign attestations", RunE: func(cmd *cobra.Command, args []string) error { - config, err := parseOrchestratorFlags(cmd, &StartConfig{}) + logger := tmlog.NewTMLogger(os.Stdout) + + homeDir, err := base.GetHomeDirectory(cmd, ServiceNameOrchestrator) if err != nil { return err } + logger.Debug("initializing orchestrator", "home", homeDir) - logger := tmlog.NewTMLogger(os.Stdout) - logger.Debug("initializing orchestrator") + fileConfig, err := LoadFileConfiguration(homeDir) + if err != nil { + return err + } + config, err := parseOrchestratorFlags(cmd, fileConfig) + if err != nil { + return err + } ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() stopFuncs := make([]func() error, 0) - tmQuerier, appQuerier, stops, err := common.NewTmAndAppQuerier(logger, config.coreRPC, config.coreGRPC, config.grpcInsecure) + tmQuerier, appQuerier, stops, err := common.NewTmAndAppQuerier(logger, config.CoreRPC, config.CoreGRPC, config.GRPCInsecure) stopFuncs = append(stopFuncs, stops...) if err != nil { return err @@ -75,9 +90,9 @@ func Start() *cobra.Command { return err } - logger.Info("loading EVM account", "address", config.evmAccAddress) + logger.Info("loading EVM account", "address", config.EvmAccAddress) - acc, err := evm2.GetAccountFromStoreAndUnlockIt(s.EVMKeyStore, config.evmAccAddress, config.EVMPassphrase) + acc, err := evm2.GetAccountFromStoreAndUnlockIt(s.EVMKeyStore, config.EvmAccAddress, config.EVMPassphrase) stopFuncs = append(stopFuncs, func() error { return s.EVMKeyStore.Lock(acc.Address) }) if err != nil { return err @@ -86,7 +101,7 @@ func Start() *cobra.Command { // creating the data store dataStore := dssync.MutexWrap(s.DataStore) - dht, err := common.CreateDHTAndWaitForPeers(ctx, logger, s.P2PKeyStore, config.p2pNickname, config.p2pListenAddr, config.bootstrappers, dataStore) + dht, err := common.CreateDHTAndWaitForPeers(ctx, logger, s.P2PKeyStore, config.P2pNickname, config.P2PListenAddr, config.Bootstrappers, dataStore) if err != nil { return err } @@ -169,8 +184,90 @@ func Init() *cobra.Command { return err } + configPath := filepath.Join(config.home, "config") + configFilePath := filepath.Join(configPath, "config.toml") + conf := DefaultStartConfig() + err = initializeConfigFile(configFilePath, configPath, conf) + if err != nil { + return err + } + return nil }, } return addInitFlags(&cmd) } + +func LoadFileConfiguration(homeDir string) (*StartConfig, error) { + v := viper.New() + v.SetEnvPrefix("") + v.AutomaticEnv() + configPath := filepath.Join(homeDir, "config") + configFilePath := filepath.Join(configPath, "config.toml") + conf := DefaultStartConfig() + + // if config.toml file does not exist, we create it and write default ClientConfig values into it. + if _, err := os.Stat(configFilePath); os.IsNotExist(err) { + if err := initializeConfigFile(configFilePath, configPath, conf); err != nil { + return nil, err + } + } + + conf, err := getStartConfig(v, configPath) + if err != nil { + return nil, fmt.Errorf("couldn't get client config: %v", err) + } + return conf, nil +} + +func initializeConfigFile(configFilePath string, configPath string, conf *StartConfig) error { + if err := ensureConfigPath(configPath); err != nil { + return fmt.Errorf("couldn't make orchestrator config: %v", err) + } + + if err := writeConfigToFile(configFilePath, conf); err != nil { + return fmt.Errorf("could not write client config to the file: %v", err) + } + return nil +} + +// ensureConfigPath creates a directory configPath if it does not exist +func ensureConfigPath(configPath string) error { + return os.MkdirAll(configPath, os.ModePerm) +} + +// writeConfigToFile parses DefaultConfigTemplate, renders config using the template and writes it to +// configFilePath. +func writeConfigToFile(configFilePath string, config *StartConfig) error { + var buffer bytes.Buffer + + tmpl := template.New("orchestratorConfigFileTemplate") + configTemplate, err := tmpl.Parse(DefaultConfigTemplate) + if err != nil { + return err + } + + if err := configTemplate.Execute(&buffer, config); err != nil { + return err + } + + return os.WriteFile(configFilePath, buffer.Bytes(), 0o600) +} + +// getStartConfig reads values from config.toml file and unmarshalls them into StartConfig +func getStartConfig(v *viper.Viper, configPath string) (*StartConfig, error) { + v.AddConfigPath(configPath) + v.SetConfigName("config") + v.SetConfigType("toml") + + if err := v.ReadInConfig(); err != nil { + return nil, err + } + + conf := new(StartConfig) + if err := v.Unmarshal(conf); err != nil { + return nil, err + } + + return conf, nil +} diff --git a/cmd/blobstream/orchestrator/config.go b/cmd/blobstream/orchestrator/config.go index 175c294e..0ec040ce 100644 --- a/cmd/blobstream/orchestrator/config.go +++ b/cmd/blobstream/orchestrator/config.go @@ -14,6 +14,34 @@ const ( ServiceNameOrchestrator = "orchestrator" ) +const DefaultConfigTemplate = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### RPC Configuration ### +############################################################################### + +# Specify the celestia app rest rpc address. +core.rpc = "{{ .CoreRPC }}" + +# Specify the celestia app grpc address. +core.grpc = "{{ .CoreGRPC }}" + +# allow gRPC over insecure channels, if not TLS the server must use TLS. +grpc.insecure = {{ .GRPCInsecure }} + +############################################################################### +### P2P Configuration ### +############################################################################### + +# Comma-separated multiaddresses of p2p peers to connect to. +# Example: "/ip4/127.0.0.1/tcp/30001/p2p/12D3K...,/ip4/127.0.0.1/tcp/30000/p2p/12D3K..." +p2p.bootstrappers = "{{ .Bootstrappers }}" + +# MultiAddr for the p2p peer to listen on. +p2p.listen-addr = "{{ .P2PListenAddr }}" +` + func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { base.AddCoreRPCFlag(cmd) base.AddCoreGRPCFlag(cmd) @@ -33,24 +61,34 @@ func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { type StartConfig struct { base.Config - coreGRPC, coreRPC string - evmAccAddress string - bootstrappers, p2pListenAddr string - p2pNickname string - grpcInsecure bool + CoreGRPC string `mapstructure:"core.grpc" json:"core.grpc"` + CoreRPC string `mapstructure:"core.rpc" json:"core.rpc"` + EvmAccAddress string `mapstructure:"evm.acccount-address" json:"evm.acccount-address"` + Bootstrappers string `mapstructure:"p2p.bootstrappers" json:"p2p.bootstrappers"` + P2PListenAddr string `mapstructure:"p2p.listen-addr" json:"p2p.listen-addr"` + P2pNickname string `mapstructure:"p2p.nickname" json:"p2p.nickname"` + GRPCInsecure bool `mapstructure:"grpc.insecure" json:"grpc.insecure"` } -func parseOrchestratorFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartConfig, error) { - evmAccAddr, changed, err := base.GetEVMAccAddressFlag(cmd) +func DefaultStartConfig() *StartConfig { + return &StartConfig{ + CoreRPC: "tcp://localhost:26657", + CoreGRPC: "localhost:9090", + Bootstrappers: "", + P2PListenAddr: "/ip4/0.0.0.0/tcp/30000", + GRPCInsecure: true, + } +} + +func parseOrchestratorFlags(cmd *cobra.Command, startConf *StartConfig) (StartConfig, error) { + evmAccAddr, _, err := base.GetEVMAccAddressFlag(cmd) if err != nil { return StartConfig{}, err } - if changed { - if evmAccAddr == "" && fileConfig.evmAccAddress == "" { - return StartConfig{}, errors.New("the evm account address should be specified") - } - fileConfig.evmAccAddress = evmAccAddr + if evmAccAddr == "" { + return StartConfig{}, errors.New("the evm account address should be specified") } + startConf.EvmAccAddress = evmAccAddr coreRPC, changed, err := base.GetCoreRPCFlag(cmd) if err != nil { @@ -60,7 +98,7 @@ func parseOrchestratorFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC if !strings.HasPrefix(coreRPC, "tcp://") { coreRPC = fmt.Sprintf("tcp://%s", coreRPC) } - fileConfig.coreRPC = coreRPC + startConf.CoreRPC = coreRPC } coreGRPC, changed, err := base.GetCoreGRPCFlag(cmd) @@ -68,7 +106,7 @@ func parseOrchestratorFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.coreGRPC = coreGRPC + startConf.CoreGRPC = coreGRPC } bootstrappers, changed, err := base.GetBootstrappersFlag(cmd) @@ -76,7 +114,7 @@ func parseOrchestratorFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.bootstrappers = bootstrappers + startConf.Bootstrappers = bootstrappers } p2pListenAddress, changed, err := base.GetP2PListenAddressFlag(cmd) @@ -84,7 +122,7 @@ func parseOrchestratorFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.p2pListenAddr = p2pListenAddress + startConf.P2PListenAddr = p2pListenAddress } p2pNickname, changed, err := base.GetP2PNicknameFlag(cmd) @@ -92,34 +130,30 @@ func parseOrchestratorFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.p2pNickname = p2pNickname + startConf.P2pNickname = p2pNickname } homeDir, changed, err := base.GetHomeFlag(cmd) if err != nil { return StartConfig{}, err } - if changed { - fileConfig.Home = homeDir - } + startConf.Home = homeDir - passphrase, changed, err := base.GetEVMPassphraseFlag(cmd) + passphrase, _, err := base.GetEVMPassphraseFlag(cmd) if err != nil { return StartConfig{}, err } - if changed { - fileConfig.EVMPassphrase = passphrase - } + startConf.EVMPassphrase = passphrase grpcInsecure, changed, err := base.GetGRPCInsecureFlag(cmd) if err != nil { return StartConfig{}, err } if changed { - fileConfig.grpcInsecure = grpcInsecure + startConf.GRPCInsecure = grpcInsecure } - return *fileConfig, nil + return *startConf, nil } func addInitFlags(cmd *cobra.Command) *cobra.Command { diff --git a/go.mod b/go.mod index e60c8ec0..7db07bc3 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/libp2p/go-libp2p-kad-dht v0.25.1 github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-multiaddr v0.12.0 + github.com/spf13/viper v1.14.0 github.com/tendermint/tendermint v0.34.28 ) @@ -251,7 +252,6 @@ require ( github.com/spf13/afero v1.9.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.14.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/supranational/blst v0.3.11 // indirect From 6707000dc0a29cc3007150cac994b8f2e7faa8eb Mon Sep 17 00:00:00 2001 From: rachid Date: Fri, 10 Nov 2023 11:38:45 +0100 Subject: [PATCH 3/7] feat: support config files for relayer --- cmd/blobstream/base/config.go | 17 ++ cmd/blobstream/keys/evm/evm.go | 1 + cmd/blobstream/orchestrator/cmd.go | 84 +--------- cmd/blobstream/orchestrator/config.go | 112 +++++++++++-- cmd/blobstream/relayer/cmd.go | 46 ++++-- cmd/blobstream/relayer/config.go | 218 ++++++++++++++++++++------ 6 files changed, 322 insertions(+), 156 deletions(-) diff --git a/cmd/blobstream/base/config.go b/cmd/blobstream/base/config.go index ac156c6a..d9e2836f 100644 --- a/cmd/blobstream/base/config.go +++ b/cmd/blobstream/base/config.go @@ -5,6 +5,8 @@ import ( "os" "strings" + ethcmn "github.com/ethereum/go-ethereum/common" + "github.com/celestiaorg/orchestrator-relayer/evm" "github.com/spf13/cobra" @@ -261,3 +263,18 @@ func GetEVMAccAddressFlag(cmd *cobra.Command) (string, bool, error) { } return val, changed, err } + +func ValidateEVMAddress(addr string) error { + if addr == "" { + return fmt.Errorf("the EVM address cannot be empty") + } + if !ethcmn.IsHexAddress(addr) { + return errors.New("valid EVM address is required") + } + return nil +} + +// EnsureConfigPath creates a directory configPath if it does not exist +func EnsureConfigPath(configPath string) error { + return os.MkdirAll(configPath, os.ModePerm) +} diff --git a/cmd/blobstream/keys/evm/evm.go b/cmd/blobstream/keys/evm/evm.go index 38c9fdce..300d118b 100644 --- a/cmd/blobstream/keys/evm/evm.go +++ b/cmd/blobstream/keys/evm/evm.go @@ -630,6 +630,7 @@ func GetPassphrase() (string, error) { if err != nil { return "", err } + fmt.Println() return string(bzPassphrase), nil } diff --git a/cmd/blobstream/orchestrator/cmd.go b/cmd/blobstream/orchestrator/cmd.go index 4431f7bc..aee75815 100644 --- a/cmd/blobstream/orchestrator/cmd.go +++ b/cmd/blobstream/orchestrator/cmd.go @@ -1,16 +1,13 @@ package orchestrator import ( - "bytes" "context" - "fmt" - "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" - "github.com/spf13/viper" "os" "path/filepath" - "text/template" "time" + "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" + "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/common" evm2 "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/keys/evm" "github.com/celestiaorg/orchestrator-relayer/p2p" @@ -66,6 +63,9 @@ func Start() *cobra.Command { if err != nil { return err } + if err := config.ValidateBasics(); err != nil { + return err + } ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() @@ -197,77 +197,3 @@ func Init() *cobra.Command { } return addInitFlags(&cmd) } - -func LoadFileConfiguration(homeDir string) (*StartConfig, error) { - v := viper.New() - v.SetEnvPrefix("") - v.AutomaticEnv() - configPath := filepath.Join(homeDir, "config") - configFilePath := filepath.Join(configPath, "config.toml") - conf := DefaultStartConfig() - - // if config.toml file does not exist, we create it and write default ClientConfig values into it. - if _, err := os.Stat(configFilePath); os.IsNotExist(err) { - if err := initializeConfigFile(configFilePath, configPath, conf); err != nil { - return nil, err - } - } - - conf, err := getStartConfig(v, configPath) - if err != nil { - return nil, fmt.Errorf("couldn't get client config: %v", err) - } - return conf, nil -} - -func initializeConfigFile(configFilePath string, configPath string, conf *StartConfig) error { - if err := ensureConfigPath(configPath); err != nil { - return fmt.Errorf("couldn't make orchestrator config: %v", err) - } - - if err := writeConfigToFile(configFilePath, conf); err != nil { - return fmt.Errorf("could not write client config to the file: %v", err) - } - return nil -} - -// ensureConfigPath creates a directory configPath if it does not exist -func ensureConfigPath(configPath string) error { - return os.MkdirAll(configPath, os.ModePerm) -} - -// writeConfigToFile parses DefaultConfigTemplate, renders config using the template and writes it to -// configFilePath. -func writeConfigToFile(configFilePath string, config *StartConfig) error { - var buffer bytes.Buffer - - tmpl := template.New("orchestratorConfigFileTemplate") - configTemplate, err := tmpl.Parse(DefaultConfigTemplate) - if err != nil { - return err - } - - if err := configTemplate.Execute(&buffer, config); err != nil { - return err - } - - return os.WriteFile(configFilePath, buffer.Bytes(), 0o600) -} - -// getStartConfig reads values from config.toml file and unmarshalls them into StartConfig -func getStartConfig(v *viper.Viper, configPath string) (*StartConfig, error) { - v.AddConfigPath(configPath) - v.SetConfigName("config") - v.SetConfigType("toml") - - if err := v.ReadInConfig(); err != nil { - return nil, err - } - - conf := new(StartConfig) - if err := v.Unmarshal(conf); err != nil { - return nil, err - } - - return conf, nil -} diff --git a/cmd/blobstream/orchestrator/config.go b/cmd/blobstream/orchestrator/config.go index 0ec040ce..e4f48bdb 100644 --- a/cmd/blobstream/orchestrator/config.go +++ b/cmd/blobstream/orchestrator/config.go @@ -1,9 +1,14 @@ package orchestrator import ( - "errors" + "bytes" "fmt" + "os" + "path/filepath" "strings" + "text/template" + + "github.com/spf13/viper" "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" "github.com/cosmos/cosmos-sdk/client/flags" @@ -22,13 +27,13 @@ const DefaultConfigTemplate = `# This is a TOML config file. ############################################################################### # Specify the celestia app rest rpc address. -core.rpc = "{{ .CoreRPC }}" +core-rpc = "{{ .CoreRPC }}" # Specify the celestia app grpc address. -core.grpc = "{{ .CoreGRPC }}" +core-grpc = "{{ .CoreGRPC }}" # allow gRPC over insecure channels, if not TLS the server must use TLS. -grpc.insecure = {{ .GRPCInsecure }} +grpc-insecure = {{ .GRPCInsecure }} ############################################################################### ### P2P Configuration ### @@ -36,10 +41,10 @@ grpc.insecure = {{ .GRPCInsecure }} # Comma-separated multiaddresses of p2p peers to connect to. # Example: "/ip4/127.0.0.1/tcp/30001/p2p/12D3K...,/ip4/127.0.0.1/tcp/30000/p2p/12D3K..." -p2p.bootstrappers = "{{ .Bootstrappers }}" +bootstrappers = "{{ .Bootstrappers }}" # MultiAddr for the p2p peer to listen on. -p2p.listen-addr = "{{ .P2PListenAddr }}" +listen-addr = "{{ .P2PListenAddr }}" ` func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { @@ -61,13 +66,13 @@ func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { type StartConfig struct { base.Config - CoreGRPC string `mapstructure:"core.grpc" json:"core.grpc"` - CoreRPC string `mapstructure:"core.rpc" json:"core.rpc"` - EvmAccAddress string `mapstructure:"evm.acccount-address" json:"evm.acccount-address"` - Bootstrappers string `mapstructure:"p2p.bootstrappers" json:"p2p.bootstrappers"` - P2PListenAddr string `mapstructure:"p2p.listen-addr" json:"p2p.listen-addr"` - P2pNickname string `mapstructure:"p2p.nickname" json:"p2p.nickname"` - GRPCInsecure bool `mapstructure:"grpc.insecure" json:"grpc.insecure"` + CoreGRPC string `mapstructure:"core-grpc" json:"core-grpc"` + CoreRPC string `mapstructure:"core-rpc" json:"core-rpc"` + EvmAccAddress string + Bootstrappers string `mapstructure:"bootstrappers" json:"bootstrappers"` + P2PListenAddr string `mapstructure:"listen-addr" json:"listen-addr"` + P2pNickname string + GRPCInsecure bool `mapstructure:"grpc-insecure" json:"grpc-insecure"` } func DefaultStartConfig() *StartConfig { @@ -80,14 +85,18 @@ func DefaultStartConfig() *StartConfig { } } +func (cfg StartConfig) ValidateBasics() error { + if err := base.ValidateEVMAddress(cfg.EvmAccAddress); err != nil { + return fmt.Errorf("%s: flag --%s", err.Error(), base.FlagEVMAccAddress) + } + return nil +} + func parseOrchestratorFlags(cmd *cobra.Command, startConf *StartConfig) (StartConfig, error) { evmAccAddr, _, err := base.GetEVMAccAddressFlag(cmd) if err != nil { return StartConfig{}, err } - if evmAccAddr == "" { - return StartConfig{}, errors.New("the evm account address should be specified") - } startConf.EvmAccAddress = evmAccAddr coreRPC, changed, err := base.GetCoreRPCFlag(cmd) @@ -133,7 +142,7 @@ func parseOrchestratorFlags(cmd *cobra.Command, startConf *StartConfig) (StartCo startConf.P2pNickname = p2pNickname } - homeDir, changed, err := base.GetHomeFlag(cmd) + homeDir, _, err := base.GetHomeFlag(cmd) if err != nil { return StartConfig{}, err } @@ -186,3 +195,72 @@ func parseInitFlags(cmd *cobra.Command) (InitConfig, error) { home: homeDir, }, nil } + +func LoadFileConfiguration(homeDir string) (*StartConfig, error) { + v := viper.New() + v.SetEnvPrefix("") + v.AutomaticEnv() + configPath := filepath.Join(homeDir, "config") + configFilePath := filepath.Join(configPath, "config.toml") + conf := DefaultStartConfig() + + // if config.toml file does not exist, we create it and write default ClientConfig values into it. + if _, err := os.Stat(configFilePath); os.IsNotExist(err) { + if err := initializeConfigFile(configFilePath, configPath, conf); err != nil { + return nil, err + } + } + + conf, err := getStartConfig(v, configPath) + if err != nil { + return nil, fmt.Errorf("couldn't get client config: %v", err) + } + return conf, nil +} + +func initializeConfigFile(configFilePath string, configPath string, conf *StartConfig) error { + if err := base.EnsureConfigPath(configPath); err != nil { + return fmt.Errorf("couldn't make orchestrator config: %v", err) + } + + if err := writeConfigToFile(configFilePath, conf); err != nil { + return fmt.Errorf("could not write orchestrator config to the file: %v", err) + } + return nil +} + +// writeConfigToFile parses DefaultConfigTemplate, renders config using the template and writes it to +// configFilePath. +func writeConfigToFile(configFilePath string, config *StartConfig) error { + var buffer bytes.Buffer + + tmpl := template.New("orchestratorConfigFileTemplate") + configTemplate, err := tmpl.Parse(DefaultConfigTemplate) + if err != nil { + return err + } + + if err := configTemplate.Execute(&buffer, config); err != nil { + return err + } + + return os.WriteFile(configFilePath, buffer.Bytes(), 0o600) +} + +// getStartConfig reads values from config.toml file and unmarshalls them into StartConfig +func getStartConfig(v *viper.Viper, configPath string) (*StartConfig, error) { + v.AddConfigPath(configPath) + v.SetConfigName("config") + v.SetConfigType("toml") + + if err := v.ReadInConfig(); err != nil { + return nil, err + } + + conf := new(StartConfig) + if err := v.Unmarshal(conf); err != nil { + return nil, err + } + + return conf, nil +} diff --git a/cmd/blobstream/relayer/cmd.go b/cmd/blobstream/relayer/cmd.go index c6bd90f1..3f9e0ba7 100644 --- a/cmd/blobstream/relayer/cmd.go +++ b/cmd/blobstream/relayer/cmd.go @@ -3,8 +3,13 @@ package relayer import ( "context" "os" + "path/filepath" "time" + "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" + + ethcmn "github.com/ethereum/go-ethereum/common" + blobstreamwrapper "github.com/celestiaorg/blobstream-contracts/v3/wrappers/Blobstream.sol" evm2 "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/keys/evm" @@ -72,6 +77,14 @@ func Init() *cobra.Command { return err } + configPath := filepath.Join(config.home, "config") + configFilePath := filepath.Join(configPath, "config.toml") + conf := DefaultStartConfig() + err = initializeConfigFile(configFilePath, configPath, conf) + if err != nil { + return err + } + return nil }, } @@ -83,21 +96,32 @@ func Start() *cobra.Command { Use: "start ", Short: "Runs the Blobstream relayer to submit attestations to the target EVM chain", RunE: func(cmd *cobra.Command, args []string) error { - config, err := parseRelayerStartFlags(cmd, &StartConfig{}) + logger := tmlog.NewTMLogger(os.Stdout) + + homeDir, err := base.GetHomeDirectory(cmd, ServiceNameRelayer) if err != nil { return err } + logger.Debug("initializing relayer", "home", homeDir) - // creating the logger - logger := tmlog.NewTMLogger(os.Stdout) - logger.Debug("initializing relayer") + fileConfig, err := LoadFileConfiguration(homeDir) + if err != nil { + return err + } + config, err := parseRelayerStartFlags(cmd, fileConfig) + if err != nil { + return err + } + if err := config.ValidateBasics(); err != nil { + return err + } ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() stopFuncs := make([]func() error, 0) - tmQuerier, appQuerier, stops, err := common.NewTmAndAppQuerier(logger, config.coreRPC, config.coreGRPC, config.grpcInsecure) + tmQuerier, appQuerier, stops, err := common.NewTmAndAppQuerier(logger, config.CoreRPC, config.CoreGRPC, config.GrpcInsecure) stopFuncs = append(stopFuncs, stops...) if err != nil { return err @@ -126,7 +150,7 @@ func Start() *cobra.Command { // creating the data store dataStore := dssync.MutexWrap(s.DataStore) - dht, err := common.CreateDHTAndWaitForPeers(ctx, logger, s.P2PKeyStore, config.p2pNickname, config.p2pListenAddr, config.bootstrappers, dataStore) + dht, err := common.CreateDHTAndWaitForPeers(ctx, logger, s.P2PKeyStore, config.p2pNickname, config.P2PListenAddr, config.Bootstrappers, dataStore) if err != nil { return err } @@ -146,23 +170,23 @@ func Start() *cobra.Command { }() // connecting to a Blobstream contract - ethClient, err := ethclient.Dial(config.evmRPC) + ethClient, err := ethclient.Dial(config.EvmRPC) if err != nil { return err } defer ethClient.Close() - blobStreamWrapper, err := blobstreamwrapper.NewWrappers(config.contractAddr, ethClient) + blobstreamWrapper, err := blobstreamwrapper.NewWrappers(ethcmn.HexToAddress(config.ContractAddr), ethClient) if err != nil { return err } evmClient := evm.NewClient( logger, - blobStreamWrapper, + blobstreamWrapper, s.EVMKeyStore, &acc, - config.evmRPC, - config.evmGasLimit, + config.EvmRPC, + config.EvmGasLimit, ) relay := relayer.NewRelayer( diff --git a/cmd/blobstream/relayer/config.go b/cmd/blobstream/relayer/config.go index 37445a64..adbca550 100644 --- a/cmd/blobstream/relayer/config.go +++ b/cmd/blobstream/relayer/config.go @@ -1,23 +1,70 @@ package relayer import ( - "errors" + "bytes" "fmt" + "os" + "path/filepath" "strings" + "text/template" + + "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/celestiaorg/orchestrator-relayer/cmd/blobstream/base" "github.com/spf13/cobra" - - ethcmn "github.com/ethereum/go-ethereum/common" ) const ( ServiceNameRelayer = "relayer" ) +const DefaultConfigTemplate = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### RPC Configuration ### +############################################################################### + +# Celestia app rest rpc address. +core-rpc = "{{ .CoreRPC }}" + +# Celestia app grpc address. +core-grpc = "{{ .CoreGRPC }}" + +# Allow gRPC over insecure channels, if not TLS the server must use TLS. +grpc-insecure = {{ .GrpcInsecure }} + +############################################################################### +### P2P Configuration ### +############################################################################### + +# Comma-separated multiaddresses of p2p peers to connect to. +# Example: "/ip4/127.0.0.1/tcp/30001/p2p/12D3K...,/ip4/127.0.0.1/tcp/30000/p2p/12D3K..." +bootstrappers = "{{ .Bootstrappers }}" + +# MultiAddr for the p2p peer to listen on. +listen-addr = "{{ .P2PListenAddr }}" + +############################################################################### +### EVM Configuration ### +############################################################################### + +# Ethereum rpc address. +evm-rpc = "{{ .EvmRPC }}" + +# Evm chain id. +evm-chain-id = "{{ .EvmChainID }}" + +# Contract address at which Blobstream is deployed. +contract-address = "{{ .ContractAddr }}" + +# Evm gas limit. +gas-limit = "{{ .EvmGasLimit }}" +` + func addRelayerStartFlags(cmd *cobra.Command) *cobra.Command { homeDir, err := base.DefaultServicePath(ServiceNameRelayer) if err != nil { @@ -42,36 +89,55 @@ func addRelayerStartFlags(cmd *cobra.Command) *cobra.Command { type StartConfig struct { base.Config - evmChainID uint64 - evmRPC, coreGRPC, coreRPC string - evmAccAddress string - contractAddr ethcmn.Address - evmGasLimit uint64 - bootstrappers, p2pListenAddr string - p2pNickname string - grpcInsecure bool + EvmChainID uint64 `mapstructure:"evm-chain-id" json:"evm-chain-id"` + EvmRPC string `mapstructure:"evm-rpc" json:"evm-rpc"` + CoreGRPC string `mapstructure:"core-grpc" json:"core-grpc"` + CoreRPC string `mapstructure:"core-rpc" json:"core-rpc"` + evmAccAddress string + ContractAddr string `mapstructure:"contract-address" json:"contract-address"` + EvmGasLimit uint64 `mapstructure:"gas-limit" json:"gas-limit"` + Bootstrappers string `mapstructure:"bootstrappers" json:"bootstrappers"` + P2PListenAddr string `mapstructure:"listen-addr" json:"listen-addr"` + p2pNickname string + GrpcInsecure bool `mapstructure:"grpc-insecure" json:"grpc-insecure"` } -// TODO add a validate basics +func DefaultStartConfig() *StartConfig { + return &StartConfig{ + CoreRPC: "tcp://localhost:26657", + CoreGRPC: "localhost:9090", + Bootstrappers: "", + P2PListenAddr: "/ip4/0.0.0.0/tcp/30000", + GrpcInsecure: true, + EvmChainID: 5, + EvmRPC: "http://localhost:8545", + EvmGasLimit: 2500000, + } +} + +func (cfg StartConfig) ValidateBasics() error { + if err := base.ValidateEVMAddress(cfg.evmAccAddress); err != nil { + return fmt.Errorf("%s: flag --%s", err.Error(), base.FlagEVMAccAddress) + } + if err := base.ValidateEVMAddress(cfg.ContractAddr); err != nil { + return fmt.Errorf("%s: flag --%s", err.Error(), base.FlagEVMContractAddress) + } + return nil +} func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartConfig, error) { - evmAccAddr, changed, err := base.GetEVMAccAddressFlag(cmd) + evmAccAddr, _, err := base.GetEVMAccAddressFlag(cmd) if err != nil { return StartConfig{}, err } - if changed { - if evmAccAddr == "" && fileConfig.evmAccAddress == "" { - return StartConfig{}, errors.New("the evm account address should be specified") - } - fileConfig.evmAccAddress = evmAccAddr - } + fileConfig.evmAccAddress = evmAccAddr evmChainID, changed, err := base.GetEVMChainIDFlag(cmd) if err != nil { return StartConfig{}, err } if changed { - fileConfig.evmChainID = evmChainID + fileConfig.EvmChainID = evmChainID } coreRPC, changed, err := base.GetCoreRPCFlag(cmd) @@ -82,7 +148,7 @@ func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC if !strings.HasPrefix(coreRPC, "tcp://") { coreRPC = fmt.Sprintf("tcp://%s", coreRPC) } - fileConfig.coreRPC = coreRPC + fileConfig.CoreRPC = coreRPC } coreGRPC, changed, err := base.GetCoreGRPCFlag(cmd) @@ -90,7 +156,7 @@ func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.coreGRPC = coreGRPC + fileConfig.CoreGRPC = coreGRPC } contractAddr, changed, err := base.GetEVMContractAddressFlag(cmd) @@ -98,16 +164,7 @@ func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - if contractAddr == "" { - // TODO fix - return StartConfig{}, fmt.Errorf("contract address flag is required: %s", base.FlagEVMContractAddress) - } - if !ethcmn.IsHexAddress(contractAddr) { - // TODO probably not the right place - return StartConfig{}, fmt.Errorf("valid contract address flag is required: %s", base.FlagEVMContractAddress) - } - address := ethcmn.HexToAddress(contractAddr) - fileConfig.contractAddr = address + fileConfig.ContractAddr = contractAddr } evmRPC, changed, err := base.GetEVMRPCFlag(cmd) @@ -115,7 +172,7 @@ func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.evmRPC = evmRPC + fileConfig.EvmRPC = evmRPC } evmGasLimit, changed, err := base.GetEVMGasLimitFlag(cmd) @@ -123,7 +180,7 @@ func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.evmGasLimit = evmGasLimit + fileConfig.EvmGasLimit = evmGasLimit } bootstrappers, changed, err := base.GetBootstrappersFlag(cmd) @@ -131,7 +188,7 @@ func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.bootstrappers = bootstrappers + fileConfig.Bootstrappers = bootstrappers } p2pListenAddress, changed, err := base.GetP2PListenAddressFlag(cmd) @@ -139,39 +196,33 @@ func parseRelayerStartFlags(cmd *cobra.Command, fileConfig *StartConfig) (StartC return StartConfig{}, err } if changed { - fileConfig.p2pListenAddr = p2pListenAddress + fileConfig.P2PListenAddr = p2pListenAddress } - p2pNickname, changed, err := base.GetP2PNicknameFlag(cmd) + p2pNickname, _, err := base.GetP2PNicknameFlag(cmd) if err != nil { return StartConfig{}, err } - if changed { - fileConfig.p2pNickname = p2pNickname - } + fileConfig.p2pNickname = p2pNickname - homeDir, changed, err := base.GetHomeFlag(cmd) + homeDir, _, err := base.GetHomeFlag(cmd) if err != nil { return StartConfig{}, err } - if changed { - fileConfig.Home = homeDir - } + fileConfig.Home = homeDir - passphrase, changed, err := base.GetEVMPassphraseFlag(cmd) + passphrase, _, err := base.GetEVMPassphraseFlag(cmd) if err != nil { return StartConfig{}, err } - if changed { - fileConfig.EVMPassphrase = passphrase - } + fileConfig.EVMPassphrase = passphrase grpcInsecure, changed, err := base.GetGRPCInsecureFlag(cmd) if err != nil { return StartConfig{}, err } if changed { - fileConfig.grpcInsecure = grpcInsecure + fileConfig.GrpcInsecure = grpcInsecure } return *fileConfig, nil @@ -207,3 +258,72 @@ func parseInitFlags(cmd *cobra.Command) (InitConfig, error) { home: homeDir, }, nil } + +func LoadFileConfiguration(homeDir string) (*StartConfig, error) { + v := viper.New() + v.SetEnvPrefix("") + v.AutomaticEnv() + configPath := filepath.Join(homeDir, "config") + configFilePath := filepath.Join(configPath, "config.toml") + conf := DefaultStartConfig() + + // if config.toml file does not exist, we create it and write default ClientConfig values into it. + if _, err := os.Stat(configFilePath); os.IsNotExist(err) { + if err := initializeConfigFile(configFilePath, configPath, conf); err != nil { + return nil, err + } + } + + conf, err := getStartConfig(v, configPath) + if err != nil { + return nil, fmt.Errorf("couldn't get client config: %v", err) + } + return conf, nil +} + +func initializeConfigFile(configFilePath string, configPath string, conf *StartConfig) error { + if err := base.EnsureConfigPath(configPath); err != nil { + return fmt.Errorf("couldn't make relayer config: %v", err) + } + + if err := writeConfigToFile(configFilePath, conf); err != nil { + return fmt.Errorf("could not write relayer config to the file: %v", err) + } + return nil +} + +// writeConfigToFile parses DefaultConfigTemplate, renders config using the template and writes it to +// configFilePath. +func writeConfigToFile(configFilePath string, config *StartConfig) error { + var buffer bytes.Buffer + + tmpl := template.New("relayerConfigFileTemplate") + configTemplate, err := tmpl.Parse(DefaultConfigTemplate) + if err != nil { + return err + } + + if err := configTemplate.Execute(&buffer, config); err != nil { + return err + } + + return os.WriteFile(configFilePath, buffer.Bytes(), 0o600) +} + +// getStartConfig reads values from config.toml file and unmarshalls them into StartConfig +func getStartConfig(v *viper.Viper, configPath string) (*StartConfig, error) { + v.AddConfigPath(configPath) + v.SetConfigName("config") + v.SetConfigType("toml") + + if err := v.ReadInConfig(); err != nil { + return nil, err + } + + conf := new(StartConfig) + if err := v.Unmarshal(conf); err != nil { + return nil, err + } + + return conf, nil +} From afd0ed540c5c9ae5b96cf5fa0783a1dbf41a6834 Mon Sep 17 00:00:00 2001 From: rachid Date: Fri, 10 Nov 2023 11:54:34 +0100 Subject: [PATCH 4/7] chore: error handling --- cmd/blobstream/base/config.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/cmd/blobstream/base/config.go b/cmd/blobstream/base/config.go index d9e2836f..a27a93ce 100644 --- a/cmd/blobstream/base/config.go +++ b/cmd/blobstream/base/config.go @@ -38,7 +38,7 @@ func GetEVMPassphraseFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } // DefaultServicePath constructs the default Blobstream store path for @@ -94,7 +94,7 @@ func GetStartingNonceFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddP2PNicknameFlag(cmd *cobra.Command) { @@ -107,7 +107,7 @@ func GetP2PNicknameFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddP2PListenAddressFlag(cmd *cobra.Command) { @@ -120,7 +120,7 @@ func GetP2PListenAddressFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddBootstrappersFlag(cmd *cobra.Command) { @@ -133,7 +133,7 @@ func GetBootstrappersFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddGRPCInsecureFlag(cmd *cobra.Command) { @@ -146,7 +146,7 @@ func GetGRPCInsecureFlag(cmd *cobra.Command) (bool, bool, error) { if err != nil { return false, changed, err } - return val, changed, err + return val, changed, nil } func AddCoreGRPCFlag(cmd *cobra.Command) { @@ -159,7 +159,7 @@ func GetCoreGRPCFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddEVMChainIDFlag(cmd *cobra.Command) { @@ -172,7 +172,7 @@ func GetEVMChainIDFlag(cmd *cobra.Command) (uint64, bool, error) { if err != nil { return 0, changed, err } - return val, changed, err + return val, changed, nil } func AddCoreRPCFlag(cmd *cobra.Command) { @@ -185,7 +185,7 @@ func GetCoreRPCFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddEVMRPCFlag(cmd *cobra.Command) { @@ -198,7 +198,7 @@ func GetEVMRPCFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddEVMContractAddressFlag(cmd *cobra.Command) { @@ -211,7 +211,7 @@ func GetEVMContractAddressFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func AddEVMGasLimitFlag(cmd *cobra.Command) { @@ -224,7 +224,7 @@ func GetEVMGasLimitFlag(cmd *cobra.Command) (uint64, bool, error) { if err != nil { return 0, changed, err } - return val, changed, err + return val, changed, nil } func AddHomeFlag(cmd *cobra.Command, serviceName string, defaultHomeDir string) { @@ -237,7 +237,7 @@ func GetHomeFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func GetHomeDirectory(cmd *cobra.Command, service string) (string, error) { @@ -261,7 +261,7 @@ func GetEVMAccAddressFlag(cmd *cobra.Command) (string, bool, error) { if err != nil { return "", changed, err } - return val, changed, err + return val, changed, nil } func ValidateEVMAddress(addr string) error { From f9bee3626cfc64dd7549c6fd5b26d9672d97f37a Mon Sep 17 00:00:00 2001 From: rachid Date: Fri, 10 Nov 2023 12:44:29 +0100 Subject: [PATCH 5/7] chore: fix flags in e2e tests --- e2e/scripts/deploy_blobstream_contract.sh | 6 ++---- .../start_orchestrator_after_validator_created.sh | 12 ++++-------- e2e/scripts/start_relayer.sh | 6 ++---- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/e2e/scripts/deploy_blobstream_contract.sh b/e2e/scripts/deploy_blobstream_contract.sh index 11c1f024..d53b068c 100644 --- a/e2e/scripts/deploy_blobstream_contract.sh +++ b/e2e/scripts/deploy_blobstream_contract.sh @@ -66,10 +66,8 @@ echo "deploying Blobstream contract..." /bin/blobstream deploy \ --evm.chain-id "${EVM_CHAIN_ID}" \ --evm.account "${EVM_ACCOUNT}" \ - --core.grpc.host "${CORE_GRPC_HOST}" \ - --core.grpc.port "${CORE_GRPC_PORT}" \ - --core.rpc.host "${CORE_RPC_HOST}" \ - --core.rpc.port "${CORE_RPC_PORT}" \ + --core.rpc="${CORE_RPC_HOST}:${CORE_RPC_PORT}" \ + --core.grpc="${CORE_GRPC_HOST}:${CORE_GRPC_PORT}" \ --grpc.insecure \ --starting-nonce "${STARTING_NONCE}" \ --evm.rpc "${EVM_ENDPOINT}" \ diff --git a/e2e/scripts/start_orchestrator_after_validator_created.sh b/e2e/scripts/start_orchestrator_after_validator_created.sh index 86d41f78..8f8fe0bb 100644 --- a/e2e/scripts/start_orchestrator_after_validator_created.sh +++ b/e2e/scripts/start_orchestrator_after_validator_created.sh @@ -49,10 +49,8 @@ then /bin/blobstream orchestrator start \ --evm.account="${EVM_ACCOUNT}" \ - --core.rpc.host="${CORE_RPC_HOST}" \ - --core.rpc.port="${CORE_RPC_PORT}" \ - --core.grpc.host="${CORE_GRPC_HOST}" \ - --core.grpc.port="${CORE_GRPC_PORT}" \ + --core.rpc="${CORE_RPC_HOST}:${CORE_RPC_PORT}" \ + --core.grpc="${CORE_GRPC_HOST}:${CORE_GRPC_PORT}" \ --grpc.insecure \ --p2p.nickname=key \ --p2p.listen-addr="${P2P_LISTEN}" \ @@ -63,10 +61,8 @@ else /bin/blobstream orchestrator start \ --evm.account="${EVM_ACCOUNT}" \ - --core.rpc.host="${CORE_RPC_HOST}" \ - --core.rpc.port="${CORE_RPC_PORT}" \ - --core.grpc.host="${CORE_GRPC_HOST}" \ - --core.grpc.port="${CORE_GRPC_PORT}" \ + --core.rpc="${CORE_RPC_HOST}:${CORE_RPC_PORT}" \ + --core.grpc="${CORE_GRPC_HOST}:${CORE_GRPC_PORT}" \ --grpc.insecure \ --p2p.listen-addr="${P2P_LISTEN}" \ --p2p.bootstrappers="${P2P_BOOTSTRAPPERS}" \ diff --git a/e2e/scripts/start_relayer.sh b/e2e/scripts/start_relayer.sh index 0f756641..9df35082 100644 --- a/e2e/scripts/start_relayer.sh +++ b/e2e/scripts/start_relayer.sh @@ -55,10 +55,8 @@ BLOBSTREAM_CONTRACT=$(cat /opt/blobstream_address.txt) sleep 5s /bin/blobstream relayer start \ --evm.account="${EVM_ACCOUNT}" \ - --core.rpc.host="${CORE_RPC_HOST}" \ - --core.rpc.port="${CORE_RPC_PORT}" \ - --core.grpc.host="${CORE_GRPC_HOST}" \ - --core.grpc.port="${CORE_GRPC_PORT}" \ + --core.rpc="${CORE_RPC_HOST}:${CORE_RPC_PORT}" \ + --core.grpc="${CORE_GRPC_HOST}:${CORE_GRPC_PORT}" \ --grpc.insecure \ --evm.chain-id="${EVM_CHAIN_ID}" \ --evm.rpc="${EVM_ENDPOINT}" \ From ff3aec628f125b7922e5b45d95af2510c57a446d Mon Sep 17 00:00:00 2001 From: rachid Date: Fri, 10 Nov 2023 12:50:04 +0100 Subject: [PATCH 6/7] chore: fix config for deploy command --- cmd/blobstream/deploy/config.go | 75 +++++++++++++-------------------- 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/cmd/blobstream/deploy/config.go b/cmd/blobstream/deploy/config.go index 30bf4da0..2187dd0c 100644 --- a/cmd/blobstream/deploy/config.go +++ b/cmd/blobstream/deploy/config.go @@ -43,92 +43,75 @@ type deployConfig struct { grpcInsecure bool } -func parseDeployFlags(cmd *cobra.Command, fileConfig *deployConfig) (deployConfig, error) { - evmAccAddr, changed, err := base.GetEVMAccAddressFlag(cmd) +func parseDeployFlags(cmd *cobra.Command) (deployConfig, error) { + evmAccAddr, _, err := base.GetEVMAccAddressFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - if evmAccAddr == "" && fileConfig.evmAccAddress == "" { - return deployConfig{}, errors.New("the evm account address should be specified") - } - fileConfig.evmAccAddress = evmAccAddr + if evmAccAddr == "" { + return deployConfig{}, errors.New("the evm account address should be specified") } - evmChainID, changed, err := base.GetEVMChainIDFlag(cmd) + evmChainID, _, err := base.GetEVMChainIDFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.evmChainID = evmChainID - } - coreRPC, changed, err := base.GetCoreRPCFlag(cmd) + coreRPC, _, err := base.GetCoreRPCFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - if !strings.HasPrefix(coreRPC, "tcp://") { - coreRPC = fmt.Sprintf("tcp://%s", coreRPC) - } - fileConfig.coreRPC = coreRPC + if !strings.HasPrefix(coreRPC, "tcp://") { + coreRPC = fmt.Sprintf("tcp://%s", coreRPC) } - coreGRPC, changed, err := base.GetCoreGRPCFlag(cmd) + coreGRPC, _, err := base.GetCoreGRPCFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.coreGRPC = coreGRPC - } - evmRPC, changed, err := base.GetEVMRPCFlag(cmd) + evmRPC, _, err := base.GetEVMRPCFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.evmRPC = evmRPC - } - startingNonce, changed, err := base.GetStartingNonceFlag(cmd) + startingNonce, _, err := base.GetStartingNonceFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.startingNonce = startingNonce - } - evmGasLimit, changed, err := base.GetEVMGasLimitFlag(cmd) + evmGasLimit, _, err := base.GetEVMGasLimitFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.evmGasLimit = evmGasLimit - } - homeDir, changed, err := base.GetHomeFlag(cmd) + homeDir, _, err := base.GetHomeFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.Home = homeDir - } - passphrase, changed, err := base.GetEVMPassphraseFlag(cmd) + passphrase, _, err := base.GetEVMPassphraseFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.EVMPassphrase = passphrase - } - grpcInsecure, changed, err := base.GetGRPCInsecureFlag(cmd) + grpcInsecure, _, err := base.GetGRPCInsecureFlag(cmd) if err != nil { return deployConfig{}, err } - if changed { - fileConfig.grpcInsecure = grpcInsecure - } - return *fileConfig, nil + return deployConfig{ + Config: base.Config{ + Home: homeDir, + EVMPassphrase: passphrase, + }, + evmRPC: evmRPC, + coreRPC: coreRPC, + coreGRPC: coreGRPC, + evmChainID: evmChainID, + evmAccAddress: evmAccAddr, + startingNonce: startingNonce, + evmGasLimit: evmGasLimit, + grpcInsecure: grpcInsecure, + }, nil } From 458b9e53bac53a58cbac6477a9bc7b29f8682ced Mon Sep 17 00:00:00 2001 From: rachid Date: Fri, 10 Nov 2023 12:50:19 +0100 Subject: [PATCH 7/7] chore: fix config for deploy command --- cmd/blobstream/deploy/cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/blobstream/deploy/cmd.go b/cmd/blobstream/deploy/cmd.go index 4c7f2446..cf1c6b14 100644 --- a/cmd/blobstream/deploy/cmd.go +++ b/cmd/blobstream/deploy/cmd.go @@ -27,7 +27,7 @@ func Command() *cobra.Command { Use: "deploy ", Short: "Deploys the Blobstream contract and initializes it using the provided Celestia chain", RunE: func(cmd *cobra.Command, args []string) error { - config, err := parseDeployFlags(cmd, &deployConfig{}) + config, err := parseDeployFlags(cmd) if err != nil { return err }