diff --git a/relayer/cmd/run/execution/command.go b/relayer/cmd/run/execution/command.go index e95b1dd95a..9bdc7a499e 100644 --- a/relayer/cmd/run/execution/command.go +++ b/relayer/cmd/run/execution/command.go @@ -2,11 +2,15 @@ package execution import ( "context" + "encoding/hex" "log" "os" "os/signal" + "reflect" + "strings" "syscall" + "github.com/mitchellh/mapstructure" "github.com/sirupsen/logrus" "github.com/snowfork/snowbridge/relayer/chain/parachain" "github.com/snowfork/snowbridge/relayer/relays/execution" @@ -50,7 +54,7 @@ func run(_ *cobra.Command, _ []string) error { } var config execution.Config - err := viper.Unmarshal(&config) + err := viper.Unmarshal(&config, viper.DecodeHook(HexHookFunc())) if err != nil { return err } @@ -101,3 +105,49 @@ func run(_ *cobra.Command, _ []string) error { return nil } + +func HexHookFunc() mapstructure.DecodeHookFuncType { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + // Check that the data is string + if f.Kind() != reflect.String { + return data, nil + } + + // Check that the target type is our custom type + if t != reflect.TypeOf(execution.ChannelID{}) { + return data, nil + } + + foo, err := HexDecodeString(data.(string)) + if err != nil { + return nil, err + } + + var out [32]byte + copy(out[:], foo) + + // Return the parsed value + return execution.ChannelID(out), nil + } +} + +// HexDecodeString decodes bytes from a hex string. Contrary to hex.DecodeString, this function does not error if "0x" +// is prefixed, and adds an extra 0 if the hex string has an odd length. +func HexDecodeString(s string) ([]byte, error) { + s = strings.TrimPrefix(s, "0x") + + if len(s)%2 != 0 { + s = "0" + s + } + + b, err := hex.DecodeString(s) + if err != nil { + return nil, err + } + + return b, nil +} diff --git a/relayer/cmd/run/parachain/command.go b/relayer/cmd/run/parachain/command.go index c4c6fa913f..6324845c64 100644 --- a/relayer/cmd/run/parachain/command.go +++ b/relayer/cmd/run/parachain/command.go @@ -2,11 +2,15 @@ package parachain import ( "context" + "encoding/hex" "log" "os" "os/signal" + "reflect" + "strings" "syscall" + "github.com/mitchellh/mapstructure" "github.com/sirupsen/logrus" "github.com/snowfork/snowbridge/relayer/chain/ethereum" "github.com/snowfork/snowbridge/relayer/relays/parachain" @@ -48,7 +52,7 @@ func run(_ *cobra.Command, _ []string) error { } var config parachain.Config - err := viper.Unmarshal(&config) + err := viper.Unmarshal(&config, viper.DecodeHook(HexHookFunc())) if err != nil { return err } @@ -97,3 +101,49 @@ func run(_ *cobra.Command, _ []string) error { return nil } + +func HexHookFunc() mapstructure.DecodeHookFuncType { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + // Check that the data is string + if f.Kind() != reflect.String { + return data, nil + } + + // Check that the target type is our custom type + if t != reflect.TypeOf(parachain.ChannelID{}) { + return data, nil + } + + foo, err := HexDecodeString(data.(string)) + if err != nil { + return nil, err + } + + var out [32]byte + copy(out[:], foo) + + // Return the parsed value + return parachain.ChannelID(out), nil + } +} + +// HexDecodeString decodes bytes from a hex string. Contrary to hex.DecodeString, this function does not error if "0x" +// is prefixed, and adds an extra 0 if the hex string has an odd length. +func HexDecodeString(s string) ([]byte, error) { + s = strings.TrimPrefix(s, "0x") + + if len(s)%2 != 0 { + s = "0" + s + } + + b, err := hex.DecodeString(s) + if err != nil { + return nil, err + } + + return b, nil +} diff --git a/relayer/relays/execution/config.go b/relayer/relays/execution/config.go index 3b1c602efb..f61e3f7c94 100644 --- a/relayer/relays/execution/config.go +++ b/relayer/relays/execution/config.go @@ -1,10 +1,6 @@ package execution import ( - "encoding/hex" - "errors" - "strings" - "github.com/snowfork/snowbridge/relayer/config" ) @@ -28,34 +24,3 @@ type SinkConfig struct { } type ChannelID [32]byte - -func (m *ChannelID) UnmarshalJSON(bz []byte) error { - data, err := HexDecodeString(string(bz)) - if err != nil { - return err - } - if len(data) != 32 { - return errors.New("Invalid Channel ID") - } - - copy(m[:], data) - - return nil -} - -// HexDecodeString decodes bytes from a hex string. Contrary to hex.DecodeString, this function does not error if "0x" -// is prefixed, and adds an extra 0 if the hex string has an odd length. -func HexDecodeString(s string) ([]byte, error) { - s = strings.TrimPrefix(s, "0x") - - if len(s)%2 != 0 { - s = "0" + s - } - - b, err := hex.DecodeString(s) - if err != nil { - return nil, err - } - - return b, nil -} diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index a1fc2bac60..0ea044879b 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -111,7 +111,7 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { log.WithFields(log.Fields{ "ethBlockNumber": executionHeaderState.BlockNumber, - "channelId": r.config.Source.ChannelID, + "channelId": types.H256(r.config.Source.ChannelID).Hex(), "paraNonce": paraNonce, "ethNonce": ethNonce, }).Info("Polled Nonces") diff --git a/relayer/relays/parachain/config.go b/relayer/relays/parachain/config.go index 9b3a6ef98c..e4eafb3887 100644 --- a/relayer/relays/parachain/config.go +++ b/relayer/relays/parachain/config.go @@ -1,10 +1,6 @@ package parachain import ( - "encoding/hex" - "errors" - "strings" - "github.com/snowfork/snowbridge/relayer/config" ) @@ -13,7 +9,6 @@ type Config struct { Sink SinkConfig `mapstructure:"sink"` } -// TODO: check whether ChannelID should be uint32 (as in the parachain) or big.Int (uint256, as in the Gateway contract) type SourceConfig struct { Polkadot config.PolkadotConfig `mapstructure:"polkadot"` Parachain config.ParachainConfig `mapstructure:"parachain"` @@ -37,34 +32,3 @@ type SinkContractsConfig struct { } type ChannelID [32]byte - -func (m *ChannelID) UnmarshalJSON(bz []byte) error { - data, err := HexDecodeString(string(bz)) - if err != nil { - return err - } - if len(data) != 32 { - return errors.New("Invalid Channel ID") - } - - copy(m[:], data) - - return nil -} - -// HexDecodeString decodes bytes from a hex string. Contrary to hex.DecodeString, this function does not error if "0x" -// is prefixed, and adds an extra 0 if the hex string has an odd length. -func HexDecodeString(s string) ([]byte, error) { - s = strings.TrimPrefix(s, "0x") - - if len(s)%2 != 0 { - s = "0" + s - } - - b, err := hex.DecodeString(s) - if err != nil { - return nil, err - } - - return b, nil -} diff --git a/web/packages/test/config/execution-relay.json b/web/packages/test/config/execution-relay.json index 3422e5cee0..91ffe603de 100644 --- a/web/packages/test/config/execution-relay.json +++ b/web/packages/test/config/execution-relay.json @@ -6,7 +6,7 @@ "contracts": { "Gateway": null }, - "channel-id": 1000 + "channel-id": null }, "sink": { "parachain": { diff --git a/web/packages/test/config/parachain-relay.json b/web/packages/test/config/parachain-relay.json index 2da5c5be37..8348c60db2 100644 --- a/web/packages/test/config/parachain-relay.json +++ b/web/packages/test/config/parachain-relay.json @@ -14,7 +14,7 @@ "Gateway": null }, "beefy-activation-block": 0, - "channel-id": 0 + "channel-id": null }, "sink": { "ethereum": { diff --git a/web/packages/test/scripts/set-env.sh b/web/packages/test/scripts/set-env.sh index c19d5846d6..b6c80bfe35 100755 --- a/web/packages/test/scripts/set-env.sh +++ b/web/packages/test/scripts/set-env.sh @@ -45,6 +45,11 @@ export ASSET_HUB_AGENT_ID="${ASSET_HUB_AGENT_ID:-0x72456f48efed08af20e5b317abf86 export TEMPLATE_PARA_ID="${TEMPLATE_PARA_ID:-1001}" export TEMPLATE_AGENT_ID="${TEMPLATE_AGENT_ID:-0x2075b9f5bc236462eb1473c9a6236c3588e33ed19ead53aa3d9c62ed941cb793}" +export ASSET_HUB_CHANNEL_ID="0xc173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539" +export TEMPLATE_CHANNEL_ID="0x26c13363ad6499b895574b3ca482545dda41d657ffc5673b39a218cd34053e5b" +export PRIMARY_GOVERNANCE_CHANNEL_ID="0x0000000000000000000000000000000000000000000000000000000000000001" +export SECONDARY_GOVERNANCE_CHANNEL_ID="0x0000000000000000000000000000000000000000000000000000000000000002" + relaychain_ws_url="${RELAYCHAIN_WS_URL:-ws://127.0.0.1:9944}" relaychain_sudo_seed="${RELAYCHAIN_SUDO_SEED:-//Alice}" diff --git a/web/packages/test/scripts/start-relayer.sh b/web/packages/test/scripts/start-relayer.sh index b937c4ff9a..23c27fcfe0 100755 --- a/web/packages/test/scripts/start-relayer.sh +++ b/web/packages/test/scripts/start-relayer.sh @@ -17,12 +17,12 @@ config_relayer() { ' \ config/beefy-relay.json >$output_dir/beefy-relay.json - # Configure parachain relay (bridge hub) + # Configure parachain relay (primary governance) jq \ --arg k1 "$(address_for GatewayProxy)" \ --arg k2 "$(address_for BeefyClient)" \ --arg eth_endpoint_ws $eth_endpoint_ws \ - --arg channelID $BRIDGE_HUB_PARAID \ + --arg channelID $PRIMARY_GOVERNANCE_CHANNEL_ID \ --arg eth_gas_limit $eth_gas_limit \ ' .source.contracts.Gateway = $k1 @@ -33,14 +33,32 @@ config_relayer() { | .sink.ethereum."gas-limit" = $eth_gas_limit | .source."channel-id" = $channelID ' \ - config/parachain-relay.json >$output_dir/parachain-relay-bridge-hub.json + config/parachain-relay.json >$output_dir/parachain-relay-bridge-hub-01.json + + # Configure parachain relay (secondary governance) + jq \ + --arg k1 "$(address_for GatewayProxy)" \ + --arg k2 "$(address_for BeefyClient)" \ + --arg eth_endpoint_ws $eth_endpoint_ws \ + --arg channelID $SECONDARY_GOVERNANCE_CHANNEL_ID \ + --arg eth_gas_limit $eth_gas_limit \ + ' + .source.contracts.Gateway = $k1 + | .source.contracts.BeefyClient = $k2 + | .sink.contracts.Gateway = $k1 + | .source.ethereum.endpoint = $eth_endpoint_ws + | .sink.ethereum.endpoint = $eth_endpoint_ws + | .sink.ethereum."gas-limit" = $eth_gas_limit + | .source."channel-id" = $channelID + ' \ + config/parachain-relay.json >$output_dir/parachain-relay-bridge-hub-02.json # Configure parachain relay (asset hub) jq \ --arg k1 "$(address_for GatewayProxy)" \ --arg k2 "$(address_for BeefyClient)" \ --arg eth_endpoint_ws $eth_endpoint_ws \ - --arg channelID $ASSET_HUB_PARAID \ + --arg channelID $ASSET_HUB_CHANNEL_ID \ --arg eth_gas_limit $eth_gas_limit \ ' .source.contracts.Gateway = $k1 @@ -58,7 +76,7 @@ config_relayer() { --arg k1 "$(address_for GatewayProxy)" \ --arg k2 "$(address_for BeefyClient)" \ --arg eth_endpoint_ws $eth_endpoint_ws \ - --arg channelID $TEMPLATE_PARA_ID \ + --arg channelID $TEMPLATE_CHANNEL_ID \ --arg eth_gas_limit $eth_gas_limit \ ' .source.contracts.Gateway = $k1 @@ -85,7 +103,7 @@ config_relayer() { jq \ --arg eth_endpoint_ws $eth_endpoint_ws \ --arg k1 "$(address_for GatewayProxy)" \ - --arg channelID $ASSET_HUB_PARAID \ + --arg channelID $ASSET_HUB_CHANNEL_ID \ ' .source.ethereum.endpoint = $eth_endpoint_ws | .source.contracts.Gateway = $k1 @@ -97,7 +115,7 @@ config_relayer() { jq \ --arg eth_endpoint_ws $eth_endpoint_ws \ --arg k1 "$(address_for GatewayProxy)" \ - --arg channelID $TEMPLATE_PARA_ID \ + --arg channelID $TEMPLATE_CHANNEL_ID \ ' .source.ethereum.endpoint = $eth_endpoint_ws | .source.contracts.Gateway = $k1 @@ -121,15 +139,28 @@ start_relayer() { done ) & - # Launch parachain relay for bridgehub + # Launch parachain relay for bridgehub (primary governance) + ( + : >"$output_dir"/parachain-relay-bridge-hub-01.log + while :; do + echo "Starting parachain-relay (primary governance) at $(date)" + "${relay_bin}" run parachain \ + --config "$output_dir/parachain-relay-bridge-hub-01.json" \ + --ethereum.private-key $parachain_relay_eth_key \ + >>"$output_dir"/parachain-relay-bridge-hub-01.log 2>&1 || true + sleep 20 + done + ) & + + # Launch parachain relay for bridgehub (secondary governance) ( - : >"$output_dir"/parachain-relay-bridge-hub.log + : >"$output_dir"/parachain-relay-bridge-hub-02.log while :; do - echo "Starting parachain-relay (bridgehub) at $(date)" + echo "Starting parachain-relay (secondary governance) at $(date)" "${relay_bin}" run parachain \ - --config "$output_dir/parachain-relay-bridge-hub.json" \ + --config "$output_dir/parachain-relay-bridge-hub-02.json" \ --ethereum.private-key $parachain_relay_eth_key \ - >>"$output_dir"/parachain-relay-bridge-hub.log 2>&1 || true + >>"$output_dir"/parachain-relay-bridge-hub-02.log 2>&1 || true sleep 20 done ) & @@ -181,7 +212,7 @@ start_relayer() { "${relay_bin}" run execution \ --config $output_dir/execution-relay-asset-hub.json \ --substrate.private-key "//ExecutionRelay" \ - >>"$output_dir"/execution-relay.log 2>&1 || true + >>"$output_dir"/execution-relay-asset-hub.log 2>&1 || true sleep 20 done ) &