mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-23 11:57:18 +00:00
Get Epoch (&Boundary) Attestations Helper Functions (#1103)
This commit is contained in:
parent
708daae04f
commit
53749c49d0
23
beacon-chain/core/epoch/BUILD.bazel
Normal file
23
beacon-chain/core/epoch/BUILD.bazel
Normal file
@ -0,0 +1,23 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["epoch_processing.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/core/types:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["epoch_processing_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
],
|
||||
)
|
68
beacon-chain/core/epoch/epoch_processing.go
Normal file
68
beacon-chain/core/epoch/epoch_processing.go
Normal file
@ -0,0 +1,68 @@
|
||||
package epoch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/types"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// Attestations returns the pending attestations of slots in the epoch
|
||||
// (state.slot-EPOCH_LENGTH...state.slot-1), not attestations that got
|
||||
// included in the chain during the epoch.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// this_epoch_attestations = [a for a in state.latest_attestations
|
||||
// if state.slot - EPOCH_LENGTH <= a.data.slot < state.slot]
|
||||
func Attestations(state *pb.BeaconState) []*pb.PendingAttestationRecord {
|
||||
epochLength := params.BeaconConfig().EpochLength
|
||||
var thisEpochAttestations []*pb.PendingAttestationRecord
|
||||
var earliestSlot uint64
|
||||
|
||||
for _, attestation := range state.LatestAttestations {
|
||||
|
||||
// If the state slot is less than epochLength, then the earliestSlot would
|
||||
// result in a negative number. Therefore we should default to
|
||||
// earliestSlot = 0 in this case.
|
||||
if state.Slot > epochLength {
|
||||
earliestSlot = state.Slot - epochLength
|
||||
}
|
||||
|
||||
if earliestSlot <= attestation.GetData().Slot && attestation.GetData().Slot < state.Slot {
|
||||
thisEpochAttestations = append(thisEpochAttestations, attestation)
|
||||
}
|
||||
}
|
||||
return thisEpochAttestations
|
||||
}
|
||||
|
||||
// BoundaryAttestations returns the pending attestations from
|
||||
// the epoch boundary block.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// [a for a in this_epoch_attestations if a.data.epoch_boundary_root ==
|
||||
// get_block_root(state, state.slot-EPOCH_LENGTH) and a.justified_slot ==
|
||||
// if state.slot - EPOCH_LENGTH <= a.data.slot < state.slot]
|
||||
func BoundaryAttestations(
|
||||
state *pb.BeaconState,
|
||||
thisEpochAttestations []*pb.PendingAttestationRecord,
|
||||
) ([]*pb.PendingAttestationRecord, error) {
|
||||
epochLength := params.BeaconConfig().EpochLength
|
||||
var boundaryAttestations []*pb.PendingAttestationRecord
|
||||
|
||||
for _, attestation := range thisEpochAttestations {
|
||||
|
||||
boundaryBlockRoot, err := types.BlockRoot(state, state.Slot-epochLength)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attestationData := attestation.GetData()
|
||||
sameRoot := bytes.Equal(attestationData.JustifiedBlockRootHash32, boundaryBlockRoot)
|
||||
sameSlotNum := attestationData.JustifiedSlot == state.JustifiedSlot
|
||||
if sameRoot && sameSlotNum {
|
||||
boundaryAttestations = append(boundaryAttestations, attestation)
|
||||
}
|
||||
}
|
||||
return boundaryAttestations, nil
|
||||
}
|
106
beacon-chain/core/epoch/epoch_processing_test.go
Normal file
106
beacon-chain/core/epoch/epoch_processing_test.go
Normal file
@ -0,0 +1,106 @@
|
||||
package epoch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func TestEpochAttestations_ok(t *testing.T) {
|
||||
if params.BeaconConfig().EpochLength != 64 {
|
||||
t.Fatalf("EpochLength should be 64 for these tests to pass")
|
||||
}
|
||||
|
||||
var pendingAttestations []*pb.PendingAttestationRecord
|
||||
for i := uint64(0); i < params.BeaconConfig().EpochLength*2; i++ {
|
||||
pendingAttestations = append(pendingAttestations, &pb.PendingAttestationRecord{
|
||||
Data: &pb.AttestationData{
|
||||
Slot: i,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
state := &pb.BeaconState{LatestAttestations: pendingAttestations}
|
||||
|
||||
tests := []struct {
|
||||
stateSlot uint64
|
||||
firstAttestationSlot uint64
|
||||
}{
|
||||
{
|
||||
stateSlot: 10,
|
||||
firstAttestationSlot: 0,
|
||||
},
|
||||
{
|
||||
stateSlot: 63,
|
||||
firstAttestationSlot: 0,
|
||||
},
|
||||
{
|
||||
stateSlot: 64,
|
||||
firstAttestationSlot: 64 - params.BeaconConfig().EpochLength,
|
||||
}, {
|
||||
stateSlot: 127,
|
||||
firstAttestationSlot: 127 - params.BeaconConfig().EpochLength,
|
||||
}, {
|
||||
stateSlot: 128,
|
||||
firstAttestationSlot: 128 - params.BeaconConfig().EpochLength,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
state.Slot = tt.stateSlot
|
||||
|
||||
if Attestations(state)[0].Data.Slot != tt.firstAttestationSlot {
|
||||
t.Errorf(
|
||||
"Result slot was an unexpected value. Wanted %d, got %d",
|
||||
tt.firstAttestationSlot,
|
||||
Attestations(state)[0].Data.Slot,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEpochBoundaryAttestations(t *testing.T) {
|
||||
if params.BeaconConfig().EpochLength != 64 {
|
||||
t.Fatalf("EpochLength should be 64 for these tests to pass")
|
||||
}
|
||||
|
||||
epochAttestations := []*pb.PendingAttestationRecord{
|
||||
{Data: &pb.AttestationData{JustifiedBlockRootHash32: []byte{0}, JustifiedSlot: 0}},
|
||||
{Data: &pb.AttestationData{JustifiedBlockRootHash32: []byte{1}, JustifiedSlot: 1}},
|
||||
{Data: &pb.AttestationData{JustifiedBlockRootHash32: []byte{2}, JustifiedSlot: 2}},
|
||||
{Data: &pb.AttestationData{JustifiedBlockRootHash32: []byte{3}, JustifiedSlot: 3}},
|
||||
}
|
||||
|
||||
var latestBlockRootHash [][]byte
|
||||
for i := uint64(0); i < params.BeaconConfig().EpochLength; i++ {
|
||||
latestBlockRootHash = append(latestBlockRootHash, []byte{byte(i)})
|
||||
}
|
||||
|
||||
state := &pb.BeaconState{
|
||||
LatestAttestations: epochAttestations,
|
||||
Slot: params.BeaconConfig().EpochLength,
|
||||
LatestBlockRootHash32S: [][]byte{},
|
||||
}
|
||||
|
||||
epochBoundaryAttestation, err := BoundaryAttestations(state, epochAttestations)
|
||||
if err == nil {
|
||||
t.Fatalf("EpochBoundaryAttestations should have failed with empty block root hash")
|
||||
}
|
||||
|
||||
state.LatestBlockRootHash32S = latestBlockRootHash
|
||||
epochBoundaryAttestation, err = BoundaryAttestations(state, epochAttestations)
|
||||
if err != nil {
|
||||
t.Fatalf("EpochBoundaryAttestations failed: %v", err)
|
||||
}
|
||||
|
||||
if epochBoundaryAttestation[0].GetData().JustifiedSlot != 0 {
|
||||
t.Errorf("Wanted justified slot 0 for epoch boundary attestation, got: %d", epochBoundaryAttestation[0].Data.JustifiedSlot)
|
||||
}
|
||||
|
||||
if !bytes.Equal(epochBoundaryAttestation[0].GetData().JustifiedBlockRootHash32, []byte{0}) {
|
||||
t.Errorf("Wanted justified block hash [0] for epoch boundary attestation, got: %v",
|
||||
epochBoundaryAttestation[0].Data.JustifiedBlockRootHash32)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user