From 1433fab0d4ca55bf38aa9d1f4ab7a878f4dbc0fc Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 18 Oct 2019 21:47:54 -0700 Subject: [PATCH] Use lowest included slot for precompute (#3805) * Fix attestations * Fix new * Testing state transition * Fix * Runtime works --- .../core/epoch/precompute/attestation.go | 21 +++++++++++++++---- .../core/epoch/precompute/attestation_test.go | 8 ++++--- beacon-chain/core/epoch/precompute/new.go | 6 ++++++ .../core/epoch/precompute/new_test.go | 13 ++++++++---- .../core/epoch/precompute/reward_penalty.go | 4 ++-- .../epoch/precompute/reward_penalty_test.go | 8 +++---- beacon-chain/core/epoch/precompute/type.go | 2 ++ 7 files changed, 45 insertions(+), 17 deletions(-) diff --git a/beacon-chain/core/epoch/precompute/attestation.go b/beacon-chain/core/epoch/precompute/attestation.go index 52b1df543..ef36e3601 100644 --- a/beacon-chain/core/epoch/precompute/attestation.go +++ b/beacon-chain/core/epoch/precompute/attestation.go @@ -40,7 +40,13 @@ func ProcessAttestations( if err != nil { return nil, nil, err } - vp = UpdateValidator(vp, v, indices, a) + // Get attestation slot to find lowest inclusion delayed attestation for each attested validators. + aSlot, err := helpers.AttestationDataSlot(state, a.Data) + if err != nil { + return nil, nil, err + + } + vp = UpdateValidator(vp, v, indices, a, aSlot) } bp = UpdateBalance(vp, bp) @@ -121,7 +127,9 @@ func SameHead(state *pb.BeaconState, a *pb.PendingAttestation) (bool, error) { } // UpdateValidator updates pre computed validator store. -func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb.PendingAttestation) []*Validator { +func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb.PendingAttestation, aSlot uint64) []*Validator { + inclusionSlot := aSlot + a.InclusionDelay + for _, i := range indices { if record.IsCurrentEpochAttester { vp[i].IsCurrentEpochAttester = true @@ -138,8 +146,13 @@ func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb if record.IsPrevEpochHeadAttester { vp[i].IsPrevEpochHeadAttester = true } - vp[i].InclusionDistance = a.InclusionDelay - vp[i].ProposerIndex = a.ProposerIndex + + // Update attestation inclusion info if inclusion slot is lower than before + if inclusionSlot < vp[i].InclusionSlot { + vp[i].InclusionSlot = aSlot + a.InclusionDelay + vp[i].InclusionDistance = a.InclusionDelay + vp[i].ProposerIndex = a.ProposerIndex + } } return vp } diff --git a/beacon-chain/core/epoch/precompute/attestation_test.go b/beacon-chain/core/epoch/precompute/attestation_test.go index 6acda58bc..23c333112 100644 --- a/beacon-chain/core/epoch/precompute/attestation_test.go +++ b/beacon-chain/core/epoch/precompute/attestation_test.go @@ -15,16 +15,18 @@ import ( ) func TestUpdateValidator(t *testing.T) { - vp := []*precompute.Validator{{}, {}, {}, {}, {}, {}} + e := params.BeaconConfig().FarFutureEpoch + vp := []*precompute.Validator{{}, {InclusionSlot:e}, {}, {InclusionSlot:e}, {}, {InclusionSlot:e}} record := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true, IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, IsPrevEpochHeadAttester: true} a := &pb.PendingAttestation{InclusionDelay: 1, ProposerIndex: 2} // Indices 1 3 and 5 attested - vp = precompute.UpdateValidator(vp, record, []uint64{1, 3, 5}, a) + vp = precompute.UpdateValidator(vp, record, []uint64{1, 3, 5}, a, 100) wanted := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true, - IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, IsPrevEpochHeadAttester: true, ProposerIndex: 2, InclusionDistance: 1} + IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, IsPrevEpochHeadAttester: true, + ProposerIndex: 2, InclusionDistance: 1, InclusionSlot: 101} wantedVp := []*precompute.Validator{{}, wanted, {}, wanted, {}, wanted} if !reflect.DeepEqual(vp, wantedVp) { t.Error("Incorrect attesting validator calculations") diff --git a/beacon-chain/core/epoch/precompute/new.go b/beacon-chain/core/epoch/precompute/new.go index 74e036c85..96ea49630 100644 --- a/beacon-chain/core/epoch/precompute/new.go +++ b/beacon-chain/core/epoch/precompute/new.go @@ -5,6 +5,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" + "github.com/prysmaticlabs/prysm/shared/params" "go.opencensus.io/trace" ) @@ -39,6 +40,11 @@ func New(ctx context.Context, state *pb.BeaconState) ([]*Validator, *Balance) { p.IsActivePrevEpoch = true bp.PrevEpoch += v.EffectiveBalance } + // Set inclusion slot and inclusion distance to be max, they will be compared and replaced + // with the lower values + p.InclusionSlot = params.BeaconConfig().FarFutureEpoch + p.InclusionDistance = params.BeaconConfig().FarFutureEpoch + vp[i] = p } return vp, bp diff --git a/beacon-chain/core/epoch/precompute/new_test.go b/beacon-chain/core/epoch/precompute/new_test.go index 8b80a6725..7c80da935 100644 --- a/beacon-chain/core/epoch/precompute/new_test.go +++ b/beacon-chain/core/epoch/precompute/new_test.go @@ -26,17 +26,22 @@ func TestNew(t *testing.T) { {WithdrawableEpoch: ffe, ExitEpoch: 1, EffectiveBalance: 100}, }, } + e := params.BeaconConfig().FarFutureEpoch v, b := precompute.New(context.Background(), s) - if !reflect.DeepEqual(v[0], &precompute.Validator{IsSlashed: true, CurrentEpochEffectiveBalance: 100}) { + if !reflect.DeepEqual(v[0], &precompute.Validator{IsSlashed: true, CurrentEpochEffectiveBalance: 100, + InclusionDistance: e, InclusionSlot: e}) { t.Error("Incorrect validator 0 status") } - if !reflect.DeepEqual(v[1], &precompute.Validator{IsWithdrawableCurrentEpoch: true, CurrentEpochEffectiveBalance: 100}) { + if !reflect.DeepEqual(v[1], &precompute.Validator{IsWithdrawableCurrentEpoch: true, CurrentEpochEffectiveBalance: 100, + InclusionDistance: e, InclusionSlot: e}) { t.Error("Incorrect validator 1 status") } - if !reflect.DeepEqual(v[2], &precompute.Validator{IsActiveCurrentEpoch: true, IsActivePrevEpoch: true, CurrentEpochEffectiveBalance: 100}) { + if !reflect.DeepEqual(v[2], &precompute.Validator{IsActiveCurrentEpoch: true, IsActivePrevEpoch: true, + CurrentEpochEffectiveBalance: 100, InclusionDistance: e, InclusionSlot: e}) { t.Error("Incorrect validator 2 status") } - if !reflect.DeepEqual(v[3], &precompute.Validator{IsActivePrevEpoch: true, CurrentEpochEffectiveBalance: 100}) { + if !reflect.DeepEqual(v[3], &precompute.Validator{IsActivePrevEpoch: true, CurrentEpochEffectiveBalance: 100, + InclusionDistance: e, InclusionSlot: e}) { t.Error("Incorrect validator 3 status") } diff --git a/beacon-chain/core/epoch/precompute/reward_penalty.go b/beacon-chain/core/epoch/precompute/reward_penalty.go index 70e888653..468671244 100644 --- a/beacon-chain/core/epoch/precompute/reward_penalty.go +++ b/beacon-chain/core/epoch/precompute/reward_penalty.go @@ -108,12 +108,12 @@ func proposerDeltaPrecompute(state *pb.BeaconState, bp *Balance, vp []*Validator totalBalance := bp.CurrentEpoch - for i, v := range vp { + for _, v := range vp { if v.IsPrevEpochAttester { vBalance := v.CurrentEpochEffectiveBalance baseReward := vBalance * params.BeaconConfig().BaseRewardFactor / mathutil.IntegerSquareRoot(totalBalance) / params.BeaconConfig().BaseRewardsPerEpoch proposerReward := baseReward / params.BeaconConfig().ProposerRewardQuotient - rewards[i] += proposerReward + rewards[v.ProposerIndex] += proposerReward } } return rewards, nil diff --git a/beacon-chain/core/epoch/precompute/reward_penalty_test.go b/beacon-chain/core/epoch/precompute/reward_penalty_test.go index 5a2158f6a..ead3c5d26 100644 --- a/beacon-chain/core/epoch/precompute/reward_penalty_test.go +++ b/beacon-chain/core/epoch/precompute/reward_penalty_test.go @@ -55,15 +55,15 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) { t.Fatal(err) } - // Indices that voted - wanted := uint64(32000001776) + // Indices that voted everything except for head, lost a bit money + wanted := uint64(31999995452) if state.Balances[4] != wanted { t.Errorf("wanted balance: %d, got: %d", wanted, state.Balances[4]) } - // Indices that did not vote - lose money - wanted = uint64(31999797616) + // Indices that did not vote, lost more money + wanted = uint64(31999949392) if state.Balances[0] != wanted { t.Errorf("wanted balance: %d, got: %d", wanted, state.Balances[0]) diff --git a/beacon-chain/core/epoch/precompute/type.go b/beacon-chain/core/epoch/precompute/type.go index c9712a7a9..467c22701 100644 --- a/beacon-chain/core/epoch/precompute/type.go +++ b/beacon-chain/core/epoch/precompute/type.go @@ -25,6 +25,8 @@ type Validator struct { // CurrentEpochEffectiveBalance is how much effective balance this validator validator has current epoch. CurrentEpochEffectiveBalance uint64 + // InclusionSlot is the slot of when the attestation gets included in the chain. + InclusionSlot uint64 // InclusionDistance is the distance between the assigned slot and this validator's attestation was included in block. InclusionDistance uint64 // ProposerIndex is the index of proposer at slot where this validator's attestation was included.