mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-03 08:37:37 +00:00
2616de1eb1
* add them * Ensure activation epoch does not overflow * add them all in * better check for overflow * fix tests * fix tests --------- Co-authored-by: Potuz <potuz@prysmaticlabs.com>
142 lines
4.8 KiB
Go
142 lines
4.8 KiB
Go
package rewards
|
|
|
|
import (
|
|
"context"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"path"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/golang/snappy"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
|
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
|
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
|
"github.com/prysmaticlabs/prysm/v5/testing/spectest/utils"
|
|
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
|
)
|
|
|
|
// Delta contains list of rewards and penalties.
|
|
type Delta struct {
|
|
Rewards []uint64 `json:"rewards"`
|
|
Penalties []uint64 `json:"penalties"`
|
|
}
|
|
|
|
// unmarshalSSZ deserializes specs data into a simple aggregating container.
|
|
func (d *Delta) unmarshalSSZ(buf []byte) error {
|
|
offset1 := binary.LittleEndian.Uint32(buf[:4])
|
|
offset2 := binary.LittleEndian.Uint32(buf[4:8])
|
|
|
|
for i := uint32(0); i < offset2-offset1; i += 8 {
|
|
d.Rewards = append(d.Rewards, binary.LittleEndian.Uint64(buf[offset1+i:offset1+i+8]))
|
|
d.Penalties = append(d.Penalties, binary.LittleEndian.Uint64(buf[offset2+i:offset2+i+8]))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RunPrecomputeRewardsAndPenaltiesTests executes "rewards/{basic, leak, random}" tests.
|
|
func RunPrecomputeRewardsAndPenaltiesTests(t *testing.T, config string) {
|
|
require.NoError(t, utils.SetConfig(t, config))
|
|
|
|
_, testsFolderPath := utils.TestFolders(t, config, "capella", "rewards")
|
|
testTypes, err := util.BazelListDirectories(testsFolderPath)
|
|
require.NoError(t, err)
|
|
|
|
if len(testTypes) == 0 {
|
|
t.Fatalf("No test types found for %s", testsFolderPath)
|
|
}
|
|
|
|
for _, testType := range testTypes {
|
|
testPath := fmt.Sprintf("rewards/%s/pyspec_tests", testType)
|
|
testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", testPath)
|
|
if len(testFolders) == 0 {
|
|
t.Fatalf("No test folders found for %s/%s/%s", config, "capella", testPath)
|
|
}
|
|
for _, folder := range testFolders {
|
|
helpers.ClearCache()
|
|
t.Run(fmt.Sprintf("%v/%v", testType, folder.Name()), func(t *testing.T) {
|
|
folderPath := path.Join(testsFolderPath, folder.Name())
|
|
runPrecomputeRewardsAndPenaltiesTest(t, folderPath)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func runPrecomputeRewardsAndPenaltiesTest(t *testing.T, testFolderPath string) {
|
|
ctx := context.Background()
|
|
preBeaconStateFile, err := util.BazelFileBytes(path.Join(testFolderPath, "pre.ssz_snappy"))
|
|
require.NoError(t, err)
|
|
preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile)
|
|
require.NoError(t, err, "Failed to decompress")
|
|
preBeaconStateBase := ðpb.BeaconStateCapella{}
|
|
require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal")
|
|
preBeaconState, err := state_native.InitializeFromProtoCapella(preBeaconStateBase)
|
|
require.NoError(t, err)
|
|
|
|
vp, bp, err := altair.InitializePrecomputeValidators(ctx, preBeaconState)
|
|
require.NoError(t, err)
|
|
vp, bp, err = altair.ProcessEpochParticipation(ctx, preBeaconState, bp, vp)
|
|
require.NoError(t, err)
|
|
|
|
activeBal, targetPrevious, targetCurrent, err := preBeaconState.UnrealizedCheckpointBalances()
|
|
require.NoError(t, err)
|
|
require.Equal(t, bp.ActiveCurrentEpoch, activeBal)
|
|
require.Equal(t, bp.CurrentEpochTargetAttested, targetCurrent)
|
|
require.Equal(t, bp.PrevEpochTargetAttested, targetPrevious)
|
|
|
|
deltas, err := altair.AttestationsDelta(preBeaconState, bp, vp)
|
|
require.NoError(t, err)
|
|
|
|
rewards := make([]uint64, len(deltas))
|
|
penalties := make([]uint64, len(deltas))
|
|
for i, d := range deltas {
|
|
rewards[i] = d.HeadReward + d.SourceReward + d.TargetReward
|
|
penalties[i] = d.SourcePenalty + d.TargetPenalty + d.InactivityPenalty
|
|
}
|
|
|
|
totalSpecTestRewards := make([]uint64, len(rewards))
|
|
totalSpecTestPenalties := make([]uint64, len(penalties))
|
|
|
|
// Fetch delta files. i.e. source_deltas.ssz_snappy, etc.
|
|
testfiles, err := util.BazelListFiles(path.Join(testFolderPath))
|
|
require.NoError(t, err)
|
|
deltaFiles := make([]string, 0, len(testfiles))
|
|
for _, tf := range testfiles {
|
|
if strings.Contains(tf, "deltas") {
|
|
deltaFiles = append(deltaFiles, tf)
|
|
}
|
|
}
|
|
if len(deltaFiles) == 0 {
|
|
t.Fatal("No delta files")
|
|
}
|
|
|
|
for _, dFile := range deltaFiles {
|
|
sourceFile, err := util.BazelFileBytes(path.Join(testFolderPath, dFile))
|
|
require.NoError(t, err)
|
|
sourceSSZ, err := snappy.Decode(nil /* dst */, sourceFile)
|
|
require.NoError(t, err, "Failed to decompress")
|
|
d := &Delta{}
|
|
require.NoError(t, d.unmarshalSSZ(sourceSSZ), "Failed to unmarshal")
|
|
for i, reward := range d.Rewards {
|
|
totalSpecTestRewards[i] += reward
|
|
}
|
|
for i, penalty := range d.Penalties {
|
|
totalSpecTestPenalties[i] += penalty
|
|
}
|
|
}
|
|
|
|
if !reflect.DeepEqual(rewards, totalSpecTestRewards) {
|
|
t.Error("Rewards don't match")
|
|
t.Log(rewards)
|
|
t.Log(totalSpecTestRewards)
|
|
}
|
|
if !reflect.DeepEqual(penalties, totalSpecTestPenalties) {
|
|
t.Error("Penalties don't match")
|
|
t.Log(penalties)
|
|
t.Log(totalSpecTestPenalties)
|
|
}
|
|
}
|