Request Assignments From Canonical Slot Upon Activation (#2097)

* request assignments from the canonical head slot at first

* imports
This commit is contained in:
Raul Jordan 2019-03-27 20:03:25 -05:00 committed by GitHub
parent 62ad3dfd61
commit 839845645c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 2 deletions

View File

@ -7,9 +7,11 @@ import (
"time"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@ -131,6 +133,22 @@ func (vs *ValidatorServer) CommitteeAssignment(
if err != nil {
return nil, fmt.Errorf("could not get active validator index: %v", err)
}
chainHead, err := vs.beaconDB.ChainHead()
if err != nil {
return nil, fmt.Errorf("could not get chain head: %v", err)
}
headRoot, err := hashutil.HashBeaconBlock(chainHead)
if err != nil {
return nil, fmt.Errorf("could not hash block: %v", err)
}
for beaconState.Slot < req.EpochStart {
beaconState, err = state.ExecuteStateTransition(
ctx, beaconState, nil /* block */, headRoot, state.DefaultConfig(),
)
if err != nil {
return nil, fmt.Errorf("could not execute head transition: %v", err)
}
}
committee, shard, slot, isProposer, err :=
helpers.CommitteeAssignment(beaconState, req.EpochStart, uint64(idx), false)

View File

@ -5,6 +5,7 @@ import (
"time"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
var _ = Validator(&fakeValidator{})
@ -15,6 +16,7 @@ type fakeValidator struct {
WaitForChainStartCalled bool
NextSlotRet <-chan uint64
NextSlotCalled bool
CanonicalHeadSlotCalled bool
UpdateAssignmentsCalled bool
UpdateAssignmentsArg1 uint64
UpdateAssignmentsRet error
@ -43,6 +45,11 @@ func (fv *fakeValidator) WaitForActivation(_ context.Context) error {
return nil
}
func (fv *fakeValidator) CanonicalHeadSlot(_ context.Context) (uint64, error) {
fv.CanonicalHeadSlotCalled = true
return params.BeaconConfig().GenesisSlot, nil
}
func (fv *fakeValidator) SlotDeadline(_ uint64) time.Time {
fv.SlotDeadlineCalled = true
return time.Now()

View File

@ -17,6 +17,7 @@ type Validator interface {
Done()
WaitForChainStart(ctx context.Context) error
WaitForActivation(ctx context.Context) error
CanonicalHeadSlot(ctx context.Context) (uint64, error)
NextSlot() <-chan uint64
SlotDeadline(slot uint64) time.Time
LogValidatorGainsAndLosses(ctx context.Context, slot uint64) error
@ -44,8 +45,12 @@ func run(ctx context.Context, v Validator) {
if err := v.WaitForActivation(ctx); err != nil {
log.Fatalf("Could not wait for validator activation: %v", err)
}
if err := v.UpdateAssignments(ctx, params.BeaconConfig().GenesisSlot); err != nil {
handleAssignmentError(err, params.BeaconConfig().GenesisSlot)
headSlot, err := v.CanonicalHeadSlot(ctx)
if err != nil {
log.Fatalf("Could not get current canonical head slot: %v", err)
}
if err := v.UpdateAssignments(ctx, headSlot); err != nil {
handleAssignmentError(err, headSlot)
}
for {
ctx, span := trace.StartSpan(ctx, "processSlot")

View File

@ -107,6 +107,18 @@ func (v *validator) WaitForActivation(ctx context.Context) error {
return nil
}
// CanonicalHeadSlot returns the slot of canonical block currently found in the
// beacon chain via RPC.
func (v *validator) CanonicalHeadSlot(ctx context.Context) (uint64, error) {
ctx, span := trace.StartSpan(ctx, "validator.CanonicalHeadSlot")
defer span.End()
head, err := v.beaconClient.CanonicalHead(ctx, &ptypes.Empty{})
if err != nil {
return params.BeaconConfig().GenesisSlot, err
}
return head.Slot, nil
}
// NextSlot emits the next slot number at the start time of that slot.
func (v *validator) NextSlot() <-chan uint64 {
return v.ticker.C()

View File

@ -250,6 +250,44 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
testutil.AssertLogsContain(t, hook, "Validator activated")
}
func TestCanonicalHeadSlot_FailedRPC(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockBeaconServiceClient(ctrl)
v := validator{
key: validatorKey,
beaconClient: client,
}
client.EXPECT().CanonicalHead(
gomock.Any(),
gomock.Any(),
).Return(nil, errors.New("failed"))
if _, err := v.CanonicalHeadSlot(context.Background()); !strings.Contains(err.Error(), "failed") {
t.Errorf("Wanted: %v, received: %v", "failed", err)
}
}
func TestCanonicalHeadSlot_OK(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockBeaconServiceClient(ctrl)
v := validator{
key: validatorKey,
beaconClient: client,
}
client.EXPECT().CanonicalHead(
gomock.Any(),
gomock.Any(),
).Return(&pbp2p.BeaconBlock{Slot: params.BeaconConfig().GenesisSlot}, nil)
headSlot, err := v.CanonicalHeadSlot(context.Background())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if headSlot != params.BeaconConfig().GenesisSlot {
t.Errorf("Mismatch slots, wanted: %v, received: %v", params.BeaconConfig().GenesisSlot, headSlot)
}
}
func TestUpdateAssignments_ReturnsError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()