Files
prysm/testing/util/state.go
Radosław Kapka 21bdbd548a Deduplicate native state (a.k.a. One State to rule them all) (#10483)
* v0

* getters/setters

* init and copy

* hasher

* all the nice stuff

* make bazel happy

* remove tests for smaller PR

* remove old states

* move files

* import fixes

* custom MarshalSSZ

* fixed deadlock

* copy version when copying state

* correct issues in state_trie

* fix Copy()

* better e2e comment

* add code to minimal state

* spectest test

* Revert "Auxiliary commit to revert individual files from 84154423464e8372f7e0a03367403656ac5cd78e"

This reverts commit 9602599d183081291dfa0ba4f1036430f63a7822.

* native state assert

* always error

* always log

* more native state usage

* cleanup

* remove empty line

* Revert "spectests"

This reverts commit 1c49bed5d1cf6224afaf21e18562bf72fae5d2b6.

# Conflicts:
#	beacon-chain/powchain/service.go
#	beacon-chain/state/v1/state_trie.go
#	beacon-chain/state/v2/state_trie.go
#	beacon-chain/state/v3/state_trie.go
#	testing/spectest/shared/phase0/finality/BUILD.bazel
#	testing/spectest/shared/phase0/finality/runner.go

* dedup field trie

* fix test issues

* cleanup

* use correct field num in FinalizedRootProof

* use existing version constant

* halfway there

* "working" version

* some fixes

* fix field nums in tests

* rename v0types to nativetypes

* Revert "Auxiliary commit to revert individual files from dc549b1cf8e724bd08cee1ecc760ff3771d5592d"

This reverts commit 7254d3070d8693b283fc686a2e01a822ecbac1b3.

* uncomment code

* remove map size

* Revert "Revert "spectests""

This reverts commit 39c271ae6b.

* use reverse map

* Revert "Revert "Revert "spectests"""

This reverts commit 19ba8cf95c.

* finally found the bug

(cherry picked from commit a5414c4be1bdb61a50b391ea5301895e772cc5e9)

* simplify populateFieldIndexes

* fix copy

(cherry picked from commit 7da4fb8cf51557ef931bb781872ea52fc6731af5)

* remove native state from e2e

* remove index map

* unsupported functions

* Use ProtobufBeaconState() from native state

* tests

* typo

* reduce complexity of `SaveStatesEfficient`

* remove unused receiver name

* update doc.go

* fix test assertion

* fix test assertion 2

* Phase0 justification bits

* bring back state tests

* rename fieldIndexRev

* versioning of ToProto

* remove version check from unexported function

* hasher tests

* don't return error from JustificationBits

* extract fieldConvertersNative

* helper error function

* use fieldConvertersNative

* Introduce RealPosition method on FieldIndex

* use RealPosition in hasher

* remove unused fields

* remove TestAppendBeyondIndicesLimit

(cherry picked from commit 3017e700282969c30006b64c95c21ffe6b166f8b)

* simplify RealPosition

* rename field interface

* use helper in proofs.go

* Update beacon-chain/core/altair/upgrade.go

Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2022-05-09 13:02:34 +00:00

271 lines
9.7 KiB
Go

package util
import (
"fmt"
"testing"
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params"
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// FillRootsNaturalOpt is meant to be used as an option when calling NewBeaconState.
// It fills state and block roots with hex representations of natural numbers starting with 0.
// Example: 16 becomes 0x00...0f.
func FillRootsNaturalOpt(state *ethpb.BeaconState) error {
roots, err := PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot))
if err != nil {
return err
}
state.StateRoots = roots
state.BlockRoots = roots
return nil
}
// FillRootsNaturalOptAltair is meant to be used as an option when calling NewBeaconStateAltair.
// It fills state and block roots with hex representations of natural numbers starting with 0.
// Example: 16 becomes 0x00...0f.
func FillRootsNaturalOptAltair(state *ethpb.BeaconStateAltair) error {
roots, err := PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot))
if err != nil {
return err
}
state.StateRoots = roots
state.BlockRoots = roots
return nil
}
// FillRootsNaturalOptBellatrix is meant to be used as an option when calling NewBeaconStateAltair.
// It fills state and block roots with hex representations of natural numbers starting with 0.
// Example: 16 becomes 0x00...0f.
func FillRootsNaturalOptBellatrix(state *ethpb.BeaconStateBellatrix) error {
roots, err := PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot))
if err != nil {
return err
}
state.StateRoots = roots
state.BlockRoots = roots
return nil
}
func WithStateSlot(slot types.Slot) NewBeaconStateOption {
return func(st *ethpb.BeaconState) error {
st.Slot = slot
return nil
}
}
func WithLatestHeaderFromBlock(t *testing.T, b interfaces.SignedBeaconBlock) NewBeaconStateOption {
return func(st *ethpb.BeaconState) error {
sh, err := b.Header()
require.NoError(t, err)
st.LatestBlockHeader = sh.Header
return nil
}
}
type NewBeaconStateOption func(state *ethpb.BeaconState) error
// NewBeaconState creates a beacon state with minimum marshalable fields.
func NewBeaconState(options ...NewBeaconStateOption) (state.BeaconState, error) {
seed := &ethpb.BeaconState{
BlockRoots: filledByteSlice2D(uint64(params.MainnetConfig().SlotsPerHistoricalRoot), 32),
StateRoots: filledByteSlice2D(uint64(params.MainnetConfig().SlotsPerHistoricalRoot), 32),
Slashings: make([]uint64, params.MainnetConfig().EpochsPerSlashingsVector),
RandaoMixes: filledByteSlice2D(uint64(params.MainnetConfig().EpochsPerHistoricalVector), 32),
Validators: make([]*ethpb.Validator, 0),
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, 32),
},
Fork: &ethpb.Fork{
PreviousVersion: make([]byte, 4),
CurrentVersion: make([]byte, 4),
},
Eth1DataVotes: make([]*ethpb.Eth1Data, 0),
HistoricalRoots: make([][]byte, 0),
JustificationBits: bitfield.Bitvector4{0x0},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
LatestBlockHeader: HydrateBeaconHeader(&ethpb.BeaconBlockHeader{}),
PreviousEpochAttestations: make([]*ethpb.PendingAttestation, 0),
CurrentEpochAttestations: make([]*ethpb.PendingAttestation, 0),
PreviousJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
}
for _, opt := range options {
err := opt(seed)
if err != nil {
return nil, err
}
}
var st, err = v1.InitializeFromProtoUnsafe(seed)
if err != nil {
return nil, err
}
return st.Copy().(*v1.BeaconState), nil
}
// NewBeaconStateAltair creates a beacon state with minimum marshalable fields.
func NewBeaconStateAltair(options ...func(state *ethpb.BeaconStateAltair) error) (state.BeaconStateAltair, error) {
pubkeys := make([][]byte, 512)
for i := range pubkeys {
pubkeys[i] = make([]byte, 48)
}
seed := &ethpb.BeaconStateAltair{
BlockRoots: filledByteSlice2D(uint64(params.MainnetConfig().SlotsPerHistoricalRoot), 32),
StateRoots: filledByteSlice2D(uint64(params.MainnetConfig().SlotsPerHistoricalRoot), 32),
Slashings: make([]uint64, params.MainnetConfig().EpochsPerSlashingsVector),
RandaoMixes: filledByteSlice2D(uint64(params.MainnetConfig().EpochsPerHistoricalVector), 32),
Validators: make([]*ethpb.Validator, 0),
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, 32),
},
Fork: &ethpb.Fork{
PreviousVersion: make([]byte, 4),
CurrentVersion: make([]byte, 4),
},
Eth1DataVotes: make([]*ethpb.Eth1Data, 0),
HistoricalRoots: make([][]byte, 0),
JustificationBits: bitfield.Bitvector4{0x0},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
LatestBlockHeader: HydrateBeaconHeader(&ethpb.BeaconBlockHeader{}),
PreviousJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
PreviousEpochParticipation: make([]byte, 0),
CurrentEpochParticipation: make([]byte, 0),
CurrentSyncCommittee: &ethpb.SyncCommittee{
Pubkeys: pubkeys,
AggregatePubkey: make([]byte, 48),
},
NextSyncCommittee: &ethpb.SyncCommittee{
Pubkeys: pubkeys,
AggregatePubkey: make([]byte, 48),
},
}
for _, opt := range options {
err := opt(seed)
if err != nil {
return nil, err
}
}
var st, err = v2.InitializeFromProtoUnsafe(seed)
if err != nil {
return nil, err
}
return st.Copy().(*v2.BeaconState), nil
}
// NewBeaconStateBellatrix creates a beacon state with minimum marshalable fields.
func NewBeaconStateBellatrix(options ...func(state *ethpb.BeaconStateBellatrix) error) (state.BeaconStateBellatrix, error) {
pubkeys := make([][]byte, 512)
for i := range pubkeys {
pubkeys[i] = make([]byte, 48)
}
seed := &ethpb.BeaconStateBellatrix{
BlockRoots: filledByteSlice2D(uint64(params.MainnetConfig().SlotsPerHistoricalRoot), 32),
StateRoots: filledByteSlice2D(uint64(params.MainnetConfig().SlotsPerHistoricalRoot), 32),
Slashings: make([]uint64, params.MainnetConfig().EpochsPerSlashingsVector),
RandaoMixes: filledByteSlice2D(uint64(params.MainnetConfig().EpochsPerHistoricalVector), 32),
Validators: make([]*ethpb.Validator, 0),
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, 32),
},
Fork: &ethpb.Fork{
PreviousVersion: make([]byte, 4),
CurrentVersion: make([]byte, 4),
},
Eth1DataVotes: make([]*ethpb.Eth1Data, 0),
HistoricalRoots: make([][]byte, 0),
JustificationBits: bitfield.Bitvector4{0x0},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
LatestBlockHeader: HydrateBeaconHeader(&ethpb.BeaconBlockHeader{}),
PreviousJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
PreviousEpochParticipation: make([]byte, 0),
CurrentEpochParticipation: make([]byte, 0),
CurrentSyncCommittee: &ethpb.SyncCommittee{
Pubkeys: pubkeys,
AggregatePubkey: make([]byte, 48),
},
NextSyncCommittee: &ethpb.SyncCommittee{
Pubkeys: pubkeys,
AggregatePubkey: make([]byte, 48),
},
LatestExecutionPayloadHeader: &ethpb.ExecutionPayloadHeader{
ParentHash: make([]byte, 32),
FeeRecipient: make([]byte, 20),
StateRoot: make([]byte, 32),
ReceiptsRoot: make([]byte, 32),
LogsBloom: make([]byte, 256),
PrevRandao: make([]byte, 32),
ExtraData: make([]byte, 0),
BaseFeePerGas: make([]byte, 32),
BlockHash: make([]byte, 32),
TransactionsRoot: make([]byte, 32),
},
}
for _, opt := range options {
err := opt(seed)
if err != nil {
return nil, err
}
}
var st, err = v3.InitializeFromProtoUnsafe(seed)
if err != nil {
return nil, err
}
return st.Copy().(*v3.BeaconState), nil
}
// SSZ will fill 2D byte slices with their respective values, so we must fill these in too for round
// trip testing.
func filledByteSlice2D(length, innerLen uint64) [][]byte {
b := make([][]byte, length)
for i := uint64(0); i < length; i++ {
b[i] = make([]byte, innerLen)
}
return b
}
// PrepareRoots returns a list of roots with hex representations of natural numbers starting with 0.
// Example: 16 becomes 0x00...0f.
func PrepareRoots(size int) ([][]byte, error) {
roots := make([][]byte, size)
for i := 0; i < size; i++ {
roots[i] = make([]byte, fieldparams.RootLength)
}
for j := 0; j < len(roots); j++ {
// Remove '0x' prefix and left-pad '0' to have 64 chars in total.
s := fmt.Sprintf("%064s", hexutil.EncodeUint64(uint64(j))[2:])
h, err := hexutil.Decode("0x" + s)
if err != nil {
return nil, err
}
roots[j] = h
}
return roots, nil
}