adminserver.go 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  1. package adminrpc
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/base64"
  6. "encoding/hex"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "math"
  12. "math/big"
  13. "math/rand"
  14. "net/http"
  15. "slices"
  16. "strconv"
  17. "strings"
  18. "sync"
  19. "time"
  20. "github.com/certusone/wormhole/node/pkg/guardiansigner"
  21. "github.com/certusone/wormhole/node/pkg/watchers/evm/connectors"
  22. "github.com/certusone/wormhole/node/pkg/watchers/interfaces"
  23. "github.com/holiman/uint256"
  24. "github.com/prometheus/client_golang/prometheus"
  25. "github.com/prometheus/client_golang/prometheus/promauto"
  26. guardianDB "github.com/certusone/wormhole/node/pkg/db"
  27. "github.com/certusone/wormhole/node/pkg/governor"
  28. gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
  29. ethcommon "github.com/ethereum/go-ethereum/common"
  30. "github.com/mr-tron/base58"
  31. "go.uber.org/zap"
  32. "google.golang.org/grpc/codes"
  33. "google.golang.org/grpc/status"
  34. "github.com/certusone/wormhole/node/pkg/common"
  35. nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
  36. "github.com/wormhole-foundation/wormhole/sdk/vaa"
  37. sdktypes "github.com/cosmos/cosmos-sdk/types"
  38. )
  39. const maxResetReleaseTimerDays = 30
  40. const ecdsaSignatureLength = 65
  41. var (
  42. vaaInjectionsTotal = promauto.NewCounter(
  43. prometheus.CounterOpts{
  44. Name: "wormhole_vaa_injections_total",
  45. Help: "Total number of injected VAA queued for broadcast",
  46. })
  47. )
  48. type nodePrivilegedService struct {
  49. nodev1.UnimplementedNodePrivilegedServiceServer
  50. db *guardianDB.Database
  51. injectC chan<- *common.MessagePublication
  52. obsvReqSendC chan<- *gossipv1.ObservationRequest
  53. logger *zap.Logger
  54. signedInC chan<- *gossipv1.SignedVAAWithQuorum
  55. governor *governor.ChainGovernor
  56. evmConnector connectors.Connector
  57. gsCache sync.Map
  58. guardianSigner guardiansigner.GuardianSigner
  59. guardianAddress ethcommon.Address
  60. rpcMap map[string]string
  61. reobservers interfaces.Reobservers
  62. }
  63. func NewPrivService(
  64. db *guardianDB.Database,
  65. injectC chan<- *common.MessagePublication,
  66. obsvReqSendC chan<- *gossipv1.ObservationRequest,
  67. logger *zap.Logger,
  68. signedInC chan<- *gossipv1.SignedVAAWithQuorum,
  69. gov *governor.ChainGovernor,
  70. evmConnector connectors.Connector,
  71. guardianSigner guardiansigner.GuardianSigner,
  72. guardianAddress ethcommon.Address,
  73. rpcMap map[string]string,
  74. reobservers interfaces.Reobservers,
  75. ) *nodePrivilegedService {
  76. return &nodePrivilegedService{
  77. db: db,
  78. injectC: injectC,
  79. obsvReqSendC: obsvReqSendC,
  80. logger: logger,
  81. signedInC: signedInC,
  82. governor: gov,
  83. evmConnector: evmConnector,
  84. guardianSigner: guardianSigner,
  85. guardianAddress: guardianAddress,
  86. rpcMap: rpcMap,
  87. reobservers: reobservers,
  88. }
  89. }
  90. // adminGuardianSetUpdateToVAA converts a nodev1.GuardianSetUpdate message to its canonical VAA representation.
  91. // Returns an error if the data is invalid.
  92. func adminGuardianSetUpdateToVAA(req *nodev1.GuardianSetUpdate, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  93. if len(req.Guardians) == 0 {
  94. return nil, errors.New("empty guardian set specified")
  95. }
  96. if len(req.Guardians) > common.MaxGuardianCount {
  97. return nil, fmt.Errorf("too many guardians - %d, maximum is %d", len(req.Guardians), common.MaxGuardianCount)
  98. }
  99. addrs := make([]ethcommon.Address, len(req.Guardians))
  100. for i, g := range req.Guardians {
  101. if !ethcommon.IsHexAddress(g.Pubkey) {
  102. return nil, fmt.Errorf("invalid pubkey format at index %d (%s)", i, g.Name)
  103. }
  104. ethAddr := ethcommon.HexToAddress(g.Pubkey)
  105. for j, pk := range addrs {
  106. if pk == ethAddr {
  107. return nil, fmt.Errorf("duplicate pubkey at index %d (duplicate of %d): %s", i, j, g.Name)
  108. }
  109. }
  110. addrs[i] = ethAddr
  111. }
  112. body, err := vaa.BodyGuardianSetUpdate{
  113. Keys: addrs,
  114. NewIndex: guardianSetIndex + 1,
  115. }.Serialize()
  116. if err != nil {
  117. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  118. }
  119. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  120. return v, nil
  121. }
  122. // adminContractUpgradeToVAA converts a nodev1.ContractUpgrade message to its canonical VAA representation.
  123. // Returns an error if the data is invalid.
  124. func adminContractUpgradeToVAA(req *nodev1.ContractUpgrade, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  125. b, err := hex.DecodeString(req.NewContract)
  126. if err != nil {
  127. return nil, errors.New("invalid new contract address encoding (expected hex)")
  128. }
  129. if len(b) != 32 {
  130. return nil, errors.New("invalid new_contract address")
  131. }
  132. if req.ChainId > math.MaxUint16 {
  133. return nil, errors.New("invalid chain_id")
  134. }
  135. newContractAddress := vaa.Address{}
  136. copy(newContractAddress[:], b)
  137. body, err := vaa.BodyContractUpgrade{
  138. ChainID: vaa.ChainID(req.ChainId),
  139. NewContract: newContractAddress,
  140. }.Serialize()
  141. if err != nil {
  142. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  143. }
  144. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  145. return v, nil
  146. }
  147. // tokenBridgeRegisterChain converts a nodev1.TokenBridgeRegisterChain message to its canonical VAA representation.
  148. // Returns an error if the data is invalid.
  149. func tokenBridgeRegisterChain(req *nodev1.BridgeRegisterChain, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  150. if req.ChainId > math.MaxUint16 {
  151. return nil, errors.New("invalid chain_id")
  152. }
  153. b, err := hex.DecodeString(req.EmitterAddress)
  154. if err != nil {
  155. return nil, errors.New("invalid emitter address encoding (expected hex)")
  156. }
  157. if len(b) != 32 {
  158. return nil, errors.New("invalid emitter address (expected 32 bytes)")
  159. }
  160. emitterAddress := vaa.Address{}
  161. copy(emitterAddress[:], b)
  162. body, err := vaa.BodyTokenBridgeRegisterChain{
  163. Module: req.Module,
  164. ChainID: vaa.ChainID(req.ChainId),
  165. EmitterAddress: emitterAddress,
  166. }.Serialize()
  167. if err != nil {
  168. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  169. }
  170. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  171. return v, nil
  172. }
  173. // recoverChainId converts a nodev1.RecoverChainId message to its canonical VAA representation.
  174. // Returns an error if the data is invalid.
  175. func recoverChainId(req *nodev1.RecoverChainId, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  176. evm_chain_id_big := big.NewInt(0)
  177. evm_chain_id_big, ok := evm_chain_id_big.SetString(req.EvmChainId, 10)
  178. if !ok {
  179. return nil, errors.New("invalid evm_chain_id")
  180. }
  181. // uint256 has Bytes32 method for easier serialization
  182. evm_chain_id, overflow := uint256.FromBig(evm_chain_id_big)
  183. if overflow {
  184. return nil, errors.New("evm_chain_id overflow")
  185. }
  186. if req.NewChainId > math.MaxUint16 {
  187. return nil, errors.New("invalid new_chain_id")
  188. }
  189. body, err := vaa.BodyRecoverChainId{
  190. Module: req.Module,
  191. EvmChainID: evm_chain_id,
  192. NewChainID: vaa.ChainID(req.NewChainId),
  193. }.Serialize()
  194. if err != nil {
  195. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  196. }
  197. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  198. return v, nil
  199. }
  200. // accountantModifyBalance converts a nodev1.AccountantModifyBalance message to its canonical VAA representation.
  201. // Returns an error if the data is invalid.
  202. func accountantModifyBalance(req *nodev1.AccountantModifyBalance, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  203. if req.TargetChainId > math.MaxUint16 {
  204. return nil, errors.New("invalid target_chain_id")
  205. }
  206. if req.ChainId > math.MaxUint16 {
  207. return nil, errors.New("invalid chain_id")
  208. }
  209. if req.TokenChain > math.MaxUint16 {
  210. return nil, errors.New("invalid token_chain")
  211. }
  212. b, err := hex.DecodeString(req.TokenAddress)
  213. if err != nil {
  214. return nil, errors.New("invalid token address (expected hex)")
  215. }
  216. if len(b) != 32 {
  217. return nil, errors.New("invalid new token address (expected 32 bytes)")
  218. }
  219. if len(req.Reason) > vaa.AccountantModifyBalanceReasonLength {
  220. return nil, fmt.Errorf("the reason should not be larger than %d bytes", vaa.AccountantModifyBalanceReasonLength)
  221. }
  222. amount_big := big.NewInt(0)
  223. amount_big, ok := amount_big.SetString(req.Amount, 10)
  224. if !ok {
  225. return nil, errors.New("invalid amount")
  226. }
  227. // uint256 has Bytes32 method for easier serialization
  228. amount, overflow := uint256.FromBig(amount_big)
  229. if overflow {
  230. return nil, errors.New("amount overflow")
  231. }
  232. tokenAdress := vaa.Address{}
  233. copy(tokenAdress[:], b)
  234. body, err := vaa.BodyAccountantModifyBalance{
  235. Module: req.Module,
  236. TargetChainID: vaa.ChainID(req.TargetChainId),
  237. Sequence: req.Sequence,
  238. ChainId: vaa.ChainID(req.ChainId),
  239. TokenChain: vaa.ChainID(req.TokenChain),
  240. TokenAddress: tokenAdress,
  241. Kind: uint8(req.Kind), // #nosec G115 -- The `ModificationKind` enum only has 3 values
  242. Amount: amount,
  243. Reason: req.Reason,
  244. }.Serialize()
  245. if err != nil {
  246. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  247. }
  248. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  249. return v, nil
  250. }
  251. // tokenBridgeUpgradeContract converts a nodev1.TokenBridgeRegisterChain message to its canonical VAA representation.
  252. // Returns an error if the data is invalid.
  253. func tokenBridgeUpgradeContract(req *nodev1.BridgeUpgradeContract, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  254. if req.TargetChainId > math.MaxUint16 {
  255. return nil, errors.New("invalid target_chain_id")
  256. }
  257. b, err := hex.DecodeString(req.NewContract)
  258. if err != nil {
  259. return nil, errors.New("invalid new contract address (expected hex)")
  260. }
  261. if len(b) != 32 {
  262. return nil, errors.New("invalid new contract address (expected 32 bytes)")
  263. }
  264. newContract := vaa.Address{}
  265. copy(newContract[:], b)
  266. body, err := vaa.BodyTokenBridgeUpgradeContract{
  267. Module: req.Module,
  268. TargetChainID: vaa.ChainID(req.TargetChainId),
  269. NewContract: newContract,
  270. }.Serialize()
  271. if err != nil {
  272. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  273. }
  274. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  275. return v, nil
  276. }
  277. // wormchainStoreCode converts a nodev1.WormchainStoreCode to its canonical VAA representation
  278. // Returns an error if the data is invalid
  279. func wormchainStoreCode(req *nodev1.WormchainStoreCode, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  280. // validate the length of the hex passed in
  281. b, err := hex.DecodeString(req.WasmHash)
  282. if err != nil {
  283. return nil, fmt.Errorf("invalid cosmwasm bytecode hash (expected hex): %w", err)
  284. }
  285. if len(b) != 32 {
  286. return nil, fmt.Errorf("invalid cosmwasm bytecode hash (expected 32 bytes but received %d bytes)", len(b))
  287. }
  288. wasmHash := [32]byte{}
  289. copy(wasmHash[:], b)
  290. body, err := vaa.BodyWormchainStoreCode{
  291. WasmHash: wasmHash,
  292. }.Serialize()
  293. if err != nil {
  294. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  295. }
  296. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  297. return v, nil
  298. }
  299. // wormchainInstantiateContract converts a nodev1.WormchainInstantiateContract to its canonical VAA representation
  300. // Returns an error if the data is invalid
  301. func wormchainInstantiateContract(req *nodev1.WormchainInstantiateContract, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  302. instantiationParams_hash := vaa.CreateInstatiateCosmwasmContractHash(req.CodeId, req.Label, []byte(req.InstantiationMsg))
  303. body, err := vaa.BodyWormchainInstantiateContract{
  304. InstantiationParamsHash: instantiationParams_hash,
  305. }.Serialize()
  306. if err != nil {
  307. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  308. }
  309. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  310. return v, nil
  311. }
  312. // wormchainMigrateContract converts a nodev1.WormchainMigrateContract to its canonical VAA representation
  313. func wormchainMigrateContract(req *nodev1.WormchainMigrateContract, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  314. instantiationParams_hash := vaa.CreateMigrateCosmwasmContractHash(req.CodeId, req.Contract, []byte(req.InstantiationMsg))
  315. body, err := vaa.BodyWormchainMigrateContract{
  316. MigrationParamsHash: instantiationParams_hash,
  317. }.Serialize()
  318. if err != nil {
  319. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  320. }
  321. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  322. return v, nil
  323. }
  324. func wormchainWasmInstantiateAllowlist(
  325. req *nodev1.WormchainWasmInstantiateAllowlist,
  326. timestamp time.Time,
  327. guardianSetIndex uint32,
  328. nonce uint32,
  329. sequence uint64,
  330. ) (*vaa.VAA, error) {
  331. decodedAddr, err := sdktypes.GetFromBech32(req.Contract, "wormhole")
  332. if err != nil {
  333. return nil, err
  334. }
  335. var action vaa.GovernanceAction
  336. if req.Action == nodev1.WormchainWasmInstantiateAllowlistAction_WORMCHAIN_WASM_INSTANTIATE_ALLOWLIST_ACTION_ADD {
  337. action = vaa.ActionAddWasmInstantiateAllowlist
  338. } else if req.Action == nodev1.WormchainWasmInstantiateAllowlistAction_WORMCHAIN_WASM_INSTANTIATE_ALLOWLIST_ACTION_DELETE {
  339. action = vaa.ActionDeleteWasmInstantiateAllowlist
  340. } else {
  341. return nil, fmt.Errorf("unrecognized wasm instantiate allowlist action")
  342. }
  343. var decodedAddr32 [32]byte
  344. copy(decodedAddr32[:], decodedAddr)
  345. body, err := vaa.BodyWormchainWasmAllowlistInstantiate{
  346. ContractAddr: decodedAddr32,
  347. CodeId: req.CodeId,
  348. }.Serialize(action)
  349. if err != nil {
  350. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  351. }
  352. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  353. return v, nil
  354. }
  355. func gatewayScheduleUpgrade(
  356. req *nodev1.GatewayScheduleUpgrade,
  357. timestamp time.Time,
  358. guardianSetIndex uint32,
  359. nonce uint32,
  360. sequence uint64,
  361. ) (*vaa.VAA, error) {
  362. body, err := vaa.BodyGatewayScheduleUpgrade{
  363. Name: req.Name,
  364. Height: req.Height,
  365. }.Serialize()
  366. if err != nil {
  367. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  368. }
  369. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  370. return v, nil
  371. }
  372. func gatewayCancelUpgrade(
  373. timestamp time.Time,
  374. guardianSetIndex uint32,
  375. nonce uint32,
  376. sequence uint64,
  377. ) (*vaa.VAA, error) {
  378. body, err := vaa.EmptyPayloadVaa(vaa.GatewayModuleStr, vaa.ActionCancelUpgrade, vaa.ChainIDWormchain)
  379. if err != nil {
  380. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  381. }
  382. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  383. return v, nil
  384. }
  385. func gatewayIbcComposabilityMwSetContract(
  386. req *nodev1.GatewayIbcComposabilityMwSetContract,
  387. timestamp time.Time,
  388. guardianSetIndex uint32,
  389. nonce uint32,
  390. sequence uint64,
  391. ) (*vaa.VAA, error) {
  392. decodedAddr, err := sdktypes.GetFromBech32(req.Contract, "wormhole")
  393. if err != nil {
  394. return nil, err
  395. }
  396. var decodedAddr32 [32]byte
  397. copy(decodedAddr32[:], decodedAddr)
  398. body, err := vaa.BodyGatewayIbcComposabilityMwContract{
  399. ContractAddr: decodedAddr32,
  400. }.Serialize()
  401. if err != nil {
  402. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  403. }
  404. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  405. return v, nil
  406. }
  407. // circleIntegrationUpdateWormholeFinality converts a nodev1.CircleIntegrationUpdateWormholeFinality to its canonical VAA representation
  408. // Returns an error if the data is invalid
  409. func circleIntegrationUpdateWormholeFinality(req *nodev1.CircleIntegrationUpdateWormholeFinality, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  410. if req.TargetChainId > math.MaxUint16 {
  411. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  412. }
  413. if req.Finality > math.MaxUint8 {
  414. return nil, fmt.Errorf("invalid finality, must be <= %d", math.MaxUint8)
  415. }
  416. body, err := vaa.BodyCircleIntegrationUpdateWormholeFinality{
  417. TargetChainID: vaa.ChainID(req.TargetChainId),
  418. Finality: uint8(req.Finality),
  419. }.Serialize()
  420. if err != nil {
  421. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  422. }
  423. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  424. return v, nil
  425. }
  426. // circleIntegrationRegisterEmitterAndDomain converts a nodev1.CircleIntegrationRegisterEmitterAndDomain to its canonical VAA representation
  427. // Returns an error if the data is invalid
  428. func circleIntegrationRegisterEmitterAndDomain(req *nodev1.CircleIntegrationRegisterEmitterAndDomain, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  429. if req.TargetChainId > math.MaxUint16 {
  430. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  431. }
  432. if req.ForeignEmitterChainId > math.MaxUint16 {
  433. return nil, fmt.Errorf("invalid foreign emitter chain id, must be <= %d", math.MaxUint16)
  434. }
  435. b, err := hex.DecodeString(req.ForeignEmitterAddress)
  436. if err != nil {
  437. return nil, errors.New("invalid foreign emitter address encoding (expected hex)")
  438. }
  439. if len(b) != 32 {
  440. return nil, errors.New("invalid foreign emitter address (expected 32 bytes)")
  441. }
  442. foreignEmitterAddress := vaa.Address{}
  443. copy(foreignEmitterAddress[:], b)
  444. body, err := vaa.BodyCircleIntegrationRegisterEmitterAndDomain{
  445. TargetChainID: vaa.ChainID(req.TargetChainId),
  446. ForeignEmitterChainId: vaa.ChainID(req.ForeignEmitterChainId),
  447. ForeignEmitterAddress: foreignEmitterAddress,
  448. CircleDomain: req.CircleDomain,
  449. }.Serialize()
  450. if err != nil {
  451. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  452. }
  453. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  454. return v, nil
  455. }
  456. // circleIntegrationUpgradeContractImplementation converts a nodev1.CircleIntegrationUpgradeContractImplementation to its canonical VAA representation
  457. // Returns an error if the data is invalid
  458. func circleIntegrationUpgradeContractImplementation(req *nodev1.CircleIntegrationUpgradeContractImplementation, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  459. if req.TargetChainId > math.MaxUint16 {
  460. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  461. }
  462. b, err := hex.DecodeString(req.NewImplementationAddress)
  463. if err != nil {
  464. return nil, errors.New("invalid new implementation address encoding (expected hex)")
  465. }
  466. if len(b) != 32 {
  467. return nil, errors.New("invalid new implementation address (expected 32 bytes)")
  468. }
  469. newImplementationAddress := vaa.Address{}
  470. copy(newImplementationAddress[:], b)
  471. body, err := vaa.BodyCircleIntegrationUpgradeContractImplementation{
  472. TargetChainID: vaa.ChainID(req.TargetChainId),
  473. NewImplementationAddress: newImplementationAddress,
  474. }.Serialize()
  475. if err != nil {
  476. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  477. }
  478. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  479. return v, nil
  480. }
  481. func ibcUpdateChannelChain(
  482. req *nodev1.IbcUpdateChannelChain,
  483. timestamp time.Time,
  484. guardianSetIndex uint32,
  485. nonce uint32,
  486. sequence uint64,
  487. ) (*vaa.VAA, error) {
  488. // validate parameters
  489. if req.TargetChainId > math.MaxUint16 {
  490. return nil, fmt.Errorf("invalid target chain id, must be <= %d", math.MaxUint16)
  491. }
  492. if req.ChainId > math.MaxUint16 {
  493. return nil, fmt.Errorf("invalid chain id, must be <= %d", math.MaxUint16)
  494. }
  495. if len(req.ChannelId) > 64 {
  496. return nil, fmt.Errorf("invalid channel ID length, must be <= 64")
  497. }
  498. channelId, err := vaa.LeftPadIbcChannelId(req.ChannelId)
  499. if err != nil {
  500. return nil, fmt.Errorf("failed to left pad channel id: %w", err)
  501. }
  502. var module string
  503. if req.Module == nodev1.IbcUpdateChannelChainModule_IBC_UPDATE_CHANNEL_CHAIN_MODULE_RECEIVER {
  504. module = vaa.IbcReceiverModuleStr
  505. } else if req.Module == nodev1.IbcUpdateChannelChainModule_IBC_UPDATE_CHANNEL_CHAIN_MODULE_TRANSLATOR {
  506. module = vaa.IbcTranslatorModuleStr
  507. } else {
  508. return nil, fmt.Errorf("unrecognized ibc update channel chain module")
  509. }
  510. body, err := vaa.BodyIbcUpdateChannelChain{
  511. TargetChainId: vaa.ChainID(req.TargetChainId),
  512. ChannelId: channelId,
  513. ChainId: vaa.ChainID(req.ChainId),
  514. }.Serialize(module)
  515. if err != nil {
  516. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  517. }
  518. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  519. return v, nil
  520. }
  521. // wormholeRelayerSetDefaultDeliveryProvider converts a nodev1.WormholeRelayerSetDefaultDeliveryProvider message to its canonical VAA representation.
  522. // Returns an error if the data is invalid.
  523. func wormholeRelayerSetDefaultDeliveryProvider(req *nodev1.WormholeRelayerSetDefaultDeliveryProvider, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  524. if req.ChainId > math.MaxUint16 {
  525. return nil, errors.New("invalid target_chain_id")
  526. }
  527. b, err := hex.DecodeString(req.NewDefaultDeliveryProviderAddress)
  528. if err != nil {
  529. return nil, errors.New("invalid new default delivery provider address (expected hex)")
  530. }
  531. if len(b) != 32 {
  532. return nil, errors.New("invalid new default delivery provider address (expected 32 bytes)")
  533. }
  534. NewDefaultDeliveryProviderAddress := vaa.Address{}
  535. copy(NewDefaultDeliveryProviderAddress[:], b)
  536. body, err := vaa.BodyWormholeRelayerSetDefaultDeliveryProvider{
  537. ChainID: vaa.ChainID(req.ChainId),
  538. NewDefaultDeliveryProviderAddress: NewDefaultDeliveryProviderAddress,
  539. }.Serialize()
  540. if err != nil {
  541. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  542. }
  543. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  544. return v, nil
  545. }
  546. func coreBridgeSetMessageFeeToVaa(req *nodev1.CoreBridgeSetMessageFee, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  547. chainId, err := vaa.KnownChainIDFromNumber[uint32](req.ChainId)
  548. if err != nil {
  549. return nil, fmt.Errorf("failed to convert chain id: %w", err)
  550. }
  551. new_fee_big := big.NewInt(0)
  552. new_fee_big, ok := new_fee_big.SetString(req.MessageFee, 10)
  553. if !ok {
  554. return nil, errors.New("invalid new fee")
  555. }
  556. new_fee, overflow := uint256.FromBig(new_fee_big)
  557. if overflow {
  558. return nil, errors.New("new fee overflow")
  559. }
  560. if new_fee_big.Cmp(big.NewInt(0)) < 0 {
  561. return nil, errors.New("new fee cannot be negative")
  562. }
  563. body, err := vaa.BodyCoreBridgeSetMessageFee{
  564. ChainID: chainId,
  565. MessageFee: new_fee,
  566. }.Serialize()
  567. if err != nil {
  568. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  569. }
  570. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  571. return v, nil
  572. }
  573. func evmCallToVaa(evmCall *nodev1.EvmCall, timestamp time.Time, guardianSetIndex, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  574. governanceContract := ethcommon.HexToAddress(evmCall.GovernanceContract)
  575. targetContract := ethcommon.HexToAddress(evmCall.TargetContract)
  576. payload, err := hex.DecodeString(evmCall.AbiEncodedCall)
  577. if err != nil {
  578. return nil, fmt.Errorf("failed to decode ABI encoded call: %w", err)
  579. }
  580. if evmCall.ChainId > math.MaxUint16 {
  581. return nil, fmt.Errorf("chain id exceeds max uint16: %v", evmCall.ChainId)
  582. }
  583. body, err := vaa.BodyGeneralPurposeGovernanceEvm{
  584. ChainID: vaa.ChainID(evmCall.ChainId),
  585. GovernanceContract: governanceContract,
  586. TargetContract: targetContract,
  587. Payload: payload,
  588. }.Serialize()
  589. if err != nil {
  590. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  591. }
  592. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  593. return v, nil
  594. }
  595. func solanaCallToVaa(solanaCall *nodev1.SolanaCall, timestamp time.Time, guardianSetIndex, nonce uint32, sequence uint64) (*vaa.VAA, error) {
  596. address, err := base58.Decode(solanaCall.GovernanceContract)
  597. if err != nil {
  598. return nil, fmt.Errorf("failed to decode base58 governance contract address: %w", err)
  599. }
  600. if len(address) != 32 {
  601. return nil, errors.New("invalid governance contract address length (expected 32 bytes)")
  602. }
  603. var governanceContract [32]byte
  604. copy(governanceContract[:], address)
  605. instruction, err := hex.DecodeString(solanaCall.EncodedInstruction)
  606. if err != nil {
  607. return nil, fmt.Errorf("failed to decode instruction: %w", err)
  608. }
  609. if solanaCall.ChainId > math.MaxUint16 {
  610. return nil, fmt.Errorf("chain id exceeds max uint16: %v", solanaCall.ChainId)
  611. }
  612. body, err := vaa.BodyGeneralPurposeGovernanceSolana{
  613. ChainID: vaa.ChainID(solanaCall.ChainId),
  614. GovernanceContract: governanceContract,
  615. Instruction: instruction,
  616. }.Serialize()
  617. if err != nil {
  618. return nil, fmt.Errorf("failed to serialize governance body: %w", err)
  619. }
  620. v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
  621. return v, nil
  622. }
  623. func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, timestamp time.Time) (*vaa.VAA, error) {
  624. var (
  625. v *vaa.VAA
  626. err error
  627. )
  628. switch payload := message.Payload.(type) {
  629. case *nodev1.GovernanceMessage_GuardianSet:
  630. v, err = adminGuardianSetUpdateToVAA(payload.GuardianSet, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  631. case *nodev1.GovernanceMessage_ContractUpgrade:
  632. v, err = adminContractUpgradeToVAA(payload.ContractUpgrade, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  633. case *nodev1.GovernanceMessage_BridgeRegisterChain:
  634. v, err = tokenBridgeRegisterChain(payload.BridgeRegisterChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  635. case *nodev1.GovernanceMessage_BridgeContractUpgrade:
  636. v, err = tokenBridgeUpgradeContract(payload.BridgeContractUpgrade, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  637. case *nodev1.GovernanceMessage_RecoverChainId:
  638. v, err = recoverChainId(payload.RecoverChainId, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  639. case *nodev1.GovernanceMessage_AccountantModifyBalance:
  640. v, err = accountantModifyBalance(payload.AccountantModifyBalance, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  641. case *nodev1.GovernanceMessage_WormchainStoreCode:
  642. v, err = wormchainStoreCode(payload.WormchainStoreCode, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  643. case *nodev1.GovernanceMessage_WormchainInstantiateContract:
  644. v, err = wormchainInstantiateContract(payload.WormchainInstantiateContract, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  645. case *nodev1.GovernanceMessage_WormchainMigrateContract:
  646. v, err = wormchainMigrateContract(payload.WormchainMigrateContract, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  647. case *nodev1.GovernanceMessage_WormchainWasmInstantiateAllowlist:
  648. v, err = wormchainWasmInstantiateAllowlist(payload.WormchainWasmInstantiateAllowlist, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  649. case *nodev1.GovernanceMessage_GatewayScheduleUpgrade:
  650. v, err = gatewayScheduleUpgrade(payload.GatewayScheduleUpgrade, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  651. case *nodev1.GovernanceMessage_GatewayCancelUpgrade:
  652. v, err = gatewayCancelUpgrade(timestamp, currentSetIndex, message.Nonce, message.Sequence)
  653. case *nodev1.GovernanceMessage_GatewayIbcComposabilityMwSetContract:
  654. v, err = gatewayIbcComposabilityMwSetContract(payload.GatewayIbcComposabilityMwSetContract, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  655. case *nodev1.GovernanceMessage_CircleIntegrationUpdateWormholeFinality:
  656. v, err = circleIntegrationUpdateWormholeFinality(payload.CircleIntegrationUpdateWormholeFinality, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  657. case *nodev1.GovernanceMessage_CircleIntegrationRegisterEmitterAndDomain:
  658. v, err = circleIntegrationRegisterEmitterAndDomain(payload.CircleIntegrationRegisterEmitterAndDomain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  659. case *nodev1.GovernanceMessage_CircleIntegrationUpgradeContractImplementation:
  660. v, err = circleIntegrationUpgradeContractImplementation(payload.CircleIntegrationUpgradeContractImplementation, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  661. case *nodev1.GovernanceMessage_IbcUpdateChannelChain:
  662. v, err = ibcUpdateChannelChain(payload.IbcUpdateChannelChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  663. case *nodev1.GovernanceMessage_WormholeRelayerSetDefaultDeliveryProvider:
  664. v, err = wormholeRelayerSetDefaultDeliveryProvider(payload.WormholeRelayerSetDefaultDeliveryProvider, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  665. case *nodev1.GovernanceMessage_EvmCall:
  666. v, err = evmCallToVaa(payload.EvmCall, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  667. case *nodev1.GovernanceMessage_SolanaCall:
  668. v, err = solanaCallToVaa(payload.SolanaCall, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  669. case *nodev1.GovernanceMessage_CoreBridgeSetMessageFee:
  670. v, err = coreBridgeSetMessageFeeToVaa(payload.CoreBridgeSetMessageFee, timestamp, currentSetIndex, message.Nonce, message.Sequence)
  671. default:
  672. err = fmt.Errorf("unsupported VAA type: %T", payload)
  673. }
  674. return v, err
  675. }
  676. func (s *nodePrivilegedService) InjectGovernanceVAA(ctx context.Context, req *nodev1.InjectGovernanceVAARequest) (*nodev1.InjectGovernanceVAAResponse, error) {
  677. s.logger.Info("governance VAA injected via admin socket", zap.String("request", req.String()))
  678. var (
  679. v *vaa.VAA
  680. err error
  681. )
  682. timestamp := time.Unix(int64(req.Timestamp), 0)
  683. digests := make([][]byte, len(req.Messages))
  684. for i, message := range req.Messages {
  685. v, err = GovMsgToVaa(message, req.CurrentSetIndex, timestamp)
  686. if err != nil {
  687. return nil, status.Error(codes.InvalidArgument, err.Error())
  688. }
  689. // Generate digest of the unsigned VAA.
  690. digest := v.SigningDigest()
  691. s.logger.Info("governance VAA constructed",
  692. zap.Any("vaa", v),
  693. zap.String("digest", digest.String()),
  694. )
  695. vaaInjectionsTotal.Inc()
  696. s.injectC <- &common.MessagePublication{ //nolint:channelcheck // Only blocks this command
  697. TxID: ethcommon.Hash{}.Bytes(),
  698. Timestamp: v.Timestamp,
  699. Nonce: v.Nonce,
  700. Sequence: v.Sequence,
  701. ConsistencyLevel: v.ConsistencyLevel,
  702. EmitterChain: v.EmitterChain,
  703. EmitterAddress: v.EmitterAddress,
  704. Payload: v.Payload,
  705. Unreliable: false,
  706. }
  707. digests[i] = digest.Bytes()
  708. }
  709. return &nodev1.InjectGovernanceVAAResponse{Digests: digests}, nil
  710. }
  711. // fetchMissing attempts to backfill a gap by fetching and storing missing signed VAAs from the network.
  712. // Returns true if the gap was filled, false otherwise.
  713. func (s *nodePrivilegedService) fetchMissing(
  714. ctx context.Context,
  715. nodes []string,
  716. c *http.Client,
  717. chain vaa.ChainID,
  718. addr string,
  719. seq uint64) (bool, error) {
  720. // shuffle the list of public RPC endpoints
  721. rand.Shuffle(len(nodes), func(i, j int) {
  722. nodes[i], nodes[j] = nodes[j], nodes[i]
  723. })
  724. ctx, cancel := context.WithTimeout(ctx, time.Second)
  725. defer cancel()
  726. for _, node := range nodes {
  727. req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf(
  728. "%s/v1/signed_vaa/%d/%s/%d", node, chain, addr, seq), nil)
  729. if err != nil {
  730. return false, fmt.Errorf("failed to create request: %w", err)
  731. }
  732. resp, err := c.Do(req)
  733. if err != nil {
  734. s.logger.Warn("failed to fetch missing VAA",
  735. zap.String("node", node),
  736. zap.String("chain", chain.String()),
  737. zap.String("address", addr),
  738. zap.Uint64("sequence", seq),
  739. zap.Error(err),
  740. )
  741. continue
  742. }
  743. switch resp.StatusCode {
  744. case http.StatusNotFound:
  745. resp.Body.Close()
  746. continue
  747. case http.StatusOK:
  748. type getVaaResp struct {
  749. VaaBytes string `json:"vaaBytes"`
  750. }
  751. var respBody getVaaResp
  752. if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
  753. resp.Body.Close()
  754. s.logger.Warn("failed to decode VAA response",
  755. zap.String("node", node),
  756. zap.String("chain", chain.String()),
  757. zap.String("address", addr),
  758. zap.Uint64("sequence", seq),
  759. zap.Error(err),
  760. )
  761. continue
  762. }
  763. // base64 decode the VAA bytes
  764. vaaBytes, err := base64.StdEncoding.DecodeString(respBody.VaaBytes)
  765. if err != nil {
  766. resp.Body.Close()
  767. s.logger.Warn("failed to decode VAA body",
  768. zap.String("node", node),
  769. zap.String("chain", chain.String()),
  770. zap.String("address", addr),
  771. zap.Uint64("sequence", seq),
  772. zap.Error(err),
  773. )
  774. continue
  775. }
  776. s.logger.Info("backfilled VAA",
  777. zap.Uint16("chain", uint16(chain)),
  778. zap.String("address", addr),
  779. zap.Uint64("sequence", seq),
  780. zap.Int("numBytes", len(vaaBytes)),
  781. )
  782. // Inject into the gossip signed VAA receive path.
  783. // This has the same effect as if the VAA was received from the network
  784. // (verifying signature, storing in local DB...).
  785. s.signedInC <- &gossipv1.SignedVAAWithQuorum{ //nolint:channelcheck // Only blocks this command
  786. Vaa: vaaBytes,
  787. }
  788. resp.Body.Close()
  789. return true, nil
  790. default:
  791. resp.Body.Close()
  792. return false, fmt.Errorf("unexpected response status: %d", resp.StatusCode)
  793. }
  794. }
  795. return false, nil
  796. }
  797. func (s *nodePrivilegedService) FindMissingMessages(ctx context.Context, req *nodev1.FindMissingMessagesRequest) (*nodev1.FindMissingMessagesResponse, error) {
  798. b, err := hex.DecodeString(req.EmitterAddress)
  799. if err != nil {
  800. return nil, status.Errorf(codes.InvalidArgument, "invalid emitter address encoding: %v", err)
  801. }
  802. if req.EmitterChain > math.MaxUint16 {
  803. return nil, status.Errorf(codes.InvalidArgument, "chain id exceeds max uint16: %v", req.EmitterChain)
  804. }
  805. emitterAddress := vaa.Address{}
  806. copy(emitterAddress[:], b)
  807. ids, first, last, err := s.db.FindEmitterSequenceGap(guardianDB.VAAID{
  808. EmitterChain: vaa.ChainID(req.EmitterChain),
  809. EmitterAddress: emitterAddress,
  810. })
  811. if err != nil {
  812. return nil, status.Errorf(codes.Internal, "database operation failed: %v", err)
  813. }
  814. if req.RpcBackfill {
  815. c := &http.Client{}
  816. unfilled := make([]uint64, 0, len(ids))
  817. for _, id := range ids {
  818. if ok, err := s.fetchMissing(ctx, req.BackfillNodes, c, vaa.ChainID(req.EmitterChain), emitterAddress.String(), id); err != nil {
  819. return nil, status.Errorf(codes.Internal, "failed to backfill VAA: %v", err)
  820. } else if ok {
  821. continue
  822. }
  823. unfilled = append(unfilled, id)
  824. }
  825. ids = unfilled
  826. }
  827. resp := make([]string, len(ids))
  828. for i, v := range ids {
  829. resp[i] = fmt.Sprintf("%d/%s/%d", req.EmitterChain, emitterAddress, v)
  830. }
  831. return &nodev1.FindMissingMessagesResponse{
  832. MissingMessages: resp,
  833. FirstSequence: first,
  834. LastSequence: last,
  835. }, nil
  836. }
  837. func (s *nodePrivilegedService) SendObservationRequest(ctx context.Context, req *nodev1.SendObservationRequestRequest) (*nodev1.SendObservationRequestResponse, error) {
  838. if err := common.PostObservationRequest(s.obsvReqSendC, req.ObservationRequest); err != nil {
  839. return nil, err
  840. }
  841. s.logger.Info("sent observation request", zap.Any("request", req.ObservationRequest))
  842. return &nodev1.SendObservationRequestResponse{}, nil
  843. }
  844. func (s *nodePrivilegedService) ReobserveWithEndpoint(ctx context.Context, req *nodev1.ReobserveWithEndpointRequest) (*nodev1.ReobserveWithEndpointResponse, error) {
  845. if req.ChainId > math.MaxUint16 {
  846. return nil, status.Errorf(codes.Internal, "chain %d is not a valid uint16", req.ChainId)
  847. }
  848. watcher := s.reobservers[vaa.ChainID(req.ChainId)]
  849. if watcher == nil {
  850. return nil, status.Errorf(codes.Internal, "chain %d does not support reobservation by endpoint", req.ChainId)
  851. }
  852. numObservations, err := watcher.Reobserve(ctx, vaa.ChainID(req.ChainId), req.TxHash, req.Url)
  853. if err != nil {
  854. return nil, status.Errorf(codes.Internal, "reobservation failed: %v", err)
  855. }
  856. return &nodev1.ReobserveWithEndpointResponse{NumObservations: numObservations}, nil
  857. }
  858. func (s *nodePrivilegedService) ChainGovernorStatus(ctx context.Context, req *nodev1.ChainGovernorStatusRequest) (*nodev1.ChainGovernorStatusResponse, error) {
  859. if s.governor == nil {
  860. return nil, fmt.Errorf("chain governor is not enabled")
  861. }
  862. return &nodev1.ChainGovernorStatusResponse{
  863. Response: s.governor.Status(),
  864. }, nil
  865. }
  866. func (s *nodePrivilegedService) ChainGovernorReload(ctx context.Context, req *nodev1.ChainGovernorReloadRequest) (*nodev1.ChainGovernorReloadResponse, error) {
  867. if s.governor == nil {
  868. return nil, fmt.Errorf("chain governor is not enabled")
  869. }
  870. resp, err := s.governor.Reload()
  871. if err != nil {
  872. return nil, err
  873. }
  874. return &nodev1.ChainGovernorReloadResponse{
  875. Response: resp,
  876. }, nil
  877. }
  878. func (s *nodePrivilegedService) ChainGovernorDropPendingVAA(ctx context.Context, req *nodev1.ChainGovernorDropPendingVAARequest) (*nodev1.ChainGovernorDropPendingVAAResponse, error) {
  879. if s.governor == nil {
  880. return nil, fmt.Errorf("chain governor is not enabled")
  881. }
  882. if len(req.VaaId) == 0 {
  883. return nil, fmt.Errorf("the VAA id must be specified as \"chainId/emitterAddress/seqNum\"")
  884. }
  885. resp, err := s.governor.DropPendingVAA(req.VaaId)
  886. if err != nil {
  887. return nil, err
  888. }
  889. return &nodev1.ChainGovernorDropPendingVAAResponse{
  890. Response: resp,
  891. }, nil
  892. }
  893. func (s *nodePrivilegedService) ChainGovernorReleasePendingVAA(ctx context.Context, req *nodev1.ChainGovernorReleasePendingVAARequest) (*nodev1.ChainGovernorReleasePendingVAAResponse, error) {
  894. if s.governor == nil {
  895. return nil, fmt.Errorf("chain governor is not enabled")
  896. }
  897. if len(req.VaaId) == 0 {
  898. return nil, fmt.Errorf("the VAA id must be specified as \"chainId/emitterAddress/seqNum\"")
  899. }
  900. resp, err := s.governor.ReleasePendingVAA(req.VaaId)
  901. if err != nil {
  902. return nil, err
  903. }
  904. return &nodev1.ChainGovernorReleasePendingVAAResponse{
  905. Response: resp,
  906. }, nil
  907. }
  908. func (s *nodePrivilegedService) ChainGovernorResetReleaseTimer(_ context.Context, req *nodev1.ChainGovernorResetReleaseTimerRequest) (*nodev1.ChainGovernorResetReleaseTimerResponse, error) {
  909. if s.governor == nil {
  910. return nil, fmt.Errorf("chain governor is not enabled")
  911. }
  912. if len(req.VaaId) == 0 {
  913. return nil, fmt.Errorf("the VAA id must be specified as \"chainId/emitterAddress/seqNum\"")
  914. }
  915. if req.NumDays < 1 || req.NumDays > maxResetReleaseTimerDays {
  916. return nil, fmt.Errorf("the specified number of days falls outside the range of 1 to %d", maxResetReleaseTimerDays)
  917. }
  918. resp, err := s.governor.ResetReleaseTimer(req.VaaId, req.NumDays)
  919. if err != nil {
  920. return nil, err
  921. }
  922. return &nodev1.ChainGovernorResetReleaseTimerResponse{
  923. Response: resp,
  924. }, nil
  925. }
  926. func (s *nodePrivilegedService) PurgePythNetVaas(ctx context.Context, req *nodev1.PurgePythNetVaasRequest) (*nodev1.PurgePythNetVaasResponse, error) {
  927. prefix := guardianDB.VAAID{EmitterChain: vaa.ChainIDPythNet}
  928. oldestTime := time.Now().Add(-time.Hour * 24 * time.Duration(req.DaysOld)) // #nosec G115 -- This conversion is safe indefinitely
  929. resp, err := s.db.PurgeVaas(prefix, oldestTime, req.LogOnly)
  930. if err != nil {
  931. return nil, err
  932. }
  933. return &nodev1.PurgePythNetVaasResponse{
  934. Response: resp,
  935. }, nil
  936. }
  937. func (s *nodePrivilegedService) SignExistingVAA(ctx context.Context, req *nodev1.SignExistingVAARequest) (*nodev1.SignExistingVAAResponse, error) {
  938. v, err := vaa.Unmarshal(req.Vaa)
  939. if err != nil {
  940. return nil, fmt.Errorf("failed to unmarshal VAA: %w", err)
  941. }
  942. if req.NewGuardianSetIndex <= v.GuardianSetIndex {
  943. return nil, errors.New("new guardian set index must be higher than provided VAA")
  944. }
  945. if s.evmConnector == nil {
  946. return nil, errors.New("the node needs to have an Ethereum connection configured to sign existing VAAs")
  947. }
  948. var gs *common.GuardianSet
  949. if cachedGs, exists := s.gsCache.Load(v.GuardianSetIndex); exists {
  950. var ok bool
  951. gs, ok = cachedGs.(*common.GuardianSet)
  952. if !ok {
  953. return nil, fmt.Errorf("internal error")
  954. }
  955. } else {
  956. evmGs, err := s.evmConnector.GetGuardianSet(ctx, v.GuardianSetIndex)
  957. if err != nil {
  958. return nil, fmt.Errorf("failed to load guardian set [%d]: %w", v.GuardianSetIndex, err)
  959. }
  960. gs = &common.GuardianSet{
  961. Keys: evmGs.Keys,
  962. Index: v.GuardianSetIndex,
  963. }
  964. s.gsCache.Store(v.GuardianSetIndex, gs)
  965. }
  966. if slices.Index(gs.Keys, s.guardianAddress) != -1 {
  967. return nil, fmt.Errorf("local guardian is already on the old set")
  968. }
  969. // Verify VAA
  970. err = v.Verify(gs.Keys)
  971. if err != nil {
  972. return nil, fmt.Errorf("failed to verify existing VAA: %w", err)
  973. }
  974. if len(req.NewGuardianAddrs) > 255 {
  975. return nil, errors.New("new guardian set has too many guardians")
  976. }
  977. newGS := make([]ethcommon.Address, len(req.NewGuardianAddrs))
  978. for i, guardianString := range req.NewGuardianAddrs {
  979. guardianAddress := ethcommon.HexToAddress(guardianString)
  980. newGS[i] = guardianAddress
  981. }
  982. // Make sure there are no duplicates. Compact needs to take a sorted slice to remove all duplicates.
  983. newGSSorted := slices.Clone(newGS)
  984. slices.SortFunc(newGSSorted, func(a, b ethcommon.Address) int {
  985. return bytes.Compare(a[:], b[:])
  986. })
  987. newGsLen := len(newGSSorted)
  988. if len(slices.Compact(newGSSorted)) != newGsLen {
  989. return nil, fmt.Errorf("duplicate guardians in the guardian set")
  990. }
  991. localGuardianIndex := slices.Index(newGS, s.guardianAddress)
  992. if localGuardianIndex == -1 {
  993. return nil, fmt.Errorf("local guardian is not a member of the new guardian set")
  994. }
  995. newVAA := &vaa.VAA{
  996. Version: v.Version,
  997. // Set the new guardian set index
  998. GuardianSetIndex: req.NewGuardianSetIndex,
  999. // Signatures will be repopulated
  1000. Signatures: nil,
  1001. Timestamp: v.Timestamp,
  1002. Nonce: v.Nonce,
  1003. Sequence: v.Sequence,
  1004. ConsistencyLevel: v.ConsistencyLevel,
  1005. EmitterChain: v.EmitterChain,
  1006. EmitterAddress: v.EmitterAddress,
  1007. Payload: v.Payload,
  1008. }
  1009. // Copy original VAA signatures
  1010. for _, sig := range v.Signatures {
  1011. signerAddress := gs.Keys[sig.Index]
  1012. newIndex := slices.Index(newGS, signerAddress)
  1013. // Guardian is not part of the new set
  1014. if newIndex == -1 {
  1015. continue
  1016. }
  1017. newVAA.Signatures = append(newVAA.Signatures, &vaa.Signature{
  1018. Index: uint8(newIndex), // #nosec G115 -- The length of newGS is constrained to a uint8 above
  1019. Signature: sig.Signature,
  1020. })
  1021. }
  1022. // Add our own signature only if the new guardian set would reach quorum
  1023. if vaa.CalculateQuorum(len(newGS)) > len(newVAA.Signatures)+1 {
  1024. return nil, errors.New("cannot reach quorum on new guardian set with the local signature")
  1025. }
  1026. // Add local signature
  1027. sig, err := s.guardianSigner.Sign(ctx, v.SigningDigest().Bytes())
  1028. if err != nil {
  1029. panic(err)
  1030. }
  1031. signature := [ecdsaSignatureLength]byte{}
  1032. copy(signature[:], sig)
  1033. newVAA.Signatures = append(v.Signatures, &vaa.Signature{
  1034. Index: uint8(localGuardianIndex), // #nosec G115 -- The length of newGS is constrained to a uint8 above
  1035. Signature: signature,
  1036. })
  1037. // Sort VAA signatures by guardian ID
  1038. slices.SortFunc(newVAA.Signatures, func(a, b *vaa.Signature) int {
  1039. if a.Index < b.Index {
  1040. return -1
  1041. } else if a.Index > b.Index {
  1042. return 1
  1043. }
  1044. return 0
  1045. })
  1046. newVAABytes, err := newVAA.Marshal()
  1047. if err != nil {
  1048. return nil, fmt.Errorf("failed to marshal new VAA: %w", err)
  1049. }
  1050. return &nodev1.SignExistingVAAResponse{Vaa: newVAABytes}, nil
  1051. }
  1052. func (s *nodePrivilegedService) DumpRPCs(ctx context.Context, req *nodev1.DumpRPCsRequest) (*nodev1.DumpRPCsResponse, error) {
  1053. return &nodev1.DumpRPCsResponse{
  1054. Response: s.rpcMap,
  1055. }, nil
  1056. }
  1057. func (s *nodePrivilegedService) GetAndObserveMissingVAAs(ctx context.Context, req *nodev1.GetAndObserveMissingVAAsRequest) (*nodev1.GetAndObserveMissingVAAsResponse, error) {
  1058. // Get URL and API key from the command line
  1059. url := req.GetUrl()
  1060. apiKey := req.GetApiKey()
  1061. // Create the body of the request
  1062. jsonBody := []byte(`{"apiKey": "` + apiKey + `"}`)
  1063. jsonBodyReader := bytes.NewReader(jsonBody)
  1064. // Create the actual request
  1065. httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, url, jsonBodyReader)
  1066. if err != nil {
  1067. fmt.Printf("GetAndObserveMissingVAAs: could not create request: %s\n", err)
  1068. return nil, err
  1069. }
  1070. httpRequest.Header.Set("Content-Type", "application/json")
  1071. client := http.Client{
  1072. Timeout: 30 * time.Second,
  1073. }
  1074. // Call the cloud function to get the missing VAAs
  1075. results, err := client.Do(httpRequest)
  1076. if err != nil {
  1077. fmt.Printf("GetAndObserveMissingVAAs: error making http request: %s\n", err)
  1078. return nil, err
  1079. }
  1080. defer results.Body.Close()
  1081. // Collect the results
  1082. resBody, err := io.ReadAll(results.Body)
  1083. if err != nil {
  1084. fmt.Printf("GetAndObserveMissingVAAs: could not read response body: %s\n", err)
  1085. return nil, err
  1086. }
  1087. fmt.Printf("client: response body: %s\n", resBody)
  1088. type MissingVAA struct {
  1089. Chain int `json:"chain"`
  1090. VaaKey string `json:"vaaKey"`
  1091. Txhash string `json:"txhash"`
  1092. }
  1093. var missingVAAs []MissingVAA
  1094. err = json.Unmarshal(resBody, &missingVAAs)
  1095. if err != nil {
  1096. fmt.Printf("GetAndObserveMissingVAAs: could not unmarshal response body: %s\n", err)
  1097. return nil, err
  1098. }
  1099. MAX_VAAS_TO_PROCESS := 25
  1100. // Only do a max of 25 at a time so as to not overload the node
  1101. numVaas := len(missingVAAs)
  1102. processingLen := numVaas
  1103. if processingLen > MAX_VAAS_TO_PROCESS {
  1104. processingLen = MAX_VAAS_TO_PROCESS
  1105. }
  1106. // Start injecting the VAAs
  1107. obsCounter := 0
  1108. errCounter := 0
  1109. errMsgs := "Messages: "
  1110. for i := 0; i < processingLen; i++ {
  1111. missingVAA := missingVAAs[i]
  1112. // First check to see if this VAA has already been signed
  1113. // Convert vaaKey to VAAID
  1114. splits := strings.Split(missingVAA.VaaKey, "/")
  1115. chainID, err := strconv.Atoi(splits[0])
  1116. if err != nil {
  1117. errMsgs += fmt.Sprintf("\nerror converting chainID [%s] to int", missingVAA.VaaKey)
  1118. errCounter++
  1119. continue
  1120. }
  1121. if chainID > math.MaxUint16 {
  1122. errMsgs += fmt.Sprintf("\nchainID [%d] not a valid uint16", chainID)
  1123. errCounter++
  1124. continue
  1125. }
  1126. sequence, err := strconv.ParseUint(splits[2], 10, 64)
  1127. if err != nil {
  1128. errMsgs += fmt.Sprintf("\nerror converting sequence %s to uint64", splits[2])
  1129. errCounter++
  1130. continue
  1131. }
  1132. vaaKey := guardianDB.VAAID{EmitterChain: vaa.ChainID(chainID), EmitterAddress: vaa.Address([]byte(splits[1])), Sequence: sequence} // #nosec G115 -- This chainId conversion is verified above
  1133. hasVaa, err := s.db.HasVAA(vaaKey)
  1134. if err != nil || hasVaa {
  1135. errMsgs += fmt.Sprintf("\nerror checking for VAA %s", missingVAA.VaaKey)
  1136. errCounter++
  1137. continue
  1138. }
  1139. var obsvReq gossipv1.ObservationRequest
  1140. if missingVAA.Chain > math.MaxUint16 {
  1141. errMsgs += fmt.Sprintf("\nmissing VAA chainID [%d] not a valid uint16", missingVAA.Chain)
  1142. errCounter++
  1143. continue
  1144. }
  1145. obsvReq.ChainId = uint32(missingVAA.Chain) // #nosec G115 -- This conversion is checked above
  1146. obsvReq.TxHash, err = hex.DecodeString(strings.TrimPrefix(missingVAA.Txhash, "0x"))
  1147. if err != nil {
  1148. obsvReq.TxHash, err = base58.Decode(missingVAA.Txhash)
  1149. if err != nil {
  1150. errMsgs += "Invalid transaction hash (neither hex nor base58)"
  1151. errCounter++
  1152. continue
  1153. }
  1154. }
  1155. errMsgs += fmt.Sprintf("\nAttempting to observe %s", missingVAA.Txhash)
  1156. // Call the following function to send the observation request
  1157. if err := common.PostObservationRequest(s.obsvReqSendC, &obsvReq); err != nil {
  1158. errMsgs += fmt.Sprintf("\nPostObservationRequest error %s", err.Error())
  1159. errCounter++
  1160. continue
  1161. }
  1162. obsCounter++
  1163. }
  1164. response := "There were no missing VAAs to recover."
  1165. if processingLen > 0 {
  1166. response = fmt.Sprintf("Successfully injected %d of %d VAAs. %d errors were encountered.", obsCounter, processingLen, errCounter)
  1167. if numVaas > MAX_VAAS_TO_PROCESS {
  1168. response += fmt.Sprintf("\nOnly %d of the %d missing VAAs were processed. Run the command again to process more.", MAX_VAAS_TO_PROCESS, numVaas)
  1169. }
  1170. }
  1171. response += "\n" + errMsgs
  1172. return &nodev1.GetAndObserveMissingVAAsResponse{
  1173. Response: response,
  1174. }, nil
  1175. }