From 91df0112c7942f844178027877a0613636ea5003 Mon Sep 17 00:00:00 2001 From: Victor Farazdagi Date: Tue, 6 Apr 2021 09:08:44 +0300 Subject: [PATCH] Add LatestWeakSubjectivityEpoch() method (#8707) * Add IsWithinWeakSubjectivityPeriod helper method * Add LatestWeakSubjectivityEpoch method Co-authored-by: Raul Jordan --- beacon-chain/core/helpers/weak_subjectivity.go | 15 +++++++++++++++ beacon-chain/rpc/beacon/blocks.go | 2 +- beacon-chain/rpc/beacon/blocks_test.go | 17 ++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/beacon-chain/core/helpers/weak_subjectivity.go b/beacon-chain/core/helpers/weak_subjectivity.go index ce41bbaa8..a8981c04c 100644 --- a/beacon-chain/core/helpers/weak_subjectivity.go +++ b/beacon-chain/core/helpers/weak_subjectivity.go @@ -141,3 +141,18 @@ func IsWithinWeakSubjectivityPeriod( return currentEpoch <= wsStateEpoch+wsPeriod, nil } + +// LatestWeakSubjectivityEpoch returns epoch of the most recent weak subjectivity checkpoint known to a node. +// +// Within the weak subjectivity period, if two conflicting blocks are finalized, 1/3 - D (D := safety decay) +// of validators will get slashed. Therefore, it is safe to assume that any finalized checkpoint within that +// period is protected by this safety margin. +func LatestWeakSubjectivityEpoch(st iface.ReadOnlyBeaconState) (types.Epoch, error) { + wsPeriod, err := ComputeWeakSubjectivityPeriod(st) + if err != nil { + return 0, err + } + + finalizedEpoch := st.FinalizedCheckpointEpoch() + return finalizedEpoch - (finalizedEpoch % wsPeriod), nil +} diff --git a/beacon-chain/rpc/beacon/blocks.go b/beacon-chain/rpc/beacon/blocks.go index d46554b37..acf295171 100644 --- a/beacon-chain/rpc/beacon/blocks.go +++ b/beacon-chain/rpc/beacon/blocks.go @@ -368,7 +368,7 @@ func (bs *Server) GetWeakSubjectivityCheckpoint(ctx context.Context, _ *ptypes.E if err != nil { return nil, status.Error(codes.Internal, "Could not get head state") } - wsEpoch, err := helpers.ComputeWeakSubjectivityPeriod(hs) + wsEpoch, err := helpers.LatestWeakSubjectivityEpoch(hs) if err != nil { return nil, status.Error(codes.Internal, "Could not get weak subjectivity epoch") } diff --git a/beacon-chain/rpc/beacon/blocks_test.go b/beacon-chain/rpc/beacon/blocks_test.go index 8521d192e..aa784963f 100644 --- a/beacon-chain/rpc/beacon/blocks_test.go +++ b/beacon-chain/rpc/beacon/blocks_test.go @@ -711,6 +711,18 @@ func TestServer_GetWeakSubjectivityCheckpoint(t *testing.T) { require.NoError(t, db.SaveState(ctx, beaconState, genesisBlockRoot)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisBlockRoot)) + // Finalized checkpoint. + finalizedEpoch := types.Epoch(1020) + require.NoError(t, beaconState.SetSlot(types.Slot(finalizedEpoch.Mul(uint64(params.BeaconConfig().SlotsPerEpoch))))) + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{ + Epoch: finalizedEpoch - 1, + Root: bytesutil.PadTo([]byte{'A'}, 32), + })) + require.NoError(t, beaconState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: finalizedEpoch, + Root: bytesutil.PadTo([]byte{'B'}, 32), + })) + chainService := &chainMock.ChainService{State: beaconState} server := &Server{ Ctx: ctx, @@ -720,9 +732,12 @@ func TestServer_GetWeakSubjectivityCheckpoint(t *testing.T) { StateGen: stategen.New(db), } + wsEpoch, err := helpers.ComputeWeakSubjectivityPeriod(beaconState) + require.NoError(t, err) + c, err := server.GetWeakSubjectivityCheckpoint(ctx, &ptypes.Empty{}) require.NoError(t, err) - e := types.Epoch(257) + e := finalizedEpoch - (finalizedEpoch % wsEpoch) require.Equal(t, e, c.Epoch) wsState, err := server.StateGen.StateBySlot(ctx, params.BeaconConfig().SlotsPerEpoch.Mul(uint64(e))) require.NoError(t, err)