2020-11-19 03:53:19 -08:00
package guardiand
import (
2023-02-15 15:39:07 -08:00
"bufio"
2020-11-19 03:53:19 -08:00
"context"
2023-01-10 08:54:35 -08:00
"encoding/csv"
2021-11-01 09:17:02 -07:00
"encoding/hex"
2020-11-19 03:53:19 -08:00
"fmt"
2023-01-10 08:54:35 -08:00
"io"
2020-11-19 03:53:19 -08:00
"log"
2022-11-28 05:48:27 -08:00
"os"
2021-10-04 04:42:56 -07:00
"strconv"
2021-10-29 05:17:13 -07:00
"strings"
2020-11-19 03:53:19 -08:00
"time"
2023-01-16 04:33:01 -08:00
"github.com/cosmos/cosmos-sdk/types"
2022-04-27 04:39:56 -07:00
"github.com/davecgh/go-spew/spew"
2023-01-16 04:33:01 -08:00
ethcommon "github.com/ethereum/go-ethereum/common"
2022-11-28 08:46:19 -08:00
"github.com/ethereum/go-ethereum/crypto"
2022-04-27 04:39:56 -07:00
"github.com/mr-tron/base58"
"github.com/spf13/pflag"
2023-02-15 15:39:07 -08:00
"golang.org/x/crypto/sha3"
2022-04-27 04:39:56 -07:00
2023-09-27 10:06:12 -07:00
"github.com/certusone/wormhole/node/pkg/common"
2022-04-27 04:39:56 -07:00
gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
publicrpcv1 "github.com/certusone/wormhole/node/pkg/proto/publicrpc/v1"
2022-08-18 01:52:36 -07:00
"github.com/wormhole-foundation/wormhole/sdk"
"github.com/wormhole-foundation/wormhole/sdk/vaa"
2022-04-27 04:39:56 -07:00
2020-11-19 03:53:19 -08:00
"github.com/spf13/cobra"
"github.com/status-im/keycard-go/hexutils"
2022-11-28 08:46:19 -08:00
2020-11-19 03:53:19 -08:00
"google.golang.org/grpc"
2022-09-05 23:18:45 -07:00
"google.golang.org/grpc/credentials/insecure"
2020-11-19 03:53:19 -08:00
"google.golang.org/protobuf/encoding/prototext"
2021-08-26 01:35:09 -07:00
nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
2020-11-19 03:53:19 -08:00
)
2021-08-07 12:12:08 -07:00
var (
clientSocketPath * string
2021-12-18 14:39:30 -08:00
shouldBackfill * bool
2023-09-27 10:06:12 -07:00
unsafeDevnetMode * bool
2021-08-07 12:12:08 -07:00
)
2020-11-19 03:53:19 -08:00
func init ( ) {
2021-08-07 12:12:08 -07:00
// Shared flags for all admin commands
pf := pflag . NewFlagSet ( "commonAdminFlags" , pflag . ContinueOnError )
2020-11-19 03:53:19 -08:00
clientSocketPath = pf . String ( "socket" , "" , "gRPC admin server socket to connect to" )
err := cobra . MarkFlagRequired ( pf , "socket" )
if err != nil {
panic ( err )
}
2021-08-07 12:12:08 -07:00
2021-12-18 14:39:30 -08:00
shouldBackfill = AdminClientFindMissingMessagesCmd . Flags ( ) . Bool (
"backfill" , false , "backfill missing VAAs from public RPC" )
2021-08-07 12:12:08 -07:00
AdminClientInjectGuardianSetUpdateCmd . Flags ( ) . AddFlagSet ( pf )
2021-10-04 04:42:56 -07:00
AdminClientFindMissingMessagesCmd . Flags ( ) . AddFlagSet ( pf )
2021-08-07 12:12:08 -07:00
AdminClientListNodes . Flags ( ) . AddFlagSet ( pf )
2021-10-29 05:17:13 -07:00
DumpVAAByMessageID . Flags ( ) . AddFlagSet ( pf )
2023-02-03 11:12:01 -08:00
DumpRPCs . Flags ( ) . AddFlagSet ( pf )
2021-12-20 13:23:45 -08:00
SendObservationRequest . Flags ( ) . AddFlagSet ( pf )
2022-07-19 11:08:06 -07:00
ClientChainGovernorStatusCmd . Flags ( ) . AddFlagSet ( pf )
ClientChainGovernorReloadCmd . Flags ( ) . AddFlagSet ( pf )
ClientChainGovernorDropPendingVAACmd . Flags ( ) . AddFlagSet ( pf )
ClientChainGovernorReleasePendingVAACmd . Flags ( ) . AddFlagSet ( pf )
2022-08-30 09:28:18 -07:00
ClientChainGovernorResetReleaseTimerCmd . Flags ( ) . AddFlagSet ( pf )
2022-09-26 07:04:30 -07:00
PurgePythNetVaasCmd . Flags ( ) . AddFlagSet ( pf )
2023-01-10 08:54:35 -08:00
SignExistingVaaCmd . Flags ( ) . AddFlagSet ( pf )
SignExistingVaasFromCSVCmd . Flags ( ) . AddFlagSet ( pf )
2023-10-25 13:17:49 -07:00
GetAndObserveMissingVAAs . Flags ( ) . AddFlagSet ( pf )
2020-11-19 03:53:19 -08:00
2023-09-27 10:06:12 -07:00
adminClientSignWormchainAddressFlags := pflag . NewFlagSet ( "adminClientSignWormchainAddressFlags" , pflag . ContinueOnError )
unsafeDevnetMode = adminClientSignWormchainAddressFlags . Bool ( "unsafeDevMode" , false , "Run in unsafe devnet mode" )
AdminClientSignWormchainAddress . Flags ( ) . AddFlagSet ( adminClientSignWormchainAddressFlags )
2020-11-19 03:53:19 -08:00
AdminCmd . AddCommand ( AdminClientInjectGuardianSetUpdateCmd )
2021-10-04 04:42:56 -07:00
AdminCmd . AddCommand ( AdminClientFindMissingMessagesCmd )
2021-01-19 04:01:45 -08:00
AdminCmd . AddCommand ( AdminClientGovernanceVAAVerifyCmd )
2021-08-07 12:12:08 -07:00
AdminCmd . AddCommand ( AdminClientListNodes )
2022-11-28 08:46:19 -08:00
AdminCmd . AddCommand ( AdminClientSignWormchainAddress )
2021-10-29 05:17:13 -07:00
AdminCmd . AddCommand ( DumpVAAByMessageID )
2023-02-03 11:12:01 -08:00
AdminCmd . AddCommand ( DumpRPCs )
2021-12-20 13:23:45 -08:00
AdminCmd . AddCommand ( SendObservationRequest )
2022-07-19 11:08:06 -07:00
AdminCmd . AddCommand ( ClientChainGovernorStatusCmd )
AdminCmd . AddCommand ( ClientChainGovernorReloadCmd )
AdminCmd . AddCommand ( ClientChainGovernorDropPendingVAACmd )
AdminCmd . AddCommand ( ClientChainGovernorReleasePendingVAACmd )
2022-08-30 09:28:18 -07:00
AdminCmd . AddCommand ( ClientChainGovernorResetReleaseTimerCmd )
2022-09-26 07:04:30 -07:00
AdminCmd . AddCommand ( PurgePythNetVaasCmd )
2023-01-10 08:54:35 -08:00
AdminCmd . AddCommand ( SignExistingVaaCmd )
AdminCmd . AddCommand ( SignExistingVaasFromCSVCmd )
2023-02-15 15:39:07 -08:00
AdminCmd . AddCommand ( Keccak256Hash )
2023-10-25 13:17:49 -07:00
AdminCmd . AddCommand ( GetAndObserveMissingVAAs )
2020-11-19 03:53:19 -08:00
}
var AdminCmd = & cobra . Command {
Use : "admin" ,
Short : "Guardian node admin commands" ,
}
2022-11-28 08:46:19 -08:00
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 ) ,
}
2020-11-19 03:53:19 -08:00
var AdminClientInjectGuardianSetUpdateCmd = & cobra . Command {
2021-01-20 15:01:34 -08:00
Use : "governance-vaa-inject [FILENAME]" ,
2021-01-19 04:01:45 -08:00
Short : "Inject and sign a governance VAA from a prototxt file (see docs!)" ,
Run : runInjectGovernanceVAA ,
2020-11-19 03:53:19 -08:00
Args : cobra . ExactArgs ( 1 ) ,
}
2021-10-04 04:42:56 -07:00
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 ) ,
}
2021-10-29 05:17:13 -07:00
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 ) ,
}
2021-12-20 13:23:45 -08:00
var SendObservationRequest = & cobra . Command {
2022-04-27 04:39:56 -07:00
Use : "send-observation-request [CHAIN_ID|CHAIN_NAME] [TX_HASH_HEX]" ,
2021-12-20 13:23:45 -08:00
Short : "Broadcast an observation request for the given chain ID and chain-specific tx_hash" ,
Run : runSendObservationRequest ,
Args : cobra . ExactArgs ( 2 ) ,
}
2022-07-19 11:08:06 -07:00
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 ) ,
}
2022-08-30 09:28:18 -07:00
var ClientChainGovernorResetReleaseTimerCmd = & cobra . Command {
Use : "governor-reset-release-timer [VAA_ID]" ,
Short : "Resets the release timer for a chain governor pending VAA, extending it to the configured maximum" ,
Run : runChainGovernorResetReleaseTimer ,
Args : cobra . ExactArgs ( 1 ) ,
}
2022-09-26 07:04:30 -07:00
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 ) ,
}
2023-01-10 08:54:35 -08:00
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 ) ,
}
2023-02-03 11:12:01 -08:00
var DumpRPCs = & cobra . Command {
Use : "dump-rpcs" ,
Short : "Displays the RPCs in use by the guardian" ,
Run : runDumpRPCs ,
Args : cobra . ExactArgs ( 0 ) ,
}
2023-10-25 13:17:49 -07:00
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 ) ,
}
2023-02-15 15:39:07 -08:00
var Keccak256Hash = & cobra . Command {
Use : "keccak256" ,
Short : "Compute legacy keccak256 hash" ,
Run : runKeccak256Hash ,
Args : cobra . ExactArgs ( 0 ) ,
}
2022-07-19 11:08:06 -07:00
func getAdminClient ( ctx context . Context , addr string ) ( * grpc . ClientConn , nodev1 . NodePrivilegedServiceClient , error ) {
2022-09-05 23:18:45 -07:00
conn , err := grpc . DialContext ( ctx , fmt . Sprintf ( "unix:///%s" , addr ) , grpc . WithTransportCredentials ( insecure . NewCredentials ( ) ) )
2020-11-19 03:53:19 -08:00
if err != nil {
log . Fatalf ( "failed to connect to %s: %v" , addr , err )
}
2021-08-21 15:34:58 -07:00
c := nodev1 . NewNodePrivilegedServiceClient ( conn )
2022-07-19 11:08:06 -07:00
return conn , c , err
2020-11-19 03:53:19 -08:00
}
2022-07-19 11:08:06 -07:00
func getPublicRPCServiceClient ( ctx context . Context , addr string ) ( * grpc . ClientConn , publicrpcv1 . PublicRPCServiceClient , error ) {
2022-09-05 23:18:45 -07:00
conn , err := grpc . DialContext ( ctx , fmt . Sprintf ( "unix:///%s" , addr ) , grpc . WithTransportCredentials ( insecure . NewCredentials ( ) ) )
2021-07-22 04:48:53 -07:00
if err != nil {
log . Fatalf ( "failed to connect to %s: %v" , addr , err )
}
2021-08-21 15:34:58 -07:00
c := publicrpcv1 . NewPublicRPCServiceClient ( conn )
2022-07-19 11:08:06 -07:00
return conn , c , err
2021-07-22 04:48:53 -07:00
}
2022-11-28 08:46:19 -08:00
func runSignWormchainValidatorAddress ( cmd * cobra . Command , args [ ] string ) error {
guardianKeyPath := args [ 0 ]
wormchainAddress := args [ 1 ]
if ! strings . HasPrefix ( wormchainAddress , "wormhole" ) || strings . HasPrefix ( wormchainAddress , "wormholeval" ) {
return fmt . Errorf ( "must provide a bech32 address that has 'wormhole' prefix" )
}
2023-09-27 10:06:12 -07:00
gk , err := common . LoadGuardianKey ( guardianKeyPath , * unsafeDevnetMode )
2022-11-28 08:46:19 -08:00
if err != nil {
return fmt . Errorf ( "failed to load guardian key: %w" , err )
}
2023-01-16 04:33:01 -08:00
addr , err := types . GetFromBech32 ( wormchainAddress , "wormhole" )
2022-11-28 08:46:19 -08:00
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
}
2021-01-19 04:01:45 -08:00
func runInjectGovernanceVAA ( cmd * cobra . Command , args [ ] string ) {
2020-11-19 03:53:19 -08:00
path := args [ 0 ]
ctx , cancel := context . WithTimeout ( context . Background ( ) , 5 * time . Second )
defer cancel ( )
2022-07-19 11:08:06 -07:00
conn , c , err := getAdminClient ( ctx , * clientSocketPath )
2021-07-22 04:48:53 -07:00
if err != nil {
log . Fatalf ( "failed to get admin client: %v" , err )
}
2022-07-19 11:08:06 -07:00
defer conn . Close ( )
2020-11-19 03:53:19 -08:00
2022-11-28 05:48:27 -08:00
b , err := os . ReadFile ( path )
2020-11-19 03:53:19 -08:00
if err != nil {
log . Fatalf ( "failed to read file: %v" , err )
}
2021-01-19 04:01:45 -08:00
var msg nodev1 . InjectGovernanceVAARequest
2020-11-19 03:53:19 -08:00
err = prototext . Unmarshal ( b , & msg )
if err != nil {
log . Fatalf ( "failed to deserialize: %v" , err )
}
2021-01-19 04:01:45 -08:00
resp , err := c . InjectGovernanceVAA ( ctx , & msg )
2020-11-19 03:53:19 -08:00
if err != nil {
2021-01-19 04:01:45 -08:00
log . Fatalf ( "failed to submit governance VAA: %v" , err )
2020-11-19 03:53:19 -08:00
}
2021-10-29 08:50:46 -07:00
for _ , digest := range resp . Digests {
log . Printf ( "VAA successfully injected with digest %s" , hexutils . BytesToHex ( digest ) )
}
2020-11-19 03:53:19 -08:00
}
2021-10-04 04:42:56 -07:00
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 ]
2021-12-18 14:39:30 -08:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Minute )
2021-10-04 04:42:56 -07:00
defer cancel ( )
2022-07-19 11:08:06 -07:00
conn , c , err := getAdminClient ( ctx , * clientSocketPath )
2021-10-04 04:42:56 -07:00
if err != nil {
log . Fatalf ( "failed to get admin client: %v" , err )
}
2022-07-19 11:08:06 -07:00
defer conn . Close ( )
2021-10-04 04:42:56 -07:00
msg := nodev1 . FindMissingMessagesRequest {
EmitterChain : uint32 ( chainID ) ,
EmitterAddress : emitterAddress ,
2021-12-18 14:39:30 -08:00
RpcBackfill : * shouldBackfill ,
2022-08-18 01:52:36 -07:00
BackfillNodes : sdk . PublicRPCEndpoints ,
2021-10-04 04:42:56 -07:00
}
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 ) )
}
2021-10-29 05:17:13 -07:00
// 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 ( )
2022-07-19 11:08:06 -07:00
conn , c , err := getPublicRPCServiceClient ( ctx , * clientSocketPath )
2021-10-29 05:17:13 -07:00
if err != nil {
log . Fatalf ( "failed to get public RPC service client: %v" , err )
}
2022-07-19 11:08:06 -07:00
defer conn . Close ( )
2021-10-29 05:17:13 -07:00
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 )
}
2021-11-01 09:17:02 -07:00
log . Printf ( "VAA with digest %s: %+v\n" , v . HexDigest ( ) , spew . Sdump ( v ) )
fmt . Printf ( "Bytes:\n%s\n" , hex . EncodeToString ( resp . VaaBytes ) )
2021-10-29 05:17:13 -07:00
}
2021-12-20 13:23:45 -08:00
func runSendObservationRequest ( cmd * cobra . Command , args [ ] string ) {
2022-04-27 04:39:56 -07:00
chainID , err := parseChainID ( args [ 0 ] )
2021-12-20 13:23:45 -08:00
if err != nil {
log . Fatalf ( "invalid chain ID: %v" , err )
}
2023-01-20 08:55:37 -08:00
// Support tx with or without leading 0x so copy / pasta
// from monitoring tools is easier.
txHash , err := hex . DecodeString ( strings . TrimPrefix ( args [ 1 ] , "0x" ) )
2021-12-20 13:23:45 -08:00
if err != nil {
2022-04-27 04:39:56 -07:00
txHash , err = base58 . Decode ( args [ 1 ] )
if err != nil {
log . Fatalf ( "invalid transaction hash (neither hex nor base58): %v" , err )
}
2021-12-20 13:23:45 -08:00
}
ctx , cancel := context . WithTimeout ( context . Background ( ) , 5 * time . Second )
defer cancel ( )
2022-07-19 11:08:06 -07:00
conn , c , err := getAdminClient ( ctx , * clientSocketPath )
2021-12-20 13:23:45 -08:00
if err != nil {
log . Fatalf ( "failed to get admin client: %v" , err )
}
2022-07-19 11:08:06 -07:00
defer conn . Close ( )
2021-12-20 13:23:45 -08:00
_ , 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 )
}
}
2022-07-19 11:08:06 -07:00
2023-02-03 11:12:01 -08:00
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 , "]" )
}
}
2023-10-25 13:17:49 -07:00
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 ( ) )
}
2022-07-19 11:08:06 -07:00
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 )
}
2022-08-30 09:28:18 -07:00
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 ( )
msg := nodev1 . ChainGovernorResetReleaseTimerRequest {
VaaId : args [ 0 ] ,
}
resp , err := c . ChainGovernorResetReleaseTimer ( ctx , & msg )
if err != nil {
log . Fatalf ( "failed to run ChainGovernorResetReleaseTimer RPC: %s" , err )
}
fmt . Println ( resp . Response )
}
2022-09-26 07:04:30 -07:00
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 )
}
2023-01-10 08:54:35 -08:00
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 ( )
}
2023-02-15 15:39:07 -08:00
// 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 ) )
}