Skip to content

Commit

Permalink
node: Added RecoverChainId governance support
Browse files Browse the repository at this point in the history
  • Loading branch information
kev1n-peters authored and evan-gray committed Feb 6, 2024
1 parent cfe1ec4 commit c7a7d1a
Show file tree
Hide file tree
Showing 6 changed files with 958 additions and 681 deletions.
77 changes: 77 additions & 0 deletions node/cmd/guardiand/admintemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/hex"
"fmt"
"log"
"math/big"
"strconv"
"strings"

Expand Down Expand Up @@ -56,6 +57,9 @@ var ibcUpdateChannelChainTargetChainId *string
var ibcUpdateChannelChainChannelId *string
var ibcUpdateChannelChainChainId *string

var recoverChainIdEvmChainId *string
var recoverChainIdNewChainId *string

func init() {
governanceFlagSet := pflag.NewFlagSet("governance", pflag.ExitOnError)
chainID = governanceFlagSet.String("chain-id", "", "Chain ID")
Expand Down Expand Up @@ -159,6 +163,14 @@ func init() {
AdminClientIbcTranslatorUpdateChannelChainCmd.Flags().AddFlagSet(ibcUpdateChannelChainFlagSet)
TemplateCmd.AddCommand(AdminClientIbcReceiverUpdateChannelChainCmd)
TemplateCmd.AddCommand(AdminClientIbcTranslatorUpdateChannelChainCmd)

// flags for the recover-chain-id command
recoverChainIdFlagSet := pflag.NewFlagSet("recover-chain-id", pflag.ExitOnError)
recoverChainIdEvmChainId = recoverChainIdFlagSet.String("evm-chain-id", "", "EVM Chain ID to recover")
recoverChainIdNewChainId = recoverChainIdFlagSet.String("new-chain-id", "", "New Chain ID to recover to")
AdminClientRecoverChainIdCmd.Flags().AddFlagSet(recoverChainIdFlagSet)
AdminClientRecoverChainIdCmd.Flags().AddFlagSet(moduleFlagSet)
TemplateCmd.AddCommand(AdminClientRecoverChainIdCmd)
}

var TemplateCmd = &cobra.Command{
Expand Down Expand Up @@ -190,6 +202,12 @@ var AdminClientTokenBridgeUpgradeContractCmd = &cobra.Command{
Run: runTokenBridgeUpgradeContractTemplate,
}

var AdminClientRecoverChainIdCmd = &cobra.Command{
Use: "recover-chain-id",
Short: "Generate an empty recover chain id template at specified path",
Run: runRecoverChainIdTemplate,
}

var AdminClientCircleIntegrationUpdateWormholeFinalityCmd = &cobra.Command{
Use: "circle-integration-update-wormhole-finality",
Short: "Generate an empty circle integration update wormhole finality template at specified path",
Expand Down Expand Up @@ -405,6 +423,48 @@ func runTokenBridgeUpgradeContractTemplate(cmd *cobra.Command, args []string) {
fmt.Print(string(b))
}

func runRecoverChainIdTemplate(cmd *cobra.Command, args []string) {
if *module == "" {
log.Fatal("--module must be specified.")
}
if *recoverChainIdEvmChainId == "" {
log.Fatal("--evm-chain-id must be specified.")
}
if _, err := isValidUint256(*recoverChainIdEvmChainId); err != nil {
log.Fatal("failed to parse evm chain id as uint256:", err)
}
if *recoverChainIdNewChainId == "" {
log.Fatal("--new-chain-id must be specified.")
}
newChainID, err := parseChainID(*recoverChainIdNewChainId)
if err != nil {
log.Fatal("failed to parse chain id:", err)
}

m := &nodev1.InjectGovernanceVAARequest{
CurrentSetIndex: uint32(*templateGuardianIndex),
Messages: []*nodev1.GovernanceMessage{
{
Sequence: rand.Uint64(),
Nonce: rand.Uint32(),
Payload: &nodev1.GovernanceMessage_RecoverChainId{
RecoverChainId: &nodev1.RecoverChainId{
Module: *module,
EvmChainId: *recoverChainIdEvmChainId,
NewChainId: uint32(newChainID),
},
},
},
},
}

b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
if err != nil {
panic(err)
}
fmt.Print(string(b))
}

func runCircleIntegrationUpdateWormholeFinalityTemplate(cmd *cobra.Command, args []string) {
if *circleIntegrationChainID == "" {
log.Fatal("--chain-id must be specified.")
Expand Down Expand Up @@ -921,3 +981,20 @@ func parseChainID(name string) (vaa.ChainID, error) {

return vaa.ChainID(i), nil
}

func isValidUint256(s string) (bool, error) {
i := new(big.Int)
i.SetString(s, 10) // Parse in base 10

// Create upper limit as 2^256 - 1
upperLimit := new(big.Int)
upperLimit.Exp(big.NewInt(2), big.NewInt(256), nil)
upperLimit.Sub(upperLimit, big.NewInt(1))

// Check if i is within the range [0, 2^256 - 1]
if i.Cmp(big.NewInt(0)) < 0 || i.Cmp(upperLimit) > 0 {
return false, fmt.Errorf("value is not a valid uint256")
}

return true, nil
}
31 changes: 31 additions & 0 deletions node/pkg/adminrpc/adminserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,35 @@ func tokenBridgeRegisterChain(req *nodev1.BridgeRegisterChain, timestamp time.Ti
return v, nil
}

// recoverChainId converts a nodev1.RecoverChainId message to its canonical VAA representation.
// Returns an error if the data is invalid.
func recoverChainId(req *nodev1.RecoverChainId, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
evm_chain_id_big := big.NewInt(0)
evm_chain_id_big, ok := evm_chain_id_big.SetString(req.EvmChainId, 10)
if !ok {
return nil, errors.New("invalid evm_chain_id")
}

// uint256 has Bytes32 method for easier serialization
evm_chain_id, overflow := uint256.FromBig(evm_chain_id_big)
if overflow {
return nil, errors.New("evm_chain_id overflow")
}

if req.NewChainId > math.MaxUint16 {
return nil, errors.New("invalid new_chain_id")
}

v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
vaa.BodyRecoverChainId{
Module: req.Module,
EvmChainID: evm_chain_id,
NewChainID: vaa.ChainID(req.NewChainId),
}.Serialize())

return v, nil
}

// accountantModifyBalance converts a nodev1.AccountantModifyBalance message to its canonical VAA representation.
// Returns an error if the data is invalid.
func accountantModifyBalance(req *nodev1.AccountantModifyBalance, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
Expand Down Expand Up @@ -563,6 +592,8 @@ func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, time
v, err = tokenBridgeRegisterChain(payload.BridgeRegisterChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
case *nodev1.GovernanceMessage_BridgeContractUpgrade:
v, err = tokenBridgeUpgradeContract(payload.BridgeContractUpgrade, timestamp, currentSetIndex, message.Nonce, message.Sequence)
case *nodev1.GovernanceMessage_RecoverChainId:
v, err = recoverChainId(payload.RecoverChainId, timestamp, currentSetIndex, message.Nonce, message.Sequence)
case *nodev1.GovernanceMessage_AccountantModifyBalance:
v, err = accountantModifyBalance(payload.AccountantModifyBalance, timestamp, currentSetIndex, message.Nonce, message.Sequence)
case *nodev1.GovernanceMessage_WormchainStoreCode:
Expand Down
Loading

0 comments on commit c7a7d1a

Please sign in to comment.