mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
441 lines
12 KiB
Go
441 lines
12 KiB
Go
package state_native
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
|
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
|
"github.com/prysmaticlabs/prysm/v4/config/params"
|
|
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
|
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
|
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
|
)
|
|
|
|
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 := handleValidatorSlice(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 := handleBalanceSlice(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 := handleBalanceSlice(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,
|
|
fieldInfo: types.FieldInfo{ArrayType: types.CompressedArray, ValueType: types.SingleValue},
|
|
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 interface{}
|
|
convertAll bool
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args func() *args
|
|
wantHex []string
|
|
errMsg string
|
|
expectedLength int
|
|
}{
|
|
{
|
|
name: "BlockRoots",
|
|
args: func() *args {
|
|
var roots [fieldparams.BlockRootsLength][32]byte
|
|
roots[0] = bytesutil.ToBytes32([]byte("dfsadfsadf"))
|
|
elems := make([][]byte, len(roots))
|
|
for i, r := range roots {
|
|
tmp := make([]byte, 32)
|
|
copy(tmp, r[:])
|
|
elems[i] = tmp
|
|
}
|
|
return &args{
|
|
field: types.FieldIndex(5),
|
|
indices: []uint64{},
|
|
elements: NewMultiValueBlockRoots(elems),
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
|
|
expectedLength: fieldparams.BlockRootsLength,
|
|
},
|
|
{
|
|
name: "BlockRoots convertAll false",
|
|
args: func() *args {
|
|
var roots [fieldparams.BlockRootsLength][32]byte
|
|
roots[0] = bytesutil.ToBytes32([]byte("dfsadfsadf"))
|
|
roots[1] = bytesutil.ToBytes32([]byte("fskjgs"))
|
|
elems := make([][]byte, len(roots))
|
|
for i, r := range roots {
|
|
tmp := make([]byte, 32)
|
|
copy(tmp, r[:])
|
|
elems[i] = tmp
|
|
}
|
|
return &args{
|
|
field: types.FieldIndex(5),
|
|
indices: []uint64{0},
|
|
elements: NewMultiValueBlockRoots(elems),
|
|
convertAll: false,
|
|
}
|
|
},
|
|
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
|
|
expectedLength: 1,
|
|
},
|
|
{
|
|
name: "BlockRoots type not found",
|
|
args: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(5),
|
|
indices: []uint64{},
|
|
elements: 123,
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: nil,
|
|
errMsg: "Incorrect type used for block roots",
|
|
},
|
|
{
|
|
name: "StateRoots",
|
|
args: func() *args {
|
|
var roots [fieldparams.StateRootsLength][32]byte
|
|
roots[0] = bytesutil.ToBytes32([]byte("dfsadfsadf"))
|
|
elems := make([][]byte, len(roots))
|
|
for i, r := range roots {
|
|
tmp := make([]byte, 32)
|
|
copy(tmp, r[:])
|
|
elems[i] = tmp
|
|
}
|
|
return &args{
|
|
field: types.FieldIndex(6),
|
|
indices: []uint64{},
|
|
elements: NewMultiValueStateRoots(elems),
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
|
|
expectedLength: fieldparams.StateRootsLength,
|
|
},
|
|
{
|
|
name: "StateRoots convertAll false",
|
|
args: func() *args {
|
|
var roots [fieldparams.StateRootsLength][32]byte
|
|
roots[0] = bytesutil.ToBytes32([]byte("dfsadfsadf"))
|
|
roots[1] = bytesutil.ToBytes32([]byte("fskjgs"))
|
|
elems := make([][]byte, len(roots))
|
|
for i, r := range roots {
|
|
tmp := make([]byte, 32)
|
|
copy(tmp, r[:])
|
|
elems[i] = tmp
|
|
}
|
|
return &args{
|
|
field: types.FieldIndex(6),
|
|
indices: []uint64{0},
|
|
elements: NewMultiValueStateRoots(elems),
|
|
convertAll: false,
|
|
}
|
|
},
|
|
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
|
|
expectedLength: 1,
|
|
},
|
|
{
|
|
name: "StateRoots type not found",
|
|
args: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(6),
|
|
indices: []uint64{},
|
|
elements: 123,
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: nil,
|
|
errMsg: "Incorrect type used for state roots",
|
|
},
|
|
{
|
|
name: "RandaoMixes",
|
|
args: func() *args {
|
|
var mixes [fieldparams.RandaoMixesLength][32]byte
|
|
mixes[0] = bytesutil.ToBytes32([]byte("dfsadfsadf"))
|
|
elems := make([][]byte, len(mixes))
|
|
for i, m := range mixes {
|
|
tmp := make([]byte, 32)
|
|
copy(tmp, m[:])
|
|
elems[i] = tmp
|
|
}
|
|
return &args{
|
|
field: types.FieldIndex(13),
|
|
indices: []uint64{},
|
|
elements: NewMultiValueRandaoMixes(elems),
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
|
|
expectedLength: fieldparams.RandaoMixesLength,
|
|
},
|
|
{
|
|
name: "RandaoMixes convertAll false",
|
|
args: func() *args {
|
|
var mixes [fieldparams.RandaoMixesLength][32]byte
|
|
mixes[0] = bytesutil.ToBytes32([]byte("dfsadfsadf"))
|
|
mixes[1] = bytesutil.ToBytes32([]byte("fskjgs"))
|
|
elems := make([][]byte, len(mixes))
|
|
for i, m := range mixes {
|
|
tmp := make([]byte, 32)
|
|
copy(tmp, m[:])
|
|
elems[i] = tmp
|
|
}
|
|
return &args{
|
|
field: types.FieldIndex(13),
|
|
indices: []uint64{0},
|
|
elements: NewMultiValueRandaoMixes(elems),
|
|
convertAll: false,
|
|
}
|
|
},
|
|
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
|
|
expectedLength: 1,
|
|
},
|
|
{
|
|
name: "RandaoMixes type not found",
|
|
args: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(13),
|
|
indices: []uint64{},
|
|
elements: 123,
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: nil,
|
|
errMsg: "Incorrect type used for randao mixes",
|
|
},
|
|
{
|
|
name: "Eth1DataVotes type not found",
|
|
args: func() *args {
|
|
return &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: func() *args {
|
|
return &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: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(9),
|
|
indices: []uint64{},
|
|
elements: 123,
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: nil,
|
|
errMsg: fmt.Sprintf("Wanted type of %T", []*ethpb.Eth1Data{}),
|
|
},
|
|
{
|
|
name: "Balances",
|
|
args: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(12),
|
|
indices: []uint64{},
|
|
elements: NewMultiValueBalances([]uint64{12321312321, 12131241234123123}),
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: []string{"0x414e68de0200000073c971b44c192b0000000000000000000000000000000000"},
|
|
},
|
|
{
|
|
name: "Validators",
|
|
args: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(11),
|
|
indices: []uint64{},
|
|
elements: NewMultiValueValidators([]*ethpb.Validator{
|
|
{
|
|
ActivationEpoch: 1,
|
|
},
|
|
}),
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: []string{"0x79817c24fc7ba90cdac48fd462fafc1cb501884e847b18733f7ca6df214a301e"},
|
|
},
|
|
{
|
|
name: "Validators not found",
|
|
args: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(11),
|
|
indices: []uint64{},
|
|
elements: 123,
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: nil,
|
|
errMsg: fmt.Sprintf("Wanted type of %T", &MultiValueValidators{}),
|
|
},
|
|
{
|
|
name: "Attestations",
|
|
args: func() *args {
|
|
return &args{
|
|
field: types.FieldIndex(15),
|
|
indices: []uint64{},
|
|
elements: []*ethpb.PendingAttestation{
|
|
{
|
|
ProposerIndex: 1,
|
|
},
|
|
},
|
|
convertAll: true,
|
|
}
|
|
},
|
|
wantHex: []string{"0x7d7696e7f12593934afcd87a0d38e1a981bee63cb4cf0568ba36a6e0596eeccb"},
|
|
},
|
|
{
|
|
name: "Attestations convertAll false",
|
|
args: func() *args {
|
|
return &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: func() *args {
|
|
return &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) {
|
|
arg := tt.args()
|
|
roots, err := fieldConverters(nil, arg.field, arg.indices, arg.elements, arg.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
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|