mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
Implement ProduceAttestationData
in the validator API (#9271)
* functionality * test * build file Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
parent
8c8f1bb9c1
commit
837cd4eb8f
@ -50,6 +50,7 @@ func (f *BeaconEndpointFactory) Paths() []string {
|
||||
"/eth/v1/validator/duties/attester/{epoch}",
|
||||
"/eth/v1/validator/duties/proposer/{epoch}",
|
||||
"/eth/v1/validator/blocks/{slot}",
|
||||
"/eth/v1/validator/attestation_data",
|
||||
"/eth/v1/validator/aggregate_attestation",
|
||||
}
|
||||
}
|
||||
@ -258,6 +259,13 @@ func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
|
||||
GetResponse: &produceBlockResponseJson{},
|
||||
RequestURLLiterals: []string{"slot"},
|
||||
RequestQueryParams: []gateway.QueryParam{{Name: "randao_reveal", Hex: true}, {Name: "graffiti", Hex: true}},
|
||||
Err: &gateway.DefaultErrorJson{},
|
||||
}
|
||||
case "/eth/v1/validator/attestation_data":
|
||||
endpoint = gateway.Endpoint{
|
||||
GetResponse: &produceAttestationDataResponseJson{},
|
||||
RequestQueryParams: []gateway.QueryParam{{Name: "slot"}, {Name: "committee_index"}},
|
||||
Err: &gateway.DefaultErrorJson{},
|
||||
}
|
||||
case "/eth/v1/validator/aggregate_attestation":
|
||||
endpoint = gateway.Endpoint{
|
||||
|
@ -196,6 +196,11 @@ type produceBlockResponseJson struct {
|
||||
Data *beaconBlockJson `json:"data"`
|
||||
}
|
||||
|
||||
// produceAttestationDataResponseJson is used in /validator/attestation_data API endpoint.
|
||||
type produceAttestationDataResponseJson struct {
|
||||
Data *attestationDataJson `json:"data"`
|
||||
}
|
||||
|
||||
// aggregateAttestationResponseJson is used in /validator/aggregate_attestation API endpoint.
|
||||
type aggregateAttestationResponseJson struct {
|
||||
Data *attestationJson `json:"data"`
|
||||
|
@ -35,6 +35,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
@ -42,6 +43,7 @@ go_test(
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p/testing:go_default_library",
|
||||
"//beacon-chain/powchain/testing:go_default_library",
|
||||
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
@ -57,5 +59,6 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -184,7 +184,21 @@ func (vs *Server) ProduceBlock(ctx context.Context, req *v1.ProduceBlockRequest)
|
||||
// ProduceAttestationData requests that the beacon node produces attestation data for
|
||||
// the requested committee index and slot based on the nodes current head.
|
||||
func (vs *Server) ProduceAttestationData(ctx context.Context, req *v1.ProduceAttestationDataRequest) (*v1.ProduceAttestationDataResponse, error) {
|
||||
return nil, errors.New("Unimplemented")
|
||||
ctx, span := trace.StartSpan(ctx, "validatorv1.ProduceAttestationData")
|
||||
defer span.End()
|
||||
|
||||
v1alpha1req := &v1alpha1.AttestationDataRequest{
|
||||
Slot: req.Slot,
|
||||
CommitteeIndex: req.CommitteeIndex,
|
||||
}
|
||||
v1alpha1resp, err := vs.V1Alpha1Server.GetAttestationData(ctx, v1alpha1req)
|
||||
if err != nil {
|
||||
// We simply return err because it's already of a gRPC error type.
|
||||
return nil, err
|
||||
}
|
||||
attData := migration.V1Alpha1AttDataToV1(v1alpha1resp)
|
||||
|
||||
return &v1.ProduceAttestationDataResponse{Data: attData}, nil
|
||||
}
|
||||
|
||||
// GetAggregateAttestation aggregates all attestations matching the given attestation data root and slot, returning the aggregated result.
|
||||
|
@ -4,10 +4,12 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
@ -15,6 +17,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||
v1alpha1validator "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
@ -28,6 +31,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestGetAttesterDuties(t *testing.T) {
|
||||
@ -314,7 +318,7 @@ func TestGetProposerDuties_SyncNotReady(t *testing.T) {
|
||||
assert.ErrorContains(t, "Syncing to latest head, not ready to respond", err)
|
||||
}
|
||||
|
||||
func TestGetBlock(t *testing.T) {
|
||||
func TestProduceBlock(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
@ -405,6 +409,82 @@ func TestGetBlock(t *testing.T) {
|
||||
assert.DeepEqual(t, expectedAttSlashings, resp.Data.Body.AttesterSlashings)
|
||||
}
|
||||
|
||||
func TestProduceAttestationData(t *testing.T) {
|
||||
block := testutil.NewBeaconBlock()
|
||||
block.Block.Slot = 3*params.BeaconConfig().SlotsPerEpoch + 1
|
||||
targetBlock := testutil.NewBeaconBlock()
|
||||
targetBlock.Block.Slot = 1 * params.BeaconConfig().SlotsPerEpoch
|
||||
justifiedBlock := testutil.NewBeaconBlock()
|
||||
justifiedBlock.Block.Slot = 2 * params.BeaconConfig().SlotsPerEpoch
|
||||
blockRoot, err := block.Block.HashTreeRoot()
|
||||
require.NoError(t, err, "Could not hash beacon block")
|
||||
justifiedRoot, err := justifiedBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err, "Could not get signing root for justified block")
|
||||
targetRoot, err := targetBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err, "Could not get signing root for target block")
|
||||
slot := 3*params.BeaconConfig().SlotsPerEpoch + 1
|
||||
beaconState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetSlot(slot))
|
||||
err = beaconState.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: 2,
|
||||
Root: justifiedRoot[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
blockRoots := beaconState.BlockRoots()
|
||||
blockRoots[1] = blockRoot[:]
|
||||
blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:]
|
||||
blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:]
|
||||
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
|
||||
chainService := &mockChain.ChainService{
|
||||
Genesis: time.Now(),
|
||||
}
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
v1Alpha1Server := &v1alpha1validator.Server{
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttestationCache: cache.NewAttestationCache(),
|
||||
HeadFetcher: &mockChain.ChainService{
|
||||
State: beaconState, Root: blockRoot[:],
|
||||
},
|
||||
FinalizationFetcher: &mockChain.ChainService{
|
||||
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
|
||||
},
|
||||
TimeFetcher: &mockChain.ChainService{
|
||||
Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
},
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
}
|
||||
v1Server := &Server{
|
||||
V1Alpha1Server: v1Alpha1Server,
|
||||
}
|
||||
|
||||
req := &v1.ProduceAttestationDataRequest{
|
||||
CommitteeIndex: 0,
|
||||
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
}
|
||||
res, err := v1Server.ProduceAttestationData(context.Background(), req)
|
||||
require.NoError(t, err, "Could not get attestation info at slot")
|
||||
|
||||
expectedInfo := &v1.AttestationData{
|
||||
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
BeaconBlockRoot: blockRoot[:],
|
||||
Source: &v1.Checkpoint{
|
||||
Epoch: 2,
|
||||
Root: justifiedRoot[:],
|
||||
},
|
||||
Target: &v1.Checkpoint{
|
||||
Epoch: 3,
|
||||
Root: blockRoot[:],
|
||||
},
|
||||
}
|
||||
|
||||
if !proto.Equal(res.Data, expectedInfo) {
|
||||
t.Errorf("Expected attestation info to match, received %v, wanted %v", res, expectedInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAggregateAttestation(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
root1 := bytesutil.PadTo([]byte("root1"), 32)
|
||||
|
Loading…
Reference in New Issue
Block a user