2019-11-12 17:01:27 +00:00
|
|
|
package beacon
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"sort"
|
|
|
|
|
|
|
|
ptypes "github.com/gogo/protobuf/types"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
|
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/pagination"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
)
|
|
|
|
|
|
|
|
// sortableAttestations implements the Sort interface to sort attestations
|
|
|
|
// by slot as the canonical sorting attribute.
|
|
|
|
type sortableAttestations []*ethpb.Attestation
|
|
|
|
|
|
|
|
func (s sortableAttestations) Len() int { return len(s) }
|
|
|
|
func (s sortableAttestations) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
|
|
func (s sortableAttestations) Less(i, j int) bool {
|
|
|
|
return s[i].Data.Slot < s[j].Data.Slot
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListAttestations retrieves attestations by block root, slot, or epoch.
|
|
|
|
// Attestations are sorted by data slot by default.
|
|
|
|
//
|
|
|
|
// The server may return an empty list when no attestations match the given
|
|
|
|
// filter criteria. This RPC should not return NOT_FOUND. Only one filter
|
|
|
|
// criteria should be used.
|
|
|
|
func (bs *Server) ListAttestations(
|
|
|
|
ctx context.Context, req *ethpb.ListAttestationsRequest,
|
|
|
|
) (*ethpb.ListAttestationsResponse, error) {
|
|
|
|
if int(req.PageSize) > params.BeaconConfig().MaxPageSize {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Requested page size %d can not be greater than max size %d",
|
2019-11-12 17:01:27 +00:00
|
|
|
req.PageSize, params.BeaconConfig().MaxPageSize)
|
|
|
|
}
|
|
|
|
var atts []*ethpb.Attestation
|
|
|
|
var err error
|
|
|
|
switch q := req.QueryFilter.(type) {
|
|
|
|
case *ethpb.ListAttestationsRequest_HeadBlockRoot:
|
|
|
|
atts, err = bs.BeaconDB.Attestations(ctx, filters.NewFilter().SetHeadBlockRoot(q.HeadBlockRoot))
|
|
|
|
if err != nil {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
case *ethpb.ListAttestationsRequest_SourceEpoch:
|
|
|
|
atts, err = bs.BeaconDB.Attestations(ctx, filters.NewFilter().SetSourceEpoch(q.SourceEpoch))
|
|
|
|
if err != nil {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
case *ethpb.ListAttestationsRequest_SourceRoot:
|
|
|
|
atts, err = bs.BeaconDB.Attestations(ctx, filters.NewFilter().SetSourceRoot(q.SourceRoot))
|
|
|
|
if err != nil {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
case *ethpb.ListAttestationsRequest_TargetEpoch:
|
|
|
|
atts, err = bs.BeaconDB.Attestations(ctx, filters.NewFilter().SetTargetEpoch(q.TargetEpoch))
|
|
|
|
if err != nil {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
case *ethpb.ListAttestationsRequest_TargetRoot:
|
|
|
|
atts, err = bs.BeaconDB.Attestations(ctx, filters.NewFilter().SetTargetRoot(q.TargetRoot))
|
|
|
|
if err != nil {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
default:
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
// We sort attestations according to the Sortable interface.
|
|
|
|
sort.Sort(sortableAttestations(atts))
|
|
|
|
numAttestations := len(atts)
|
|
|
|
|
|
|
|
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), numAttestations)
|
|
|
|
if err != nil {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
return ðpb.ListAttestationsResponse{
|
|
|
|
Attestations: atts[start:end],
|
|
|
|
TotalSize: int32(numAttestations),
|
|
|
|
NextPageToken: nextPageToken,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// AttestationPool retrieves pending attestations.
|
|
|
|
//
|
|
|
|
// The server returns a list of attestations that have been seen but not
|
|
|
|
// yet processed. Pool attestations eventually expire as the slot
|
|
|
|
// advances, so an attestation missing from this request does not imply
|
|
|
|
// that it was included in a block. The attestation may have expired.
|
|
|
|
// Refer to the ethereum 2.0 specification for more details on how
|
|
|
|
// attestations are processed and when they are no longer valid.
|
|
|
|
// https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md#attestations
|
|
|
|
func (bs *Server) AttestationPool(
|
|
|
|
ctx context.Context, _ *ptypes.Empty,
|
|
|
|
) (*ethpb.AttestationPoolResponse, error) {
|
|
|
|
atts, err := bs.Pool.AttestationPoolNoVerify(ctx)
|
|
|
|
if err != nil {
|
2019-11-13 21:03:12 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
2019-11-12 17:01:27 +00:00
|
|
|
}
|
|
|
|
return ðpb.AttestationPoolResponse{
|
|
|
|
Attestations: atts,
|
|
|
|
}, nil
|
|
|
|
}
|