| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769 |
- package guardiand
- import (
- "bufio"
- "context"
- "encoding/csv"
- "encoding/hex"
- "errors"
- "fmt"
- "io"
- "log"
- "os"
- "strconv"
- "strings"
- "time"
- "github.com/cosmos/cosmos-sdk/types"
- "github.com/davecgh/go-spew/spew"
- ethcommon "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/mr-tron/base58"
- "github.com/spf13/pflag"
- "golang.org/x/crypto/sha3"
- "github.com/certusone/wormhole/node/pkg/common"
- gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
- publicrpcv1 "github.com/certusone/wormhole/node/pkg/proto/publicrpc/v1"
- "github.com/wormhole-foundation/wormhole/sdk"
- "github.com/wormhole-foundation/wormhole/sdk/vaa"
- "github.com/spf13/cobra"
- "github.com/status-im/keycard-go/hexutils"
- "google.golang.org/grpc"
- "google.golang.org/grpc/credentials/insecure"
- "google.golang.org/protobuf/encoding/prototext"
- nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
- )
- var (
- clientSocketPath *string
- shouldBackfill *bool
- unsafeDevnetMode *bool
- )
- func init() {
- // Shared flags for all admin commands
- pf := pflag.NewFlagSet("commonAdminFlags", pflag.ContinueOnError)
- clientSocketPath = pf.String("socket", "", "gRPC admin server socket to connect to")
- err := cobra.MarkFlagRequired(pf, "socket")
- if err != nil {
- panic(err)
- }
- shouldBackfill = AdminClientFindMissingMessagesCmd.Flags().Bool(
- "backfill", false, "backfill missing VAAs from public RPC")
- AdminClientInjectGuardianSetUpdateCmd.Flags().AddFlagSet(pf)
- AdminClientFindMissingMessagesCmd.Flags().AddFlagSet(pf)
- AdminClientListNodes.Flags().AddFlagSet(pf)
- DumpVAAByMessageID.Flags().AddFlagSet(pf)
- DumpRPCs.Flags().AddFlagSet(pf)
- SendObservationRequest.Flags().AddFlagSet(pf)
- ClientChainGovernorStatusCmd.Flags().AddFlagSet(pf)
- ClientChainGovernorReloadCmd.Flags().AddFlagSet(pf)
- ClientChainGovernorDropPendingVAACmd.Flags().AddFlagSet(pf)
- ClientChainGovernorReleasePendingVAACmd.Flags().AddFlagSet(pf)
- ClientChainGovernorResetReleaseTimerCmd.Flags().AddFlagSet(pf)
- PurgePythNetVaasCmd.Flags().AddFlagSet(pf)
- SignExistingVaaCmd.Flags().AddFlagSet(pf)
- SignExistingVaasFromCSVCmd.Flags().AddFlagSet(pf)
- GetAndObserveMissingVAAs.Flags().AddFlagSet(pf)
- adminClientSignWormchainAddressFlags := pflag.NewFlagSet("adminClientSignWormchainAddressFlags", pflag.ContinueOnError)
- unsafeDevnetMode = adminClientSignWormchainAddressFlags.Bool("unsafeDevMode", false, "Run in unsafe devnet mode")
- AdminClientSignWormchainAddress.Flags().AddFlagSet(adminClientSignWormchainAddressFlags)
- AdminCmd.AddCommand(AdminClientInjectGuardianSetUpdateCmd)
- AdminCmd.AddCommand(AdminClientFindMissingMessagesCmd)
- AdminCmd.AddCommand(AdminClientGovernanceVAAVerifyCmd)
- AdminCmd.AddCommand(AdminClientListNodes)
- AdminCmd.AddCommand(AdminClientSignWormchainAddress)
- AdminCmd.AddCommand(DumpVAAByMessageID)
- AdminCmd.AddCommand(DumpRPCs)
- AdminCmd.AddCommand(SendObservationRequest)
- AdminCmd.AddCommand(ClientChainGovernorStatusCmd)
- AdminCmd.AddCommand(ClientChainGovernorReloadCmd)
- AdminCmd.AddCommand(ClientChainGovernorDropPendingVAACmd)
- AdminCmd.AddCommand(ClientChainGovernorReleasePendingVAACmd)
- AdminCmd.AddCommand(ClientChainGovernorResetReleaseTimerCmd)
- AdminCmd.AddCommand(PurgePythNetVaasCmd)
- AdminCmd.AddCommand(SignExistingVaaCmd)
- AdminCmd.AddCommand(SignExistingVaasFromCSVCmd)
- AdminCmd.AddCommand(Keccak256Hash)
- AdminCmd.AddCommand(GetAndObserveMissingVAAs)
- }
- var AdminCmd = &cobra.Command{
- Use: "admin",
- Short: "Guardian node admin commands",
- }
- var AdminClientSignWormchainAddress = &cobra.Command{
- Use: "sign-wormchain-address [/path/to/guardianKey] [wormchain-validator-address]",
- Short: "Sign a wormchain validator address. Only sign the address that you control the key for and will be for your validator.",
- RunE: runSignWormchainValidatorAddress,
- Args: cobra.ExactArgs(2),
- }
- var AdminClientInjectGuardianSetUpdateCmd = &cobra.Command{
- Use: "governance-vaa-inject [FILENAME]",
- Short: "Inject and sign a governance VAA from a prototxt file (see docs!)",
- Run: runInjectGovernanceVAA,
- Args: cobra.ExactArgs(1),
- }
- var AdminClientFindMissingMessagesCmd = &cobra.Command{
- Use: "find-missing-messages [CHAIN_ID] [EMITTER_ADDRESS_HEX]",
- Short: "Find sequence number gaps for the given chain ID and emitter address",
- Run: runFindMissingMessages,
- Args: cobra.ExactArgs(2),
- }
- var DumpVAAByMessageID = &cobra.Command{
- Use: "dump-vaa-by-message-id [MESSAGE_ID]",
- Short: "Retrieve a VAA by message ID (chain/emitter/seq) and decode and dump the VAA",
- Run: runDumpVAAByMessageID,
- Args: cobra.ExactArgs(1),
- }
- var SendObservationRequest = &cobra.Command{
- Use: "send-observation-request [CHAIN_ID|CHAIN_NAME] [TX_HASH_HEX]",
- Short: "Broadcast an observation request for the given chain ID and chain-specific tx_hash",
- Run: runSendObservationRequest,
- Args: cobra.ExactArgs(2),
- }
- var ClientChainGovernorStatusCmd = &cobra.Command{
- Use: "governor-status",
- Short: "Displays the status of the chain governor",
- Run: runChainGovernorStatus,
- Args: cobra.ExactArgs(0),
- }
- var ClientChainGovernorReloadCmd = &cobra.Command{
- Use: "governor-reload",
- Short: "Clears the chain governor history and reloads it from the database",
- Run: runChainGovernorReload,
- Args: cobra.ExactArgs(0),
- }
- var ClientChainGovernorDropPendingVAACmd = &cobra.Command{
- Use: "governor-drop-pending-vaa [VAA_ID]",
- Short: "Removes the specified VAA (chain/emitter/seq) from the chain governor pending list",
- Run: runChainGovernorDropPendingVAA,
- Args: cobra.ExactArgs(1),
- }
- var ClientChainGovernorReleasePendingVAACmd = &cobra.Command{
- Use: "governor-release-pending-vaa [VAA_ID]",
- Short: "Releases the specified VAA (chain/emitter/seq) from the chain governor pending list, publishing it immediately",
- Run: runChainGovernorReleasePendingVAA,
- Args: cobra.ExactArgs(1),
- }
- var ClientChainGovernorResetReleaseTimerCmd = &cobra.Command{
- Use: "governor-reset-release-timer [VAA_ID] <num_days>",
- Short: "Resets the release timer for a chain governor pending VAA, extending it to num_days (up to a maximum of 7), defaulting to one day if num_days is omitted",
- Run: runChainGovernorResetReleaseTimer,
- Args: cobra.RangeArgs(1, 2),
- }
- var PurgePythNetVaasCmd = &cobra.Command{
- Use: "purge-pythnet-vaas [DAYS_OLD] <logonly>",
- Short: "Deletes PythNet VAAs from the database that are more than [DAYS_OLD] days only (if logonly is specified, doesn't delete anything)",
- Run: runPurgePythNetVaas,
- Args: cobra.RangeArgs(1, 2),
- }
- var SignExistingVaaCmd = &cobra.Command{
- Use: "sign-existing-vaa [VAA] [NEW_GUARDIANS] [NEW_GUARDIAN_SET_INDEX]",
- Short: "Signs an existing VAA for a new guardian set using the local guardian key. This only works if the new VAA would have quorum.",
- Run: runSignExistingVaa,
- Args: cobra.ExactArgs(3),
- }
- var SignExistingVaasFromCSVCmd = &cobra.Command{
- Use: "sign-existing-vaas-csv [IN_FILE] [OUT_FILE] [NEW_GUARDIANS] [NEW_GUARDIAN_SET_INDEX]",
- Short: "Signs a CSV [VAA_ID,VAA_HEX] of existing VAAs for a new guardian set using the local guardian key and writes it to a new CSV. VAAs that don't have quorum on the new set will be dropped.",
- Run: runSignExistingVaasFromCSV,
- Args: cobra.ExactArgs(4),
- }
- var DumpRPCs = &cobra.Command{
- Use: "dump-rpcs",
- Short: "Displays the RPCs in use by the guardian",
- Run: runDumpRPCs,
- Args: cobra.ExactArgs(0),
- }
- var GetAndObserveMissingVAAs = &cobra.Command{
- Use: "get-and-observe-missing-vaas [URL] [API_KEY]",
- Short: "Get the list of missing VAAs from a cloud function and try to reobserve them.",
- Run: runGetAndObserveMissingVAAs,
- Args: cobra.ExactArgs(2),
- }
- var Keccak256Hash = &cobra.Command{
- Use: "keccak256",
- Short: "Compute legacy keccak256 hash",
- Run: runKeccak256Hash,
- Args: cobra.ExactArgs(0),
- }
- func getAdminClient(ctx context.Context, addr string) (*grpc.ClientConn, nodev1.NodePrivilegedServiceClient, error) {
- conn, err := grpc.DialContext(ctx, fmt.Sprintf("unix:///%s", addr), grpc.WithTransportCredentials(insecure.NewCredentials()))
- if err != nil {
- log.Fatalf("failed to connect to %s: %v", addr, err)
- }
- c := nodev1.NewNodePrivilegedServiceClient(conn)
- return conn, c, err
- }
- func getPublicRPCServiceClient(ctx context.Context, addr string) (*grpc.ClientConn, publicrpcv1.PublicRPCServiceClient, error) {
- conn, err := grpc.DialContext(ctx, fmt.Sprintf("unix:///%s", addr), grpc.WithTransportCredentials(insecure.NewCredentials()))
- if err != nil {
- log.Fatalf("failed to connect to %s: %v", addr, err)
- }
- c := publicrpcv1.NewPublicRPCServiceClient(conn)
- return conn, c, err
- }
- func runSignWormchainValidatorAddress(cmd *cobra.Command, args []string) error {
- guardianKeyPath := args[0]
- wormchainAddress := args[1]
- if !strings.HasPrefix(wormchainAddress, "wormhole") || strings.HasPrefix(wormchainAddress, "wormholeval") {
- return errors.New("must provide a bech32 address that has 'wormhole' prefix")
- }
- gk, err := common.LoadGuardianKey(guardianKeyPath, *unsafeDevnetMode)
- if err != nil {
- return fmt.Errorf("failed to load guardian key: %w", err)
- }
- addr, err := types.GetFromBech32(wormchainAddress, "wormhole")
- if err != nil {
- return fmt.Errorf("failed to decode wormchain address: %w", err)
- }
- // Hash and sign address
- addrHash := crypto.Keccak256Hash(sdk.SignedWormchainAddressPrefix, addr)
- sig, err := crypto.Sign(addrHash[:], gk)
- if err != nil {
- return fmt.Errorf("failed to sign wormchain address: %w", err)
- }
- fmt.Println(hex.EncodeToString(sig))
- return nil
- }
- func runInjectGovernanceVAA(cmd *cobra.Command, args []string) {
- path := args[0]
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- b, err := os.ReadFile(path)
- if err != nil {
- log.Fatalf("failed to read file: %v", err)
- }
- var msg nodev1.InjectGovernanceVAARequest
- err = prototext.Unmarshal(b, &msg)
- if err != nil {
- log.Fatalf("failed to deserialize: %v", err)
- }
- resp, err := c.InjectGovernanceVAA(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to submit governance VAA: %v", err)
- }
- for _, digest := range resp.Digests {
- log.Printf("VAA successfully injected with digest %s", hexutils.BytesToHex(digest))
- }
- }
- func runFindMissingMessages(cmd *cobra.Command, args []string) {
- chainID, err := strconv.Atoi(args[0])
- if err != nil {
- log.Fatalf("invalid chain ID: %v", err)
- }
- emitterAddress := args[1]
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- msg := nodev1.FindMissingMessagesRequest{
- EmitterChain: uint32(chainID),
- EmitterAddress: emitterAddress,
- RpcBackfill: *shouldBackfill,
- BackfillNodes: sdk.PublicRPCEndpoints,
- }
- resp, err := c.FindMissingMessages(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run find FindMissingMessages RPC: %v", err)
- }
- for _, id := range resp.MissingMessages {
- fmt.Println(id)
- }
- log.Printf("processed %s sequences %d to %d (%d gaps)",
- emitterAddress, resp.FirstSequence, resp.LastSequence, len(resp.MissingMessages))
- }
- // runDumpVAAByMessageID uses GetSignedVAA to request the given message,
- // then decode and dump the VAA.
- func runDumpVAAByMessageID(cmd *cobra.Command, args []string) {
- // Parse the {chain,emitter,seq} string.
- parts := strings.Split(args[0], "/")
- if len(parts) != 3 {
- log.Fatalf("invalid message ID: %s", args[0])
- }
- chainID, err := strconv.ParseUint(parts[0], 10, 32)
- if err != nil {
- log.Fatalf("invalid chain ID: %v", err)
- }
- emitterAddress := parts[1]
- seq, err := strconv.ParseUint(parts[2], 10, 64)
- if err != nil {
- log.Fatalf("invalid sequence number: %v", err)
- }
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getPublicRPCServiceClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get public RPC service client: %v", err)
- }
- defer conn.Close()
- msg := publicrpcv1.GetSignedVAARequest{
- MessageId: &publicrpcv1.MessageID{
- EmitterChain: publicrpcv1.ChainID(chainID),
- EmitterAddress: emitterAddress,
- Sequence: seq,
- },
- }
- resp, err := c.GetSignedVAA(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run GetSignedVAA RPC: %v", err)
- }
- v, err := vaa.Unmarshal(resp.VaaBytes)
- if err != nil {
- log.Fatalf("failed to decode VAA: %v", err)
- }
- log.Printf("VAA with digest %s: %+v\n", v.HexDigest(), spew.Sdump(v))
- fmt.Printf("Bytes:\n%s\n", hex.EncodeToString(resp.VaaBytes))
- }
- func runSendObservationRequest(cmd *cobra.Command, args []string) {
- chainID, err := parseChainID(args[0])
- if err != nil {
- log.Fatalf("invalid chain ID: %v", err)
- }
- // Support tx with or without leading 0x so copy / pasta
- // from monitoring tools is easier.
- txHash, err := hex.DecodeString(strings.TrimPrefix(args[1], "0x"))
- if err != nil {
- txHash, err = base58.Decode(args[1])
- if err != nil {
- log.Fatalf("invalid transaction hash (neither hex nor base58): %v", err)
- }
- }
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- _, err = c.SendObservationRequest(ctx, &nodev1.SendObservationRequestRequest{
- ObservationRequest: &gossipv1.ObservationRequest{
- ChainId: uint32(chainID),
- TxHash: txHash,
- },
- })
- if err != nil {
- log.Fatalf("failed to send observation request: %v", err)
- }
- }
- func runDumpRPCs(cmd *cobra.Command, args []string) {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- resp, err := c.DumpRPCs(ctx, &nodev1.DumpRPCsRequest{})
- if err != nil {
- log.Fatalf("failed to run dump-rpcs: %s", err)
- }
- for parm, rpc := range resp.Response {
- fmt.Println(parm, " = [", rpc, "]")
- }
- }
- func runGetAndObserveMissingVAAs(cmd *cobra.Command, args []string) {
- url := args[0]
- if !strings.HasPrefix(url, "https://") {
- log.Fatalf("invalid url: %s", url)
- }
- apiKey := args[1]
- if len(apiKey) == 0 {
- log.Fatalf("missing api key")
- }
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- cmdInfo := nodev1.GetAndObserveMissingVAAsRequest{
- Url: url,
- ApiKey: apiKey,
- }
- resp, err := c.GetAndObserveMissingVAAs(ctx, &cmdInfo)
- if err != nil {
- log.Fatalf("failed to run get-missing-vaas: %s", err)
- }
- fmt.Println(resp.GetResponse())
- }
- func runChainGovernorStatus(cmd *cobra.Command, args []string) {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- msg := nodev1.ChainGovernorStatusRequest{}
- resp, err := c.ChainGovernorStatus(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run ChainGovernorStatus RPC: %s", err)
- }
- fmt.Println(resp.Response)
- }
- func runChainGovernorReload(cmd *cobra.Command, args []string) {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- msg := nodev1.ChainGovernorReloadRequest{}
- resp, err := c.ChainGovernorReload(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run ChainGovernorReload RPC: %s", err)
- }
- fmt.Println(resp.Response)
- }
- func runChainGovernorDropPendingVAA(cmd *cobra.Command, args []string) {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- msg := nodev1.ChainGovernorDropPendingVAARequest{
- VaaId: args[0],
- }
- resp, err := c.ChainGovernorDropPendingVAA(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run ChainGovernorDropPendingVAA RPC: %s", err)
- }
- fmt.Println(resp.Response)
- }
- func runChainGovernorReleasePendingVAA(cmd *cobra.Command, args []string) {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- msg := nodev1.ChainGovernorReleasePendingVAARequest{
- VaaId: args[0],
- }
- resp, err := c.ChainGovernorReleasePendingVAA(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run ChainGovernorReleasePendingVAA RPC: %s", err)
- }
- fmt.Println(resp.Response)
- }
- func runChainGovernorResetReleaseTimer(cmd *cobra.Command, args []string) {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- // defaults to 1 day if num_days isn't specified
- numDays := uint32(1)
- if len(args) > 1 {
- numDaysArg, err := strconv.Atoi(args[1])
- if err != nil {
- log.Fatalf("invalid num_days: %v", err)
- }
- numDays = uint32(numDaysArg)
- }
- msg := nodev1.ChainGovernorResetReleaseTimerRequest{
- VaaId: args[0],
- NumDays: numDays,
- }
- resp, err := c.ChainGovernorResetReleaseTimer(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run ChainGovernorResetReleaseTimer RPC: %s", err)
- }
- fmt.Println(resp.Response)
- }
- func runPurgePythNetVaas(cmd *cobra.Command, args []string) {
- daysOld, err := strconv.Atoi(args[0])
- if err != nil {
- log.Fatalf("invalid DAYS_OLD: %v", err)
- }
- if daysOld < 0 {
- log.Fatalf("DAYS_OLD may not be negative")
- }
- logOnly := false
- if len(args) > 1 {
- if args[1] != "logonly" {
- log.Fatalf("invalid option, only \"logonly\" is supported")
- }
- logOnly = true
- }
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- msg := nodev1.PurgePythNetVaasRequest{
- DaysOld: uint64(daysOld),
- LogOnly: logOnly,
- }
- resp, err := c.PurgePythNetVaas(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run PurgePythNetVaas RPC: %s", err)
- }
- fmt.Println(resp.Response)
- }
- func runSignExistingVaa(cmd *cobra.Command, args []string) {
- existingVAA := ethcommon.Hex2Bytes(args[0])
- if len(existingVAA) == 0 {
- log.Fatalf("vaa hex invalid")
- }
- newGsStrings := strings.Split(args[1], ",")
- newGsIndex, err := strconv.ParseUint(args[2], 10, 32)
- if err != nil {
- log.Fatalf("invalid new guardian set index")
- }
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- msg := nodev1.SignExistingVAARequest{
- Vaa: existingVAA,
- NewGuardianAddrs: newGsStrings,
- NewGuardianSetIndex: uint32(newGsIndex),
- }
- resp, err := c.SignExistingVAA(ctx, &msg)
- if err != nil {
- log.Fatalf("failed to run SignExistingVAA RPC: %s", err)
- }
- fmt.Println(hex.EncodeToString(resp.Vaa))
- }
- func runSignExistingVaasFromCSV(cmd *cobra.Command, args []string) {
- oldVAAFile, err := os.Open(args[0])
- if err != nil {
- log.Fatalf("failed to read old VAA db: %v", err)
- }
- defer oldVAAFile.Close()
- newVAAFile, err := os.OpenFile(args[1], os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
- if err != nil {
- log.Fatalf("failed to create new VAA db: %v", err)
- }
- defer newVAAFile.Close()
- newVAAWriter := csv.NewWriter(newVAAFile)
- newGsStrings := strings.Split(args[2], ",")
- newGsIndex, err := strconv.ParseUint(args[3], 10, 32)
- if err != nil {
- log.Fatalf("invalid new guardian set index")
- }
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- conn, c, err := getAdminClient(ctx, *clientSocketPath)
- if err != nil {
- log.Fatalf("failed to get admin client: %v", err)
- }
- defer conn.Close()
- // Scan the CSV once to make sure it won't fail while reading unless raced
- oldVAAReader := csv.NewReader(oldVAAFile)
- numOldVAAs := 0
- for {
- row, err := oldVAAReader.Read()
- if err != nil {
- if err == io.EOF {
- break
- }
- log.Fatalf("failed to parse VAA CSV: %v", err)
- }
- if len(row) != 2 {
- log.Fatalf("row [%d] does not have 2 elements", numOldVAAs)
- }
- numOldVAAs++
- }
- // Reset reader
- _, err = oldVAAFile.Seek(0, io.SeekStart)
- if err != nil {
- log.Fatalf("failed to seek back in CSV file: %v", err)
- }
- oldVAAReader = csv.NewReader(oldVAAFile)
- counter, i := 0, 0
- for {
- row, err := oldVAAReader.Read()
- if err != nil {
- if err == io.EOF {
- break
- }
- log.Fatalf("failed to parse VAA CSV: %v", err)
- }
- if len(row) != 2 {
- log.Fatalf("row [%d] does not have 2 elements", i)
- }
- i++
- if i%10 == 0 {
- log.Printf("Processing VAA %d/%d", i, numOldVAAs)
- }
- vaaBytes := ethcommon.Hex2Bytes(row[1])
- msg := nodev1.SignExistingVAARequest{
- Vaa: vaaBytes,
- NewGuardianAddrs: newGsStrings,
- NewGuardianSetIndex: uint32(newGsIndex),
- }
- resp, err := c.SignExistingVAA(ctx, &msg)
- if err != nil {
- log.Printf("signing VAA (%s)[%d] failed - skipping: %v", row[0], i, err)
- continue
- }
- err = newVAAWriter.Write([]string{row[0], hex.EncodeToString(resp.Vaa)})
- if err != nil {
- log.Fatalf("failed to write new VAA to out db: %v", err)
- }
- counter++
- }
- log.Printf("Successfully signed %d out of %d VAAs", counter, numOldVAAs)
- newVAAWriter.Flush()
- }
- // This exposes keccak256 as a command line utility, mostly for validating goverance messages
- // that use this hash. There isn't any common utility that computes this since this is nonstandard outside of evm.
- // It is used similar to other hashing utilities, e.g. `cat <file> | guardiand admin keccak256`.
- func runKeccak256Hash(cmd *cobra.Command, args []string) {
- reader := bufio.NewReader(os.Stdin)
- hash := sha3.NewLegacyKeccak256()
- // ~10 MB chunks
- buf := make([]byte, 10*1024*1024)
- for {
- count, err := reader.Read(buf)
- if err != nil && err != io.EOF {
- log.Fatalf("could not read: %v", err)
- }
- _, errHash := hash.Write(buf[:count])
- if errHash != nil {
- log.Fatalf("could not hash: %v", errHash)
- }
- if err == io.EOF {
- break
- }
- }
- digest := hash.Sum([]byte{})
- fmt.Printf("%s", hex.EncodeToString(digest))
- }
|