diff --git a/beacon-chain/blockchain/metrics_test.go b/beacon-chain/blockchain/metrics_test.go index 1bd6606c89..0c223074ef 100644 --- a/beacon-chain/blockchain/metrics_test.go +++ b/beacon-chain/blockchain/metrics_test.go @@ -9,16 +9,6 @@ import ( "github.com/prysmaticlabs/prysm/v4/testing/util" ) -func TestReportEpochMetrics_BadHeadState(t *testing.T) { - s, err := util.NewBeaconState() - require.NoError(t, err) - h, err := util.NewBeaconState() - require.NoError(t, err) - require.NoError(t, h.SetValidators(nil)) - err = reportEpochMetrics(context.Background(), s, h) - require.ErrorContains(t, "failed to initialize precompute: nil validators in state", err) -} - func TestReportEpochMetrics_BadAttestation(t *testing.T) { s, err := util.NewBeaconState() require.NoError(t, err) diff --git a/beacon-chain/core/epoch/precompute/justification_finalization_test.go b/beacon-chain/core/epoch/precompute/justification_finalization_test.go index ea55723a86..1462c222be 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization_test.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization_test.go @@ -59,7 +59,7 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *te a := params.BeaconConfig().MaxEffectiveBalance blockRoots := make([][]byte, params.BeaconConfig().SlotsPerEpoch*2+1) for i := 0; i < len(blockRoots); i++ { - blockRoots[i] = []byte{byte(i)} + blockRoots[i] = bytesutil.PadTo([]byte{byte(i)}, 32) } base := ðpb.BeaconState{ Slot: params.BeaconConfig().SlotsPerEpoch*2 + 1, diff --git a/beacon-chain/core/helpers/beacon_committee_test.go b/beacon-chain/core/helpers/beacon_committee_test.go index 4b6d4eaed2..f0ed87dadb 100644 --- a/beacon-chain/core/helpers/beacon_committee_test.go +++ b/beacon-chain/core/helpers/beacon_committee_test.go @@ -128,10 +128,14 @@ func TestCommitteeAssignments_NoProposerForSlot0(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, } } + mixes := make([][]byte, fieldparams.RandaoMixesLength) + for i := range mixes { + mixes[i] = bytesutil.PadTo([]byte{}, 32) + } state, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{ Validators: validators, Slot: 2 * params.BeaconConfig().SlotsPerEpoch, // epoch 2 - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + RandaoMixes: mixes, }) require.NoError(t, err) _, proposerIndexToSlots, err := CommitteeAssignments(context.Background(), state, 0) @@ -157,11 +161,15 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, } } + mixes := make([][]byte, fieldparams.RandaoMixesLength) + for i := range mixes { + mixes[i] = bytesutil.PadTo([]byte{}, 32) + } state, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{ Validators: validators, Slot: 2 * params.BeaconConfig().SlotsPerEpoch, // epoch 2 - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + RandaoMixes: mixes, }) require.NoError(t, err) diff --git a/beacon-chain/core/transition/transition_test.go b/beacon-chain/core/transition/transition_test.go index 70d62ecead..bd4356b0fa 100644 --- a/beacon-chain/core/transition/transition_test.go +++ b/beacon-chain/core/transition/transition_test.go @@ -375,9 +375,7 @@ func TestProcessEpochPrecompute_CanProcess(t *testing.T) { slashing := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector) base := ðpb.BeaconState{ Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch)) + 1, - BlockRoots: make([][]byte, 128), Slashings: slashing, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), CurrentEpochAttestations: atts, FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, JustificationBits: bitfield.Bitvector4{0x00}, diff --git a/beacon-chain/rpc/eth/beacon/validator.go b/beacon-chain/rpc/eth/beacon/validator.go index c79d7e2bc4..1e5f5b5b92 100644 --- a/beacon-chain/rpc/eth/beacon/validator.go +++ b/beacon-chain/rpc/eth/beacon/validator.go @@ -3,6 +3,7 @@ package beacon import ( "context" "strconv" + "strings" "github.com/pkg/errors" corehelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers" @@ -279,8 +280,8 @@ func valContainersByRequestIds(state state.BeaconState, validatorIds [][]byte) ( valIndex = primitives.ValidatorIndex(index) } validator, err := state.ValidatorAtIndex(valIndex) - if _, ok := err.(*statenative.ValidatorIndexOutOfRangeError); ok { - // Ignore well-formed yet unknown indexes. + if err != nil && strings.Contains(err.Error(), "out of bounds") { + // Ignore indexes out of bounds. continue } if err != nil { diff --git a/beacon-chain/rpc/eth/validator/validator_test.go b/beacon-chain/rpc/eth/validator/validator_test.go index 7818a583ac..c9725c9206 100644 --- a/beacon-chain/rpc/eth/validator/validator_test.go +++ b/beacon-chain/rpc/eth/validator/validator_test.go @@ -226,9 +226,12 @@ func TestGetProposerDuties(t *testing.T) { genesisRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") roots := make([][]byte, fieldparams.BlockRootsLength) + for i := range roots { + roots[i] = bytesutil.PadTo([]byte{}, 32) + } roots[0] = genesisRoot[:] // We DON'T WANT this root to be returned when testing the next epoch - roots[31] = []byte("next_epoch_dependent_root") + roots[31] = bytesutil.PadTo([]byte("next_epoch_dependent_root"), 32) db := dbutil.SetupDB(t) pubKeys := make([][]byte, len(deposits)) @@ -270,10 +273,10 @@ func TestGetProposerDuties(t *testing.T) { } vid, _, has := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(11, [32]byte{}) require.Equal(t, true, has) - require.Equal(t, primitives.ValidatorIndex(9982), vid) + require.Equal(t, primitives.ValidatorIndex(12289), vid) require.NotNil(t, expectedDuty, "Expected duty for slot 11 not found") - assert.Equal(t, primitives.ValidatorIndex(9982), expectedDuty.ValidatorIndex) - assert.DeepEqual(t, pubKeys[9982], expectedDuty.Pubkey) + assert.Equal(t, primitives.ValidatorIndex(12289), expectedDuty.ValidatorIndex) + assert.DeepEqual(t, pubKeys[12289], expectedDuty.Pubkey) }) t.Run("Next epoch", func(t *testing.T) { @@ -309,10 +312,10 @@ func TestGetProposerDuties(t *testing.T) { } vid, _, has := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(43, [32]byte{}) require.Equal(t, true, has) - require.Equal(t, primitives.ValidatorIndex(4863), vid) + require.Equal(t, primitives.ValidatorIndex(1360), vid) require.NotNil(t, expectedDuty, "Expected duty for slot 43 not found") - assert.Equal(t, primitives.ValidatorIndex(4863), expectedDuty.ValidatorIndex) - assert.DeepEqual(t, pubKeys[4863], expectedDuty.Pubkey) + assert.Equal(t, primitives.ValidatorIndex(1360), expectedDuty.ValidatorIndex) + assert.DeepEqual(t, pubKeys[1360], expectedDuty.Pubkey) }) t.Run("Prune payload ID cache ok", func(t *testing.T) { @@ -336,9 +339,6 @@ func TestGetProposerDuties(t *testing.T) { req := ðpbv1.ProposerDutiesRequest{ Epoch: 1, } - vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(1, 1, [8]byte{1}, [32]byte{2}) - vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(31, 2, [8]byte{2}, [32]byte{3}) - vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(32, 4309, [8]byte{3}, [32]byte{4}) _, err = vs.GetProposerDuties(ctx, req) require.NoError(t, err) @@ -351,7 +351,7 @@ func TestGetProposerDuties(t *testing.T) { require.Equal(t, primitives.ValidatorIndex(0), vid) vid, _, has = vs.ProposerSlotIndexCache.GetProposerPayloadIDs(32, [32]byte{}) require.Equal(t, true, has) - require.Equal(t, primitives.ValidatorIndex(4309), vid) + require.Equal(t, primitives.ValidatorIndex(10565), vid) }) t.Run("Epoch out of bound", func(t *testing.T) { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go index 242787de93..6aac5fccf1 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go @@ -74,8 +74,12 @@ func TestSubmitAggregateAndProof_CantFindValidatorIndex(t *testing.T) { func TestSubmitAggregateAndProof_IsAggregatorAndNoAtts(t *testing.T) { ctx := context.Background() + mixes := make([][]byte, fieldparams.RandaoMixesLength) + for i := range mixes { + mixes[i] = bytesutil.PadTo([]byte{}, 32) + } s, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{ - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + RandaoMixes: mixes, Validators: []*ethpb.Validator{ {PublicKey: pubKey(0)}, {PublicKey: pubKey(1)}, diff --git a/beacon-chain/state/state-native/custom-types/block_roots_test.go b/beacon-chain/state/state-native/custom-types/block_roots_test.go index 37ed99df24..5b1da6d4e7 100644 --- a/beacon-chain/state/state-native/custom-types/block_roots_test.go +++ b/beacon-chain/state/state-native/custom-types/block_roots_test.go @@ -62,7 +62,7 @@ func TestBlockRoots_MarshalSSZTo(t *testing.T) { } func TestBlockRoots_MarshalSSZ(t *testing.T) { - d := BlockRoots{} + d := BlockRoots(make([][32]byte, fieldparams.BlockRootsLength)) d[0] = [32]byte{'f', 'o', 'o'} d[1] = [32]byte{'b', 'a', 'r'} b, err := d.MarshalSSZ() @@ -86,7 +86,7 @@ func TestBlockRoots_SizeSSZ(t *testing.T) { func TestBlockRoots_Slice(t *testing.T) { a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'} - roots := BlockRoots{} + roots := BlockRoots(make([][32]byte, fieldparams.BlockRootsLength)) roots[1] = a roots[10] = b roots[100] = c diff --git a/beacon-chain/state/state-native/custom-types/randao_mixes_test.go b/beacon-chain/state/state-native/custom-types/randao_mixes_test.go index 56c03b977e..3680a8d4e0 100644 --- a/beacon-chain/state/state-native/custom-types/randao_mixes_test.go +++ b/beacon-chain/state/state-native/custom-types/randao_mixes_test.go @@ -8,14 +8,6 @@ import ( "github.com/prysmaticlabs/prysm/v4/testing/assert" ) -func TestRandaoMixes_Casting(t *testing.T) { - var b [][32]byte - d := RandaoMixes(b) - if !reflect.DeepEqual([fieldparams.RandaoMixesLength][32]byte(d), b) { - t.Errorf("Unequal: %v = %v", d, b) - } -} - func TestRandaoMixes_UnmarshalSSZ(t *testing.T) { t.Run("Ok", func(t *testing.T) { d := RandaoMixes{} @@ -70,7 +62,7 @@ func TestRandaoMixes_MarshalSSZTo(t *testing.T) { } func TestRandaoMixes_MarshalSSZ(t *testing.T) { - d := RandaoMixes{} + d := RandaoMixes(make([][32]byte, fieldparams.RandaoMixesLength)) d[0] = [32]byte{'f', 'o', 'o'} d[1] = [32]byte{'b', 'a', 'r'} b, err := d.MarshalSSZ() @@ -94,7 +86,7 @@ func TestRandaoMixes_SizeSSZ(t *testing.T) { func TestRandaoMixes_Slice(t *testing.T) { a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'} - roots := RandaoMixes{} + roots := RandaoMixes(make([][32]byte, fieldparams.RandaoMixesLength)) roots[1] = a roots[10] = b roots[100] = c diff --git a/beacon-chain/state/state-native/custom-types/state_roots_test.go b/beacon-chain/state/state-native/custom-types/state_roots_test.go index 4d5ea96236..9b150bd9c8 100644 --- a/beacon-chain/state/state-native/custom-types/state_roots_test.go +++ b/beacon-chain/state/state-native/custom-types/state_roots_test.go @@ -8,14 +8,6 @@ import ( "github.com/prysmaticlabs/prysm/v4/testing/assert" ) -func TestStateRoots_Casting(t *testing.T) { - var b [][32]byte - d := StateRoots(b) - if !reflect.DeepEqual([fieldparams.StateRootsLength][32]byte(d), b) { - t.Errorf("Unequal: %v = %v", d, b) - } -} - func TestStateRoots_UnmarshalSSZ(t *testing.T) { t.Run("Ok", func(t *testing.T) { d := StateRoots{} @@ -70,7 +62,7 @@ func TestStateRoots_MarshalSSZTo(t *testing.T) { } func TestStateRoots_MarshalSSZ(t *testing.T) { - d := StateRoots{} + d := StateRoots(make([][32]byte, fieldparams.StateRootsLength)) d[0] = [32]byte{'f', 'o', 'o'} d[1] = [32]byte{'b', 'a', 'r'} b, err := d.MarshalSSZ() @@ -94,7 +86,7 @@ func TestStateRoots_SizeSSZ(t *testing.T) { func TestStateRoots_Slice(t *testing.T) { a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'} - roots := StateRoots{} + roots := StateRoots(make([][32]byte, fieldparams.StateRootsLength)) roots[1] = a roots[10] = b roots[100] = c diff --git a/beacon-chain/state/state-native/getters_validator_test.go b/beacon-chain/state/state-native/getters_validator_test.go index 4d09835e69..f3dc17e1a9 100644 --- a/beacon-chain/state/state-native/getters_validator_test.go +++ b/beacon-chain/state/state-native/getters_validator_test.go @@ -4,46 +4,11 @@ import ( "testing" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/state" statenative "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native" - testtmpl "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v4/testing/require" "github.com/prysmaticlabs/prysm/v4/testing/util" ) -func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Phase0(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { - return statenative.InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ - Validators: nil, - }) - }) -} - -func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Altair(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { - return statenative.InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ - Validators: nil, - }) - }) -} - -func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Bellatrix(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { - return statenative.InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ - Validators: nil, - }) - }) -} - -func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Capella(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { - return statenative.InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{ - Validators: nil, - }) - }) -} - func TestValidatorIndexOutOfRangeError(t *testing.T) { err := statenative.NewValidatorIndexOutOfRangeError(1) require.Equal(t, err.Error(), "index 1 out of range") diff --git a/beacon-chain/state/state-native/helpers_test.go b/beacon-chain/state/state-native/helpers_test.go index 4f6e3b92c6..22a8d3a409 100644 --- a/beacon-chain/state/state-native/helpers_test.go +++ b/beacon-chain/state/state-native/helpers_test.go @@ -323,7 +323,7 @@ func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) { errMsg: fmt.Sprintf("Wanted type of %T", []*ethpb.Eth1Data{}), }, { - name: "Balance", + name: "Balances", args: func() *args { return &args{ field: types.FieldIndex(12), @@ -340,11 +340,11 @@ func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) { return &args{ field: types.FieldIndex(11), indices: []uint64{}, - elements: []*ethpb.Validator{ + elements: NewMultiValueValidators([]*ethpb.Validator{ { ActivationEpoch: 1, }, - }, + }), convertAll: true, } }, @@ -361,7 +361,7 @@ func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) { } }, wantHex: nil, - errMsg: fmt.Sprintf("Wanted type of %T", []*ethpb.Validator{}), + errMsg: fmt.Sprintf("Wanted type of %T", &MultiValueValidators{}), }, { name: "Attestations", diff --git a/beacon-chain/state/state-native/references_test.go b/beacon-chain/state/state-native/references_test.go index 5167c407d6..ce7dcc704d 100644 --- a/beacon-chain/state/state-native/references_test.go +++ b/beacon-chain/state/state-native/references_test.go @@ -16,533 +16,121 @@ import ( ) func TestStateReferenceSharing_Finalizer_Phase0(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{Slashings: []uint64{123}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference to slashings") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to slashings") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to slashings") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to slashings") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 456)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to slashings for both a and b") } } func TestStateReferenceSharing_Finalizer_Altair(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{Slashings: []uint64{123}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference to slashings") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to slashings") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to slashings") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to slashings") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 456)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to slashings for both a and b") } } func TestStateReferenceSharing_Finalizer_Bellatrix(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{Slashings: []uint64{123}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference to slashings") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to slashings") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to slashings") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to slashings") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 456)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to slashings for both a and b") } } func TestStateReferenceSharing_Finalizer_Capella(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{Slashings: []uint64{123}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference to slashings") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to slashings") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to slashings") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to slashings") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 456)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to slashings for both a and b") } } -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Phase0(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) - - // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Altair(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) - - // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Bellatrix(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) - - // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Capella(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) - - // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Phase0(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Altair(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Bellatrix(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Capella(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) { assertAttFound := func(vals []*ethpb.PendingAttestation, val uint64) { for i := range vals { @@ -855,25 +443,3 @@ func assertRefCount(t *testing.T, b *BeaconState, idx types.FieldIndex, want uin t.Errorf("Unexpected count of references for index %d, want: %v, got: %v", idx, want, cnt) } } - -// assertValFound checks whether item with a given value exists in list. -func assertValFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - return - } - } - t.Log(string(debug.Stack())) - t.Fatalf("Expected value not found (%v), want: %v", vals, val) -} - -// assertValNotFound checks whether item with a given value doesn't exist in list. -func assertValNotFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - t.Log(string(debug.Stack())) - t.Errorf("Unexpected value found (%v),: %v", vals, val) - return - } - } -}