github.com/prysmaticlabs/prysm@v1.4.4/spectest/shared/phase0/rewards/rewards_penalties.go (about)

     1  package rewards
     2  
     3  import (
     4  	"context"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"path"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/golang/snappy"
    12  	"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
    13  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    14  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    15  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    16  	"github.com/prysmaticlabs/prysm/shared/testutil"
    17  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    18  	"github.com/prysmaticlabs/prysm/spectest/utils"
    19  )
    20  
    21  // Delta contains list of rewards and penalties.
    22  type Delta struct {
    23  	Rewards   []uint64 `json:"rewards"`
    24  	Penalties []uint64 `json:"penalties"`
    25  }
    26  
    27  // unmarshalSSZ deserializes specs data into a simple aggregating container.
    28  func (d *Delta) unmarshalSSZ(buf []byte) error {
    29  	offset1 := binary.LittleEndian.Uint32(buf[:4])
    30  	offset2 := binary.LittleEndian.Uint32(buf[4:8])
    31  
    32  	for i := uint32(0); i < offset2-offset1; i += 8 {
    33  		d.Rewards = append(d.Rewards, binary.LittleEndian.Uint64(buf[offset1+i:offset1+i+8]))
    34  		d.Penalties = append(d.Penalties, binary.LittleEndian.Uint64(buf[offset2+i:offset2+i+8]))
    35  	}
    36  	return nil
    37  }
    38  
    39  var deltaFiles = []string{
    40  	"source_deltas.ssz_snappy",
    41  	"target_deltas.ssz_snappy",
    42  	"head_deltas.ssz_snappy",
    43  	"inactivity_penalty_deltas.ssz_snappy",
    44  	"inclusion_delay_deltas.ssz_snappy",
    45  }
    46  
    47  // RunPrecomputeRewardsAndPenaltiesTests executes "rewards/{basic, leak, random}" tests.
    48  func RunPrecomputeRewardsAndPenaltiesTests(t *testing.T, config string) {
    49  	require.NoError(t, utils.SetConfig(t, config))
    50  	testTypes := []string{"basic", "leak", "random"}
    51  	for _, testType := range testTypes {
    52  		testFolders, testsFolderPath := utils.TestFolders(t, config, "phase0", fmt.Sprintf("rewards/%s/pyspec_tests", testType))
    53  		for _, folder := range testFolders {
    54  			helpers.ClearCache()
    55  			t.Run(fmt.Sprintf("%v/%v", testType, folder.Name()), func(t *testing.T) {
    56  				folderPath := path.Join(testsFolderPath, folder.Name())
    57  				runPrecomputeRewardsAndPenaltiesTest(t, folderPath)
    58  			})
    59  		}
    60  	}
    61  }
    62  
    63  func runPrecomputeRewardsAndPenaltiesTest(t *testing.T, testFolderPath string) {
    64  	ctx := context.Background()
    65  	preBeaconStateFile, err := testutil.BazelFileBytes(path.Join(testFolderPath, "pre.ssz_snappy"))
    66  	require.NoError(t, err)
    67  	preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile)
    68  	require.NoError(t, err, "Failed to decompress")
    69  	preBeaconStateBase := &pb.BeaconState{}
    70  	require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal")
    71  	preBeaconState, err := v1.InitializeFromProto(preBeaconStateBase)
    72  	require.NoError(t, err)
    73  
    74  	vp, bp, err := precompute.New(ctx, preBeaconState)
    75  	require.NoError(t, err)
    76  	vp, bp, err = precompute.ProcessAttestations(ctx, preBeaconState, vp, bp)
    77  	require.NoError(t, err)
    78  
    79  	rewards, penalties, err := precompute.AttestationsDelta(preBeaconState, bp, vp)
    80  	require.NoError(t, err)
    81  	pRewards, err := precompute.ProposersDelta(preBeaconState, bp, vp)
    82  	require.NoError(t, err)
    83  	if len(rewards) != len(penalties) && len(rewards) != len(pRewards) {
    84  		t.Fatal("Incorrect lengths")
    85  	}
    86  	for i, reward := range rewards {
    87  		rewards[i] = reward + pRewards[i]
    88  	}
    89  
    90  	totalSpecTestRewards := make([]uint64, len(rewards))
    91  	totalSpecTestPenalties := make([]uint64, len(penalties))
    92  
    93  	for _, dFile := range deltaFiles {
    94  		sourceFile, err := testutil.BazelFileBytes(path.Join(testFolderPath, dFile))
    95  		require.NoError(t, err)
    96  		sourceSSZ, err := snappy.Decode(nil /* dst */, sourceFile)
    97  		require.NoError(t, err, "Failed to decompress")
    98  		d := &Delta{}
    99  		require.NoError(t, d.unmarshalSSZ(sourceSSZ), "Failed to unmarshal")
   100  		for i, reward := range d.Rewards {
   101  			totalSpecTestRewards[i] += reward
   102  		}
   103  		for i, penalty := range d.Penalties {
   104  			totalSpecTestPenalties[i] += penalty
   105  		}
   106  	}
   107  
   108  	if !reflect.DeepEqual(rewards, totalSpecTestRewards) {
   109  		t.Error("Rewards don't match")
   110  		t.Log(rewards)
   111  		t.Log(totalSpecTestRewards)
   112  	}
   113  	if !reflect.DeepEqual(penalties, totalSpecTestPenalties) {
   114  		t.Error("Penalties don't match")
   115  		t.Log(penalties)
   116  		t.Log(totalSpecTestPenalties)
   117  	}
   118  }