diff --git a/app/clients/hedera/client.go b/app/clients/hedera/client.go index a991dc9fe..ccfcb8521 100644 --- a/app/clients/hedera/client.go +++ b/app/clients/hedera/client.go @@ -25,33 +25,6 @@ import ( log "github.com/sirupsen/logrus" ) -var mainnetNodes = map[string]hedera.AccountID{ - "15.165.118.251:50211": {Account: 3}, - "137.116.36.18:50211": {Account: 4}, - "107.155.64.98:50211": {Account: 5}, - "13.71.90.154:50211": {Account: 6}, - "23.102.74.34:50211": {Account: 7}, - "23.96.185.18:50211": {Account: 8}, - //"31.214.8.131:50211": {Account: 9}, - "179.190.33.184:50211": {Account: 10}, - "69.87.221.231:50211": {Account: 11}, - "51.140.102.228:50211": {Account: 12}, - "13.77.158.252:50211": {Account: 13}, - "40.114.107.85:50211": {Account: 14}, - "40.89.139.247:50211": {Account: 15}, - "50.7.124.46:50211": {Account: 16}, - "40.114.92.39:50211": {Account: 17}, - "139.162.156.222:50211": {Account: 18}, - //"51.140.43.81:50211": {Account: 19}, - "13.77.151.212:50211": {Account: 20}, - "13.36.123.209:50211": {Account: 21}, - "52.78.202.34:50211": {Account: 22}, - "3.18.91.176:50211": {Account: 23}, - //"18.135.7.211:50211": {Account: 24}, - "13.232.240.207:50211": {Account: 25}, - "13.228.103.14:50211": {Account: 26}, -} - // Node struct holding the hedera.Client. Used to interact with Hedera consensus nodes type Node struct { client *hedera.Client @@ -63,10 +36,6 @@ func NewNodeClient(config config.Hedera) *Node { switch config.Network { case "mainnet": client = hedera.ClientForMainnet() - err := client.SetNetwork(mainnetNodes) - if err != nil { - log.Fatalf("Could not set mainnet nodes. Error [%s]", err) - } case "testnet": client = hedera.ClientForTestnet() case "previewnet": @@ -74,6 +43,15 @@ func NewNodeClient(config config.Hedera) *Node { default: log.Fatalf("Invalid Client Network provided: [%s]", config.Network) } + if len(config.Rpc) > 0 { + log.Infof("Setting provided RPC nodes for [%s].", config.Network) + err := client.SetNetwork(config.Rpc) + if err != nil { + log.Fatalf("Could not set rpc nodes [%s]. Error: [%s]", config.Rpc, err) + } + } else { + log.Infof("Setting default node rpc urls for [%s].", config.Network) + } accID, err := hedera.AccountIDFromString(config.Operator.AccountId) if err != nil { diff --git a/config/node.go b/config/node.go index b1b65916f..b8b9b1d04 100644 --- a/config/node.go +++ b/config/node.go @@ -17,7 +17,9 @@ package config import ( + "github.com/hashgraph/hedera-sdk-go/v2" "github.com/limechain/hedera-eth-bridge-validator/config/parser" + log "github.com/sirupsen/logrus" "time" ) @@ -55,6 +57,7 @@ type Evm struct { type Hedera struct { Operator Operator Network string + Rpc map[string]hedera.AccountID StartTimestamp int64 } @@ -75,6 +78,15 @@ type Recovery struct { } func New(node parser.Node) Node { + rpc := make(map[string]hedera.AccountID) + for key, value := range node.Clients.Hedera.Rpc { + nodeAccoundID, err := hedera.AccountIDFromString(value) + if err != nil { + log.Fatalf("Hedera RPC [%s] failed to parse Node Account ID [%s]. Error: [%s]", key, value, err) + } + rpc[key] = nodeAccoundID + } + config := Node{ Database: Database(node.Database), Clients: Clients{ @@ -82,6 +94,7 @@ func New(node parser.Node) Node { Operator: Operator(node.Clients.Hedera.Operator), Network: node.Clients.Hedera.Network, StartTimestamp: node.Clients.Hedera.StartTimestamp, + Rpc: rpc, }, MirrorNode: MirrorNode(node.Clients.MirrorNode), Evm: make(map[int64]Evm), diff --git a/config/node.yml b/config/node.yml index 7f7c0031c..b27415fc7 100644 --- a/config/node.yml +++ b/config/node.yml @@ -12,13 +12,12 @@ node: account_id: private_key: network: testnet + rpc: +# "127.0.0.1": "0.0.1" mirror_node: api_address: https://testnet.mirrornode.hedera.com/api/v1/ client_address: hcs.testnet.mirrornode.hedera.com:5600 polling_interval: 5 log_level: info port: 5200 - recovery: - start_timestamp: - start_block: validator: true \ No newline at end of file diff --git a/config/parser/node.go b/config/parser/node.go index c5ee709d9..7b0a86496 100644 --- a/config/parser/node.go +++ b/config/parser/node.go @@ -53,9 +53,10 @@ type Evm struct { } type Hedera struct { - Operator Operator `yaml:"operator"` - Network string `yaml:"network"` - StartTimestamp int64 `yaml:"start_timestamp"` + Operator Operator `yaml:"operator"` + Network string `yaml:"network"` + Rpc map[string]string `yaml:"rpc"` + StartTimestamp int64 `yaml:"start_timestamp"` } type Operator struct { diff --git a/docs/configuration.md b/docs/configuration.md index 7e831eabf..97d5b22f2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -15,43 +15,43 @@ Unless you need to set a non-default value, it is recommended to only populate o Configuration for `config/node.yml`: -Name | Default | Description --------------------------------------------------------------- | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -`node.database.host` | 127.0.0.1 | The IP or hostname used to connect to the database. -`node.database.name` | hedera_validator | The name of the database. -`node.database.password` | validator_pass | The database password the processor uses to connect. -`node.database.port` | 5432 | The port used to connect to the database. -`node.database.username` | validator | The username the processor uses to connect to the database. -`node.clients.evm[]` | "" | The chain id of the EVM network. Used as a key for the following `node.clients.evm[i].*` configuration fields below. -`node.clients.evm[].block_confirmations` | "" | The number of block confirmations to wait for before processing an event for the given EVM network. -`node.clients.evm[].node_url` | "" | The endpoint of the node for the given EVM network. -`node.clients.evm[].private_key` | "" | The private key for the given EVM network. -`node.clients.evm[].start_block` | 0 | The block from which the application will monitor for events for the given network. If specified, it will start in its primary mode (check `node.validator`) from the given block. If not specified, it will start in read-only mode from the latest saved block in the database to the current block at runtime (`now`) and then continue in its primary mode. -`node.clients.evm[].polling_interval` | 15 | How often (in seconds) the evm client will poll the network for upcoming events. -`node.clients.evm[].max_logs_blocks` | 500 | The maximum amount of blocks range per query when filtering events. -`node.clients.hedera.operator.account_id` | "" | The operator's Hedera account id. -`node.clients.hedera.operator.private_key` | "" | The operator's Hedera private key. -`node.clients.hedera.network` | testnet | Which Hedera network to use. Can be either `mainnet`, `previewnet`, `testnet`. -`node.clients.hedera.start_timestamp` | 0 | The timestamp from which the Hedera Transfer and Hedera Message watchers will begin. If specified, the Hedera Transfers and Messages will begin listening in its primary mode (check `node.validator`) from the given timestamp. If not specified, the HT and Messages will run in read-only mode from the latest saved timestamp in the database to the moment the application has been run (`now`) and then continue in its primary mode. -`node.clients.mirror_node.api_address` | https://testnet.mirrornode.hedera.com/api/v1/ | The Hedera Rest API root endpoint. Depending on the Hedera network type, this will need to be changed. -`node.clients.mirror_node.client_address` | hcs.testnet.mirrornode.hedera.com:5600 | The HCS Mirror node endpoint. Depending on the Hedera network type, this will need to be changed. -`node.clients.mirror_node.polling_interval` | 5 | How often (in seconds) the application will poll the mirror node for new transactions. -`node.log_level` | info | The log level of the validator. Possible values: `info`, `debug`, `trace` case insensitive. -`node.port` | 5200 | The port on which the application runs. -`node.validator` | true | The primary mode in which the application will run. If set to `true`, the application will make write operations (HCS submission, Scheduled Transactions). If set to `false`, the application will be in a read-only mode, searching for transactions/messages from the other validators in the networks. - +| Name | Default | Description | +|---------------------------------------------|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `node.database.host` | 127.0.0.1 | The IP or hostname used to connect to the database. | +| `node.database.name` | hedera_validator | The name of the database. | +| `node.database.password` | validator_pass | The database password the processor uses to connect. | +| `node.database.port` | 5432 | The port used to connect to the database. | +| `node.database.username` | validator | The username the processor uses to connect to the database. | +| `node.clients.evm[]` | "" | The chain id of the EVM network. Used as a key for the following `node.clients.evm[i].*` configuration fields below. | +| `node.clients.evm[].block_confirmations` | "" | The number of block confirmations to wait for before processing an event for the given EVM network. | +| `node.clients.evm[].node_url` | "" | The endpoint of the node for the given EVM network. | +| `node.clients.evm[].private_key` | "" | The private key for the given EVM network. | +| `node.clients.evm[].start_block` | 0 | The block from which the application will monitor for events for the given network. If specified, it will start in its primary mode (check `node.validator`) from the given block. If not specified, it will start in read-only mode from the latest saved block in the database to the current block at runtime (`now`) and then continue in its primary mode. | +| `node.clients.evm[].polling_interval` | 15 | How often (in seconds) the evm client will poll the network for upcoming events. | +| `node.clients.evm[].max_logs_blocks` | 500 | The maximum amount of blocks range per query when filtering events. | +| `node.clients.hedera.operator.account_id` | "" | The operator's Hedera account id. | +| `node.clients.hedera.operator.private_key` | "" | The operator's Hedera private key. | +| `node.clients.hedera.network` | testnet | Which Hedera network to use. Can be either `mainnet`, `previewnet`, `testnet`. | +| `node.clients.hedera.start_timestamp` | 0 | The timestamp from which the Hedera Transfer and Hedera Message watchers will begin. If specified, the Hedera Transfers and Messages will begin listening in its primary mode (check `node.validator`) from the given timestamp. If not specified, the HT and Messages will run in read-only mode from the latest saved timestamp in the database to the moment the application has been run (`now`) and then continue in its primary mode. | +| `node.clients.hedera.rpc[]` | [] | A list of Hedera rpc node urls, in the format `{rpc_url}:{node_account_ID}` for the given network. If no list is provided, it will take the SDK's default node list for the given network. | +| `node.clients.mirror_node.api_address` | https://testnet.mirrornode.hedera.com/api/v1/ | The Hedera Rest API root endpoint. Depending on the Hedera network type, this will need to be changed. | +| `node.clients.mirror_node.client_address` | hcs.testnet.mirrornode.hedera.com:5600 | The HCS Mirror node endpoint. Depending on the Hedera network type, this will need to be changed. | +| `node.clients.mirror_node.polling_interval` | 5 | How often (in seconds) the application will poll the mirror node for new transactions. | +| `node.log_level` | info | The log level of the validator. Possible values: `info`, `debug`, `trace` case insensitive. | +| `node.port` | 5200 | The port on which the application runs. | +| `node.validator` | true | The primary mode in which the application will run. If set to `true`, the application will make write operations (HCS submission, Scheduled Transactions). If set to `false`, the application will be in a read-only mode, searching for transactions/messages from the other validators in the networks. | Configuration for `config/bridge.yml`: -Name | Default | Description --------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -`bridge.topic_id` | "" | The topic id, which the validators will use to monitor and submit consensus messages to. -`bridge.networks[i]` | "" | The id of the network. **`0` stands for Hedera**. Every other id must be the `chainId` of the EVM network. Used as a key for the following `bridge.networks[i].*` configuration fields below. -`bridge.networks[i].bridge_account` | "" | The account id validators use to monitor for incoming transfers. Applies only for network with id `0`. Also, serves as a distributor for Hedera transfers (validator fees and bridged amounts). -`bridge.networks[i].payer_account` | "" | The account id paying for Hedera transfers fees. Applies **only** for network with id `0`. -`bridge.networks[i].members` | [] | The Hedera account ids of the validators, to which their bridge fees will be sent. Applies **only** for network with id `0`. If the bridge accepts Hedera Native Tokens, each member will need to have an association with the given token. -`bridge.networks[i].router_contract_address` | "" | The address of the Router contract on the EVM network. Ignored for network with id `0`. -`bridge.networks[i].tokens[j]` | "" | The Address/HBAR/Token ID of the native asset for the given network. Used as a key to for the following `bridge.networks[i].tokens[j].*` configuration fields below. -`bridge.networks[i].tokens[j].min_amount` | "" | The minimum amount(in the lowest denomination) for the native fungible asset that is allowed to be transferred in both directions. Default is "", which is interpreted as 0. -`bridge.networks[i].tokens[j].fee_percentage` | "" | The percentage which validators take for every bridge transfer. Applies **only** for assets from network with id `0`. Range is from 0 to 100.000 (multiplied by 1 000). Examples: 1% is 1 000, 1.234% = 1234, 0.15% = 150. Default 10% = 10 000 -`bridge.networks[i].tokens[j].networks[k]` | "" | A key-value pair representing the id and wrapped asset to which the token `j` has a wrapped representation. Example: TokenID `0.0.2473688` (`j`) on Network `0` (`i`) has a wrapped version on `80001` (`k`), which is `0x95341E9cf3Bc3f69fEBfFC0E33E2B2EC14a6F969`. +| Name | Default | Description | +|-----------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bridge.topic_id` | "" | The topic id, which the validators will use to monitor and submit consensus messages to. | +| `bridge.networks[i]` | "" | The id of the network. **`0` stands for Hedera**. Every other id must be the `chainId` of the EVM network. Used as a key for the following `bridge.networks[i].*` configuration fields below. | +| `bridge.networks[i].bridge_account` | "" | The account id validators use to monitor for incoming transfers. Applies only for network with id `0`. Also, serves as a distributor for Hedera transfers (validator fees and bridged amounts). | +| `bridge.networks[i].payer_account` | "" | The account id paying for Hedera transfers fees. Applies **only** for network with id `0`. | +| `bridge.networks[i].members` | [] | The Hedera account ids of the validators, to which their bridge fees will be sent. Applies **only** for network with id `0`. If the bridge accepts Hedera Native Tokens, each member will need to have an association with the given token. | +| `bridge.networks[i].router_contract_address` | "" | The address of the Router contract on the EVM network. Ignored for network with id `0`. | +| `bridge.networks[i].tokens[j]` | "" | The Address/HBAR/Token ID of the native asset for the given network. Used as a key to for the following `bridge.networks[i].tokens[j].*` configuration fields below. | +| `bridge.networks[i].tokens[j].min_amount` | "" | The minimum amount(in the lowest denomination) for the native fungible asset that is allowed to be transferred in both directions. Default is "", which is interpreted as 0. | +| `bridge.networks[i].tokens[j].fee_percentage` | "" | The percentage which validators take for every bridge transfer. Applies **only** for assets from network with id `0`. Range is from 0 to 100.000 (multiplied by 1 000). Examples: 1% is 1 000, 1.234% = 1234, 0.15% = 150. Default 10% = 10 000 | +| `bridge.networks[i].tokens[j].networks[k]` | "" | A key-value pair representing the id and wrapped asset to which the token `j` has a wrapped representation. Example: TokenID `0.0.2473688` (`j`) on Network `0` (`i`) has a wrapped version on `80001` (`k`), which is `0x95341E9cf3Bc3f69fEBfFC0E33E2B2EC14a6F969`. | diff --git a/node.yml b/node.yml index 138bb108f..9bd4d78b6 100644 --- a/node.yml +++ b/node.yml @@ -18,7 +18,4 @@ # polling_interval: 5 # log_level: info # port: 5200 -# recovery: -# start_timestamp: -# start_block: # validator: true \ No newline at end of file