adminserver.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. package adminrpc
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/ecdsa"
  6. "encoding/base64"
  7. "encoding/hex"
  8. "encoding/json"
  9. "errors"
  10. "fmt"
  11. "math"
  12. "math/big"
  13. "math/rand"
  14. "net/http"
  15. "sync"
  16. "time"
  17. "github.com/certusone/wormhole/node/pkg/watchers/evm/connectors"
  18. "github.com/holiman/uint256"
  19. "golang.org/x/exp/slices"
  20. "github.com/certusone/wormhole/node/pkg/db"
  21. "github.com/certusone/wormhole/node/pkg/governor"
  22. gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
  23. ethcommon "github.com/ethereum/go-ethereum/common"
  24. "go.uber.org/zap"
  25. "google.golang.org/grpc/codes"
  26. "google.golang.org/grpc/status"
  27. "github.com/certusone/wormhole/node/pkg/common"
  28. nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
  29. "github.com/wormhole-foundation/wormhole/sdk/vaa"
  30. sdktypes "github.com/cosmos/cosmos-sdk/types"
  31. )
  32. type nodePrivilegedService struct {
  33. nodev1.UnimplementedNodePrivilegedServiceServer
  34. db *db.Database
  35. injectC chan<- *vaa.VAA
  36. obsvReqSendC chan<- *gossipv1.ObservationRequest
  37. logger *zap.Logger
  38. signedInC chan<- *gossipv1.SignedVAAWithQuorum
  39. governor *governor.ChainGovernor
  40. evmConnector connectors.Connector
  41. gsCache sync.Map
  42. gk *ecdsa.PrivateKey
  43. guardianAddress ethcommon.Address
  44. rpcMap map[string]string
  45. }
  46. func NewPrivService(
  47. db *db.Database,
  48. injectC chan<- *vaa.VAA,
  49. obsvReqSendC chan<- *gossipv1.ObservationRequest,
  50. logger *zap.Logger,
  51. signedInC chan<- *gossipv1.SignedVAAWithQuorum,
  52. governor *governor.ChainGovernor,
  53. evmConnector connectors.Connector,
  54. gk *ecdsa.PrivateKey,
  55. guardianAddress ethcommon.Address,
  56. rpcMap map[string]string,
  57. ) *nodePrivilegedService {
  58. return &nodePrivilegedService{
  59. db: db,
  60. injectC: injectC,
  61. obsvReqSendC: obsvReqSendC,
  62. logger: logger,
  63. signedInC: signedInC,
  64. governor: governor,
  65. evmConnector: evmConnector,
  66. gk: gk,
  67. guardianAddress: guardianAddress,
  68. rpcMap: rpcMap,
  69. }
  70. }
  71. // adminGuardianSetUpdateToVAA converts a nodev1.GuardianSetUpdate message to its canonical VAA representation.
  72. // Returns an error if the data is invalid.
  73. func adminGuardianSetUpdateToVAA(req *nodev1.GuardianSetUpdate, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  74. if len(req.Guardians) == 0 {
  75. return nil, errors.New("empty guardian set specified")
  76. }
  77. if len(req.Guardians) > common.MaxGuardianCount {
  78. return nil, fmt.Errorf("too many guardians - %d, maximum is %d", len(req.Guardians), common.MaxGuardianCount)
  79. }
  80. addrs := make([]ethcommon.Address, len(req.Guardians))
  81. for i, g := range req.Guardians {
  82. if !ethcommon.IsHexAddress(g.Pubkey) {
  83. return nil, fmt.Errorf("invalid pubkey format at index %d (%s)", i, g.Name)
  84. }
  85. ethAddr := ethcommon.HexToAddress(g.Pubkey)
  86. for j, pk := range addrs {
  87. if pk == ethAddr {
  88. return nil, fmt.Errorf("duplicate pubkey at index %d (duplicate of %d): %s", i, j, g.Name)
  89. }
  90. }
  91. addrs[i] = ethAddr
  92. }
  93. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  94. vaa.BodyGuardianSetUpdate{
  95. Keys: addrs,
  96. NewIndex: guardianSetIndex + 1,
  97. }.Serialize())
  98. return v, nil
  99. }
  100. // adminContractUpgradeToVAA converts a nodev1.ContractUpgrade message to its canonical VAA representation.
  101. // Returns an error if the data is invalid.
  102. func adminContractUpgradeToVAA(req *nodev1.ContractUpgrade, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  103. b, err := hex.DecodeString(req.NewContract)
  104. if err != nil {
  105. return nil, errors.New("invalid new contract address encoding (expected hex)")
  106. }
  107. if len(b) != 32 {
  108. return nil, errors.New("invalid new_contract address")
  109. }
  110. if req.ChainId > math.MaxUint16 {
  111. return nil, errors.New("invalid chain_id")
  112. }
  113. newContractAddress := vaa.Address{}
  114. copy(newContractAddress[:], b)
  115. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  116. vaa.BodyContractUpgrade{
  117. ChainID: vaa.ChainID(req.ChainId),
  118. NewContract: newContractAddress,
  119. }.Serialize())
  120. return v, nil
  121. }
  122. // tokenBridgeRegisterChain converts a nodev1.TokenBridgeRegisterChain message to its canonical VAA representation.
  123. // Returns an error if the data is invalid.
  124. func tokenBridgeRegisterChain(req *nodev1.BridgeRegisterChain, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  125. if req.ChainId > math.MaxUint16 {
  126. return nil, errors.New("invalid chain_id")
  127. }
  128. b, err := hex.DecodeString(req.EmitterAddress)
  129. if err != nil {
  130. return nil, errors.New("invalid emitter address encoding (expected hex)")
  131. }
  132. if len(b) != 32 {
  133. return nil, errors.New("invalid emitter address (expected 32 bytes)")
  134. }
  135. emitterAddress := vaa.Address{}
  136. copy(emitterAddress[:], b)
  137. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  138. vaa.BodyTokenBridgeRegisterChain{
  139. Module: req.Module,
  140. ChainID: vaa.ChainID(req.ChainId),
  141. EmitterAddress: emitterAddress,
  142. }.Serialize())
  143. return v, nil
  144. }
  145. // accountantModifyBalance converts a nodev1.AccountantModifyBalance message to its canonical VAA representation.
  146. // Returns an error if the data is invalid.
  147. func accountantModifyBalance(req *nodev1.AccountantModifyBalance, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  148. if req.TargetChainId > math.MaxUint16 {
  149. return nil, errors.New("invalid target_chain_id")
  150. }
  151. if req.ChainId > math.MaxUint16 {
  152. return nil, errors.New("invalid chain_id")
  153. }
  154. if req.TokenChain > math.MaxUint16 {
  155. return nil, errors.New("invalid token_chain")
  156. }
  157. b, err := hex.DecodeString(req.TokenAddress)
  158. if err != nil {
  159. return nil, errors.New("invalid token address (expected hex)")
  160. }
  161. if len(b) != 32 {
  162. return nil, errors.New("invalid new token address (expected 32 bytes)")
  163. }
  164. if len(req.Reason) > 32 {
  165. return nil, errors.New("the reason should not be larger than 32 bytes")
  166. }
  167. amount_big := big.NewInt(0)
  168. amount_big, ok := amount_big.SetString(req.Amount, 10)
  169. if !ok {
  170. return nil, errors.New("invalid amount")
  171. }
  172. // uint256 has Bytes32 method for easier serialization
  173. amount, overflow := uint256.FromBig(amount_big)
  174. if overflow {
  175. return nil, errors.New("amount overflow")
  176. }
  177. tokenAdress := vaa.Address{}
  178. copy(tokenAdress[:], b)
  179. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  180. vaa.BodyAccountantModifyBalance{
  181. Module: req.Module,
  182. TargetChainID: vaa.ChainID(req.TargetChainId),
  183. Sequence: req.Sequence,
  184. ChainId: vaa.ChainID(req.ChainId),
  185. TokenChain: vaa.ChainID(req.TokenChain),
  186. TokenAddress: tokenAdress,
  187. Kind: uint8(req.Kind),
  188. Amount: amount,
  189. Reason: req.Reason,
  190. }.Serialize())
  191. return v, nil
  192. }
  193. // tokenBridgeUpgradeContract converts a nodev1.TokenBridgeRegisterChain message to its canonical VAA representation.
  194. // Returns an error if the data is invalid.
  195. func tokenBridgeUpgradeContract(req *nodev1.BridgeUpgradeContract, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  196. if req.TargetChainId > math.MaxUint16 {
  197. return nil, errors.New("invalid target_chain_id")
  198. }
  199. b, err := hex.DecodeString(req.NewContract)
  200. if err != nil {
  201. return nil, errors.New("invalid new contract address (expected hex)")
  202. }
  203. if len(b) != 32 {
  204. return nil, errors.New("invalid new contract address (expected 32 bytes)")
  205. }
  206. newContract := vaa.Address{}
  207. copy(newContract[:], b)
  208. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  209. vaa.BodyTokenBridgeUpgradeContract{
  210. Module: req.Module,
  211. TargetChainID: vaa.ChainID(req.TargetChainId),
  212. NewContract: newContract,
  213. }.Serialize())
  214. return v, nil
  215. }
  216. // wormchainStoreCode converts a nodev1.WormchainStoreCode to its canonical VAA representation
  217. // Returns an error if the data is invalid
  218. func wormchainStoreCode(req *nodev1.WormchainStoreCode, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  219. // validate the length of the hex passed in
  220. b, err := hex.DecodeString(req.WasmHash)
  221. if err != nil {
  222. return nil, fmt.Errorf("invalid cosmwasm bytecode hash (expected hex): %w", err)
  223. }
  224. if len(b) != 32 {
  225. return nil, fmt.Errorf("invalid cosmwasm bytecode hash (expected 32 bytes but received %d bytes)", len(b))
  226. }
  227. wasmHash := [32]byte{}
  228. copy(wasmHash[:], b)
  229. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  230. vaa.BodyWormchainStoreCode{
  231. WasmHash: wasmHash,
  232. }.Serialize())
  233. return v, nil
  234. }
  235. // wormchainInstantiateContract converts a nodev1.WormchainInstantiateContract to its canonical VAA representation
  236. // Returns an error if the data is invalid
  237. 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
  238. instantiationParams_hash := vaa.CreateInstatiateCosmwasmContractHash(req.CodeId, req.Label, []byte(req.InstantiationMsg))
  239. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  240. vaa.BodyWormchainInstantiateContract{
  241. InstantiationParamsHash: instantiationParams_hash,
  242. }.Serialize())
  243. return v, nil
  244. }
  245. // wormchainMigrateContract converts a nodev1.WormchainMigrateContract to its canonical VAA representation
  246. 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
  247. instantiationParams_hash := vaa.CreateMigrateCosmwasmContractHash(req.CodeId, req.Contract, []byte(req.InstantiationMsg))
  248. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  249. vaa.BodyWormchainMigrateContract{
  250. MigrationParamsHash: instantiationParams_hash,
  251. }.Serialize())
  252. return v, nil
  253. }
  254. func wormchainAddWasmInstantiateAllowlist(req *nodev1.WormchainAddWasmInstantiateAllowlist, 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
  255. return wormchainWasmInstantiateAllowlist(vaa.ActionAddWasmInstantiateAllowlist, req.CodeId, req.Contract, timestamp, guardianSetIndex, nonce, sequence)
  256. }
  257. func wormchainDeleteWasmInstantiateAllowlist(req *nodev1.WormchainDeleteWasmInstantiateAllowlist, 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
  258. return wormchainWasmInstantiateAllowlist(vaa.ActionDeleteWasmInstantiateAllowlist, req.CodeId, req.Contract, timestamp, guardianSetIndex, nonce, sequence)
  259. }
  260. func wormchainWasmInstantiateAllowlist(action vaa.GovernanceAction, codeId uint64, contract string, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  261. // parse contract address into 32 bytes
  262. // bech32 decode the string into bytes
  263. decoded, err := sdktypes.GetFromBech32(contract, "wormhole")
  264. if err != nil {
  265. return nil, fmt.Errorf("invalid bech32 contract address %w", err)
  266. }
  267. if len(decoded) != 32 {
  268. return nil, fmt.Errorf("contract address is not 32 bytes: %s", contract)
  269. }
  270. var decodedArr [32]byte
  271. copy(decodedArr[:], decoded)
  272. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, vaa.BodyWormchainWasmAllowlistInstantiate{
  273. ContractAddr: decodedArr,
  274. CodeId: codeId,
  275. }.Serialize(action))
  276. return v, nil
  277. }
  278. // circleIntegrationUpdateWormholeFinality converts a nodev1.CircleIntegrationUpdateWormholeFinality to its canonical VAA representation
  279. // Returns an error if the data is invalid
  280. func circleIntegrationUpdateWormholeFinality(req *nodev1.CircleIntegrationUpdateWormholeFinality, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  281. if req.TargetChainId > math.MaxUint16 {
  282. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  283. }
  284. if req.Finality > math.MaxUint8 {
  285. return nil, fmt.Errorf("invalid finality, must be <= %d", math.MaxUint8)
  286. }
  287. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  288. vaa.BodyCircleIntegrationUpdateWormholeFinality{
  289. TargetChainID: vaa.ChainID(req.TargetChainId),
  290. Finality: uint8(req.Finality),
  291. }.Serialize())
  292. return v, nil
  293. }
  294. // circleIntegrationRegisterEmitterAndDomain converts a nodev1.CircleIntegrationRegisterEmitterAndDomain to its canonical VAA representation
  295. // Returns an error if the data is invalid
  296. func circleIntegrationRegisterEmitterAndDomain(req *nodev1.CircleIntegrationRegisterEmitterAndDomain, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  297. if req.TargetChainId > math.MaxUint16 {
  298. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  299. }
  300. if req.ForeignEmitterChainId > math.MaxUint16 {
  301. return nil, fmt.Errorf("invalid foreign emitter chain id, must be <= %d", math.MaxUint16)
  302. }
  303. b, err := hex.DecodeString(req.ForeignEmitterAddress)
  304. if err != nil {
  305. return nil, errors.New("invalid foreign emitter address encoding (expected hex)")
  306. }
  307. if len(b) != 32 {
  308. return nil, errors.New("invalid foreign emitter address (expected 32 bytes)")
  309. }
  310. foreignEmitterAddress := vaa.Address{}
  311. copy(foreignEmitterAddress[:], b)
  312. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  313. vaa.BodyCircleIntegrationRegisterEmitterAndDomain{
  314. TargetChainID: vaa.ChainID(req.TargetChainId),
  315. ForeignEmitterChainId: vaa.ChainID(req.ForeignEmitterChainId),
  316. ForeignEmitterAddress: foreignEmitterAddress,
  317. CircleDomain: req.CircleDomain,
  318. }.Serialize())
  319. return v, nil
  320. }
  321. // circleIntegrationUpgradeContractImplementation converts a nodev1.CircleIntegrationUpgradeContractImplementation to its canonical VAA representation
  322. // Returns an error if the data is invalid
  323. func circleIntegrationUpgradeContractImplementation(req *nodev1.CircleIntegrationUpgradeContractImplementation, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  324. if req.TargetChainId > math.MaxUint16 {
  325. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  326. }
  327. b, err := hex.DecodeString(req.NewImplementationAddress)
  328. if err != nil {
  329. return nil, errors.New("invalid new implementation address encoding (expected hex)")
  330. }
  331. if len(b) != 32 {
  332. return nil, errors.New("invalid new implementation address (expected 32 bytes)")
  333. }
  334. newImplementationAddress := vaa.Address{}
  335. copy(newImplementationAddress[:], b)
  336. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  337. vaa.BodyCircleIntegrationUpgradeContractImplementation{
  338. TargetChainID: vaa.ChainID(req.TargetChainId),
  339. NewImplementationAddress: newImplementationAddress,
  340. }.Serialize())
  341. return v, nil
  342. }
  343. func ibcReceiverUpdateChannelChain(
  344. req *nodev1.IbcReceiverUpdateChannelChain,
  345. timestamp time.Time,
  346. guardianSetIndex uint32,
  347. nonce uint32,
  348. sequence uint64,
  349. ) (*vaa.VAA, error) {
  350. // validate parameters
  351. if req.TargetChainId > math.MaxUint16 {
  352. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  353. }
  354. if req.ChainId > math.MaxUint16 {
  355. return nil, fmt.Errorf("invalid chain id, must be <= %d", math.MaxUint16)
  356. }
  357. if len(req.ChannelId) > 64 {
  358. return nil, fmt.Errorf("invalid channel ID length, must be <= 64")
  359. }
  360. channelId := vaa.LeftPadIbcChannelId(req.ChannelId)
  361. // create governance VAA
  362. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  363. vaa.BodyIbcReceiverUpdateChannelChain{
  364. TargetChainId: vaa.ChainID(req.TargetChainId),
  365. ChannelId: channelId,
  366. ChainId: vaa.ChainID(req.ChainId),
  367. }.Serialize())
  368. return v, nil
  369. }
  370. // wormholeRelayerSetDefaultDeliveryProvider converts a nodev1.WormholeRelayerSetDefaultDeliveryProvider message to its canonical VAA representation.
  371. // Returns an error if the data is invalid.
  372. func wormholeRelayerSetDefaultDeliveryProvider(req *nodev1.WormholeRelayerSetDefaultDeliveryProvider, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  373. if req.ChainId > math.MaxUint16 {
  374. return nil, errors.New("invalid target_chain_id")
  375. }
  376. b, err := hex.DecodeString(req.NewDefaultDeliveryProviderAddress)
  377. if err != nil {
  378. return nil, errors.New("invalid new default delivery provider address (expected hex)")
  379. }
  380. if len(b) != 32 {
  381. return nil, errors.New("invalid new default delivery provider address (expected 32 bytes)")
  382. }
  383. NewDefaultDeliveryProviderAddress := vaa.Address{}
  384. copy(NewDefaultDeliveryProviderAddress[:], b)
  385. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
  386. vaa.BodyWormholeRelayerSetDefaultDeliveryProvider{
  387. ChainID: vaa.ChainID(req.ChainId),
  388. NewDefaultDeliveryProviderAddress: NewDefaultDeliveryProviderAddress,
  389. }.Serialize())
  390. return v, nil
  391. }
  392. func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, timestamp time.Time) (*vaa.VAA, error) {
  393. var (
  394. v *vaa.VAA
  395. err error
  396. )
  397. switch payload := message.Payload.(type) {
  398. case *nodev1.GovernanceMessage_GuardianSet:
  399. v, err = adminGuardianSetUpdateToVAA(payload.GuardianSet, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  400. case *nodev1.GovernanceMessage_ContractUpgrade:
  401. v, err = adminContractUpgradeToVAA(payload.ContractUpgrade, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  402. case *nodev1.GovernanceMessage_BridgeRegisterChain:
  403. v, err = tokenBridgeRegisterChain(payload.BridgeRegisterChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  404. case *nodev1.GovernanceMessage_BridgeContractUpgrade:
  405. v, err = tokenBridgeUpgradeContract(payload.BridgeContractUpgrade, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  406. case *nodev1.GovernanceMessage_AccountantModifyBalance:
  407. v, err = accountantModifyBalance(payload.AccountantModifyBalance, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  408. case *nodev1.GovernanceMessage_WormchainStoreCode:
  409. v, err = wormchainStoreCode(payload.WormchainStoreCode, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  410. case *nodev1.GovernanceMessage_WormchainInstantiateContract:
  411. v, err = wormchainInstantiateContract(payload.WormchainInstantiateContract, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  412. case *nodev1.GovernanceMessage_WormchainMigrateContract:
  413. v, err = wormchainMigrateContract(payload.WormchainMigrateContract, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  414. case *nodev1.GovernanceMessage_WormchainAddWasmInstantiateAllowlist:
  415. v, err = wormchainAddWasmInstantiateAllowlist(payload.WormchainAddWasmInstantiateAllowlist, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  416. case *nodev1.GovernanceMessage_WormchainDeleteWasmInstantiateAllowlist:
  417. v, err = wormchainDeleteWasmInstantiateAllowlist(payload.WormchainDeleteWasmInstantiateAllowlist, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  418. case *nodev1.GovernanceMessage_CircleIntegrationUpdateWormholeFinality:
  419. v, err = circleIntegrationUpdateWormholeFinality(payload.CircleIntegrationUpdateWormholeFinality, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  420. case *nodev1.GovernanceMessage_CircleIntegrationRegisterEmitterAndDomain:
  421. v, err = circleIntegrationRegisterEmitterAndDomain(payload.CircleIntegrationRegisterEmitterAndDomain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  422. case *nodev1.GovernanceMessage_CircleIntegrationUpgradeContractImplementation:
  423. v, err = circleIntegrationUpgradeContractImplementation(payload.CircleIntegrationUpgradeContractImplementation, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  424. case *nodev1.GovernanceMessage_IbcReceiverUpdateChannelChain:
  425. v, err = ibcReceiverUpdateChannelChain(payload.IbcReceiverUpdateChannelChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  426. case *nodev1.GovernanceMessage_WormholeRelayerSetDefaultDeliveryProvider:
  427. v, err = wormholeRelayerSetDefaultDeliveryProvider(payload.WormholeRelayerSetDefaultDeliveryProvider, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  428. default:
  429. panic(fmt.Sprintf("unsupported VAA type: %T", payload))
  430. }
  431. return v, err
  432. }
  433. func (s *nodePrivilegedService) InjectGovernanceVAA(ctx context.Context, req *nodev1.InjectGovernanceVAARequest) (*nodev1.InjectGovernanceVAAResponse, error) {
  434. s.logger.Info("governance VAA injected via admin socket", zap.String("request", req.String()))
  435. var (
  436. v *vaa.VAA
  437. err error
  438. )
  439. timestamp := time.Unix(int64(req.Timestamp), 0)
  440. digests := make([][]byte, len(req.Messages))
  441. for i, message := range req.Messages {
  442. v, err = GovMsgToVaa(message, req.CurrentSetIndex, timestamp)
  443. if err != nil {
  444. return nil, status.Error(codes.InvalidArgument, err.Error())
  445. }
  446. // Generate digest of the unsigned VAA.
  447. digest := v.SigningDigest()
  448. s.logger.Info("governance VAA constructed",
  449. zap.Any("vaa", v),
  450. zap.String("digest", digest.String()),
  451. )
  452. s.injectC <- v
  453. digests[i] = digest.Bytes()
  454. }
  455. return &nodev1.InjectGovernanceVAAResponse{Digests: digests}, nil
  456. }
  457. // fetchMissing attempts to backfill a gap by fetching and storing missing signed VAAs from the network.
  458. // Returns true if the gap was filled, false otherwise.
  459. func (s *nodePrivilegedService) fetchMissing(
  460. ctx context.Context,
  461. nodes []string,
  462. c *http.Client,
  463. chain vaa.ChainID,
  464. addr string,
  465. seq uint64) (bool, error) {
  466. // shuffle the list of public RPC endpoints
  467. rand.Shuffle(len(nodes), func(i, j int) {
  468. nodes[i], nodes[j] = nodes[j], nodes[i]
  469. })
  470. ctx, cancel := context.WithTimeout(ctx, time.Second)
  471. defer cancel()
  472. for _, node := range nodes {
  473. req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf(
  474. "%s/v1/signed_vaa/%d/%s/%d", node, chain, addr, seq), nil)
  475. if err != nil {
  476. return false, fmt.Errorf("failed to create request: %w", err)
  477. }
  478. resp, err := c.Do(req)
  479. if err != nil {
  480. s.logger.Warn("failed to fetch missing VAA",
  481. zap.String("node", node),
  482. zap.String("chain", chain.String()),
  483. zap.String("address", addr),
  484. zap.Uint64("sequence", seq),
  485. zap.Error(err),
  486. )
  487. continue
  488. }
  489. switch resp.StatusCode {
  490. case http.StatusNotFound:
  491. resp.Body.Close()
  492. continue
  493. case http.StatusOK:
  494. type getVaaResp struct {
  495. VaaBytes string `json:"vaaBytes"`
  496. }
  497. var respBody getVaaResp
  498. if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
  499. resp.Body.Close()
  500. s.logger.Warn("failed to decode VAA response",
  501. zap.String("node", node),
  502. zap.String("chain", chain.String()),
  503. zap.String("address", addr),
  504. zap.Uint64("sequence", seq),
  505. zap.Error(err),
  506. )
  507. continue
  508. }
  509. // base64 decode the VAA bytes
  510. vaaBytes, err := base64.StdEncoding.DecodeString(respBody.VaaBytes)
  511. if err != nil {
  512. resp.Body.Close()
  513. s.logger.Warn("failed to decode VAA body",
  514. zap.String("node", node),
  515. zap.String("chain", chain.String()),
  516. zap.String("address", addr),
  517. zap.Uint64("sequence", seq),
  518. zap.Error(err),
  519. )
  520. continue
  521. }
  522. s.logger.Info("backfilled VAA",
  523. zap.Uint16("chain", uint16(chain)),
  524. zap.String("address", addr),
  525. zap.Uint64("sequence", seq),
  526. zap.Int("numBytes", len(vaaBytes)),
  527. )
  528. // Inject into the gossip signed VAA receive path.
  529. // This has the same effect as if the VAA was received from the network
  530. // (verifying signature, publishing to BigTable, storing in local DB...).
  531. s.signedInC <- &gossipv1.SignedVAAWithQuorum{
  532. Vaa: vaaBytes,
  533. }
  534. resp.Body.Close()
  535. return true, nil
  536. default:
  537. resp.Body.Close()
  538. return false, fmt.Errorf("unexpected response status: %d", resp.StatusCode)
  539. }
  540. }
  541. return false, nil
  542. }
  543. func (s *nodePrivilegedService) FindMissingMessages(ctx context.Context, req *nodev1.FindMissingMessagesRequest) (*nodev1.FindMissingMessagesResponse, error) {
  544. b, err := hex.DecodeString(req.EmitterAddress)
  545. if err != nil {
  546. return nil, status.Errorf(codes.InvalidArgument, "invalid emitter address encoding: %v", err)
  547. }
  548. emitterAddress := vaa.Address{}
  549. copy(emitterAddress[:], b)
  550. ids, first, last, err := s.db.FindEmitterSequenceGap(db.VAAID{
  551. EmitterChain: vaa.ChainID(req.EmitterChain),
  552. EmitterAddress: emitterAddress,
  553. })
  554. if err != nil {
  555. return nil, status.Errorf(codes.Internal, "database operation failed: %v", err)
  556. }
  557. if req.RpcBackfill {
  558. c := &http.Client{}
  559. unfilled := make([]uint64, 0, len(ids))
  560. for _, id := range ids {
  561. if ok, err := s.fetchMissing(ctx, req.BackfillNodes, c, vaa.ChainID(req.EmitterChain), emitterAddress.String(), id); err != nil {
  562. return nil, status.Errorf(codes.Internal, "failed to backfill VAA: %v", err)
  563. } else if ok {
  564. continue
  565. }
  566. unfilled = append(unfilled, id)
  567. }
  568. ids = unfilled
  569. }
  570. resp := make([]string, len(ids))
  571. for i, v := range ids {
  572. resp[i] = fmt.Sprintf("%d/%s/%d", req.EmitterChain, emitterAddress, v)
  573. }
  574. return &nodev1.FindMissingMessagesResponse{
  575. MissingMessages: resp,
  576. FirstSequence: first,
  577. LastSequence: last,
  578. }, nil
  579. }
  580. func (s *nodePrivilegedService) SendObservationRequest(ctx context.Context, req *nodev1.SendObservationRequestRequest) (*nodev1.SendObservationRequestResponse, error) {
  581. if err := common.PostObservationRequest(s.obsvReqSendC, req.ObservationRequest); err != nil {
  582. return nil, err
  583. }
  584. s.logger.Info("sent observation request", zap.Any("request", req.ObservationRequest))
  585. return &nodev1.SendObservationRequestResponse{}, nil
  586. }
  587. func (s *nodePrivilegedService) ChainGovernorStatus(ctx context.Context, req *nodev1.ChainGovernorStatusRequest) (*nodev1.ChainGovernorStatusResponse, error) {
  588. if s.governor == nil {
  589. return nil, fmt.Errorf("chain governor is not enabled")
  590. }
  591. return &nodev1.ChainGovernorStatusResponse{
  592. Response: s.governor.Status(),
  593. }, nil
  594. }
  595. func (s *nodePrivilegedService) ChainGovernorReload(ctx context.Context, req *nodev1.ChainGovernorReloadRequest) (*nodev1.ChainGovernorReloadResponse, error) {
  596. if s.governor == nil {
  597. return nil, fmt.Errorf("chain governor is not enabled")
  598. }
  599. resp, err := s.governor.Reload()
  600. if err != nil {
  601. return nil, err
  602. }
  603. return &nodev1.ChainGovernorReloadResponse{
  604. Response: resp,
  605. }, nil
  606. }
  607. func (s *nodePrivilegedService) ChainGovernorDropPendingVAA(ctx context.Context, req *nodev1.ChainGovernorDropPendingVAARequest) (*nodev1.ChainGovernorDropPendingVAAResponse, error) {
  608. if s.governor == nil {
  609. return nil, fmt.Errorf("chain governor is not enabled")
  610. }
  611. if len(req.VaaId) == 0 {
  612. return nil, fmt.Errorf("the VAA id must be specified as \"chainId/emitterAddress/seqNum\"")
  613. }
  614. resp, err := s.governor.DropPendingVAA(req.VaaId)
  615. if err != nil {
  616. return nil, err
  617. }
  618. return &nodev1.ChainGovernorDropPendingVAAResponse{
  619. Response: resp,
  620. }, nil
  621. }
  622. func (s *nodePrivilegedService) ChainGovernorReleasePendingVAA(ctx context.Context, req *nodev1.ChainGovernorReleasePendingVAARequest) (*nodev1.ChainGovernorReleasePendingVAAResponse, error) {
  623. if s.governor == nil {
  624. return nil, fmt.Errorf("chain governor is not enabled")
  625. }
  626. if len(req.VaaId) == 0 {
  627. return nil, fmt.Errorf("the VAA id must be specified as \"chainId/emitterAddress/seqNum\"")
  628. }
  629. resp, err := s.governor.ReleasePendingVAA(req.VaaId)
  630. if err != nil {
  631. return nil, err
  632. }
  633. return &nodev1.ChainGovernorReleasePendingVAAResponse{
  634. Response: resp,
  635. }, nil
  636. }
  637. func (s *nodePrivilegedService) ChainGovernorResetReleaseTimer(ctx context.Context, req *nodev1.ChainGovernorResetReleaseTimerRequest) (*nodev1.ChainGovernorResetReleaseTimerResponse, error) {
  638. if s.governor == nil {
  639. return nil, fmt.Errorf("chain governor is not enabled")
  640. }
  641. if len(req.VaaId) == 0 {
  642. return nil, fmt.Errorf("the VAA id must be specified as \"chainId/emitterAddress/seqNum\"")
  643. }
  644. resp, err := s.governor.ResetReleaseTimer(req.VaaId)
  645. if err != nil {
  646. return nil, err
  647. }
  648. return &nodev1.ChainGovernorResetReleaseTimerResponse{
  649. Response: resp,
  650. }, nil
  651. }
  652. func (s *nodePrivilegedService) PurgePythNetVaas(ctx context.Context, req *nodev1.PurgePythNetVaasRequest) (*nodev1.PurgePythNetVaasResponse, error) {
  653. prefix := db.VAAID{EmitterChain: vaa.ChainIDPythNet}
  654. oldestTime := time.Now().Add(-time.Hour * 24 * time.Duration(req.DaysOld))
  655. resp, err := s.db.PurgeVaas(prefix, oldestTime, req.LogOnly)
  656. if err != nil {
  657. return nil, err
  658. }
  659. return &nodev1.PurgePythNetVaasResponse{
  660. Response: resp,
  661. }, nil
  662. }
  663. func (s *nodePrivilegedService) SignExistingVAA(ctx context.Context, req *nodev1.SignExistingVAARequest) (*nodev1.SignExistingVAAResponse, error) {
  664. v, err := vaa.Unmarshal(req.Vaa)
  665. if err != nil {
  666. return nil, fmt.Errorf("failed to unmarshal VAA: %w", err)
  667. }
  668. if req.NewGuardianSetIndex <= v.GuardianSetIndex {
  669. return nil, errors.New("new guardian set index must be higher than provided VAA")
  670. }
  671. if s.evmConnector == nil {
  672. return nil, errors.New("the node needs to have an Ethereum connection configured to sign existing VAAs")
  673. }
  674. var gs *common.GuardianSet
  675. if cachedGs, exists := s.gsCache.Load(v.GuardianSetIndex); exists {
  676. var ok bool
  677. gs, ok = cachedGs.(*common.GuardianSet)
  678. if !ok {
  679. return nil, fmt.Errorf("internal error")
  680. }
  681. } else {
  682. evmGs, err := s.evmConnector.GetGuardianSet(ctx, v.GuardianSetIndex)
  683. if err != nil {
  684. return nil, fmt.Errorf("failed to load guardian set [%d]: %w", v.GuardianSetIndex, err)
  685. }
  686. gs = &common.GuardianSet{
  687. Keys: evmGs.Keys,
  688. Index: v.GuardianSetIndex,
  689. }
  690. s.gsCache.Store(v.GuardianSetIndex, gs)
  691. }
  692. if slices.Index(gs.Keys, s.guardianAddress) != -1 {
  693. return nil, fmt.Errorf("local guardian is already on the old set")
  694. }
  695. // Verify VAA
  696. err = v.Verify(gs.Keys)
  697. if err != nil {
  698. return nil, fmt.Errorf("failed to verify existing VAA: %w", err)
  699. }
  700. if len(req.NewGuardianAddrs) > 255 {
  701. return nil, errors.New("new guardian set has too many guardians")
  702. }
  703. newGS := make([]ethcommon.Address, len(req.NewGuardianAddrs))
  704. for i, guardianString := range req.NewGuardianAddrs {
  705. guardianAddress := ethcommon.HexToAddress(guardianString)
  706. newGS[i] = guardianAddress
  707. }
  708. // Make sure there are no duplicates. Compact needs to take a sorted slice to remove all duplicates.
  709. newGSSorted := slices.Clone(newGS)
  710. slices.SortFunc(newGSSorted, func(a, b ethcommon.Address) bool {
  711. return bytes.Compare(a[:], b[:]) < 0
  712. })
  713. newGsLen := len(newGSSorted)
  714. if len(slices.Compact(newGSSorted)) != newGsLen {
  715. return nil, fmt.Errorf("duplicate guardians in the guardian set")
  716. }
  717. localGuardianIndex := slices.Index(newGS, s.guardianAddress)
  718. if localGuardianIndex == -1 {
  719. return nil, fmt.Errorf("local guardian is not a member of the new guardian set")
  720. }
  721. newVAA := &vaa.VAA{
  722. Version: v.Version,
  723. // Set the new guardian set index
  724. GuardianSetIndex: req.NewGuardianSetIndex,
  725. // Signatures will be repopulated
  726. Signatures: nil,
  727. Timestamp: v.Timestamp,
  728. Nonce: v.Nonce,
  729. Sequence: v.Sequence,
  730. ConsistencyLevel: v.ConsistencyLevel,
  731. EmitterChain: v.EmitterChain,
  732. EmitterAddress: v.EmitterAddress,
  733. Payload: v.Payload,
  734. }
  735. // Copy original VAA signatures
  736. for _, sig := range v.Signatures {
  737. signerAddress := gs.Keys[sig.Index]
  738. newIndex := slices.Index(newGS, signerAddress)
  739. // Guardian is not part of the new set
  740. if newIndex == -1 {
  741. continue
  742. }
  743. newVAA.Signatures = append(newVAA.Signatures, &vaa.Signature{
  744. Index: uint8(newIndex),
  745. Signature: sig.Signature,
  746. })
  747. }
  748. // Add our own signature only if the new guardian set would reach quorum
  749. if vaa.CalculateQuorum(len(newGS)) > len(newVAA.Signatures)+1 {
  750. return nil, errors.New("cannot reach quorum on new guardian set with the local signature")
  751. }
  752. // Add local signature
  753. newVAA.AddSignature(s.gk, uint8(localGuardianIndex))
  754. // Sort VAA signatures by guardian ID
  755. slices.SortFunc(newVAA.Signatures, func(a, b *vaa.Signature) bool {
  756. return a.Index < b.Index
  757. })
  758. newVAABytes, err := newVAA.Marshal()
  759. if err != nil {
  760. return nil, fmt.Errorf("failed to marshal new VAA: %w", err)
  761. }
  762. return &nodev1.SignExistingVAAResponse{Vaa: newVAABytes}, nil
  763. }
  764. func (s *nodePrivilegedService) DumpRPCs(ctx context.Context, req *nodev1.DumpRPCsRequest) (*nodev1.DumpRPCsResponse, error) {
  765. return &nodev1.DumpRPCsResponse{
  766. Response: s.rpcMap,
  767. }, nil
  768. }