diff --git a/README.md b/README.md index 8810840a..260e108c 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ See the [Building](#building) section for instructions on how to build the relay - platform.validatedBy - platform.getValidatorsAt OR platform.getCurrentValidators +The Fuji and Mainnet [public API nodes](https://docs.avax.network/tooling/rpc-providers) provided by Avalanche have these methods enabled, and are suitable for use with the relayer. + ## Usage ### Building @@ -90,25 +92,22 @@ The relayer binary accepts a path to a JSON configuration file as the sole argum The relayer is configured via a JSON file, the path to which is passed in via the `--config-file` command line argument. The following configuration options are available: -`"log-level": "debug" | "info" | "warn" | "error" | "fatal" | "panic"` +`"log-level": "verbo" | "debug" | "info" | "warn" | "error" | "fatal" | "panic"` - The log level for the relayer. Defaults to `info`. -`"network-id": unsigned integer` - -- The ID of the Avalanche network to which the relayer will connect. Defaults to `1` (Mainnet). - `"p-chain-api-url": string` - The URL of the Avalanche P-Chain API node to which the relayer will connect. This API node needs to have the following methods enabled: - - info.peers - platform.getHeight - platform.validatedBy - platform.getValidatorsAt -`"encrypt-connection": boolean` +`"info-api-url": string` -- Whether or not to encrypt the connection to the P-Chain API node. Defaults to `true`. +- The URL of the Avalanche Info API node to which the relayer will connect. This API node needs to have the following methods enabled: + - info.peers + - info.getNetworkID `"storage-location": string` @@ -142,45 +141,33 @@ The relayer is configured via a JSON file, the path to which is passed in via th - The address of the destination account that will receive the Warp message. -`"source-subnets": []SourceSubnets` +`"source-blockchains": []SourceBlockchains` -- The list of source subnets to support. Each `SourceSubnet` has the following configuration: +- The list of source subnets to support. Each `SourceBlockchain` has the following configuration: `"subnet-id": string` - - cb58-encoded Subnet ID + - cb58-encoded Subnet ID. `"blockchain-id": string` - - cb58-encoded Blockchain ID + - cb58-encoded Blockchain ID. `"vm": string` - The VM type of the source subnet. - `"api-node-host": string` - - - The host of the source subnet's API node. - - `"api-node-port": unsigned integer` - - - The port of the source subnet's API node. - - `"encrypt-connection": boolean` - - - Whether or not to encrypt the connection to the source subnet's API node. - `"rpc-endpoint": string` - - The RPC endpoint of the source subnet's API node. Used in favor of `api-node-host`, `api-node-port`, and `encrypt-connection` when constructing the endpoint + - The RPC endpoint of the source subnet's API node. `"ws-endpoint": string` - - The WebSocket endpoint of the source subnet's API node. Used in favor of `api-node-host`, `api-node-port`, and `encrypt-connection` when constructing the endpoint + - The WebSocket endpoint of the source subnet's API node. `"message-contracts": map[string]MessageProtocolConfig` - - Map of contract addresses to the config options of the protocol at that address. Each `MessageProtocolConfig` consists of a unique `message-format` name, and the raw JSON `settings` + - Map of contract addresses to the config options of the protocol at that address. Each `MessageProtocolConfig` consists of a unique `message-format` name, and the raw JSON `settings`. `"supported-destinations": []string` @@ -190,37 +177,25 @@ The relayer is configured via a JSON file, the path to which is passed in via th - The block height at which to back-process transactions from the source subnet. If the database already contains a later block height for the source subnet, then that will be used instead. Must be non-zero. -`"destination-subnets": []DestinationSubnets` +`"destination-blockchains": []DestinationBlockchains` -- The list of destination subnets to support. Each `DestinationSubnet` has the following configuration: +- The list of destination subnets to support. Each `DestinationBlockchain` has the following configuration: `"subnet-id": string` - - cb58-encoded Subnet ID + - cb58-encoded Subnet ID. `"blockchain-id": string` - - cb58-encoded Blockchain ID + - cb58-encoded Blockchain ID. `"vm": string` - The VM type of the source subnet. - `"api-node-host": string` - - - The host of the source subnet's API node. - - `"api-node-port": unsigned integer` - - - The port of the source subnet's API node. - - `"encrypt-connection": boolean` - - - Whether or not to encrypt the connection to the source subnet's API node. - `"rpc-endpoint": string` - - The RPC endpoint of the destination subnet's API node. Used in favor of `api-node-host`, `api-node-port`, and `encrypt-connection` when constructing the endpoint + - The RPC endpoint of the destination subnet's API node. `"account-private-key": string` diff --git a/config/config.go b/config/config.go index dd6cb9ce..4dba303a 100644 --- a/config/config.go +++ b/config/config.go @@ -55,13 +55,10 @@ type ManualWarpMessage struct { destinationAddress common.Address } -type SourceSubnet struct { +type SourceBlockchain struct { SubnetID string `mapstructure:"subnet-id" json:"subnet-id"` BlockchainID string `mapstructure:"blockchain-id" json:"blockchain-id"` VM string `mapstructure:"vm" json:"vm"` - APINodeHost string `mapstructure:"api-node-host" json:"api-node-host"` - APINodePort uint32 `mapstructure:"api-node-port" json:"api-node-port"` - EncryptConnection bool `mapstructure:"encrypt-connection" json:"encrypt-connection"` RPCEndpoint string `mapstructure:"rpc-endpoint" json:"rpc-endpoint"` WSEndpoint string `mapstructure:"ws-endpoint" json:"ws-endpoint"` MessageContracts map[string]MessageProtocolConfig `mapstructure:"message-contracts" json:"message-contracts"` @@ -72,13 +69,10 @@ type SourceSubnet struct { supportedDestinations set.Set[ids.ID] } -type DestinationSubnet struct { +type DestinationBlockchain struct { SubnetID string `mapstructure:"subnet-id" json:"subnet-id"` BlockchainID string `mapstructure:"blockchain-id" json:"blockchain-id"` VM string `mapstructure:"vm" json:"vm"` - APINodeHost string `mapstructure:"api-node-host" json:"api-node-host"` - APINodePort uint32 `mapstructure:"api-node-port" json:"api-node-port"` - EncryptConnection bool `mapstructure:"encrypt-connection" json:"encrypt-connection"` RPCEndpoint string `mapstructure:"rpc-endpoint" json:"rpc-endpoint"` AccountPrivateKey string `mapstructure:"account-private-key" json:"account-private-key"` @@ -92,15 +86,14 @@ type WarpQuorum struct { } type Config struct { - LogLevel string `mapstructure:"log-level" json:"log-level"` - NetworkID uint32 `mapstructure:"network-id" json:"network-id"` - PChainAPIURL string `mapstructure:"p-chain-api-url" json:"p-chain-api-url"` - EncryptConnection bool `mapstructure:"encrypt-connection" json:"encrypt-connection"` - StorageLocation string `mapstructure:"storage-location" json:"storage-location"` - SourceSubnets []*SourceSubnet `mapstructure:"source-subnets" json:"source-subnets"` - DestinationSubnets []*DestinationSubnet `mapstructure:"destination-subnets" json:"destination-subnets"` - ProcessMissedBlocks bool `mapstructure:"process-missed-blocks" json:"process-missed-blocks"` - ManualWarpMessages []*ManualWarpMessage `mapstructure:"manual-warp-messages" json:"manual-warp-messages"` + LogLevel string `mapstructure:"log-level" json:"log-level"` + PChainAPIURL string `mapstructure:"p-chain-api-url" json:"p-chain-api-url"` + InfoAPIURL string `mapstructure:"info-api-url" json:"info-api-url"` + StorageLocation string `mapstructure:"storage-location" json:"storage-location"` + SourceBlockchains []*SourceBlockchain `mapstructure:"source-blockchains" json:"source-blockchains"` + DestinationBlockchains []*DestinationBlockchain `mapstructure:"destination-blockchains" json:"destination-blockchains"` + ProcessMissedBlocks bool `mapstructure:"process-missed-blocks" json:"process-missed-blocks"` + ManualWarpMessages []*ManualWarpMessage `mapstructure:"manual-warp-messages" json:"manual-warp-messages"` // convenience fields to access the source subnet and chain IDs after initialization sourceSubnetIDs []ids.ID @@ -109,8 +102,6 @@ type Config struct { func SetDefaultConfigValues(v *viper.Viper) { v.SetDefault(LogLevelKey, logging.Info.String()) - v.SetDefault(NetworkIDKey, constants.MainnetID) - v.SetDefault(EncryptConnectionKey, true) v.SetDefault(StorageLocationKey, "./.awm-relayer-storage") v.SetDefault(ProcessMissedBlocksKey, true) } @@ -138,18 +129,17 @@ func BuildConfig(v *viper.Viper) (Config, bool, error) { ) cfg.LogLevel = v.GetString(LogLevelKey) - cfg.NetworkID = v.GetUint32(NetworkIDKey) cfg.PChainAPIURL = v.GetString(PChainAPIURLKey) - cfg.EncryptConnection = v.GetBool(EncryptConnectionKey) + cfg.InfoAPIURL = v.GetString(InfoAPIURLKey) cfg.StorageLocation = v.GetString(StorageLocationKey) cfg.ProcessMissedBlocks = v.GetBool(ProcessMissedBlocksKey) if err := v.UnmarshalKey(ManualWarpMessagesKey, &cfg.ManualWarpMessages); err != nil { return Config{}, false, fmt.Errorf("failed to unmarshal manual warp messages: %w", err) } - if err := v.UnmarshalKey(DestinationSubnetsKey, &cfg.DestinationSubnets); err != nil { + if err := v.UnmarshalKey(DestinationBlockchainsKey, &cfg.DestinationBlockchains); err != nil { return Config{}, false, fmt.Errorf("failed to unmarshal destination subnets: %w", err) } - if err := v.UnmarshalKey(SourceSubnetsKey, &cfg.SourceSubnets); err != nil { + if err := v.UnmarshalKey(SourceBlockchainsKey, &cfg.SourceBlockchains); err != nil { return Config{}, false, fmt.Errorf("failed to unmarshal source subnets: %w", err) } @@ -160,19 +150,19 @@ func BuildConfig(v *viper.Viper) (Config, bool, error) { accountPrivateKey := v.GetString(AccountPrivateKeyKey) if accountPrivateKey != "" { optionOverwritten = true - for i := range cfg.DestinationSubnets { - cfg.DestinationSubnets[i].AccountPrivateKey = utils.SanitizeHexString(accountPrivateKey) + for i := range cfg.DestinationBlockchains { + cfg.DestinationBlockchains[i].AccountPrivateKey = utils.SanitizeHexString(accountPrivateKey) } } else { // Otherwise, check for private keys suffixed with the chain ID and set it for that subnet // Since the key is dynamic, this is only possible through environment variables - for i, subnet := range cfg.DestinationSubnets { + for i, subnet := range cfg.DestinationBlockchains { subnetAccountPrivateKey := os.Getenv(fmt.Sprintf("%s_%s", accountPrivateKeyEnvVarName, subnet.BlockchainID)) if subnetAccountPrivateKey != "" { optionOverwritten = true - cfg.DestinationSubnets[i].AccountPrivateKey = utils.SanitizeHexString(subnetAccountPrivateKey) + cfg.DestinationBlockchains[i].AccountPrivateKey = utils.SanitizeHexString(subnetAccountPrivateKey) } else { - cfg.DestinationSubnets[i].AccountPrivateKey = utils.SanitizeHexString(cfg.DestinationSubnets[i].AccountPrivateKey) + cfg.DestinationBlockchains[i].AccountPrivateKey = utils.SanitizeHexString(cfg.DestinationBlockchains[i].AccountPrivateKey) } } } @@ -181,19 +171,6 @@ func BuildConfig(v *viper.Viper) (Config, bool, error) { return Config{}, false, fmt.Errorf("failed to validate configuration: %w", err) } - var protocol string - if cfg.EncryptConnection { - protocol = "https" - } else { - protocol = "http" - } - - pChainapiUrl, err := utils.ConvertProtocol(cfg.PChainAPIURL, protocol) - if err != nil { - return Config{}, false, err - } - cfg.PChainAPIURL = pChainapiUrl - return cfg, optionOverwritten, nil } @@ -201,19 +178,22 @@ func BuildConfig(v *viper.Viper) (Config, bool, error) { // Does not modify the public fields as derived from the configuration passed to the application, // but does initialize private fields available through getters func (c *Config) Validate() error { - if len(c.SourceSubnets) == 0 { + if len(c.SourceBlockchains) == 0 { return errors.New("relayer not configured to relay from any subnets. A list of source subnets must be provided in the configuration file") } - if len(c.DestinationSubnets) == 0 { + if len(c.DestinationBlockchains) == 0 { return errors.New("relayer not configured to relay to any subnets. A list of destination subnets must be provided in the configuration file") } if _, err := url.ParseRequestURI(c.PChainAPIURL); err != nil { return err } + if _, err := url.ParseRequestURI(c.InfoAPIURL); err != nil { + return err + } // Validate the destination chains - destinationChains := set.NewSet[string](len(c.DestinationSubnets)) - for _, s := range c.DestinationSubnets { + destinationChains := set.NewSet[string](len(c.DestinationBlockchains)) + for _, s := range c.DestinationBlockchains { if err := s.Validate(); err != nil { return err } @@ -224,10 +204,10 @@ func (c *Config) Validate() error { } // Validate the source chains and store the source subnet and chain IDs for future use - sourceBlockchains := set.NewSet[string](len(c.SourceSubnets)) + sourceBlockchains := set.NewSet[string](len(c.SourceBlockchains)) var sourceSubnetIDs []ids.ID var sourceBlockchainIDs []ids.ID - for _, s := range c.SourceSubnets { + for _, s := range c.SourceBlockchains { // Validate configuration if err := s.Validate(&destinationChains); err != nil { return err @@ -379,7 +359,7 @@ func getWarpQuorum( func (c *Config) InitializeWarpQuorums() error { // Fetch the Warp quorum values for each destination subnet. - for _, destinationSubnet := range c.DestinationSubnets { + for _, destinationSubnet := range c.DestinationBlockchains { err := destinationSubnet.initializeWarpQuorum() if err != nil { return fmt.Errorf("failed to initialize Warp quorum for destination subnet %s: %w", destinationSubnet.SubnetID, err) @@ -389,24 +369,24 @@ func (c *Config) InitializeWarpQuorums() error { return nil } -func (s *SourceSubnet) GetSupportedDestinations() set.Set[ids.ID] { +func (s *SourceBlockchain) GetSupportedDestinations() set.Set[ids.ID] { return s.supportedDestinations } // Validates the source subnet configuration, including verifying that the supported destinations are present in destinationBlockchainIDs // Does not modify the public fields as derived from the configuration passed to the application, // but does initialize private fields available through getters -func (s *SourceSubnet) Validate(destinationBlockchainIDs *set.Set[string]) error { +func (s *SourceBlockchain) Validate(destinationBlockchainIDs *set.Set[string]) error { if _, err := ids.FromString(s.SubnetID); err != nil { return fmt.Errorf("invalid subnetID in source subnet configuration. Provided ID: %s", s.SubnetID) } if _, err := ids.FromString(s.BlockchainID); err != nil { return fmt.Errorf("invalid blockchainID in source subnet configuration. Provided ID: %s", s.BlockchainID) } - if _, err := url.ParseRequestURI(s.GetNodeWSEndpoint()); err != nil { + if _, err := url.ParseRequestURI(s.WSEndpoint); err != nil { return fmt.Errorf("invalid relayer subscribe URL in source subnet configuration: %w", err) } - if _, err := url.ParseRequestURI(s.GetNodeRPCEndpoint()); err != nil { + if _, err := url.ParseRequestURI(s.RPCEndpoint); err != nil { return fmt.Errorf("invalid relayer RPC URL in source subnet configuration: %w", err) } @@ -461,14 +441,14 @@ func (s *SourceSubnet) Validate(destinationBlockchainIDs *set.Set[string]) error } // Validatees the destination subnet configuration -func (s *DestinationSubnet) Validate() error { +func (s *DestinationBlockchain) Validate() error { if _, err := ids.FromString(s.SubnetID); err != nil { return fmt.Errorf("invalid subnetID in source subnet configuration. Provided ID: %s", s.SubnetID) } if _, err := ids.FromString(s.BlockchainID); err != nil { return fmt.Errorf("invalid blockchainID in source subnet configuration. Provided ID: %s", s.BlockchainID) } - if _, err := url.ParseRequestURI(s.GetNodeRPCEndpoint()); err != nil { + if _, err := url.ParseRequestURI(s.RPCEndpoint); err != nil { return fmt.Errorf("invalid relayer broadcast URL: %w", err) } @@ -489,7 +469,7 @@ func (s *DestinationSubnet) Validate() error { return nil } -func (s *DestinationSubnet) initializeWarpQuorum() error { +func (s *DestinationBlockchain) initializeWarpQuorum() error { blockchainID, err := ids.FromString(s.BlockchainID) if err != nil { return fmt.Errorf("invalid blockchainID in configuration. error: %w", err) @@ -499,7 +479,7 @@ func (s *DestinationSubnet) initializeWarpQuorum() error { return fmt.Errorf("invalid subnetID in configuration. error: %w", err) } - client, err := ethclient.Dial(s.GetNodeRPCEndpoint()) + client, err := ethclient.Dial(s.RPCEndpoint) if err != nil { return fmt.Errorf("failed to dial destination blockchain %s: %w", blockchainID, err) } @@ -513,92 +493,8 @@ func (s *DestinationSubnet) initializeWarpQuorum() error { return nil } -func constructURL(protocol string, host string, port uint32, encrypt bool, blockchainIDStr string, subnetIDStr string) string { - var protocolPathMap = map[string]string{ - "http": "rpc", - "ws": "ws", - } - path := protocolPathMap[protocol] - - if encrypt { - protocol = protocol + "s" - } - portStr := "" - if port != 0 { - portStr = fmt.Sprintf(":%d", port) - } - subnetID, _ := ids.FromString(subnetIDStr) // already validated in Validate() - if subnetID == constants.PrimaryNetworkID { - blockchainIDStr = cChainIdentifierString - } - return fmt.Sprintf("%s://%s%s/ext/bc/%s/%s", protocol, host, portStr, blockchainIDStr, path) -} - -// Constructs an RPC endpoint for the subnet. -// If the RPCEndpoint field is set in the configuration, returns that directly. -// Otherwise, constructs the endpoint from the APINodeHost, APINodePort, and EncryptConnection fields, -// following the /ext/bc/{blockchainID}/rpc format. -func (s *DestinationSubnet) GetNodeRPCEndpoint() string { - if s.RPCEndpoint != "" { - return s.RPCEndpoint - } - - // Save this result for future use - s.RPCEndpoint = constructURL( - "http", - s.APINodeHost, - s.APINodePort, - s.EncryptConnection, - s.BlockchainID, - s.SubnetID, - ) - return s.RPCEndpoint -} - -// Constructs an RPC endpoint for the subnet. -// If the RPCEndpoint field is set in the configuration, returns that directly. -// Otherwise, constructs the endpoint from the APINodeHost, APINodePort, and EncryptConnection fields, -// following the /ext/bc/{blockchainID}/rpc format. -func (s *SourceSubnet) GetNodeRPCEndpoint() string { - if s.RPCEndpoint != "" { - return s.RPCEndpoint - } - - // Save this result for future use - s.RPCEndpoint = constructURL( - "http", - s.APINodeHost, - s.APINodePort, - s.EncryptConnection, - s.BlockchainID, - s.SubnetID, - ) - return s.RPCEndpoint -} - -// Constructs a WS endpoint for the subnet. -// If the WSEndpoint field is set in the configuration, returns that directly. -// Otherwise, constructs the endpoint from the APINodeHost, APINodePort, and EncryptConnection fields, -// following the /ext/bc/{blockchainID}/ws format. -func (s *SourceSubnet) GetNodeWSEndpoint() string { - if s.WSEndpoint != "" { - return s.WSEndpoint - } - - // Save this result for future use - s.WSEndpoint = constructURL( - "ws", - s.APINodeHost, - s.APINodePort, - s.EncryptConnection, - s.BlockchainID, - s.SubnetID, - ) - return s.WSEndpoint -} - // Get the private key and derive the wallet address from a relayer's configured private key for a given destination subnet. -func (s *DestinationSubnet) GetRelayerAccountInfo() (*ecdsa.PrivateKey, common.Address, error) { +func (s *DestinationBlockchain) GetRelayerAccountInfo() (*ecdsa.PrivateKey, common.Address, error) { pk, err := crypto.HexToECDSA(s.AccountPrivateKey) if err != nil { return nil, common.Address{}, err @@ -617,7 +513,7 @@ func (c *Config) GetSourceIDs() ([]ids.ID, []ids.ID) { } func (c *Config) GetWarpQuorum(blockchainID ids.ID) (WarpQuorum, error) { - for _, s := range c.DestinationSubnets { + for _, s := range c.DestinationBlockchains { if blockchainID.String() == s.BlockchainID { return s.warpQuorum, nil } diff --git a/config/config_test.go b/config/config_test.go index 13ea2add..2f9c0c4e 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -29,20 +29,17 @@ var ( testBlockchainID string = "S4mMqUXe7vHsGiRAma6bv3CKnyaLssyAxmQ2KvFpX1KEvfFCD" testBlockchainID2 string = "291etJW5EpagFY94v1JraFy8vLFYXcCnWKJ6Yz9vrjfPjCF4QL" testAddress string = "0xd81545385803bCD83bd59f58Ba2d2c0562387F83" - primarySubnetID string = "11111111111111111111111111111111LpoYY" testValidConfig = Config{ - LogLevel: "info", - NetworkID: 1337, - PChainAPIURL: "http://test.avax.network", - EncryptConnection: false, - SourceSubnets: []*SourceSubnet{ + LogLevel: "info", + PChainAPIURL: "http://test.avax.network", + InfoAPIURL: "http://test.avax.network", + SourceBlockchains: []*SourceBlockchain{ { - APINodeHost: "http://test.avax.network", - APINodePort: 0, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - VM: "evm", - EncryptConnection: false, + RPCEndpoint: fmt.Sprintf("http://test.avax.network/ext/bc/%s/rpc", testBlockchainID), + WSEndpoint: fmt.Sprintf("ws://test.avax.network/ext/bc/%s/ws", testBlockchainID), + BlockchainID: testBlockchainID, + SubnetID: testSubnetID, + VM: "evm", MessageContracts: map[string]MessageProtocolConfig{ testAddress: { MessageFormat: TELEPORTER.String(), @@ -50,14 +47,12 @@ var ( }, }, }, - DestinationSubnets: []*DestinationSubnet{ + DestinationBlockchains: []*DestinationBlockchain{ { - APINodeHost: "http://test.avax.network", - APINodePort: 0, + RPCEndpoint: fmt.Sprintf("http://test.avax.network/ext/bc/%s/rpc", testBlockchainID), BlockchainID: testBlockchainID, SubnetID: testSubnetID, VM: "evm", - EncryptConnection: false, AccountPrivateKey: "0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", }, }, @@ -66,157 +61,6 @@ var ( testPk2 string = "0x12389e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8123" ) -func TestGetDestinationRPCEndpoint(t *testing.T) { - testCases := []struct { - name string - s DestinationSubnet - expectedResult string - }{ - { - name: "No encrypt connection", - s: DestinationSubnet{ - EncryptConnection: false, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - }, - expectedResult: fmt.Sprintf("http://127.0.0.1:9650/ext/bc/%s/rpc", testBlockchainID), - }, - { - name: "Encrypt connection", - s: DestinationSubnet{ - EncryptConnection: true, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - }, - expectedResult: fmt.Sprintf("https://127.0.0.1:9650/ext/bc/%s/rpc", testBlockchainID), - }, - { - name: "No port", - s: DestinationSubnet{ - EncryptConnection: false, - APINodeHost: "api.avax.network", - APINodePort: 0, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - }, - expectedResult: fmt.Sprintf("http://api.avax.network/ext/bc/%s/rpc", testBlockchainID), - }, - { - name: "Primary subnet", - s: DestinationSubnet{ - EncryptConnection: false, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: primarySubnetID, - }, - expectedResult: "http://127.0.0.1:9650/ext/bc/C/rpc", - }, - { - name: "Override with set rpc endpoint", - s: DestinationSubnet{ - EncryptConnection: false, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - RPCEndpoint: "https://subnets.avax.network/mysubnet/rpc", // overrides all other settings used to construct the endpoint - }, - expectedResult: "https://subnets.avax.network/mysubnet/rpc", - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - res := testCase.s.GetNodeRPCEndpoint() - require.Equal(t, testCase.expectedResult, res) - }) - } -} - -func TestGetSourceSubnetEndpoints(t *testing.T) { - testCases := []struct { - name string - s SourceSubnet - expectedWsResult string - expectedRpcResult string - }{ - { - name: "No encrypt connection", - s: SourceSubnet{ - EncryptConnection: false, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - }, - expectedWsResult: fmt.Sprintf("ws://127.0.0.1:9650/ext/bc/%s/ws", testBlockchainID), - expectedRpcResult: fmt.Sprintf("http://127.0.0.1:9650/ext/bc/%s/rpc", testBlockchainID), - }, - { - name: "Encrypt connection", - s: SourceSubnet{ - EncryptConnection: true, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - }, - expectedWsResult: fmt.Sprintf("wss://127.0.0.1:9650/ext/bc/%s/ws", testBlockchainID), - expectedRpcResult: fmt.Sprintf("https://127.0.0.1:9650/ext/bc/%s/rpc", testBlockchainID), - }, - { - name: "No port", - s: SourceSubnet{ - EncryptConnection: false, - APINodeHost: "api.avax.network", - APINodePort: 0, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - }, - expectedWsResult: fmt.Sprintf("ws://api.avax.network/ext/bc/%s/ws", testBlockchainID), - expectedRpcResult: fmt.Sprintf("http://api.avax.network/ext/bc/%s/rpc", testBlockchainID), - }, - { - name: "Primary subnet", - s: SourceSubnet{ - EncryptConnection: false, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: primarySubnetID, - }, - expectedWsResult: "ws://127.0.0.1:9650/ext/bc/C/ws", - expectedRpcResult: "http://127.0.0.1:9650/ext/bc/C/rpc", - }, - { - name: "Override with set endpoints", - s: SourceSubnet{ - EncryptConnection: false, - APINodeHost: "127.0.0.1", - APINodePort: 9650, - BlockchainID: testBlockchainID, - SubnetID: testSubnetID, - WSEndpoint: "wss://subnets.avax.network/mysubnet/ws", // overrides all other settings used to construct the endpoint - RPCEndpoint: "https://subnets.avax.network/mysubnet/rpc", // overrides all other settings used to construct the endpoint - }, - expectedWsResult: "wss://subnets.avax.network/mysubnet/ws", - expectedRpcResult: "https://subnets.avax.network/mysubnet/rpc", - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - require.Equal(t, testCase.expectedWsResult, testCase.s.GetNodeWSEndpoint()) - require.Equal(t, testCase.expectedRpcResult, testCase.s.GetNodeRPCEndpoint()) - }) - } -} - func TestGetRelayerAccountInfo(t *testing.T) { type retStruct struct { pk *ecdsa.PrivateKey @@ -226,12 +70,12 @@ func TestGetRelayerAccountInfo(t *testing.T) { testCases := []struct { name string - s DestinationSubnet + s DestinationBlockchain expectedResult retStruct }{ { name: "valid", - s: DestinationSubnet{ + s: DestinationBlockchain{ AccountPrivateKey: "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", }, expectedResult: retStruct{ @@ -244,7 +88,7 @@ func TestGetRelayerAccountInfo(t *testing.T) { }, { name: "invalid 0x prefix", - s: DestinationSubnet{ + s: DestinationBlockchain{ AccountPrivateKey: "0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", }, expectedResult: retStruct{ @@ -257,7 +101,7 @@ func TestGetRelayerAccountInfo(t *testing.T) { }, { name: "invalid private key", - s: DestinationSubnet{ + s: DestinationBlockchain{ AccountPrivateKey: "invalid56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", }, expectedResult: retStruct{ @@ -324,9 +168,9 @@ func TestGetRelayerAccountPrivateKey_set_pk_in_config(t *testing.T) { expectedOverwritten: false, resultVerifier: func(c Config) bool { // All destination subnets should have the default private key - for i, subnet := range c.DestinationSubnets { - if subnet.AccountPrivateKey != utils.SanitizeHexString(testValidConfig.DestinationSubnets[i].AccountPrivateKey) { - fmt.Printf("expected: %s, got: %s\n", utils.SanitizeHexString(testValidConfig.DestinationSubnets[i].AccountPrivateKey), subnet.AccountPrivateKey) + for i, subnet := range c.DestinationBlockchains { + if subnet.AccountPrivateKey != utils.SanitizeHexString(testValidConfig.DestinationBlockchains[i].AccountPrivateKey) { + fmt.Printf("expected: %s, got: %s\n", utils.SanitizeHexString(testValidConfig.DestinationBlockchains[i].AccountPrivateKey), subnet.AccountPrivateKey) return false } } @@ -341,26 +185,26 @@ func TestGetRelayerAccountPrivateKey_set_pk_with_subnet_env(t *testing.T) { baseConfig: testValidConfig, configModifier: func(c Config) Config { // Add a second destination subnet. This PK should NOT be overwritten - newSubnet := *c.DestinationSubnets[0] + newSubnet := *c.DestinationBlockchains[0] newSubnet.BlockchainID = testBlockchainID2 newSubnet.AccountPrivateKey = testPk1 - c.DestinationSubnets = append(c.DestinationSubnets, &newSubnet) + c.DestinationBlockchains = append(c.DestinationBlockchains, &newSubnet) return c }, envSetter: func() { // Overwrite the PK for the first subnet using an env var - varName := fmt.Sprintf("%s_%s", accountPrivateKeyEnvVarName, testValidConfig.DestinationSubnets[0].BlockchainID) + varName := fmt.Sprintf("%s_%s", accountPrivateKeyEnvVarName, testValidConfig.DestinationBlockchains[0].BlockchainID) t.Setenv(varName, testPk2) }, expectedOverwritten: true, resultVerifier: func(c Config) bool { // All destination subnets should have testPk1 - if c.DestinationSubnets[0].AccountPrivateKey != utils.SanitizeHexString(testPk2) { - fmt.Printf("expected: %s, got: %s\n", utils.SanitizeHexString(testPk2), c.DestinationSubnets[0].AccountPrivateKey) + if c.DestinationBlockchains[0].AccountPrivateKey != utils.SanitizeHexString(testPk2) { + fmt.Printf("expected: %s, got: %s\n", utils.SanitizeHexString(testPk2), c.DestinationBlockchains[0].AccountPrivateKey) return false } - if c.DestinationSubnets[1].AccountPrivateKey != utils.SanitizeHexString(testPk1) { - fmt.Printf("expected: %s, got: %s\n", utils.SanitizeHexString(testPk1), c.DestinationSubnets[1].AccountPrivateKey) + if c.DestinationBlockchains[1].AccountPrivateKey != utils.SanitizeHexString(testPk1) { + fmt.Printf("expected: %s, got: %s\n", utils.SanitizeHexString(testPk1), c.DestinationBlockchains[1].AccountPrivateKey) return false } return true @@ -373,10 +217,10 @@ func TestGetRelayerAccountPrivateKey_set_pk_with_global_env(t *testing.T) { baseConfig: testValidConfig, configModifier: func(c Config) Config { // Add a second destination subnet. This PK SHOULD be overwritten - newSubnet := *c.DestinationSubnets[0] + newSubnet := *c.DestinationBlockchains[0] newSubnet.BlockchainID = testBlockchainID2 newSubnet.AccountPrivateKey = testPk1 - c.DestinationSubnets = append(c.DestinationSubnets, &newSubnet) + c.DestinationBlockchains = append(c.DestinationBlockchains, &newSubnet) return c }, envSetter: func() { @@ -386,7 +230,7 @@ func TestGetRelayerAccountPrivateKey_set_pk_with_global_env(t *testing.T) { expectedOverwritten: true, resultVerifier: func(c Config) bool { // All destination subnets should have testPk2 - for _, subnet := range c.DestinationSubnets { + for _, subnet := range c.DestinationBlockchains { if subnet.AccountPrivateKey != utils.SanitizeHexString(testPk2) { fmt.Printf("expected: %s, got: %s\n", utils.SanitizeHexString(testPk2), subnet.AccountPrivateKey) return false @@ -409,7 +253,7 @@ func TestGetRelayerAccountInfoSkipChainConfigCheckCompatible(t *testing.T) { accountPrivateKey := "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027" expectedAddress := "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC" - info := DestinationSubnet{ + info := DestinationBlockchain{ AccountPrivateKey: accountPrivateKey, } _, address, err := info.GetRelayerAccountInfo() @@ -544,14 +388,13 @@ func TestGetWarpQuorum(t *testing.T) { } } -func TestValidateSourceSubnet(t *testing.T) { - validSourceCfg := SourceSubnet{ - APINodeHost: "http://test.avax.network", - APINodePort: 0, +func TestValidateSourceBlockchain(t *testing.T) { + validSourceCfg := SourceBlockchain{ BlockchainID: testBlockchainID, + RPCEndpoint: fmt.Sprintf("http://test.avax.network/ext/bc/%s/rpc", testBlockchainID), + WSEndpoint: fmt.Sprintf("ws://test.avax.network/ext/bc/%s/ws", testBlockchainID), SubnetID: testSubnetID, VM: "evm", - EncryptConnection: false, SupportedDestinations: []string{testBlockchainID}, MessageContracts: map[string]MessageProtocolConfig{ testAddress: { @@ -561,21 +404,21 @@ func TestValidateSourceSubnet(t *testing.T) { } testCases := []struct { name string - sourceSubnet func() SourceSubnet + sourceSubnet func() SourceBlockchain destinationBlockchainIDs []string expectError bool expectedSupportedDestinations []string }{ { name: "valid source subnet; explicitly supported destination", - sourceSubnet: func() SourceSubnet { return validSourceCfg }, + sourceSubnet: func() SourceBlockchain { return validSourceCfg }, destinationBlockchainIDs: []string{testBlockchainID}, expectError: false, expectedSupportedDestinations: []string{testBlockchainID}, }, { name: "valid source subnet; implicitly supported destination", - sourceSubnet: func() SourceSubnet { + sourceSubnet: func() SourceBlockchain { cfg := validSourceCfg cfg.SupportedDestinations = nil return cfg @@ -586,14 +429,14 @@ func TestValidateSourceSubnet(t *testing.T) { }, { name: "valid source subnet; partially supported destinations", - sourceSubnet: func() SourceSubnet { return validSourceCfg }, + sourceSubnet: func() SourceBlockchain { return validSourceCfg }, destinationBlockchainIDs: []string{testBlockchainID, testBlockchainID2}, expectError: false, expectedSupportedDestinations: []string{testBlockchainID}, }, { name: "valid source subnet; unsupported destinations", - sourceSubnet: func() SourceSubnet { return validSourceCfg }, + sourceSubnet: func() SourceBlockchain { return validSourceCfg }, destinationBlockchainIDs: []string{testBlockchainID2}, expectError: true, expectedSupportedDestinations: []string{}, diff --git a/config/keys.go b/config/keys.go index 096eef83..274ec6cb 100644 --- a/config/keys.go +++ b/config/keys.go @@ -5,15 +5,14 @@ package config // Top-level configuration keys const ( - ConfigFileKey = "config-file" - LogLevelKey = "log-level" - NetworkIDKey = "network-id" - PChainAPIURLKey = "p-chain-api-url" - SourceSubnetsKey = "source-subnets" - DestinationSubnetsKey = "destination-subnets" - EncryptConnectionKey = "encrypt-connection" - AccountPrivateKeyKey = "account-private-key" - StorageLocationKey = "storage-location" - ProcessMissedBlocksKey = "process-missed-blocks" - ManualWarpMessagesKey = "manual-warp-messages" + ConfigFileKey = "config-file" + LogLevelKey = "log-level" + PChainAPIURLKey = "p-chain-api-url" + InfoAPIURLKey = "info-api-url" + SourceBlockchainsKey = "source-blockchains" + DestinationBlockchainsKey = "destination-blockchains" + AccountPrivateKeyKey = "account-private-key" + StorageLocationKey = "storage-location" + ProcessMissedBlocksKey = "process-missed-blocks" + ManualWarpMessagesKey = "manual-warp-messages" ) diff --git a/main/main.go b/main/main.go index 175118a1..4a816856 100644 --- a/main/main.go +++ b/main/main.go @@ -106,7 +106,7 @@ func main() { if logLevel <= logging.Debug { networkLogLevel = logLevel } - network, responseChans, err := peers.NewNetwork(networkLogLevel, registerer, cfg.NetworkID, sourceSubnetIDs, sourceBlockchainIDs, cfg.PChainAPIURL) + network, responseChans, err := peers.NewNetwork(networkLogLevel, registerer, sourceSubnetIDs, sourceBlockchainIDs, cfg.InfoAPIURL) if err != nil { logger.Error( "Failed to create app request network", @@ -189,7 +189,7 @@ func main() { // Create relayers for each of the subnets configured as a source errGroup, ctx := errgroup.WithContext(context.Background()) - for _, s := range cfg.SourceSubnets { + for _, s := range cfg.SourceBlockchains { blockchainID, err := ids.FromString(s.BlockchainID) if err != nil { logger.Error( @@ -236,7 +236,7 @@ func runRelayer( logger logging.Logger, metrics *relayer.MessageRelayerMetrics, db database.RelayerDatabase, - sourceSubnetInfo config.SourceSubnet, + sourceSubnetInfo config.SourceBlockchain, pChainClient platformvm.Client, network *peers.AppRequestNetwork, responseChan chan message.InboundMessage, diff --git a/peers/app_request_network.go b/peers/app_request_network.go index 4effcb31..a64f1016 100644 --- a/peers/app_request_network.go +++ b/peers/app_request_network.go @@ -16,7 +16,6 @@ import ( "github.com/ava-labs/avalanchego/message" "github.com/ava-labs/avalanchego/network" "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/ips" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" @@ -43,10 +42,9 @@ type AppRequestNetwork struct { func NewNetwork( logLevel logging.Level, registerer prometheus.Registerer, - networkID uint32, subnetIDs []ids.ID, blockchainIDs []ids.ID, - APINodeURL string, + infoAPINodeURL string, ) (*AppRequestNetwork, map[ids.ID]chan message.InboundMessage, error) { logger := logging.NewLogger( "awm-relayer-p2p", @@ -57,10 +55,20 @@ func NewNetwork( ), ) - if networkID != constants.MainnetID && - networkID != constants.FujiID && - len(APINodeURL) == 0 { - return nil, nil, fmt.Errorf("must provide an API URL for local networks") + if infoAPINodeURL == "" { + logger.Error("No InfoAPI node URL provided") + return nil, nil, fmt.Errorf("must provide an Inffo API URL") + } + + // Create the info client + infoClient := info.NewClient(infoAPINodeURL) + networkID, err := infoClient.GetNetworkID(context.Background()) + if err != nil { + logger.Error( + "Failed to get network ID", + zap.Error(err), + ) + return nil, nil, err } // Create the test network for AppRequests @@ -97,13 +105,8 @@ func NewNetwork( // We need to initially connect to some nodes in the network before peer // gossip will enable connecting to all the remaining nodes in the network. - var ( - beaconIPs, beaconIDs []string - infoClient info.Client - ) + var beaconIPs, beaconIDs []string - // Create the info client - infoClient = info.NewClient(APINodeURL) peers, err := infoClient.Peers(context.Background()) if err != nil { logger.Error( diff --git a/relayer/message_relayer.go b/relayer/message_relayer.go index 08f332fc..4c8f3793 100644 --- a/relayer/message_relayer.go +++ b/relayer/message_relayer.go @@ -145,7 +145,9 @@ func (r *messageRelayer) relayMessage(unsignedMessage *avalancheWarp.UnsignedMes // will need to be accounted for here. func (r *messageRelayer) createSignedMessage() (*avalancheWarp.Message, error) { r.relayer.logger.Info("Fetching aggregate signature from the source chain validators via API") - warpClient, err := warpBackend.NewClient(r.relayer.apiNodeURI, r.relayer.sourceBlockchainID.String()) + // TODO: To properly support this, we should provide a dedicated Warp API endpoint in the config + uri := utils.StripFromString(r.relayer.rpcEndpoint, "/ext") + warpClient, err := warpBackend.NewClient(uri, r.relayer.sourceBlockchainID.String()) if err != nil { r.relayer.logger.Error( "Failed to create Warp API client", diff --git a/relayer/relayer.go b/relayer/relayer.go index cd6fc732..e3a8825a 100644 --- a/relayer/relayer.go +++ b/relayer/relayer.go @@ -21,7 +21,6 @@ import ( "github.com/ava-labs/awm-relayer/database" "github.com/ava-labs/awm-relayer/messages" "github.com/ava-labs/awm-relayer/peers" - "github.com/ava-labs/awm-relayer/utils" vms "github.com/ava-labs/awm-relayer/vms" "github.com/ava-labs/awm-relayer/vms/vmtypes" "github.com/ava-labs/coreth/ethclient" @@ -59,7 +58,6 @@ type Relayer struct { db database.RelayerDatabase supportedDestinations set.Set[ids.ID] rpcEndpoint string - apiNodeURI string messageCreator message.Creator catchUpResultChan chan bool healthStatus *atomic.Bool @@ -70,7 +68,7 @@ func NewRelayer( logger logging.Logger, metrics *MessageRelayerMetrics, db database.RelayerDatabase, - sourceSubnetInfo config.SourceSubnet, + sourceSubnetInfo config.SourceBlockchain, pChainClient platformvm.Client, network *peers.AppRequestNetwork, responseChan chan message.InboundMessage, @@ -114,9 +112,6 @@ func NewRelayer( messageManagers[address] = messageManager } - rpcEndpoint := sourceSubnetInfo.GetNodeRPCEndpoint() - uri := utils.StripFromString(rpcEndpoint, "/ext") - // Marks when the relayer has finished the catch-up process on startup. // Until that time, we do not know the order in which messages are processed, // since the catch-up process occurs concurrently with normal message processing @@ -147,8 +142,7 @@ func NewRelayer( metrics: metrics, db: db, supportedDestinations: sourceSubnetInfo.GetSupportedDestinations(), - rpcEndpoint: rpcEndpoint, - apiNodeURI: uri, + rpcEndpoint: sourceSubnetInfo.RPCEndpoint, messageCreator: messageCreator, catchUpResultChan: catchUpResultChan, healthStatus: relayerHealth, diff --git a/scripts/build_local_image.sh b/scripts/build_local_image.sh index fe6c4f44..ca98e39a 100755 --- a/scripts/build_local_image.sh +++ b/scripts/build_local_image.sh @@ -19,8 +19,13 @@ source "$RELAYER_PATH"/scripts/versions.sh full_commit_hash="$(git --git-dir="$RELAYER_PATH/.git" rev-parse HEAD)" commit_hash="${full_commit_hash::8}" +./scripts/build.sh +cp $RELAYER_PATH/build/awm-relayer $RELAYER_PATH/awm-relayer + echo "Building Docker Image with tags: $relayer_dockerhub_repo:$commit_hash , $relayer_dockerhub_repo:$current_branch" docker build -t "$relayer_dockerhub_repo:$commit_hash" \ -t "$relayer_dockerhub_repo:$current_branch" \ "$RELAYER_PATH" -f "$RELAYER_PATH/Dockerfile" \ --build-arg GO_VERSION=$GO_VERSION + +rm $RELAYER_PATH/awm-relayer \ No newline at end of file diff --git a/tests/basic_relay.go b/tests/basic_relay.go index 3d33f0c9..89c09f1f 100644 --- a/tests/basic_relay.go +++ b/tests/basic_relay.go @@ -163,7 +163,7 @@ func BasicRelay(network interfaces.LocalNetwork) { // StartBlockHeight to the block height of the *third* message, we expect the relayer to skip // the first two messages on startup, but process the third. modifiedRelayerConfig := relayerConfig - modifiedRelayerConfig.SourceSubnets[0].StartBlockHeight = currHeight + modifiedRelayerConfig.SourceBlockchains[0].StartBlockHeight = currHeight modifiedRelayerConfig.ProcessMissedBlocks = true relayerConfigPath = writeRelayerConfig(modifiedRelayerConfig) diff --git a/tests/utils/utils.go b/tests/utils/utils.go index 5efea861..be3000ef 100644 --- a/tests/utils/utils.go +++ b/tests/utils/utils.go @@ -14,7 +14,6 @@ import ( "os/exec" "strings" - anrConstants "github.com/ava-labs/avalanche-network-runner/utils/constants" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/awm-relayer/config" offchainregistry "github.com/ava-labs/awm-relayer/messages/off-chain-registry" @@ -95,19 +94,19 @@ func CreateDefaultRelayerConfig( "Setting up relayer config", ) // Construct the config values for each subnet - sources := make([]*config.SourceSubnet, len(subnetsInfo)) - destinations := make([]*config.DestinationSubnet, len(subnetsInfo)) + sources := make([]*config.SourceBlockchain, len(subnetsInfo)) + destinations := make([]*config.DestinationBlockchain, len(subnetsInfo)) for i, subnetInfo := range subnetsInfo { host, port, err := teleporterTestUtils.GetURIHostAndPort(subnetInfo.NodeURIs[0]) Expect(err).Should(BeNil()) - sources[i] = &config.SourceSubnet{ - SubnetID: subnetInfo.SubnetID.String(), - BlockchainID: subnetInfo.BlockchainID.String(), - VM: config.EVM.String(), - EncryptConnection: false, - APINodeHost: host, - APINodePort: port, + sources[i] = &config.SourceBlockchain{ + SubnetID: subnetInfo.SubnetID.String(), + BlockchainID: subnetInfo.BlockchainID.String(), + VM: config.EVM.String(), + RPCEndpoint: fmt.Sprintf("http://%s:%d/ext/bc/%s/rpc", host, port, subnetInfo.BlockchainID.String()), + WSEndpoint: fmt.Sprintf("ws://%s:%d/ext/bc/%s/ws", host, port, subnetInfo.BlockchainID.String()), + MessageContracts: map[string]config.MessageProtocolConfig{ teleporterContractAddress.Hex(): { MessageFormat: config.TELEPORTER.String(), @@ -124,13 +123,11 @@ func CreateDefaultRelayerConfig( }, } - destinations[i] = &config.DestinationSubnet{ + destinations[i] = &config.DestinationBlockchain{ SubnetID: subnetInfo.SubnetID.String(), BlockchainID: subnetInfo.BlockchainID.String(), VM: config.EVM.String(), - EncryptConnection: false, - APINodeHost: host, - APINodePort: port, + RPCEndpoint: fmt.Sprintf("http://%s:%d/ext/bc/%s/rpc", host, port, subnetInfo.BlockchainID.String()), AccountPrivateKey: hex.EncodeToString(relayerKey.D.Bytes()), } @@ -144,14 +141,13 @@ func CreateDefaultRelayerConfig( } return config.Config{ - LogLevel: logging.Info.LowerString(), - NetworkID: anrConstants.DefaultNetworkID, - PChainAPIURL: subnetsInfo[0].NodeURIs[0], - EncryptConnection: false, - StorageLocation: RelayerStorageLocation(), - ProcessMissedBlocks: false, - SourceSubnets: sources, - DestinationSubnets: destinations, + LogLevel: logging.Info.LowerString(), + PChainAPIURL: subnetsInfo[0].NodeURIs[0], + InfoAPIURL: subnetsInfo[0].NodeURIs[0], + StorageLocation: RelayerStorageLocation(), + ProcessMissedBlocks: false, + SourceBlockchains: sources, + DestinationBlockchains: destinations, } } diff --git a/utils/utils.go b/utils/utils.go index d3e297c3..9ffc296c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -5,9 +5,7 @@ package utils import ( "errors" - "fmt" "math/big" - "net/url" "strings" "github.com/ethereum/go-ethereum/common" @@ -64,23 +62,6 @@ func BigToHashSafe(in *big.Int) (common.Hash, error) { return common.BytesToHash(bytes), nil } -func ConvertProtocol(URLString, protocol string) (string, error) { - var ( - u *url.URL - err error - ) - if u, err = url.ParseRequestURI(URLString); err != nil { - return "", fmt.Errorf("invalid url") - } - - u.Scheme = protocol - if _, err = url.ParseRequestURI(u.String()); err != nil { - return "", fmt.Errorf("invalid protocol") - } - - return u.String(), nil -} - // SanitizeHexString removes the "0x" prefix from a hex string if it exists. // Otherwise, returns the original string. func SanitizeHexString(hex string) string { diff --git a/utils/utils_test.go b/utils/utils_test.go index 5ff732e2..2349915b 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -10,65 +10,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestConvertProtocol(t *testing.T) { - testCases := []struct { - name string - urlString string - protocol string - expectedUrl string - expectedError bool - }{ - { - name: "valid http to https", - urlString: "http://www.hello.com", - protocol: "https", - expectedUrl: "https://www.hello.com", - expectedError: false, - }, - { - name: "valid https to http", - urlString: "https://www.hello.com", - protocol: "http", - expectedUrl: "http://www.hello.com", - expectedError: false, - }, - { - name: "valid http to http", - urlString: "http://www.hello.com", - protocol: "http", - expectedUrl: "http://www.hello.com", - expectedError: false, - }, - { - name: "valid https to https", - urlString: "https://www.hello.com", - protocol: "https", - expectedUrl: "https://www.hello.com", - expectedError: false, - }, - { - name: "invalid protocol", - urlString: "http://www.hello.com", - protocol: "\n", - expectedUrl: "", - expectedError: true, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - actualUrl, err := ConvertProtocol(testCase.urlString, testCase.protocol) - - if testCase.expectedError { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, testCase.expectedUrl, actualUrl) - } - }) - } -} - func TestSanitizeHexString(t *testing.T) { testCases := []struct { name string diff --git a/vms/contract_message.go b/vms/contract_message.go index a3cf1794..f7331171 100644 --- a/vms/contract_message.go +++ b/vms/contract_message.go @@ -15,7 +15,7 @@ type ContractMessage interface { UnpackWarpMessage(unsignedMsgBytes []byte) (*warp.UnsignedMessage, error) } -func NewContractMessage(logger logging.Logger, subnetInfo config.SourceSubnet) ContractMessage { +func NewContractMessage(logger logging.Logger, subnetInfo config.SourceBlockchain) ContractMessage { switch config.ParseVM(subnetInfo.VM) { case config.EVM: return evm.NewContractMessage(logger, subnetInfo) diff --git a/vms/destination_client.go b/vms/destination_client.go index c8352367..bed8a808 100644 --- a/vms/destination_client.go +++ b/vms/destination_client.go @@ -34,7 +34,7 @@ type DestinationClient interface { DestinationBlockchainID() ids.ID } -func NewDestinationClient(logger logging.Logger, subnetInfo config.DestinationSubnet) (DestinationClient, error) { +func NewDestinationClient(logger logging.Logger, subnetInfo config.DestinationBlockchain) (DestinationClient, error) { switch config.ParseVM(subnetInfo.VM) { case config.EVM: return evm.NewDestinationClient(logger, subnetInfo) @@ -46,7 +46,7 @@ func NewDestinationClient(logger logging.Logger, subnetInfo config.DestinationSu // CreateDestinationClients creates destination clients for all subnets configured as destinations func CreateDestinationClients(logger logging.Logger, relayerConfig config.Config) (map[ids.ID]DestinationClient, error) { destinationClients := make(map[ids.ID]DestinationClient) - for _, subnetInfo := range relayerConfig.DestinationSubnets { + for _, subnetInfo := range relayerConfig.DestinationBlockchains { blockchainID, err := ids.FromString(subnetInfo.BlockchainID) if err != nil { logger.Error( diff --git a/vms/evm/contract_message.go b/vms/evm/contract_message.go index ce5dcbc7..49ace169 100644 --- a/vms/evm/contract_message.go +++ b/vms/evm/contract_message.go @@ -17,7 +17,7 @@ type contractMessage struct { logger logging.Logger } -func NewContractMessage(logger logging.Logger, subnetInfo config.SourceSubnet) *contractMessage { +func NewContractMessage(logger logging.Logger, subnetInfo config.SourceBlockchain) *contractMessage { return &contractMessage{ logger: logger, } diff --git a/vms/evm/contract_message_test.go b/vms/evm/contract_message_test.go index 269c4e56..cff0ec97 100644 --- a/vms/evm/contract_message_test.go +++ b/vms/evm/contract_message_test.go @@ -51,7 +51,7 @@ func TestUnpack(t *testing.T) { logging.JSON.ConsoleEncoder(), ), ) - m := NewContractMessage(logger, config.SourceSubnet{}) + m := NewContractMessage(logger, config.SourceBlockchain{}) testCases := []struct { name string diff --git a/vms/evm/destination_client.go b/vms/evm/destination_client.go index 83d1e774..0be4a735 100644 --- a/vms/evm/destination_client.go +++ b/vms/evm/destination_client.go @@ -48,9 +48,9 @@ type destinationClient struct { logger logging.Logger } -func NewDestinationClient(logger logging.Logger, subnetInfo config.DestinationSubnet) (*destinationClient, error) { +func NewDestinationClient(logger logging.Logger, subnetInfo config.DestinationBlockchain) (*destinationClient, error) { // Dial the destination RPC endpoint - client, err := ethclient.Dial(subnetInfo.GetNodeRPCEndpoint()) + client, err := ethclient.Dial(subnetInfo.RPCEndpoint) if err != nil { logger.Error( "Failed to dial rpc endpoint", diff --git a/vms/evm/destination_client_test.go b/vms/evm/destination_client_test.go index 2081a96a..c7be3413 100644 --- a/vms/evm/destination_client_test.go +++ b/vms/evm/destination_client_test.go @@ -17,13 +17,10 @@ import ( "go.uber.org/mock/gomock" ) -var destinationSubnet = config.DestinationSubnet{ +var destinationSubnet = config.DestinationBlockchain{ SubnetID: "2TGBXcnwx5PqiXWiqxAKUaNSqDguXNh1mxnp82jui68hxJSZAx", BlockchainID: "S4mMqUXe7vHsGiRAma6bv3CKnyaLssyAxmQ2KvFpX1KEvfFCD", VM: config.EVM.String(), - APINodeHost: "127.0.0.1", - APINodePort: 9650, - EncryptConnection: false, RPCEndpoint: "https://subnets.avax.network/mysubnet/rpc", AccountPrivateKey: "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", } diff --git a/vms/evm/subscriber.go b/vms/evm/subscriber.go index fedb8de1..432c8df9 100644 --- a/vms/evm/subscriber.go +++ b/vms/evm/subscriber.go @@ -61,7 +61,7 @@ type subscriber struct { } // NewSubscriber returns a subscriber -func NewSubscriber(logger logging.Logger, subnetInfo config.SourceSubnet) *subscriber { +func NewSubscriber(logger logging.Logger, subnetInfo config.SourceBlockchain) *subscriber { blockchainID, err := ids.FromString(subnetInfo.BlockchainID) if err != nil { logger.Error( @@ -74,8 +74,8 @@ func NewSubscriber(logger logging.Logger, subnetInfo config.SourceSubnet) *subsc logs := make(chan vmtypes.WarpLogInfo, maxClientSubscriptionBuffer) return &subscriber{ - nodeWSURL: subnetInfo.GetNodeWSEndpoint(), - nodeRPCURL: subnetInfo.GetNodeRPCEndpoint(), + nodeWSURL: subnetInfo.WSEndpoint, + nodeRPCURL: subnetInfo.RPCEndpoint, blockchainID: blockchainID, logger: logger, logsChan: logs, diff --git a/vms/evm/subscriber_test.go b/vms/evm/subscriber_test.go index 09734c75..e46aed84 100644 --- a/vms/evm/subscriber_test.go +++ b/vms/evm/subscriber_test.go @@ -15,14 +15,11 @@ import ( ) func makeSubscriberWithMockEthClient(t *testing.T) (*subscriber, *mock_ethclient.MockClient) { - sourceSubnet := config.SourceSubnet{ - SubnetID: "2TGBXcnwx5PqiXWiqxAKUaNSqDguXNh1mxnp82jui68hxJSZAx", - BlockchainID: "S4mMqUXe7vHsGiRAma6bv3CKnyaLssyAxmQ2KvFpX1KEvfFCD", - VM: config.EVM.String(), - APINodeHost: "127.0.0.1", - APINodePort: 9650, - EncryptConnection: false, - RPCEndpoint: "https://subnets.avax.network/mysubnet/rpc", + sourceSubnet := config.SourceBlockchain{ + SubnetID: "2TGBXcnwx5PqiXWiqxAKUaNSqDguXNh1mxnp82jui68hxJSZAx", + BlockchainID: "S4mMqUXe7vHsGiRAma6bv3CKnyaLssyAxmQ2KvFpX1KEvfFCD", + VM: config.EVM.String(), + RPCEndpoint: "https://subnets.avax.network/mysubnet/rpc", } logger := logging.NoLog{} diff --git a/vms/subscriber.go b/vms/subscriber.go index 3dbc6362..3a25199b 100644 --- a/vms/subscriber.go +++ b/vms/subscriber.go @@ -37,7 +37,7 @@ type Subscriber interface { } // NewSubscriber returns a concrete Subscriber according to the VM specified by [subnetInfo] -func NewSubscriber(logger logging.Logger, subnetInfo config.SourceSubnet) Subscriber { +func NewSubscriber(logger logging.Logger, subnetInfo config.SourceBlockchain) Subscriber { switch config.ParseVM(subnetInfo.VM) { case config.EVM: return evm.NewSubscriber(logger, subnetInfo)