wormhole/node/pkg/publicrpc/publicrpcserver.go

111 lines
3.2 KiB
Go

package publicrpc
import (
"context"
"encoding/hex"
"fmt"
"github.com/certusone/wormhole/node/pkg/common"
"github.com/certusone/wormhole/node/pkg/db"
publicrpcv1 "github.com/certusone/wormhole/node/pkg/proto/publicrpc/v1"
"github.com/certusone/wormhole/node/pkg/vaa"
"go.uber.org/zap"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// PublicrpcServer implements the publicrpc gRPC service.
type PublicrpcServer struct {
publicrpcv1.UnsafePublicRPCServiceServer
logger *zap.Logger
db *db.Database
gst *common.GuardianSetState
}
func NewPublicrpcServer(
logger *zap.Logger,
db *db.Database,
gst *common.GuardianSetState,
) *PublicrpcServer {
return &PublicrpcServer{
logger: logger.Named("publicrpcserver"),
db: db,
gst: gst,
}
}
func (s *PublicrpcServer) GetLastHeartbeats(ctx context.Context, req *publicrpcv1.GetLastHeartbeatsRequest) (*publicrpcv1.GetLastHeartbeatsResponse, error) {
gs := s.gst.Get()
if gs == nil {
return nil, status.Error(codes.Unavailable, "guardian set not fetched from chain yet")
}
resp := &publicrpcv1.GetLastHeartbeatsResponse{
Entries: make([]*publicrpcv1.GetLastHeartbeatsResponse_Entry, 0),
}
// Fetch all heartbeats (including from nodes not in the guardian set - which
// can happen either with --disableHeartbeatVerify or when the guardian set changes)
for addr, v := range s.gst.GetAll() {
for peerId, hb := range v {
resp.Entries = append(resp.Entries, &publicrpcv1.GetLastHeartbeatsResponse_Entry{
VerifiedGuardianAddr: addr.Hex(),
P2PNodeAddr: peerId.Pretty(),
RawHeartbeat: hb,
})
}
}
return resp, nil
}
func (s *PublicrpcServer) GetSignedVAA(ctx context.Context, req *publicrpcv1.GetSignedVAARequest) (*publicrpcv1.GetSignedVAAResponse, error) {
address, err := hex.DecodeString(req.MessageId.EmitterAddress)
if err != nil {
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to decode address: %v", err))
}
if len(address) != 32 {
return nil, status.Error(codes.InvalidArgument, "address must be 32 bytes")
}
addr := vaa.Address{}
copy(addr[:], address)
b, err := s.db.GetSignedVAABytes(db.VAAID{
EmitterChain: vaa.ChainID(req.MessageId.EmitterChain.Number()),
EmitterAddress: addr,
Sequence: uint64(req.MessageId.Sequence),
})
if err != nil {
if err == db.ErrVAANotFound {
return nil, status.Error(codes.NotFound, err.Error())
}
s.logger.Error("failed to fetch VAA", zap.Error(err), zap.Any("request", req))
return nil, status.Error(codes.Internal, "internal server error")
}
return &publicrpcv1.GetSignedVAAResponse{
VaaBytes: b,
}, nil
}
func (s *PublicrpcServer) GetCurrentGuardianSet(ctx context.Context, req *publicrpcv1.GetCurrentGuardianSetRequest) (*publicrpcv1.GetCurrentGuardianSetResponse, error) {
gs := s.gst.Get()
if gs == nil {
return nil, status.Error(codes.Unavailable, "guardian set not fetched from chain yet")
}
resp := &publicrpcv1.GetCurrentGuardianSetResponse{
GuardianSet: &publicrpcv1.GuardianSet{
Index: gs.Index,
Addresses: make([]string, len(gs.Keys)),
},
}
for i, v := range gs.Keys {
resp.GuardianSet.Addresses[i] = v.Hex()
}
return resp, nil
}