Files
prysm/beacon-chain/state/fieldtrie/helpers_test.go
Preston Van Loon 2fd6bd8150 Add golang.org/x/tools modernize static analyzer and fix violations (#15946)
* Ran gopls modernize to fix everything

go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...

* Override rules_go provided dependency for golang.org/x/tools to v0.38.0.

To update this, checked out rules_go, then ran `bazel run //go/tools/releaser -- upgrade-dep -mirror=false org_golang_x_tools` and copied the patches.

* Fix buildtag violations and ignore buildtag violations in external

* Introduce modernize analyzer package.

* Add modernize "any" analyzer.

* Fix violations of any analyzer

* Add modernize "appendclipped" analyzer.

* Fix violations of appendclipped

* Add modernize "bloop" analyzer.

* Add modernize "fmtappendf" analyzer.

* Add modernize "forvar" analyzer.

* Add modernize "mapsloop" analyzer.

* Add modernize "minmax" analyzer.

* Fix violations of minmax analyzer

* Add modernize "omitzero" analyzer.

* Add modernize "rangeint" analyzer.

* Fix violations of rangeint.

* Add modernize "reflecttypefor" analyzer.

* Fix violations of reflecttypefor analyzer.

* Add modernize "slicescontains" analyzer.

* Add modernize "slicessort" analyzer.

* Add modernize "slicesdelete" analyzer. This is disabled by default for now. See https://go.dev/issue/73686.

* Add modernize "stringscutprefix" analyzer.

* Add modernize "stringsbuilder" analyzer.

* Fix violations of stringsbuilder analyzer.

* Add modernize "stringsseq" analyzer.

* Add modernize "testingcontext" analyzer.

* Add modernize "waitgroup" analyzer.

* Changelog fragment

* gofmt

* gazelle

* Add modernize "newexpr" analyzer.

* Disable newexpr until go1.26

* Add more details in WORKSPACE on how to update the override

* @nalepae feedback on min()

* gofmt

* Fix violations of forvar
2025-11-14 01:27:22 +00:00

332 lines
9.1 KiB
Go

package fieldtrie
import (
"encoding/binary"
"fmt"
"sync"
"testing"
customtypes "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native/custom-types"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native/types"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/stateutil"
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/config/params"
mvslice "github.com/OffchainLabs/prysm/v7/container/multi-value-slice"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/testing/assert"
"github.com/OffchainLabs/prysm/v7/testing/require"
"github.com/ethereum/go-ethereum/common/hexutil"
)
func Test_handlePendingAttestation_OutOfRange(t *testing.T) {
items := make([]*ethpb.PendingAttestation, 1)
indices := []uint64{3}
_, err := handlePendingAttestationSlice(items, indices, false)
assert.ErrorContains(t, "index 3 greater than number of pending attestations 1", err)
}
func Test_handleEth1DataSlice_OutOfRange(t *testing.T) {
items := make([]*ethpb.Eth1Data, 1)
indices := []uint64{3}
_, err := handleEth1DataSlice(items, indices, false)
assert.ErrorContains(t, "index 3 greater than number of items in eth1 data slice 1", err)
}
func Test_handleValidatorSlice_OutOfRange(t *testing.T) {
vals := make([]*ethpb.Validator, 1)
indices := []uint64{3}
_, err := handleValidatorMVSlice(mvslice.BuildEmptyCompositeSlice[*ethpb.Validator](vals), indices, false)
assert.ErrorContains(t, "index 3 greater than number of validators 1", err)
}
func TestBalancesSlice_CorrectRoots_All(t *testing.T) {
balances := []uint64{5, 2929, 34, 1291, 354305}
roots, err := handleBalanceMVSlice(mvslice.BuildEmptyCompositeSlice[uint64](balances), []uint64{}, true)
assert.NoError(t, err)
var root1 [32]byte
binary.LittleEndian.PutUint64(root1[:8], balances[0])
binary.LittleEndian.PutUint64(root1[8:16], balances[1])
binary.LittleEndian.PutUint64(root1[16:24], balances[2])
binary.LittleEndian.PutUint64(root1[24:32], balances[3])
var root2 [32]byte
binary.LittleEndian.PutUint64(root2[:8], balances[4])
assert.DeepEqual(t, roots, [][32]byte{root1, root2})
}
func TestBalancesSlice_CorrectRoots_Some(t *testing.T) {
balances := []uint64{5, 2929, 34, 1291, 354305}
roots, err := handleBalanceMVSlice(mvslice.BuildEmptyCompositeSlice[uint64](balances), []uint64{2, 3}, false)
assert.NoError(t, err)
var root1 [32]byte
binary.LittleEndian.PutUint64(root1[:8], balances[0])
binary.LittleEndian.PutUint64(root1[8:16], balances[1])
binary.LittleEndian.PutUint64(root1[16:24], balances[2])
binary.LittleEndian.PutUint64(root1[24:32], balances[3])
// Returns root for each indice(even if duplicated)
assert.DeepEqual(t, roots, [][32]byte{root1, root1})
}
func TestValidateIndices_CompressedField(t *testing.T) {
fakeTrie := &FieldTrie{
RWMutex: new(sync.RWMutex),
reference: stateutil.NewRef(0),
fieldLayers: nil,
field: types.Balances,
dataType: types.CompressedArray,
length: params.BeaconConfig().ValidatorRegistryLimit / 4,
numOfElems: 0,
}
goodIdx := params.BeaconConfig().ValidatorRegistryLimit - 1
assert.NoError(t, fakeTrie.validateIndices([]uint64{goodIdx}))
badIdx := goodIdx + 1
assert.ErrorContains(t, "invalid index for field balances", fakeTrie.validateIndices([]uint64{badIdx}))
}
func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) {
type args struct {
field types.FieldIndex
indices []uint64
elements any
convertAll bool
}
tests := []struct {
name string
args *args
wantHex []string
errMsg string
expectedLength int
}{
{
name: "BlockRoots customtypes.BlockRoots",
args: &args{
field: types.FieldIndex(5),
indices: []uint64{},
elements: customtypes.BlockRoots{},
convertAll: true,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
expectedLength: 8192,
},
{
name: "BlockRoots type not found",
args: &args{
field: types.FieldIndex(5),
indices: []uint64{},
elements: 123,
convertAll: true,
},
wantHex: nil,
errMsg: "non-existent type provided",
},
{
name: "StateRoots customtypes.StateRoots",
args: &args{
field: types.FieldIndex(6),
indices: []uint64{},
elements: customtypes.StateRoots{},
convertAll: true,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
expectedLength: 8192,
},
{
name: "StateRoots type not found",
args: &args{
field: types.FieldIndex(6),
indices: []uint64{},
elements: 123,
convertAll: true,
},
wantHex: nil,
errMsg: "non-existent type provided",
},
{
name: "StateRoots customtypes.StateRoots convert all false",
args: &args{
field: types.FieldIndex(6),
indices: []uint64{},
elements: customtypes.StateRoots{},
convertAll: false,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
expectedLength: 8192,
},
{
name: "RandaoMixes customtypes.RandaoMixes",
args: &args{
field: types.FieldIndex(13),
indices: []uint64{},
elements: customtypes.RandaoMixes{},
convertAll: true,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
expectedLength: 65536,
},
{
name: "RandaoMixes type not found",
args: &args{
field: types.FieldIndex(13),
indices: []uint64{},
elements: 123,
convertAll: true,
},
wantHex: nil,
errMsg: "non-existent type provided",
},
{
name: "Eth1DataVotes type not found",
args: &args{
field: types.FieldIndex(9),
indices: []uint64{},
elements: []*ethpb.Eth1Data{
{
DepositRoot: make([]byte, fieldparams.RootLength),
DepositCount: 1,
},
},
convertAll: true,
},
wantHex: []string{"0x4833912e1264aef8a18392d795f3f2eed17cf5c0e8471cb0c0db2ec5aca10231"},
},
{
name: "Eth1DataVotes convertAll false",
args: &args{
field: types.FieldIndex(9),
indices: []uint64{1},
elements: []*ethpb.Eth1Data{
{
DepositRoot: make([]byte, fieldparams.RootLength),
DepositCount: 2,
},
{
DepositRoot: make([]byte, fieldparams.RootLength),
DepositCount: 1,
},
},
convertAll: false,
},
wantHex: []string{"0x4833912e1264aef8a18392d795f3f2eed17cf5c0e8471cb0c0db2ec5aca10231"},
},
{
name: "Eth1DataVotes type not found",
args: &args{
field: types.FieldIndex(9),
indices: []uint64{},
elements: 123,
convertAll: true,
},
wantHex: nil,
errMsg: fmt.Sprintf("Wanted type of %T", []*ethpb.Eth1Data{}),
},
{
name: "Balance",
args: &args{
field: types.FieldIndex(12),
indices: []uint64{},
elements: []uint64{12321312321, 12131241234123123},
convertAll: true,
},
wantHex: []string{"0x414e68de0200000073c971b44c192b0000000000000000000000000000000000"},
},
{
name: "Validators",
args: &args{
field: types.FieldIndex(11),
indices: []uint64{},
elements: []*ethpb.Validator{
{
ActivationEpoch: 1,
},
},
convertAll: true,
},
wantHex: []string{"0x79817c24fc7ba90cdac48fd462fafc1cb501884e847b18733f7ca6df214a301e"},
},
{
name: "Validators not found",
args: &args{
field: types.FieldIndex(11),
indices: []uint64{},
elements: 123,
convertAll: true,
},
wantHex: nil,
errMsg: fmt.Sprintf("Wanted type of %T", []*ethpb.Validator{}),
},
{
name: "Attestations",
args: &args{
field: types.FieldIndex(15),
indices: []uint64{},
elements: []*ethpb.PendingAttestation{
{
ProposerIndex: 1,
},
},
convertAll: true,
},
wantHex: []string{"0x7d7696e7f12593934afcd87a0d38e1a981bee63cb4cf0568ba36a6e0596eeccb"},
},
{
name: "Attestations convertAll false",
args: &args{
field: types.FieldIndex(15),
indices: []uint64{1},
elements: []*ethpb.PendingAttestation{
{
ProposerIndex: 0,
},
{
ProposerIndex: 1,
},
},
convertAll: false,
},
wantHex: []string{"0x7d7696e7f12593934afcd87a0d38e1a981bee63cb4cf0568ba36a6e0596eeccb"},
},
{
name: "Type not found",
args: &args{
field: types.FieldIndex(999),
indices: []uint64{},
elements: []*ethpb.PendingAttestation{
{
ProposerIndex: 1,
},
},
convertAll: true,
},
errMsg: "got unsupported type of",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
roots, err := fieldConverters(tt.args.field, tt.args.indices, tt.args.elements, tt.args.convertAll)
if err != nil {
if tt.errMsg != "" {
require.ErrorContains(t, tt.errMsg, err)
} else {
t.Error("Unexpected error: " + err.Error())
}
} else {
for i, root := range roots {
hex := hexutil.Encode(root[:])
require.Equal(t, tt.wantHex[i], hex)
if tt.expectedLength != 0 {
require.Equal(t, len(roots), tt.expectedLength)
break
}
}
}
})
}
}