publicrpcserver.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package publicrpc
  2. import (
  3. "context"
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "math"
  8. "github.com/certusone/wormhole/node/pkg/common"
  9. guardianDB "github.com/certusone/wormhole/node/pkg/db"
  10. "github.com/certusone/wormhole/node/pkg/governor"
  11. publicrpcv1 "github.com/certusone/wormhole/node/pkg/proto/publicrpc/v1"
  12. "github.com/wormhole-foundation/wormhole/sdk/vaa"
  13. "go.uber.org/zap"
  14. "google.golang.org/grpc/codes"
  15. "google.golang.org/grpc/status"
  16. )
  17. // PublicrpcServer implements the publicrpc gRPC service.
  18. type PublicrpcServer struct {
  19. publicrpcv1.UnsafePublicRPCServiceServer
  20. logger *zap.Logger
  21. db *guardianDB.Database
  22. gst *common.GuardianSetState
  23. gov *governor.ChainGovernor
  24. }
  25. func NewPublicrpcServer(
  26. logger *zap.Logger,
  27. db *guardianDB.Database,
  28. gst *common.GuardianSetState,
  29. gov *governor.ChainGovernor,
  30. ) *PublicrpcServer {
  31. return &PublicrpcServer{
  32. logger: logger.Named("publicrpcserver"),
  33. db: db,
  34. gst: gst,
  35. gov: gov,
  36. }
  37. }
  38. func (s *PublicrpcServer) GetLastHeartbeats(ctx context.Context, req *publicrpcv1.GetLastHeartbeatsRequest) (*publicrpcv1.GetLastHeartbeatsResponse, error) {
  39. gs := s.gst.Get()
  40. if gs == nil {
  41. return nil, status.Error(codes.Unavailable, "guardian set not fetched from chain yet")
  42. }
  43. resp := &publicrpcv1.GetLastHeartbeatsResponse{
  44. Entries: make([]*publicrpcv1.GetLastHeartbeatsResponse_Entry, 0),
  45. }
  46. // Fetch all heartbeats (including from nodes not in the guardian set - which
  47. // can happen either with --disableHeartbeatVerify or when the guardian set changes)
  48. for addr, v := range s.gst.GetAll() {
  49. for peerId, hb := range v {
  50. resp.Entries = append(resp.Entries, &publicrpcv1.GetLastHeartbeatsResponse_Entry{
  51. VerifiedGuardianAddr: addr.Hex(),
  52. P2PNodeAddr: peerId.String(),
  53. RawHeartbeat: hb,
  54. })
  55. }
  56. }
  57. return resp, nil
  58. }
  59. func (s *PublicrpcServer) GetSignedVAA(ctx context.Context, req *publicrpcv1.GetSignedVAARequest) (*publicrpcv1.GetSignedVAAResponse, error) {
  60. if req.MessageId == nil {
  61. return nil, status.Error(codes.InvalidArgument, "no message ID specified")
  62. }
  63. if req.MessageId.GetEmitterChain() > math.MaxUint16 {
  64. return nil, status.Error(codes.InvalidArgument, "emitter chain id must be no greater than 16 bits")
  65. }
  66. chainID := vaa.ChainID(req.MessageId.GetEmitterChain()) // #nosec G115 -- This conversion is checked above
  67. // This interface is not supported for PythNet messages because those VAAs are not stored in the database.
  68. if chainID == vaa.ChainIDPythNet {
  69. return nil, status.Error(codes.InvalidArgument, "not supported for PythNet")
  70. }
  71. address, err := hex.DecodeString(req.MessageId.EmitterAddress)
  72. if err != nil {
  73. return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to decode address: %v", err))
  74. }
  75. if len(address) != 32 {
  76. return nil, status.Error(codes.InvalidArgument, "address must be 32 bytes")
  77. }
  78. addr := vaa.Address{}
  79. copy(addr[:], address)
  80. b, err := s.db.GetSignedVAABytes(guardianDB.VAAID{
  81. EmitterChain: chainID,
  82. EmitterAddress: addr,
  83. Sequence: req.MessageId.Sequence,
  84. })
  85. if err != nil {
  86. if errors.Is(err, guardianDB.ErrVAANotFound) {
  87. return nil, status.Error(codes.NotFound, err.Error())
  88. }
  89. s.logger.Error("failed to fetch VAA", zap.Error(err), zap.Any("request", req))
  90. return nil, status.Error(codes.Internal, "internal server error")
  91. }
  92. return &publicrpcv1.GetSignedVAAResponse{
  93. VaaBytes: b,
  94. }, nil
  95. }
  96. func (s *PublicrpcServer) GetCurrentGuardianSet(ctx context.Context, req *publicrpcv1.GetCurrentGuardianSetRequest) (*publicrpcv1.GetCurrentGuardianSetResponse, error) {
  97. gs := s.gst.Get()
  98. if gs == nil {
  99. return nil, status.Error(codes.Unavailable, "guardian set not fetched from chain yet")
  100. }
  101. resp := &publicrpcv1.GetCurrentGuardianSetResponse{
  102. GuardianSet: &publicrpcv1.GuardianSet{
  103. Index: gs.Index,
  104. Addresses: make([]string, len(gs.Keys)),
  105. },
  106. }
  107. for i, v := range gs.Keys {
  108. resp.GuardianSet.Addresses[i] = v.Hex()
  109. }
  110. return resp, nil
  111. }
  112. func (s *PublicrpcServer) GovernorGetAvailableNotionalByChain(ctx context.Context, req *publicrpcv1.GovernorGetAvailableNotionalByChainRequest) (*publicrpcv1.GovernorGetAvailableNotionalByChainResponse, error) {
  113. resp := &publicrpcv1.GovernorGetAvailableNotionalByChainResponse{}
  114. if s.gov != nil {
  115. resp.Entries = s.gov.GetAvailableNotionalByChain()
  116. } else {
  117. resp.Entries = make([]*publicrpcv1.GovernorGetAvailableNotionalByChainResponse_Entry, 0)
  118. }
  119. return resp, nil
  120. }
  121. func (s *PublicrpcServer) GovernorGetEnqueuedVAAs(ctx context.Context, req *publicrpcv1.GovernorGetEnqueuedVAAsRequest) (*publicrpcv1.GovernorGetEnqueuedVAAsResponse, error) {
  122. resp := &publicrpcv1.GovernorGetEnqueuedVAAsResponse{}
  123. if s.gov != nil {
  124. resp.Entries = s.gov.GetEnqueuedVAAs()
  125. } else {
  126. resp.Entries = make([]*publicrpcv1.GovernorGetEnqueuedVAAsResponse_Entry, 0)
  127. }
  128. return resp, nil
  129. }
  130. func (s *PublicrpcServer) GovernorIsVAAEnqueued(ctx context.Context, req *publicrpcv1.GovernorIsVAAEnqueuedRequest) (*publicrpcv1.GovernorIsVAAEnqueuedResponse, error) {
  131. resp := &publicrpcv1.GovernorIsVAAEnqueuedResponse{}
  132. if req.MessageId == nil {
  133. return nil, status.Error(codes.InvalidArgument, "no message ID specified")
  134. }
  135. if s.gov != nil {
  136. var err error
  137. resp.IsEnqueued, err = s.gov.IsVAAEnqueued(req.MessageId)
  138. if err != nil {
  139. return resp, err
  140. }
  141. } else {
  142. resp.IsEnqueued = false
  143. }
  144. return resp, nil
  145. }
  146. func (s *PublicrpcServer) GovernorGetTokenList(ctx context.Context, req *publicrpcv1.GovernorGetTokenListRequest) (*publicrpcv1.GovernorGetTokenListResponse, error) {
  147. resp := &publicrpcv1.GovernorGetTokenListResponse{}
  148. if s.gov != nil {
  149. resp.Entries = s.gov.GetTokenList()
  150. } else {
  151. resp.Entries = make([]*publicrpcv1.GovernorGetTokenListResponse_Entry, 0)
  152. }
  153. return resp, nil
  154. }