diff --git a/cmd/zetae2e/local/get_zetaclient_bootstrap.go b/cmd/zetae2e/local/get_zetaclient_bootstrap.go new file mode 100644 index 0000000000..16cbdcf10c --- /dev/null +++ b/cmd/zetae2e/local/get_zetaclient_bootstrap.go @@ -0,0 +1,104 @@ +package local + +import ( + "fmt" + "net" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/spf13/cobra" + "gitlab.com/thorchain/tss/go-tss/conversion" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + "github.com/zeta-chain/node/pkg/rpc" + "github.com/zeta-chain/node/pkg/sdkconfig" + observertypes "github.com/zeta-chain/node/x/observer/types" +) + +const grpcURLFlag = "grpc-url" + +func NewGetZetaclientBootstrap() *cobra.Command { + var cmd = &cobra.Command{ + Use: "get-zetaclient-bootstrap", + Short: "get bootstrap address book entries for zetaclient", + RunE: getZetaclientBootstrap, + } + + cmd.Flags(). + String(grpcURLFlag, "zetacore0:9090", "--grpc-url zetacore0:9090") + + return cmd +} + +func getZetaclientBootstrap(cmd *cobra.Command, _ []string) error { + sdkconfig.SetDefault(true) + grpcURL, _ := cmd.Flags().GetString(grpcURLFlag) + rpcClient, err := rpc.NewGRPCClients( + grpcURL, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithBlock(), + ) + if err != nil { + return fmt.Errorf("get zetacore rpc client: %w", err) + } + var res *observertypes.QueryAllNodeAccountResponse + for { + res, err = rpcClient.Observer.NodeAccountAll(cmd.Context(), &observertypes.QueryAllNodeAccountRequest{}) + if err != nil { + return fmt.Errorf("get all node accounts: %w", err) + } + if len(res.NodeAccount) > 1 { + break + } + fmt.Fprintln(cmd.OutOrStderr(), "waiting for node accounts") + } + + // note that we deliberately do not filter ourselfs/localhost + // to mirror the production configuration + for _, account := range res.NodeAccount { + accAddr, err := sdk.AccAddressFromBech32(account.Operator) + if err != nil { + return err + } + valAddr := sdk.ValAddress(accAddr).String() + validatorRes, err := rpcClient.Staking.Validator(cmd.Context(), &stakingtypes.QueryValidatorRequest{ + ValidatorAddr: valAddr, + }) + if err != nil { + return fmt.Errorf("getting validator info for %s: %w", account.Operator, err) + } + // in localnet, moniker is also the hostname + moniker := validatorRes.Validator.Description.Moniker + + peerID, err := conversion.Bech32PubkeyToPeerID(account.GranteePubkey.Secp256k1.String()) + if err != nil { + return fmt.Errorf("converting pubkey to peerID: %w", err) + } + zetaclientHostname := strings.ReplaceAll(moniker, "zetacore", "zetaclient") + + // resolve the hostname + // something in libp2p/go-tss requires /ip4/ and doesn't tolerate /dns4/ + ipAddresses, err := net.LookupIP(zetaclientHostname) + if err != nil { + return fmt.Errorf("failed to resolve hostname %s: %w", zetaclientHostname, err) + } + if len(ipAddresses) == 0 { + return fmt.Errorf("no IP addresses found for hostname %s", zetaclientHostname) + } + ipv4Address := "" + for _, ip := range ipAddresses { + if ip.To4() != nil { + ipv4Address = ip.String() + break + } + } + if ipv4Address == "" { + return fmt.Errorf("no IPv4 address found for hostname %s", zetaclientHostname) + } + fmt.Printf("/ip4/%s/tcp/6668/p2p/%s\n", ipv4Address, peerID.String()) + } + + return nil +} diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index 0ebb6244f9..e625b4174a 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -83,6 +83,8 @@ func NewLocalCmd() *cobra.Command { cmd.Flags(). Bool(flagUpgradeContracts, false, "set to true to upgrade Gateways and ERC20Custody contracts during setup for ZEVM and EVM") + cmd.AddCommand(NewGetZetaclientBootstrap()) + return cmd } diff --git a/contrib/localnet/scripts/start-zetaclientd.sh b/contrib/localnet/scripts/start-zetaclientd.sh index 93fa5c2af6..c994f1d2df 100755 --- a/contrib/localnet/scripts/start-zetaclientd.sh +++ b/contrib/localnet/scripts/start-zetaclientd.sh @@ -68,11 +68,15 @@ echo "operatorAddress: $operatorAddress" RELAYER_KEY_PATH="$HOME/.zetacored/relayer-keys" mkdir -p "${RELAYER_KEY_PATH}" +mkdir -p "$HOME/.tss/" +zetae2e local get-zetaclient-bootstrap > "$HOME/.tss/address_book.seed" + +MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) + echo "Start zetaclientd" # skip initialization if the config file already exists (zetaclientd init has already been run) if [[ $HOSTNAME == "zetaclient0" && ! -f ~/.zetacored/config/zetaclient_config.json ]] then - MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) zetaclientd init --zetacore-url zetacore0 --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --keyring-backend "$BACKEND" --pre-params "$PREPARAMS_PATH" # import relayer private key for zetaclient0 @@ -90,13 +94,7 @@ if [[ $HOSTNAME != "zetaclient0" && ! -f ~/.zetacored/config/zetaclient_config.j then num=$(echo $HOSTNAME | tr -dc '0-9') node="zetacore$num" - MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) - SEED="" - while [ -z "$SEED" ] - do - SEED=$(curl --retry 30 --retry-delay 1 --max-time 1 --retry-connrefused -s zetaclient0:8123/p2p) - done - zetaclientd init --peer "/ip4/172.20.0.21/tcp/6668/p2p/${SEED}" --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 1 --keyring-backend "$BACKEND" --pre-params "$PREPARAMS_PATH" + zetaclientd init --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 1 --keyring-backend "$BACKEND" --pre-params "$PREPARAMS_PATH" # import relayer private key for zetaclient{$num} import_relayer_key "${num}"