Skip to content

Commit

Permalink
node/cmd/guardiand: governance template improvements
Browse files Browse the repository at this point in the history
The template commands now support generating full governance messages
with all required fields. Outputs to stdout instead of a file.

Change-Id: I3837107c3075363a54d31f9dfb4d6dc07c79daa5
  • Loading branch information
Leo committed Oct 29, 2021
1 parent 964566c commit d5f6540
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 42 deletions.
157 changes: 115 additions & 42 deletions node/cmd/guardiand/admintemplate.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package guardiand

import (
"encoding/hex"
"fmt"
"github.com/btcsuite/btcutil/bech32"
"github.com/certusone/wormhole/node/pkg/vaa"
"github.com/ethereum/go-ethereum/common"
"github.com/mr-tron/base58"
"github.com/spf13/pflag"
"github.com/tendermint/tendermint/libs/rand"
"io/ioutil"
"log"
"strconv"
"strings"

"github.com/ethereum/go-ethereum/crypto"
"github.com/spf13/cobra"
Expand All @@ -16,14 +23,31 @@ import (

var setUpdateNumGuardians *int
var templateGuardianIndex *int
var chainID *string
var address *string
var module *string

func init() {
governanceFlagSet := pflag.NewFlagSet("governance", pflag.ExitOnError)
chainID = governanceFlagSet.String("chain-id", "", "Chain ID")
address = governanceFlagSet.String("new-address", "", "New address (hex, base58 or bech32)")

moduleFlagSet := pflag.NewFlagSet("module", pflag.ExitOnError)
module = moduleFlagSet.String("module", "", "Module name")

templateGuardianIndex = TemplateCmd.PersistentFlags().Int("idx", 0, "Default current guardian set index")

setUpdateNumGuardians = AdminClientGuardianSetTemplateCmd.Flags().Int("num", 1, "Number of devnet guardians in example file")

TemplateCmd.AddCommand(AdminClientGuardianSetTemplateCmd)
AdminClientContractUpgradeTemplateCmd.Flags().AddFlagSet(governanceFlagSet)
TemplateCmd.AddCommand(AdminClientContractUpgradeTemplateCmd)

AdminClientTokenBridgeRegisterChainCmd.Flags().AddFlagSet(governanceFlagSet)
AdminClientTokenBridgeRegisterChainCmd.Flags().AddFlagSet(moduleFlagSet)
TemplateCmd.AddCommand(AdminClientTokenBridgeRegisterChainCmd)

AdminClientTokenBridgeUpgradeContractCmd.Flags().AddFlagSet(governanceFlagSet)
AdminClientTokenBridgeUpgradeContractCmd.Flags().AddFlagSet(moduleFlagSet)
TemplateCmd.AddCommand(AdminClientTokenBridgeUpgradeContractCmd)
}

Expand All @@ -33,36 +57,30 @@ var TemplateCmd = &cobra.Command{
}

var AdminClientGuardianSetTemplateCmd = &cobra.Command{
Use: "guardian-set-update [FILENAME]",
Short: "Generate an empty guardian set template at specified path (offline)",
Use: "guardian-set-update",
Short: "Generate an empty guardian set template",
Run: runGuardianSetTemplate,
Args: cobra.ExactArgs(1),
}

var AdminClientContractUpgradeTemplateCmd = &cobra.Command{
Use: "contract-upgrade [FILENAME]",
Short: "Generate an empty contract upgrade template at specified path (offline)",
Use: "contract-upgrade",
Short: "Generate an empty contract upgrade template",
Run: runContractUpgradeTemplate,
Args: cobra.ExactArgs(1),
}

var AdminClientTokenBridgeRegisterChainCmd = &cobra.Command{
Use: "token-bridge-register-chain [FILENAME]",
Short: "Generate an empty token bridge chain registration template at specified path (offline)",
Use: "token-bridge-register-chain",
Short: "Generate an empty token bridge chain registration template at specified path",
Run: runTokenBridgeRegisterChainTemplate,
Args: cobra.ExactArgs(1),
}

var AdminClientTokenBridgeUpgradeContractCmd = &cobra.Command{
Use: "token-bridge-upgrade-contract [FILENAME]",
Short: "Generate an empty token bridge contract upgrade template at specified path (offline)",
Use: "token-bridge-upgrade-contract",
Short: "Generate an empty token bridge contract upgrade template at specified path",
Run: runTokenBridgeUpgradeContractTemplate,
Args: cobra.ExactArgs(1),
}

func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
path := args[0]

// Use deterministic devnet addresses as examples in the template, such that this doubles as a test fixture.
guardians := make([]*nodev1.GuardianSetUpdate_Guardian, *setUpdateNumGuardians)
for i := 0; i < *setUpdateNumGuardians; i++ {
Expand All @@ -75,7 +93,7 @@ func runGuardianSetTemplate(cmd *cobra.Command, args []string) {

m := &nodev1.InjectGovernanceVAARequest{
CurrentSetIndex: uint32(*templateGuardianIndex),
Sequence: 1234,
Sequence: rand.Uint64(),
Nonce: rand.Uint32(),
Payload: &nodev1.InjectGovernanceVAARequest_GuardianSet{
GuardianSet: &nodev1.GuardianSetUpdate{Guardians: guardians},
Expand All @@ -86,24 +104,27 @@ func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
if err != nil {
panic(err)
}
fmt.Print(string(b))
}

err = ioutil.WriteFile(path, b, 0640)
func runContractUpgradeTemplate(cmd *cobra.Command, args []string) {
address, err := parseAddress(*address)
if err != nil {
log.Fatal(err)
}
chainID, err := parseChainID(*chainID)
if err != nil {
log.Fatal(err)
}
}

func runContractUpgradeTemplate(cmd *cobra.Command, args []string) {
path := args[0]

m := &nodev1.InjectGovernanceVAARequest{
CurrentSetIndex: uint32(*templateGuardianIndex),
Sequence: rand.Uint64(),
Nonce: rand.Uint32(),
Payload: &nodev1.InjectGovernanceVAARequest_ContractUpgrade{
ContractUpgrade: &nodev1.ContractUpgrade{
ChainId: 1,
NewContract: "0000000000000000000000000290FB167208Af455bB137780163b7B7a9a10C16",
ChainId: uint32(chainID),
NewContract: address,
},
},
}
Expand All @@ -112,24 +133,27 @@ func runContractUpgradeTemplate(cmd *cobra.Command, args []string) {
if err != nil {
panic(err)
}

err = ioutil.WriteFile(path, b, 0640)
fmt.Print(string(b))
}
func runTokenBridgeRegisterChainTemplate(cmd *cobra.Command, args []string) {
address, err := parseAddress(*address)
if err != nil {
log.Fatal(err)
}
chainID, err := parseChainID(*chainID)
if err != nil {
log.Fatal(err)
}
}
func runTokenBridgeRegisterChainTemplate(cmd *cobra.Command, args []string) {
path := args[0]

m := &nodev1.InjectGovernanceVAARequest{
CurrentSetIndex: uint32(*templateGuardianIndex),
Sequence: rand.Uint64(),
Nonce: rand.Uint32(),
Payload: &nodev1.InjectGovernanceVAARequest_BridgeRegisterChain{
BridgeRegisterChain: &nodev1.BridgeRegisterChain{
Module: "TokenBridge",
ChainId: 5,
EmitterAddress: "0000000000000000000000000290FB167208Af455bB137780163b7B7a9a10C16",
Module: *module,
ChainId: uint32(chainID),
EmitterAddress: address,
},
},
}
Expand All @@ -138,25 +162,28 @@ func runTokenBridgeRegisterChainTemplate(cmd *cobra.Command, args []string) {
if err != nil {
panic(err)
}
fmt.Print(string(b))
}

err = ioutil.WriteFile(path, b, 0640)
func runTokenBridgeUpgradeContractTemplate(cmd *cobra.Command, args []string) {
address, err := parseAddress(*address)
if err != nil {
log.Fatal(err)
}
chainID, err := parseChainID(*chainID)
if err != nil {
log.Fatal(err)
}
}

func runTokenBridgeUpgradeContractTemplate(cmd *cobra.Command, args []string) {
path := args[0]

m := &nodev1.InjectGovernanceVAARequest{
CurrentSetIndex: uint32(*templateGuardianIndex),
Sequence: rand.Uint64(),
Nonce: rand.Uint32(),
Payload: &nodev1.InjectGovernanceVAARequest_BridgeContractUpgrade{
BridgeContractUpgrade: &nodev1.BridgeUpgradeContract{
Module: "TokenBridge",
TargetChainId: 5,
NewContract: "0000000000000000000000000290FB167208Af455bB137780163b7B7a9a10C16",
Module: *module,
TargetChainId: uint32(chainID),
NewContract: address,
},
},
}
Expand All @@ -165,9 +192,55 @@ func runTokenBridgeUpgradeContractTemplate(cmd *cobra.Command, args []string) {
if err != nil {
panic(err)
}
fmt.Print(string(b))
}

// parseAddress parses either a hex-encoded address and returns
// a left-padded 32 byte hex string.
func parseAddress(s string) (string, error) {
// try base58
b, err := base58.Decode(s)
if err == nil {
return leftPadAddress(b)
}

// try bech32
_, b, err = bech32.Decode(s)
if err == nil {
return leftPadAddress(b)
}

// try hex
if len(s) > 2 && strings.ToLower(s[:2]) == "0x" {
s = s[2:]
}

err = ioutil.WriteFile(path, b, 0640)
a, err := hex.DecodeString(s)
if err != nil {
log.Fatal(err)
return "", fmt.Errorf("invalid hex address: %v", err)
}
return leftPadAddress(a)
}

func leftPadAddress(a []byte) (string, error) {
if len(a) > 32 {
return "", fmt.Errorf("address longer than 32 bytes")
}
return hex.EncodeToString(common.LeftPadBytes(a, 32)), nil
}

// parseChainID parses a human-readable chain name or a chain ID.
func parseChainID(name string) (vaa.ChainID, error) {
s, err := vaa.ChainIDFromString(name)
if err == nil {
return s, nil
}

// parse as uint32
i, err := strconv.ParseUint(name, 10, 32)
if err != nil {
return 0, fmt.Errorf("failed to parse as name or uint32: %v", err)
}

return vaa.ChainID(i), nil
}
20 changes: 20 additions & 0 deletions node/pkg/vaa/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/hex"
"fmt"
"io"
"strings"
"time"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -98,6 +99,25 @@ func (c ChainID) String() string {
}
}

func ChainIDFromString(s string) (ChainID, error) {
s = strings.ToLower(s)

switch s {
case "solana":
return ChainIDSolana, nil
case "ethereum":
return ChainIDEthereum, nil
case "terra":
return ChainIDTerra, nil
case "bsc":
return ChainIDBSC, nil
case "polygon":
return ChainIDPolygon, nil
default:
return ChainIDUnset, fmt.Errorf("unknown chain ID: %s", s)
}
}

const (
ChainIDUnset ChainID = 0
// ChainIDSolana is the ChainID of Solana
Expand Down

0 comments on commit d5f6540

Please sign in to comment.