2020-11-19 03:53:19 -08:00
package guardiand
import (
2023-01-10 08:54:35 -08:00
"bytes"
2020-11-19 03:53:19 -08:00
"context"
2023-01-10 08:54:35 -08:00
"crypto/ecdsa"
2021-12-19 08:27:06 -08:00
"encoding/base64"
2021-09-30 11:57:44 -07:00
"encoding/hex"
2021-12-19 08:27:06 -08:00
"encoding/json"
2020-11-19 03:53:19 -08:00
"errors"
"fmt"
2022-06-21 12:18:16 -07:00
"math"
2023-02-13 16:40:11 -08:00
"math/big"
2022-06-21 12:18:16 -07:00
"math/rand"
"net"
"net/http"
"os"
2023-01-10 08:54:35 -08:00
"sync"
2022-06-21 12:18:16 -07:00
"time"
2023-01-10 08:54:35 -08:00
"github.com/certusone/wormhole/node/pkg/watchers/evm/connectors"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
2023-02-14 10:01:15 -08:00
"github.com/holiman/uint256"
2023-01-10 08:54:35 -08:00
"golang.org/x/exp/slices"
2021-08-26 01:35:09 -07:00
"github.com/certusone/wormhole/node/pkg/db"
2022-07-19 11:08:06 -07:00
"github.com/certusone/wormhole/node/pkg/governor"
2021-12-19 08:27:06 -08:00
gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
2021-08-26 01:35:09 -07:00
publicrpcv1 "github.com/certusone/wormhole/node/pkg/proto/publicrpc/v1"
"github.com/certusone/wormhole/node/pkg/publicrpc"
2021-09-30 11:57:44 -07:00
ethcommon "github.com/ethereum/go-ethereum/common"
2020-11-19 03:53:19 -08:00
"go.uber.org/zap"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
2021-08-26 01:35:09 -07:00
"github.com/certusone/wormhole/node/pkg/common"
nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
"github.com/certusone/wormhole/node/pkg/supervisor"
2022-08-18 01:52:36 -07:00
"github.com/wormhole-foundation/wormhole/sdk/vaa"
2020-11-19 03:53:19 -08:00
)
type nodePrivilegedService struct {
2021-08-21 15:34:58 -07:00
nodev1 . UnimplementedNodePrivilegedServiceServer
2023-01-10 08:54:35 -08:00
db * db . Database
injectC chan <- * vaa . VAA
2023-01-20 13:15:13 -08:00
obsvReqSendC chan <- * gossipv1 . ObservationRequest
2023-01-10 08:54:35 -08:00
logger * zap . Logger
2023-01-20 13:15:13 -08:00
signedInC chan <- * gossipv1 . SignedVAAWithQuorum
2023-01-10 08:54:35 -08:00
governor * governor . ChainGovernor
evmConnector connectors . Connector
gsCache sync . Map
gk * ecdsa . PrivateKey
guardianAddress ethcommon . Address
2023-04-03 07:24:17 -07:00
testnetMode bool
2020-11-19 03:53:19 -08:00
}
// adminGuardianSetUpdateToVAA converts a nodev1.GuardianSetUpdate message to its canonical VAA representation.
// Returns an error if the data is invalid.
2022-04-19 08:59:00 -07:00
func adminGuardianSetUpdateToVAA ( req * nodev1 . GuardianSetUpdate , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
2020-11-19 03:53:19 -08:00
if len ( req . Guardians ) == 0 {
return nil , errors . New ( "empty guardian set specified" )
}
if len ( req . Guardians ) > common . MaxGuardianCount {
return nil , fmt . Errorf ( "too many guardians - %d, maximum is %d" , len ( req . Guardians ) , common . MaxGuardianCount )
}
addrs := make ( [ ] ethcommon . Address , len ( req . Guardians ) )
for i , g := range req . Guardians {
if ! ethcommon . IsHexAddress ( g . Pubkey ) {
return nil , fmt . Errorf ( "invalid pubkey format at index %d (%s)" , i , g . Name )
}
2021-01-20 15:25:38 -08:00
ethAddr := ethcommon . HexToAddress ( g . Pubkey )
for j , pk := range addrs {
if pk == ethAddr {
return nil , fmt . Errorf ( "duplicate pubkey at index %d (duplicate of %d): %s" , i , j , g . Name )
}
}
addrs [ i ] = ethAddr
2020-11-19 03:53:19 -08:00
}
2022-04-19 08:59:00 -07:00
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
2021-09-30 11:57:44 -07:00
vaa . BodyGuardianSetUpdate {
2020-11-19 03:53:19 -08:00
Keys : addrs ,
2021-01-19 04:01:45 -08:00
NewIndex : guardianSetIndex + 1 ,
2021-09-30 11:57:44 -07:00
} . Serialize ( ) )
2020-11-19 03:53:19 -08:00
return v , nil
}
2021-01-19 04:01:45 -08:00
// adminContractUpgradeToVAA converts a nodev1.ContractUpgrade message to its canonical VAA representation.
// Returns an error if the data is invalid.
2022-04-19 08:59:00 -07:00
func adminContractUpgradeToVAA ( req * nodev1 . ContractUpgrade , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
2021-10-12 06:22:07 -07:00
b , err := hex . DecodeString ( req . NewContract )
if err != nil {
return nil , errors . New ( "invalid new contract address encoding (expected hex)" )
}
if len ( b ) != 32 {
2021-01-19 04:01:45 -08:00
return nil , errors . New ( "invalid new_contract address" )
}
2021-10-12 05:55:14 -07:00
if req . ChainId > math . MaxUint16 {
2021-01-19 04:01:45 -08:00
return nil , errors . New ( "invalid chain_id" )
}
newContractAddress := vaa . Address { }
2022-02-02 16:06:57 -08:00
copy ( newContractAddress [ : ] , b )
2021-01-19 04:01:45 -08:00
2022-04-19 08:59:00 -07:00
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
2021-09-30 11:57:44 -07:00
vaa . BodyContractUpgrade {
2021-06-29 04:55:44 -07:00
ChainID : vaa . ChainID ( req . ChainId ) ,
2021-01-19 04:01:45 -08:00
NewContract : newContractAddress ,
2021-09-30 11:57:44 -07:00
} . Serialize ( ) )
return v , nil
}
// tokenBridgeRegisterChain converts a nodev1.TokenBridgeRegisterChain message to its canonical VAA representation.
// Returns an error if the data is invalid.
2022-04-19 08:59:00 -07:00
func tokenBridgeRegisterChain ( req * nodev1 . BridgeRegisterChain , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
2021-10-12 05:55:14 -07:00
if req . ChainId > math . MaxUint16 {
2021-09-30 11:57:44 -07:00
return nil , errors . New ( "invalid chain_id" )
}
b , err := hex . DecodeString ( req . EmitterAddress )
if err != nil {
return nil , errors . New ( "invalid emitter address encoding (expected hex)" )
}
if len ( b ) != 32 {
return nil , errors . New ( "invalid emitter address (expected 32 bytes)" )
2021-01-19 04:01:45 -08:00
}
2021-09-30 11:57:44 -07:00
emitterAddress := vaa . Address { }
2021-10-01 03:27:48 -07:00
copy ( emitterAddress [ : ] , b )
2021-09-30 11:57:44 -07:00
2022-04-19 08:59:00 -07:00
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
2021-09-30 11:57:44 -07:00
vaa . BodyTokenBridgeRegisterChain {
2021-10-01 03:26:05 -07:00
Module : req . Module ,
2021-09-30 11:57:44 -07:00
ChainID : vaa . ChainID ( req . ChainId ) ,
EmitterAddress : emitterAddress ,
} . Serialize ( ) )
2021-01-19 04:01:45 -08:00
return v , nil
}
2023-03-14 08:58:05 -07:00
// accountantModifyBalance converts a nodev1.AccountantModifyBalance message to its canonical VAA representation.
2023-02-13 16:40:11 -08:00
// Returns an error if the data is invalid.
2023-03-13 17:30:15 -07:00
func accountantModifyBalance ( req * nodev1 . AccountantModifyBalance , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
2023-02-13 16:40:11 -08:00
if req . TargetChainId > math . MaxUint16 {
return nil , errors . New ( "invalid target_chain_id" )
}
if req . ChainId > math . MaxUint16 {
return nil , errors . New ( "invalid chain_id" )
}
if req . TokenChain > math . MaxUint16 {
return nil , errors . New ( "invalid token_chain" )
}
b , err := hex . DecodeString ( req . TokenAddress )
if err != nil {
return nil , errors . New ( "invalid token address (expected hex)" )
}
if len ( b ) != 32 {
return nil , errors . New ( "invalid new token address (expected 32 bytes)" )
}
if len ( req . Reason ) > 32 {
return nil , errors . New ( "the reason should not be larger than 32 bytes" )
}
2023-02-14 10:01:15 -08:00
amount_big := big . NewInt ( 0 )
amount_big , ok := amount_big . SetString ( req . Amount , 10 )
if ! ok {
return nil , errors . New ( "invalid amount" )
}
// uint256 has Bytes32 method for easier serialization
2023-03-23 15:00:34 -07:00
amount , overflow := uint256 . FromBig ( amount_big )
if overflow {
return nil , errors . New ( "amount overflow" )
2023-02-13 16:40:11 -08:00
}
tokenAdress := vaa . Address { }
copy ( tokenAdress [ : ] , b )
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
2023-03-13 17:30:15 -07:00
vaa . BodyAccountantModifyBalance {
2023-02-13 16:40:11 -08:00
Module : req . Module ,
TargetChainID : vaa . ChainID ( req . TargetChainId ) ,
Sequence : req . Sequence ,
ChainId : vaa . ChainID ( req . ChainId ) ,
TokenChain : vaa . ChainID ( req . TokenChain ) ,
TokenAddress : tokenAdress ,
Kind : uint8 ( req . Kind ) ,
Amount : amount ,
Reason : req . Reason ,
} . Serialize ( ) )
return v , nil
}
node: add BridgeUpgradeContract governance VAA
Example VAA produced by the template:
(*vaa.VAA)(0xc0004f4510)({
Version: (uint8) 1,
GuardianSetIndex: (uint32) 0,
Signatures: ([]*vaa.Signature) (len=1 cap=1) {
(*vaa.Signature)(0xc0003b0370)({
Index: (uint8) 0,
Signature: (vaa.SignatureData) (len=65 cap=65) 0f97ec9093c21ccc4ce544898ed5c21b66ab4c90be894642fbb43474ed9fb48a26d6e12f3397b9fdab160fee64e797d26599a2a9d81a4bf4bc98970b5fa5122501
})
},
Timestamp: (time.Time) 1970-01-01 00:00:00 +0000 UTC,
Nonce: (uint32) 1375049878,
Sequence: (uint64) 3557202656914991802,
ConsistencyLevel: (uint8) 32,
EmitterChain: (vaa.ChainID) solana,
EmitterAddress: (vaa.Address) (len=32 cap=32) 0000000000000000000000000000000000000000000000000000000000000004,
Payload: ([]uint8) (len=67 cap=1000) {
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 54 6f 6b 65 6e 42 72 69 64 67 65 |.....TokenBridge|
00000020 02 00 05 00 00 00 00 00 00 00 00 00 00 00 00 02 |................|
00000030 90 fb 16 72 08 af 45 5b b1 37 78 01 63 b7 b7 a9 |...r..E[.7x.c...|
00000040 a1 0c 16 |...|
}
})
Change-Id: Ibe95db01e1bc0a9c36e1be06920a389db886fdd1
2021-10-08 10:41:43 -07:00
// tokenBridgeUpgradeContract converts a nodev1.TokenBridgeRegisterChain message to its canonical VAA representation.
// Returns an error if the data is invalid.
2022-04-19 08:59:00 -07:00
func tokenBridgeUpgradeContract ( req * nodev1 . BridgeUpgradeContract , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
node: add BridgeUpgradeContract governance VAA
Example VAA produced by the template:
(*vaa.VAA)(0xc0004f4510)({
Version: (uint8) 1,
GuardianSetIndex: (uint32) 0,
Signatures: ([]*vaa.Signature) (len=1 cap=1) {
(*vaa.Signature)(0xc0003b0370)({
Index: (uint8) 0,
Signature: (vaa.SignatureData) (len=65 cap=65) 0f97ec9093c21ccc4ce544898ed5c21b66ab4c90be894642fbb43474ed9fb48a26d6e12f3397b9fdab160fee64e797d26599a2a9d81a4bf4bc98970b5fa5122501
})
},
Timestamp: (time.Time) 1970-01-01 00:00:00 +0000 UTC,
Nonce: (uint32) 1375049878,
Sequence: (uint64) 3557202656914991802,
ConsistencyLevel: (uint8) 32,
EmitterChain: (vaa.ChainID) solana,
EmitterAddress: (vaa.Address) (len=32 cap=32) 0000000000000000000000000000000000000000000000000000000000000004,
Payload: ([]uint8) (len=67 cap=1000) {
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 54 6f 6b 65 6e 42 72 69 64 67 65 |.....TokenBridge|
00000020 02 00 05 00 00 00 00 00 00 00 00 00 00 00 00 02 |................|
00000030 90 fb 16 72 08 af 45 5b b1 37 78 01 63 b7 b7 a9 |...r..E[.7x.c...|
00000040 a1 0c 16 |...|
}
})
Change-Id: Ibe95db01e1bc0a9c36e1be06920a389db886fdd1
2021-10-08 10:41:43 -07:00
if req . TargetChainId > math . MaxUint16 {
return nil , errors . New ( "invalid target_chain_id" )
}
b , err := hex . DecodeString ( req . NewContract )
if err != nil {
return nil , errors . New ( "invalid new contract address (expected hex)" )
}
if len ( b ) != 32 {
return nil , errors . New ( "invalid new contract address (expected 32 bytes)" )
}
newContract := vaa . Address { }
copy ( newContract [ : ] , b )
2022-04-19 08:59:00 -07:00
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
node: add BridgeUpgradeContract governance VAA
Example VAA produced by the template:
(*vaa.VAA)(0xc0004f4510)({
Version: (uint8) 1,
GuardianSetIndex: (uint32) 0,
Signatures: ([]*vaa.Signature) (len=1 cap=1) {
(*vaa.Signature)(0xc0003b0370)({
Index: (uint8) 0,
Signature: (vaa.SignatureData) (len=65 cap=65) 0f97ec9093c21ccc4ce544898ed5c21b66ab4c90be894642fbb43474ed9fb48a26d6e12f3397b9fdab160fee64e797d26599a2a9d81a4bf4bc98970b5fa5122501
})
},
Timestamp: (time.Time) 1970-01-01 00:00:00 +0000 UTC,
Nonce: (uint32) 1375049878,
Sequence: (uint64) 3557202656914991802,
ConsistencyLevel: (uint8) 32,
EmitterChain: (vaa.ChainID) solana,
EmitterAddress: (vaa.Address) (len=32 cap=32) 0000000000000000000000000000000000000000000000000000000000000004,
Payload: ([]uint8) (len=67 cap=1000) {
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 54 6f 6b 65 6e 42 72 69 64 67 65 |.....TokenBridge|
00000020 02 00 05 00 00 00 00 00 00 00 00 00 00 00 00 02 |................|
00000030 90 fb 16 72 08 af 45 5b b1 37 78 01 63 b7 b7 a9 |...r..E[.7x.c...|
00000040 a1 0c 16 |...|
}
})
Change-Id: Ibe95db01e1bc0a9c36e1be06920a389db886fdd1
2021-10-08 10:41:43 -07:00
vaa . BodyTokenBridgeUpgradeContract {
Module : req . Module ,
TargetChainID : vaa . ChainID ( req . TargetChainId ) ,
NewContract : newContract ,
} . Serialize ( ) )
return v , nil
}
2022-12-06 11:10:32 -08:00
// wormchainStoreCode converts a nodev1.WormchainStoreCode to its canonical VAA representation
// Returns an error if the data is invalid
func wormchainStoreCode ( req * nodev1 . WormchainStoreCode , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
// validate the length of the hex passed in
b , err := hex . DecodeString ( req . WasmHash )
if err != nil {
return nil , fmt . Errorf ( "invalid cosmwasm bytecode hash (expected hex): %w" , err )
}
if len ( b ) != 32 {
return nil , fmt . Errorf ( "invalid cosmwasm bytecode hash (expected 32 bytes but received %d bytes)" , len ( b ) )
}
wasmHash := [ 32 ] byte { }
copy ( wasmHash [ : ] , b )
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
vaa . BodyWormchainStoreCode {
WasmHash : wasmHash ,
} . Serialize ( ) )
return v , nil
}
// wormchainInstantiateContract converts a nodev1.WormchainInstantiateContract to its canonical VAA representation
// Returns an error if the data is invalid
2023-05-03 15:26:44 -07:00
func wormchainInstantiateContract ( req * nodev1 . WormchainInstantiateContract , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) { //nolint:unparam // error is always nil but kept to mirror function signature of other functions
2022-12-06 11:10:32 -08:00
instantiationParams_hash := vaa . CreateInstatiateCosmwasmContractHash ( req . CodeId , req . Label , [ ] byte ( req . InstantiationMsg ) )
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
vaa . BodyWormchainInstantiateContract {
InstantiationParamsHash : instantiationParams_hash ,
} . Serialize ( ) )
return v , nil
}
2023-02-02 10:49:52 -08:00
// wormchainMigrateContract converts a nodev1.WormchainMigrateContract to its canonical VAA representation
2023-05-03 15:26:44 -07:00
func wormchainMigrateContract ( req * nodev1 . WormchainMigrateContract , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) { //nolint:unparam // error is always nil but kept to mirror function signature of other functions
2023-02-02 10:49:52 -08:00
instantiationParams_hash := vaa . CreateMigrateCosmwasmContractHash ( req . CodeId , req . Contract , [ ] byte ( req . InstantiationMsg ) )
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
2023-02-06 08:58:42 -08:00
vaa . BodyWormchainMigrateContract {
MigrationParamsHash : instantiationParams_hash ,
2023-02-02 10:49:52 -08:00
} . Serialize ( ) )
return v , nil
}
2023-03-06 11:23:48 -08:00
// circleIntegrationUpdateWormholeFinality converts a nodev1.CircleIntegrationUpdateWormholeFinality to its canonical VAA representation
// Returns an error if the data is invalid
func circleIntegrationUpdateWormholeFinality ( req * nodev1 . CircleIntegrationUpdateWormholeFinality , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
2023-03-16 07:13:50 -07:00
if req . TargetChainId > math . MaxUint16 {
return nil , fmt . Errorf ( "invalid target chain id, must be <= %d" , math . MaxUint16 )
}
2023-03-06 11:23:48 -08:00
if req . Finality > math . MaxUint8 {
return nil , fmt . Errorf ( "invalid finality, must be <= %d" , math . MaxUint8 )
}
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
vaa . BodyCircleIntegrationUpdateWormholeFinality {
2023-03-16 07:13:50 -07:00
TargetChainID : vaa . ChainID ( req . TargetChainId ) ,
Finality : uint8 ( req . Finality ) ,
2023-03-06 11:23:48 -08:00
} . Serialize ( ) )
return v , nil
}
// circleIntegrationRegisterEmitterAndDomain converts a nodev1.CircleIntegrationRegisterEmitterAndDomain to its canonical VAA representation
// Returns an error if the data is invalid
func circleIntegrationRegisterEmitterAndDomain ( req * nodev1 . CircleIntegrationRegisterEmitterAndDomain , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
2023-03-16 07:13:50 -07:00
if req . TargetChainId > math . MaxUint16 {
return nil , fmt . Errorf ( "invalid target chain id, must be <= %d" , math . MaxUint16 )
}
2023-03-06 11:23:48 -08:00
if req . ForeignEmitterChainId > math . MaxUint16 {
return nil , fmt . Errorf ( "invalid foreign emitter chain id, must be <= %d" , math . MaxUint16 )
}
b , err := hex . DecodeString ( req . ForeignEmitterAddress )
if err != nil {
return nil , errors . New ( "invalid foreign emitter address encoding (expected hex)" )
}
if len ( b ) != 32 {
return nil , errors . New ( "invalid foreign emitter address (expected 32 bytes)" )
}
foreignEmitterAddress := vaa . Address { }
copy ( foreignEmitterAddress [ : ] , b )
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
vaa . BodyCircleIntegrationRegisterEmitterAndDomain {
2023-03-16 07:13:50 -07:00
TargetChainID : vaa . ChainID ( req . TargetChainId ) ,
2023-03-06 11:23:48 -08:00
ForeignEmitterChainId : vaa . ChainID ( req . ForeignEmitterChainId ) ,
ForeignEmitterAddress : foreignEmitterAddress ,
CircleDomain : req . CircleDomain ,
} . Serialize ( ) )
return v , nil
}
// circleIntegrationUpgradeContractImplementation converts a nodev1.CircleIntegrationUpgradeContractImplementation to its canonical VAA representation
// Returns an error if the data is invalid
func circleIntegrationUpgradeContractImplementation ( req * nodev1 . CircleIntegrationUpgradeContractImplementation , timestamp time . Time , guardianSetIndex uint32 , nonce uint32 , sequence uint64 ) ( * vaa . VAA , error ) {
2023-03-16 07:13:50 -07:00
if req . TargetChainId > math . MaxUint16 {
return nil , fmt . Errorf ( "invalid target chain id, must be <= %d" , math . MaxUint16 )
}
2023-03-06 11:23:48 -08:00
b , err := hex . DecodeString ( req . NewImplementationAddress )
if err != nil {
return nil , errors . New ( "invalid new implementation address encoding (expected hex)" )
}
if len ( b ) != 32 {
return nil , errors . New ( "invalid new implementation address (expected 32 bytes)" )
}
newImplementationAddress := vaa . Address { }
copy ( newImplementationAddress [ : ] , b )
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
vaa . BodyCircleIntegrationUpgradeContractImplementation {
2023-03-16 07:13:50 -07:00
TargetChainID : vaa . ChainID ( req . TargetChainId ) ,
2023-03-06 11:23:48 -08:00
NewImplementationAddress : newImplementationAddress ,
} . Serialize ( ) )
return v , nil
}
2023-05-12 03:11:21 -07:00
func ibcReceiverUpdateChannelChain (
req * nodev1 . IbcReceiverUpdateChannelChain ,
timestamp time . Time ,
guardianSetIndex uint32 ,
nonce uint32 ,
sequence uint64 ,
) ( * vaa . VAA , error ) {
// validate parameters
if req . TargetChainId > math . MaxUint16 {
return nil , fmt . Errorf ( "invalid target chain id, must be <= %d" , math . MaxUint16 )
}
if req . ChainId > math . MaxUint16 {
return nil , fmt . Errorf ( "invalid chain id, must be <= %d" , math . MaxUint16 )
}
if len ( req . ChannelId ) > 64 {
return nil , fmt . Errorf ( "invalid channel ID length, must be <= 64" )
}
channelId := vaa . LeftPadIbcChannelId ( req . ChannelId )
// create governance VAA
v := vaa . CreateGovernanceVAA ( timestamp , nonce , sequence , guardianSetIndex ,
vaa . BodyIbcReceiverUpdateChannelChain {
TargetChainId : vaa . ChainID ( req . TargetChainId ) ,
ChannelId : channelId ,
ChainId : vaa . ChainID ( req . ChainId ) ,
} . Serialize ( ) )
return v , nil
}
2021-01-19 04:01:45 -08:00
func ( s * nodePrivilegedService ) InjectGovernanceVAA ( ctx context . Context , req * nodev1 . InjectGovernanceVAARequest ) ( * nodev1 . InjectGovernanceVAAResponse , error ) {
s . logger . Info ( "governance VAA injected via admin socket" , zap . String ( "request" , req . String ( ) ) )
2020-11-19 03:53:19 -08:00
2021-01-19 04:01:45 -08:00
var (
v * vaa . VAA
err error
)
2020-11-19 03:53:19 -08:00
2022-04-19 08:59:00 -07:00
timestamp := time . Unix ( int64 ( req . Timestamp ) , 0 )
2021-10-29 08:50:46 -07:00
digests := make ( [ ] [ ] byte , len ( req . Messages ) )
for i , message := range req . Messages {
switch payload := message . Payload . ( type ) {
case * nodev1 . GovernanceMessage_GuardianSet :
2022-04-19 08:59:00 -07:00
v , err = adminGuardianSetUpdateToVAA ( payload . GuardianSet , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2021-10-29 08:50:46 -07:00
case * nodev1 . GovernanceMessage_ContractUpgrade :
2022-04-19 08:59:00 -07:00
v , err = adminContractUpgradeToVAA ( payload . ContractUpgrade , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2021-10-29 08:50:46 -07:00
case * nodev1 . GovernanceMessage_BridgeRegisterChain :
2022-04-19 08:59:00 -07:00
v , err = tokenBridgeRegisterChain ( payload . BridgeRegisterChain , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2021-10-29 08:50:46 -07:00
case * nodev1 . GovernanceMessage_BridgeContractUpgrade :
2022-04-19 08:59:00 -07:00
v , err = tokenBridgeUpgradeContract ( payload . BridgeContractUpgrade , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2023-03-13 17:30:15 -07:00
case * nodev1 . GovernanceMessage_AccountantModifyBalance :
v , err = accountantModifyBalance ( payload . AccountantModifyBalance , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2022-12-06 11:10:32 -08:00
case * nodev1 . GovernanceMessage_WormchainStoreCode :
v , err = wormchainStoreCode ( payload . WormchainStoreCode , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
case * nodev1 . GovernanceMessage_WormchainInstantiateContract :
v , err = wormchainInstantiateContract ( payload . WormchainInstantiateContract , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2023-02-02 10:49:52 -08:00
case * nodev1 . GovernanceMessage_WormchainMigrateContract :
v , err = wormchainMigrateContract ( payload . WormchainMigrateContract , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2023-03-06 11:23:48 -08:00
case * nodev1 . GovernanceMessage_CircleIntegrationUpdateWormholeFinality :
v , err = circleIntegrationUpdateWormholeFinality ( payload . CircleIntegrationUpdateWormholeFinality , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
case * nodev1 . GovernanceMessage_CircleIntegrationRegisterEmitterAndDomain :
v , err = circleIntegrationRegisterEmitterAndDomain ( payload . CircleIntegrationRegisterEmitterAndDomain , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
case * nodev1 . GovernanceMessage_CircleIntegrationUpgradeContractImplementation :
v , err = circleIntegrationUpgradeContractImplementation ( payload . CircleIntegrationUpgradeContractImplementation , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2023-05-12 03:11:21 -07:00
case * nodev1 . GovernanceMessage_IbcReceiverUpdateChannelChain :
v , err = ibcReceiverUpdateChannelChain ( payload . IbcReceiverUpdateChannelChain , timestamp , req . CurrentSetIndex , message . Nonce , message . Sequence )
2021-10-29 08:50:46 -07:00
default :
panic ( fmt . Sprintf ( "unsupported VAA type: %T" , payload ) )
}
if err != nil {
return nil , status . Error ( codes . InvalidArgument , err . Error ( ) )
}
2020-11-19 03:53:19 -08:00
2021-10-29 08:50:46 -07:00
// Generate digest of the unsigned VAA.
2023-02-22 18:31:15 -08:00
digest := v . SigningDigest ( )
2020-11-19 03:53:19 -08:00
2021-10-29 08:50:46 -07:00
s . logger . Info ( "governance VAA constructed" ,
zap . Any ( "vaa" , v ) ,
zap . String ( "digest" , digest . String ( ) ) ,
)
s . injectC <- v
digests [ i ] = digest . Bytes ( )
}
2020-11-19 03:53:19 -08:00
2021-10-29 08:50:46 -07:00
return & nodev1 . InjectGovernanceVAAResponse { Digests : digests } , nil
2020-11-19 03:53:19 -08:00
}
2021-12-19 08:27:06 -08:00
// fetchMissing attempts to backfill a gap by fetching and storing missing signed VAAs from the network.
2021-12-18 14:39:30 -08:00
// Returns true if the gap was filled, false otherwise.
func ( s * nodePrivilegedService ) fetchMissing (
ctx context . Context ,
nodes [ ] string ,
c * http . Client ,
chain vaa . ChainID ,
addr string ,
seq uint64 ) ( bool , error ) {
// shuffle the list of public RPC endpoints
rand . Shuffle ( len ( nodes ) , func ( i , j int ) {
nodes [ i ] , nodes [ j ] = nodes [ j ] , nodes [ i ]
} )
ctx , cancel := context . WithTimeout ( ctx , time . Second )
defer cancel ( )
for _ , node := range nodes {
req , err := http . NewRequestWithContext ( ctx , "GET" , fmt . Sprintf (
"%s/v1/signed_vaa/%d/%s/%d" , node , chain , addr , seq ) , nil )
if err != nil {
return false , fmt . Errorf ( "failed to create request: %w" , err )
}
resp , err := c . Do ( req )
if err != nil {
s . logger . Warn ( "failed to fetch missing VAA" ,
zap . String ( "node" , node ) ,
zap . String ( "chain" , chain . String ( ) ) ,
zap . String ( "address" , addr ) ,
zap . Uint64 ( "sequence" , seq ) ,
zap . Error ( err ) ,
)
continue
}
switch resp . StatusCode {
case http . StatusNotFound :
resp . Body . Close ( )
continue
case http . StatusOK :
2021-12-19 08:27:06 -08:00
type getVaaResp struct {
VaaBytes string ` json:"vaaBytes" `
}
var respBody getVaaResp
if err := json . NewDecoder ( resp . Body ) . Decode ( & respBody ) ; err != nil {
resp . Body . Close ( )
s . logger . Warn ( "failed to decode VAA response" ,
zap . String ( "node" , node ) ,
zap . String ( "chain" , chain . String ( ) ) ,
zap . String ( "address" , addr ) ,
zap . Uint64 ( "sequence" , seq ) ,
zap . Error ( err ) ,
)
continue
}
// base64 decode the VAA bytes
vaaBytes , err := base64 . StdEncoding . DecodeString ( respBody . VaaBytes )
if err != nil {
resp . Body . Close ( )
s . logger . Warn ( "failed to decode VAA body" ,
zap . String ( "node" , node ) ,
zap . String ( "chain" , chain . String ( ) ) ,
zap . String ( "address" , addr ) ,
zap . Uint64 ( "sequence" , seq ) ,
zap . Error ( err ) ,
)
continue
}
2021-12-18 14:39:30 -08:00
s . logger . Info ( "backfilled VAA" ,
zap . Uint16 ( "chain" , uint16 ( chain ) ) ,
zap . String ( "address" , addr ) ,
zap . Uint64 ( "sequence" , seq ) ,
2021-12-19 08:27:06 -08:00
zap . Int ( "numBytes" , len ( vaaBytes ) ) ,
2021-12-18 14:39:30 -08:00
)
2021-12-19 08:27:06 -08:00
// Inject into the gossip signed VAA receive path.
// This has the same effect as if the VAA was received from the network
// (verifying signature, publishing to BigTable, storing in local DB...).
s . signedInC <- & gossipv1 . SignedVAAWithQuorum {
Vaa : vaaBytes ,
}
2021-12-18 14:39:30 -08:00
resp . Body . Close ( )
return true , nil
default :
resp . Body . Close ( )
return false , fmt . Errorf ( "unexpected response status: %d" , resp . StatusCode )
}
}
return false , nil
}
2021-10-04 04:42:56 -07:00
func ( s * nodePrivilegedService ) FindMissingMessages ( ctx context . Context , req * nodev1 . FindMissingMessagesRequest ) ( * nodev1 . FindMissingMessagesResponse , error ) {
b , err := hex . DecodeString ( req . EmitterAddress )
if err != nil {
return nil , status . Errorf ( codes . InvalidArgument , "invalid emitter address encoding: %v" , err )
}
emitterAddress := vaa . Address { }
copy ( emitterAddress [ : ] , b )
ids , first , last , err := s . db . FindEmitterSequenceGap ( db . VAAID {
EmitterChain : vaa . ChainID ( req . EmitterChain ) ,
EmitterAddress : emitterAddress ,
} )
if err != nil {
return nil , status . Errorf ( codes . Internal , "database operation failed: %v" , err )
}
2021-12-18 14:39:30 -08:00
if req . RpcBackfill {
c := & http . Client { }
unfilled := make ( [ ] uint64 , 0 , len ( ids ) )
for _ , id := range ids {
if ok , err := s . fetchMissing ( ctx , req . BackfillNodes , c , vaa . ChainID ( req . EmitterChain ) , emitterAddress . String ( ) , id ) ; err != nil {
return nil , status . Errorf ( codes . Internal , "failed to backfill VAA: %v" , err )
} else if ok {
continue
}
unfilled = append ( unfilled , id )
}
ids = unfilled
}
2021-10-04 04:42:56 -07:00
resp := make ( [ ] string , len ( ids ) )
for i , v := range ids {
resp [ i ] = fmt . Sprintf ( "%d/%s/%d" , req . EmitterChain , emitterAddress , v )
}
return & nodev1 . FindMissingMessagesResponse {
MissingMessages : resp ,
FirstSequence : first ,
LastSequence : last ,
} , nil
}
2023-01-20 13:15:13 -08:00
func adminServiceRunnable (
logger * zap . Logger ,
socketPath string ,
injectC chan <- * vaa . VAA ,
signedInC chan <- * gossipv1 . SignedVAAWithQuorum ,
obsvReqSendC chan <- * gossipv1 . ObservationRequest ,
db * db . Database ,
gst * common . GuardianSetState ,
gov * governor . ChainGovernor ,
gk * ecdsa . PrivateKey ,
ethRpc * string ,
ethContract * string ,
2023-04-03 07:24:17 -07:00
testnetMode bool ,
2023-01-20 13:15:13 -08:00
) ( supervisor . Runnable , error ) {
2020-11-19 03:53:19 -08:00
// Delete existing UNIX socket, if present.
fi , err := os . Stat ( socketPath )
if err == nil {
fmode := fi . Mode ( )
if fmode & os . ModeType == os . ModeSocket {
err = os . Remove ( socketPath )
if err != nil {
return nil , fmt . Errorf ( "failed to remove existing socket at %s: %w" , socketPath , err )
}
} else {
return nil , fmt . Errorf ( "%s is not a UNIX socket" , socketPath )
}
}
// Create a new UNIX socket and listen to it.
// The socket is created with the default umask. We set a restrictive umask in setRestrictiveUmask
// to ensure that any files we create are only readable by the user - this is much harder to mess up.
// The umask avoids a race condition between file creation and chmod.
laddr , err := net . ResolveUnixAddr ( "unix" , socketPath )
2021-08-30 11:40:38 -07:00
if err != nil {
return nil , fmt . Errorf ( "invalid listen address: %v" , err )
}
2020-11-19 03:53:19 -08:00
l , err := net . ListenUnix ( "unix" , laddr )
if err != nil {
return nil , fmt . Errorf ( "failed to listen on %s: %w" , socketPath , err )
}
2020-11-24 00:48:44 -08:00
logger . Info ( "admin server listening on" , zap . String ( "path" , socketPath ) )
2020-11-19 03:53:19 -08:00
2023-01-10 08:54:35 -08:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , time . Second * 5 )
defer cancel ( )
var evmConnector connectors . Connector
if ethRPC != nil && ethContract != nil {
contract := ethcommon . HexToAddress ( * ethContract )
evmConnector , err = connectors . NewEthereumConnector ( ctx , "eth" , * ethRpc , contract , logger )
if err != nil {
return nil , fmt . Errorf ( "failed to connecto to ethereum" )
}
}
2020-11-19 03:53:19 -08:00
nodeService := & nodePrivilegedService {
2023-01-10 08:54:35 -08:00
db : db ,
injectC : injectC ,
obsvReqSendC : obsvReqSendC ,
logger : logger . Named ( "adminservice" ) ,
signedInC : signedInC ,
governor : gov ,
gk : gk ,
guardianAddress : ethcrypto . PubkeyToAddress ( gk . PublicKey ) ,
evmConnector : evmConnector ,
2023-04-03 07:24:17 -07:00
testnetMode : testnetMode ,
2020-11-19 03:53:19 -08:00
}
2022-07-19 11:08:06 -07:00
publicrpcService := publicrpc . NewPublicrpcServer ( logger , db , gst , gov )
2021-07-22 04:31:46 -07:00
2023-03-01 07:10:04 -08:00
grpcServer := common . NewInstrumentedGRPCServer ( logger , common . GrpcLogDetailMinimal )
2021-08-21 15:34:58 -07:00
nodev1 . RegisterNodePrivilegedServiceServer ( grpcServer , nodeService )
publicrpcv1 . RegisterPublicRPCServiceServer ( grpcServer , publicrpcService )
2020-11-19 03:53:19 -08:00
return supervisor . GRPCServer ( grpcServer , l , false ) , nil
}
2021-12-20 13:23:45 -08:00
func ( s * nodePrivilegedService ) SendObservationRequest ( ctx context . Context , req * nodev1 . SendObservationRequestRequest ) ( * nodev1 . SendObservationRequestResponse , error ) {
2022-08-15 05:33:45 -07:00
if err := common . PostObservationRequest ( s . obsvReqSendC , req . ObservationRequest ) ; err != nil {
return nil , err
}
2021-12-20 13:23:45 -08:00
s . logger . Info ( "sent observation request" , zap . Any ( "request" , req . ObservationRequest ) )
return & nodev1 . SendObservationRequestResponse { } , nil
}
2022-07-19 11:08:06 -07:00
func ( s * nodePrivilegedService ) ChainGovernorStatus ( ctx context . Context , req * nodev1 . ChainGovernorStatusRequest ) ( * nodev1 . ChainGovernorStatusResponse , error ) {
if s . governor == nil {
return nil , fmt . Errorf ( "chain governor is not enabled" )
}
return & nodev1 . ChainGovernorStatusResponse {
Response : s . governor . Status ( ) ,
} , nil
}
func ( s * nodePrivilegedService ) ChainGovernorReload ( ctx context . Context , req * nodev1 . ChainGovernorReloadRequest ) ( * nodev1 . ChainGovernorReloadResponse , error ) {
if s . governor == nil {
return nil , fmt . Errorf ( "chain governor is not enabled" )
}
resp , err := s . governor . Reload ( )
if err != nil {
return nil , err
}
return & nodev1 . ChainGovernorReloadResponse {
Response : resp ,
} , nil
}
func ( s * nodePrivilegedService ) ChainGovernorDropPendingVAA ( ctx context . Context , req * nodev1 . ChainGovernorDropPendingVAARequest ) ( * nodev1 . ChainGovernorDropPendingVAAResponse , error ) {
if s . governor == nil {
return nil , fmt . Errorf ( "chain governor is not enabled" )
}
if len ( req . VaaId ) == 0 {
return nil , fmt . Errorf ( "the VAA id must be specified as \"chainId/emitterAddress/seqNum\"" )
}
resp , err := s . governor . DropPendingVAA ( req . VaaId )
if err != nil {
return nil , err
}
return & nodev1 . ChainGovernorDropPendingVAAResponse {
Response : resp ,
} , nil
}
func ( s * nodePrivilegedService ) ChainGovernorReleasePendingVAA ( ctx context . Context , req * nodev1 . ChainGovernorReleasePendingVAARequest ) ( * nodev1 . ChainGovernorReleasePendingVAAResponse , error ) {
if s . governor == nil {
return nil , fmt . Errorf ( "chain governor is not enabled" )
}
if len ( req . VaaId ) == 0 {
return nil , fmt . Errorf ( "the VAA id must be specified as \"chainId/emitterAddress/seqNum\"" )
}
resp , err := s . governor . ReleasePendingVAA ( req . VaaId )
if err != nil {
return nil , err
}
return & nodev1 . ChainGovernorReleasePendingVAAResponse {
Response : resp ,
} , nil
}
2022-08-30 09:28:18 -07:00
func ( s * nodePrivilegedService ) ChainGovernorResetReleaseTimer ( ctx context . Context , req * nodev1 . ChainGovernorResetReleaseTimerRequest ) ( * nodev1 . ChainGovernorResetReleaseTimerResponse , error ) {
if s . governor == nil {
return nil , fmt . Errorf ( "chain governor is not enabled" )
}
if len ( req . VaaId ) == 0 {
return nil , fmt . Errorf ( "the VAA id must be specified as \"chainId/emitterAddress/seqNum\"" )
}
resp , err := s . governor . ResetReleaseTimer ( req . VaaId )
if err != nil {
return nil , err
}
return & nodev1 . ChainGovernorResetReleaseTimerResponse {
Response : resp ,
} , nil
}
2022-09-26 07:04:30 -07:00
func ( s * nodePrivilegedService ) PurgePythNetVaas ( ctx context . Context , req * nodev1 . PurgePythNetVaasRequest ) ( * nodev1 . PurgePythNetVaasResponse , error ) {
prefix := db . VAAID { EmitterChain : vaa . ChainIDPythNet }
oldestTime := time . Now ( ) . Add ( - time . Hour * 24 * time . Duration ( req . DaysOld ) )
resp , err := s . db . PurgeVaas ( prefix , oldestTime , req . LogOnly )
if err != nil {
return nil , err
}
return & nodev1 . PurgePythNetVaasResponse {
Response : resp ,
} , nil
}
2023-01-10 08:54:35 -08:00
func ( s * nodePrivilegedService ) SignExistingVAA ( ctx context . Context , req * nodev1 . SignExistingVAARequest ) ( * nodev1 . SignExistingVAAResponse , error ) {
v , err := vaa . Unmarshal ( req . Vaa )
if err != nil {
return nil , fmt . Errorf ( "failed to unmarshal VAA: %w" , err )
}
if req . NewGuardianSetIndex <= v . GuardianSetIndex {
return nil , errors . New ( "new guardian set index must be higher than provided VAA" )
}
if s . evmConnector == nil {
return nil , errors . New ( "the node needs to have an Ethereum connection configured to sign existing VAAs" )
}
var gs * common . GuardianSet
if cachedGs , exists := s . gsCache . Load ( v . GuardianSetIndex ) ; exists {
2023-05-03 15:26:44 -07:00
var ok bool
gs , ok = cachedGs . ( * common . GuardianSet )
if ! ok {
return nil , fmt . Errorf ( "internal error" )
}
2023-01-10 08:54:35 -08:00
} else {
evmGs , err := s . evmConnector . GetGuardianSet ( ctx , v . GuardianSetIndex )
if err != nil {
return nil , fmt . Errorf ( "failed to load guardian set [%d]: %w" , v . GuardianSetIndex , err )
}
gs = & common . GuardianSet {
Keys : evmGs . Keys ,
Index : v . GuardianSetIndex ,
}
s . gsCache . Store ( v . GuardianSetIndex , gs )
}
if slices . Index ( gs . Keys , s . guardianAddress ) != - 1 {
return nil , fmt . Errorf ( "local guardian is already on the old set" )
}
// Verify VAA
err = v . Verify ( gs . Keys )
if err != nil {
return nil , fmt . Errorf ( "failed to verify existing VAA: %w" , err )
}
if len ( req . NewGuardianAddrs ) > 255 {
return nil , errors . New ( "new guardian set has too many guardians" )
}
newGS := make ( [ ] ethcommon . Address , len ( req . NewGuardianAddrs ) )
for i , guardianString := range req . NewGuardianAddrs {
guardianAddress := ethcommon . HexToAddress ( guardianString )
newGS [ i ] = guardianAddress
}
// Make sure there are no duplicates. Compact needs to take a sorted slice to remove all duplicates.
newGSSorted := slices . Clone ( newGS )
slices . SortFunc ( newGSSorted , func ( a , b ethcommon . Address ) bool {
return bytes . Compare ( a [ : ] , b [ : ] ) < 0
} )
newGsLen := len ( newGSSorted )
if len ( slices . Compact ( newGSSorted ) ) != newGsLen {
return nil , fmt . Errorf ( "duplicate guardians in the guardian set" )
}
localGuardianIndex := slices . Index ( newGS , s . guardianAddress )
if localGuardianIndex == - 1 {
return nil , fmt . Errorf ( "local guardian is not a member of the new guardian set" )
}
newVAA := & vaa . VAA {
Version : v . Version ,
// Set the new guardian set index
GuardianSetIndex : req . NewGuardianSetIndex ,
// Signatures will be repopulated
Signatures : nil ,
Timestamp : v . Timestamp ,
Nonce : v . Nonce ,
Sequence : v . Sequence ,
ConsistencyLevel : v . ConsistencyLevel ,
EmitterChain : v . EmitterChain ,
EmitterAddress : v . EmitterAddress ,
Payload : v . Payload ,
}
// Copy original VAA signatures
for _ , sig := range v . Signatures {
signerAddress := gs . Keys [ sig . Index ]
newIndex := slices . Index ( newGS , signerAddress )
// Guardian is not part of the new set
if newIndex == - 1 {
continue
}
newVAA . Signatures = append ( newVAA . Signatures , & vaa . Signature {
Index : uint8 ( newIndex ) ,
Signature : sig . Signature ,
} )
}
// Add our own signature only if the new guardian set would reach quorum
if vaa . CalculateQuorum ( len ( newGS ) ) > len ( newVAA . Signatures ) + 1 {
return nil , errors . New ( "cannot reach quorum on new guardian set with the local signature" )
}
// Add local signature
newVAA . AddSignature ( s . gk , uint8 ( localGuardianIndex ) )
// Sort VAA signatures by guardian ID
slices . SortFunc ( newVAA . Signatures , func ( a , b * vaa . Signature ) bool {
return a . Index < b . Index
} )
newVAABytes , err := newVAA . Marshal ( )
if err != nil {
return nil , fmt . Errorf ( "failed to marshal new VAA: %w" , err )
}
return & nodev1 . SignExistingVAAResponse { Vaa : newVAABytes } , nil
}
2023-02-03 11:12:01 -08:00
func ( s * nodePrivilegedService ) DumpRPCs ( ctx context . Context , req * nodev1 . DumpRPCsRequest ) ( * nodev1 . DumpRPCsResponse , error ) {
rpcMap := make ( map [ string ] string )
rpcMap [ "acalaRPC" ] = * acalaRPC
rpcMap [ "algorandIndexerRPC" ] = * algorandIndexerRPC
rpcMap [ "algorandAlgodRPC" ] = * algorandAlgodRPC
rpcMap [ "aptosRPC" ] = * aptosRPC
rpcMap [ "arbitrumRPC" ] = * arbitrumRPC
rpcMap [ "auroraRPC" ] = * auroraRPC
rpcMap [ "avalancheRPC" ] = * avalancheRPC
2023-02-23 15:37:35 -08:00
rpcMap [ "baseRPC" ] = * baseRPC
2023-02-03 11:12:01 -08:00
rpcMap [ "bscRPC" ] = * bscRPC
rpcMap [ "celoRPC" ] = * celoRPC
rpcMap [ "ethRPC" ] = * ethRPC
rpcMap [ "fantomRPC" ] = * fantomRPC
2023-04-17 07:54:36 -07:00
rpcMap [ "ibcLCD" ] = * ibcLCD
rpcMap [ "ibcWS" ] = * ibcWS
2023-02-03 11:12:01 -08:00
rpcMap [ "karuraRPC" ] = * karuraRPC
rpcMap [ "klaytnRPC" ] = * klaytnRPC
rpcMap [ "moonbeamRPC" ] = * moonbeamRPC
rpcMap [ "nearRPC" ] = * nearRPC
rpcMap [ "neonRPC" ] = * neonRPC
rpcMap [ "oasisRPC" ] = * oasisRPC
2023-02-15 10:36:03 -08:00
rpcMap [ "optimismRPC" ] = * optimismRPC
2023-02-03 11:12:01 -08:00
rpcMap [ "polygonRPC" ] = * polygonRPC
rpcMap [ "pythnetRPC" ] = * pythnetRPC
rpcMap [ "pythnetWS" ] = * pythnetWS
2023-04-18 06:34:01 -07:00
rpcMap [ "sei" ] = "IBC"
2023-04-03 07:24:17 -07:00
if s . testnetMode {
rpcMap [ "sepoliaRPC" ] = * sepoliaRPC
}
2023-02-03 11:12:01 -08:00
rpcMap [ "solanaRPC" ] = * solanaRPC
2023-05-02 07:24:57 -07:00
rpcMap [ "suiRPC" ] = * suiRPC
2023-02-03 11:12:01 -08:00
rpcMap [ "terraWS" ] = * terraWS
rpcMap [ "terraLCD" ] = * terraLCD
rpcMap [ "terra2WS" ] = * terra2WS
rpcMap [ "terra2LCD" ] = * terra2LCD
rpcMap [ "wormchainWS" ] = * wormchainWS
rpcMap [ "wormchainLCD" ] = * wormchainLCD
rpcMap [ "xplaWS" ] = * xplaWS
rpcMap [ "xplaLCD" ] = * xplaLCD
return & nodev1 . DumpRPCsResponse {
Response : rpcMap ,
} , nil
}