diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index 9e942c5590..8c3414adaa 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -50,8 +50,8 @@ go_library( "//beacon-chain/operations/voluntaryexits:go_default_library", "//beacon-chain/p2p:go_default_library", "//beacon-chain/powchain:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//cmd/beacon-chain/flags:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", @@ -118,8 +118,8 @@ go_test( "//beacon-chain/db/testing:go_default_library", "//beacon-chain/p2p:go_default_library", "//beacon-chain/powchain:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", diff --git a/beacon-chain/blockchain/chain_info.go b/beacon-chain/blockchain/chain_info.go index 3c2178f9f7..5afc763898 100644 --- a/beacon-chain/blockchain/chain_info.go +++ b/beacon-chain/blockchain/chain_info.go @@ -7,9 +7,10 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "go.opencensus.io/trace" @@ -239,7 +240,7 @@ func (s *Service) GenesisValidatorRoot() [32]byte { if !s.hasHeadState() { return [32]byte{} } - return s.head.state.GenesisValidatorRoot() + return bytesutil.ToBytes32(s.head.state.GenesisValidatorRoot()) } // CurrentFork retrieves the latest fork information of the beacon chain. diff --git a/beacon-chain/blockchain/chain_info_norace_test.go b/beacon-chain/blockchain/chain_info_norace_test.go index 2448100675..6cac02c8aa 100644 --- a/beacon-chain/blockchain/chain_info_norace_test.go +++ b/beacon-chain/blockchain/chain_info_norace_test.go @@ -5,7 +5,7 @@ import ( "testing" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/blockchain/chain_info_test.go b/beacon-chain/blockchain/chain_info_test.go index 1baaf164ba..43cf1c1326 100644 --- a/beacon-chain/blockchain/chain_info_test.go +++ b/beacon-chain/blockchain/chain_info_test.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -154,7 +154,7 @@ func TestHeadState_CanRetrieve(t *testing.T) { c.head = &head{state: s} headState, err := c.HeadState(context.Background()) require.NoError(t, err) - assert.DeepEqual(t, headState.ToProtoUnsafe(), s.ToProtoUnsafe(), "Incorrect head state received") + assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Incorrect head state received") } func TestGenesisTime_CanRetrieve(t *testing.T) { @@ -275,7 +275,7 @@ func TestService_HeadGenesisValidatorRoot(t *testing.T) { c.head = &head{state: s} root = c.HeadGenesisValidatorRoot() - require.DeepEqual(t, root, s.GenesisValidatorRoot()) + require.DeepEqual(t, root[:], s.GenesisValidatorRoot()) } func TestService_ProtoArrayStore(t *testing.T) { diff --git a/beacon-chain/blockchain/head.go b/beacon-chain/blockchain/head.go index 6f81cd872d..dca0a05cea 100644 --- a/beacon-chain/blockchain/head.go +++ b/beacon-chain/blockchain/head.go @@ -11,7 +11,7 @@ import ( statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -253,7 +253,7 @@ func (s *Service) headState(ctx context.Context) state.BeaconState { // This returns the genesis validator root of the head state. // This is a lock free version. func (s *Service) headGenesisValidatorRoot() [32]byte { - return s.head.state.GenesisValidatorRoot() + return bytesutil.ToBytes32(s.head.state.GenesisValidatorRoot()) } // This returns the validator referenced by the provided index in diff --git a/beacon-chain/blockchain/head_sync_committee_info.go b/beacon-chain/blockchain/head_sync_committee_info.go index 5fbf214482..1dd84bec45 100644 --- a/beacon-chain/blockchain/head_sync_committee_info.go +++ b/beacon-chain/blockchain/head_sync_committee_info.go @@ -12,7 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/time/slots" @@ -130,8 +130,7 @@ func (s *Service) domainWithHeadState(ctx context.Context, slot types.Slot, doma if err != nil { return nil, err } - gvRoot := headState.GenesisValidatorRoot() - return signing.Domain(headState.Fork(), slots.ToEpoch(headState.Slot()), domain, gvRoot[:]) + return signing.Domain(headState.Fork(), slots.ToEpoch(headState.Slot()), domain, headState.GenesisValidatorRoot()) } // returns the head state that is advanced up to `slot`. It utilizes the cache `syncCommitteeHeadState` by retrieving using `slot` as key. diff --git a/beacon-chain/blockchain/head_sync_committee_info_test.go b/beacon-chain/blockchain/head_sync_committee_info_test.go index 6e7a59fd76..fb1a6d2c89 100644 --- a/beacon-chain/blockchain/head_sync_committee_info_test.go +++ b/beacon-chain/blockchain/head_sync_committee_info_test.go @@ -8,7 +8,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" @@ -122,8 +122,7 @@ func TestService_HeadSyncCommitteeDomain(t *testing.T) { c := &Service{} c.head = &head{state: s} - gvr := s.GenesisValidatorRoot() - wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr[:]) + wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorRoot()) require.NoError(t, err) d, err := c.HeadSyncCommitteeDomain(context.Background(), 0) @@ -137,8 +136,7 @@ func TestService_HeadSyncContributionProofDomain(t *testing.T) { c := &Service{} c.head = &head{state: s} - gvr := s.GenesisValidatorRoot() - wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainContributionAndProof, gvr[:]) + wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainContributionAndProof, s.GenesisValidatorRoot()) require.NoError(t, err) d, err := c.HeadSyncContributionProofDomain(context.Background(), 0) @@ -152,8 +150,7 @@ func TestService_HeadSyncSelectionProofDomain(t *testing.T) { c := &Service{} c.head = &head{state: s} - gvr := s.GenesisValidatorRoot() - wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr[:]) + wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommitteeSelectionProof, s.GenesisValidatorRoot()) require.NoError(t, err) d, err := c.HeadSyncSelectionProofDomain(context.Background(), 0) diff --git a/beacon-chain/blockchain/head_test.go b/beacon-chain/blockchain/head_test.go index 5a21371102..dd5baa4e7f 100644 --- a/beacon-chain/blockchain/head_test.go +++ b/beacon-chain/blockchain/head_test.go @@ -71,7 +71,7 @@ func TestSaveHead_Different(t *testing.T) { require.NoError(t, err) assert.DeepEqual(t, cachedRoot, newRoot[:], "Head did not change") assert.DeepEqual(t, newHeadSignedBlock, service.headBlock().Proto(), "Head did not change") - assert.DeepSSZEqual(t, headState.ToProto(), service.headState(ctx).ToProto(), "Head did not change") + assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change") } func TestSaveHead_Different_Reorg(t *testing.T) { @@ -116,7 +116,7 @@ func TestSaveHead_Different_Reorg(t *testing.T) { t.Error("Head did not change") } assert.DeepEqual(t, newHeadSignedBlock, service.headBlock().Proto(), "Head did not change") - assert.DeepSSZEqual(t, headState.ToProto(), service.headState(ctx).ToProto(), "Head did not change") + assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change") require.LogsContain(t, hook, "Chain reorg occurred") } diff --git a/beacon-chain/blockchain/info_test.go b/beacon-chain/blockchain/info_test.go index 607dde95b9..cb52e50eb7 100644 --- a/beacon-chain/blockchain/info_test.go +++ b/beacon-chain/blockchain/info_test.go @@ -8,7 +8,7 @@ import ( testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/blockchain/metrics.go b/beacon-chain/blockchain/metrics.go index 3508487d31..addd1fce75 100644 --- a/beacon-chain/blockchain/metrics.go +++ b/beacon-chain/blockchain/metrics.go @@ -9,7 +9,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -263,7 +263,7 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt return err } default: - return errors.Errorf("invalid state type provided: %T", headState.ToProtoUnsafe()) + return errors.Errorf("invalid state type provided: %T", headState.InnerStateUnsafe()) } prevEpochActiveBalances.Set(float64(b.ActivePrevEpoch)) prevEpochSourceBalances.Set(float64(b.PrevEpochAttested)) diff --git a/beacon-chain/blockchain/mock_test.go b/beacon-chain/blockchain/mock_test.go index 8a6cf27f76..5adce88187 100644 --- a/beacon-chain/blockchain/mock_test.go +++ b/beacon-chain/blockchain/mock_test.go @@ -7,8 +7,8 @@ import ( testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" ) func testServiceOptsWithDB(t *testing.T) []Option { diff --git a/beacon-chain/blockchain/options.go b/beacon-chain/blockchain/options.go index abc604e64d..d1ae4ab38c 100644 --- a/beacon-chain/blockchain/options.go +++ b/beacon-chain/blockchain/options.go @@ -11,8 +11,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/blockchain/process_attestation_helpers.go b/beacon-chain/blockchain/process_attestation_helpers.go index 20f81d2c31..3525e7763d 100644 --- a/beacon-chain/blockchain/process_attestation_helpers.go +++ b/beacon-chain/blockchain/process_attestation_helpers.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/async" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/blockchain/process_attestation_test.go b/beacon-chain/blockchain/process_attestation_test.go index 475d2c3f2b..05b106134e 100644 --- a/beacon-chain/blockchain/process_attestation_test.go +++ b/beacon-chain/blockchain/process_attestation_test.go @@ -8,7 +8,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -261,7 +261,7 @@ func TestStore_UpdateCheckpointState(t *testing.T) { cached, err = service.checkpointStateCache.StateByCheckpoint(newCheckpoint) require.NoError(t, err) - require.DeepSSZEqual(t, returned.ToProtoUnsafe(), cached.ToProtoUnsafe()) + require.DeepSSZEqual(t, returned.InnerStateUnsafe(), cached.InnerStateUnsafe()) } func TestAttEpoch_MatchPrevEpoch(t *testing.T) { diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index 3f8300253a..4af9c7bf23 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -11,7 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/beacon-chain/blockchain/process_block_helpers.go b/beacon-chain/blockchain/process_block_helpers.go index 8b60e96834..878d3040f3 100644 --- a/beacon-chain/blockchain/process_block_helpers.go +++ b/beacon-chain/blockchain/process_block_helpers.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/monitoring/tracing" diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index 00072bb0a2..f525c7fc85 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -17,9 +17,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/db" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/features" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/blockchain/receive_attestation.go b/beacon-chain/blockchain/receive_attestation.go index e7f4dd0fd6..a4c5dc2ed0 100644 --- a/beacon-chain/blockchain/receive_attestation.go +++ b/beacon-chain/blockchain/receive_attestation.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/async/event" "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/blockchain/receive_block_test.go b/beacon-chain/blockchain/receive_block_test.go index 9c537e97bf..dd43957037 100644 --- a/beacon-chain/blockchain/receive_block_test.go +++ b/beacon-chain/blockchain/receive_block_test.go @@ -12,7 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index 5fb9386329..f6b9f048ba 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -26,8 +26,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -217,12 +217,11 @@ func (s *Service) startFromSavedState(saved state.BeaconState) error { return errors.Wrap(err, "could not verify initial checkpoint provided for chain sync") } - gvr := saved.GenesisValidatorRoot() s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ Type: statefeed.Initialized, Data: &statefeed.InitializedData{ StartTime: s.genesisTime, - GenesisValidatorsRoot: gvr[:], + GenesisValidatorsRoot: saved.GenesisValidatorRoot(), }, }) @@ -380,12 +379,11 @@ func (s *Service) onPowchainStart(ctx context.Context, genesisTime time.Time) { // We send out a state initialized event to the rest of the services // running in the beacon node. - genesisValidatorRoot := initializedState.GenesisValidatorRoot() s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ Type: statefeed.Initialized, Data: &statefeed.InitializedData{ StartTime: genesisTime, - GenesisValidatorsRoot: genesisValidatorRoot[:], + GenesisValidatorsRoot: initializedState.GenesisValidatorRoot(), }, }) } diff --git a/beacon-chain/blockchain/service_test.go b/beacon-chain/blockchain/service_test.go index c480be7974..f0c75393a7 100644 --- a/beacon-chain/blockchain/service_test.go +++ b/beacon-chain/blockchain/service_test.go @@ -22,8 +22,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -77,7 +77,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service { var web3Service *powchain.Service var err error bState, _ := util.DeterministicGenesisState(t, 10) - pbState, err := v1.ProtobufBeaconState(bState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(bState.InnerStateUnsafe()) require.NoError(t, err) err = beaconDB.SavePowchainData(ctx, ðpb.ETH1ChainData{ BeaconState: pbState, @@ -277,7 +277,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) { headState, err := util.NewBeaconState() require.NoError(t, err) require.NoError(t, headState.SetSlot(finalizedSlot)) - require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash)) + require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:])) headRoot, err := headBlock.Block.HashTreeRoot() require.NoError(t, err) require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot)) @@ -294,7 +294,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) { assert.DeepEqual(t, headBlock, headBlk.Proto(), "Head block incorrect") s, err := c.HeadState(ctx) require.NoError(t, err) - assert.DeepSSZEqual(t, headState.ToProtoUnsafe(), s.ToProtoUnsafe(), "Head state incorrect") + assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect") assert.Equal(t, c.HeadSlot(), headBlock.Block.Slot, "Head slot incorrect") r, err := c.HeadRoot(context.Background()) require.NoError(t, err) @@ -321,7 +321,7 @@ func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) { headState, err := util.NewBeaconState() require.NoError(t, err) require.NoError(t, headState.SetSlot(finalizedSlot)) - require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash)) + require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:])) headRoot, err := headBlock.Block.HashTreeRoot() require.NoError(t, err) require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot)) @@ -334,7 +334,7 @@ func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) { require.NoError(t, c.startFromSavedState(headState)) s, err := c.HeadState(ctx) require.NoError(t, err) - assert.DeepSSZEqual(t, headState.ToProtoUnsafe(), s.ToProtoUnsafe(), "Head state incorrect") + assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect") assert.Equal(t, genesisRoot, c.originBlockRoot, "Genesis block root incorrect") assert.DeepEqual(t, genesis, c.head.block.Proto()) } @@ -377,7 +377,7 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) { headState, err := util.NewBeaconState() require.NoError(t, err) require.NoError(t, headState.SetSlot(headBlock.Block.Slot)) - require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash)) + require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:])) require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot)) require.NoError(t, beaconDB.SaveState(ctx, headState, finalizedRoot)) require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot)) @@ -394,7 +394,7 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) { require.NoError(t, c.startFromSavedState(headState)) s, err := c.HeadState(ctx) require.NoError(t, err) - assert.DeepSSZEqual(t, headState.ToProtoUnsafe(), s.ToProtoUnsafe(), "Head state incorrect") + assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect") assert.Equal(t, genesisRoot, c.originBlockRoot, "Genesis block root incorrect") // Since head sync is not triggered, chain is initialized to the last finalization checkpoint. assert.DeepEqual(t, finalizedBlock, c.head.block.Proto()) @@ -415,7 +415,7 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) { require.NoError(t, c.initializeHeadFromDB(ctx)) s, err = c.HeadState(ctx) require.NoError(t, err) - assert.DeepSSZEqual(t, headState.ToProtoUnsafe(), s.ToProtoUnsafe(), "Head state incorrect") + assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect") assert.Equal(t, genesisRoot, c.originBlockRoot, "Genesis block root incorrect") // Head slot is far beyond the latest finalized checkpoint, head sync is triggered. assert.DeepEqual(t, headBlock, c.head.block.Proto()) diff --git a/beacon-chain/blockchain/state_balance_cache.go b/beacon-chain/blockchain/state_balance_cache.go index 700c0cc66c..fdd98111a9 100644 --- a/beacon-chain/blockchain/state_balance_cache.go +++ b/beacon-chain/blockchain/state_balance_cache.go @@ -7,8 +7,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" ) var errNilStateFromStategen = errors.New("justified state can't be nil") diff --git a/beacon-chain/blockchain/state_balance_cache_test.go b/beacon-chain/blockchain/state_balance_cache_test.go index e41f350e52..993096ac85 100644 --- a/beacon-chain/blockchain/state_balance_cache_test.go +++ b/beacon-chain/blockchain/state_balance_cache_test.go @@ -7,8 +7,8 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/blockchain/testing/BUILD.bazel b/beacon-chain/blockchain/testing/BUILD.bazel index d16619eddd..85afc7cc1e 100644 --- a/beacon-chain/blockchain/testing/BUILD.bazel +++ b/beacon-chain/blockchain/testing/BUILD.bazel @@ -20,8 +20,8 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/db:go_default_library", "//beacon-chain/forkchoice/protoarray:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", diff --git a/beacon-chain/blockchain/testing/mock.go b/beacon-chain/blockchain/testing/mock.go index 85b396717c..c3fecc9c65 100644 --- a/beacon-chain/blockchain/testing/mock.go +++ b/beacon-chain/blockchain/testing/mock.go @@ -19,8 +19,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -215,11 +215,7 @@ func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []block.Signe // ReceiveBlock mocks ReceiveBlock method in chain service. func (s *ChainService) ReceiveBlock(ctx context.Context, block block.SignedBeaconBlock, _ [32]byte) error { if s.State == nil { - st, err := v1.Initialize() - if err != nil { - return err - } - s.State = st + s.State = &v1.BeaconState{} } if !bytes.Equal(s.Root, block.Block().ParentRoot()) { return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block().ParentRoot()) diff --git a/beacon-chain/cache/BUILD.bazel b/beacon-chain/cache/BUILD.bazel index 392dd4daa4..f946a00fe0 100644 --- a/beacon-chain/cache/BUILD.bazel +++ b/beacon-chain/cache/BUILD.bazel @@ -37,10 +37,10 @@ go_library( "//tools:__subpackages__", ], deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", - "//beacon-chain/state/v3:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", + "//beacon-chain/state-proto/v3:go_default_library", "//cache/lru:go_default_library", "//config/features:go_default_library", "//config/params:go_default_library", @@ -80,10 +80,10 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", - "//beacon-chain/state/v3:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", + "//beacon-chain/state-proto/v3:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", diff --git a/beacon-chain/cache/active_balance.go b/beacon-chain/cache/active_balance.go index 8d56767f27..0afbb4e048 100644 --- a/beacon-chain/cache/active_balance.go +++ b/beacon-chain/cache/active_balance.go @@ -11,7 +11,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ethTypes "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" @@ -108,7 +108,7 @@ func balanceCacheKey(st state.ReadOnlyBeaconState) (string, error) { // Mix in current epoch b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(currentEpoch)) - key := append(r[:], b...) + key := append(r, b...) // Mix in validator count b = make([]byte, 8) diff --git a/beacon-chain/cache/active_balance_disabled.go b/beacon-chain/cache/active_balance_disabled.go index 2796a285dc..c27eb12a45 100644 --- a/beacon-chain/cache/active_balance_disabled.go +++ b/beacon-chain/cache/active_balance_disabled.go @@ -6,7 +6,7 @@ import ( "sync" lru "github.com/hashicorp/golang-lru" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ) // FakeBalanceCache is a fake struct with 1 LRU cache for looking up balance by epoch. diff --git a/beacon-chain/cache/active_balance_test.go b/beacon-chain/cache/active_balance_test.go index 2d6faa5edb..d8fc986366 100644 --- a/beacon-chain/cache/active_balance_test.go +++ b/beacon-chain/cache/active_balance_test.go @@ -6,7 +6,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - state "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + state "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/cache/checkpoint_state.go b/beacon-chain/cache/checkpoint_state.go index 0cf8bb03b4..38f09f392a 100644 --- a/beacon-chain/cache/checkpoint_state.go +++ b/beacon-chain/cache/checkpoint_state.go @@ -6,7 +6,7 @@ import ( lru "github.com/hashicorp/golang-lru" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" "github.com/prysmaticlabs/prysm/crypto/hash" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/cache/checkpoint_state_test.go b/beacon-chain/cache/checkpoint_state_test.go index b5212e1533..1e76e19543 100644 --- a/beacon-chain/cache/checkpoint_state_test.go +++ b/beacon-chain/cache/checkpoint_state_test.go @@ -4,8 +4,8 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -33,9 +33,9 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) { s, err = cache.StateByCheckpoint(cp1) require.NoError(t, err) - pbState1, err := v1.ProtobufBeaconState(s.ToProtoUnsafe()) + pbState1, err := v1.ProtobufBeaconState(s.InnerStateUnsafe()) require.NoError(t, err) - pbstate, err := v1.ProtobufBeaconState(st.ToProtoUnsafe()) + pbstate, err := v1.ProtobufBeaconState(st.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState1, pbstate) { t.Error("incorrectly cached state") @@ -50,11 +50,11 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) { s, err = cache.StateByCheckpoint(cp2) require.NoError(t, err) - assert.DeepEqual(t, st2.ToProto(), s.ToProto(), "incorrectly cached state") + assert.DeepEqual(t, st2.CloneInnerState(), s.CloneInnerState(), "incorrectly cached state") s, err = cache.StateByCheckpoint(cp1) require.NoError(t, err) - assert.DeepEqual(t, st.ToProto(), s.ToProto(), "incorrectly cached state") + assert.DeepEqual(t, st.CloneInnerState(), s.CloneInnerState(), "incorrectly cached state") } func TestCheckpointStateCache_MaxSize(t *testing.T) { diff --git a/beacon-chain/cache/skip_slot_cache.go b/beacon-chain/cache/skip_slot_cache.go index 1088c42781..cbefe8cefd 100644 --- a/beacon-chain/cache/skip_slot_cache.go +++ b/beacon-chain/cache/skip_slot_cache.go @@ -9,7 +9,7 @@ import ( lru "github.com/hashicorp/golang-lru" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" "go.opencensus.io/trace" ) diff --git a/beacon-chain/cache/skip_slot_cache_test.go b/beacon-chain/cache/skip_slot_cache_test.go index efcba6dd4c..5026a22090 100644 --- a/beacon-chain/cache/skip_slot_cache_test.go +++ b/beacon-chain/cache/skip_slot_cache_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/cache" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" @@ -33,5 +33,5 @@ func TestSkipSlotCache_RoundTrip(t *testing.T) { res, err := c.Get(ctx, r) require.NoError(t, err) - assert.DeepEqual(t, res.ToProto(), s.ToProto(), "Expected equal protos to return from cache") + assert.DeepEqual(t, res.CloneInnerState(), s.CloneInnerState(), "Expected equal protos to return from cache") } diff --git a/beacon-chain/cache/sync_committee.go b/beacon-chain/cache/sync_committee.go index baf15c11d2..5b4900cafe 100644 --- a/beacon-chain/cache/sync_committee.go +++ b/beacon-chain/cache/sync_committee.go @@ -8,7 +8,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "k8s.io/client-go/tools/cache" ) diff --git a/beacon-chain/cache/sync_committee_disabled.go b/beacon-chain/cache/sync_committee_disabled.go index 68da51f3c4..7363c25603 100644 --- a/beacon-chain/cache/sync_committee_disabled.go +++ b/beacon-chain/cache/sync_committee_disabled.go @@ -4,7 +4,7 @@ package cache import ( types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ) // FakeSyncCommitteeCache is a fake `SyncCommitteeCache` to satisfy fuzzing. diff --git a/beacon-chain/cache/sync_committee_head_state.go b/beacon-chain/cache/sync_committee_head_state.go index 6a2357e95c..13e3e53fe0 100644 --- a/beacon-chain/cache/sync_committee_head_state.go +++ b/beacon-chain/cache/sync_committee_head_state.go @@ -5,10 +5,10 @@ import ( lru "github.com/hashicorp/golang-lru" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" - "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" ) diff --git a/beacon-chain/cache/sync_committee_head_state_test.go b/beacon-chain/cache/sync_committee_head_state_test.go index 5dfa0b6253..0a50993926 100644 --- a/beacon-chain/cache/sync_committee_head_state_test.go +++ b/beacon-chain/cache/sync_committee_head_state_test.go @@ -4,10 +4,10 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - "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" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/core/altair/BUILD.bazel b/beacon-chain/core/altair/BUILD.bazel index 55be78b357..a579885958 100644 --- a/beacon-chain/core/altair/BUILD.bazel +++ b/beacon-chain/core/altair/BUILD.bazel @@ -28,8 +28,8 @@ go_library( "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", @@ -70,9 +70,9 @@ go_test( "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v2:go_default_library", - "//beacon-chain/state/v3:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", + "//beacon-chain/state-proto/v3:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", diff --git a/beacon-chain/core/altair/attestation.go b/beacon-chain/core/altair/attestation.go index 3fe78afa3f..dd5a00f4ce 100644 --- a/beacon-chain/core/altair/attestation.go +++ b/beacon-chain/core/altair/attestation.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation" diff --git a/beacon-chain/core/altair/attestation_test.go b/beacon-chain/core/altair/attestation_test.go index 676474975f..0eff9a79bf 100644 --- a/beacon-chain/core/altair/attestation_test.go +++ b/beacon-chain/core/altair/attestation_test.go @@ -12,8 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/beacon-chain/core/altair/block.go b/beacon-chain/core/altair/block.go index 99effce4a4..9c6c368849 100644 --- a/beacon-chain/core/altair/block.go +++ b/beacon-chain/core/altair/block.go @@ -8,7 +8,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" p2pType "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -102,8 +102,7 @@ func FilterSyncCommitteeVotes(s state.BeaconStateAltair, sync *ethpb.SyncAggrega // VerifySyncCommitteeSig verifies sync committee signature `syncSig` is valid with respect to public keys `syncKeys`. func VerifySyncCommitteeSig(s state.BeaconStateAltair, syncKeys []bls.PublicKey, syncSig []byte) error { ps := slots.PrevSlot(s.Slot()) - gvRoot := s.GenesisValidatorRoot() - d, err := signing.Domain(s.Fork(), slots.ToEpoch(ps), params.BeaconConfig().DomainSyncCommittee, gvRoot[:]) + d, err := signing.Domain(s.Fork(), slots.ToEpoch(ps), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorRoot()) if err != nil { return err } diff --git a/beacon-chain/core/altair/deposit.go b/beacon-chain/core/altair/deposit.go index 8f55162834..291f26c080 100644 --- a/beacon-chain/core/altair/deposit.go +++ b/beacon-chain/core/altair/deposit.go @@ -5,7 +5,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/core/altair/deposit_fuzz_test.go b/beacon-chain/core/altair/deposit_fuzz_test.go index c440d8ae2f..2878b0b9ed 100644 --- a/beacon-chain/core/altair/deposit_fuzz_test.go +++ b/beacon-chain/core/altair/deposit_fuzz_test.go @@ -6,7 +6,7 @@ import ( fuzz "github.com/google/gofuzz" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" ) diff --git a/beacon-chain/core/altair/deposit_test.go b/beacon-chain/core/altair/deposit_test.go index 64e9c57bee..ac19d7aba6 100644 --- a/beacon-chain/core/altair/deposit_test.go +++ b/beacon-chain/core/altair/deposit_test.go @@ -6,7 +6,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index 69f551d1db..55d1df9c17 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" "github.com/prysmaticlabs/prysm/runtime/version" diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go index b13c495123..6003fc8f1c 100644 --- a/beacon-chain/core/altair/epoch_precompute_test.go +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -7,9 +7,9 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" - v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/core/altair/epoch_spec.go b/beacon-chain/core/altair/epoch_spec.go index 2720ea0eb9..fbdf76d594 100644 --- a/beacon-chain/core/altair/epoch_spec.go +++ b/beacon-chain/core/altair/epoch_spec.go @@ -5,7 +5,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" log "github.com/sirupsen/logrus" ) diff --git a/beacon-chain/core/altair/epoch_spec_test.go b/beacon-chain/core/altair/epoch_spec_test.go index 00036a8fd9..52548b3746 100644 --- a/beacon-chain/core/altair/epoch_spec_test.go +++ b/beacon-chain/core/altair/epoch_spec_test.go @@ -11,7 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/altair/reward.go b/beacon-chain/core/altair/reward.go index c7e6660e19..2e8d00fa16 100644 --- a/beacon-chain/core/altair/reward.go +++ b/beacon-chain/core/altair/reward.go @@ -4,7 +4,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" ) diff --git a/beacon-chain/core/altair/reward_test.go b/beacon-chain/core/altair/reward_test.go index a7a9372126..2409344261 100644 --- a/beacon-chain/core/altair/reward_test.go +++ b/beacon-chain/core/altair/reward_test.go @@ -6,7 +6,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" diff --git a/beacon-chain/core/altair/sync_committee.go b/beacon-chain/core/altair/sync_committee.go index b334c6e08a..5a123abbe9 100644 --- a/beacon-chain/core/altair/sync_committee.go +++ b/beacon-chain/core/altair/sync_committee.go @@ -9,7 +9,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/beacon-chain/core/altair/sync_committee_test.go b/beacon-chain/core/altair/sync_committee_test.go index 79e1096873..b0febbdbda 100644 --- a/beacon-chain/core/altair/sync_committee_test.go +++ b/beacon-chain/core/altair/sync_committee_test.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/altair/transition.go b/beacon-chain/core/altair/transition.go index 810c6e28f3..aca5a9fb5c 100644 --- a/beacon-chain/core/altair/transition.go +++ b/beacon-chain/core/altair/transition.go @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" e "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/runtime/version" "go.opencensus.io/trace" diff --git a/beacon-chain/core/altair/upgrade.go b/beacon-chain/core/altair/upgrade.go index 077c2672f9..7f794d8e75 100644 --- a/beacon-chain/core/altair/upgrade.go +++ b/beacon-chain/core/altair/upgrade.go @@ -3,11 +3,10 @@ package altair import ( "context" - "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - statealtair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + statealtair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation" @@ -68,82 +67,39 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon numValidators := state.NumValidators() - newState, err := statealtair.Initialize() + s := ðpb.BeaconStateAltair{ + GenesisTime: state.GenesisTime(), + GenesisValidatorsRoot: state.GenesisValidatorRoot(), + Slot: state.Slot(), + Fork: ðpb.Fork{ + PreviousVersion: state.Fork().CurrentVersion, + CurrentVersion: params.BeaconConfig().AltairForkVersion, + Epoch: epoch, + }, + LatestBlockHeader: state.LatestBlockHeader(), + BlockRoots: state.BlockRoots(), + StateRoots: state.StateRoots(), + HistoricalRoots: state.HistoricalRoots(), + Eth1Data: state.Eth1Data(), + Eth1DataVotes: state.Eth1DataVotes(), + Eth1DepositIndex: state.Eth1DepositIndex(), + Validators: state.Validators(), + Balances: state.Balances(), + RandaoMixes: state.RandaoMixes(), + Slashings: state.Slashings(), + PreviousEpochParticipation: make([]byte, numValidators), + CurrentEpochParticipation: make([]byte, numValidators), + JustificationBits: state.JustificationBits(), + PreviousJustifiedCheckpoint: state.PreviousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: state.CurrentJustifiedCheckpoint(), + FinalizedCheckpoint: state.FinalizedCheckpoint(), + InactivityScores: make([]uint64, numValidators), + } + + newState, err := statealtair.InitializeFromProto(s) if err != nil { return nil, err } - - if err = newState.SetGenesisTime(state.GenesisTime()); err != nil { - return nil, errors.Wrap(err, "could not set genesis time") - } - if err = newState.SetGenesisValidatorRoot(state.GenesisValidatorRoot()); err != nil { - return nil, errors.Wrap(err, "could not set genesis validators root") - } - if err = newState.SetSlot(state.Slot()); err != nil { - return nil, errors.Wrap(err, "could not set slot") - } - if err = newState.SetFork(ðpb.Fork{ - PreviousVersion: state.Fork().CurrentVersion, - CurrentVersion: params.BeaconConfig().AltairForkVersion, - Epoch: epoch, - }); err != nil { - return nil, errors.Wrap(err, "could not set fork") - } - if err = newState.SetLatestBlockHeader(state.LatestBlockHeader()); err != nil { - return nil, errors.Wrap(err, "could not set latest block header") - } - if err = newState.SetBlockRoots(state.BlockRoots()); err != nil { - return nil, errors.Wrap(err, "could not set block roots") - } - if err = newState.SetStateRoots(state.StateRoots()); err != nil { - return nil, errors.Wrap(err, "could not set state roots") - } - if err = newState.SetHistoricalRoots(state.HistoricalRoots()); err != nil { - return nil, errors.Wrap(err, "could not set historical roots") - } - if err = newState.SetEth1Data(state.Eth1Data()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = newState.SetEth1DataVotes(state.Eth1DataVotes()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data votes") - } - if err = newState.SetEth1DepositIndex(state.Eth1DepositIndex()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 deposit index") - } - if err = newState.SetValidators(state.Validators()); err != nil { - return nil, errors.Wrap(err, "could not set validators") - } - if err = newState.SetBalances(state.Balances()); err != nil { - return nil, errors.Wrap(err, "could not set balances") - } - if err = newState.SetRandaoMixes(state.RandaoMixes()); err != nil { - return nil, errors.Wrap(err, "could not set randao mixes") - } - if err = newState.SetSlashings(state.Slashings()); err != nil { - return nil, errors.Wrap(err, "could not set slashings") - } - if err = newState.SetJustificationBits(state.JustificationBits()); err != nil { - return nil, errors.Wrap(err, "could not set justification bits") - } - if err = newState.SetPreviousParticipationBits(make([]byte, numValidators)); err != nil { - return nil, errors.Wrap(err, "could not set previous participation bits") - } - if err = newState.SetCurrentParticipationBits(make([]byte, numValidators)); err != nil { - return nil, errors.Wrap(err, "could not set current participation bits") - } - if err = newState.SetInactivityScores(make([]uint64, numValidators)); err != nil { - return nil, errors.Wrap(err, "could not set inactivity scores") - } - if err = newState.SetPreviousJustifiedCheckpoint(state.PreviousJustifiedCheckpoint()); err != nil { - return nil, errors.Wrap(err, "could not set previous justified checkpoint") - } - if err = newState.SetCurrentJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { - return nil, errors.Wrap(err, "could not set current justified checkpoint") - } - if err = newState.SetFinalizedCheckpoint(state.FinalizedCheckpoint()); err != nil { - return nil, errors.Wrap(err, "could not set finalized checkpoint") - } - prevEpochAtts, err := state.PreviousEpochAttestations() if err != nil { return nil, err diff --git a/beacon-chain/core/altair/upgrade_test.go b/beacon-chain/core/altair/upgrade_test.go index 44e0203220..9ac1c71a42 100644 --- a/beacon-chain/core/altair/upgrade_test.go +++ b/beacon-chain/core/altair/upgrade_test.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation" diff --git a/beacon-chain/core/blocks/BUILD.bazel b/beacon-chain/core/blocks/BUILD.bazel index ee1eea3923..8a0da67f84 100644 --- a/beacon-chain/core/blocks/BUILD.bazel +++ b/beacon-chain/core/blocks/BUILD.bazel @@ -29,7 +29,7 @@ go_library( "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/validators:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//container/slice:go_default_library", @@ -84,8 +84,8 @@ go_test( "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/validators:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", diff --git a/beacon-chain/core/blocks/attestation.go b/beacon-chain/core/blocks/attestation.go index 0491e5aa1f..c12896fb19 100644 --- a/beacon-chain/core/blocks/attestation.go +++ b/beacon-chain/core/blocks/attestation.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -204,12 +204,11 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState state.ReadOnlyBea if err := attestation.IsValidAttestationIndices(ctx, indexedAtt); err != nil { return err } - gvRoot := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, - gvRoot[:], + beaconState.GenesisValidatorRoot(), ) if err != nil { return err diff --git a/beacon-chain/core/blocks/attestation_regression_test.go b/beacon-chain/core/blocks/attestation_regression_test.go index 21779a3054..b3b208dd79 100644 --- a/beacon-chain/core/blocks/attestation_regression_test.go +++ b/beacon-chain/core/blocks/attestation_regression_test.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/core/blocks/attestation_test.go b/beacon-chain/core/blocks/attestation_test.go index d0bd792a61..63f827b607 100644 --- a/beacon-chain/core/blocks/attestation_test.go +++ b/beacon-chain/core/blocks/attestation_test.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -416,7 +416,7 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) { }, }) gvr := st.GenesisValidatorRoot() - prevDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch-1, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + prevDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch-1, params.BeaconConfig().DomainBeaconAttester, gvr) require.NoError(t, err) root, err := signing.ComputeSigningRoot(att1.Data, prevDomain) require.NoError(t, err) @@ -436,7 +436,7 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) { CommitteeIndex: 1, }, }) - currDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + currDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, gvr) require.NoError(t, err) root, err = signing.ComputeSigningRoot(att2.Data, currDomain) require.NoError(t, err) @@ -475,8 +475,7 @@ func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing Slot: 1, }, }) - gvr := st.GenesisValidatorRoot() - domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot()) require.NoError(t, err) root, err := signing.ComputeSigningRoot(att1.Data, domain) require.NoError(t, err) @@ -540,8 +539,7 @@ func TestRetrieveAttestationSignatureSet_AcrossFork(t *testing.T) { Slot: 1, }, }) - gvr := st.GenesisValidatorRoot() - domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot()) require.NoError(t, err) root, err := signing.ComputeSigningRoot(att1.Data, domain) require.NoError(t, err) diff --git a/beacon-chain/core/blocks/attester_slashing.go b/beacon-chain/core/blocks/attester_slashing.go index c558561ff3..0ea381fd68 100644 --- a/beacon-chain/core/blocks/attester_slashing.go +++ b/beacon-chain/core/blocks/attester_slashing.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/slice" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/blocks/attester_slashing_test.go b/beacon-chain/core/blocks/attester_slashing_test.go index 4d46242d2d..e7e260a93f 100644 --- a/beacon-chain/core/blocks/attester_slashing_test.go +++ b/beacon-chain/core/blocks/attester_slashing_test.go @@ -8,7 +8,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -108,8 +108,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) { }, AttestingIndices: []uint64{0, 1}, }) - gvr := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) assert.NoError(t, err, "Could not get signing root of beacon block header") @@ -178,8 +177,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatusAltair(t *testing.T) { }, AttestingIndices: []uint64{0, 1}, }) - gvr := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) assert.NoError(t, err, "Could not get signing root of beacon block header") @@ -248,8 +246,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatusMerge(t *testing.T) { }, AttestingIndices: []uint64{0, 1}, }) - gvr := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) assert.NoError(t, err, "Could not get signing root of beacon block header") diff --git a/beacon-chain/core/blocks/block_operations_fuzz_test.go b/beacon-chain/core/blocks/block_operations_fuzz_test.go index 687fdbea98..33da95bacd 100644 --- a/beacon-chain/core/blocks/block_operations_fuzz_test.go +++ b/beacon-chain/core/blocks/block_operations_fuzz_test.go @@ -7,7 +7,7 @@ import ( fuzz "github.com/google/gofuzz" types "github.com/prysmaticlabs/eth2-types" v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -74,8 +74,7 @@ func TestFuzzverifyDepositDataSigningRoot_10000(_ *testing.T) { func TestFuzzProcessEth1DataInBlock_10000(t *testing.T) { fuzzer := fuzz.NewWithSeed(0) e := ðpb.Eth1Data{} - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} for i := 0; i < 10000; i++ { fuzzer.Fuzz(state) fuzzer.Fuzz(e) diff --git a/beacon-chain/core/blocks/block_regression_test.go b/beacon-chain/core/blocks/block_regression_test.go index 18b2e3f33f..b5187ce915 100644 --- a/beacon-chain/core/blocks/block_regression_test.go +++ b/beacon-chain/core/blocks/block_regression_test.go @@ -44,8 +44,7 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) { AttestingIndices: setA, Signature: make([]byte, 96), } - gvr := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) require.NoError(t, err, "Could not get signing root of beacon block header") diff --git a/beacon-chain/core/blocks/deposit.go b/beacon-chain/core/blocks/deposit.go index 9864d7598e..310ce5e664 100644 --- a/beacon-chain/core/blocks/deposit.go +++ b/beacon-chain/core/blocks/deposit.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/contracts/deposit" diff --git a/beacon-chain/core/blocks/deposit_test.go b/beacon-chain/core/blocks/deposit_test.go index 98f7092cee..3eea944f48 100644 --- a/beacon-chain/core/blocks/deposit_test.go +++ b/beacon-chain/core/blocks/deposit_test.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" diff --git a/beacon-chain/core/blocks/eth1_data.go b/beacon-chain/core/blocks/eth1_data.go index 93d6871cf0..5f9fbefe9a 100644 --- a/beacon-chain/core/blocks/eth1_data.go +++ b/beacon-chain/core/blocks/eth1_data.go @@ -5,7 +5,7 @@ import ( "context" "errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/core/blocks/eth1_data_test.go b/beacon-chain/core/blocks/eth1_data_test.go index 1682abcfd0..7708aecad6 100644 --- a/beacon-chain/core/blocks/eth1_data_test.go +++ b/beacon-chain/core/blocks/eth1_data_test.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/blocks/exit.go b/beacon-chain/core/blocks/exit.go index 6dd8aa3b83..db4fc5a245 100644 --- a/beacon-chain/core/blocks/exit.go +++ b/beacon-chain/core/blocks/exit.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/time/slots" @@ -57,8 +57,7 @@ func ProcessVoluntaryExits( if err != nil { return nil, err } - gvRoot := beaconState.GenesisValidatorRoot() - if err := VerifyExitAndSignature(val, beaconState.Slot(), beaconState.Fork(), exit, gvRoot[:]); err != nil { + if err := VerifyExitAndSignature(val, beaconState.Slot(), beaconState.Fork(), exit, beaconState.GenesisValidatorRoot()); err != nil { return nil, errors.Wrapf(err, "could not verify exit %d", idx) } beaconState, err = v.InitiateValidatorExit(ctx, beaconState, exit.Exit.ValidatorIndex) diff --git a/beacon-chain/core/blocks/exit_test.go b/beacon-chain/core/blocks/exit_test.go index 3beca254b3..8fef26032d 100644 --- a/beacon-chain/core/blocks/exit_test.go +++ b/beacon-chain/core/blocks/exit_test.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/blocks/header.go b/beacon-chain/core/blocks/header.go index e7a039e686..28ac55c6a8 100644 --- a/beacon-chain/core/blocks/header.go +++ b/beacon-chain/core/blocks/header.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" diff --git a/beacon-chain/core/blocks/payload.go b/beacon-chain/core/blocks/payload.go index 34eedfa5ad..69ba7cce31 100644 --- a/beacon-chain/core/blocks/payload.go +++ b/beacon-chain/core/blocks/payload.go @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/encoding/ssz" diff --git a/beacon-chain/core/blocks/proposer_slashing.go b/beacon-chain/core/blocks/proposer_slashing.go index 4bb1120c23..3eb82348ec 100644 --- a/beacon-chain/core/blocks/proposer_slashing.go +++ b/beacon-chain/core/blocks/proposer_slashing.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime/version" diff --git a/beacon-chain/core/blocks/proposer_slashing_regression_test.go b/beacon-chain/core/blocks/proposer_slashing_regression_test.go index 02e181c1a6..22f973c512 100644 --- a/beacon-chain/core/blocks/proposer_slashing_regression_test.go +++ b/beacon-chain/core/blocks/proposer_slashing_regression_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" ) diff --git a/beacon-chain/core/blocks/proposer_slashing_test.go b/beacon-chain/core/blocks/proposer_slashing_test.go index 0f3f177ae0..951e935d98 100644 --- a/beacon-chain/core/blocks/proposer_slashing_test.go +++ b/beacon-chain/core/blocks/proposer_slashing_test.go @@ -9,8 +9,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -378,8 +378,7 @@ func TestVerifyProposerSlashing(t *testing.T) { t.Run(tt.name, func(t *testing.T) { sk := sks[tt.args.slashing.Header_1.Header.ProposerIndex] - gvr := tt.args.beaconState.GenesisValidatorRoot() - d, err := signing.Domain(tt.args.beaconState.Fork(), slots.ToEpoch(tt.args.slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer, gvr[:]) + d, err := signing.Domain(tt.args.beaconState.Fork(), slots.ToEpoch(tt.args.slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer, tt.args.beaconState.GenesisValidatorRoot()) require.NoError(t, err) if tt.args.slashing.Header_1.Signature == nil { sr, err := signing.ComputeSigningRoot(tt.args.slashing.Header_1.Header, d) diff --git a/beacon-chain/core/blocks/randao.go b/beacon-chain/core/blocks/randao.go index 0123fa52bb..9e6741f51a 100644 --- a/beacon-chain/core/blocks/randao.go +++ b/beacon-chain/core/blocks/randao.go @@ -5,7 +5,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" diff --git a/beacon-chain/core/blocks/randao_test.go b/beacon-chain/core/blocks/randao_test.go index 98ffaa4da2..758490458a 100644 --- a/beacon-chain/core/blocks/randao_test.go +++ b/beacon-chain/core/blocks/randao_test.go @@ -26,8 +26,7 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) { epoch := types.Epoch(0) buf := make([]byte, 32) binary.LittleEndian.PutUint64(buf, uint64(epoch)) - gvr := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, gvr[:]) + domain, err := signing.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot()) require.NoError(t, err) root, err := (ðpb.SigningData{ObjectRoot: buf, Domain: domain}).HashTreeRoot() require.NoError(t, err) diff --git a/beacon-chain/core/blocks/signature.go b/beacon-chain/core/blocks/signature.go index b4f4b0e5ea..5ca0cbbf2a 100644 --- a/beacon-chain/core/blocks/signature.go +++ b/beacon-chain/core/blocks/signature.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/network/forks" @@ -68,8 +68,7 @@ func VerifyBlockSignature(beaconState state.ReadOnlyBeaconState, sig []byte, rootFunc func() ([32]byte, error)) error { currentEpoch := slots.ToEpoch(beaconState.Slot()) - gvRoot := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, gvRoot[:]) + domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot()) if err != nil { return err } @@ -84,8 +83,7 @@ func VerifyBlockSignature(beaconState state.ReadOnlyBeaconState, // VerifyBlockHeaderSignature verifies the proposer signature of a beacon block header. func VerifyBlockHeaderSignature(beaconState state.BeaconState, header *ethpb.SignedBeaconBlockHeader) error { currentEpoch := slots.ToEpoch(beaconState.Slot()) - gvRoot := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, gvRoot[:]) + domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot()) if err != nil { return err } @@ -106,8 +104,7 @@ func VerifyBlockSignatureUsingCurrentFork(beaconState state.ReadOnlyBeaconState, if err != nil { return err } - gvRoot := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(fork, currentEpoch, params.BeaconConfig().DomainBeaconProposer, gvRoot[:]) + domain, err := signing.Domain(fork, currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot()) if err != nil { return err } @@ -125,8 +122,7 @@ func BlockSignatureBatch(beaconState state.ReadOnlyBeaconState, sig []byte, rootFunc func() ([32]byte, error)) (*bls.SignatureBatch, error) { currentEpoch := slots.ToEpoch(beaconState.Slot()) - gvRoot := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, gvRoot[:]) + domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot()) if err != nil { return nil, err } @@ -168,8 +164,7 @@ func randaoSigningData(ctx context.Context, beaconState state.ReadOnlyBeaconStat buf := make([]byte, 32) binary.LittleEndian.PutUint64(buf, uint64(currentEpoch)) - gvRoot := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, gvRoot[:]) + domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot()) if err != nil { return nil, nil, nil, err } @@ -253,7 +248,7 @@ func AttestationSignatureBatch(ctx context.Context, beaconState state.ReadOnlyBe // Check attestations from before the fork. if fork.Epoch > 0 && len(preForkAtts) > 0 { // Check to prevent underflow and there is valid attestations to create sig batch. - prevDomain, err := signing.Domain(fork, fork.Epoch-1, dt, gvr[:]) + prevDomain, err := signing.Domain(fork, fork.Epoch-1, dt, gvr) if err != nil { return nil, err } @@ -272,7 +267,7 @@ func AttestationSignatureBatch(ctx context.Context, beaconState state.ReadOnlyBe if len(postForkAtts) > 0 { // Then check attestations from after the fork. - currDomain, err := signing.Domain(fork, fork.Epoch, dt, gvr[:]) + currDomain, err := signing.Domain(fork, fork.Epoch, dt, gvr) if err != nil { return nil, err } diff --git a/beacon-chain/core/blocks/signature_test.go b/beacon-chain/core/blocks/signature_test.go index b1c3933d63..62acc4f1fb 100644 --- a/beacon-chain/core/blocks/signature_test.go +++ b/beacon-chain/core/blocks/signature_test.go @@ -37,12 +37,11 @@ func TestVerifyBlockHeaderSignature(t *testing.T) { ProposerIndex: 0, }, }) - gvr := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, - gvr[:], + beaconState.GenesisValidatorRoot(), ) require.NoError(t, err) htr, err := blockHeader.Header.HashTreeRoot() @@ -78,8 +77,7 @@ func TestVerifyBlockSignatureUsingCurrentFork(t *testing.T) { CurrentVersion: params.BeaconConfig().AltairForkVersion, PreviousVersion: params.BeaconConfig().GenesisForkVersion, } - gvr := bState.GenesisValidatorRoot() - domain, err := signing.Domain(fData, 100, params.BeaconConfig().DomainBeaconProposer, gvr[:]) + domain, err := signing.Domain(fData, 100, params.BeaconConfig().DomainBeaconProposer, bState.GenesisValidatorRoot()) assert.NoError(t, err) rt, err := signing.ComputeSigningRoot(altairBlk.Block, domain) assert.NoError(t, err) diff --git a/beacon-chain/core/epoch/BUILD.bazel b/beacon-chain/core/epoch/BUILD.bazel index c22a561580..026b65b04d 100644 --- a/beacon-chain/core/epoch/BUILD.bazel +++ b/beacon-chain/core/epoch/BUILD.bazel @@ -12,10 +12,9 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/validators:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/features:go_default_library", "//config/params:go_default_library", - "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", @@ -35,8 +34,8 @@ go_test( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/core/epoch/epoch_processing.go b/beacon-chain/core/epoch/epoch_processing.go index 896010f70f..799983c671 100644 --- a/beacon-chain/core/epoch/epoch_processing.go +++ b/beacon-chain/core/epoch/epoch_processing.go @@ -14,10 +14,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/math" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation" @@ -359,7 +358,7 @@ func ProcessRandaoMixesReset(state state.BeaconState) (state.BeaconState, error) if err != nil { return nil, err } - if err := state.UpdateRandaoMixesAtIndex(uint64(nextEpoch%randaoMixLength), bytesutil.ToBytes32(mix)); err != nil { + if err := state.UpdateRandaoMixesAtIndex(uint64(nextEpoch%randaoMixLength), mix); err != nil { return nil, err } @@ -386,13 +385,13 @@ func ProcessHistoricalRootsUpdate(state state.BeaconState) (state.BeaconState, e bRoots := make([][]byte, len(blockRoots)) for i := range bRoots { tmp := blockRoots[i] - bRoots[i] = tmp[:] + bRoots[i] = tmp } stateRoots := state.StateRoots() sRoots := make([][]byte, len(stateRoots)) for i := range sRoots { tmp := stateRoots[i] - sRoots[i] = tmp[:] + sRoots[i] = tmp } historicalBatch := ðpb.HistoricalBatch{ BlockRoots: bRoots, diff --git a/beacon-chain/core/epoch/epoch_processing_fuzz_test.go b/beacon-chain/core/epoch/epoch_processing_fuzz_test.go index aa081c20dc..17c4ac31a7 100644 --- a/beacon-chain/core/epoch/epoch_processing_fuzz_test.go +++ b/beacon-chain/core/epoch/epoch_processing_fuzz_test.go @@ -4,7 +4,7 @@ import ( "testing" fuzz "github.com/google/gofuzz" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" ) diff --git a/beacon-chain/core/epoch/epoch_processing_test.go b/beacon-chain/core/epoch/epoch_processing_test.go index 7f15c9c952..135485173f 100644 --- a/beacon-chain/core/epoch/epoch_processing_test.go +++ b/beacon-chain/core/epoch/epoch_processing_test.go @@ -11,8 +11,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -256,7 +256,7 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) { slashings[ce] = 0 require.NoError(t, s.SetSlashings(slashings)) mixes := s.RandaoMixes() - mixes[ce] = [32]byte{'A'} + mixes[ce] = []byte{'A'} require.NoError(t, s.SetRandaoMixes(mixes)) newS, err := epoch.ProcessFinalUpdates(s) require.NoError(t, err) diff --git a/beacon-chain/core/epoch/precompute/BUILD.bazel b/beacon-chain/core/epoch/precompute/BUILD.bazel index a857eb7686..989775848b 100644 --- a/beacon-chain/core/epoch/precompute/BUILD.bazel +++ b/beacon-chain/core/epoch/precompute/BUILD.bazel @@ -18,7 +18,7 @@ go_library( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", @@ -46,8 +46,8 @@ go_test( "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//math:go_default_library", diff --git a/beacon-chain/core/epoch/precompute/attestation.go b/beacon-chain/core/epoch/precompute/attestation.go index b549634534..699680bf89 100644 --- a/beacon-chain/core/epoch/precompute/attestation.go +++ b/beacon-chain/core/epoch/precompute/attestation.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/monitoring/tracing" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/epoch/precompute/attestation_test.go b/beacon-chain/core/epoch/precompute/attestation_test.go index af55015d50..0b16eb6385 100644 --- a/beacon-chain/core/epoch/precompute/attestation_test.go +++ b/beacon-chain/core/epoch/precompute/attestation_test.go @@ -101,7 +101,7 @@ func TestSameHead(t *testing.T) { Target: ðpb.Checkpoint{Epoch: 0}}} r := [32]byte{'A'} br := beaconState.BlockRoots() - br[0] = r + br[0] = r[:] require.NoError(t, beaconState.SetBlockRoots(br)) att.Data.BeaconBlockRoot = r[:] same, err := precompute.SameHead(beaconState, ðpb.PendingAttestation{Data: att.Data}) @@ -121,7 +121,7 @@ func TestSameTarget(t *testing.T) { Target: ðpb.Checkpoint{Epoch: 0}}} r := [32]byte{'A'} br := beaconState.BlockRoots() - br[0] = r + br[0] = r[:] require.NoError(t, beaconState.SetBlockRoots(br)) att.Data.Target.Root = r[:] same, err := precompute.SameTarget(beaconState, ðpb.PendingAttestation{Data: att.Data}, 0) @@ -141,7 +141,7 @@ func TestAttestedPrevEpoch(t *testing.T) { Target: ðpb.Checkpoint{Epoch: 0}}} r := [32]byte{'A'} br := beaconState.BlockRoots() - br[0] = r + br[0] = r[:] require.NoError(t, beaconState.SetBlockRoots(br)) att.Data.Target.Root = r[:] att.Data.BeaconBlockRoot = r[:] @@ -160,7 +160,7 @@ func TestAttestedCurrentEpoch(t *testing.T) { r := [32]byte{'A'} br := beaconState.BlockRoots() - br[params.BeaconConfig().SlotsPerEpoch] = r + br[params.BeaconConfig().SlotsPerEpoch] = r[:] require.NoError(t, beaconState.SetBlockRoots(br)) att.Data.Target.Root = r[:] att.Data.BeaconBlockRoot = r[:] @@ -190,7 +190,7 @@ func TestProcessAttestations(t *testing.T) { att1.Data.BeaconBlockRoot = rt[:] br := beaconState.BlockRoots() newRt := [32]byte{'B'} - br[0] = newRt + br[0] = newRt[:] require.NoError(t, beaconState.SetBlockRoots(br)) att2.Data.Target.Root = newRt[:] att2.Data.BeaconBlockRoot = newRt[:] diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 1c71d23363..5b8f6eaf9c 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -4,7 +4,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/time/slots" ) diff --git a/beacon-chain/core/epoch/precompute/justification_finalization_test.go b/beacon-chain/core/epoch/precompute/justification_finalization_test.go index c877d92d70..3fd7fca676 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization_test.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization_test.go @@ -6,7 +6,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/epoch/precompute/new.go b/beacon-chain/core/epoch/precompute/new.go index a41d35c3b3..bd41d05642 100644 --- a/beacon-chain/core/epoch/precompute/new.go +++ b/beacon-chain/core/epoch/precompute/new.go @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "go.opencensus.io/trace" ) diff --git a/beacon-chain/core/epoch/precompute/new_test.go b/beacon-chain/core/epoch/precompute/new_test.go index fa8c8bc650..6ad45ab3b3 100644 --- a/beacon-chain/core/epoch/precompute/new_test.go +++ b/beacon-chain/core/epoch/precompute/new_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/core/epoch/precompute/reward_penalty.go b/beacon-chain/core/epoch/precompute/reward_penalty.go index aaf004748d..9dfdc232d5 100644 --- a/beacon-chain/core/epoch/precompute/reward_penalty.go +++ b/beacon-chain/core/epoch/precompute/reward_penalty.go @@ -5,7 +5,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" ) diff --git a/beacon-chain/core/epoch/precompute/reward_penalty_test.go b/beacon-chain/core/epoch/precompute/reward_penalty_test.go index 73f4a60a2b..8f53d4ee5c 100644 --- a/beacon-chain/core/epoch/precompute/reward_penalty_test.go +++ b/beacon-chain/core/epoch/precompute/reward_penalty_test.go @@ -10,8 +10,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" diff --git a/beacon-chain/core/epoch/precompute/slashing.go b/beacon-chain/core/epoch/precompute/slashing.go index 698da324b2..5c8fd36938 100644 --- a/beacon-chain/core/epoch/precompute/slashing.go +++ b/beacon-chain/core/epoch/precompute/slashing.go @@ -4,7 +4,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/epoch/precompute/slashing_test.go b/beacon-chain/core/epoch/precompute/slashing_test.go index a8af9a7307..22e6b86607 100644 --- a/beacon-chain/core/epoch/precompute/slashing_test.go +++ b/beacon-chain/core/epoch/precompute/slashing_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/core/execution/BUILD.bazel b/beacon-chain/core/execution/BUILD.bazel index 367e9d1fa8..8721fc2f3d 100644 --- a/beacon-chain/core/execution/BUILD.bazel +++ b/beacon-chain/core/execution/BUILD.bazel @@ -7,11 +7,10 @@ go_library( visibility = ["//beacon-chain:__subpackages__"], deps = [ "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v3:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v3:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/beacon-chain/core/execution/upgrade.go b/beacon-chain/core/execution/upgrade.go index 204d7336bb..2f60458352 100644 --- a/beacon-chain/core/execution/upgrade.go +++ b/beacon-chain/core/execution/upgrade.go @@ -3,10 +3,9 @@ package execution import ( "context" - "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - statemerge "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -37,104 +36,51 @@ func UpgradeToMerge(ctx context.Context, state state.BeaconState) (state.BeaconS return nil, err } - newState, err := statemerge.Initialize() - if err != nil { - return nil, err + s := ðpb.BeaconStateMerge{ + GenesisTime: state.GenesisTime(), + GenesisValidatorsRoot: state.GenesisValidatorRoot(), + Slot: state.Slot(), + Fork: ðpb.Fork{ + PreviousVersion: state.Fork().CurrentVersion, + CurrentVersion: params.BeaconConfig().BellatrixForkVersion, + Epoch: epoch, + }, + LatestBlockHeader: state.LatestBlockHeader(), + BlockRoots: state.BlockRoots(), + StateRoots: state.StateRoots(), + HistoricalRoots: state.HistoricalRoots(), + Eth1Data: state.Eth1Data(), + Eth1DataVotes: state.Eth1DataVotes(), + Eth1DepositIndex: state.Eth1DepositIndex(), + Validators: state.Validators(), + Balances: state.Balances(), + RandaoMixes: state.RandaoMixes(), + Slashings: state.Slashings(), + PreviousEpochParticipation: prevEpochParticipation, + CurrentEpochParticipation: currentEpochParticipation, + JustificationBits: state.JustificationBits(), + PreviousJustifiedCheckpoint: state.PreviousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: state.CurrentJustifiedCheckpoint(), + FinalizedCheckpoint: state.FinalizedCheckpoint(), + InactivityScores: inactivityScores, + CurrentSyncCommittee: currentSyncCommittee, + NextSyncCommittee: nextSyncCommittee, + LatestExecutionPayloadHeader: ðpb.ExecutionPayloadHeader{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + Random: make([]byte, 32), + BlockNumber: 0, + GasLimit: 0, + GasUsed: 0, + Timestamp: 0, + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + }, } - if err = newState.SetGenesisTime(state.GenesisTime()); err != nil { - return nil, errors.Wrap(err, "could not set genesis time") - } - if err = newState.SetGenesisValidatorRoot(state.GenesisValidatorRoot()); err != nil { - return nil, errors.Wrap(err, "could not set genesis validators root") - } - if err = newState.SetSlot(state.Slot()); err != nil { - return nil, errors.Wrap(err, "could not set slot") - } - if err = newState.SetFork(ðpb.Fork{ - PreviousVersion: state.Fork().CurrentVersion, - CurrentVersion: params.BeaconConfig().BellatrixForkVersion, - Epoch: epoch, - }); err != nil { - return nil, errors.Wrap(err, "could not set fork") - } - if err = newState.SetLatestBlockHeader(state.LatestBlockHeader()); err != nil { - return nil, errors.Wrap(err, "could not set latest block header") - } - if err = newState.SetBlockRoots(state.BlockRoots()); err != nil { - return nil, errors.Wrap(err, "could not set block roots") - } - if err = newState.SetStateRoots(state.StateRoots()); err != nil { - return nil, errors.Wrap(err, "could not set state roots") - } - if err = newState.SetHistoricalRoots(state.HistoricalRoots()); err != nil { - return nil, errors.Wrap(err, "could not set historical roots") - } - if err = newState.SetEth1Data(state.Eth1Data()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = newState.SetEth1DataVotes(state.Eth1DataVotes()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data votes") - } - if err = newState.SetEth1DepositIndex(state.Eth1DepositIndex()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 deposit index") - } - if err = newState.SetValidators(state.Validators()); err != nil { - return nil, errors.Wrap(err, "could not set validators") - } - if err = newState.SetBalances(state.Balances()); err != nil { - return nil, errors.Wrap(err, "could not set balances") - } - if err = newState.SetRandaoMixes(state.RandaoMixes()); err != nil { - return nil, errors.Wrap(err, "could not set randao mixes") - } - if err = newState.SetSlashings(state.Slashings()); err != nil { - return nil, errors.Wrap(err, "could not set slashings") - } - if err = newState.SetJustificationBits(state.JustificationBits()); err != nil { - return nil, errors.Wrap(err, "could not set justification bits") - } - if err = newState.SetPreviousParticipationBits(prevEpochParticipation); err != nil { - return nil, errors.Wrap(err, "could not set previous participation bits") - } - if err = newState.SetCurrentParticipationBits(currentEpochParticipation); err != nil { - return nil, errors.Wrap(err, "could not set current participation bits") - } - if err = newState.SetInactivityScores(inactivityScores); err != nil { - return nil, errors.Wrap(err, "could not set inactivity scores") - } - if err = newState.SetPreviousJustifiedCheckpoint(state.PreviousJustifiedCheckpoint()); err != nil { - return nil, errors.Wrap(err, "could not set previous justified checkpoint") - } - if err = newState.SetCurrentJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { - return nil, errors.Wrap(err, "could not set current justified checkpoint") - } - if err = newState.SetFinalizedCheckpoint(state.FinalizedCheckpoint()); err != nil { - return nil, errors.Wrap(err, "could not set finalized checkpoint") - } - if err := newState.SetCurrentSyncCommittee(currentSyncCommittee); err != nil { - return nil, errors.Wrap(err, "could not set current sync committee") - } - if err := newState.SetNextSyncCommittee(nextSyncCommittee); err != nil { - return nil, errors.Wrap(err, "could not set next sync committee") - } - if err := newState.SetLatestExecutionPayloadHeader(ðpb.ExecutionPayloadHeader{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptRoot: make([]byte, 32), - LogsBloom: make([]byte, 256), - Random: make([]byte, 32), - BlockNumber: 0, - GasLimit: 0, - GasUsed: 0, - Timestamp: 0, - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, 32), - }); err != nil { - return nil, errors.Wrap(err, "could not set latest execution payload header") - } - - return newState, nil + return v3.InitializeFromProto(s) } diff --git a/beacon-chain/core/helpers/BUILD.bazel b/beacon-chain/core/helpers/BUILD.bazel index 017422430f..3d3b906788 100644 --- a/beacon-chain/core/helpers/BUILD.bazel +++ b/beacon-chain/core/helpers/BUILD.bazel @@ -39,7 +39,7 @@ go_library( deps = [ "//beacon-chain/cache:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//container/slice:go_default_library", "//container/trie:go_default_library", @@ -79,9 +79,9 @@ go_test( deps = [ "//beacon-chain/cache:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", diff --git a/beacon-chain/core/helpers/attestation_test.go b/beacon-chain/core/helpers/attestation_test.go index b0296a44e5..f14e17e13c 100644 --- a/beacon-chain/core/helpers/attestation_test.go +++ b/beacon-chain/core/helpers/attestation_test.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/core/helpers/beacon_committee.go b/beacon-chain/core/helpers/beacon_committee.go index d77d0f5725..30d490ebc7 100644 --- a/beacon-chain/core/helpers/beacon_committee.go +++ b/beacon-chain/core/helpers/beacon_committee.go @@ -13,7 +13,7 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/slice" "github.com/prysmaticlabs/prysm/crypto/hash" diff --git a/beacon-chain/core/helpers/beacon_committee_test.go b/beacon-chain/core/helpers/beacon_committee_test.go index a7bb6d286f..d55f13206f 100644 --- a/beacon-chain/core/helpers/beacon_committee_test.go +++ b/beacon-chain/core/helpers/beacon_committee_test.go @@ -9,7 +9,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/slice" "github.com/prysmaticlabs/prysm/crypto/hash" diff --git a/beacon-chain/core/helpers/block.go b/beacon-chain/core/helpers/block.go index b48f0ba667..b814bb10a7 100644 --- a/beacon-chain/core/helpers/block.go +++ b/beacon-chain/core/helpers/block.go @@ -5,7 +5,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/time/slots" @@ -48,7 +48,7 @@ func BlockRootAtSlot(state state.ReadOnlyBeaconState, slot types.Slot) ([]byte, if err != nil { return nil, err } - return root[:], err + return root, err } // StateRootAtSlot returns the cached state root at that particular slot. If no state @@ -61,7 +61,7 @@ func StateRootAtSlot(state state.ReadOnlyBeaconState, slot types.Slot) ([]byte, if err != nil { return nil, err } - return root[:], err + return root, err } // BlockRoot returns the block root stored in the BeaconState for epoch start slot. diff --git a/beacon-chain/core/helpers/block_test.go b/beacon-chain/core/helpers/block_test.go index fb5c5eb01a..11618e623a 100644 --- a/beacon-chain/core/helpers/block_test.go +++ b/beacon-chain/core/helpers/block_test.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/core/helpers/genesis.go b/beacon-chain/core/helpers/genesis.go index bc4cc8d36f..651441f4fd 100644 --- a/beacon-chain/core/helpers/genesis.go +++ b/beacon-chain/core/helpers/genesis.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/helpers/randao.go b/beacon-chain/core/helpers/randao.go index 0a30716990..535006b18b 100644 --- a/beacon-chain/core/helpers/randao.go +++ b/beacon-chain/core/helpers/randao.go @@ -2,7 +2,7 @@ package helpers import ( types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/crypto/hash" @@ -50,5 +50,5 @@ func RandaoMix(state state.ReadOnlyBeaconState, epoch types.Epoch) ([]byte, erro if err != nil { return nil, err } - return root[:], err + return root, err } diff --git a/beacon-chain/core/helpers/randao_test.go b/beacon-chain/core/helpers/randao_test.go index 761df72967..cc9373a5d9 100644 --- a/beacon-chain/core/helpers/randao_test.go +++ b/beacon-chain/core/helpers/randao_test.go @@ -5,7 +5,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/helpers/rewards_penalties.go b/beacon-chain/core/helpers/rewards_penalties.go index 2c169dddd4..5108732768 100644 --- a/beacon-chain/core/helpers/rewards_penalties.go +++ b/beacon-chain/core/helpers/rewards_penalties.go @@ -5,7 +5,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/cache" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" mathutil "github.com/prysmaticlabs/prysm/math" "github.com/prysmaticlabs/prysm/time/slots" diff --git a/beacon-chain/core/helpers/rewards_penalties_test.go b/beacon-chain/core/helpers/rewards_penalties_test.go index 9ebb60de5d..62abfc697c 100644 --- a/beacon-chain/core/helpers/rewards_penalties_test.go +++ b/beacon-chain/core/helpers/rewards_penalties_test.go @@ -6,7 +6,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/helpers/sync_committee.go b/beacon-chain/core/helpers/sync_committee.go index 4c0dd24c0a..ffbcf91999 100644 --- a/beacon-chain/core/helpers/sync_committee.go +++ b/beacon-chain/core/helpers/sync_committee.go @@ -9,7 +9,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/time/slots" diff --git a/beacon-chain/core/helpers/sync_committee_test.go b/beacon-chain/core/helpers/sync_committee_test.go index 2578d62f61..55e46d450a 100644 --- a/beacon-chain/core/helpers/sync_committee_test.go +++ b/beacon-chain/core/helpers/sync_committee_test.go @@ -7,8 +7,8 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/cache" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/helpers/validators.go b/beacon-chain/core/helpers/validators.go index f593fbb149..ea7a19181b 100644 --- a/beacon-chain/core/helpers/validators.go +++ b/beacon-chain/core/helpers/validators.go @@ -10,7 +10,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/core/helpers/validators_test.go b/beacon-chain/core/helpers/validators_test.go index ee628d1d7d..5bbe50dbf8 100644 --- a/beacon-chain/core/helpers/validators_test.go +++ b/beacon-chain/core/helpers/validators_test.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/hash" diff --git a/beacon-chain/core/helpers/weak_subjectivity.go b/beacon-chain/core/helpers/weak_subjectivity.go index 0d66b4d212..2136a001e5 100644 --- a/beacon-chain/core/helpers/weak_subjectivity.go +++ b/beacon-chain/core/helpers/weak_subjectivity.go @@ -11,7 +11,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/helpers/weak_subjectivity_test.go b/beacon-chain/core/helpers/weak_subjectivity_test.go index e491eda137..310db0130b 100644 --- a/beacon-chain/core/helpers/weak_subjectivity_test.go +++ b/beacon-chain/core/helpers/weak_subjectivity_test.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/signing/BUILD.bazel b/beacon-chain/core/signing/BUILD.bazel index 5e83609c9e..ba6dcf87a1 100644 --- a/beacon-chain/core/signing/BUILD.bazel +++ b/beacon-chain/core/signing/BUILD.bazel @@ -9,7 +9,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/signing", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", @@ -30,7 +30,7 @@ go_test( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", diff --git a/beacon-chain/core/signing/signing_root.go b/beacon-chain/core/signing/signing_root.go index 6c81187627..1ccb431bda 100644 --- a/beacon-chain/core/signing/signing_root.go +++ b/beacon-chain/core/signing/signing_root.go @@ -4,7 +4,7 @@ import ( fssz "github.com/ferranbt/fastssz" "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -23,8 +23,7 @@ var ErrSigFailedToVerify = errors.New("signature did not verify") // ComputeDomainAndSign computes the domain and signing root and sign it using the passed in private key. func ComputeDomainAndSign(st state.ReadOnlyBeaconState, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, key bls.SecretKey) ([]byte, error) { - gvRoot := st.GenesisValidatorRoot() - d, err := Domain(st.Fork(), epoch, domain, gvRoot[:]) + d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorRoot()) if err != nil { return nil, err } @@ -70,8 +69,7 @@ func ComputeDomainVerifySigningRoot(st state.ReadOnlyBeaconState, index types.Va if err != nil { return err } - gvRoot := st.GenesisValidatorRoot() - d, err := Domain(st.Fork(), epoch, domain, gvRoot[:]) + d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorRoot()) if err != nil { return err } diff --git a/beacon-chain/core/signing/signing_root_test.go b/beacon-chain/core/signing/signing_root_test.go index 6374dc89ef..c189eafdc6 100644 --- a/beacon-chain/core/signing/signing_root_test.go +++ b/beacon-chain/core/signing/signing_root_test.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/beacon-chain/core/time/BUILD.bazel b/beacon-chain/core/time/BUILD.bazel index 4826b559ff..63c0a71f32 100644 --- a/beacon-chain/core/time/BUILD.bazel +++ b/beacon-chain/core/time/BUILD.bazel @@ -6,7 +6,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/time", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", @@ -19,7 +19,7 @@ go_test( srcs = ["slot_epoch_test.go"], embed = [":go_default_library"], deps = [ - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/core/time/slot_epoch.go b/beacon-chain/core/time/slot_epoch.go index 63e67508d8..8e0506d036 100644 --- a/beacon-chain/core/time/slot_epoch.go +++ b/beacon-chain/core/time/slot_epoch.go @@ -2,7 +2,7 @@ package time import ( types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/runtime/version" "github.com/prysmaticlabs/prysm/time/slots" diff --git a/beacon-chain/core/time/slot_epoch_test.go b/beacon-chain/core/time/slot_epoch_test.go index a50d1861d0..843bad5e30 100644 --- a/beacon-chain/core/time/slot_epoch_test.go +++ b/beacon-chain/core/time/slot_epoch_test.go @@ -4,7 +4,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/core/transition/BUILD.bazel b/beacon-chain/core/transition/BUILD.bazel index 149f2173cf..40c2637dd5 100644 --- a/beacon-chain/core/transition/BUILD.bazel +++ b/beacon-chain/core/transition/BUILD.bazel @@ -34,11 +34,10 @@ go_library( "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/transition/interop:go_default_library", "//beacon-chain/core/validators:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/features:go_default_library", - "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", @@ -84,8 +83,8 @@ go_test( "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", @@ -125,7 +124,7 @@ go_test( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/benchmark:go_default_library", diff --git a/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go b/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go index ea70e19590..8422e9df38 100644 --- a/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go +++ b/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go @@ -12,7 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" p2pType "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go b/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go index 010d2f321a..ceae411594 100644 --- a/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go +++ b/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go @@ -12,7 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" p2pType "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/beacon-chain/core/transition/benchmarks_test.go b/beacon-chain/core/transition/benchmarks_test.go index ea85f39598..653ec199e1 100644 --- a/beacon-chain/core/transition/benchmarks_test.go +++ b/beacon-chain/core/transition/benchmarks_test.go @@ -7,8 +7,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" @@ -112,7 +112,7 @@ func BenchmarkHashTreeRootState_FullState(b *testing.B) { func BenchmarkMarshalState_FullState(b *testing.B) { beaconState, err := benchmark.PreGenstateFullEpochs() require.NoError(b, err) - natState, err := v1.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + natState, err := v1.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(b, err) b.Run("Proto_Marshal", func(b *testing.B) { b.ResetTimer() @@ -136,7 +136,7 @@ func BenchmarkMarshalState_FullState(b *testing.B) { func BenchmarkUnmarshalState_FullState(b *testing.B) { beaconState, err := benchmark.PreGenstateFullEpochs() require.NoError(b, err) - natState, err := v1.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + natState, err := v1.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(b, err) protoObject, err := proto.Marshal(natState) require.NoError(b, err) diff --git a/beacon-chain/core/transition/interop/BUILD.bazel b/beacon-chain/core/transition/interop/BUILD.bazel index 5bc780d20e..15484c337e 100644 --- a/beacon-chain/core/transition/interop/BUILD.bazel +++ b/beacon-chain/core/transition/interop/BUILD.bazel @@ -13,7 +13,7 @@ go_library( "//tools:__subpackages__", ], deps = [ - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/features:go_default_library", "//io/file:go_default_library", "//proto/prysm/v1alpha1/block:go_default_library", diff --git a/beacon-chain/core/transition/interop/write_state_to_disk.go b/beacon-chain/core/transition/interop/write_state_to_disk.go index 5f342ea9de..b042a7d4b3 100644 --- a/beacon-chain/core/transition/interop/write_state_to_disk.go +++ b/beacon-chain/core/transition/interop/write_state_to_disk.go @@ -5,7 +5,7 @@ import ( "os" "path" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/io/file" ) diff --git a/beacon-chain/core/transition/skip_slot_cache.go b/beacon-chain/core/transition/skip_slot_cache.go index 53b3f1ecbb..0c280afb96 100644 --- a/beacon-chain/core/transition/skip_slot_cache.go +++ b/beacon-chain/core/transition/skip_slot_cache.go @@ -5,7 +5,7 @@ import ( "errors" "github.com/prysmaticlabs/prysm/beacon-chain/cache" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) diff --git a/beacon-chain/core/transition/skip_slot_cache_test.go b/beacon-chain/core/transition/skip_slot_cache_test.go index be839a957b..838d1770c3 100644 --- a/beacon-chain/core/transition/skip_slot_cache_test.go +++ b/beacon-chain/core/transition/skip_slot_cache_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/assert" @@ -19,7 +19,7 @@ func TestSkipSlotCache_OK(t *testing.T) { transition.SkipSlotCache.Enable() defer transition.SkipSlotCache.Disable() bState, privs := util.DeterministicGenesisState(t, params.MinimalSpecConfig().MinGenesisActiveValidatorCount) - pbState, err := v1.ProtobufBeaconState(bState.ToProto()) + pbState, err := v1.ProtobufBeaconState(bState.CloneInnerState()) require.NoError(t, err) originalState, err := v1.InitializeFromProto(pbState) require.NoError(t, err) @@ -38,12 +38,12 @@ func TestSkipSlotCache_OK(t *testing.T) { bState, err = transition.ExecuteStateTransition(context.Background(), bState, wrapper.WrappedPhase0SignedBeaconBlock(blk)) require.NoError(t, err, "Could not process state transition") - assert.DeepEqual(t, originalState.ToProto(), bState.ToProto(), "Skipped slots cache leads to different states") + assert.DeepEqual(t, originalState.CloneInnerState(), bState.CloneInnerState(), "Skipped slots cache leads to different states") } func TestSkipSlotCache_ConcurrentMixup(t *testing.T) { bState, privs := util.DeterministicGenesisState(t, params.MinimalSpecConfig().MinGenesisActiveValidatorCount) - pbState, err := v1.ProtobufBeaconState(bState.ToProto()) + pbState, err := v1.ProtobufBeaconState(bState.CloneInnerState()) require.NoError(t, err) originalState, err := v1.InitializeFromProto(pbState) require.NoError(t, err) @@ -120,7 +120,7 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) { tmp1, err := transition.ProcessSlots(context.Background(), expected1.Copy(), problemSlot+1) require.NoError(t, err) gotRoot := tmp1.StateRoots()[problemSlot] - require.DeepEqual(t, expectedRoot1, gotRoot, "State roots for chain 1 are bad, expected root doesn't match") + require.DeepEqual(t, expectedRoot1[:], gotRoot, "State roots for chain 1 are bad, expected root doesn't match") expected2, err := transition.ProcessSlots(context.Background(), s0.Copy(), problemSlot) require.NoError(t, err) @@ -131,7 +131,7 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) { tmp2, err := transition.ProcessSlots(context.Background(), expected2.Copy(), problemSlot+1) require.NoError(t, err) gotRoot = tmp2.StateRoots()[problemSlot] - require.DeepEqual(t, expectedRoot2, gotRoot, "State roots for chain 2 are bad, expected root doesn't match") + require.DeepEqual(t, expectedRoot2[:], gotRoot, "State roots for chain 2 are bad, expected root doesn't match") var wg sync.WaitGroup wg.Add(len(setups)) @@ -143,9 +143,9 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) { roots := outState.StateRoots() gotRoot := roots[problemSlot] if i%2 == 0 { - assert.DeepEqual(t, expectedRoot1, gotRoot, "Unexpected root on chain 1") + assert.DeepEqual(t, expectedRoot1[:], gotRoot, "Unexpected root on chain 1") } else { - assert.DeepEqual(t, expectedRoot2, gotRoot, "Unexpected root on chain 2") + assert.DeepEqual(t, expectedRoot2[:], gotRoot, "Unexpected root on chain 2") } wg.Done() } diff --git a/beacon-chain/core/transition/state.go b/beacon-chain/core/transition/state.go index 5bee5ded2c..1759acc8bd 100644 --- a/beacon-chain/core/transition/state.go +++ b/beacon-chain/core/transition/state.go @@ -6,10 +6,9 @@ import ( "github.com/pkg/errors" b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -81,29 +80,28 @@ func OptimizedGenesisBeaconState(genesisTime uint64, preState state.BeaconState, return nil, errors.New("no eth1data provided for genesis state") } - var randaoMixes [fieldparams.RandaoMixesLength][32]byte + randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) for i := 0; i < len(randaoMixes); i++ { - var h [32]byte - copy(h[:], eth1Data.BlockHash) + h := make([]byte, 32) + copy(h, eth1Data.BlockHash) randaoMixes[i] = h } - zeroHash32 := params.BeaconConfig().ZeroHash - zeroHash := zeroHash32[:] + zeroHash := params.BeaconConfig().ZeroHash[:] activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) for i := 0; i < len(activeIndexRoots); i++ { activeIndexRoots[i] = zeroHash } - var blockRoots [fieldparams.BlockRootsLength][32]byte + blockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) for i := 0; i < len(blockRoots); i++ { - blockRoots[i] = zeroHash32 + blockRoots[i] = zeroHash } - var stateRoots [fieldparams.StateRootsLength][32]byte + stateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) for i := 0; i < len(stateRoots); i++ { - stateRoots[i] = zeroHash32 + stateRoots[i] = zeroHash } slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector) @@ -113,6 +111,53 @@ func OptimizedGenesisBeaconState(genesisTime uint64, preState state.BeaconState, return nil, errors.Wrapf(err, "could not hash tree root genesis validators %v", err) } + state := ðpb.BeaconState{ + // Misc fields. + Slot: 0, + GenesisTime: genesisTime, + GenesisValidatorsRoot: genesisValidatorsRoot[:], + + Fork: ðpb.Fork{ + PreviousVersion: params.BeaconConfig().GenesisForkVersion, + CurrentVersion: params.BeaconConfig().GenesisForkVersion, + Epoch: 0, + }, + + // Validator registry fields. + Validators: preState.Validators(), + Balances: preState.Balances(), + + // Randomness and committees. + RandaoMixes: randaoMixes, + + // Finality. + PreviousJustifiedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + CurrentJustifiedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + JustificationBits: []byte{0}, + FinalizedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + + HistoricalRoots: [][]byte{}, + BlockRoots: blockRoots, + StateRoots: stateRoots, + Slashings: slashings, + CurrentEpochAttestations: []*ethpb.PendingAttestation{}, + PreviousEpochAttestations: []*ethpb.PendingAttestation{}, + + // Eth1 data. + Eth1Data: eth1Data, + Eth1DataVotes: []*ethpb.Eth1Data{}, + Eth1DepositIndex: preState.Eth1DepositIndex(), + } + bodyRoot, err := (ðpb.BeaconBlockBody{ RandaoReveal: make([]byte, 96), Eth1Data: ðpb.Eth1Data{ @@ -125,126 +170,40 @@ func OptimizedGenesisBeaconState(genesisTime uint64, preState state.BeaconState, return nil, errors.Wrap(err, "could not hash tree root empty block body") } - s, err := v1.Initialize() - if err != nil { - return nil, errors.Wrap(err, "could not initialize state from proto state") - } - - if err = s.SetGenesisTime(genesisTime); err != nil { - return nil, errors.Wrap(err, "could not set genesis time") - } - if err = s.SetGenesisValidatorRoot(genesisValidatorsRoot); err != nil { - return nil, errors.Wrap(err, "could not set genesis validators root") - } - if err = s.SetSlot(0); err != nil { - return nil, errors.Wrap(err, "could not set slot") - } - if err = s.SetFork(ðpb.Fork{ - PreviousVersion: params.BeaconConfig().GenesisForkVersion, - CurrentVersion: params.BeaconConfig().GenesisForkVersion, - Epoch: 0, - }); err != nil { - return nil, errors.Wrap(err, "could not set fork") - } - if err = s.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ + state.LatestBlockHeader = ðpb.BeaconBlockHeader{ ParentRoot: zeroHash, StateRoot: zeroHash, BodyRoot: bodyRoot[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set latest block header") - } - if err = s.SetBlockRoots(&blockRoots); err != nil { - return nil, errors.Wrap(err, "could not set block roots") - } - if err = s.SetStateRoots(&stateRoots); err != nil { - return nil, errors.Wrap(err, "could not set state roots") - } - if err = s.SetHistoricalRoots([][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set historical roots") - } - if err = s.SetEth1Data(eth1Data); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = s.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data votes") - } - if err = s.SetEth1DepositIndex(preState.Eth1DepositIndex()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 deposit index") - } - if err = s.SetValidators(preState.Validators()); err != nil { - return nil, errors.Wrap(err, "could not set validators") - } - if err = s.SetBalances(preState.Balances()); err != nil { - return nil, errors.Wrap(err, "could not set balances") - } - if err = s.SetRandaoMixes(&randaoMixes); err != nil { - return nil, errors.Wrap(err, "could not set randao mixes") - } - if err = s.SetSlashings(slashings); err != nil { - return nil, errors.Wrap(err, "could not set slashings") - } - if err = s.SetJustificationBits([]byte{0}); err != nil { - return nil, errors.Wrap(err, "could not set justification bits") - } - if err = s.SetPreviousJustifiedCheckpoint(ðpb.Checkpoint{ - Epoch: 0, - Root: params.BeaconConfig().ZeroHash[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set previous justified checkpoint") - } - if err = s.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{ - Epoch: 0, - Root: params.BeaconConfig().ZeroHash[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set current justified checkpoint") - } - if err = s.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: 0, - Root: params.BeaconConfig().ZeroHash[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set finalized checkpoint") } - return s, nil + return v1.InitializeFromProto(state) } // EmptyGenesisState returns an empty beacon state object. func EmptyGenesisState() (state.BeaconState, error) { - s, err := v1.Initialize() - if err != nil { - return nil, errors.Wrap(err, "could not initialize state from proto state") - } + state := ðpb.BeaconState{ + // Misc fields. + Slot: 0, + Fork: ðpb.Fork{ + PreviousVersion: params.BeaconConfig().GenesisForkVersion, + CurrentVersion: params.BeaconConfig().GenesisForkVersion, + Epoch: 0, + }, + // Validator registry fields. + Validators: []*ethpb.Validator{}, + Balances: []uint64{}, - if err = s.SetSlot(0); err != nil { - return nil, errors.Wrap(err, "could not set slot") - } - if err = s.SetFork(ðpb.Fork{ - PreviousVersion: params.BeaconConfig().GenesisForkVersion, - CurrentVersion: params.BeaconConfig().GenesisForkVersion, - Epoch: 0, - }); err != nil { - return nil, errors.Wrap(err, "could not set fork") - } - if err = s.SetHistoricalRoots([][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set historical roots") - } - if err = s.SetEth1Data(ðpb.Eth1Data{}); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = s.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data votes") - } - if err = s.SetValidators([]*ethpb.Validator{}); err != nil { - return nil, errors.Wrap(err, "could not set validators") - } - if err = s.SetBalances([]uint64{}); err != nil { - return nil, errors.Wrap(err, "could not set balances") - } - if err = s.SetJustificationBits([]byte{0}); err != nil { - return nil, errors.Wrap(err, "could not set justification bits") - } + JustificationBits: []byte{0}, + HistoricalRoots: [][]byte{}, + CurrentEpochAttestations: []*ethpb.PendingAttestation{}, + PreviousEpochAttestations: []*ethpb.PendingAttestation{}, - return s, nil + // Eth1 data. + Eth1Data: ðpb.Eth1Data{}, + Eth1DataVotes: []*ethpb.Eth1Data{}, + Eth1DepositIndex: 0, + } + return v1.InitializeFromProto(state) } // IsValidGenesisState gets called whenever there's a deposit event, diff --git a/beacon-chain/core/transition/state_fuzz_test.go b/beacon-chain/core/transition/state_fuzz_test.go index c446033c29..2d95b1c780 100644 --- a/beacon-chain/core/transition/state_fuzz_test.go +++ b/beacon-chain/core/transition/state_fuzz_test.go @@ -5,7 +5,7 @@ import ( "testing" fuzz "github.com/google/gofuzz" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/core/transition/state_test.go b/beacon-chain/core/transition/state_test.go index 2d0adb40e9..c461478fd6 100644 --- a/beacon-chain/core/transition/state_test.go +++ b/beacon-chain/core/transition/state_test.go @@ -6,10 +6,9 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/hash" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" @@ -64,7 +63,7 @@ func TestGenesisBeaconState_OK(t *testing.T) { assert.Equal(t, latestRandaoMixesLength, types.Epoch(len(newState.RandaoMixes())), "Length of RandaoMixes was not correctly initialized") mix, err := newState.RandaoMixAtIndex(0) require.NoError(t, err) - assert.DeepEqual(t, bytesutil.ToBytes32(eth1Data.BlockHash), mix, "RandaoMixes was not correctly initialized") + assert.DeepEqual(t, eth1Data.BlockHash, mix, "RandaoMixes was not correctly initialized") // Finality fields checks. assert.Equal(t, genesisEpoch, newState.PreviousJustifiedCheckpoint().Epoch, "PreviousJustifiedCheckpoint.Epoch was not correctly initialized") @@ -83,8 +82,8 @@ func TestGenesisBeaconState_OK(t *testing.T) { zeroHash := params.BeaconConfig().ZeroHash // History root checks. - assert.DeepEqual(t, zeroHash, newState.StateRoots()[0], "StateRoots was not correctly initialized") - assert.DeepEqual(t, zeroHash, newState.BlockRoots()[0], "BlockRoots was not correctly initialized") + assert.DeepEqual(t, zeroHash[:], newState.StateRoots()[0], "StateRoots was not correctly initialized") + assert.DeepEqual(t, zeroHash[:], newState.BlockRoots()[0], "BlockRoots was not correctly initialized") // Deposit root checks. assert.DeepEqual(t, eth1Data.DepositRoot, newState.Eth1Data().DepositRoot, "Eth1Data DepositRoot was not correctly initialized") @@ -99,9 +98,9 @@ func TestGenesisState_HashEquality(t *testing.T) { state, err := transition.GenesisBeaconState(context.Background(), deposits, 0, ðpb.Eth1Data{BlockHash: make([]byte, 32)}) require.NoError(t, err) - pbState1, err := v1.ProtobufBeaconState(state1.ToProto()) + pbState1, err := v1.ProtobufBeaconState(state1.CloneInnerState()) require.NoError(t, err) - pbstate, err := v1.ProtobufBeaconState(state.ToProto()) + pbstate, err := v1.ProtobufBeaconState(state.CloneInnerState()) require.NoError(t, err) root1, err1 := hash.HashProto(pbState1) @@ -123,7 +122,7 @@ func TestGenesisState_InitializesLatestBlockHashes(t *testing.T) { assert.Equal(t, want, got, "The slice underlying array capacity is wrong") for _, h := range s.BlockRoots() { - assert.DeepEqual(t, params.BeaconConfig().ZeroHash, h, "Unexpected non-zero hash data") + assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], h, "Unexpected non-zero hash data") } } diff --git a/beacon-chain/core/transition/stateutils/BUILD.bazel b/beacon-chain/core/transition/stateutils/BUILD.bazel index d913edfc81..3c8669806e 100644 --- a/beacon-chain/core/transition/stateutils/BUILD.bazel +++ b/beacon-chain/core/transition/stateutils/BUILD.bazel @@ -22,7 +22,7 @@ go_test( srcs = ["validator_index_map_test.go"], deps = [ ":go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/fieldparams:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/core/transition/stateutils/validator_index_map_test.go b/beacon-chain/core/transition/stateutils/validator_index_map_test.go index 2597bd9339..61131d0f38 100644 --- a/beacon-chain/core/transition/stateutils/validator_index_map_test.go +++ b/beacon-chain/core/transition/stateutils/validator_index_map_test.go @@ -5,7 +5,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition/stateutils" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/core/transition/trailing_slot_state_cache.go b/beacon-chain/core/transition/trailing_slot_state_cache.go index 174a9a002d..510fbfb06e 100644 --- a/beacon-chain/core/transition/trailing_slot_state_cache.go +++ b/beacon-chain/core/transition/trailing_slot_state_cache.go @@ -7,7 +7,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ) type nextSlotCache struct { diff --git a/beacon-chain/core/transition/transition.go b/beacon-chain/core/transition/transition.go index 499dc10b05..18709fb5fe 100644 --- a/beacon-chain/core/transition/transition.go +++ b/beacon-chain/core/transition/transition.go @@ -16,7 +16,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" "github.com/prysmaticlabs/prysm/monitoring/tracing" diff --git a/beacon-chain/core/transition/transition_fuzz_test.go b/beacon-chain/core/transition/transition_fuzz_test.go index b37f08d18b..6eb9a0c374 100644 --- a/beacon-chain/core/transition/transition_fuzz_test.go +++ b/beacon-chain/core/transition/transition_fuzz_test.go @@ -7,18 +7,16 @@ import ( fuzz "github.com/google/gofuzz" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" - "github.com/prysmaticlabs/prysm/testing/require" ) func TestFuzzExecuteStateTransition_1000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() ctx := context.Background() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} sb := ðpb.SignedBeaconBlock{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) @@ -36,8 +34,7 @@ func TestFuzzCalculateStateRoot_1000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() ctx := context.Background() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} sb := ðpb.SignedBeaconBlock{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) @@ -55,8 +52,7 @@ func TestFuzzProcessSlot_1000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() ctx := context.Background() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) for i := 0; i < 1000; i++ { @@ -72,8 +68,7 @@ func TestFuzzProcessSlots_1000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() ctx := context.Background() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} slot := types.Slot(0) fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) @@ -91,8 +86,7 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() ctx := context.Background() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} bb := ðpb.SignedBeaconBlock{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) @@ -109,8 +103,7 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) { func TestFuzzverifyOperationLengths_10000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} bb := ðpb.SignedBeaconBlock{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) @@ -125,8 +118,7 @@ func TestFuzzverifyOperationLengths_10000(t *testing.T) { func TestFuzzCanProcessEpoch_10000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) for i := 0; i < 10000; i++ { @@ -139,8 +131,7 @@ func TestFuzzProcessEpochPrecompute_1000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() ctx := context.Background() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) for i := 0; i < 1000; i++ { @@ -156,8 +147,7 @@ func TestFuzzProcessBlockForStateRoot_1000(t *testing.T) { SkipSlotCache.Disable() defer SkipSlotCache.Enable() ctx := context.Background() - state, err := v1.Initialize() - require.NoError(t, err) + state := &v1.BeaconState{} sb := ðpb.SignedBeaconBlock{} fuzzer := fuzz.NewWithSeed(0) fuzzer.NilChance(0.1) diff --git a/beacon-chain/core/transition/transition_no_verify_sig.go b/beacon-chain/core/transition/transition_no_verify_sig.go index 2f85eb4ae8..b33751e98d 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig.go +++ b/beacon-chain/core/transition/transition_no_verify_sig.go @@ -11,7 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition/interop" v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/monitoring/tracing" diff --git a/beacon-chain/core/transition/transition_test.go b/beacon-chain/core/transition/transition_test.go index 2ddf52b663..75cdd0879c 100644 --- a/beacon-chain/core/transition/transition_test.go +++ b/beacon-chain/core/transition/transition_test.go @@ -12,8 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -141,11 +141,11 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) { }, }, } - var blockRoots [fieldparams.BlockRootsLength][32]byte + var blockRoots [][]byte for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ { - blockRoots[i] = [32]byte{byte(i)} + blockRoots = append(blockRoots, []byte{byte(i)}) } - require.NoError(t, beaconState.SetBlockRoots(&blockRoots)) + require.NoError(t, beaconState.SetBlockRoots(blockRoots)) blockAtt := util.HydrateAttestation(ðpb.Attestation{ Data: ðpb.AttestationData{ Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("hello-world"), 32)}, @@ -253,8 +253,7 @@ func createFullBlockWithOperations(t *testing.T) (state.BeaconState, }, AttestingIndices: []uint64{0, 1}, }) - gvr := beaconState.GenesisValidatorRoot() - domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att1.Data, domain) require.NoError(t, err) @@ -286,11 +285,11 @@ func createFullBlockWithOperations(t *testing.T) (state.BeaconState, }, } - var blockRoots [fieldparams.BlockRootsLength][32]byte + var blockRoots [][]byte for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ { - blockRoots[i] = [32]byte{byte(i)} + blockRoots = append(blockRoots, []byte{byte(i)}) } - require.NoError(t, beaconState.SetBlockRoots(&blockRoots)) + require.NoError(t, beaconState.SetBlockRoots(blockRoots)) aggBits := bitfield.NewBitlist(1) aggBits.SetBitAt(0, true) diff --git a/beacon-chain/core/validators/BUILD.bazel b/beacon-chain/core/validators/BUILD.bazel index 12667570b2..ba3ca8f87c 100644 --- a/beacon-chain/core/validators/BUILD.bazel +++ b/beacon-chain/core/validators/BUILD.bazel @@ -11,7 +11,7 @@ go_library( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//time/slots:go_default_library", @@ -28,7 +28,7 @@ go_test( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/core/validators/validator.go b/beacon-chain/core/validators/validator.go index ec76c47472..ed75ab797c 100644 --- a/beacon-chain/core/validators/validator.go +++ b/beacon-chain/core/validators/validator.go @@ -11,7 +11,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/time/slots" diff --git a/beacon-chain/core/validators/validator_test.go b/beacon-chain/core/validators/validator_test.go index 903b5493bd..179ddf9763 100644 --- a/beacon-chain/core/validators/validator_test.go +++ b/beacon-chain/core/validators/validator_test.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/db/iface/BUILD.bazel b/beacon-chain/db/iface/BUILD.bazel index d089b14a36..a8f9c9fd54 100644 --- a/beacon-chain/db/iface/BUILD.bazel +++ b/beacon-chain/db/iface/BUILD.bazel @@ -12,7 +12,7 @@ go_library( deps = [ "//beacon-chain/db/filters:go_default_library", "//beacon-chain/slasher/types:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//monitoring/backup:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/block:go_default_library", diff --git a/beacon-chain/db/iface/interface.go b/beacon-chain/db/iface/interface.go index ad900097f7..0e1b0f88b8 100644 --- a/beacon-chain/db/iface/interface.go +++ b/beacon-chain/db/iface/interface.go @@ -11,7 +11,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/db/filters" slashertypes "github.com/prysmaticlabs/prysm/beacon-chain/slasher/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/monitoring/backup" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" diff --git a/beacon-chain/db/kv/BUILD.bazel b/beacon-chain/db/kv/BUILD.bazel index 13853a7a0a..ac59f928ab 100644 --- a/beacon-chain/db/kv/BUILD.bazel +++ b/beacon-chain/db/kv/BUILD.bazel @@ -38,11 +38,11 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/db/filters:go_default_library", "//beacon-chain/db/iface:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/genesis:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", - "//beacon-chain/state/v3:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/genesis:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", + "//beacon-chain/state-proto/v3:go_default_library", "//config/features:go_default_library", "//config/params:go_default_library", "//container/slice:go_default_library", @@ -101,9 +101,9 @@ go_test( deps = [ "//beacon-chain/db/filters:go_default_library", "//beacon-chain/db/iface:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", diff --git a/beacon-chain/db/kv/genesis.go b/beacon-chain/db/kv/genesis.go index 58d53e975f..d0c29ffae5 100644 --- a/beacon-chain/db/kv/genesis.go +++ b/beacon-chain/db/kv/genesis.go @@ -10,8 +10,8 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" dbIface "github.com/prysmaticlabs/prysm/beacon-chain/db/iface" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" diff --git a/beacon-chain/db/kv/migration_state_validators_test.go b/beacon-chain/db/kv/migration_state_validators_test.go index 1c3cdefc47..f53d6635e1 100644 --- a/beacon-chain/db/kv/migration_state_validators_test.go +++ b/beacon-chain/db/kv/migration_state_validators_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/golang/snappy" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/features" v1alpha1 "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" @@ -91,7 +91,7 @@ func Test_migrateStateValidators(t *testing.T) { assert.NoError(t, hashErr) individualHashes = append(individualHashes, hash[:]) } - pbState, err := v1.ProtobufBeaconState(st.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(st.InnerStateUnsafe()) assert.NoError(t, err) validatorsFoundCount := 0 for _, val := range pbState.Validators { @@ -137,7 +137,7 @@ func Test_migrateStateValidators(t *testing.T) { blockRoot := [32]byte{'A'} rcvdState, err := dbStore.State(context.Background(), blockRoot) assert.NoError(t, err) - require.DeepSSZEqual(t, rcvdState.ToProtoUnsafe(), state.ToProtoUnsafe(), "saved state with validators and retrieved state are not matching") + require.DeepSSZEqual(t, rcvdState.InnerStateUnsafe(), state.InnerStateUnsafe(), "saved state with validators and retrieved state are not matching") // find hashes of the validators that are set as part of the state var hashes []byte @@ -150,7 +150,7 @@ func Test_migrateStateValidators(t *testing.T) { } // check if all the validators that were in the state, are stored properly in the validator bucket - pbState, err := v1.ProtobufBeaconState(rcvdState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(rcvdState.InnerStateUnsafe()) assert.NoError(t, err) validatorsFoundCount := 0 for _, val := range pbState.Validators { @@ -240,7 +240,7 @@ func Test_migrateAltairStateValidators(t *testing.T) { blockRoot := [32]byte{'A'} rcvdState, err := dbStore.State(context.Background(), blockRoot) assert.NoError(t, err) - require.DeepSSZEqual(t, rcvdState.ToProtoUnsafe(), state.ToProtoUnsafe(), "saved state with validators and retrieved state are not matching") + require.DeepSSZEqual(t, rcvdState.InnerStateUnsafe(), state.InnerStateUnsafe(), "saved state with validators and retrieved state are not matching") // find hashes of the validators that are set as part of the state var hashes []byte @@ -253,7 +253,7 @@ func Test_migrateAltairStateValidators(t *testing.T) { } // check if all the validators that were in the state, are stored properly in the validator bucket - pbState, err := v2.ProtobufBeaconState(rcvdState.ToProtoUnsafe()) + pbState, err := v2.ProtobufBeaconState(rcvdState.InnerStateUnsafe()) assert.NoError(t, err) validatorsFoundCount := 0 for _, val := range pbState.Validators { diff --git a/beacon-chain/db/kv/state.go b/beacon-chain/db/kv/state.go index 43da7a37b0..9e91016143 100644 --- a/beacon-chain/db/kv/state.go +++ b/beacon-chain/db/kv/state.go @@ -8,11 +8,11 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/genesis" - 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" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/genesis" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -148,21 +148,21 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly validatorKeys := make([][]byte, len(states)) // For every state, this stores a compressed list of validator keys. for i, st := range states { var validators []*ethpb.Validator - switch st.ToProtoUnsafe().(type) { + switch st.InnerStateUnsafe().(type) { case *ethpb.BeaconState: - pbState, err := v1.ProtobufBeaconState(st.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(st.InnerStateUnsafe()) if err != nil { return err } validators = pbState.Validators case *ethpb.BeaconStateAltair: - pbState, err := v2.ProtobufBeaconState(st.ToProtoUnsafe()) + pbState, err := v2.ProtobufBeaconState(st.InnerStateUnsafe()) if err != nil { return err } validators = pbState.Validators case *ethpb.BeaconStateMerge: - pbState, err := v3.ProtobufBeaconState(st.ToProtoUnsafe()) + pbState, err := v3.ProtobufBeaconState(st.InnerStateUnsafe()) if err != nil { return err } @@ -201,7 +201,7 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly // validator entries.To bring the gap closer, we empty the validators // just before Put() and repopulate that state with original validators. // look at issue https://github.com/prysmaticlabs/prysm/issues/9262. - switch rawType := states[i].ToProtoUnsafe().(type) { + switch rawType := states[i].InnerStateUnsafe().(type) { case *ethpb.BeaconState: pbState, err := v1.ProtobufBeaconState(rawType) if err != nil { @@ -461,15 +461,15 @@ func (s *Store) unmarshalState(_ context.Context, enc []byte, validatorEntries [ // marshal versioned state from struct type down to bytes. func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, error) { - switch st.ToProtoUnsafe().(type) { + switch st.InnerStateUnsafe().(type) { case *ethpb.BeaconState: - rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconState) + rState, ok := st.InnerStateUnsafe().(*ethpb.BeaconState) if !ok { return nil, errors.New("non valid inner state") } return encode(ctx, rState) case *ethpb.BeaconStateAltair: - rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateAltair) + rState, ok := st.InnerStateUnsafe().(*ethpb.BeaconStateAltair) if !ok { return nil, errors.New("non valid inner state") } @@ -482,7 +482,7 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er } return snappy.Encode(nil, append(altairKey, rawObj...)), nil case *ethpb.BeaconStateMerge: - rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateMerge) + rState, ok := st.InnerStateUnsafe().(*ethpb.BeaconStateMerge) if !ok { return nil, errors.New("non valid inner state") } diff --git a/beacon-chain/db/kv/state_test.go b/beacon-chain/db/kv/state_test.go index 602d3ddd1b..60bbacdd23 100644 --- a/beacon-chain/db/kv/state_test.go +++ b/beacon-chain/db/kv/state_test.go @@ -8,7 +8,7 @@ import ( "time" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -38,7 +38,7 @@ func TestState_CanSaveRetrieve(t *testing.T) { savedS, err := db.State(context.Background(), r) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe(), "saved state and retrieved state are not matching") + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedS.InnerStateUnsafe(), "saved state and retrieved state are not matching") savedS, err = db.State(context.Background(), [32]byte{'B'}) require.NoError(t, err) @@ -71,7 +71,7 @@ func TestState_CanSaveRetrieveValidatorEntries(t *testing.T) { savedS, err := db.State(context.Background(), r) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe(), "saved state with validators and retrieved state are not matching") + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedS.InnerStateUnsafe(), "saved state with validators and retrieved state are not matching") // check if the index of the second state is still present. err = db.db.Update(func(tx *bolt.Tx) error { @@ -123,7 +123,7 @@ func TestStateAltair_CanSaveRetrieveValidatorEntries(t *testing.T) { savedS, err := db.State(context.Background(), r) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe(), "saved state with validators and retrieved state are not matching") + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedS.InnerStateUnsafe(), "saved state with validators and retrieved state are not matching") // check if the index of the second state is still present. err = db.db.Update(func(tx *bolt.Tx) error { @@ -233,7 +233,7 @@ func TestState_CanSaveRetrieveValidatorEntriesWithoutCache(t *testing.T) { savedS, err := db.State(context.Background(), r) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe(), "saved state with validators and retrieved state are not matching") + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedS.InnerStateUnsafe(), "saved state with validators and retrieved state are not matching") // check if the index of the second state is still present. err = db.db.Update(func(tx *bolt.Tx) error { @@ -354,7 +354,7 @@ func TestGenesisState_CanSaveRetrieve(t *testing.T) { savedGenesisS, err := db.GenesisState(context.Background()) require.NoError(t, err) - assert.DeepSSZEqual(t, st.ToProtoUnsafe(), savedGenesisS.ToProtoUnsafe(), "Did not retrieve saved state") + assert.DeepSSZEqual(t, st.InnerStateUnsafe(), savedGenesisS.InnerStateUnsafe(), "Did not retrieve saved state") require.NoError(t, db.SaveGenesisBlockRoot(context.Background(), [32]byte{'C'})) } @@ -468,7 +468,7 @@ func TestStore_SaveDeleteState_CanGetHighestBelow(t *testing.T) { st, err := util.NewBeaconState() require.NoError(t, err) require.NoError(t, st.SetSlot(1)) - s0 := st.ToProtoUnsafe() + s0 := st.InnerStateUnsafe() require.NoError(t, db.SaveState(context.Background(), st, r)) b.Block.Slot = 100 @@ -478,7 +478,7 @@ func TestStore_SaveDeleteState_CanGetHighestBelow(t *testing.T) { st, err = util.NewBeaconState() require.NoError(t, err) require.NoError(t, st.SetSlot(100)) - s1 := st.ToProtoUnsafe() + s1 := st.InnerStateUnsafe() require.NoError(t, db.SaveState(context.Background(), st, r1)) b.Block.Slot = 1000 @@ -488,21 +488,21 @@ func TestStore_SaveDeleteState_CanGetHighestBelow(t *testing.T) { st, err = util.NewBeaconState() require.NoError(t, err) require.NoError(t, st.SetSlot(1000)) - s2 := st.ToProtoUnsafe() + s2 := st.InnerStateUnsafe() require.NoError(t, db.SaveState(context.Background(), st, r2)) highest, err := db.HighestSlotStatesBelow(context.Background(), 2) require.NoError(t, err) - assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), s0) + assert.DeepSSZEqual(t, highest[0].InnerStateUnsafe(), s0) highest, err = db.HighestSlotStatesBelow(context.Background(), 101) require.NoError(t, err) - assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), s1) + assert.DeepSSZEqual(t, highest[0].InnerStateUnsafe(), s1) highest, err = db.HighestSlotStatesBelow(context.Background(), 1001) require.NoError(t, err) - assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), s2) + assert.DeepSSZEqual(t, highest[0].InnerStateUnsafe(), s2) } func TestStore_GenesisState_CanGetHighestBelow(t *testing.T) { @@ -527,14 +527,14 @@ func TestStore_GenesisState_CanGetHighestBelow(t *testing.T) { highest, err := db.HighestSlotStatesBelow(context.Background(), 2) require.NoError(t, err) - assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), st.ToProtoUnsafe()) + assert.DeepSSZEqual(t, highest[0].InnerStateUnsafe(), st.InnerStateUnsafe()) highest, err = db.HighestSlotStatesBelow(context.Background(), 1) require.NoError(t, err) - assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), genesisState.ToProtoUnsafe()) + assert.DeepSSZEqual(t, highest[0].InnerStateUnsafe(), genesisState.InnerStateUnsafe()) highest, err = db.HighestSlotStatesBelow(context.Background(), 0) require.NoError(t, err) - assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), genesisState.ToProtoUnsafe()) + assert.DeepSSZEqual(t, highest[0].InnerStateUnsafe(), genesisState.InnerStateUnsafe()) } func TestStore_CleanUpDirtyStates_AboveThreshold(t *testing.T) { @@ -655,7 +655,7 @@ func TestAltairState_CanSaveRetrieve(t *testing.T) { savedS, err := db.State(context.Background(), r) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe()) + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedS.InnerStateUnsafe()) savedS, err = db.State(context.Background(), [32]byte{'B'}) require.NoError(t, err) @@ -806,7 +806,7 @@ func TestStateMerge_CanSaveRetrieveValidatorEntries(t *testing.T) { savedS, err := db.State(context.Background(), r) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe(), "saved state with validators and retrieved state are not matching") + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedS.InnerStateUnsafe(), "saved state with validators and retrieved state are not matching") // check if the index of the second state is still present. err = db.db.Update(func(tx *bolt.Tx) error { @@ -849,7 +849,7 @@ func TestMergeState_CanSaveRetrieve(t *testing.T) { savedS, err := db.State(context.Background(), r) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe()) + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedS.InnerStateUnsafe()) savedS, err = db.State(context.Background(), [32]byte{'B'}) require.NoError(t, err) diff --git a/beacon-chain/db/kv/wss.go b/beacon-chain/db/kv/wss.go index 82194dc3cb..6fac694b7d 100644 --- a/beacon-chain/db/kv/wss.go +++ b/beacon-chain/db/kv/wss.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" diff --git a/beacon-chain/deterministic-genesis/BUILD.bazel b/beacon-chain/deterministic-genesis/BUILD.bazel index 47a10653b9..7cae423457 100644 --- a/beacon-chain/deterministic-genesis/BUILD.bazel +++ b/beacon-chain/deterministic-genesis/BUILD.bazel @@ -12,8 +12,8 @@ go_library( "//beacon-chain/cache/depositcache:go_default_library", "//beacon-chain/db:go_default_library", "//beacon-chain/powchain:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime:go_default_library", "//runtime/interop:go_default_library", diff --git a/beacon-chain/deterministic-genesis/service.go b/beacon-chain/deterministic-genesis/service.go index b860f3687c..2c1d9e74b6 100644 --- a/beacon-chain/deterministic-genesis/service.go +++ b/beacon-chain/deterministic-genesis/service.go @@ -13,8 +13,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime" "github.com/prysmaticlabs/prysm/runtime/interop" diff --git a/beacon-chain/monitor/BUILD.bazel b/beacon-chain/monitor/BUILD.bazel index ebd0cac455..4fa4412079 100644 --- a/beacon-chain/monitor/BUILD.bazel +++ b/beacon-chain/monitor/BUILD.bazel @@ -22,8 +22,8 @@ go_library( "//beacon-chain/core/feed/operation:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", @@ -54,7 +54,7 @@ go_test( "//beacon-chain/core/feed:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/db/testing:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/monitor/process_attestation.go b/beacon-chain/monitor/process_attestation.go index 021a9d36c4..317939b9b1 100644 --- a/beacon-chain/monitor/process_attestation.go +++ b/beacon-chain/monitor/process_attestation.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/monitor/process_block.go b/beacon-chain/monitor/process_block.go index d2310cb467..732d6e84af 100644 --- a/beacon-chain/monitor/process_block.go +++ b/beacon-chain/monitor/process_block.go @@ -6,7 +6,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" diff --git a/beacon-chain/monitor/process_sync_committee.go b/beacon-chain/monitor/process_sync_committee.go index 921cba7197..d338f5fe9e 100644 --- a/beacon-chain/monitor/process_sync_committee.go +++ b/beacon-chain/monitor/process_sync_committee.go @@ -3,7 +3,7 @@ package monitor import ( "fmt" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/sirupsen/logrus" diff --git a/beacon-chain/monitor/service.go b/beacon-chain/monitor/service.go index 79f60f0182..04de9a1cbb 100644 --- a/beacon-chain/monitor/service.go +++ b/beacon-chain/monitor/service.go @@ -13,8 +13,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/time/slots" "github.com/sirupsen/logrus" ) diff --git a/beacon-chain/monitor/service_test.go b/beacon-chain/monitor/service_test.go index c5c9b853b4..87b5566503 100644 --- a/beacon-chain/monitor/service_test.go +++ b/beacon-chain/monitor/service_test.go @@ -13,7 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/node/BUILD.bazel b/beacon-chain/node/BUILD.bazel index 03e29098b4..141b893aa2 100644 --- a/beacon-chain/node/BUILD.bazel +++ b/beacon-chain/node/BUILD.bazel @@ -37,8 +37,8 @@ go_library( "//beacon-chain/rpc:go_default_library", "//beacon-chain/rpc/apimiddleware:go_default_library", "//beacon-chain/slasher:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//beacon-chain/sync/initial-sync:go_default_library", "//cmd:go_default_library", diff --git a/beacon-chain/node/node.go b/beacon-chain/node/node.go index 5a5eb61ba4..81bd5b9e76 100644 --- a/beacon-chain/node/node.go +++ b/beacon-chain/node/node.go @@ -40,8 +40,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/rpc" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/apimiddleware" "github.com/prysmaticlabs/prysm/beacon-chain/slasher" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" regularsync "github.com/prysmaticlabs/prysm/beacon-chain/sync" initialsync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync" "github.com/prysmaticlabs/prysm/cmd" diff --git a/beacon-chain/operations/slashings/BUILD.bazel b/beacon-chain/operations/slashings/BUILD.bazel index 0ebc25b11b..61eccb1b51 100644 --- a/beacon-chain/operations/slashings/BUILD.bazel +++ b/beacon-chain/operations/slashings/BUILD.bazel @@ -21,7 +21,7 @@ go_library( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//container/slice:go_default_library", "//proto/prysm/v1alpha1:go_default_library", @@ -45,7 +45,7 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", diff --git a/beacon-chain/operations/slashings/mock.go b/beacon-chain/operations/slashings/mock.go index b5042e2c11..4ce97fda5c 100644 --- a/beacon-chain/operations/slashings/mock.go +++ b/beacon-chain/operations/slashings/mock.go @@ -3,7 +3,7 @@ package slashings import ( "context" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/operations/slashings/service.go b/beacon-chain/operations/slashings/service.go index c6e328c247..b865c302b7 100644 --- a/beacon-chain/operations/slashings/service.go +++ b/beacon-chain/operations/slashings/service.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/slice" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/operations/slashings/service_attester_test.go b/beacon-chain/operations/slashings/service_attester_test.go index 410f88328b..66073ebaae 100644 --- a/beacon-chain/operations/slashings/service_attester_test.go +++ b/beacon-chain/operations/slashings/service_attester_test.go @@ -5,7 +5,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/operations/slashings/types.go b/beacon-chain/operations/slashings/types.go index 23a0549526..8d6bba22d5 100644 --- a/beacon-chain/operations/slashings/types.go +++ b/beacon-chain/operations/slashings/types.go @@ -5,7 +5,7 @@ import ( "sync" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/operations/voluntaryexits/BUILD.bazel b/beacon-chain/operations/voluntaryexits/BUILD.bazel index ad3dde9f54..8e5a6277c4 100644 --- a/beacon-chain/operations/voluntaryexits/BUILD.bazel +++ b/beacon-chain/operations/voluntaryexits/BUILD.bazel @@ -13,7 +13,7 @@ go_library( "//testing/fuzz:__pkg__", ], deps = [ - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//time/slots:go_default_library", @@ -28,7 +28,7 @@ go_test( srcs = ["service_test.go"], embed = [":go_default_library"], deps = [ - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", diff --git a/beacon-chain/operations/voluntaryexits/mock.go b/beacon-chain/operations/voluntaryexits/mock.go index 7a321fa23f..919dd2c36d 100644 --- a/beacon-chain/operations/voluntaryexits/mock.go +++ b/beacon-chain/operations/voluntaryexits/mock.go @@ -4,7 +4,7 @@ import ( "context" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/operations/voluntaryexits/service.go b/beacon-chain/operations/voluntaryexits/service.go index 5767ed16ae..0a5b97ad3d 100644 --- a/beacon-chain/operations/voluntaryexits/service.go +++ b/beacon-chain/operations/voluntaryexits/service.go @@ -6,7 +6,7 @@ import ( "sync" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/time/slots" diff --git a/beacon-chain/operations/voluntaryexits/service_test.go b/beacon-chain/operations/voluntaryexits/service_test.go index 8c64f2ee6f..1a13b6d9f6 100644 --- a/beacon-chain/operations/voluntaryexits/service_test.go +++ b/beacon-chain/operations/voluntaryexits/service_test.go @@ -6,7 +6,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/p2p/BUILD.bazel b/beacon-chain/p2p/BUILD.bazel index 2ba5738975..b4d86513f9 100644 --- a/beacon-chain/p2p/BUILD.bazel +++ b/beacon-chain/p2p/BUILD.bazel @@ -142,7 +142,6 @@ go_test( "//beacon-chain/p2p/peers/scorers:go_default_library", "//beacon-chain/p2p/testing:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", "//cmd/beacon-chain/flags:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", diff --git a/beacon-chain/p2p/encoder/ssz_test.go b/beacon-chain/p2p/encoder/ssz_test.go index 3157a67466..2b7f38bdc0 100644 --- a/beacon-chain/p2p/encoder/ssz_test.go +++ b/beacon-chain/p2p/encoder/ssz_test.go @@ -115,7 +115,7 @@ func TestSszNetworkEncoder_DecodeWithMultipleFrames(t *testing.T) { maxChunkSize := uint64(1 << 22) c.MaxChunkSize = maxChunkSize params.OverrideBeaconNetworkConfig(c) - _, err := e.EncodeWithMaxLength(buf, st.ToProtoUnsafe().(*ethpb.BeaconState)) + _, err := e.EncodeWithMaxLength(buf, st.InnerStateUnsafe().(*ethpb.BeaconState)) require.NoError(t, err) // Max snappy block size if buf.Len() <= 76490 { diff --git a/beacon-chain/p2p/gossip_scoring_params_test.go b/beacon-chain/p2p/gossip_scoring_params_test.go index 3f767946fe..c66824198f 100644 --- a/beacon-chain/p2p/gossip_scoring_params_test.go +++ b/beacon-chain/p2p/gossip_scoring_params_test.go @@ -6,7 +6,6 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" @@ -26,7 +25,7 @@ func TestCorrect_ActiveValidatorsCount(t *testing.T) { ctx: context.Background(), cfg: &Config{DB: db}, } - bState, err := util.NewBeaconState(func(state state.BeaconState) error { + bState, err := util.NewBeaconState(func(state *ethpb.BeaconState) error { validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) for i := 0; i < len(validators); i++ { validators[i] = ðpb.Validator{ @@ -36,7 +35,7 @@ func TestCorrect_ActiveValidatorsCount(t *testing.T) { Slashed: false, } } - require.NoError(t, state.SetValidators(validators)) + state.Validators = validators return nil }) require.NoError(t, err) diff --git a/beacon-chain/powchain/BUILD.bazel b/beacon-chain/powchain/BUILD.bazel index 61f650dca2..42808700c4 100644 --- a/beacon-chain/powchain/BUILD.bazel +++ b/beacon-chain/powchain/BUILD.bazel @@ -28,9 +28,9 @@ go_library( "//beacon-chain/core/transition:go_default_library", "//beacon-chain/db:go_default_library", "//beacon-chain/powchain/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", "//contracts/deposit:go_default_library", @@ -86,7 +86,7 @@ go_test( "//beacon-chain/db/testing:go_default_library", "//beacon-chain/powchain/testing:go_default_library", "//beacon-chain/powchain/types:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", diff --git a/beacon-chain/powchain/log_processing.go b/beacon-chain/powchain/log_processing.go index d1be94c1ab..85c594c5dd 100644 --- a/beacon-chain/powchain/log_processing.go +++ b/beacon-chain/powchain/log_processing.go @@ -16,7 +16,7 @@ import ( statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" contracts "github.com/prysmaticlabs/prysm/contracts/deposit" "github.com/prysmaticlabs/prysm/crypto/hash" @@ -503,7 +503,7 @@ func (s *Service) checkForChainstart(ctx context.Context, blockHash [32]byte, bl // save all powchain related metadata to disk. func (s *Service) savePowchainData(ctx context.Context) error { - pbState, err := v1.ProtobufBeaconState(s.preGenesisState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe()) if err != nil { return err } diff --git a/beacon-chain/powchain/options.go b/beacon-chain/powchain/options.go index bf0b1ccf5a..0126056a8b 100644 --- a/beacon-chain/powchain/options.go +++ b/beacon-chain/powchain/options.go @@ -5,8 +5,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/db" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/network" ) diff --git a/beacon-chain/powchain/service.go b/beacon-chain/powchain/service.go index 3f2c377e9f..218c8a4688 100644 --- a/beacon-chain/powchain/service.go +++ b/beacon-chain/powchain/service.go @@ -28,9 +28,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/powchain/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" contracts "github.com/prysmaticlabs/prysm/contracts/deposit" @@ -1011,7 +1011,7 @@ func (s *Service) ensureValidPowchainData(ctx context.Context) error { return errors.Wrap(err, "unable to retrieve eth1 data") } if eth1Data == nil || !eth1Data.ChainstartData.Chainstarted || !validateDepositContainers(eth1Data.DepositContainers) { - pbState, err := v1.ProtobufBeaconState(s.preGenesisState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe()) if err != nil { return err } diff --git a/beacon-chain/powchain/service_test.go b/beacon-chain/powchain/service_test.go index 51314ebe1b..8342eccfae 100644 --- a/beacon-chain/powchain/service_test.go +++ b/beacon-chain/powchain/service_test.go @@ -19,7 +19,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" contracts "github.com/prysmaticlabs/prysm/contracts/deposit" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/powchain/testing/BUILD.bazel b/beacon-chain/powchain/testing/BUILD.bazel index 9c79e0a95b..fece9d8e6c 100644 --- a/beacon-chain/powchain/testing/BUILD.bazel +++ b/beacon-chain/powchain/testing/BUILD.bazel @@ -15,8 +15,8 @@ go_library( deps = [ "//async/event:go_default_library", "//beacon-chain/powchain/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//container/trie:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/powchain/testing/mock_faulty_powchain.go b/beacon-chain/powchain/testing/mock_faulty_powchain.go index 51ca92571b..a1d6ddfa37 100644 --- a/beacon-chain/powchain/testing/mock_faulty_powchain.go +++ b/beacon-chain/powchain/testing/mock_faulty_powchain.go @@ -8,8 +8,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/prysmaticlabs/prysm/async/event" "github.com/prysmaticlabs/prysm/beacon-chain/powchain/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/container/trie" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/powchain/testing/mock_powchain.go b/beacon-chain/powchain/testing/mock_powchain.go index 171d410a59..640857dbf9 100644 --- a/beacon-chain/powchain/testing/mock_powchain.go +++ b/beacon-chain/powchain/testing/mock_powchain.go @@ -15,7 +15,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/prysmaticlabs/prysm/async/event" "github.com/prysmaticlabs/prysm/beacon-chain/powchain/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/rpc/BUILD.bazel b/beacon-chain/rpc/BUILD.bazel index fcff389c8c..bdf2bb6a19 100644 --- a/beacon-chain/rpc/BUILD.bazel +++ b/beacon-chain/rpc/BUILD.bazel @@ -33,7 +33,7 @@ go_library( "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/statefetcher:go_default_library", "//beacon-chain/slasher:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//config/features:go_default_library", "//config/params:go_default_library", diff --git a/beacon-chain/rpc/eth/beacon/BUILD.bazel b/beacon-chain/rpc/eth/beacon/BUILD.bazel index d59977385c..6cc9c1204c 100644 --- a/beacon-chain/rpc/eth/beacon/BUILD.bazel +++ b/beacon-chain/rpc/eth/beacon/BUILD.bazel @@ -32,9 +32,9 @@ go_library( "//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/statefetcher:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/features:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", @@ -88,8 +88,8 @@ go_test( "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/statefetcher:go_default_library", "//beacon-chain/rpc/testutil:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", diff --git a/beacon-chain/rpc/eth/beacon/pool.go b/beacon-chain/rpc/eth/beacon/pool.go index 2a7a9fe93d..89438233a3 100644 --- a/beacon-chain/rpc/eth/beacon/pool.go +++ b/beacon-chain/rpc/eth/beacon/pool.go @@ -275,8 +275,7 @@ func (bs *Server) SubmitVoluntaryExit(ctx context.Context, req *ethpbv1.SignedVo return nil, status.Errorf(codes.Internal, "Could not get exiting validator: %v", err) } alphaExit := migration.V1ExitToV1Alpha1(req) - gvRoot := headState.GenesisValidatorRoot() - err = blocks.VerifyExitAndSignature(validator, headState.Slot(), headState.Fork(), alphaExit, gvRoot[:]) + err = blocks.VerifyExitAndSignature(validator, headState.Slot(), headState.Fork(), alphaExit, headState.GenesisValidatorRoot()) if err != nil { return nil, status.Errorf(codes.InvalidArgument, "Invalid voluntary exit: %v", err) } diff --git a/beacon-chain/rpc/eth/beacon/pool_test.go b/beacon-chain/rpc/eth/beacon/pool_test.go index 0d13772ab8..bb5d6514fd 100644 --- a/beacon-chain/rpc/eth/beacon/pool_test.go +++ b/beacon-chain/rpc/eth/beacon/pool_test.go @@ -16,7 +16,6 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" p2pMock "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -379,8 +378,8 @@ func TestSubmitAttesterSlashing_Ok(t *testing.T) { validator := ðpbv1alpha1.Validator{ PublicKey: keys[0].PublicKey().Marshal(), } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators([]*ethpbv1alpha1.Validator{validator})) + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = []*ethpbv1alpha1.Validator{validator} return nil }) require.NoError(t, err) @@ -494,8 +493,8 @@ func TestSubmitProposerSlashing_Ok(t *testing.T) { PublicKey: keys[0].PublicKey().Marshal(), WithdrawableEpoch: eth2types.Epoch(1), } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators([]*ethpbv1alpha1.Validator{validator})) + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = []*ethpbv1alpha1.Validator{validator} return nil }) require.NoError(t, err) @@ -594,10 +593,10 @@ func TestSubmitVoluntaryExit_Ok(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, PublicKey: keys[0].PublicKey().Marshal(), } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators([]*ethpbv1alpha1.Validator{validator})) + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = []*ethpbv1alpha1.Validator{validator} // Satisfy activity time required before exiting. - require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)))) + state.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)) return nil }) require.NoError(t, err) @@ -640,8 +639,8 @@ func TestSubmitVoluntaryExit_InvalidValidatorIndex(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, PublicKey: keys[0].PublicKey().Marshal(), } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators([]*ethpbv1alpha1.Validator{validator})) + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = []*ethpbv1alpha1.Validator{validator} return nil }) require.NoError(t, err) @@ -675,8 +674,8 @@ func TestSubmitVoluntaryExit_InvalidExit(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, PublicKey: keys[0].PublicKey().Marshal(), } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators([]*ethpbv1alpha1.Validator{validator})) + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = []*ethpbv1alpha1.Validator{validator} return nil }) require.NoError(t, err) @@ -717,13 +716,13 @@ func TestServer_SubmitAttestations_Ok(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, }, } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators(validators)) - require.NoError(t, beaconState.SetSlot(1)) - require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(ðpbv1alpha1.Checkpoint{ + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = validators + state.Slot = 1 + state.PreviousJustifiedCheckpoint = ðpbv1alpha1.Checkpoint{ Epoch: 0, Root: bytesutil.PadTo([]byte("sourceroot1"), 32), - })) + } return nil }) require.NoError(t, err) @@ -823,13 +822,13 @@ func TestServer_SubmitAttestations_ValidAttestationSubmitted(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, }, } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators(validators)) - require.NoError(t, beaconState.SetSlot(1)) - require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(ðpbv1alpha1.Checkpoint{ + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = validators + state.Slot = 1 + state.PreviousJustifiedCheckpoint = ðpbv1alpha1.Checkpoint{ Epoch: 0, Root: bytesutil.PadTo([]byte("sourceroot1"), 32), - })) + } return nil }) @@ -923,13 +922,13 @@ func TestServer_SubmitAttestations_InvalidAttestationGRPCHeader(t *testing.T) { ExitEpoch: params.BeaconConfig().FarFutureEpoch, }, } - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetValidators(validators)) - require.NoError(t, beaconState.SetSlot(1)) - require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(ðpbv1alpha1.Checkpoint{ + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = validators + state.Slot = 1 + state.PreviousJustifiedCheckpoint = ðpbv1alpha1.Checkpoint{ Epoch: 0, Root: bytesutil.PadTo([]byte("sourceroot1"), 32), - })) + } return nil }) diff --git a/beacon-chain/rpc/eth/beacon/server.go b/beacon-chain/rpc/eth/beacon/server.go index 3fc59f1e1e..27d605814d 100644 --- a/beacon-chain/rpc/eth/beacon/server.go +++ b/beacon-chain/rpc/eth/beacon/server.go @@ -14,7 +14,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/p2p" v1alpha1validator "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" ) // Server defines a server implementation of the gRPC Beacon Chain service, diff --git a/beacon-chain/rpc/eth/beacon/state.go b/beacon-chain/rpc/eth/beacon/state.go index f3edb3a223..9a2ed95cf1 100644 --- a/beacon-chain/rpc/eth/beacon/state.go +++ b/beacon-chain/rpc/eth/beacon/state.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1" eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/rpc/eth/beacon/state_test.go b/beacon-chain/rpc/eth/beacon/state_test.go index 87c7e16c58..081748273c 100644 --- a/beacon-chain/rpc/eth/beacon/state_test.go +++ b/beacon-chain/rpc/eth/beacon/state_test.go @@ -7,7 +7,6 @@ import ( chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" eth "github.com/prysmaticlabs/prysm/proto/eth/v1" @@ -92,12 +91,12 @@ func TestGetStateRoot(t *testing.T) { } func TestGetStateFork(t *testing.T) { - fillFork := func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetFork(ðpb.Fork{ + fillFork := func(state *ethpb.BeaconState) error { + state.Fork = ðpb.Fork{ PreviousVersion: []byte("prev"), CurrentVersion: []byte("curr"), Epoch: 123, - })) + } return nil } fakeState, err := util.NewBeaconState(fillFork) @@ -120,19 +119,19 @@ func TestGetStateFork(t *testing.T) { } func TestGetFinalityCheckpoints(t *testing.T) { - fillCheckpoints := func(state state.BeaconState) error { - require.NoError(t, state.SetPreviousJustifiedCheckpoint(ðpb.Checkpoint{ + fillCheckpoints := func(state *ethpb.BeaconState) error { + state.PreviousJustifiedCheckpoint = ðpb.Checkpoint{ Root: bytesutil.PadTo([]byte("previous"), 32), Epoch: 113, - })) - require.NoError(t, state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{ + } + state.CurrentJustifiedCheckpoint = ðpb.Checkpoint{ Root: bytesutil.PadTo([]byte("current"), 32), Epoch: 123, - })) - require.NoError(t, state.SetFinalizedCheckpoint(ðpb.Checkpoint{ + } + state.FinalizedCheckpoint = ðpb.Checkpoint{ Root: bytesutil.PadTo([]byte("finalized"), 32), Epoch: 103, - })) + } return nil } fakeState, err := util.NewBeaconState(fillCheckpoints) diff --git a/beacon-chain/rpc/eth/beacon/sync_committee.go b/beacon-chain/rpc/eth/beacon/sync_committee.go index 1ad1260ada..15d77e2158 100644 --- a/beacon-chain/rpc/eth/beacon/sync_committee.go +++ b/beacon-chain/rpc/eth/beacon/sync_committee.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/api/grpc" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2" diff --git a/beacon-chain/rpc/eth/beacon/sync_committee_test.go b/beacon-chain/rpc/eth/beacon/sync_committee_test.go index 30a618dfc3..e61138542f 100644 --- a/beacon-chain/rpc/eth/beacon/sync_committee_test.go +++ b/beacon-chain/rpc/eth/beacon/sync_committee_test.go @@ -16,7 +16,7 @@ import ( mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2" diff --git a/beacon-chain/rpc/eth/beacon/validator.go b/beacon-chain/rpc/eth/beacon/validator.go index 438d2fac51..8d00aa8fb0 100644 --- a/beacon-chain/rpc/eth/beacon/validator.go +++ b/beacon-chain/rpc/eth/beacon/validator.go @@ -8,8 +8,8 @@ import ( types "github.com/prysmaticlabs/eth2-types" corehelpers "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1" diff --git a/beacon-chain/rpc/eth/beacon/validator_test.go b/beacon-chain/rpc/eth/beacon/validator_test.go index c582572f26..4a0cf33e4b 100644 --- a/beacon-chain/rpc/eth/beacon/validator_test.go +++ b/beacon-chain/rpc/eth/beacon/validator_test.go @@ -11,8 +11,8 @@ import ( rpchelpers "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1" "github.com/prysmaticlabs/prysm/proto/migration" diff --git a/beacon-chain/rpc/eth/debug/BUILD.bazel b/beacon-chain/rpc/eth/debug/BUILD.bazel index 189db1927c..4e9bc943fd 100644 --- a/beacon-chain/rpc/eth/debug/BUILD.bazel +++ b/beacon-chain/rpc/eth/debug/BUILD.bazel @@ -13,8 +13,8 @@ go_library( "//beacon-chain/db:go_default_library", "//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/statefetcher:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//proto/eth/v1:go_default_library", "//proto/eth/v2:go_default_library", "//proto/migration:go_default_library", diff --git a/beacon-chain/rpc/eth/debug/debug.go b/beacon-chain/rpc/eth/debug/debug.go index bf2d31a62d..06fcf80181 100644 --- a/beacon-chain/rpc/eth/debug/debug.go +++ b/beacon-chain/rpc/eth/debug/debug.go @@ -4,8 +4,8 @@ import ( "context" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers" - statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1" ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2" "github.com/prysmaticlabs/prysm/proto/migration" diff --git a/beacon-chain/rpc/eth/helpers/BUILD.bazel b/beacon-chain/rpc/eth/helpers/BUILD.bazel index d8bff8841c..83b0cc5c3a 100644 --- a/beacon-chain/rpc/eth/helpers/BUILD.bazel +++ b/beacon-chain/rpc/eth/helpers/BUILD.bazel @@ -13,7 +13,7 @@ go_library( "//api/grpc:go_default_library", "//beacon-chain/blockchain:go_default_library", "//beacon-chain/rpc/statefetcher:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//beacon-chain/sync:go_default_library", "//config/params:go_default_library", "//proto/eth/v1:go_default_library", @@ -34,7 +34,7 @@ go_test( deps = [ "//api/grpc:go_default_library", "//beacon-chain/blockchain/testing:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library", "//config/params:go_default_library", "//proto/eth/v1:go_default_library", diff --git a/beacon-chain/rpc/eth/helpers/validator_status.go b/beacon-chain/rpc/eth/helpers/validator_status.go index 2f6e318579..cca3eb76fa 100644 --- a/beacon-chain/rpc/eth/helpers/validator_status.go +++ b/beacon-chain/rpc/eth/helpers/validator_status.go @@ -3,7 +3,7 @@ package helpers import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1" ) diff --git a/beacon-chain/rpc/eth/helpers/validator_status_test.go b/beacon-chain/rpc/eth/helpers/validator_status_test.go index 3a3364177f..6dbed862f6 100644 --- a/beacon-chain/rpc/eth/helpers/validator_status_test.go +++ b/beacon-chain/rpc/eth/helpers/validator_status_test.go @@ -5,7 +5,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1" "github.com/prysmaticlabs/prysm/proto/migration" diff --git a/beacon-chain/rpc/eth/validator/BUILD.bazel b/beacon-chain/rpc/eth/validator/BUILD.bazel index 2fe8815278..61ed7e4cc4 100644 --- a/beacon-chain/rpc/eth/validator/BUILD.bazel +++ b/beacon-chain/rpc/eth/validator/BUILD.bazel @@ -19,8 +19,8 @@ go_library( "//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/statefetcher:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//beacon-chain/sync:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -63,8 +63,8 @@ go_test( "//beacon-chain/powchain/testing:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/testutil:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", diff --git a/beacon-chain/rpc/eth/validator/validator.go b/beacon-chain/rpc/eth/validator/validator.go index 1376da6619..5501b5a2fd 100644 --- a/beacon-chain/rpc/eth/validator/validator.go +++ b/beacon-chain/rpc/eth/validator/validator.go @@ -14,8 +14,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" rpchelpers "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/rpc/eth/validator/validator_test.go b/beacon-chain/rpc/eth/validator/validator_test.go index f37997a574..69509f8b65 100644 --- a/beacon-chain/rpc/eth/validator/validator_test.go +++ b/beacon-chain/rpc/eth/validator/validator_test.go @@ -26,8 +26,8 @@ import ( mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" v1alpha1validator "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testutil" - beaconState "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + beaconState "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" @@ -59,9 +59,9 @@ func TestGetAttesterDuties(t *testing.T) { require.NoError(t, bs.SetSlot(5)) genesisRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") - var roots [fieldparams.BlockRootsLength][32]byte - roots[0] = genesisRoot - require.NoError(t, bs.SetBlockRoots(&roots)) + roots := make([][]byte, fieldparams.BlockRootsLength) + roots[0] = genesisRoot[:] + require.NoError(t, bs.SetBlockRoots(roots)) // Deactivate last validator. vals := bs.Validators() @@ -141,9 +141,9 @@ func TestGetAttesterDuties(t *testing.T) { require.NoError(t, bs.SetSlot(5)) genesisRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") - var roots [fieldparams.BlockRootsLength][32]byte - roots[0] = genesisRoot - require.NoError(t, bs.SetBlockRoots(&roots)) + roots := make([][]byte, fieldparams.BlockRootsLength) + roots[0] = genesisRoot[:] + require.NoError(t, bs.SetBlockRoots(roots)) pubKeys := make([][]byte, len(deposits)) indices := make([]uint64, len(deposits)) @@ -167,7 +167,7 @@ func TestGetAttesterDuties(t *testing.T) { } resp, err := vs.GetAttesterDuties(ctx, req) require.NoError(t, err) - assert.DeepEqual(t, bs.BlockRoots()[31], bytesutil.ToBytes32(resp.DependentRoot)) + assert.DeepEqual(t, bs.BlockRoots()[31], resp.DependentRoot) require.Equal(t, 1, len(resp.Data)) duty := resp.Data[0] assert.Equal(t, types.CommitteeIndex(1), duty.CommitteeIndex) @@ -236,9 +236,9 @@ func TestGetProposerDuties(t *testing.T) { require.NoError(t, bs.SetSlot(5)) genesisRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") - var roots [fieldparams.BlockRootsLength][32]byte - roots[0] = genesisRoot - require.NoError(t, bs.SetBlockRoots(&roots)) + roots := make([][]byte, fieldparams.BlockRootsLength) + roots[0] = genesisRoot[:] + require.NoError(t, bs.SetBlockRoots(roots)) pubKeys := make([][]byte, len(deposits)) for i := 0; i < len(deposits); i++ { @@ -285,9 +285,9 @@ func TestGetProposerDuties(t *testing.T) { require.NoError(t, bs.SetSlot(5)) genesisRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") - var roots [fieldparams.BlockRootsLength][32]byte - roots[0] = genesisRoot - require.NoError(t, bs.SetBlockRoots(&roots)) + roots := make([][]byte, fieldparams.BlockRootsLength) + roots[0] = genesisRoot[:] + require.NoError(t, bs.SetBlockRoots(roots)) pubKeys := make([][]byte, len(deposits)) indices := make([]uint64, len(deposits)) @@ -310,7 +310,7 @@ func TestGetProposerDuties(t *testing.T) { } resp, err := vs.GetProposerDuties(ctx, req) require.NoError(t, err) - assert.DeepEqual(t, bs.BlockRoots()[31], bytesutil.ToBytes32(resp.DependentRoot)) + assert.DeepEqual(t, bs.BlockRoots()[31], resp.DependentRoot) assert.Equal(t, 32, len(resp.Data)) // We expect a proposer duty for slot 74. var expectedDuty *ethpbv1.ProposerDuty @@ -899,9 +899,9 @@ func TestProduceAttestationData(t *testing.T) { require.NoError(t, err) blockRoots := beaconState.BlockRoots() - blockRoots[1] = blockRoot - blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot - blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot + blockRoots[1] = blockRoot[:] + blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:] + blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:] require.NoError(t, beaconState.SetBlockRoots(blockRoots)) chainService := &mockChain.ChainService{ Genesis: time.Now(), @@ -1117,9 +1117,9 @@ func TestSubmitBeaconCommitteeSubscription(t *testing.T) { require.NoError(t, bs.SetSlot(5)) genesisRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") - var roots [fieldparams.BlockRootsLength][32]byte - roots[0] = genesisRoot - require.NoError(t, bs.SetBlockRoots(&roots)) + roots := make([][]byte, fieldparams.BlockRootsLength) + roots[0] = genesisRoot[:] + require.NoError(t, bs.SetBlockRoots(roots)) pubKeys := make([][]byte, len(deposits)) for i := 0; i < len(deposits); i++ { @@ -1258,9 +1258,9 @@ func TestSubmitSyncCommitteeSubscription(t *testing.T) { require.NoError(t, err, "Could not set up genesis state") genesisRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") - var roots [fieldparams.BlockRootsLength][32]byte - roots[0] = genesisRoot - require.NoError(t, bs.SetBlockRoots(&roots)) + roots := make([][]byte, fieldparams.BlockRootsLength) + roots[0] = genesisRoot[:] + require.NoError(t, bs.SetBlockRoots(roots)) pubkeys := make([][]byte, len(deposits)) for i := 0; i < len(deposits); i++ { diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/beacon/BUILD.bazel index 7af5e047a2..9ed8f7446b 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/BUILD.bazel @@ -38,8 +38,8 @@ go_library( "//beacon-chain/operations/slashings:go_default_library", "//beacon-chain/p2p:go_default_library", "//beacon-chain/powchain:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//cmd:go_default_library", "//config/features:go_default_library", @@ -95,9 +95,9 @@ go_test( "//beacon-chain/operations/attestations:go_default_library", "//beacon-chain/operations/slashings:go_default_library", "//beacon-chain/p2p/testing:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library", "//cmd:go_default_library", "//cmd/beacon-chain/flags:go_default_library", diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/assignments_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/assignments_test.go index c0bd7fccbe..4f88fcd28b 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/assignments_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/assignments_test.go @@ -11,7 +11,7 @@ import ( mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/cmd" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go index d93efce2cf..dfb4c7f167 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go @@ -18,8 +18,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/cmd" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" @@ -642,8 +642,11 @@ func TestServer_ListIndexedAttestations_OldEpoch(t *testing.T) { numValidators := uint64(128) state, _ := util.DeterministicGenesisState(t, numValidators) - var mixes [fieldparams.RandaoMixesLength][fieldparams.RootLength]byte - require.NoError(t, state.SetRandaoMixes(&mixes)) + randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(randaoMixes); i++ { + randaoMixes[i] = make([]byte, fieldparams.RootLength) + } + require.NoError(t, state.SetRandaoMixes(randaoMixes)) require.NoError(t, state.SetSlot(startSlot)) // Next up we convert the test attestations to indexed form: @@ -907,8 +910,7 @@ func TestServer_StreamIndexedAttestations_OK(t *testing.T) { }, }, } - gvr := headState.GenesisValidatorRoot() - domain, err := signing.Domain(headState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(headState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, headState.GenesisValidatorRoot()) require.NoError(t, err) encoded, err := signing.ComputeSigningRoot(attExample.Data, domain) require.NoError(t, err) diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go index 4322929a3a..d6c09e9ef0 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go @@ -14,8 +14,8 @@ import ( statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/cmd" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/committees_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/committees_test.go index a35264705f..2eeadb744e 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/committees_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/committees_test.go @@ -9,8 +9,8 @@ import ( mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -80,8 +80,11 @@ func TestServer_ListBeaconCommittees_PreviousEpoch(t *testing.T) { numValidators := 128 headState := setupActiveValidators(t, numValidators) - var mixes [fieldparams.RandaoMixesLength][fieldparams.RootLength]byte - require.NoError(t, headState.SetRandaoMixes(&mixes)) + randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(randaoMixes); i++ { + randaoMixes[i] = make([]byte, fieldparams.RootLength) + } + require.NoError(t, headState.SetRandaoMixes(randaoMixes)) require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) b := util.NewBeaconBlock() diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go index c7aaa4b722..647662d1a2 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go @@ -17,7 +17,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/beacon-chain/sync" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators.go index 9eb6de56c8..2547ecb25c 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators.go @@ -13,7 +13,7 @@ import ( coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/cmd" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go index 6d82cdd07c..01a0a228eb 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go @@ -23,7 +23,7 @@ import ( coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_test.go index 0e1b85e39a..1c762caf38 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_test.go @@ -17,9 +17,9 @@ import ( coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/db" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/cmd" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" @@ -2166,7 +2166,7 @@ func TestServer_GetIndividualVotes_Working(t *testing.T) { att1.Data.BeaconBlockRoot = rt[:] br := beaconState.BlockRoots() newRt := [32]byte{'B'} - br[0] = newRt + br[0] = newRt[:] require.NoError(t, beaconState.SetBlockRoots(br)) att2.Data.Target.Root = rt[:] att2.Data.BeaconBlockRoot = newRt[:] diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel index 1e767aaa83..7fe789e02d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel @@ -17,8 +17,8 @@ go_library( "//beacon-chain/db:go_default_library", "//beacon-chain/db/filters:go_default_library", "//beacon-chain/p2p:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", @@ -50,7 +50,7 @@ go_test( "//beacon-chain/db/testing:go_default_library", "//beacon-chain/forkchoice/protoarray:go_default_library", "//beacon-chain/p2p/testing:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/block.go b/beacon-chain/rpc/prysm/v1alpha1/debug/block.go index 504e6dc1c1..e0bf8b2592 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/block.go +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/block.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/db/filters" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" pbrpc "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/block_test.go b/beacon-chain/rpc/prysm/v1alpha1/debug/block_test.go index 8fecfba23e..5681328c97 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/block_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/block_test.go @@ -9,7 +9,7 @@ import ( mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/server.go b/beacon-chain/rpc/prysm/v1alpha1/debug/server.go index b1d06685f6..f19b92be5c 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/server.go @@ -13,7 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" pbrpc "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go b/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go index 08a28b0976..3572e35dc9 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" pbrpc "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 5345aff754..a1c74ddff7 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -45,8 +45,8 @@ go_library( "//beacon-chain/operations/voluntaryexits:go_default_library", "//beacon-chain/p2p:go_default_library", "//beacon-chain/powchain:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", @@ -123,9 +123,9 @@ go_test( "//beacon-chain/operations/voluntaryexits:go_default_library", "//beacon-chain/p2p/testing:go_default_library", "//beacon-chain/powchain/testing:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go index 18be04189f..2397ac001d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator_test.go @@ -12,8 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/assignments.go b/beacon-chain/rpc/prysm/v1alpha1/validator/assignments.go index df091e52f9..c1710c6ea5 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/assignments.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/assignments.go @@ -12,7 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - beaconState "github.com/prysmaticlabs/prysm/beacon-chain/state" + beaconState "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/rand" diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go index 8a6207955c..9407ebc9a1 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go @@ -13,8 +13,8 @@ import ( dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -112,9 +112,9 @@ func TestGetAttestationData_OK(t *testing.T) { require.NoError(t, err) blockRoots := beaconState.BlockRoots() - blockRoots[1] = blockRoot - blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot - blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot + blockRoots[1] = blockRoot[:] + blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:] + blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:] require.NoError(t, beaconState.SetBlockRoots(blockRoots)) chainService := &mock.ChainService{ Genesis: time.Now(), @@ -212,9 +212,9 @@ func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) { }) require.NoError(t, err) blockRoots := beaconState.BlockRoots() - blockRoots[1] = blockRoot - blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = epochBoundaryRoot - blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedBlockRoot + blockRoots[1] = blockRoot[:] + blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = epochBoundaryRoot[:] + blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedBlockRoot[:] require.NoError(t, beaconState.SetBlockRoots(blockRoots)) chainService := &mock.ChainService{ Genesis: time.Now(), @@ -369,10 +369,10 @@ func TestServer_GetAttestationData_HeadStateSlotGreaterThanRequestSlot(t *testin }) require.NoError(t, err) blockRoots := beaconState.BlockRoots() - blockRoots[1] = blockRoot - blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot - blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot - blockRoots[3*params.BeaconConfig().SlotsPerEpoch] = blockRoot2 + blockRoots[1] = blockRoot[:] + blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:] + blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:] + blockRoots[3*params.BeaconConfig().SlotsPerEpoch] = blockRoot2[:] require.NoError(t, beaconState.SetBlockRoots(blockRoots)) beaconstate := beaconState.Copy() @@ -445,9 +445,9 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) { }) require.NoError(t, err) blockRoots := beaconState.BlockRoots() - blockRoots[1] = blockRoot - blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot - blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot + blockRoots[1] = blockRoot[:] + blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:] + blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:] require.NoError(t, beaconState.SetBlockRoots(blockRoots)) chainService := &mock.ChainService{ Genesis: time.Now(), diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/exit.go b/beacon-chain/rpc/prysm/v1alpha1/validator/exit.go index eefe62ec07..978390097f 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/exit.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/exit.go @@ -34,8 +34,7 @@ func (vs *Server) ProposeExit(ctx context.Context, req *ethpb.SignedVoluntaryExi return nil, status.Error(codes.InvalidArgument, "validator index exceeds validator set length") } - gvRoot := s.GenesisValidatorRoot() - if err := blocks.VerifyExitAndSignature(val, s.Slot(), s.Fork(), req, gvRoot[:]); err != nil { + if err := blocks.VerifyExitAndSignature(val, s.Slot(), s.Fork(), req, s.GenesisValidatorRoot()); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go index fcb4b023ca..1042c441ef 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go index 34938ac630..5247fbea9f 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go @@ -6,7 +6,7 @@ import ( "math/big" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go index 9adab9391d..fbea1deb28 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/hash" diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go index 166ceb5d3d..f9ad98d022 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go @@ -152,8 +152,7 @@ func (vs *Server) buildPhase0BlockData(ctx context.Context, req *ethpb.BlockRequ log.WithError(err).Warn("Proposer: invalid exit") continue } - gvRoot := head.GenesisValidatorRoot() - if err := blocks.VerifyExitAndSignature(val, head.Slot(), head.Fork(), exit, gvRoot[:]); err != nil { + if err := blocks.VerifyExitAndSignature(val, head.Slot(), head.Fork(), exit, head.GenesisValidatorRoot()); err != nil { log.WithError(err).Warn("Proposer: invalid exit") continue } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index a42f575c05..32e79eb0af 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -20,9 +20,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" @@ -1790,7 +1790,7 @@ func TestProposer_FilterAttestation(t *testing.T) { numValidators := uint64(64) state, privKeys := util.DeterministicGenesisState(t, numValidators) - require.NoError(t, state.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash)) + require.NoError(t, state.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:])) assert.NoError(t, state.SetSlot(1)) genesisRoot, err := genesis.Block.HashTreeRoot() diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go index a103a9ba0c..465d42150e 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go @@ -22,7 +22,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/beacon-chain/sync" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -162,11 +162,10 @@ func (vs *Server) WaitForChainStart(_ *emptypb.Empty, stream ethpb.BeaconNodeVal return status.Errorf(codes.Internal, "Could not retrieve head state: %v", err) } if head != nil && !head.IsNil() { - genesisValidatorRoot := head.GenesisValidatorRoot() res := ðpb.ChainStartResponse{ Started: true, GenesisTime: head.GenesisTime(), - GenesisValidatorsRoot: genesisValidatorRoot[:], + GenesisValidatorsRoot: head.GenesisValidatorRoot(), } return stream.Send(res) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/server_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/server_test.go index c027c69a37..d32e8d02be 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/server_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/server_test.go @@ -14,7 +14,7 @@ import ( statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -300,7 +300,7 @@ func TestWaitForChainStart_AlreadyStarted(t *testing.T) { require.NoError(t, err) require.NoError(t, st.SetSlot(3)) genesisValidatorsRoot := bytesutil.ToBytes32([]byte("validators")) - require.NoError(t, st.SetGenesisValidatorRoot(genesisValidatorsRoot)) + require.NoError(t, st.SetGenesisValidatorRoot(genesisValidatorsRoot[:])) chainService := &mockChain.ChainService{State: st, ValidatorsRoot: genesisValidatorsRoot} Server := &Server{ diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/status.go b/beacon-chain/rpc/prysm/v1alpha1/validator/status.go index 4414bd2a65..05101316b4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/status.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/status.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/contracts/deposit" diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go index 945934aa6e..2df65a1f65 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go @@ -13,9 +13,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/rpc/service.go b/beacon-chain/rpc/service.go index a36b4e4307..57eabc1b3c 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -37,7 +37,7 @@ import ( validatorv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator" "github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher" slasherservice "github.com/prysmaticlabs/prysm/beacon-chain/slasher" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" chainSync "github.com/prysmaticlabs/prysm/beacon-chain/sync" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/rpc/statefetcher/BUILD.bazel b/beacon-chain/rpc/statefetcher/BUILD.bazel index 2d941f187a..7ac89acb95 100644 --- a/beacon-chain/rpc/statefetcher/BUILD.bazel +++ b/beacon-chain/rpc/statefetcher/BUILD.bazel @@ -9,8 +9,8 @@ go_library( "//beacon-chain/blockchain:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/db:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//encoding/bytesutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", @@ -24,8 +24,7 @@ go_test( deps = [ "//beacon-chain/blockchain/testing:go_default_library", "//beacon-chain/db/testing:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/rpc/statefetcher/fetcher.go b/beacon-chain/rpc/statefetcher/fetcher.go index 8db34c37e8..b5baf2d602 100644 --- a/beacon-chain/rpc/statefetcher/fetcher.go +++ b/beacon-chain/rpc/statefetcher/fetcher.go @@ -12,8 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/db" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) @@ -177,9 +177,9 @@ func (p *StateProvider) stateByHex(ctx context.Context, stateId []byte) (state.B return nil, errors.Wrap(err, "could not get head state") } for i, root := range headState.StateRoots() { - if bytes.Equal(root[:], stateId) { + if bytes.Equal(root, stateId) { blockRoot := headState.BlockRoots()[i] - return p.StateGenService.StateByRoot(ctx, blockRoot) + return p.StateGenService.StateByRoot(ctx, bytesutil.ToBytes32(blockRoot)) } } @@ -259,7 +259,7 @@ func (p *StateProvider) stateRootByHex(ctx context.Context, stateId []byte) ([]b return nil, errors.Wrap(err, "could not get head state") } for _, root := range headState.StateRoots() { - if root == stateRoot { + if bytes.Equal(root, stateRoot[:]) { return stateRoot[:], nil } } diff --git a/beacon-chain/rpc/statefetcher/fetcher_test.go b/beacon-chain/rpc/statefetcher/fetcher_test.go index 50ca1f2d20..9512dd1350 100644 --- a/beacon-chain/rpc/statefetcher/fetcher_test.go +++ b/beacon-chain/rpc/statefetcher/fetcher_test.go @@ -11,8 +11,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -26,8 +25,8 @@ func TestGetState(t *testing.T) { ctx := context.Background() headSlot := types.Slot(123) - fillSlot := func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetSlot(headSlot)) + fillSlot := func(state *ethpb.BeaconState) error { + state.Slot = headSlot return nil } newBeaconState, err := util.NewBeaconState(util.FillRootsNaturalOpt, fillSlot) @@ -60,10 +59,8 @@ func TestGetState(t *testing.T) { r, err := b.Block.HashTreeRoot() require.NoError(t, err) - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - bRoots := beaconState.BlockRoots() - bRoots[0] = r - require.NoError(t, beaconState.SetBlockRoots(bRoots)) + bs, err := util.NewBeaconState(func(state *ethpb.BeaconState) error { + state.BlockRoots[0] = r[:] return nil }) require.NoError(t, err) @@ -190,8 +187,8 @@ func TestGetStateRoot(t *testing.T) { ctx := context.Background() headSlot := types.Slot(123) - fillSlot := func(beaconState state.BeaconState) error { - require.NoError(t, beaconState.SetSlot(headSlot)) + fillSlot := func(state *ethpb.BeaconState) error { + state.Slot = headSlot return nil } newBeaconState, err := util.NewBeaconState(util.FillRootsNaturalOpt, fillSlot) @@ -221,10 +218,8 @@ func TestGetStateRoot(t *testing.T) { r, err := b.Block.HashTreeRoot() require.NoError(t, err) - bs, err := util.NewBeaconState(func(beaconState state.BeaconState) error { - bRoots := beaconState.BlockRoots() - bRoots[0] = r - require.NoError(t, beaconState.SetBlockRoots(bRoots)) + bs, err := util.NewBeaconState(func(state *ethpb.BeaconState) error { + state.BlockRoots[0] = r[:] return nil }) require.NoError(t, err) diff --git a/beacon-chain/rpc/testutil/BUILD.bazel b/beacon-chain/rpc/testutil/BUILD.bazel index 4714040101..8b0d6b3bef 100644 --- a/beacon-chain/rpc/testutil/BUILD.bazel +++ b/beacon-chain/rpc/testutil/BUILD.bazel @@ -10,7 +10,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testutil", visibility = ["//beacon-chain:__subpackages__"], deps = [ - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", ], diff --git a/beacon-chain/rpc/testutil/mock_state_fetcher.go b/beacon-chain/rpc/testutil/mock_state_fetcher.go index 302f9b0730..6b62182ee4 100644 --- a/beacon-chain/rpc/testutil/mock_state_fetcher.go +++ b/beacon-chain/rpc/testutil/mock_state_fetcher.go @@ -3,7 +3,7 @@ package testutil import ( "context" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ) // MockFetcher is a fake implementation of statefetcher.Fetcher. diff --git a/beacon-chain/sharedstate/BUILD.bazel b/beacon-chain/sharedstate/BUILD.bazel new file mode 100644 index 0000000000..64ecfb6758 --- /dev/null +++ b/beacon-chain/sharedstate/BUILD.bazel @@ -0,0 +1,12 @@ +load("@prysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["prometheus.go"], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/sharedstate", + visibility = ["//visibility:public"], + deps = [ + "@com_github_prometheus_client_golang//prometheus:go_default_library", + "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", + ], +) diff --git a/beacon-chain/sharedstate/prometheus.go b/beacon-chain/sharedstate/prometheus.go new file mode 100644 index 0000000000..c10633db1b --- /dev/null +++ b/beacon-chain/sharedstate/prometheus.go @@ -0,0 +1,13 @@ +package sharedstate + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +var ( + StateCount = promauto.NewGauge(prometheus.GaugeOpts{ + Name: "beacon_state_count", + Help: "Count the number of active beacon state objects.", + }) +) diff --git a/beacon-chain/slasher/BUILD.bazel b/beacon-chain/slasher/BUILD.bazel index 9a76fddf02..c00f841c84 100644 --- a/beacon-chain/slasher/BUILD.bazel +++ b/beacon-chain/slasher/BUILD.bazel @@ -32,8 +32,8 @@ go_library( "//beacon-chain/db:go_default_library", "//beacon-chain/operations/slashings:go_default_library", "//beacon-chain/slasher/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -77,7 +77,7 @@ go_test( "//beacon-chain/db/testing:go_default_library", "//beacon-chain/operations/slashings:go_default_library", "//beacon-chain/slasher/types:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", diff --git a/beacon-chain/slasher/detect_attestations_test.go b/beacon-chain/slasher/detect_attestations_test.go index a6d0cc23a0..3f76fa930b 100644 --- a/beacon-chain/slasher/detect_attestations_test.go +++ b/beacon-chain/slasher/detect_attestations_test.go @@ -211,12 +211,11 @@ func Test_processQueuedAttestations(t *testing.T) { } err = beaconState.SetValidators(validators) require.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, - gvr[:], + beaconState.GenesisValidatorRoot(), ) require.NoError(t, err) diff --git a/beacon-chain/slasher/detect_blocks_test.go b/beacon-chain/slasher/detect_blocks_test.go index e9b14625a4..71a3576e5d 100644 --- a/beacon-chain/slasher/detect_blocks_test.go +++ b/beacon-chain/slasher/detect_blocks_test.go @@ -10,7 +10,7 @@ import ( dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" slashertypes "github.com/prysmaticlabs/prysm/beacon-chain/slasher/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -44,12 +44,11 @@ func Test_processQueuedBlocks_DetectsDoubleProposals(t *testing.T) { } err = beaconState.SetValidators(validators) require.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, - gvr[:], + beaconState.GenesisValidatorRoot(), ) require.NoError(t, err) diff --git a/beacon-chain/slasher/process_slashings.go b/beacon-chain/slasher/process_slashings.go index 8e8c6d1f2e..7eb344eaa9 100644 --- a/beacon-chain/slasher/process_slashings.go +++ b/beacon-chain/slasher/process_slashings.go @@ -4,7 +4,7 @@ import ( "context" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/slasher/process_slashings_test.go b/beacon-chain/slasher/process_slashings_test.go index e9bf64c2e8..906f11c4a9 100644 --- a/beacon-chain/slasher/process_slashings_test.go +++ b/beacon-chain/slasher/process_slashings_test.go @@ -8,7 +8,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -57,12 +57,11 @@ func TestService_processAttesterSlashings(t *testing.T) { AttestingIndices: []uint64{0}, }) - gvr := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, - gvr[:], + beaconState.GenesisValidatorRoot(), ) require.NoError(t, err) signingRoot, err := signing.ComputeSigningRoot(firstAtt.Data, domain) @@ -177,12 +176,11 @@ func TestService_processProposerSlashings(t *testing.T) { }, }) - gvr := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, - gvr[:], + beaconState.GenesisValidatorRoot(), ) require.NoError(t, err) htr, err := firstBlockHeader.Header.HashTreeRoot() diff --git a/beacon-chain/slasher/service.go b/beacon-chain/slasher/service.go index 4c01ea5c18..fa24f3fcf4 100644 --- a/beacon-chain/slasher/service.go +++ b/beacon-chain/slasher/service.go @@ -15,7 +15,7 @@ import ( statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/beacon-chain/sync" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state/BUILD.bazel b/beacon-chain/state-native/BUILD.bazel similarity index 98% rename from beacon-chain/state/BUILD.bazel rename to beacon-chain/state-native/BUILD.bazel index 9edc6abda7..d0a2e1b972 100644 --- a/beacon-chain/state/BUILD.bazel +++ b/beacon-chain/state-native/BUILD.bazel @@ -6,7 +6,7 @@ go_library( "altair.go", "phase0.go", ], - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native", visibility = [ "//beacon-chain:__subpackages__", "//contracts/deposit:__subpackages__", diff --git a/beacon-chain/state/altair.go b/beacon-chain/state-native/altair.go similarity index 100% rename from beacon-chain/state/altair.go rename to beacon-chain/state-native/altair.go diff --git a/beacon-chain/state/custom-types/BUILD.bazel b/beacon-chain/state-native/custom-types/BUILD.bazel similarity index 95% rename from beacon-chain/state/custom-types/BUILD.bazel rename to beacon-chain/state-native/custom-types/BUILD.bazel index 9722dcccca..5350681bdb 100644 --- a/beacon-chain/state/custom-types/BUILD.bazel +++ b/beacon-chain/state-native/custom-types/BUILD.bazel @@ -3,7 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = ["state_arrays.go"], - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types", visibility = ["//visibility:public"], deps = [ "//config/fieldparams:go_default_library", diff --git a/beacon-chain/state/custom-types/state_arrays.go b/beacon-chain/state-native/custom-types/state_arrays.go similarity index 100% rename from beacon-chain/state/custom-types/state_arrays.go rename to beacon-chain/state-native/custom-types/state_arrays.go diff --git a/beacon-chain/state/custom-types/state_arrays_test.go b/beacon-chain/state-native/custom-types/state_arrays_test.go similarity index 100% rename from beacon-chain/state/custom-types/state_arrays_test.go rename to beacon-chain/state-native/custom-types/state_arrays_test.go diff --git a/beacon-chain/state/fieldtrie/BUILD.bazel b/beacon-chain/state-native/fieldtrie/BUILD.bazel similarity index 74% rename from beacon-chain/state/fieldtrie/BUILD.bazel rename to beacon-chain/state-native/fieldtrie/BUILD.bazel index ce4538745d..e2e8b1533d 100644 --- a/beacon-chain/state/fieldtrie/BUILD.bazel +++ b/beacon-chain/state-native/fieldtrie/BUILD.bazel @@ -6,12 +6,11 @@ go_library( "field_trie.go", "field_trie_helpers.go", ], - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie", visibility = ["//beacon-chain:__subpackages__"], deps = [ - "//beacon-chain/state/custom-types:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", @@ -29,9 +28,8 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//beacon-chain/state/custom-types:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/state/fieldtrie/field_trie.go b/beacon-chain/state-native/fieldtrie/field_trie.go similarity index 97% rename from beacon-chain/state/fieldtrie/field_trie.go rename to beacon-chain/state-native/fieldtrie/field_trie.go index 7e60feb04b..55083bd680 100644 --- a/beacon-chain/state/fieldtrie/field_trie.go +++ b/beacon-chain/state-native/fieldtrie/field_trie.go @@ -5,8 +5,8 @@ import ( "sync" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" ) // FieldTrie is the representation of the representative diff --git a/beacon-chain/state/fieldtrie/field_trie_helpers.go b/beacon-chain/state-native/fieldtrie/field_trie_helpers.go similarity index 88% rename from beacon-chain/state/fieldtrie/field_trie_helpers.go rename to beacon-chain/state-native/fieldtrie/field_trie_helpers.go index e8cc378358..5f3a3fce68 100644 --- a/beacon-chain/state/fieldtrie/field_trie_helpers.go +++ b/beacon-chain/state-native/fieldtrie/field_trie_helpers.go @@ -6,9 +6,8 @@ import ( "reflect" "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/encoding/ssz" @@ -66,42 +65,13 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements // fieldConverters converts the corresponding field and the provided elements to the appropriate roots. func fieldConverters(field types.FieldIndex, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { switch field { - case types.BlockRoots: - val, ok := elements.(*customtypes.BlockRoots) + case types.BlockRoots, types.StateRoots, types.RandaoMixes: + val, ok := elements.([][]byte) if !ok { return nil, errors.Errorf("Wanted type of %v but got %v", reflect.TypeOf([][]byte{}).Name(), reflect.TypeOf(elements).Name()) } - roots := make([][]byte, len(val)) - for i, r := range val { - tmp := r - roots[i] = tmp[:] - } - return handleByteArrays(roots, indices, convertAll) - case types.StateRoots: - val, ok := elements.(*customtypes.StateRoots) - if !ok { - return nil, errors.Errorf("Wanted type of %v but got %v", - reflect.TypeOf([][]byte{}).Name(), reflect.TypeOf(elements).Name()) - } - roots := make([][]byte, len(val)) - for i, r := range val { - tmp := r - roots[i] = tmp[:] - } - return handleByteArrays(roots, indices, convertAll) - case types.RandaoMixes: - val, ok := elements.(*customtypes.RandaoMixes) - if !ok { - return nil, errors.Errorf("Wanted type of %v but got %v", - reflect.TypeOf([][]byte{}).Name(), reflect.TypeOf(elements).Name()) - } - mixes := make([][]byte, len(val)) - for i, m := range val { - tmp := m - mixes[i] = tmp[:] - } - return handleByteArrays(mixes, indices, convertAll) + return handleByteArrays(val, indices, convertAll) case types.Eth1DataVotes: val, ok := elements.([]*ethpb.Eth1Data) if !ok { diff --git a/beacon-chain/state/fieldtrie/field_trie_test.go b/beacon-chain/state-native/fieldtrie/field_trie_test.go similarity index 67% rename from beacon-chain/state/fieldtrie/field_trie_test.go rename to beacon-chain/state-native/fieldtrie/field_trie_test.go index d13041054b..8440deb1f4 100644 --- a/beacon-chain/state/fieldtrie/field_trie_test.go +++ b/beacon-chain/state-native/fieldtrie/field_trie_test.go @@ -4,10 +4,9 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" @@ -19,20 +18,9 @@ func TestFieldTrie_NewTrie(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 40) // 5 represents the enum value of state roots - sRoots := customtypes.BlockRoots(*newState.StateRoots()) - trie, err := fieldtrie.NewFieldTrie(5, stateTypes.BasicArray, &sRoots, uint64(params.BeaconConfig().SlotsPerHistoricalRoot)) + trie, err := fieldtrie.NewFieldTrie(5, stateTypes.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot)) require.NoError(t, err) - sRootsSlice := make([][]byte, len(newState.StateRoots())) - for i, r := range newState.StateRoots() { - tmp := r - sRootsSlice[i] = tmp[:] - } - sR := make([][]byte, len(newState.StateRoots())) - for i, r := range newState.StateRoots() { - tmp := r - sR[i] = tmp[:] - } - root, err := stateutil.RootsArrayHashTreeRoot(sR, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "StateRoots") + root, err := stateutil.RootsArrayHashTreeRoot(newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "StateRoots") require.NoError(t, err) newRoot, err := trie.TrieRoot() require.NoError(t, err) @@ -70,8 +58,7 @@ func TestFieldTrie_RecomputeTrie(t *testing.T) { func TestFieldTrie_CopyTrieImmutable(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 32) // 12 represents the enum value of randao mixes. - mixes := customtypes.RandaoMixes(*newState.RandaoMixes()) - trie, err := fieldtrie.NewFieldTrie(13, stateTypes.BasicArray, &mixes, uint64(params.BeaconConfig().EpochsPerHistoricalVector)) + trie, err := fieldtrie.NewFieldTrie(13, stateTypes.BasicArray, newState.RandaoMixes(), uint64(params.BeaconConfig().EpochsPerHistoricalVector)) require.NoError(t, err) newTrie := trie.CopyTrie() @@ -79,11 +66,10 @@ func TestFieldTrie_CopyTrieImmutable(t *testing.T) { changedIdx := []uint64{2, 29} changedVals := [][32]byte{{'A', 'B'}, {'C', 'D'}} - require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[0], changedVals[0])) - require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[1], changedVals[1])) + require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[0], changedVals[0][:])) + require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[1], changedVals[1][:])) - mixes = customtypes.RandaoMixes(*newState.RandaoMixes()) - root, err := trie.RecomputeTrie(changedIdx, &mixes) + root, err := trie.RecomputeTrie(changedIdx, newState.RandaoMixes()) require.NoError(t, err) newRoot, err := newTrie.TrieRoot() require.NoError(t, err) diff --git a/beacon-chain/state-native/fieldtrie/helpers_test.go b/beacon-chain/state-native/fieldtrie/helpers_test.go new file mode 100644 index 0000000000..3024acdfd0 --- /dev/null +++ b/beacon-chain/state-native/fieldtrie/helpers_test.go @@ -0,0 +1,85 @@ +package fieldtrie + +import ( + "encoding/binary" + "sync" + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" +) + +func Test_handlePendingAttestation_OutOfRange(t *testing.T) { + items := make([]*ethpb.PendingAttestation, 1) + indices := []uint64{3} + _, err := handlePendingAttestation(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) + + 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]) + + 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) + + 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})) + +} diff --git a/beacon-chain/state-native/genesis/BUILD.bazel b/beacon-chain/state-native/genesis/BUILD.bazel new file mode 100644 index 0000000000..8e9c939c2e --- /dev/null +++ b/beacon-chain/state-native/genesis/BUILD.bazel @@ -0,0 +1,24 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["genesis.go"], + embedsrcs = ["mainnet.ssz.snappy"], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/genesis", + visibility = ["//beacon-chain/db:__subpackages__"], + deps = [ + "//beacon-chain/state-native/v1:go_default_library", + "//config/params:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "@com_github_golang_snappy//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["genesis_test.go"], + deps = [ + ":go_default_library", + "//config/params:go_default_library", + ], +) diff --git a/beacon-chain/state-native/genesis/genesis.go b/beacon-chain/state-native/genesis/genesis.go new file mode 100644 index 0000000000..d6f480e73a --- /dev/null +++ b/beacon-chain/state-native/genesis/genesis.go @@ -0,0 +1,39 @@ +package genesis + +import ( + _ "embed" + + "github.com/golang/snappy" + state "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +var ( + //go:embed mainnet.ssz.snappy + mainnetRawSSZCompressed []byte // 1.8Mb +) + +// State returns a copy of the genesis state from a hardcoded value. +func State(name string) (*state.BeaconState, error) { + switch name { + case params.ConfigNames[params.Mainnet]: + return load(mainnetRawSSZCompressed) + default: + // No state found. + return nil, nil + } +} + +// load a compressed ssz state file into a beacon state struct. +func load(b []byte) (*state.BeaconState, error) { + st := ðpb.BeaconState{} + b, err := snappy.Decode(nil /*dst*/, b) + if err != nil { + return nil, err + } + if err := st.UnmarshalSSZ(b); err != nil { + return nil, err + } + return state.InitializeFromProtoUnsafe(st) +} diff --git a/beacon-chain/state-native/genesis/genesis_test.go b/beacon-chain/state-native/genesis/genesis_test.go new file mode 100644 index 0000000000..5302758dad --- /dev/null +++ b/beacon-chain/state-native/genesis/genesis_test.go @@ -0,0 +1,32 @@ +package genesis_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/genesis" + "github.com/prysmaticlabs/prysm/config/params" +) + +func TestGenesisState(t *testing.T) { + tests := []struct { + name params.ConfigName + }{ + { + name: params.Mainnet, + }, + } + for _, tt := range tests { + t.Run(params.ConfigNames[tt.name], func(t *testing.T) { + st, err := genesis.State(params.ConfigNames[tt.name]) + if err != nil { + t.Fatal(err) + } + if st == nil { + t.Fatal("nil state") + } + if st.NumValidators() <= 0 { + t.Error("No validators present in state") + } + }) + } +} diff --git a/beacon-chain/state/genesis/mainnet.ssz.snappy b/beacon-chain/state-native/genesis/mainnet.ssz.snappy similarity index 100% rename from beacon-chain/state/genesis/mainnet.ssz.snappy rename to beacon-chain/state-native/genesis/mainnet.ssz.snappy diff --git a/beacon-chain/state/phase0.go b/beacon-chain/state-native/phase0.go similarity index 90% rename from beacon-chain/state/phase0.go rename to beacon-chain/state-native/phase0.go index ff789cd3c2..e14fd1691c 100644 --- a/beacon-chain/state/phase0.go +++ b/beacon-chain/state-native/phase0.go @@ -39,14 +39,14 @@ type ReadOnlyBeaconState interface { ReadOnlyBalances ReadOnlyCheckpoint ReadOnlyAttestations - ToProtoUnsafe() interface{} - ToProto() interface{} + InnerStateUnsafe() interface{} + CloneInnerState() interface{} GenesisTime() uint64 - GenesisValidatorRoot() [32]byte + GenesisValidatorRoot() []byte Slot() types.Slot Fork() *ethpb.Fork LatestBlockHeader() *ethpb.BeaconBlockHeader - HistoricalRoots() [][32]byte + HistoricalRoots() [][]byte Slashings() []uint64 FieldReferencesCount() map[string]uint64 MarshalSSZ() ([]byte, error) @@ -66,11 +66,11 @@ type WriteOnlyBeaconState interface { WriteOnlyCheckpoint WriteOnlyAttestations SetGenesisTime(val uint64) error - SetGenesisValidatorRoot(val [32]byte) error + SetGenesisValidatorRoot(val []byte) error SetSlot(val types.Slot) error SetFork(val *ethpb.Fork) error SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error - SetHistoricalRoots(val [][32]byte) error + SetHistoricalRoots(val [][]byte) error SetSlashings(val []uint64) error UpdateSlashingsAtIndex(idx, val uint64) error AppendHistoricalRoots(root [32]byte) error @@ -121,20 +121,20 @@ type ReadOnlyCheckpoint interface { // ReadOnlyBlockRoots defines a struct which only has read access to block roots methods. type ReadOnlyBlockRoots interface { - BlockRoots() *[fieldparams.BlockRootsLength][32]byte - BlockRootAtIndex(idx uint64) ([32]byte, error) + BlockRoots() [][]byte + BlockRootAtIndex(idx uint64) ([]byte, error) } // ReadOnlyStateRoots defines a struct which only has read access to state roots methods. type ReadOnlyStateRoots interface { - StateRoots() *[fieldparams.StateRootsLength][32]byte - StateRootAtIndex(idx uint64) ([32]byte, error) + StateRoots() [][]byte + StateRootAtIndex(idx uint64) ([]byte, error) } // ReadOnlyRandaoMixes defines a struct which only has read access to randao mixes methods. type ReadOnlyRandaoMixes interface { - RandaoMixes() *[fieldparams.RandaoMixesLength][32]byte - RandaoMixAtIndex(idx uint64) ([32]byte, error) + RandaoMixes() [][]byte + RandaoMixAtIndex(idx uint64) ([]byte, error) RandaoMixesLength() int } @@ -153,13 +153,13 @@ type ReadOnlyAttestations interface { // WriteOnlyBlockRoots defines a struct which only has write access to block roots methods. type WriteOnlyBlockRoots interface { - SetBlockRoots(val *[fieldparams.BlockRootsLength][32]byte) error + SetBlockRoots(val [][]byte) error UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error } // WriteOnlyStateRoots defines a struct which only has write access to state roots methods. type WriteOnlyStateRoots interface { - SetStateRoots(val *[fieldparams.StateRootsLength][32]byte) error + SetStateRoots(val [][]byte) error UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error } @@ -188,8 +188,8 @@ type WriteOnlyBalances interface { // WriteOnlyRandaoMixes defines a struct which only has write access to randao mixes methods. type WriteOnlyRandaoMixes interface { - SetRandaoMixes(val *[fieldparams.RandaoMixesLength][32]byte) error - UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error + SetRandaoMixes(val [][]byte) error + UpdateRandaoMixesAtIndex(idx uint64, val []byte) error } // WriteOnlyCheckpoint defines a struct which only has write access to check point methods. diff --git a/beacon-chain/state-native/stategen/BUILD.bazel b/beacon-chain/state-native/stategen/BUILD.bazel new file mode 100644 index 0000000000..2e60754aaa --- /dev/null +++ b/beacon-chain/state-native/stategen/BUILD.bazel @@ -0,0 +1,83 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "epoch_boundary_state_cache.go", + "errors.go", + "getter.go", + "hot_state_cache.go", + "log.go", + "metrics.go", + "migrate.go", + "mock.go", + "replay.go", + "service.go", + "setter.go", + ], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stategen", + visibility = [ + "//beacon-chain:__subpackages__", + "//testing/endtoend:__subpackages__", + "//testing/fuzz:__pkg__", + "//testing/slasher/simulator:__pkg__", + ], + deps = [ + "//beacon-chain/core/altair:go_default_library", + "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/core/time:go_default_library", + "//beacon-chain/core/transition:go_default_library", + "//beacon-chain/db:go_default_library", + "//beacon-chain/db/filters:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//cache/lru:go_default_library", + "//config/params:go_default_library", + "//encoding/bytesutil:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/block:go_default_library", + "//runtime/version:go_default_library", + "//time/slots:go_default_library", + "@com_github_hashicorp_golang_lru//:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_prometheus_client_golang//prometheus:go_default_library", + "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@io_k8s_client_go//tools/cache:go_default_library", + "@io_opencensus_go//trace:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "epoch_boundary_state_cache_test.go", + "getter_test.go", + "hot_state_cache_test.go", + "init_test.go", + "migrate_test.go", + "replay_test.go", + "service_test.go", + "setter_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/db:go_default_library", + "//beacon-chain/db/testing:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-native/v1:go_default_library", + "//config/params:go_default_library", + "//encoding/bytesutil:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/block:go_default_library", + "//proto/prysm/v1alpha1/wrapper:go_default_library", + "//runtime/version:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + ], +) diff --git a/beacon-chain/state/stategen/epoch_boundary_state_cache.go b/beacon-chain/state-native/stategen/epoch_boundary_state_cache.go similarity index 98% rename from beacon-chain/state/stategen/epoch_boundary_state_cache.go rename to beacon-chain/state-native/stategen/epoch_boundary_state_cache.go index c938859fd9..8d198090d5 100644 --- a/beacon-chain/state/stategen/epoch_boundary_state_cache.go +++ b/beacon-chain/state-native/stategen/epoch_boundary_state_cache.go @@ -6,7 +6,7 @@ import ( "sync" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "k8s.io/client-go/tools/cache" ) diff --git a/beacon-chain/state/stategen/epoch_boundary_state_cache_test.go b/beacon-chain/state-native/stategen/epoch_boundary_state_cache_test.go similarity index 91% rename from beacon-chain/state/stategen/epoch_boundary_state_cache_test.go rename to beacon-chain/state-native/stategen/epoch_boundary_state_cache_test.go index 987d40508e..eefb84e715 100644 --- a/beacon-chain/state/stategen/epoch_boundary_state_cache_test.go +++ b/beacon-chain/state-native/stategen/epoch_boundary_state_cache_test.go @@ -35,7 +35,7 @@ func TestEpochBoundaryStateCache_CanSave(t *testing.T) { got, exists, err = e.getByRoot([32]byte{'a'}) require.NoError(t, err) assert.Equal(t, true, exists, "Should exist") - assert.DeepSSZEqual(t, s.ToProtoUnsafe(), got.state.ToProtoUnsafe(), "Should have the same state") + assert.DeepSSZEqual(t, s.InnerStateUnsafe(), got.state.InnerStateUnsafe(), "Should have the same state") got, exists, err = e.getBySlot(2) require.NoError(t, err) @@ -45,7 +45,7 @@ func TestEpochBoundaryStateCache_CanSave(t *testing.T) { got, exists, err = e.getBySlot(1) require.NoError(t, err) assert.Equal(t, true, exists, "Should exist") - assert.DeepSSZEqual(t, s.ToProtoUnsafe(), got.state.ToProtoUnsafe(), "Should have the same state") + assert.DeepSSZEqual(t, s.InnerStateUnsafe(), got.state.InnerStateUnsafe(), "Should have the same state") } func TestEpochBoundaryStateCache_CanTrim(t *testing.T) { diff --git a/beacon-chain/state/stategen/errors.go b/beacon-chain/state-native/stategen/errors.go similarity index 100% rename from beacon-chain/state/stategen/errors.go rename to beacon-chain/state-native/stategen/errors.go diff --git a/beacon-chain/state/stategen/getter.go b/beacon-chain/state-native/stategen/getter.go similarity index 99% rename from beacon-chain/state/stategen/getter.go rename to beacon-chain/state-native/stategen/getter.go index 6751f2eb4e..057bc244ff 100644 --- a/beacon-chain/state/stategen/getter.go +++ b/beacon-chain/state-native/stategen/getter.go @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state/stategen/getter_test.go b/beacon-chain/state-native/stategen/getter_test.go similarity index 96% rename from beacon-chain/state/stategen/getter_test.go rename to beacon-chain/state-native/stategen/getter_test.go index 63c12fd525..6e49dcf391 100644 --- a/beacon-chain/state/stategen/getter_test.go +++ b/beacon-chain/state-native/stategen/getter_test.go @@ -30,7 +30,7 @@ func TestStateByRoot_GenesisState(t *testing.T) { require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) loadedState, err := service.StateByRoot(ctx, params.BeaconConfig().ZeroHash) // Zero hash is genesis state root. require.NoError(t, err) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) } func TestStateByRoot_ColdState(t *testing.T) { @@ -53,7 +53,7 @@ func TestStateByRoot_ColdState(t *testing.T) { require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) loadedState, err := service.StateByRoot(ctx, bRoot) require.NoError(t, err) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) } func TestStateByRootIfCachedNoCopy_HotState(t *testing.T) { @@ -68,7 +68,7 @@ func TestStateByRootIfCachedNoCopy_HotState(t *testing.T) { service.hotStateCache.put(r, beaconState) loadedState := service.StateByRootIfCachedNoCopy(r) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) } func TestStateByRootIfCachedNoCopy_ColdState(t *testing.T) { @@ -150,7 +150,7 @@ func TestStateByRoot_HotStateCached(t *testing.T) { loadedState, err := service.StateByRoot(ctx, r) require.NoError(t, err) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) } func TestStateByRoot_StateByRootInitialSync(t *testing.T) { @@ -167,7 +167,7 @@ func TestStateByRoot_StateByRootInitialSync(t *testing.T) { require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) loadedState, err := service.StateByRootInitialSync(ctx, params.BeaconConfig().ZeroHash) // Zero hash is genesis state root. require.NoError(t, err) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) } func TestStateByRootInitialSync_UseEpochStateCache(t *testing.T) { @@ -201,7 +201,7 @@ func TestStateByRootInitialSync_UseCache(t *testing.T) { loadedState, err := service.StateByRootInitialSync(ctx, r) require.NoError(t, err) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) if service.hotStateCache.has(r) { t.Error("Hot state cache was not invalidated") } @@ -300,7 +300,7 @@ func TestLoadeStateByRoot_Cached(t *testing.T) { // This tests where hot state was already cached. loadedState, err := service.loadStateByRoot(ctx, r) require.NoError(t, err) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) } func TestLoadeStateByRoot_FinalizedState(t *testing.T) { @@ -324,7 +324,7 @@ func TestLoadeStateByRoot_FinalizedState(t *testing.T) { // This tests where hot state was already cached. loadedState, err := service.loadStateByRoot(ctx, gRoot) require.NoError(t, err) - require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe()) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) } func TestLoadeStateByRoot_EpochBoundaryStateCanProcess(t *testing.T) { diff --git a/beacon-chain/state/stategen/hot_state_cache.go b/beacon-chain/state-native/stategen/hot_state_cache.go similarity index 97% rename from beacon-chain/state/stategen/hot_state_cache.go rename to beacon-chain/state-native/stategen/hot_state_cache.go index f0fe69b82a..97fdbed10e 100644 --- a/beacon-chain/state/stategen/hot_state_cache.go +++ b/beacon-chain/state-native/stategen/hot_state_cache.go @@ -6,7 +6,7 @@ import ( lru "github.com/hashicorp/golang-lru" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" ) diff --git a/beacon-chain/state-native/stategen/hot_state_cache_test.go b/beacon-chain/state-native/stategen/hot_state_cache_test.go new file mode 100644 index 0000000000..c60b63db17 --- /dev/null +++ b/beacon-chain/state-native/stategen/hot_state_cache_test.go @@ -0,0 +1,34 @@ +package stategen + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestHotStateCache_RoundTrip(t *testing.T) { + c := newHotStateCache() + root := [32]byte{'A'} + s := c.get(root) + assert.Equal(t, state.BeaconState(nil), s) + assert.Equal(t, false, c.has(root), "Empty cache has an object") + + s, err := v1.InitializeFromProto(ðpb.BeaconState{ + Slot: 10, + }) + require.NoError(t, err) + + c.put(root, s) + assert.Equal(t, true, c.has(root), "Empty cache does not have an object") + + res := c.get(root) + assert.NotNil(t, s) + assert.DeepEqual(t, res.CloneInnerState(), s.CloneInnerState(), "Expected equal protos to return from cache") + + c.delete(root) + assert.Equal(t, false, c.has(root), "Cache not supposed to have the object") +} diff --git a/beacon-chain/state/stategen/init_test.go b/beacon-chain/state-native/stategen/init_test.go similarity index 100% rename from beacon-chain/state/stategen/init_test.go rename to beacon-chain/state-native/stategen/init_test.go diff --git a/beacon-chain/state/stategen/log.go b/beacon-chain/state-native/stategen/log.go similarity index 100% rename from beacon-chain/state/stategen/log.go rename to beacon-chain/state-native/stategen/log.go diff --git a/beacon-chain/state/stategen/metrics.go b/beacon-chain/state-native/stategen/metrics.go similarity index 100% rename from beacon-chain/state/stategen/metrics.go rename to beacon-chain/state-native/stategen/metrics.go diff --git a/beacon-chain/state/stategen/migrate.go b/beacon-chain/state-native/stategen/migrate.go similarity index 98% rename from beacon-chain/state/stategen/migrate.go rename to beacon-chain/state-native/stategen/migrate.go index 60b5510922..388c0e18d9 100644 --- a/beacon-chain/state/stategen/migrate.go +++ b/beacon-chain/state-native/stategen/migrate.go @@ -5,7 +5,7 @@ import ( "encoding/hex" "fmt" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/sirupsen/logrus" "go.opencensus.io/trace" diff --git a/beacon-chain/state/stategen/migrate_test.go b/beacon-chain/state-native/stategen/migrate_test.go similarity index 98% rename from beacon-chain/state/stategen/migrate_test.go rename to beacon-chain/state-native/stategen/migrate_test.go index 9123d319ab..ec2c5d8cc6 100644 --- a/beacon-chain/state/stategen/migrate_test.go +++ b/beacon-chain/state-native/stategen/migrate_test.go @@ -52,7 +52,7 @@ func TestMigrateToCold_HappyPath(t *testing.T) { gotState, err := service.beaconDB.State(ctx, fRoot) require.NoError(t, err) - assert.DeepSSZEqual(t, beaconState.ToProtoUnsafe(), gotState.ToProtoUnsafe(), "Did not save state") + assert.DeepSSZEqual(t, beaconState.InnerStateUnsafe(), gotState.InnerStateUnsafe(), "Did not save state") gotRoot := service.beaconDB.ArchivedPointRoot(ctx, stateSlot/service.slotsPerArchivedPoint) assert.Equal(t, fRoot, gotRoot, "Did not save archived root") lastIndex, err := service.beaconDB.LastArchivedSlot(ctx) diff --git a/beacon-chain/state/stategen/mock.go b/beacon-chain/state-native/stategen/mock.go similarity index 98% rename from beacon-chain/state/stategen/mock.go rename to beacon-chain/state-native/stategen/mock.go index 4bef97f00b..8dbde0369a 100644 --- a/beacon-chain/state/stategen/mock.go +++ b/beacon-chain/state-native/stategen/mock.go @@ -4,7 +4,7 @@ import ( "context" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" ) diff --git a/beacon-chain/state/stategen/replay.go b/beacon-chain/state-native/stategen/replay.go similarity index 99% rename from beacon-chain/state/stategen/replay.go rename to beacon-chain/state-native/stategen/replay.go index 7b3f08c826..6d4e336bfb 100644 --- a/beacon-chain/state/stategen/replay.go +++ b/beacon-chain/state-native/stategen/replay.go @@ -12,7 +12,7 @@ import ( prysmTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/beacon-chain/db/filters" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/runtime/version" diff --git a/beacon-chain/state/stategen/replay_test.go b/beacon-chain/state-native/stategen/replay_test.go similarity index 99% rename from beacon-chain/state/stategen/replay_test.go rename to beacon-chain/state-native/stategen/replay_test.go index 33d996a156..72846a162c 100644 --- a/beacon-chain/state/stategen/replay_test.go +++ b/beacon-chain/state-native/stategen/replay_test.go @@ -394,7 +394,7 @@ func TestLastSavedState_Genesis(t *testing.T) { savedState, err := s.lastSavedState(ctx, 0) require.NoError(t, err) - require.DeepSSZEqual(t, gState.ToProtoUnsafe(), savedState.ToProtoUnsafe()) + require.DeepSSZEqual(t, gState.InnerStateUnsafe(), savedState.InnerStateUnsafe()) } func TestLastSavedState_CanGet(t *testing.T) { @@ -424,7 +424,7 @@ func TestLastSavedState_CanGet(t *testing.T) { savedState, err := s.lastSavedState(ctx, s.finalizedInfo.slot+100) require.NoError(t, err) - require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedState.ToProtoUnsafe()) + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedState.InnerStateUnsafe()) } func TestLastSavedState_NoSavedBlockState(t *testing.T) { diff --git a/beacon-chain/state/stategen/service.go b/beacon-chain/state-native/stategen/service.go similarity index 98% rename from beacon-chain/state/stategen/service.go rename to beacon-chain/state-native/stategen/service.go index 69dce996ee..95cf97ac1d 100644 --- a/beacon-chain/state/stategen/service.go +++ b/beacon-chain/state-native/stategen/service.go @@ -10,7 +10,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/db" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state/stategen/service_test.go b/beacon-chain/state-native/stategen/service_test.go similarity index 94% rename from beacon-chain/state/stategen/service_test.go rename to beacon-chain/state-native/stategen/service_test.go index 4a2ac735ff..e839cca80b 100644 --- a/beacon-chain/state/stategen/service_test.go +++ b/beacon-chain/state-native/stategen/service_test.go @@ -30,7 +30,7 @@ func TestResume(t *testing.T) { resumeState, err := service.Resume(ctx, beaconState) require.NoError(t, err) - require.DeepSSZEqual(t, beaconState.ToProtoUnsafe(), resumeState.ToProtoUnsafe()) + require.DeepSSZEqual(t, beaconState.InnerStateUnsafe(), resumeState.InnerStateUnsafe()) assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, service.finalizedInfo.slot, "Did not get watned slot") assert.Equal(t, service.finalizedInfo.root, root, "Did not get wanted root") assert.NotNil(t, service.finalizedState(), "Wanted a non nil finalized state") diff --git a/beacon-chain/state/stategen/setter.go b/beacon-chain/state-native/stategen/setter.go similarity index 98% rename from beacon-chain/state/stategen/setter.go rename to beacon-chain/state-native/stategen/setter.go index 6cb81ee1b0..06e349eb2f 100644 --- a/beacon-chain/state/stategen/setter.go +++ b/beacon-chain/state-native/stategen/setter.go @@ -4,7 +4,7 @@ import ( "context" "math" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state/stategen/setter_test.go b/beacon-chain/state-native/stategen/setter_test.go similarity index 100% rename from beacon-chain/state/stategen/setter_test.go rename to beacon-chain/state-native/stategen/setter_test.go diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state-native/stateutil/BUILD.bazel similarity index 95% rename from beacon-chain/state/stateutil/BUILD.bazel rename to beacon-chain/state-native/stateutil/BUILD.bazel index ea960dbb58..c32bc2e7f1 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state-native/stateutil/BUILD.bazel @@ -18,7 +18,7 @@ go_library( "validator_map_handler.go", "validator_root.go", ], - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil", visibility = [ "//beacon-chain:__subpackages__", "//proto/migration:__subpackages__", @@ -66,6 +66,7 @@ go_test( "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//crypto/hash:go_default_library", + "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/interop:go_default_library", @@ -91,7 +92,7 @@ go_test( "no-cache", ], deps = [ - "//beacon-chain/state/stateutil:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", "//crypto/hash:go_default_library", "//encoding/ssz:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/state/stateutil/benchmark_test.go b/beacon-chain/state-native/stateutil/benchmark_test.go similarity index 100% rename from beacon-chain/state/stateutil/benchmark_test.go rename to beacon-chain/state-native/stateutil/benchmark_test.go diff --git a/beacon-chain/state/stateutil/block_header_root.go b/beacon-chain/state-native/stateutil/block_header_root.go similarity index 100% rename from beacon-chain/state/stateutil/block_header_root.go rename to beacon-chain/state-native/stateutil/block_header_root.go diff --git a/beacon-chain/state/stateutil/eth1_root.go b/beacon-chain/state-native/stateutil/eth1_root.go similarity index 100% rename from beacon-chain/state/stateutil/eth1_root.go rename to beacon-chain/state-native/stateutil/eth1_root.go diff --git a/beacon-chain/state/stateutil/field_root_attestation.go b/beacon-chain/state-native/stateutil/field_root_attestation.go similarity index 100% rename from beacon-chain/state/stateutil/field_root_attestation.go rename to beacon-chain/state-native/stateutil/field_root_attestation.go diff --git a/beacon-chain/state/stateutil/field_root_eth1.go b/beacon-chain/state-native/stateutil/field_root_eth1.go similarity index 100% rename from beacon-chain/state/stateutil/field_root_eth1.go rename to beacon-chain/state-native/stateutil/field_root_eth1.go diff --git a/beacon-chain/state/stateutil/field_root_test.go b/beacon-chain/state-native/stateutil/field_root_test.go similarity index 100% rename from beacon-chain/state/stateutil/field_root_test.go rename to beacon-chain/state-native/stateutil/field_root_test.go diff --git a/beacon-chain/state/stateutil/field_root_validator.go b/beacon-chain/state-native/stateutil/field_root_validator.go similarity index 100% rename from beacon-chain/state/stateutil/field_root_validator.go rename to beacon-chain/state-native/stateutil/field_root_validator.go diff --git a/beacon-chain/state/stateutil/field_root_vector.go b/beacon-chain/state-native/stateutil/field_root_vector.go similarity index 100% rename from beacon-chain/state/stateutil/field_root_vector.go rename to beacon-chain/state-native/stateutil/field_root_vector.go diff --git a/beacon-chain/state/stateutil/participation_bit_root.go b/beacon-chain/state-native/stateutil/participation_bit_root.go similarity index 100% rename from beacon-chain/state/stateutil/participation_bit_root.go rename to beacon-chain/state-native/stateutil/participation_bit_root.go diff --git a/beacon-chain/state/stateutil/pending_attestation_root.go b/beacon-chain/state-native/stateutil/pending_attestation_root.go similarity index 100% rename from beacon-chain/state/stateutil/pending_attestation_root.go rename to beacon-chain/state-native/stateutil/pending_attestation_root.go diff --git a/beacon-chain/state/stateutil/reference.go b/beacon-chain/state-native/stateutil/reference.go similarity index 100% rename from beacon-chain/state/stateutil/reference.go rename to beacon-chain/state-native/stateutil/reference.go diff --git a/beacon-chain/state/stateutil/reference_bench_test.go b/beacon-chain/state-native/stateutil/reference_bench_test.go similarity index 100% rename from beacon-chain/state/stateutil/reference_bench_test.go rename to beacon-chain/state-native/stateutil/reference_bench_test.go diff --git a/beacon-chain/state/stateutil/state_hasher.go b/beacon-chain/state-native/stateutil/state_hasher.go similarity index 100% rename from beacon-chain/state/stateutil/state_hasher.go rename to beacon-chain/state-native/stateutil/state_hasher.go diff --git a/beacon-chain/state/stateutil/state_root_test.go b/beacon-chain/state-native/stateutil/state_root_test.go similarity index 100% rename from beacon-chain/state/stateutil/state_root_test.go rename to beacon-chain/state-native/stateutil/state_root_test.go diff --git a/beacon-chain/state/stateutil/stateutil_test.go b/beacon-chain/state-native/stateutil/stateutil_test.go similarity index 100% rename from beacon-chain/state/stateutil/stateutil_test.go rename to beacon-chain/state-native/stateutil/stateutil_test.go diff --git a/beacon-chain/state/stateutil/sync_committee.root.go b/beacon-chain/state-native/stateutil/sync_committee.root.go similarity index 100% rename from beacon-chain/state/stateutil/sync_committee.root.go rename to beacon-chain/state-native/stateutil/sync_committee.root.go diff --git a/beacon-chain/state/stateutil/trie_helpers.go b/beacon-chain/state-native/stateutil/trie_helpers.go similarity index 100% rename from beacon-chain/state/stateutil/trie_helpers.go rename to beacon-chain/state-native/stateutil/trie_helpers.go diff --git a/beacon-chain/state/stateutil/trie_helpers_test.go b/beacon-chain/state-native/stateutil/trie_helpers_test.go similarity index 86% rename from beacon-chain/state/stateutil/trie_helpers_test.go rename to beacon-chain/state-native/stateutil/trie_helpers_test.go index 77ef9923f6..1f92152fee 100644 --- a/beacon-chain/state/stateutil/trie_helpers_test.go +++ b/beacon-chain/state-native/stateutil/trie_helpers_test.go @@ -4,9 +4,10 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" @@ -15,17 +16,12 @@ import ( func TestReturnTrieLayer_OK(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 32) - bRootsSlice := make([][]byte, len(newState.BlockRoots())) - for i, r := range newState.BlockRoots() { - tmp := r - bRootsSlice[i] = tmp[:] - } - root, err := stateutil.RootsArrayHashTreeRoot(bRootsSlice, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots") + root, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots") require.NoError(t, err) blockRts := newState.BlockRoots() roots := make([][32]byte, 0, len(blockRts)) for _, rt := range blockRts { - roots = append(roots, rt) + roots = append(roots, bytesutil.ToBytes32(rt)) } layers, err := stateutil.ReturnTrieLayer(roots, uint64(len(roots))) assert.NoError(t, err) @@ -57,7 +53,7 @@ func TestRecomputeFromLayer_FixedSizedArray(t *testing.T) { blockRts := newState.BlockRoots() roots := make([][32]byte, 0, len(blockRts)) for _, rt := range blockRts { - roots = append(roots, rt) + roots = append(roots, bytesutil.ToBytes32(rt)) } layers, err := stateutil.ReturnTrieLayer(roots, uint64(len(roots))) require.NoError(t, err) @@ -67,12 +63,7 @@ func TestRecomputeFromLayer_FixedSizedArray(t *testing.T) { require.NoError(t, newState.UpdateBlockRootAtIndex(changedIdx[0], changedRoots[0])) require.NoError(t, newState.UpdateBlockRootAtIndex(changedIdx[1], changedRoots[1])) - bRootsSlice := make([][]byte, len(newState.BlockRoots())) - for i, r := range newState.BlockRoots() { - tmp := r - bRootsSlice[i] = tmp[:] - } - expectedRoot, err := stateutil.RootsArrayHashTreeRoot(bRootsSlice, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots") + expectedRoot, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots") require.NoError(t, err) root, _, err := stateutil.RecomputeFromLayer(changedRoots, changedIdx, layers) require.NoError(t, err) diff --git a/beacon-chain/state/stateutil/validator_map_handler.go b/beacon-chain/state-native/stateutil/validator_map_handler.go similarity index 100% rename from beacon-chain/state/stateutil/validator_map_handler.go rename to beacon-chain/state-native/stateutil/validator_map_handler.go diff --git a/beacon-chain/state/stateutil/validator_root.go b/beacon-chain/state-native/stateutil/validator_root.go similarity index 100% rename from beacon-chain/state/stateutil/validator_root.go rename to beacon-chain/state-native/stateutil/validator_root.go diff --git a/beacon-chain/state-native/stateutil/validator_root_test.go b/beacon-chain/state-native/stateutil/validator_root_test.go new file mode 100644 index 0000000000..60a01a5914 --- /dev/null +++ b/beacon-chain/state-native/stateutil/validator_root_test.go @@ -0,0 +1,22 @@ +package stateutil_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" +) + +func BenchmarkUint64ListRootWithRegistryLimit(b *testing.B) { + balances := make([]uint64, 100000) + for i := 0; i < len(balances); i++ { + balances[i] = uint64(i) + } + b.Run("100k balances", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := stateutil.Uint64ListRootWithRegistryLimit(balances) + if err != nil { + b.Fatal(err) + } + } + }) +} diff --git a/beacon-chain/state-native/types/BUILD.bazel b/beacon-chain/state-native/types/BUILD.bazel new file mode 100644 index 0000000000..c3724b06f4 --- /dev/null +++ b/beacon-chain/state-native/types/BUILD.bazel @@ -0,0 +1,19 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["types.go"], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types", + visibility = ["//beacon-chain:__subpackages__"], + deps = [ + "//runtime/version:go_default_library", + "@com_github_pkg_errors//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["types_test.go"], + embed = [":go_default_library"], + deps = ["//testing/assert:go_default_library"], +) diff --git a/beacon-chain/state/types/types.go b/beacon-chain/state-native/types/types.go similarity index 100% rename from beacon-chain/state/types/types.go rename to beacon-chain/state-native/types/types.go diff --git a/beacon-chain/state/types/types_test.go b/beacon-chain/state-native/types/types_test.go similarity index 100% rename from beacon-chain/state/types/types_test.go rename to beacon-chain/state-native/types/types_test.go diff --git a/beacon-chain/state/v1/BUILD.bazel b/beacon-chain/state-native/v1/BUILD.bazel similarity index 87% rename from beacon-chain/state/v1/BUILD.bazel rename to beacon-chain/state-native/v1/BUILD.bazel index d0aae818a6..993ff9ef9a 100644 --- a/beacon-chain/state/v1/BUILD.bazel +++ b/beacon-chain/state-native/v1/BUILD.bazel @@ -35,7 +35,7 @@ go_library( "//config:mainnet": ["beacon_state_mainnet.go"], "//config:minimal": ["beacon_state_minimal.go"], }), - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v1", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1", visibility = [ "//beacon-chain:__subpackages__", "//contracts/deposit:__subpackages__", @@ -52,11 +52,12 @@ go_library( "//tools/pcli:__pkg__", ], deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/custom-types:go_default_library", - "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", + "//beacon-chain/sharedstate:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", + "//beacon-chain/state-native/fieldtrie:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -95,9 +96,9 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -122,7 +123,7 @@ ssz_gen_marshal( "//config:minimal": ["beacon_state_minimal.go"], }), includes = [ - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", "//config/fieldparams:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", diff --git a/beacon-chain/state/v1/beacon_state_mainnet.go b/beacon-chain/state-native/v1/beacon_state_mainnet.go similarity index 90% rename from beacon-chain/state/v1/beacon_state_mainnet.go rename to beacon-chain/state-native/v1/beacon_state_mainnet.go index 1ba6dfc56f..8fddb01482 100644 --- a/beacon-chain/state/v1/beacon_state_mainnet.go +++ b/beacon-chain/state-native/v1/beacon_state_mainnet.go @@ -7,10 +7,10 @@ import ( eth2types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v1/beacon_state_minimal.go b/beacon-chain/state-native/v1/beacon_state_minimal.go similarity index 89% rename from beacon-chain/state/v1/beacon_state_minimal.go rename to beacon-chain/state-native/v1/beacon_state_minimal.go index 69ae68729a..9b9b8a7a03 100644 --- a/beacon-chain/state/v1/beacon_state_minimal.go +++ b/beacon-chain/state-native/v1/beacon_state_minimal.go @@ -7,10 +7,10 @@ import ( eth2types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v1/doc.go b/beacon-chain/state-native/v1/doc.go similarity index 100% rename from beacon-chain/state/v1/doc.go rename to beacon-chain/state-native/v1/doc.go diff --git a/beacon-chain/state/v1/field_roots.go b/beacon-chain/state-native/v1/field_roots.go similarity index 91% rename from beacon-chain/state/v1/field_roots.go rename to beacon-chain/state-native/v1/field_roots.go index 6f93d2a321..30c5c1b226 100644 --- a/beacon-chain/state/v1/field_roots.go +++ b/beacon-chain/state-native/v1/field_roots.go @@ -4,7 +4,7 @@ import ( "context" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" "github.com/prysmaticlabs/prysm/config/features" eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v1/generated.ssz.go b/beacon-chain/state-native/v1/generated.ssz.go similarity index 100% rename from beacon-chain/state/v1/generated.ssz.go rename to beacon-chain/state-native/v1/generated.ssz.go diff --git a/beacon-chain/state/v1/getters_attestation.go b/beacon-chain/state-native/v1/getters_attestation.go similarity index 100% rename from beacon-chain/state/v1/getters_attestation.go rename to beacon-chain/state-native/v1/getters_attestation.go diff --git a/beacon-chain/state/v1/getters_attestation_test.go b/beacon-chain/state-native/v1/getters_attestation_test.go similarity index 100% rename from beacon-chain/state/v1/getters_attestation_test.go rename to beacon-chain/state-native/v1/getters_attestation_test.go diff --git a/beacon-chain/state/v1/getters_block.go b/beacon-chain/state-native/v1/getters_block.go similarity index 81% rename from beacon-chain/state/v1/getters_block.go rename to beacon-chain/state-native/v1/getters_block.go index 880c090794..5d54f268cf 100644 --- a/beacon-chain/state/v1/getters_block.go +++ b/beacon-chain/state-native/v1/getters_block.go @@ -3,8 +3,7 @@ package v1 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -46,7 +45,7 @@ func (b *BeaconState) latestBlockHeaderInternal() *ethpb.BeaconBlockHeader { } // BlockRoots kept track of in the beacon state. -func (b *BeaconState) BlockRoots() *[fieldparams.BlockRootsLength][32]byte { +func (b *BeaconState) BlockRoots() [][]byte { if b.blockRoots == nil { return nil } @@ -54,8 +53,12 @@ func (b *BeaconState) BlockRoots() *[fieldparams.BlockRootsLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - roots := [fieldparams.BlockRootsLength][32]byte(*b.blockRootsInternal()) - return &roots + rootsArr := b.blockRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + return roots } // blockRootsInternal kept track of in the beacon state. @@ -66,15 +69,19 @@ func (b *BeaconState) blockRootsInternal() *customtypes.BlockRoots { // BlockRootAtIndex retrieves a specific block root based on an // input index value. -func (b *BeaconState) BlockRootAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { if b.blockRoots == nil { - return [32]byte{}, nil + return []byte{}, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.blockRootAtIndex(idx) + r, err := b.blockRootAtIndex(idx) + if err != nil { + return nil, err + } + return r[:], nil } // blockRootAtIndex retrieves a specific block root based on an diff --git a/beacon-chain/state/v1/getters_block_test.go b/beacon-chain/state-native/v1/getters_block_test.go similarity index 96% rename from beacon-chain/state/v1/getters_block_test.go rename to beacon-chain/state-native/v1/getters_block_test.go index acf47e1cb5..6cb1380b27 100644 --- a/beacon-chain/state/v1/getters_block_test.go +++ b/beacon-chain/state-native/v1/getters_block_test.go @@ -29,7 +29,7 @@ func TestBeaconState_BlockRoots(t *testing.T) { s, err := InitializeFromProto(ðpb.BeaconState{}) require.NoError(t, err) got := s.BlockRoots() - require.DeepEqual(t, [fieldparams.BlockRootsLength][32]byte{}, *got) + require.DeepEqual(t, [fieldparams.BlockRootsLength][32]byte{}, got) want := [fieldparams.BlockRootsLength][32]byte{{'a'}} bRoots := make([][]byte, len(want)) @@ -40,11 +40,11 @@ func TestBeaconState_BlockRoots(t *testing.T) { s, err = InitializeFromProto(ðpb.BeaconState{BlockRoots: bRoots}) require.NoError(t, err) got = s.BlockRoots() - require.DeepEqual(t, want, *got) + require.DeepEqual(t, want, got) // Test copy does not mutate. got[0][0] = 'b' - require.DeepNotEqual(t, want, *got) + require.DeepNotEqual(t, want, got) } func TestBeaconState_BlockRootAtIndex(t *testing.T) { diff --git a/beacon-chain/state/v1/getters_checkpoint.go b/beacon-chain/state-native/v1/getters_checkpoint.go similarity index 100% rename from beacon-chain/state/v1/getters_checkpoint.go rename to beacon-chain/state-native/v1/getters_checkpoint.go diff --git a/beacon-chain/state/v1/getters_eth1.go b/beacon-chain/state-native/v1/getters_eth1.go similarity index 100% rename from beacon-chain/state/v1/getters_eth1.go rename to beacon-chain/state-native/v1/getters_eth1.go diff --git a/beacon-chain/state/v1/getters_misc.go b/beacon-chain/state-native/v1/getters_misc.go similarity index 87% rename from beacon-chain/state/v1/getters_misc.go rename to beacon-chain/state-native/v1/getters_misc.go index f9b1f4bfb8..e499ff3364 100644 --- a/beacon-chain/state/v1/getters_misc.go +++ b/beacon-chain/state-native/v1/getters_misc.go @@ -2,7 +2,7 @@ package v1 import ( types "github.com/prysmaticlabs/eth2-types" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime/version" @@ -23,11 +23,12 @@ func (b *BeaconState) genesisTimeInternal() uint64 { } // GenesisValidatorRoot of the beacon state. -func (b *BeaconState) GenesisValidatorRoot() [32]byte { +func (b *BeaconState) GenesisValidatorRoot() []byte { b.lock.RLock() defer b.lock.RUnlock() - return b.genesisValidatorRootInternal() + r := b.genesisValidatorRootInternal() + return r[:] } // genesisValidatorRootInternal of the beacon state. @@ -88,7 +89,7 @@ func (b *BeaconState) forkInternal() *ethpb.Fork { } // HistoricalRoots based on epochs stored in the beacon state. -func (b *BeaconState) HistoricalRoots() [][32]byte { +func (b *BeaconState) HistoricalRoots() [][]byte { if b.historicalRoots == nil { return nil } @@ -96,7 +97,13 @@ func (b *BeaconState) HistoricalRoots() [][32]byte { b.lock.RLock() defer b.lock.RUnlock() - return b.historicalRootsInternal() + rootsArr := b.historicalRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + + return roots } // historicalRootsInternal based on epochs stored in the beacon state. diff --git a/beacon-chain/state/v1/getters_randao.go b/beacon-chain/state-native/v1/getters_randao.go similarity index 75% rename from beacon-chain/state/v1/getters_randao.go rename to beacon-chain/state-native/v1/getters_randao.go index 4c4fea5a46..c654d51bd7 100644 --- a/beacon-chain/state/v1/getters_randao.go +++ b/beacon-chain/state-native/v1/getters_randao.go @@ -3,12 +3,11 @@ package v1 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ) // RandaoMixes of block proposers on the beacon chain. -func (b *BeaconState) RandaoMixes() *[fieldparams.RandaoMixesLength][32]byte { +func (b *BeaconState) RandaoMixes() [][]byte { if b.randaoMixes == nil { return nil } @@ -16,8 +15,13 @@ func (b *BeaconState) RandaoMixes() *[fieldparams.RandaoMixesLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - mixes := [fieldparams.RandaoMixesLength][32]byte(*b.randaoMixesInternal()) - return &mixes + mixesArr := b.randaoMixesInternal() + mixes := make([][]byte, len(mixesArr)) + for i, m := range mixesArr { + mixes[i] = m[:] + } + + return mixes } // randaoMixesInternal of block proposers on the beacon chain. @@ -28,15 +32,19 @@ func (b *BeaconState) randaoMixesInternal() *customtypes.RandaoMixes { // RandaoMixAtIndex retrieves a specific block root based on an // input index value. -func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { if b.randaoMixes == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.randaoMixAtIndex(idx) + m, err := b.randaoMixAtIndex(idx) + if err != nil { + return nil, err + } + return m[:], nil } // randaoMixAtIndex retrieves a specific block root based on an diff --git a/beacon-chain/state/v1/getters_state.go b/beacon-chain/state-native/v1/getters_state.go similarity index 87% rename from beacon-chain/state/v1/getters_state.go rename to beacon-chain/state-native/v1/getters_state.go index 61d6349f84..62487b733b 100644 --- a/beacon-chain/state/v1/getters_state.go +++ b/beacon-chain/state-native/v1/getters_state.go @@ -4,8 +4,7 @@ import ( "fmt" "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -153,7 +152,7 @@ func (b *BeaconState) toProtoNoLock() interface{} { } // StateRoots kept track of in the beacon state. -func (b *BeaconState) StateRoots() *[fieldparams.StateRootsLength][32]byte { +func (b *BeaconState) StateRoots() [][]byte { if b.stateRoots == nil { return nil } @@ -161,8 +160,13 @@ func (b *BeaconState) StateRoots() *[fieldparams.StateRootsLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - roots := [fieldparams.StateRootsLength][32]byte(*b.stateRootsInternal()) - return &roots + rootsArr := b.stateRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + + return roots } // stateRootsInternal kept track of in the beacon state. @@ -173,15 +177,19 @@ func (b *BeaconState) stateRootsInternal() *customtypes.StateRoots { // StateRootAtIndex retrieves a specific state root based on an // input index value. -func (b *BeaconState) StateRootAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { if b.stateRoots == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.stateRootAtIndex(idx) + r, err := b.stateRootAtIndex(idx) + if err != nil { + return nil, err + } + return r[:], nil } // stateRootAtIndex retrieves a specific state root based on an @@ -203,3 +211,14 @@ func ProtobufBeaconState(s interface{}) (*ethpb.BeaconState, error) { } return pbState, nil } + +// InnerStateUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) InnerStateUnsafe() interface{} { + return b.ToProtoUnsafe() +} + +// CloneInnerState the beacon state into a protobuf for usage. +func (b *BeaconState) CloneInnerState() interface{} { + return b.ToProto() +} diff --git a/beacon-chain/state/v1/getters_test.go b/beacon-chain/state-native/v1/getters_test.go similarity index 100% rename from beacon-chain/state/v1/getters_test.go rename to beacon-chain/state-native/v1/getters_test.go diff --git a/beacon-chain/state/v1/getters_validator.go b/beacon-chain/state-native/v1/getters_validator.go similarity index 99% rename from beacon-chain/state/v1/getters_validator.go rename to beacon-chain/state-native/v1/getters_validator.go index 040137f2d7..0ce302a204 100644 --- a/beacon-chain/state/v1/getters_validator.go +++ b/beacon-chain/state-native/v1/getters_validator.go @@ -5,7 +5,7 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state-native/v1/getters_validator_test.go b/beacon-chain/state-native/v1/getters_validator_test.go new file mode 100644 index 0000000000..510ca8cb18 --- /dev/null +++ b/beacon-chain/state-native/v1/getters_validator_test.go @@ -0,0 +1,20 @@ +package v1_test + +import ( + "testing" + + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice(t *testing.T) { + st, err := v1.InitializeFromProtoUnsafe(ðpb.BeaconState{ + Validators: nil, + }) + require.NoError(t, err) + + _, err = st.ValidatorAtIndexReadOnly(0) + assert.Equal(t, v1.ErrNilValidatorsInState, err) +} diff --git a/beacon-chain/state/v1/proofs.go b/beacon-chain/state-native/v1/proofs.go similarity index 95% rename from beacon-chain/state/v1/proofs.go rename to beacon-chain/state-native/v1/proofs.go index 1d3fc5dd34..8d31957558 100644 --- a/beacon-chain/state/v1/proofs.go +++ b/beacon-chain/state-native/v1/proofs.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) diff --git a/beacon-chain/state-native/v1/proofs_test.go b/beacon-chain/state-native/v1/proofs_test.go new file mode 100644 index 0000000000..6bcca5eefc --- /dev/null +++ b/beacon-chain/state-native/v1/proofs_test.go @@ -0,0 +1,34 @@ +package v1_test + +import ( + "context" + "testing" + + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" + "github.com/prysmaticlabs/prysm/container/trie" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestBeaconStateMerkleProofs(t *testing.T) { + ctx := context.Background() + st, _ := util.DeterministicGenesisState(t, 256) + htr, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + t.Run("current sync committee", func(t *testing.T) { + _, err := st.CurrentSyncCommitteeProof() + require.ErrorContains(t, "unsupported", err) + }) + t.Run("next sync committee", func(t *testing.T) { + _, err := st.NextSyncCommitteeProof() + require.ErrorContains(t, "unsupported", err) + }) + t.Run("finalized root", func(t *testing.T) { + finalizedRoot := st.FinalizedCheckpoint().Root + proof, err := st.FinalizedRootProof() + require.NoError(t, err) + gIndex := v1.FinalizedRootGeneralizedIndex() + valid := trie.VerifyMerkleProof(htr[:], finalizedRoot, gIndex, proof) + require.Equal(t, true, valid) + }) +} diff --git a/beacon-chain/state/v1/readonly_validator.go b/beacon-chain/state-native/v1/readonly_validator.go similarity index 97% rename from beacon-chain/state/v1/readonly_validator.go rename to beacon-chain/state-native/v1/readonly_validator.go index ce82153968..d04ee5b109 100644 --- a/beacon-chain/state/v1/readonly_validator.go +++ b/beacon-chain/state-native/v1/readonly_validator.go @@ -3,7 +3,7 @@ package v1 import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state-native/v1/readonly_validator_test.go b/beacon-chain/state-native/v1/readonly_validator_test.go new file mode 100644 index 0000000000..081d8808ed --- /dev/null +++ b/beacon-chain/state-native/v1/readonly_validator_test.go @@ -0,0 +1,73 @@ +package v1_test + +import ( + "testing" + + types "github.com/prysmaticlabs/eth2-types" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestReadOnlyValidator_ReturnsErrorOnNil(t *testing.T) { + if _, err := v1.NewValidator(nil); err != v1.ErrNilWrappedValidator { + t.Errorf("Wrong error returned. Got %v, wanted %v", err, v1.ErrNilWrappedValidator) + } +} + +func TestReadOnlyValidator_EffectiveBalance(t *testing.T) { + bal := uint64(234) + v, err := v1.NewValidator(ðpb.Validator{EffectiveBalance: bal}) + require.NoError(t, err) + assert.Equal(t, bal, v.EffectiveBalance()) +} + +func TestReadOnlyValidator_ActivationEligibilityEpoch(t *testing.T) { + epoch := types.Epoch(234) + v, err := v1.NewValidator(ðpb.Validator{ActivationEligibilityEpoch: epoch}) + require.NoError(t, err) + assert.Equal(t, epoch, v.ActivationEligibilityEpoch()) +} + +func TestReadOnlyValidator_ActivationEpoch(t *testing.T) { + epoch := types.Epoch(234) + v, err := v1.NewValidator(ðpb.Validator{ActivationEpoch: epoch}) + require.NoError(t, err) + assert.Equal(t, epoch, v.ActivationEpoch()) +} + +func TestReadOnlyValidator_WithdrawableEpoch(t *testing.T) { + epoch := types.Epoch(234) + v, err := v1.NewValidator(ðpb.Validator{WithdrawableEpoch: epoch}) + require.NoError(t, err) + assert.Equal(t, epoch, v.WithdrawableEpoch()) +} + +func TestReadOnlyValidator_ExitEpoch(t *testing.T) { + epoch := types.Epoch(234) + v, err := v1.NewValidator(ðpb.Validator{ExitEpoch: epoch}) + require.NoError(t, err) + assert.Equal(t, epoch, v.ExitEpoch()) +} + +func TestReadOnlyValidator_PublicKey(t *testing.T) { + key := [48]byte{0xFA, 0xCC} + v, err := v1.NewValidator(ðpb.Validator{PublicKey: key[:]}) + require.NoError(t, err) + assert.Equal(t, key, v.PublicKey()) +} + +func TestReadOnlyValidator_WithdrawalCredentials(t *testing.T) { + creds := []byte{0xFA, 0xCC} + v, err := v1.NewValidator(ðpb.Validator{WithdrawalCredentials: creds}) + require.NoError(t, err) + assert.DeepEqual(t, creds, v.WithdrawalCredentials()) +} + +func TestReadOnlyValidator_Slashed(t *testing.T) { + slashed := true + v, err := v1.NewValidator(ðpb.Validator{Slashed: slashed}) + require.NoError(t, err) + assert.Equal(t, slashed, v.Slashed()) +} diff --git a/beacon-chain/state/v1/references_test.go b/beacon-chain/state-native/v1/references_test.go similarity index 80% rename from beacon-chain/state/v1/references_test.go rename to beacon-chain/state-native/v1/references_test.go index 542ebc201f..c8a7c01a3e 100644 --- a/beacon-chain/state/v1/references_test.go +++ b/beacon-chain/state-native/v1/references_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" @@ -36,7 +36,7 @@ func TestStateReferenceSharing_Finalizer(t *testing.T) { b, ok := copied.(*BeaconState) require.Equal(t, true, ok) assert.Equal(t, uint(2), b.sharedFieldReferences[randaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) + require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) if b.sharedFieldReferences[randaoMixes].Refs() != 1 || a.sharedFieldReferences[randaoMixes].Refs() != 1 { t.Error("Expected 1 shared reference to RANDAO mix for both a and b") } @@ -64,70 +64,46 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) { assertRefCount(t, a, stateRoots, 2) assertRefCount(t, b, blockRoots, 2) assertRefCount(t, b, stateRoots, 2) + assert.Equal(t, 1, len(b.BlockRoots()), "No block roots found") + assert.Equal(t, 1, len(b.StateRoots()), "No state roots found") // Assert shared state. - bRootsA := make([][]byte, len(a.BlockRoots())) - for i, r := range a.BlockRoots() { - tmp := r - bRootsA[i] = tmp[:] + blockRootsA := a.BlockRoots() + stateRootsA := a.StateRoots() + blockRootsB := b.BlockRoots() + stateRootsB := b.StateRoots() + if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { + t.Errorf("Unexpected number of block roots, want: %v", 1) } - sRootsA := make([][]byte, len(a.StateRoots())) - for i, r := range a.StateRoots() { - tmp := r - sRootsA[i] = tmp[:] + if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { + t.Errorf("Unexpected number of state roots, want: %v", 1) } - bRootsB := make([][]byte, len(b.BlockRoots())) - for i, r := range b.BlockRoots() { - tmp := r - bRootsB[i] = tmp[:] - } - sRootsB := make([][]byte, len(b.StateRoots())) - for i, r := range b.StateRoots() { - tmp := r - sRootsB[i] = tmp[:] - } - assertValFound(t, bRootsA, root1[:]) - assertValFound(t, bRootsB, root1[:]) - assertValFound(t, sRootsA, root1[:]) - assertValFound(t, sRootsB, root1[:]) + 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). - bRootsA = make([][]byte, len(a.BlockRoots())) - for i, r := range a.BlockRoots() { - tmp := r - bRootsA[i] = tmp[:] + 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[:]) + if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { + t.Errorf("Unexpected number of block roots, want: %v", 1) } - sRootsA = make([][]byte, len(a.StateRoots())) - for i, r := range a.StateRoots() { - tmp := r - sRootsA[i] = tmp[:] + if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { + t.Errorf("Unexpected number of state roots, want: %v", 1) } - blockRootsB := b.BlockRoots() - bRootsB = make([][]byte, len(b.BlockRoots())) - for i, r := range b.BlockRoots() { - tmp := r - bRootsB[i] = tmp[:] - } - stateRootsB := b.StateRoots() - sRootsB = make([][]byte, len(b.StateRoots())) - for i, r := range b.StateRoots() { - tmp := r - sRootsB[i] = tmp[:] - } - assertValNotFound(t, bRootsA, root1[:]) - assertValNotFound(t, sRootsA, root1[:]) - assertValFound(t, bRootsA, root2[:]) - assertValFound(t, sRootsA, root2[:]) - assertValFound(t, bRootsB, root1[:]) - assertValFound(t, sRootsB, 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") + 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, blockRoots, 1) @@ -138,10 +114,10 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) { func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) + val1, val2 := []byte("foo"), []byte("bar") a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ RandaoMixes: [][]byte{ - val1[:], + val1, }, }) require.NoError(t, err) @@ -155,41 +131,29 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) { assertRefCount(t, b, randaoMixes, 2) // Assert shared state. - mixesA := make([][]byte, len(a.RandaoMixes())) - for i, r := range a.RandaoMixes() { - tmp := r - mixesA[i] = tmp[:] + mixesA := a.RandaoMixes() + mixesB := b.RandaoMixes() + if len(mixesA) != len(mixesB) || len(mixesA) < 1 { + t.Errorf("Unexpected number of mix values, want: %v", 1) } - mixesB := make([][]byte, len(b.RandaoMixes())) - for i, r := range b.RandaoMixes() { - tmp := r - mixesB[i] = tmp[:] - } - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) + 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). - mixesA = make([][]byte, len(a.RandaoMixes())) - for i, r := range a.RandaoMixes() { - tmp := r - mixesA[i] = tmp[:] + if len(mixesA) != len(mixesB) || len(mixesA) < 1 { + t.Errorf("Unexpected number of mix values, want: %v", 1) } - mixesB = make([][]byte, len(b.RandaoMixes())) - for i, r := range b.RandaoMixes() { - tmp := r - mixesB[i] = tmp[:] - } - assertValFound(t, mixesA, val2[:]) - assertValNotFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, bytesutil.ToBytes32(val2[:]), a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") + 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, randaoMixes, 1) diff --git a/beacon-chain/state/v1/setters_attestation.go b/beacon-chain/state-native/v1/setters_attestation.go similarity index 97% rename from beacon-chain/state/v1/setters_attestation.go rename to beacon-chain/state-native/v1/setters_attestation.go index 6e716d7fbe..49fe20730f 100644 --- a/beacon-chain/state/v1/setters_attestation.go +++ b/beacon-chain/state-native/v1/setters_attestation.go @@ -3,7 +3,7 @@ package v1 import ( "fmt" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v1/setters_attestation_test.go b/beacon-chain/state-native/v1/setters_attestation_test.go similarity index 97% rename from beacon-chain/state/v1/setters_attestation_test.go rename to beacon-chain/state-native/v1/setters_attestation_test.go index 0003358ef1..174e44bf1b 100644 --- a/beacon-chain/state/v1/setters_attestation_test.go +++ b/beacon-chain/state-native/v1/setters_attestation_test.go @@ -5,7 +5,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/state/v1/setters_block.go b/beacon-chain/state-native/v1/setters_block.go similarity index 77% rename from beacon-chain/state/v1/setters_block.go rename to beacon-chain/state-native/v1/setters_block.go index 9eb06bf95a..21638e4985 100644 --- a/beacon-chain/state/v1/setters_block.go +++ b/beacon-chain/state-native/v1/setters_block.go @@ -3,9 +3,10 @@ package v1 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -21,14 +22,18 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { // SetBlockRoots for the beacon state. Updates the entire // list to a new value by overwriting the previous one. -func (b *BeaconState) SetBlockRoots(val *[fieldparams.BlockRootsLength][32]byte) error { +func (b *BeaconState) SetBlockRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[blockRoots].MinusRef() b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - roots := customtypes.BlockRoots(*val) + var rootsArr [fieldparams.BlockRootsLength][32]byte + for i := 0; i < len(rootsArr); i++ { + rootsArr[i] = bytesutil.ToBytes32(val[i]) + } + roots := customtypes.BlockRoots(rootsArr) b.blockRoots = &roots b.markFieldAsDirty(blockRoots) b.rebuildTrie[blockRoots] = true diff --git a/beacon-chain/state/v1/setters_checkpoint.go b/beacon-chain/state-native/v1/setters_checkpoint.go similarity index 100% rename from beacon-chain/state/v1/setters_checkpoint.go rename to beacon-chain/state-native/v1/setters_checkpoint.go diff --git a/beacon-chain/state/v1/setters_eth1.go b/beacon-chain/state-native/v1/setters_eth1.go similarity index 95% rename from beacon-chain/state/v1/setters_eth1.go rename to beacon-chain/state-native/v1/setters_eth1.go index ce3d6af567..c615945846 100644 --- a/beacon-chain/state/v1/setters_eth1.go +++ b/beacon-chain/state-native/v1/setters_eth1.go @@ -1,7 +1,7 @@ package v1 import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v1/setters_misc.go b/beacon-chain/state-native/v1/setters_misc.go similarity index 90% rename from beacon-chain/state/v1/setters_misc.go rename to beacon-chain/state-native/v1/setters_misc.go index 83d2f9d1ec..87f965233b 100644 --- a/beacon-chain/state/v1/setters_misc.go +++ b/beacon-chain/state-native/v1/setters_misc.go @@ -3,10 +3,11 @@ package v1 import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "google.golang.org/protobuf/proto" ) @@ -50,11 +51,11 @@ func (b *BeaconState) SetGenesisTime(val uint64) error { } // SetGenesisValidatorRoot for the beacon state. -func (b *BeaconState) SetGenesisValidatorRoot(val [32]byte) error { +func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error { b.lock.Lock() defer b.lock.Unlock() - b.genesisValidatorsRoot = val + b.genesisValidatorsRoot = bytesutil.ToBytes32(val) b.markFieldAsDirty(genesisValidatorRoot) return nil } @@ -85,14 +86,18 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error { // SetHistoricalRoots for the beacon state. Updates the entire // list to a new value by overwriting the previous one. -func (b *BeaconState) SetHistoricalRoots(val [][32]byte) error { +func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[historicalRoots].MinusRef() b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - b.historicalRoots = val + roots := make([][32]byte, len(val)) + for i, r := range val { + roots[i] = bytesutil.ToBytes32(r) + } + b.historicalRoots = roots b.markFieldAsDirty(historicalRoots) return nil } diff --git a/beacon-chain/state/v1/setters_randao.go b/beacon-chain/state-native/v1/setters_randao.go similarity index 71% rename from beacon-chain/state/v1/setters_randao.go rename to beacon-chain/state-native/v1/setters_randao.go index b5f0c2c9fe..8f8b106678 100644 --- a/beacon-chain/state/v1/setters_randao.go +++ b/beacon-chain/state-native/v1/setters_randao.go @@ -2,21 +2,26 @@ package v1 import ( "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) // SetRandaoMixes for the beacon state. Updates the entire // randao mixes to a new value by overwriting the previous one. -func (b *BeaconState) SetRandaoMixes(val *[fieldparams.RandaoMixesLength][32]byte) error { +func (b *BeaconState) SetRandaoMixes(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[randaoMixes].MinusRef() b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - mixes := customtypes.RandaoMixes(*val) + var mixesArr [fieldparams.RandaoMixesLength][32]byte + for i := 0; i < len(mixesArr); i++ { + mixesArr[i] = bytesutil.ToBytes32(val[i]) + } + mixes := customtypes.RandaoMixes(mixesArr) b.randaoMixes = &mixes b.markFieldAsDirty(randaoMixes) b.rebuildTrie[randaoMixes] = true @@ -25,7 +30,7 @@ func (b *BeaconState) SetRandaoMixes(val *[fieldparams.RandaoMixesLength][32]byt // UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes // at a specific index to a new value. -func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error { +func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { if uint64(len(b.randaoMixes)) <= idx { return errors.Errorf("invalid index provided %d", idx) } @@ -42,7 +47,7 @@ func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error { b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) } - mixes[idx] = val + mixes[idx] = bytesutil.ToBytes32(val) b.randaoMixes = mixes b.markFieldAsDirty(randaoMixes) b.addDirtyIndices(randaoMixes, []uint64{idx}) diff --git a/beacon-chain/state/v1/setters_state.go b/beacon-chain/state-native/v1/setters_state.go similarity index 75% rename from beacon-chain/state/v1/setters_state.go rename to beacon-chain/state-native/v1/setters_state.go index a8f6421217..c3c48c73ad 100644 --- a/beacon-chain/state/v1/setters_state.go +++ b/beacon-chain/state-native/v1/setters_state.go @@ -2,21 +2,26 @@ package v1 import ( "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) // SetStateRoots for the beacon state. Updates the state roots // to a new value by overwriting the previous value. -func (b *BeaconState) SetStateRoots(val *[fieldparams.StateRootsLength][32]byte) error { +func (b *BeaconState) SetStateRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[stateRoots].MinusRef() b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - roots := customtypes.StateRoots(*val) + var rootsArr [fieldparams.StateRootsLength][32]byte + for i := 0; i < len(rootsArr); i++ { + rootsArr[i] = bytesutil.ToBytes32(val[i]) + } + roots := customtypes.StateRoots(rootsArr) b.stateRoots = &roots b.markFieldAsDirty(stateRoots) b.rebuildTrie[stateRoots] = true diff --git a/beacon-chain/state/v1/setters_validator.go b/beacon-chain/state-native/v1/setters_validator.go similarity index 98% rename from beacon-chain/state/v1/setters_validator.go rename to beacon-chain/state-native/v1/setters_validator.go index 99f7d3e4d9..9280973c0f 100644 --- a/beacon-chain/state/v1/setters_validator.go +++ b/beacon-chain/state-native/v1/setters_validator.go @@ -3,7 +3,7 @@ package v1 import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v1/state_test.go b/beacon-chain/state-native/v1/state_test.go similarity index 98% rename from beacon-chain/state/v1/state_test.go rename to beacon-chain/state-native/v1/state_test.go index 8d9006e683..2b779b4327 100644 --- a/beacon-chain/state/v1/state_test.go +++ b/beacon-chain/state-native/v1/state_test.go @@ -8,7 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/state/v1/state_trie.go b/beacon-chain/state-native/v1/state_trie.go similarity index 96% rename from beacon-chain/state/v1/state_trie.go rename to beacon-chain/state-native/v1/state_trie.go index 59462d7089..595accc151 100644 --- a/beacon-chain/state/v1/state_trie.go +++ b/beacon-chain/state-native/v1/state_trie.go @@ -6,13 +6,12 @@ import ( "sort" "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/sharedstate" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/features" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" @@ -25,13 +24,6 @@ import ( "google.golang.org/protobuf/proto" ) -var ( - stateCount = promauto.NewGauge(prometheus.GaugeOpts{ - Name: "beacon_state_count", - Help: "Count the number of active beacon state objects.", - }) -) - // InitializeFromProto the beacon state from a protobuf representation. func InitializeFromProto(st *ethpb.BeaconState) (*BeaconState, error) { return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState)) @@ -116,7 +108,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (*BeaconState, error) { b.sharedFieldReferences[balances] = stateutil.NewRef(1) b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - stateCount.Inc() + sharedstate.StateCount.Inc() return b, nil } @@ -160,7 +152,7 @@ func Initialize() (*BeaconState, error) { b.sharedFieldReferences[balances] = stateutil.NewRef(1) b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - stateCount.Inc() + sharedstate.StateCount.Inc() return b, nil } @@ -255,7 +247,7 @@ func (b *BeaconState) Copy() state.BeaconState { } } - stateCount.Inc() + sharedstate.StateCount.Inc() // Finalizer runs when dst is being destroyed in garbage collection. runtime.SetFinalizer(dst, func(b *BeaconState) { for field, v := range b.sharedFieldReferences { @@ -273,7 +265,7 @@ func (b *BeaconState) Copy() state.BeaconState { delete(b.sharedFieldReferences, field) delete(b.stateFieldLeaves, field) } - stateCount.Sub(1) + sharedstate.StateCount.Sub(1) }) return dst } diff --git a/beacon-chain/state/v1/state_trie_test.go b/beacon-chain/state-native/v1/state_trie_test.go similarity index 94% rename from beacon-chain/state/v1/state_trie_test.go rename to beacon-chain/state-native/v1/state_trie_test.go index 639a7a1f1e..95458d0e1b 100644 --- a/beacon-chain/state/v1/state_trie_test.go +++ b/beacon-chain/state-native/v1/state_trie_test.go @@ -5,8 +5,8 @@ import ( "context" "testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -24,7 +24,7 @@ func TestMain(m *testing.M) { func TestInitializeFromProto(t *testing.T) { testState, _ := util.DeterministicGenesisState(t, 64) - pbState, err := v1.ProtobufBeaconState(testState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) require.NoError(t, err) type test struct { name string @@ -67,7 +67,7 @@ func TestInitializeFromProto(t *testing.T) { func TestInitializeFromProtoUnsafe(t *testing.T) { testState, _ := util.DeterministicGenesisState(t, 64) - pbState, err := v1.ProtobufBeaconState(testState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) require.NoError(t, err) type test struct { name string @@ -161,7 +161,7 @@ func TestBeaconState_HashTreeRoot(t *testing.T) { if err == nil && tt.error != "" { t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) } - pbState, err := v1.ProtobufBeaconState(testState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) require.NoError(t, err) genericHTR, err := pbState.HashTreeRoot() if err == nil && tt.error != "" { @@ -230,7 +230,7 @@ func TestBeaconState_HashTreeRoot_FieldTrie(t *testing.T) { if err == nil && tt.error != "" { t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) } - pbState, err := v1.ProtobufBeaconState(testState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) require.NoError(t, err) genericHTR, err := pbState.HashTreeRoot() if err == nil && tt.error != "" { diff --git a/beacon-chain/state/v1/types.go b/beacon-chain/state-native/v1/types.go similarity index 94% rename from beacon-chain/state/v1/types.go rename to beacon-chain/state-native/v1/types.go index e395259950..566f131dba 100644 --- a/beacon-chain/state/v1/types.go +++ b/beacon-chain/state-native/v1/types.go @@ -2,8 +2,8 @@ package v1 import ( "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/params" ) diff --git a/beacon-chain/state/v1/types_test.go b/beacon-chain/state-native/v1/types_test.go similarity index 98% rename from beacon-chain/state/v1/types_test.go rename to beacon-chain/state-native/v1/types_test.go index 9af391c03e..d8ecd95eb4 100644 --- a/beacon-chain/state/v1/types_test.go +++ b/beacon-chain/state-native/v1/types_test.go @@ -6,7 +6,7 @@ import ( "strconv" "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -190,7 +190,7 @@ func TestBeaconState_ImmutabilityWithSharedResources(t *testing.T) { // Randao mixes require.DeepEqual(t, a.RandaoMixes(), b.RandaoMixes(), "Test precondition failed, fields are not equal") - require.NoError(t, a.UpdateRandaoMixesAtIndex(1, bytesutil.ToBytes32([]byte("foo")))) + require.NoError(t, a.UpdateRandaoMixesAtIndex(1, []byte("foo"))) if reflect.DeepEqual(a.RandaoMixes(), b.RandaoMixes()) { t.Error("Expect a.RandaoMixes() to be different from b.RandaoMixes()") } diff --git a/beacon-chain/state/v1/unsupported_getters.go b/beacon-chain/state-native/v1/unsupported_getters.go similarity index 100% rename from beacon-chain/state/v1/unsupported_getters.go rename to beacon-chain/state-native/v1/unsupported_getters.go diff --git a/beacon-chain/state/v1/unsupported_setters.go b/beacon-chain/state-native/v1/unsupported_setters.go similarity index 100% rename from beacon-chain/state/v1/unsupported_setters.go rename to beacon-chain/state-native/v1/unsupported_setters.go diff --git a/beacon-chain/state/v2/BUILD.bazel b/beacon-chain/state-native/v2/BUILD.bazel similarity index 84% rename from beacon-chain/state/v2/BUILD.bazel rename to beacon-chain/state-native/v2/BUILD.bazel index 789371fc21..5ea90f8bf3 100644 --- a/beacon-chain/state/v2/BUILD.bazel +++ b/beacon-chain/state-native/v2/BUILD.bazel @@ -35,7 +35,7 @@ go_library( "//config:mainnet": ["beacon_state_mainnet.go"], "//config:minimal": ["beacon_state_minimal.go"], }), - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v2", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v2", visibility = [ "//beacon-chain:__subpackages__", "//proto/migration:__subpackages__", @@ -43,12 +43,13 @@ go_library( "//testing/util:__pkg__", ], deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/custom-types:go_default_library", - "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/sharedstate:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", + "//beacon-chain/state-native/fieldtrie:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", + "//beacon-chain/state-native/v1:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -83,9 +84,9 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", + "//beacon-chain/state-native/v1:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -108,7 +109,7 @@ ssz_gen_marshal( "//config:minimal": ["beacon_state_minimal.go"], }), includes = [ - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", "//config/fieldparams:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", diff --git a/beacon-chain/state/v2/beacon_state_mainnet.go b/beacon-chain/state-native/v2/beacon_state_mainnet.go similarity index 90% rename from beacon-chain/state/v2/beacon_state_mainnet.go rename to beacon-chain/state-native/v2/beacon_state_mainnet.go index ae5106164f..6c8f43c247 100644 --- a/beacon-chain/state/v2/beacon_state_mainnet.go +++ b/beacon-chain/state-native/v2/beacon_state_mainnet.go @@ -7,10 +7,10 @@ import ( eth2types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v2/beacon_state_minimal.go b/beacon-chain/state-native/v2/beacon_state_minimal.go similarity index 90% rename from beacon-chain/state/v2/beacon_state_minimal.go rename to beacon-chain/state-native/v2/beacon_state_minimal.go index f94f2e3e40..fca96794e8 100644 --- a/beacon-chain/state/v2/beacon_state_minimal.go +++ b/beacon-chain/state-native/v2/beacon_state_minimal.go @@ -7,10 +7,10 @@ import ( eth2types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v2/deprecated_getters.go b/beacon-chain/state-native/v2/deprecated_getters.go similarity index 100% rename from beacon-chain/state/v2/deprecated_getters.go rename to beacon-chain/state-native/v2/deprecated_getters.go diff --git a/beacon-chain/state/v2/deprecated_getters_test.go b/beacon-chain/state-native/v2/deprecated_getters_test.go similarity index 100% rename from beacon-chain/state/v2/deprecated_getters_test.go rename to beacon-chain/state-native/v2/deprecated_getters_test.go diff --git a/beacon-chain/state/v2/deprecated_setters.go b/beacon-chain/state-native/v2/deprecated_setters.go similarity index 100% rename from beacon-chain/state/v2/deprecated_setters.go rename to beacon-chain/state-native/v2/deprecated_setters.go diff --git a/beacon-chain/state/v2/deprecated_setters_test.go b/beacon-chain/state-native/v2/deprecated_setters_test.go similarity index 100% rename from beacon-chain/state/v2/deprecated_setters_test.go rename to beacon-chain/state-native/v2/deprecated_setters_test.go diff --git a/beacon-chain/state/v2/field_roots.go b/beacon-chain/state-native/v2/field_roots.go similarity index 91% rename from beacon-chain/state/v2/field_roots.go rename to beacon-chain/state-native/v2/field_roots.go index 2314c59e8f..ea3db898de 100644 --- a/beacon-chain/state/v2/field_roots.go +++ b/beacon-chain/state-native/v2/field_roots.go @@ -4,7 +4,7 @@ import ( "context" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" "github.com/prysmaticlabs/prysm/config/features" eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v2/generated.ssz.go b/beacon-chain/state-native/v2/generated.ssz.go similarity index 100% rename from beacon-chain/state/v2/generated.ssz.go rename to beacon-chain/state-native/v2/generated.ssz.go diff --git a/beacon-chain/state/v2/getters_block.go b/beacon-chain/state-native/v2/getters_block.go similarity index 81% rename from beacon-chain/state/v2/getters_block.go rename to beacon-chain/state-native/v2/getters_block.go index 277e620a44..5c32f66697 100644 --- a/beacon-chain/state/v2/getters_block.go +++ b/beacon-chain/state-native/v2/getters_block.go @@ -3,8 +3,7 @@ package v2 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -46,7 +45,7 @@ func (b *BeaconState) latestBlockHeaderInternal() *ethpb.BeaconBlockHeader { } // BlockRoots kept track of in the beacon state. -func (b *BeaconState) BlockRoots() *[fieldparams.BlockRootsLength][32]byte { +func (b *BeaconState) BlockRoots() [][]byte { if b.blockRoots == nil { return nil } @@ -54,8 +53,12 @@ func (b *BeaconState) BlockRoots() *[fieldparams.BlockRootsLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - roots := [fieldparams.BlockRootsLength][32]byte(*b.blockRootsInternal()) - return &roots + rootsArr := b.blockRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + return roots } // blockRootsInternal kept track of in the beacon state. @@ -66,15 +69,19 @@ func (b *BeaconState) blockRootsInternal() *customtypes.BlockRoots { // BlockRootAtIndex retrieves a specific block root based on an // input index value. -func (b *BeaconState) BlockRootAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { if b.blockRoots == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.blockRootAtIndex(idx) + r, err := b.blockRootAtIndex(idx) + if err != nil { + return nil, err + } + return r[:], nil } // blockRootAtIndex retrieves a specific block root based on an diff --git a/beacon-chain/state/v2/getters_block_test.go b/beacon-chain/state-native/v2/getters_block_test.go similarity index 96% rename from beacon-chain/state/v2/getters_block_test.go rename to beacon-chain/state-native/v2/getters_block_test.go index fb7e5dd6b8..c7054f2e3f 100644 --- a/beacon-chain/state/v2/getters_block_test.go +++ b/beacon-chain/state-native/v2/getters_block_test.go @@ -29,7 +29,7 @@ func TestBeaconState_BlockRoots(t *testing.T) { s, err := InitializeFromProto(ðpb.BeaconStateAltair{}) require.NoError(t, err) got := s.BlockRoots() - require.DeepEqual(t, [fieldparams.BlockRootsLength][32]byte{}, *got) + require.DeepEqual(t, [fieldparams.BlockRootsLength][32]byte{}, got) want := [fieldparams.BlockRootsLength][32]byte{{'a'}} bRoots := make([][]byte, len(want)) @@ -40,11 +40,11 @@ func TestBeaconState_BlockRoots(t *testing.T) { s, err = InitializeFromProto(ðpb.BeaconStateAltair{BlockRoots: bRoots}) require.NoError(t, err) got = s.BlockRoots() - require.DeepEqual(t, want, *got) + require.DeepEqual(t, want, got) // Test copy does not mutate. got[0][0] = 'b' - require.DeepNotEqual(t, want, *got) + require.DeepNotEqual(t, want, got) } func TestBeaconState_BlockRootAtIndex(t *testing.T) { diff --git a/beacon-chain/state/v2/getters_checkpoint.go b/beacon-chain/state-native/v2/getters_checkpoint.go similarity index 100% rename from beacon-chain/state/v2/getters_checkpoint.go rename to beacon-chain/state-native/v2/getters_checkpoint.go diff --git a/beacon-chain/state/v2/getters_eth1.go b/beacon-chain/state-native/v2/getters_eth1.go similarity index 100% rename from beacon-chain/state/v2/getters_eth1.go rename to beacon-chain/state-native/v2/getters_eth1.go diff --git a/beacon-chain/state/v2/getters_misc.go b/beacon-chain/state-native/v2/getters_misc.go similarity index 90% rename from beacon-chain/state/v2/getters_misc.go rename to beacon-chain/state-native/v2/getters_misc.go index 032d8b7469..8b26d9a6fd 100644 --- a/beacon-chain/state/v2/getters_misc.go +++ b/beacon-chain/state-native/v2/getters_misc.go @@ -4,7 +4,7 @@ import ( "time" types "github.com/prysmaticlabs/eth2-types" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime/version" @@ -25,11 +25,12 @@ func (b *BeaconState) genesisTimeInternal() uint64 { } // GenesisValidatorRoot of the beacon state. -func (b *BeaconState) GenesisValidatorRoot() [32]byte { +func (b *BeaconState) GenesisValidatorRoot() []byte { b.lock.RLock() defer b.lock.RUnlock() - return b.genesisValidatorRootInternal() + r := b.genesisValidatorRootInternal() + return r[:] } // genesisValidatorRootInternal of the beacon state. @@ -124,7 +125,7 @@ func (b *BeaconState) forkInternal() *ethpb.Fork { } // HistoricalRoots based on epochs stored in the beacon state. -func (b *BeaconState) HistoricalRoots() [][32]byte { +func (b *BeaconState) HistoricalRoots() [][]byte { if b.historicalRoots == nil { return nil } @@ -132,7 +133,12 @@ func (b *BeaconState) HistoricalRoots() [][32]byte { b.lock.RLock() defer b.lock.RUnlock() - return b.historicalRootsInternal() + rootsArr := b.historicalRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + return roots } // historicalRootsInternal based on epochs stored in the beacon state. diff --git a/beacon-chain/state/v2/getters_participation.go b/beacon-chain/state-native/v2/getters_participation.go similarity index 100% rename from beacon-chain/state/v2/getters_participation.go rename to beacon-chain/state-native/v2/getters_participation.go diff --git a/beacon-chain/state/v2/getters_randao.go b/beacon-chain/state-native/v2/getters_randao.go similarity index 75% rename from beacon-chain/state/v2/getters_randao.go rename to beacon-chain/state-native/v2/getters_randao.go index 7bbfb06411..6124591719 100644 --- a/beacon-chain/state/v2/getters_randao.go +++ b/beacon-chain/state-native/v2/getters_randao.go @@ -3,12 +3,11 @@ package v2 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ) // RandaoMixes of block proposers on the beacon chain. -func (b *BeaconState) RandaoMixes() *[fieldparams.RandaoMixesLength][32]byte { +func (b *BeaconState) RandaoMixes() [][]byte { if b.randaoMixes == nil { return nil } @@ -16,8 +15,13 @@ func (b *BeaconState) RandaoMixes() *[fieldparams.RandaoMixesLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - mixes := [fieldparams.RandaoMixesLength][32]byte(*b.randaoMixesInternal()) - return &mixes + mixesArr := b.randaoMixesInternal() + mixes := make([][]byte, len(mixesArr)) + for i, m := range mixesArr { + mixes[i] = m[:] + } + + return mixes } // randaoMixesInternal of block proposers on the beacon chain. @@ -28,15 +32,19 @@ func (b *BeaconState) randaoMixesInternal() *customtypes.RandaoMixes { // RandaoMixAtIndex retrieves a specific block root based on an // input index value. -func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { if b.randaoMixes == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.randaoMixAtIndex(idx) + m, err := b.randaoMixAtIndex(idx) + if err != nil { + return nil, err + } + return m[:], nil } // randaoMixAtIndex retrieves a specific block root based on an diff --git a/beacon-chain/state/v2/getters_state.go b/beacon-chain/state-native/v2/getters_state.go similarity index 88% rename from beacon-chain/state/v2/getters_state.go rename to beacon-chain/state-native/v2/getters_state.go index dff47837e9..6c5066ec79 100644 --- a/beacon-chain/state/v2/getters_state.go +++ b/beacon-chain/state-native/v2/getters_state.go @@ -4,8 +4,7 @@ import ( "fmt" "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -146,7 +145,7 @@ func (b *BeaconState) toProtoNoLock() interface{} { } // StateRoots kept track of in the beacon state. -func (b *BeaconState) StateRoots() *[fieldparams.StateRootsLength][32]byte { +func (b *BeaconState) StateRoots() [][]byte { if b.stateRoots == nil { return nil } @@ -154,8 +153,13 @@ func (b *BeaconState) StateRoots() *[fieldparams.StateRootsLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - roots := [fieldparams.StateRootsLength][32]byte(*b.stateRootsInternal()) - return &roots + rootsArr := b.stateRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + + return roots } // stateRootsInternal kept track of in the beacon state. @@ -166,15 +170,19 @@ func (b *BeaconState) stateRootsInternal() *customtypes.StateRoots { // StateRootAtIndex retrieves a specific state root based on an // input index value. -func (b *BeaconState) StateRootAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { if b.stateRoots == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.stateRootAtIndex(idx) + r, err := b.stateRootAtIndex(idx) + if err != nil { + return nil, err + } + return r[:], nil } // stateRootAtIndex retrieves a specific state root based on an @@ -197,3 +205,14 @@ func ProtobufBeaconState(s interface{}) (*ethpb.BeaconStateAltair, error) { } return pbState, nil } + +// InnerStateUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) InnerStateUnsafe() interface{} { + return b.ToProtoUnsafe() +} + +// CloneInnerState the beacon state into a protobuf for usage. +func (b *BeaconState) CloneInnerState() interface{} { + return nil +} diff --git a/beacon-chain/state/v2/getters_sync_committee.go b/beacon-chain/state-native/v2/getters_sync_committee.go similarity index 100% rename from beacon-chain/state/v2/getters_sync_committee.go rename to beacon-chain/state-native/v2/getters_sync_committee.go diff --git a/beacon-chain/state/v2/getters_test.go b/beacon-chain/state-native/v2/getters_test.go similarity index 100% rename from beacon-chain/state/v2/getters_test.go rename to beacon-chain/state-native/v2/getters_test.go diff --git a/beacon-chain/state/v2/getters_validator.go b/beacon-chain/state-native/v2/getters_validator.go similarity index 98% rename from beacon-chain/state/v2/getters_validator.go rename to beacon-chain/state-native/v2/getters_validator.go index 6a31963a37..4338305452 100644 --- a/beacon-chain/state/v2/getters_validator.go +++ b/beacon-chain/state-native/v2/getters_validator.go @@ -5,8 +5,8 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state-native/v2/getters_validator_test.go b/beacon-chain/state-native/v2/getters_validator_test.go new file mode 100644 index 0000000000..997893cfb4 --- /dev/null +++ b/beacon-chain/state-native/v2/getters_validator_test.go @@ -0,0 +1,20 @@ +package v2_test + +import ( + "testing" + + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice(t *testing.T) { + st, err := v1.InitializeFromProtoUnsafe(ðpb.BeaconState{ + Validators: nil, + }) + require.NoError(t, err) + + _, err = st.ValidatorAtIndexReadOnly(0) + assert.Equal(t, v1.ErrNilValidatorsInState, err) +} diff --git a/beacon-chain/state/v2/proofs.go b/beacon-chain/state-native/v2/proofs.go similarity index 96% rename from beacon-chain/state/v2/proofs.go rename to beacon-chain/state-native/v2/proofs.go index 026bb25fec..7d8a3f3dc7 100644 --- a/beacon-chain/state/v2/proofs.go +++ b/beacon-chain/state-native/v2/proofs.go @@ -3,7 +3,7 @@ package v2 import ( "encoding/binary" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) diff --git a/beacon-chain/state-native/v2/proofs_test.go b/beacon-chain/state-native/v2/proofs_test.go new file mode 100644 index 0000000000..8cd63a16ac --- /dev/null +++ b/beacon-chain/state-native/v2/proofs_test.go @@ -0,0 +1,75 @@ +package v2_test + +import ( + "context" + "testing" + + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v2" + "github.com/prysmaticlabs/prysm/container/trie" + "github.com/prysmaticlabs/prysm/crypto/bls" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestBeaconStateMerkleProofs(t *testing.T) { + ctx := context.Background() + st, _ := util.DeterministicGenesisStateAltair(t, 256) + htr, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + t.Run("current sync committee", func(t *testing.T) { + sc, err := st.CurrentSyncCommittee() + require.NoError(t, err) + + // Verify the Merkle proof. + scRoot, err := sc.HashTreeRoot() + require.NoError(t, err) + proof, err := st.CurrentSyncCommitteeProof() + require.NoError(t, err) + valid := trie.VerifyMerkleProof(htr[:], scRoot[:], v2.CurrentSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, true, valid) + }) + t.Run("next sync committee", func(t *testing.T) { + nextSC, err := st.NextSyncCommittee() + require.NoError(t, err) + proof, err := st.NextSyncCommitteeProof() + require.NoError(t, err) + + // Verify the Merkle proof. + nextSCRoot, err := nextSC.HashTreeRoot() + require.NoError(t, err) + valid := trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v2.NextSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, true, valid) + + // Edit the sync committee. + privKey, err := bls.RandKey() + require.NoError(t, err) + nextSC.AggregatePubkey = privKey.PublicKey().Marshal() + require.NoError(t, st.SetNextSyncCommittee(nextSC)) + + // Verifying the old Merkle proof for the new value should fail. + nextSCRoot, err = nextSC.HashTreeRoot() + require.NoError(t, err) + valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v2.NextSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, false, valid) + + // Generating a new, valid proof should pass. + proof, err = st.NextSyncCommitteeProof() + require.NoError(t, err) + htr, err = st.HashTreeRoot(ctx) + require.NoError(t, err) + valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v2.NextSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, true, valid) + }) + t.Run("finalized root", func(t *testing.T) { + finalizedRoot := st.FinalizedCheckpoint().Root + + // Verify the Merkle proof. + htr, err = st.HashTreeRoot(ctx) + require.NoError(t, err) + proof, err := st.FinalizedRootProof() + require.NoError(t, err) + gIndex := v2.FinalizedRootGeneralizedIndex() + valid := trie.VerifyMerkleProof(htr[:], finalizedRoot, gIndex, proof) + require.Equal(t, true, valid) + }) +} diff --git a/beacon-chain/state/v2/setters_block.go b/beacon-chain/state-native/v2/setters_block.go similarity index 77% rename from beacon-chain/state/v2/setters_block.go rename to beacon-chain/state-native/v2/setters_block.go index 7a1833b4d6..4140921ce5 100644 --- a/beacon-chain/state/v2/setters_block.go +++ b/beacon-chain/state-native/v2/setters_block.go @@ -3,9 +3,10 @@ package v2 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -21,14 +22,18 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { // SetBlockRoots for the beacon state. Updates the entire // list to a new value by overwriting the previous one. -func (b *BeaconState) SetBlockRoots(val *[fieldparams.BlockRootsLength][32]byte) error { +func (b *BeaconState) SetBlockRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[blockRoots].MinusRef() b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - roots := customtypes.BlockRoots(*val) + var rootsArr [fieldparams.BlockRootsLength][32]byte + for i := 0; i < len(rootsArr); i++ { + rootsArr[i] = bytesutil.ToBytes32(val[i]) + } + roots := customtypes.BlockRoots(rootsArr) b.blockRoots = &roots b.markFieldAsDirty(blockRoots) b.rebuildTrie[blockRoots] = true diff --git a/beacon-chain/state/v2/setters_checkpoint.go b/beacon-chain/state-native/v2/setters_checkpoint.go similarity index 100% rename from beacon-chain/state/v2/setters_checkpoint.go rename to beacon-chain/state-native/v2/setters_checkpoint.go diff --git a/beacon-chain/state/v2/setters_eth1.go b/beacon-chain/state-native/v2/setters_eth1.go similarity index 95% rename from beacon-chain/state/v2/setters_eth1.go rename to beacon-chain/state-native/v2/setters_eth1.go index 7446ea6838..b32ec489c3 100644 --- a/beacon-chain/state/v2/setters_eth1.go +++ b/beacon-chain/state-native/v2/setters_eth1.go @@ -1,7 +1,7 @@ package v2 import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v2/setters_misc.go b/beacon-chain/state-native/v2/setters_misc.go similarity index 90% rename from beacon-chain/state/v2/setters_misc.go rename to beacon-chain/state-native/v2/setters_misc.go index c08aed5837..3310b8ac02 100644 --- a/beacon-chain/state/v2/setters_misc.go +++ b/beacon-chain/state-native/v2/setters_misc.go @@ -3,10 +3,11 @@ package v2 import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "google.golang.org/protobuf/proto" ) @@ -49,11 +50,11 @@ func (b *BeaconState) SetGenesisTime(val uint64) error { } // SetGenesisValidatorRoot for the beacon state. -func (b *BeaconState) SetGenesisValidatorRoot(val [32]byte) error { +func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error { b.lock.Lock() defer b.lock.Unlock() - b.genesisValidatorsRoot = val + b.genesisValidatorsRoot = bytesutil.ToBytes32(val) b.markFieldAsDirty(genesisValidatorRoot) return nil } @@ -84,14 +85,18 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error { // SetHistoricalRoots for the beacon state. Updates the entire // list to a new value by overwriting the previous one. -func (b *BeaconState) SetHistoricalRoots(val [][32]byte) error { +func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[historicalRoots].MinusRef() b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - b.historicalRoots = val + roots := make([][32]byte, len(val)) + for i, r := range val { + roots[i] = bytesutil.ToBytes32(r) + } + b.historicalRoots = roots b.markFieldAsDirty(historicalRoots) return nil } diff --git a/beacon-chain/state/v2/setters_participation.go b/beacon-chain/state-native/v2/setters_participation.go similarity index 97% rename from beacon-chain/state/v2/setters_participation.go rename to beacon-chain/state-native/v2/setters_participation.go index 5e92d63042..5f5adb7f6d 100644 --- a/beacon-chain/state/v2/setters_participation.go +++ b/beacon-chain/state-native/v2/setters_participation.go @@ -1,7 +1,7 @@ package v2 import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" ) // SetPreviousParticipationBits for the beacon state. Updates the entire diff --git a/beacon-chain/state/v2/setters_randao.go b/beacon-chain/state-native/v2/setters_randao.go similarity index 71% rename from beacon-chain/state/v2/setters_randao.go rename to beacon-chain/state-native/v2/setters_randao.go index 0db89b9d86..2f208a5e91 100644 --- a/beacon-chain/state/v2/setters_randao.go +++ b/beacon-chain/state-native/v2/setters_randao.go @@ -2,21 +2,26 @@ package v2 import ( "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) // SetRandaoMixes for the beacon state. Updates the entire // randao mixes to a new value by overwriting the previous one. -func (b *BeaconState) SetRandaoMixes(val *[fieldparams.RandaoMixesLength][32]byte) error { +func (b *BeaconState) SetRandaoMixes(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[randaoMixes].MinusRef() b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - mixes := customtypes.RandaoMixes(*val) + var mixesArr [fieldparams.RandaoMixesLength][32]byte + for i := 0; i < len(mixesArr); i++ { + mixesArr[i] = bytesutil.ToBytes32(val[i]) + } + mixes := customtypes.RandaoMixes(mixesArr) b.randaoMixes = &mixes b.markFieldAsDirty(randaoMixes) b.rebuildTrie[randaoMixes] = true @@ -25,7 +30,7 @@ func (b *BeaconState) SetRandaoMixes(val *[fieldparams.RandaoMixesLength][32]byt // UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes // at a specific index to a new value. -func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error { +func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { if uint64(len(b.randaoMixes)) <= idx { return errors.Errorf("invalid index provided %d", idx) } @@ -42,7 +47,7 @@ func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error { b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) } - mixes[idx] = val + mixes[idx] = bytesutil.ToBytes32(val) b.randaoMixes = mixes b.markFieldAsDirty(randaoMixes) b.addDirtyIndices(randaoMixes, []uint64{idx}) diff --git a/beacon-chain/state/v2/setters_state.go b/beacon-chain/state-native/v2/setters_state.go similarity index 75% rename from beacon-chain/state/v2/setters_state.go rename to beacon-chain/state-native/v2/setters_state.go index c2b4f6a626..ee6b4525d9 100644 --- a/beacon-chain/state/v2/setters_state.go +++ b/beacon-chain/state-native/v2/setters_state.go @@ -2,21 +2,26 @@ package v2 import ( "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) // SetStateRoots for the beacon state. Updates the state roots // to a new value by overwriting the previous value. -func (b *BeaconState) SetStateRoots(val *[fieldparams.StateRootsLength][32]byte) error { +func (b *BeaconState) SetStateRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[stateRoots].MinusRef() b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - roots := customtypes.StateRoots(*val) + var rootsArr [fieldparams.StateRootsLength][32]byte + for i := 0; i < len(rootsArr); i++ { + rootsArr[i] = bytesutil.ToBytes32(val[i]) + } + roots := customtypes.StateRoots(rootsArr) b.stateRoots = &roots b.markFieldAsDirty(stateRoots) b.rebuildTrie[stateRoots] = true diff --git a/beacon-chain/state/v2/setters_sync_committee.go b/beacon-chain/state-native/v2/setters_sync_committee.go similarity index 100% rename from beacon-chain/state/v2/setters_sync_committee.go rename to beacon-chain/state-native/v2/setters_sync_committee.go diff --git a/beacon-chain/state/v2/setters_test.go b/beacon-chain/state-native/v2/setters_test.go similarity index 97% rename from beacon-chain/state/v2/setters_test.go rename to beacon-chain/state-native/v2/setters_test.go index 8329667aa7..32a157ef16 100644 --- a/beacon-chain/state/v2/setters_test.go +++ b/beacon-chain/state-native/v2/setters_test.go @@ -7,8 +7,8 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/state/v2/setters_validator.go b/beacon-chain/state-native/v2/setters_validator.go similarity index 98% rename from beacon-chain/state/v2/setters_validator.go rename to beacon-chain/state-native/v2/setters_validator.go index a142d06620..c6f2907c0c 100644 --- a/beacon-chain/state/v2/setters_validator.go +++ b/beacon-chain/state-native/v2/setters_validator.go @@ -3,7 +3,7 @@ package v2 import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v2/state_trie.go b/beacon-chain/state-native/v2/state_trie.go similarity index 96% rename from beacon-chain/state/v2/state_trie.go rename to beacon-chain/state-native/v2/state_trie.go index ad66b60798..1714268843 100644 --- a/beacon-chain/state/v2/state_trie.go +++ b/beacon-chain/state-native/v2/state_trie.go @@ -8,13 +8,12 @@ import ( "sort" "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/sharedstate" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/features" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" @@ -27,13 +26,6 @@ import ( "google.golang.org/protobuf/proto" ) -var ( - stateCount = promauto.NewGauge(prometheus.GaugeOpts{ - Name: "beacon_state_altair_count", - Help: "Count the number of active beacon state objects.", - }) -) - // InitializeFromProto the beacon state from a protobuf representation. func InitializeFromProto(st *ethpb.BeaconStateAltair) (*BeaconState, error) { return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateAltair)) @@ -143,7 +135,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) // New in Altair. b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - stateCount.Inc() + sharedstate.StateCount.Inc() return b, nil } @@ -188,7 +180,7 @@ func Initialize() (*BeaconState, error) { b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) // New in Altair. b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - stateCount.Inc() + sharedstate.StateCount.Inc() return b, nil } @@ -283,7 +275,7 @@ func (b *BeaconState) Copy() state.BeaconState { } } - stateCount.Inc() + sharedstate.StateCount.Inc() // Finalizer runs when dst is being destroyed in garbage collection. runtime.SetFinalizer(dst, func(b *BeaconState) { for field, v := range b.sharedFieldReferences { @@ -300,7 +292,7 @@ func (b *BeaconState) Copy() state.BeaconState { delete(b.sharedFieldReferences, field) delete(b.stateFieldLeaves, field) } - stateCount.Sub(1) + sharedstate.StateCount.Sub(1) }) return dst diff --git a/beacon-chain/state-native/v2/state_trie_test.go b/beacon-chain/state-native/v2/state_trie_test.go new file mode 100644 index 0000000000..21a6d83967 --- /dev/null +++ b/beacon-chain/state-native/v2/state_trie_test.go @@ -0,0 +1,168 @@ +package v2 + +import ( + "strconv" + "sync" + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/config/features" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestMain(m *testing.M) { + resetCfg := features.InitWithReset(&features.Flags{EnableBalanceTrieComputation: true}) + defer resetCfg() + m.Run() +} + +func TestValidatorMap_DistinctCopy(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + handler := stateutil.NewValMapHandler(vals) + newHandler := handler.Copy() + wantedPubkey := strconv.Itoa(22) + handler.Set(bytesutil.ToBytes48([]byte(wantedPubkey)), 27) + val1, _ := handler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) + val2, _ := newHandler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) + assert.NotEqual(t, val1, val2, "Values are supposed to be unequal due to copy") +} + +func TestInitializeFromProto(t *testing.T) { + type test struct { + name string + state *ethpb.BeaconStateAltair + error string + } + initTests := []test{ + { + name: "nil state", + state: nil, + error: "received nil state", + }, + { + name: "nil validators", + state: ðpb.BeaconStateAltair{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateAltair{}, + }, + // TODO: Add full state. Blocked by testutil migration. + } + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + _, err := InitializeFromProto(tt.state) + if tt.error != "" { + require.ErrorContains(t, tt.error, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestBeaconState_NoDeadlock(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + st, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{ + Validators: vals, + }) + assert.NoError(t, err) + + wg := new(sync.WaitGroup) + + wg.Add(1) + go func() { + // Continuously lock and unlock the state + // by acquiring the lock. + for i := 0; i < 1000; i++ { + for _, f := range st.stateFieldLeaves { + f.Lock() + if f.Empty() { + f.InsertFieldLayer(make([][]*[32]byte, 10)) + } + f.Unlock() + f.FieldReference().AddRef() + } + } + wg.Done() + }() + // Constantly read from the offending portion + // of the code to ensure there is no possible + // recursive read locking. + for i := 0; i < 1000; i++ { + go func() { + _ = st.FieldReferencesCount() + }() + } + // Test will not terminate in the event of a deadlock. + wg.Wait() +} + +func TestInitializeFromProtoUnsafe(t *testing.T) { + type test struct { + name string + state *ethpb.BeaconStateAltair + error string + } + initTests := []test{ + { + name: "nil state", + state: nil, + error: "received nil state", + }, + { + name: "nil validators", + state: ðpb.BeaconStateAltair{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateAltair{}, + }, + // TODO: Add full state. Blocked by testutil migration. + } + _ = initTests +} diff --git a/beacon-chain/state/v2/types.go b/beacon-chain/state-native/v2/types.go similarity index 97% rename from beacon-chain/state/v2/types.go rename to beacon-chain/state-native/v2/types.go index 0b967b5e67..69893f5793 100644 --- a/beacon-chain/state/v2/types.go +++ b/beacon-chain/state-native/v2/types.go @@ -2,7 +2,7 @@ package v2 import ( "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/params" ) diff --git a/beacon-chain/state/v3/BUILD.bazel b/beacon-chain/state-native/v3/BUILD.bazel similarity index 84% rename from beacon-chain/state/v3/BUILD.bazel rename to beacon-chain/state-native/v3/BUILD.bazel index f7371ec165..ede8553f81 100644 --- a/beacon-chain/state/v3/BUILD.bazel +++ b/beacon-chain/state-native/v3/BUILD.bazel @@ -37,18 +37,19 @@ go_library( "//config:mainnet": ["beacon_state_mainnet.go"], "//config:minimal": ["beacon_state_minimal.go"], }), - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v3", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v3", visibility = [ "//beacon-chain:__subpackages__", "//testing/util:__pkg__", ], deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/custom-types:go_default_library", - "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/sharedstate:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", + "//beacon-chain/state-native/fieldtrie:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", + "//beacon-chain/state-native/v1:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -83,9 +84,9 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native/stateutil:go_default_library", + "//beacon-chain/state-native/types:go_default_library", + "//beacon-chain/state-native/v1:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -108,7 +109,7 @@ ssz_gen_marshal( "//config:minimal": ["beacon_state_minimal.go"], }), includes = [ - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", "//config/fieldparams:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", diff --git a/beacon-chain/state/v3/beacon_state_mainnet.go b/beacon-chain/state-native/v3/beacon_state_mainnet.go similarity index 91% rename from beacon-chain/state/v3/beacon_state_mainnet.go rename to beacon-chain/state-native/v3/beacon_state_mainnet.go index 18d56d5d7a..d89b9bb8d1 100644 --- a/beacon-chain/state/v3/beacon_state_mainnet.go +++ b/beacon-chain/state-native/v3/beacon_state_mainnet.go @@ -7,10 +7,10 @@ import ( eth2types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v3/beacon_state_minimal.go b/beacon-chain/state-native/v3/beacon_state_minimal.go similarity index 91% rename from beacon-chain/state/v3/beacon_state_minimal.go rename to beacon-chain/state-native/v3/beacon_state_minimal.go index 935fcf8b7d..b109c08811 100644 --- a/beacon-chain/state/v3/beacon_state_minimal.go +++ b/beacon-chain/state-native/v3/beacon_state_minimal.go @@ -7,10 +7,10 @@ import ( eth2types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v3/deprecated_getters.go b/beacon-chain/state-native/v3/deprecated_getters.go similarity index 100% rename from beacon-chain/state/v3/deprecated_getters.go rename to beacon-chain/state-native/v3/deprecated_getters.go diff --git a/beacon-chain/state/v3/deprecated_getters_test.go b/beacon-chain/state-native/v3/deprecated_getters_test.go similarity index 100% rename from beacon-chain/state/v3/deprecated_getters_test.go rename to beacon-chain/state-native/v3/deprecated_getters_test.go diff --git a/beacon-chain/state/v3/deprecated_setters.go b/beacon-chain/state-native/v3/deprecated_setters.go similarity index 100% rename from beacon-chain/state/v3/deprecated_setters.go rename to beacon-chain/state-native/v3/deprecated_setters.go diff --git a/beacon-chain/state/v3/deprecated_setters_test.go b/beacon-chain/state-native/v3/deprecated_setters_test.go similarity index 100% rename from beacon-chain/state/v3/deprecated_setters_test.go rename to beacon-chain/state-native/v3/deprecated_setters_test.go diff --git a/beacon-chain/state/v3/field_roots.go b/beacon-chain/state-native/v3/field_roots.go similarity index 91% rename from beacon-chain/state/v3/field_roots.go rename to beacon-chain/state-native/v3/field_roots.go index 51fa71af6e..07a93ef098 100644 --- a/beacon-chain/state/v3/field_roots.go +++ b/beacon-chain/state-native/v3/field_roots.go @@ -4,7 +4,7 @@ import ( "context" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" "github.com/prysmaticlabs/prysm/config/features" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v3/generated.ssz.go b/beacon-chain/state-native/v3/generated.ssz.go similarity index 100% rename from beacon-chain/state/v3/generated.ssz.go rename to beacon-chain/state-native/v3/generated.ssz.go diff --git a/beacon-chain/state/v3/getters_block.go b/beacon-chain/state-native/v3/getters_block.go similarity index 81% rename from beacon-chain/state/v3/getters_block.go rename to beacon-chain/state-native/v3/getters_block.go index d7b515e073..66358c91e9 100644 --- a/beacon-chain/state/v3/getters_block.go +++ b/beacon-chain/state-native/v3/getters_block.go @@ -3,8 +3,7 @@ package v3 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -46,7 +45,7 @@ func (b *BeaconState) latestBlockHeaderInternal() *ethpb.BeaconBlockHeader { } // BlockRoots kept track of in the beacon state. -func (b *BeaconState) BlockRoots() *[fieldparams.BlockRootsLength][32]byte { +func (b *BeaconState) BlockRoots() [][]byte { if b.blockRoots == nil { return nil } @@ -54,8 +53,12 @@ func (b *BeaconState) BlockRoots() *[fieldparams.BlockRootsLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - roots := [fieldparams.BlockRootsLength][32]byte(*b.blockRootsInternal()) - return &roots + rootsArr := b.blockRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + return roots } // blockRootsInternal kept track of in the beacon state. @@ -66,15 +69,19 @@ func (b *BeaconState) blockRootsInternal() *customtypes.BlockRoots { // BlockRootAtIndex retrieves a specific block root based on an // input index value. -func (b *BeaconState) BlockRootAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { if b.blockRoots == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.blockRootAtIndex(idx) + r, err := b.blockRootAtIndex(idx) + if err != nil { + return nil, err + } + return r[:], nil } // blockRootAtIndex retrieves a specific block root based on an diff --git a/beacon-chain/state/v3/getters_block_test.go b/beacon-chain/state-native/v3/getters_block_test.go similarity index 96% rename from beacon-chain/state/v3/getters_block_test.go rename to beacon-chain/state-native/v3/getters_block_test.go index f929623f5d..24cc360983 100644 --- a/beacon-chain/state/v3/getters_block_test.go +++ b/beacon-chain/state-native/v3/getters_block_test.go @@ -29,7 +29,7 @@ func TestBeaconState_BlockRoots(t *testing.T) { s, err := InitializeFromProto(ðpb.BeaconStateMerge{}) require.NoError(t, err) got := s.BlockRoots() - require.DeepEqual(t, [fieldparams.BlockRootsLength][32]byte{}, *got) + require.DeepEqual(t, [fieldparams.BlockRootsLength][32]byte{}, got) want := [fieldparams.BlockRootsLength][32]byte{{'a'}} bRoots := make([][]byte, len(want)) @@ -40,11 +40,11 @@ func TestBeaconState_BlockRoots(t *testing.T) { s, err = InitializeFromProto(ðpb.BeaconStateMerge{BlockRoots: bRoots}) require.NoError(t, err) got = s.BlockRoots() - require.DeepEqual(t, want, *got) + require.DeepEqual(t, want, got) // Test copy does not mutate. got[0][0] = 'b' - require.DeepNotEqual(t, want, *got) + require.DeepNotEqual(t, want, got) } func TestBeaconState_BlockRootAtIndex(t *testing.T) { diff --git a/beacon-chain/state/v3/getters_checkpoint.go b/beacon-chain/state-native/v3/getters_checkpoint.go similarity index 100% rename from beacon-chain/state/v3/getters_checkpoint.go rename to beacon-chain/state-native/v3/getters_checkpoint.go diff --git a/beacon-chain/state/v3/getters_eth1.go b/beacon-chain/state-native/v3/getters_eth1.go similarity index 100% rename from beacon-chain/state/v3/getters_eth1.go rename to beacon-chain/state-native/v3/getters_eth1.go diff --git a/beacon-chain/state/v3/getters_misc.go b/beacon-chain/state-native/v3/getters_misc.go similarity index 90% rename from beacon-chain/state/v3/getters_misc.go rename to beacon-chain/state-native/v3/getters_misc.go index 8aa97dc5cf..8592b55c34 100644 --- a/beacon-chain/state/v3/getters_misc.go +++ b/beacon-chain/state-native/v3/getters_misc.go @@ -4,7 +4,7 @@ import ( "time" types "github.com/prysmaticlabs/eth2-types" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime/version" @@ -25,11 +25,12 @@ func (b *BeaconState) genesisTimeInternal() uint64 { } // GenesisValidatorRoot of the beacon state. -func (b *BeaconState) GenesisValidatorRoot() [32]byte { +func (b *BeaconState) GenesisValidatorRoot() []byte { b.lock.RLock() defer b.lock.RUnlock() - return b.genesisValidatorRootInternal() + r := b.genesisValidatorRootInternal() + return r[:] } // genesisValidatorRootInternal of the beacon state. @@ -124,7 +125,7 @@ func (b *BeaconState) forkInternal() *ethpb.Fork { } // HistoricalRoots based on epochs stored in the beacon state. -func (b *BeaconState) HistoricalRoots() [][32]byte { +func (b *BeaconState) HistoricalRoots() [][]byte { if b.historicalRoots == nil { return nil } @@ -132,7 +133,13 @@ func (b *BeaconState) HistoricalRoots() [][32]byte { b.lock.RLock() defer b.lock.RUnlock() - return b.historicalRootsInternal() + rootsArr := b.historicalRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + + return roots } // historicalRootsInternal based on epochs stored in the beacon state. diff --git a/beacon-chain/state/v3/getters_participation.go b/beacon-chain/state-native/v3/getters_participation.go similarity index 100% rename from beacon-chain/state/v3/getters_participation.go rename to beacon-chain/state-native/v3/getters_participation.go diff --git a/beacon-chain/state/v3/getters_payload_header.go b/beacon-chain/state-native/v3/getters_payload_header.go similarity index 100% rename from beacon-chain/state/v3/getters_payload_header.go rename to beacon-chain/state-native/v3/getters_payload_header.go diff --git a/beacon-chain/state/v3/getters_randao.go b/beacon-chain/state-native/v3/getters_randao.go similarity index 75% rename from beacon-chain/state/v3/getters_randao.go rename to beacon-chain/state-native/v3/getters_randao.go index fdad917b22..cede515ca4 100644 --- a/beacon-chain/state/v3/getters_randao.go +++ b/beacon-chain/state-native/v3/getters_randao.go @@ -3,12 +3,11 @@ package v3 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ) // RandaoMixes of block proposers on the beacon chain. -func (b *BeaconState) RandaoMixes() *[fieldparams.RandaoMixesLength][32]byte { +func (b *BeaconState) RandaoMixes() [][]byte { if b.randaoMixes == nil { return nil } @@ -16,8 +15,13 @@ func (b *BeaconState) RandaoMixes() *[fieldparams.RandaoMixesLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - mixes := [fieldparams.RandaoMixesLength][32]byte(*b.randaoMixesInternal()) - return &mixes + mixesArr := b.randaoMixesInternal() + mixes := make([][]byte, len(mixesArr)) + for i, m := range mixesArr { + mixes[i] = m[:] + } + + return mixes } // randaoMixesInternal of block proposers on the beacon chain. @@ -28,15 +32,19 @@ func (b *BeaconState) randaoMixesInternal() *customtypes.RandaoMixes { // RandaoMixAtIndex retrieves a specific block root based on an // input index value. -func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { if b.randaoMixes == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.randaoMixAtIndex(idx) + m, err := b.randaoMixAtIndex(idx) + if err != nil { + return nil, err + } + return m[:], nil } // randaoMixAtIndex retrieves a specific block root based on an diff --git a/beacon-chain/state/v3/getters_state.go b/beacon-chain/state-native/v3/getters_state.go similarity index 88% rename from beacon-chain/state/v3/getters_state.go rename to beacon-chain/state-native/v3/getters_state.go index 688b6b5884..0e64571b4d 100644 --- a/beacon-chain/state/v3/getters_state.go +++ b/beacon-chain/state-native/v3/getters_state.go @@ -4,8 +4,7 @@ import ( "fmt" "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -148,7 +147,7 @@ func (b *BeaconState) toProtoNoLock() interface{} { } // StateRoots kept track of in the beacon state. -func (b *BeaconState) StateRoots() *[fieldparams.StateRootsLength][32]byte { +func (b *BeaconState) StateRoots() [][]byte { if b.stateRoots == nil { return nil } @@ -156,8 +155,13 @@ func (b *BeaconState) StateRoots() *[fieldparams.StateRootsLength][32]byte { b.lock.RLock() defer b.lock.RUnlock() - roots := [fieldparams.StateRootsLength][32]byte(*b.stateRootsInternal()) - return &roots + rootsArr := b.stateRootsInternal() + roots := make([][]byte, len(rootsArr)) + for i, r := range rootsArr { + roots[i] = r[:] + } + + return roots } // stateRootsInternal kept track of in the beacon state. @@ -168,15 +172,19 @@ func (b *BeaconState) stateRootsInternal() *customtypes.StateRoots { // StateRootAtIndex retrieves a specific state root based on an // input index value. -func (b *BeaconState) StateRootAtIndex(idx uint64) ([32]byte, error) { +func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { if b.stateRoots == nil { - return [32]byte{}, nil + return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.stateRootAtIndex(idx) + r, err := b.stateRootAtIndex(idx) + if err != nil { + return nil, err + } + return r[:], nil } // stateRootAtIndex retrieves a specific state root based on an @@ -199,3 +207,14 @@ func ProtobufBeaconState(s interface{}) (*ethpb.BeaconStateMerge, error) { } return pbState, nil } + +// InnerStateUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) InnerStateUnsafe() interface{} { + return b.ToProtoUnsafe() +} + +// CloneInnerState the beacon state into a protobuf for usage. +func (b *BeaconState) CloneInnerState() interface{} { + return nil +} diff --git a/beacon-chain/state/v3/getters_sync_committee.go b/beacon-chain/state-native/v3/getters_sync_committee.go similarity index 100% rename from beacon-chain/state/v3/getters_sync_committee.go rename to beacon-chain/state-native/v3/getters_sync_committee.go diff --git a/beacon-chain/state/v3/getters_test.go b/beacon-chain/state-native/v3/getters_test.go similarity index 100% rename from beacon-chain/state/v3/getters_test.go rename to beacon-chain/state-native/v3/getters_test.go diff --git a/beacon-chain/state/v3/getters_validator.go b/beacon-chain/state-native/v3/getters_validator.go similarity index 98% rename from beacon-chain/state/v3/getters_validator.go rename to beacon-chain/state-native/v3/getters_validator.go index 2e9541f977..d1b8a4c1ef 100644 --- a/beacon-chain/state/v3/getters_validator.go +++ b/beacon-chain/state-native/v3/getters_validator.go @@ -5,8 +5,8 @@ import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state-native/v3/getters_validator_test.go b/beacon-chain/state-native/v3/getters_validator_test.go new file mode 100644 index 0000000000..ce9ef604de --- /dev/null +++ b/beacon-chain/state-native/v3/getters_validator_test.go @@ -0,0 +1,20 @@ +package v3_test + +import ( + "testing" + + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v1" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice(t *testing.T) { + st, err := v1.InitializeFromProtoUnsafe(ðpb.BeaconState{ + Validators: nil, + }) + require.NoError(t, err) + + _, err = st.ValidatorAtIndexReadOnly(0) + assert.Equal(t, v1.ErrNilValidatorsInState, err) +} diff --git a/beacon-chain/state/v3/proofs.go b/beacon-chain/state-native/v3/proofs.go similarity index 96% rename from beacon-chain/state/v3/proofs.go rename to beacon-chain/state-native/v3/proofs.go index 408bc9f096..57b300b149 100644 --- a/beacon-chain/state/v3/proofs.go +++ b/beacon-chain/state-native/v3/proofs.go @@ -3,7 +3,7 @@ package v3 import ( "encoding/binary" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) diff --git a/beacon-chain/state-native/v3/proofs_test.go b/beacon-chain/state-native/v3/proofs_test.go new file mode 100644 index 0000000000..d26665a995 --- /dev/null +++ b/beacon-chain/state-native/v3/proofs_test.go @@ -0,0 +1,75 @@ +package v3_test + +import ( + "context" + "testing" + + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-native/v3" + "github.com/prysmaticlabs/prysm/container/trie" + "github.com/prysmaticlabs/prysm/crypto/bls" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestBeaconStateMerkleProofs(t *testing.T) { + ctx := context.Background() + st, _ := util.DeterministicGenesisStateAltair(t, 256) + htr, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + t.Run("current sync committee", func(t *testing.T) { + sc, err := st.CurrentSyncCommittee() + require.NoError(t, err) + + // Verify the Merkle proof. + scRoot, err := sc.HashTreeRoot() + require.NoError(t, err) + proof, err := st.CurrentSyncCommitteeProof() + require.NoError(t, err) + valid := trie.VerifyMerkleProof(htr[:], scRoot[:], v3.CurrentSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, true, valid) + }) + t.Run("next sync committee", func(t *testing.T) { + nextSC, err := st.NextSyncCommittee() + require.NoError(t, err) + proof, err := st.NextSyncCommitteeProof() + require.NoError(t, err) + + // Verify the Merkle proof. + nextSCRoot, err := nextSC.HashTreeRoot() + require.NoError(t, err) + valid := trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v3.NextSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, true, valid) + + // Edit the sync committee. + privKey, err := bls.RandKey() + require.NoError(t, err) + nextSC.AggregatePubkey = privKey.PublicKey().Marshal() + require.NoError(t, st.SetNextSyncCommittee(nextSC)) + + // Verifying the old Merkle proof for the new value should fail. + nextSCRoot, err = nextSC.HashTreeRoot() + require.NoError(t, err) + valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v3.NextSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, false, valid) + + // Generating a new, valid proof should pass. + proof, err = st.NextSyncCommitteeProof() + require.NoError(t, err) + htr, err = st.HashTreeRoot(ctx) + require.NoError(t, err) + valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v3.NextSyncCommitteeGeneralizedIndex(), proof) + require.Equal(t, true, valid) + }) + t.Run("finalized root", func(t *testing.T) { + finalizedRoot := st.FinalizedCheckpoint().Root + + // Verify the Merkle proof. + htr, err = st.HashTreeRoot(ctx) + require.NoError(t, err) + proof, err := st.FinalizedRootProof() + require.NoError(t, err) + gIndex := v3.FinalizedRootGeneralizedIndex() + valid := trie.VerifyMerkleProof(htr[:], finalizedRoot, gIndex, proof) + require.Equal(t, true, valid) + }) +} diff --git a/beacon-chain/state/v3/setters_block.go b/beacon-chain/state-native/v3/setters_block.go similarity index 77% rename from beacon-chain/state/v3/setters_block.go rename to beacon-chain/state-native/v3/setters_block.go index 6badd97036..50e60e87a7 100644 --- a/beacon-chain/state/v3/setters_block.go +++ b/beacon-chain/state-native/v3/setters_block.go @@ -3,9 +3,10 @@ package v3 import ( "fmt" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -21,14 +22,18 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { // SetBlockRoots for the beacon state. Updates the entire // list to a new value by overwriting the previous one. -func (b *BeaconState) SetBlockRoots(val *[fieldparams.BlockRootsLength][32]byte) error { +func (b *BeaconState) SetBlockRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[blockRoots].MinusRef() b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - roots := customtypes.BlockRoots(*val) + var rootsArr [fieldparams.BlockRootsLength][32]byte + for i := 0; i < len(rootsArr); i++ { + rootsArr[i] = bytesutil.ToBytes32(val[i]) + } + roots := customtypes.BlockRoots(rootsArr) b.blockRoots = &roots b.markFieldAsDirty(blockRoots) b.rebuildTrie[blockRoots] = true diff --git a/beacon-chain/state/v3/setters_checkpoint.go b/beacon-chain/state-native/v3/setters_checkpoint.go similarity index 100% rename from beacon-chain/state/v3/setters_checkpoint.go rename to beacon-chain/state-native/v3/setters_checkpoint.go diff --git a/beacon-chain/state/v3/setters_eth1.go b/beacon-chain/state-native/v3/setters_eth1.go similarity index 95% rename from beacon-chain/state/v3/setters_eth1.go rename to beacon-chain/state-native/v3/setters_eth1.go index 4167599ef7..f0b9866fed 100644 --- a/beacon-chain/state/v3/setters_eth1.go +++ b/beacon-chain/state-native/v3/setters_eth1.go @@ -1,7 +1,7 @@ package v3 import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v3/setters_misc.go b/beacon-chain/state-native/v3/setters_misc.go similarity index 90% rename from beacon-chain/state/v3/setters_misc.go rename to beacon-chain/state-native/v3/setters_misc.go index 26b0d4de35..5a0d14f295 100644 --- a/beacon-chain/state/v3/setters_misc.go +++ b/beacon-chain/state-native/v3/setters_misc.go @@ -3,10 +3,11 @@ package v3 import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "google.golang.org/protobuf/proto" ) @@ -49,11 +50,11 @@ func (b *BeaconState) SetGenesisTime(val uint64) error { } // SetGenesisValidatorRoot for the beacon state. -func (b *BeaconState) SetGenesisValidatorRoot(val [32]byte) error { +func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error { b.lock.Lock() defer b.lock.Unlock() - b.genesisValidatorsRoot = val + b.genesisValidatorsRoot = bytesutil.ToBytes32(val) b.markFieldAsDirty(genesisValidatorRoot) return nil } @@ -84,14 +85,18 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error { // SetHistoricalRoots for the beacon state. Updates the entire // list to a new value by overwriting the previous one. -func (b *BeaconState) SetHistoricalRoots(val [][32]byte) error { +func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[historicalRoots].MinusRef() b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - b.historicalRoots = val + roots := make([][32]byte, len(val)) + for i, r := range val { + roots[i] = bytesutil.ToBytes32(r) + } + b.historicalRoots = roots b.markFieldAsDirty(historicalRoots) return nil } diff --git a/beacon-chain/state/v3/setters_participation.go b/beacon-chain/state-native/v3/setters_participation.go similarity index 97% rename from beacon-chain/state/v3/setters_participation.go rename to beacon-chain/state-native/v3/setters_participation.go index b3cca9cd3a..763c0f27a6 100644 --- a/beacon-chain/state/v3/setters_participation.go +++ b/beacon-chain/state-native/v3/setters_participation.go @@ -1,7 +1,7 @@ package v3 import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" ) // SetPreviousParticipationBits for the beacon state. Updates the entire diff --git a/beacon-chain/state/v3/setters_payload_header.go b/beacon-chain/state-native/v3/setters_payload_header.go similarity index 100% rename from beacon-chain/state/v3/setters_payload_header.go rename to beacon-chain/state-native/v3/setters_payload_header.go diff --git a/beacon-chain/state/v3/setters_randao.go b/beacon-chain/state-native/v3/setters_randao.go similarity index 71% rename from beacon-chain/state/v3/setters_randao.go rename to beacon-chain/state-native/v3/setters_randao.go index a9737346f8..083b835f16 100644 --- a/beacon-chain/state/v3/setters_randao.go +++ b/beacon-chain/state-native/v3/setters_randao.go @@ -2,21 +2,26 @@ package v3 import ( "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) // SetRandaoMixes for the beacon state. Updates the entire // randao mixes to a new value by overwriting the previous one. -func (b *BeaconState) SetRandaoMixes(val *[fieldparams.RandaoMixesLength][32]byte) error { +func (b *BeaconState) SetRandaoMixes(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[randaoMixes].MinusRef() b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - mixes := customtypes.RandaoMixes(*val) + var mixesArr [fieldparams.RandaoMixesLength][32]byte + for i := 0; i < len(mixesArr); i++ { + mixesArr[i] = bytesutil.ToBytes32(val[i]) + } + mixes := customtypes.RandaoMixes(mixesArr) b.randaoMixes = &mixes b.markFieldAsDirty(randaoMixes) b.rebuildTrie[randaoMixes] = true @@ -25,7 +30,7 @@ func (b *BeaconState) SetRandaoMixes(val *[fieldparams.RandaoMixesLength][32]byt // UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes // at a specific index to a new value. -func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error { +func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { if uint64(len(b.randaoMixes)) <= idx { return errors.Errorf("invalid index provided %d", idx) } @@ -42,7 +47,7 @@ func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error { b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) } - mixes[idx] = val + mixes[idx] = bytesutil.ToBytes32(val) b.randaoMixes = mixes b.markFieldAsDirty(randaoMixes) b.addDirtyIndices(randaoMixes, []uint64{idx}) diff --git a/beacon-chain/state/v3/setters_state.go b/beacon-chain/state-native/v3/setters_state.go similarity index 75% rename from beacon-chain/state/v3/setters_state.go rename to beacon-chain/state-native/v3/setters_state.go index 6593eb8853..d1fb309d36 100644 --- a/beacon-chain/state/v3/setters_state.go +++ b/beacon-chain/state-native/v3/setters_state.go @@ -2,21 +2,26 @@ package v3 import ( "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" ) // SetStateRoots for the beacon state. Updates the state roots // to a new value by overwriting the previous value. -func (b *BeaconState) SetStateRoots(val *[fieldparams.StateRootsLength][32]byte) error { +func (b *BeaconState) SetStateRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[stateRoots].MinusRef() b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - roots := customtypes.StateRoots(*val) + var rootsArr [fieldparams.StateRootsLength][32]byte + for i := 0; i < len(rootsArr); i++ { + rootsArr[i] = bytesutil.ToBytes32(val[i]) + } + roots := customtypes.StateRoots(rootsArr) b.stateRoots = &roots b.markFieldAsDirty(stateRoots) b.rebuildTrie[stateRoots] = true diff --git a/beacon-chain/state/v3/setters_sync_committee.go b/beacon-chain/state-native/v3/setters_sync_committee.go similarity index 100% rename from beacon-chain/state/v3/setters_sync_committee.go rename to beacon-chain/state-native/v3/setters_sync_committee.go diff --git a/beacon-chain/state/v3/setters_test.go b/beacon-chain/state-native/v3/setters_test.go similarity index 97% rename from beacon-chain/state/v3/setters_test.go rename to beacon-chain/state-native/v3/setters_test.go index db2a6efa31..635a247061 100644 --- a/beacon-chain/state/v3/setters_test.go +++ b/beacon-chain/state-native/v3/setters_test.go @@ -7,8 +7,8 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/state/v3/setters_validator.go b/beacon-chain/state-native/v3/setters_validator.go similarity index 98% rename from beacon-chain/state/v3/setters_validator.go rename to beacon-chain/state-native/v3/setters_validator.go index c696766f1b..1ebce577dd 100644 --- a/beacon-chain/state/v3/setters_validator.go +++ b/beacon-chain/state-native/v3/setters_validator.go @@ -3,7 +3,7 @@ package v3 import ( "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/v3/state_trie.go b/beacon-chain/state-native/v3/state_trie.go similarity index 96% rename from beacon-chain/state/v3/state_trie.go rename to beacon-chain/state-native/v3/state_trie.go index d6dee64b51..d6fef13fb4 100644 --- a/beacon-chain/state/v3/state_trie.go +++ b/beacon-chain/state-native/v3/state_trie.go @@ -6,13 +6,12 @@ import ( "sort" "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/sharedstate" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/slice" @@ -24,13 +23,6 @@ import ( "google.golang.org/protobuf/proto" ) -var ( - stateCount = promauto.NewGauge(prometheus.GaugeOpts{ - Name: "beacon_state_merge_count", - Help: "Count the number of active beacon state objects.", - }) -) - // InitializeFromProto the beacon state from a protobuf representation. func InitializeFromProto(st *ethpb.BeaconStateMerge) (*BeaconState, error) { return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateMerge)) @@ -120,7 +112,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateMerge) (*BeaconState, error) b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) // New in Altair. b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) b.sharedFieldReferences[latestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Merge. - stateCount.Inc() + sharedstate.StateCount.Inc() return b, nil } @@ -166,7 +158,7 @@ func Initialize() (*BeaconState, error) { b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) b.sharedFieldReferences[latestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Merge. - stateCount.Inc() + sharedstate.StateCount.Inc() return b, nil } @@ -261,7 +253,7 @@ func (b *BeaconState) Copy() state.BeaconState { } } } - stateCount.Inc() + sharedstate.StateCount.Inc() // Finalizer runs when dst is being destroyed in garbage collection. runtime.SetFinalizer(dst, func(b *BeaconState) { for field, v := range b.sharedFieldReferences { @@ -278,7 +270,7 @@ func (b *BeaconState) Copy() state.BeaconState { delete(b.sharedFieldReferences, field) delete(b.stateFieldLeaves, field) } - stateCount.Sub(1) + sharedstate.StateCount.Sub(1) }) return dst diff --git a/beacon-chain/state-native/v3/state_trie_test.go b/beacon-chain/state-native/v3/state_trie_test.go new file mode 100644 index 0000000000..5ec8aad22e --- /dev/null +++ b/beacon-chain/state-native/v3/state_trie_test.go @@ -0,0 +1,167 @@ +package v3 + +import ( + "strconv" + "sync" + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/stateutil" + "github.com/prysmaticlabs/prysm/config/features" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestMain(m *testing.M) { + resetCfg := features.InitWithReset(&features.Flags{EnableBalanceTrieComputation: true}) + defer resetCfg() + m.Run() +} + +func TestValidatorMap_DistinctCopy(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + handler := stateutil.NewValMapHandler(vals) + newHandler := handler.Copy() + wantedPubkey := strconv.Itoa(22) + handler.Set(bytesutil.ToBytes48([]byte(wantedPubkey)), 27) + val1, _ := handler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) + val2, _ := newHandler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) + assert.NotEqual(t, val1, val2, "Values are supposed to be unequal due to copy") +} + +func TestInitializeFromProto(t *testing.T) { + type test struct { + name string + state *ethpb.BeaconStateMerge + error string + } + initTests := []test{ + { + name: "nil state", + state: nil, + error: "received nil state", + }, + { + name: "nil validators", + state: ðpb.BeaconStateMerge{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateMerge{}, + }, + } + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + _, err := InitializeFromProto(tt.state) + if tt.error != "" { + require.ErrorContains(t, tt.error, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestBeaconState_NoDeadlock(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + st, err := InitializeFromProtoUnsafe(ðpb.BeaconStateMerge{ + Validators: vals, + }) + assert.NoError(t, err) + + wg := new(sync.WaitGroup) + + wg.Add(1) + go func() { + // Continuously lock and unlock the state + // by acquiring the lock. + for i := 0; i < 1000; i++ { + for _, f := range st.stateFieldLeaves { + f.Lock() + if f.Empty() { + f.InsertFieldLayer(make([][]*[32]byte, 10)) + } + f.Unlock() + f.FieldReference().AddRef() + } + } + wg.Done() + }() + // Constantly read from the offending portion + // of the code to ensure there is no possible + // recursive read locking. + for i := 0; i < 1000; i++ { + go func() { + _ = st.FieldReferencesCount() + }() + } + // Test will not terminate in the event of a deadlock. + wg.Wait() +} + +func TestInitializeFromProtoUnsafe(t *testing.T) { + type test struct { + name string + state *ethpb.BeaconStateMerge + error string + } + initTests := []test{ + { + name: "nil state", + state: nil, + error: "received nil state", + }, + { + name: "nil validators", + state: ðpb.BeaconStateMerge{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateMerge{}, + }, + // TODO: Add full state. Blocked by testutil migration. + } + _ = initTests +} diff --git a/beacon-chain/state/v3/types.go b/beacon-chain/state-native/v3/types.go similarity index 97% rename from beacon-chain/state/v3/types.go rename to beacon-chain/state-native/v3/types.go index 7f8bbe81d1..bb387b2b2b 100644 --- a/beacon-chain/state/v3/types.go +++ b/beacon-chain/state-native/v3/types.go @@ -2,7 +2,7 @@ package v3 import ( "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native/types" "github.com/prysmaticlabs/prysm/config/params" ) diff --git a/beacon-chain/state-proto/fieldtrie/BUILD.bazel b/beacon-chain/state-proto/fieldtrie/BUILD.bazel new file mode 100644 index 0000000000..5dd3e53334 --- /dev/null +++ b/beacon-chain/state-proto/fieldtrie/BUILD.bazel @@ -0,0 +1,40 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "field_trie.go", + "field_trie_helpers.go", + ], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie", + visibility = ["//beacon-chain:__subpackages__"], + deps = [ + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//crypto/hash:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "@com_github_pkg_errors//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "field_trie_test.go", + "helpers_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//config/params:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + ], +) diff --git a/beacon-chain/state-proto/fieldtrie/field_trie.go b/beacon-chain/state-proto/fieldtrie/field_trie.go new file mode 100644 index 0000000000..030e5cd512 --- /dev/null +++ b/beacon-chain/state-proto/fieldtrie/field_trie.go @@ -0,0 +1,200 @@ +package fieldtrie + +import ( + "reflect" + "sync" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" +) + +// FieldTrie is the representation of the representative +// trie of the particular field. +type FieldTrie struct { + *sync.RWMutex + reference *stateutil.Reference + fieldLayers [][]*[32]byte + field types.FieldIndex + dataType types.DataType + length uint64 + numOfElems int +} + +// NewFieldTrie is the constructor for the field trie data structure. It creates the corresponding +// trie according to the given parameters. Depending on whether the field is a basic/composite array +// which is either fixed/variable length, it will appropriately determine the trie. +func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) (*FieldTrie, error) { + if elements == nil { + return &FieldTrie{ + field: field, + dataType: dataType, + reference: stateutil.NewRef(1), + RWMutex: new(sync.RWMutex), + length: length, + numOfElems: 0, + }, nil + } + fieldRoots, err := fieldConverters(field, []uint64{}, elements, true) + if err != nil { + return nil, err + } + if err := validateElements(field, dataType, elements, length); err != nil { + return nil, err + } + switch dataType { + case types.BasicArray: + fl, err := stateutil.ReturnTrieLayer(fieldRoots, length) + if err != nil { + return nil, err + } + return &FieldTrie{ + fieldLayers: fl, + field: field, + dataType: dataType, + reference: stateutil.NewRef(1), + RWMutex: new(sync.RWMutex), + length: length, + numOfElems: reflect.ValueOf(elements).Len(), + }, nil + case types.CompositeArray, types.CompressedArray: + return &FieldTrie{ + fieldLayers: stateutil.ReturnTrieLayerVariable(fieldRoots, length), + field: field, + dataType: dataType, + reference: stateutil.NewRef(1), + RWMutex: new(sync.RWMutex), + length: length, + numOfElems: reflect.ValueOf(elements).Len(), + }, nil + default: + return nil, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(dataType).Name()) + } + +} + +// RecomputeTrie rebuilds the affected branches in the trie according to the provided +// changed indices and elements. This recomputes the trie according to the particular +// field the trie is based on. +func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]byte, error) { + f.Lock() + defer f.Unlock() + var fieldRoot [32]byte + if len(indices) == 0 { + return f.TrieRoot() + } + fieldRoots, err := fieldConverters(f.field, indices, elements, false) + if err != nil { + return [32]byte{}, err + } + if err := f.validateIndices(indices); err != nil { + return [32]byte{}, err + } + switch f.dataType { + case types.BasicArray: + fieldRoot, f.fieldLayers, err = stateutil.RecomputeFromLayer(fieldRoots, indices, f.fieldLayers) + if err != nil { + return [32]byte{}, err + } + f.numOfElems = reflect.ValueOf(elements).Len() + return fieldRoot, nil + case types.CompositeArray: + fieldRoot, f.fieldLayers, err = stateutil.RecomputeFromLayerVariable(fieldRoots, indices, f.fieldLayers) + if err != nil { + return [32]byte{}, err + } + f.numOfElems = reflect.ValueOf(elements).Len() + return stateutil.AddInMixin(fieldRoot, uint64(len(f.fieldLayers[0]))) + case types.CompressedArray: + numOfElems, err := f.field.ElemsInChunk() + if err != nil { + return [32]byte{}, err + } + // We remove the duplicates here in order to prevent + // duplicated insertions into the trie. + newIndices := []uint64{} + indexExists := make(map[uint64]bool) + newRoots := make([][32]byte, 0, len(fieldRoots)/int(numOfElems)) + for i, idx := range indices { + startIdx := idx / numOfElems + if indexExists[startIdx] { + continue + } + newIndices = append(newIndices, startIdx) + indexExists[startIdx] = true + newRoots = append(newRoots, fieldRoots[i]) + } + fieldRoot, f.fieldLayers, err = stateutil.RecomputeFromLayerVariable(newRoots, newIndices, f.fieldLayers) + if err != nil { + return [32]byte{}, err + } + f.numOfElems = reflect.ValueOf(elements).Len() + return stateutil.AddInMixin(fieldRoot, uint64(f.numOfElems)) + default: + return [32]byte{}, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(f.dataType).Name()) + } +} + +// CopyTrie copies the references to the elements the trie +// is built on. +func (f *FieldTrie) CopyTrie() *FieldTrie { + if f.fieldLayers == nil { + return &FieldTrie{ + field: f.field, + dataType: f.dataType, + reference: stateutil.NewRef(1), + RWMutex: new(sync.RWMutex), + length: f.length, + numOfElems: f.numOfElems, + } + } + dstFieldTrie := make([][]*[32]byte, len(f.fieldLayers)) + for i, layer := range f.fieldLayers { + dstFieldTrie[i] = make([]*[32]byte, len(layer)) + copy(dstFieldTrie[i], layer) + } + return &FieldTrie{ + fieldLayers: dstFieldTrie, + field: f.field, + dataType: f.dataType, + reference: stateutil.NewRef(1), + RWMutex: new(sync.RWMutex), + length: f.length, + numOfElems: f.numOfElems, + } +} + +// TrieRoot returns the corresponding root of the trie. +func (f *FieldTrie) TrieRoot() ([32]byte, error) { + switch f.dataType { + case types.BasicArray: + return *f.fieldLayers[len(f.fieldLayers)-1][0], nil + case types.CompositeArray: + trieRoot := *f.fieldLayers[len(f.fieldLayers)-1][0] + return stateutil.AddInMixin(trieRoot, uint64(len(f.fieldLayers[0]))) + case types.CompressedArray: + trieRoot := *f.fieldLayers[len(f.fieldLayers)-1][0] + return stateutil.AddInMixin(trieRoot, uint64(f.numOfElems)) + default: + return [32]byte{}, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(f.dataType).Name()) + } +} + +// FieldReference returns the underlying field reference +// object for the trie. +func (f *FieldTrie) FieldReference() *stateutil.Reference { + return f.reference +} + +// Empty checks whether the underlying field trie is +// empty or not. +func (f *FieldTrie) Empty() bool { + return f == nil || len(f.fieldLayers) == 0 +} + +// InsertFieldLayer manually inserts a field layer. This method +// bypasses the normal method of field computation, it is only +// meant to be used in tests. +func (f *FieldTrie) InsertFieldLayer(layer [][]*[32]byte) { + f.fieldLayers = layer +} diff --git a/beacon-chain/state-proto/fieldtrie/field_trie_helpers.go b/beacon-chain/state-proto/fieldtrie/field_trie_helpers.go new file mode 100644 index 0000000000..17c0445858 --- /dev/null +++ b/beacon-chain/state-proto/fieldtrie/field_trie_helpers.go @@ -0,0 +1,295 @@ +package fieldtrie + +import ( + "encoding/binary" + "fmt" + "reflect" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// ProofFromMerkleLayers creates a proof starting at the leaf index of the state Merkle layers. +func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex types.FieldIndex) [][]byte { + // The merkle tree structure looks as follows: + // [[r1, r2, r3, r4], [parent1, parent2], [root]] + proof := make([][]byte, 0) + currentIndex := startingLeafIndex + for i := 0; i < len(layers)-1; i++ { + neighborIdx := currentIndex ^ 1 + neighbor := layers[i][neighborIdx] + proof = append(proof, neighbor) + currentIndex = currentIndex / 2 + } + return proof +} + +func (f *FieldTrie) validateIndices(idxs []uint64) error { + length := f.length + if f.dataType == types.CompressedArray { + comLength, err := f.field.ElemsInChunk() + if err != nil { + return err + } + length *= comLength + } + for _, idx := range idxs { + if idx >= length { + return errors.Errorf("invalid index for field %s: %d >= length %d", f.field.String(version.Phase0), idx, length) + } + } + return nil +} + +func validateElements(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) error { + if dataType == types.CompressedArray { + comLength, err := field.ElemsInChunk() + if err != nil { + return err + } + length *= comLength + } + val := reflect.ValueOf(elements) + if val.Len() > int(length) { + return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(version.Phase0), val.Len(), length) + } + return nil +} + +// fieldConverters converts the corresponding field and the provided elements to the appropriate roots. +func fieldConverters(field types.FieldIndex, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + switch field { + case types.BlockRoots, types.StateRoots, types.RandaoMixes: + val, ok := elements.([][]byte) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([][]byte{}).Name(), reflect.TypeOf(elements).Name()) + } + return handleByteArrays(val, indices, convertAll) + case types.Eth1DataVotes: + val, ok := elements.([]*ethpb.Eth1Data) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]*ethpb.Eth1Data{}).Name(), reflect.TypeOf(elements).Name()) + } + return handleEth1DataSlice(val, indices, convertAll) + case types.Validators: + val, ok := elements.([]*ethpb.Validator) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]*ethpb.Validator{}).Name(), reflect.TypeOf(elements).Name()) + } + return handleValidatorSlice(val, indices, convertAll) + case types.PreviousEpochAttestations, types.CurrentEpochAttestations: + val, ok := elements.([]*ethpb.PendingAttestation) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]*ethpb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name()) + } + return handlePendingAttestation(val, indices, convertAll) + case types.Balances: + val, ok := elements.([]uint64) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]uint64{}).Name(), reflect.TypeOf(elements).Name()) + } + return handleBalanceSlice(val, indices, convertAll) + default: + return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name()) + } +} + +// handleByteArrays computes and returns byte arrays in a slice of root format. +func handleByteArrays(val [][]byte, indices []uint64, convertAll bool) ([][32]byte, error) { + length := len(indices) + if convertAll { + length = len(val) + } + roots := make([][32]byte, 0, length) + rootCreator := func(input []byte) { + newRoot := bytesutil.ToBytes32(input) + roots = append(roots, newRoot) + } + if convertAll { + for i := range val { + rootCreator(val[i]) + } + return roots, nil + } + if len(val) > 0 { + for _, idx := range indices { + if idx > uint64(len(val))-1 { + return nil, fmt.Errorf("index %d greater than number of byte arrays %d", idx, len(val)) + } + rootCreator(val[idx]) + } + } + return roots, nil +} + +// handleValidatorSlice returns the validator indices in a slice of root format. +func handleValidatorSlice(val []*ethpb.Validator, indices []uint64, convertAll bool) ([][32]byte, error) { + length := len(indices) + if convertAll { + length = len(val) + } + roots := make([][32]byte, 0, length) + hasher := hash.CustomSHA256Hasher() + rootCreator := func(input *ethpb.Validator) error { + newRoot, err := stateutil.ValidatorRootWithHasher(hasher, input) + if err != nil { + return err + } + roots = append(roots, newRoot) + return nil + } + if convertAll { + for i := range val { + err := rootCreator(val[i]) + if err != nil { + return nil, err + } + } + return roots, nil + } + if len(val) > 0 { + for _, idx := range indices { + if idx > uint64(len(val))-1 { + return nil, fmt.Errorf("index %d greater than number of validators %d", idx, len(val)) + } + err := rootCreator(val[idx]) + if err != nil { + return nil, err + } + } + } + return roots, nil +} + +// handleEth1DataSlice processes a list of eth1data and indices into the appropriate roots. +func handleEth1DataSlice(val []*ethpb.Eth1Data, indices []uint64, convertAll bool) ([][32]byte, error) { + length := len(indices) + if convertAll { + length = len(val) + } + roots := make([][32]byte, 0, length) + hasher := hash.CustomSHA256Hasher() + rootCreator := func(input *ethpb.Eth1Data) error { + newRoot, err := stateutil.Eth1DataRootWithHasher(hasher, input) + if err != nil { + return err + } + roots = append(roots, newRoot) + return nil + } + if convertAll { + for i := range val { + err := rootCreator(val[i]) + if err != nil { + return nil, err + } + } + return roots, nil + } + if len(val) > 0 { + for _, idx := range indices { + if idx > uint64(len(val))-1 { + return nil, fmt.Errorf("index %d greater than number of items in eth1 data slice %d", idx, len(val)) + } + err := rootCreator(val[idx]) + if err != nil { + return nil, err + } + } + } + return roots, nil +} + +func handlePendingAttestation(val []*ethpb.PendingAttestation, indices []uint64, convertAll bool) ([][32]byte, error) { + length := len(indices) + if convertAll { + length = len(val) + } + roots := make([][32]byte, 0, length) + hasher := hash.CustomSHA256Hasher() + rootCreator := func(input *ethpb.PendingAttestation) error { + newRoot, err := stateutil.PendingAttRootWithHasher(hasher, input) + if err != nil { + return err + } + roots = append(roots, newRoot) + return nil + } + if convertAll { + for i := range val { + err := rootCreator(val[i]) + if err != nil { + return nil, err + } + } + return roots, nil + } + if len(val) > 0 { + for _, idx := range indices { + if idx > uint64(len(val))-1 { + return nil, fmt.Errorf("index %d greater than number of pending attestations %d", idx, len(val)) + } + err := rootCreator(val[idx]) + if err != nil { + return nil, err + } + } + } + return roots, nil +} + +func handleBalanceSlice(val, indices []uint64, convertAll bool) ([][32]byte, error) { + if convertAll { + balancesMarshaling := make([][]byte, 0) + for _, b := range val { + balanceBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(balanceBuf, b) + balancesMarshaling = append(balancesMarshaling, balanceBuf) + } + balancesChunks, err := ssz.PackByChunk(balancesMarshaling) + if err != nil { + return [][32]byte{}, errors.Wrap(err, "could not pack balances into chunks") + } + return balancesChunks, nil + } + if len(val) > 0 { + numOfElems, err := types.Balances.ElemsInChunk() + if err != nil { + return nil, err + } + roots := [][32]byte{} + for _, idx := range indices { + // We split the indexes into their relevant groups. Balances + // are compressed according to 4 values -> 1 chunk. + startIdx := idx / numOfElems + startGroup := startIdx * numOfElems + chunk := [32]byte{} + sizeOfElem := len(chunk) / int(numOfElems) + for i, j := 0, startGroup; j < startGroup+numOfElems; i, j = i+sizeOfElem, j+1 { + wantedVal := uint64(0) + // We are adding chunks in sets of 4, if the set is at the edge of the array + // then you will need to zero out the rest of the chunk. Ex : 41 indexes, + // so 41 % 4 = 1 . There are 3 indexes, which do not exist yet but we + // have to add in as a root. These 3 indexes are then given a 'zero' value. + if int(j) < len(val) { + wantedVal = val[j] + } + binary.LittleEndian.PutUint64(chunk[i:i+sizeOfElem], wantedVal) + } + roots = append(roots, chunk) + } + return roots, nil + } + return [][32]byte{}, nil +} diff --git a/beacon-chain/state-proto/fieldtrie/field_trie_test.go b/beacon-chain/state-proto/fieldtrie/field_trie_test.go new file mode 100644 index 0000000000..e601bffa89 --- /dev/null +++ b/beacon-chain/state-proto/fieldtrie/field_trie_test.go @@ -0,0 +1,79 @@ +package fieldtrie_test + +import ( + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestFieldTrie_NewTrie(t *testing.T) { + newState, _ := util.DeterministicGenesisState(t, 40) + + // 5 represents the enum value of state roots + trie, err := fieldtrie.NewFieldTrie(5, stateTypes.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot)) + require.NoError(t, err) + root, err := stateutil.RootsArrayHashTreeRoot(newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "StateRoots") + require.NoError(t, err) + newRoot, err := trie.TrieRoot() + require.NoError(t, err) + assert.Equal(t, root, newRoot) +} + +func TestFieldTrie_RecomputeTrie(t *testing.T) { + newState, _ := util.DeterministicGenesisState(t, 32) + // 10 represents the enum value of validators + trie, err := fieldtrie.NewFieldTrie(11, stateTypes.CompositeArray, newState.Validators(), params.BeaconConfig().ValidatorRegistryLimit) + require.NoError(t, err) + + changedIdx := []uint64{2, 29} + val1, err := newState.ValidatorAtIndex(10) + require.NoError(t, err) + val2, err := newState.ValidatorAtIndex(11) + require.NoError(t, err) + val1.Slashed = true + val1.ExitEpoch = 20 + + val2.Slashed = true + val2.ExitEpoch = 40 + + changedVals := []*ethpb.Validator{val1, val2} + require.NoError(t, newState.UpdateValidatorAtIndex(types.ValidatorIndex(changedIdx[0]), changedVals[0])) + require.NoError(t, newState.UpdateValidatorAtIndex(types.ValidatorIndex(changedIdx[1]), changedVals[1])) + + expectedRoot, err := stateutil.ValidatorRegistryRoot(newState.Validators()) + require.NoError(t, err) + root, err := trie.RecomputeTrie(changedIdx, newState.Validators()) + require.NoError(t, err) + assert.Equal(t, expectedRoot, root) +} + +func TestFieldTrie_CopyTrieImmutable(t *testing.T) { + newState, _ := util.DeterministicGenesisState(t, 32) + // 12 represents the enum value of randao mixes. + trie, err := fieldtrie.NewFieldTrie(13, stateTypes.BasicArray, newState.RandaoMixes(), uint64(params.BeaconConfig().EpochsPerHistoricalVector)) + require.NoError(t, err) + + newTrie := trie.CopyTrie() + + changedIdx := []uint64{2, 29} + + changedVals := [][32]byte{{'A', 'B'}, {'C', 'D'}} + require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[0], changedVals[0][:])) + require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[1], changedVals[1][:])) + + root, err := trie.RecomputeTrie(changedIdx, newState.RandaoMixes()) + require.NoError(t, err) + newRoot, err := newTrie.TrieRoot() + require.NoError(t, err) + if root == newRoot { + t.Errorf("Wanted roots to be different, but they are the same: %#x", root) + } +} diff --git a/beacon-chain/state/fieldtrie/helpers_test.go b/beacon-chain/state-proto/fieldtrie/helpers_test.go similarity index 95% rename from beacon-chain/state/fieldtrie/helpers_test.go rename to beacon-chain/state-proto/fieldtrie/helpers_test.go index 54666b872a..19d4c6bcc0 100644 --- a/beacon-chain/state/fieldtrie/helpers_test.go +++ b/beacon-chain/state-proto/fieldtrie/helpers_test.go @@ -5,8 +5,8 @@ import ( "sync" "testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/state/genesis/BUILD.bazel b/beacon-chain/state-proto/genesis/BUILD.bazel similarity index 88% rename from beacon-chain/state/genesis/BUILD.bazel rename to beacon-chain/state-proto/genesis/BUILD.bazel index f6ad87381e..278436e6d5 100644 --- a/beacon-chain/state/genesis/BUILD.bazel +++ b/beacon-chain/state-proto/genesis/BUILD.bazel @@ -4,10 +4,10 @@ go_library( name = "go_default_library", srcs = ["genesis.go"], embedsrcs = ["mainnet.ssz.snappy"], - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/genesis", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/genesis", visibility = ["//beacon-chain/db:__subpackages__"], deps = [ - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_golang_snappy//:go_default_library", diff --git a/beacon-chain/state/genesis/genesis.go b/beacon-chain/state-proto/genesis/genesis.go similarity index 92% rename from beacon-chain/state/genesis/genesis.go rename to beacon-chain/state-proto/genesis/genesis.go index 3992f27e42..a1b12c9923 100644 --- a/beacon-chain/state/genesis/genesis.go +++ b/beacon-chain/state-proto/genesis/genesis.go @@ -4,7 +4,7 @@ import ( _ "embed" "github.com/golang/snappy" - state "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + state "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/beacon-chain/state/genesis/genesis_test.go b/beacon-chain/state-proto/genesis/genesis_test.go similarity index 89% rename from beacon-chain/state/genesis/genesis_test.go rename to beacon-chain/state-proto/genesis/genesis_test.go index 59f47c2200..7d1b6048e6 100644 --- a/beacon-chain/state/genesis/genesis_test.go +++ b/beacon-chain/state-proto/genesis/genesis_test.go @@ -3,7 +3,7 @@ package genesis_test import ( "testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/genesis" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/genesis" "github.com/prysmaticlabs/prysm/config/params" ) diff --git a/beacon-chain/state-proto/genesis/mainnet.ssz.snappy b/beacon-chain/state-proto/genesis/mainnet.ssz.snappy new file mode 100644 index 0000000000..55d52c320a Binary files /dev/null and b/beacon-chain/state-proto/genesis/mainnet.ssz.snappy differ diff --git a/beacon-chain/state/stategen/BUILD.bazel b/beacon-chain/state-proto/stategen/BUILD.bazel similarity index 93% rename from beacon-chain/state/stategen/BUILD.bazel rename to beacon-chain/state-proto/stategen/BUILD.bazel index 9a4252acf7..7a0d106f29 100644 --- a/beacon-chain/state/stategen/BUILD.bazel +++ b/beacon-chain/state-proto/stategen/BUILD.bazel @@ -15,7 +15,7 @@ go_library( "service.go", "setter.go", ], - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen", visibility = [ "//beacon-chain:__subpackages__", "//testing/endtoend:__subpackages__", @@ -29,7 +29,7 @@ go_library( "//beacon-chain/core/transition:go_default_library", "//beacon-chain/db:go_default_library", "//beacon-chain/db/filters:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//cache/lru:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", @@ -65,8 +65,8 @@ go_test( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/db:go_default_library", "//beacon-chain/db/testing:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/state-proto/stategen/epoch_boundary_state_cache.go b/beacon-chain/state-proto/stategen/epoch_boundary_state_cache.go new file mode 100644 index 0000000000..8d198090d5 --- /dev/null +++ b/beacon-chain/state-proto/stategen/epoch_boundary_state_cache.go @@ -0,0 +1,155 @@ +package stategen + +import ( + "errors" + "strconv" + "sync" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "k8s.io/client-go/tools/cache" +) + +var ( + // maxCacheSize is 8. That means 8 epochs and roughly an hour + // of no finality can be endured. + maxCacheSize = uint64(8) + errNotSlotRootInfo = errors.New("not slot root info type") + errNotRootStateInfo = errors.New("not root state info type") +) + +// slotRootInfo specifies the slot root info in the epoch boundary state cache. +type slotRootInfo struct { + slot types.Slot + root [32]byte +} + +// slotKeyFn takes the string representation of the slot to be used as key +// to retrieve root. +func slotKeyFn(obj interface{}) (string, error) { + s, ok := obj.(*slotRootInfo) + if !ok { + return "", errNotSlotRootInfo + } + return slotToString(s.slot), nil +} + +// rootStateInfo specifies the root state info in the epoch boundary state cache. +type rootStateInfo struct { + root [32]byte + state state.BeaconState +} + +// rootKeyFn takes the string representation of the block root to be used as key +// to retrieve epoch boundary state. +func rootKeyFn(obj interface{}) (string, error) { + s, ok := obj.(*rootStateInfo) + if !ok { + return "", errNotRootStateInfo + } + return string(s.root[:]), nil +} + +// epochBoundaryState struct with two queues by looking up beacon state by slot or root. +type epochBoundaryState struct { + rootStateCache *cache.FIFO + slotRootCache *cache.FIFO + lock sync.RWMutex +} + +// newBoundaryStateCache creates a new block newBoundaryStateCache for storing and accessing epoch boundary states from +// memory. +func newBoundaryStateCache() *epochBoundaryState { + return &epochBoundaryState{ + rootStateCache: cache.NewFIFO(rootKeyFn), + slotRootCache: cache.NewFIFO(slotKeyFn), + } +} + +// get epoch boundary state by its block root. Returns copied state in state info object if exists. Otherwise returns nil. +func (e *epochBoundaryState) getByRoot(r [32]byte) (*rootStateInfo, bool, error) { + e.lock.RLock() + defer e.lock.RUnlock() + + obj, exists, err := e.rootStateCache.GetByKey(string(r[:])) + if err != nil { + return nil, false, err + } + if !exists { + return nil, false, nil + } + s, ok := obj.(*rootStateInfo) + if !ok { + return nil, false, errNotRootStateInfo + } + + return &rootStateInfo{ + root: r, + state: s.state.Copy(), + }, true, nil +} + +// get epoch boundary state by its slot. Returns copied state in state info object if exists. Otherwise returns nil. +func (e *epochBoundaryState) getBySlot(s types.Slot) (*rootStateInfo, bool, error) { + e.lock.RLock() + defer e.lock.RUnlock() + + obj, exists, err := e.slotRootCache.GetByKey(slotToString(s)) + if err != nil { + return nil, false, err + } + if !exists { + return nil, false, nil + } + info, ok := obj.(*slotRootInfo) + if !ok { + return nil, false, errNotSlotRootInfo + } + + return e.getByRoot(info.root) +} + +// put adds a state to the epoch boundary state cache. This method also trims the +// least recently added state info if the cache size has reached the max cache +// size limit. +func (e *epochBoundaryState) put(r [32]byte, s state.BeaconState) error { + e.lock.Lock() + defer e.lock.Unlock() + + if err := e.slotRootCache.AddIfNotPresent(&slotRootInfo{ + slot: s.Slot(), + root: r, + }); err != nil { + return err + } + if err := e.rootStateCache.AddIfNotPresent(&rootStateInfo{ + root: r, + state: s.Copy(), + }); err != nil { + return err + } + + trim(e.rootStateCache, maxCacheSize) + trim(e.slotRootCache, maxCacheSize) + + return nil +} + +// trim the FIFO queue to the maxSize. +func trim(queue *cache.FIFO, maxSize uint64) { + for s := uint64(len(queue.ListKeys())); s > maxSize; s-- { + if _, err := queue.Pop(popProcessNoopFunc); err != nil { // This never returns an error, but we'll handle anyway for sanity. + panic(err) + } + } +} + +// popProcessNoopFunc is a no-op function that never returns an error. +func popProcessNoopFunc(_ interface{}) error { + return nil +} + +// Converts input uint64 to string. To be used as key for slot to get root. +func slotToString(s types.Slot) string { + return strconv.FormatUint(uint64(s), 10) +} diff --git a/beacon-chain/state-proto/stategen/epoch_boundary_state_cache_test.go b/beacon-chain/state-proto/stategen/epoch_boundary_state_cache_test.go new file mode 100644 index 0000000000..eefb84e715 --- /dev/null +++ b/beacon-chain/state-proto/stategen/epoch_boundary_state_cache_test.go @@ -0,0 +1,71 @@ +package stategen + +import ( + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestEpochBoundaryStateCache_BadSlotKey(t *testing.T) { + _, err := slotKeyFn("sushi") + assert.ErrorContains(t, errNotSlotRootInfo.Error(), err, "Did not get wanted error") +} + +func TestEpochBoundaryStateCache_BadRootKey(t *testing.T) { + _, err := rootKeyFn("noodle") + assert.ErrorContains(t, errNotRootStateInfo.Error(), err, "Did not get wanted error") +} + +func TestEpochBoundaryStateCache_CanSave(t *testing.T) { + e := newBoundaryStateCache() + s, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, s.SetSlot(1)) + r := [32]byte{'a'} + require.NoError(t, e.put(r, s)) + + got, exists, err := e.getByRoot([32]byte{'b'}) + require.NoError(t, err) + assert.Equal(t, false, exists, "Should not exist") + assert.Equal(t, (*rootStateInfo)(nil), got, "Should not exist") + + got, exists, err = e.getByRoot([32]byte{'a'}) + require.NoError(t, err) + assert.Equal(t, true, exists, "Should exist") + assert.DeepSSZEqual(t, s.InnerStateUnsafe(), got.state.InnerStateUnsafe(), "Should have the same state") + + got, exists, err = e.getBySlot(2) + require.NoError(t, err) + assert.Equal(t, false, exists, "Should not exist") + assert.Equal(t, (*rootStateInfo)(nil), got, "Should not exist") + + got, exists, err = e.getBySlot(1) + require.NoError(t, err) + assert.Equal(t, true, exists, "Should exist") + assert.DeepSSZEqual(t, s.InnerStateUnsafe(), got.state.InnerStateUnsafe(), "Should have the same state") +} + +func TestEpochBoundaryStateCache_CanTrim(t *testing.T) { + e := newBoundaryStateCache() + offSet := types.Slot(10) + for i := types.Slot(0); i < offSet.Add(maxCacheSize); i++ { + s, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, s.SetSlot(i)) + r := [32]byte{byte(i)} + require.NoError(t, e.put(r, s)) + } + + assert.Equal(t, int(maxCacheSize), len(e.rootStateCache.ListKeys()), "Did not trim to the correct amount") + assert.Equal(t, int(maxCacheSize), len(e.slotRootCache.ListKeys()), "Did not trim to the correct amount") + for _, l := range e.rootStateCache.List() { + i, ok := l.(*rootStateInfo) + require.Equal(t, true, ok, "Bad type assertion") + if i.state.Slot() < offSet { + t.Error("Did not trim the correct state") + } + } +} diff --git a/beacon-chain/state-proto/stategen/errors.go b/beacon-chain/state-proto/stategen/errors.go new file mode 100644 index 0000000000..2d5049cd54 --- /dev/null +++ b/beacon-chain/state-proto/stategen/errors.go @@ -0,0 +1,7 @@ +package stategen + +import "errors" + +var errUnknownBoundaryState = errors.New("unknown boundary state") +var errUnknownState = errors.New("unknown state") +var errUnknownBlock = errors.New("unknown block") diff --git a/beacon-chain/state-proto/stategen/getter.go b/beacon-chain/state-proto/stategen/getter.go new file mode 100644 index 0000000000..057bc244ff --- /dev/null +++ b/beacon-chain/state-proto/stategen/getter.go @@ -0,0 +1,306 @@ +package stategen + +import ( + "context" + + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "go.opencensus.io/trace" +) + +// HasState returns true if the state exists in cache or in DB. +func (s *State) HasState(ctx context.Context, blockRoot [32]byte) (bool, error) { + has, err := s.HasStateInCache(ctx, blockRoot) + if err != nil { + return false, err + } + if has { + return true, nil + } + return s.beaconDB.HasState(ctx, blockRoot), nil +} + +// HasStateInCache returns true if the state exists in cache. +func (s *State) HasStateInCache(ctx context.Context, blockRoot [32]byte) (bool, error) { + if s.hotStateCache.has(blockRoot) { + return true, nil + } + _, has, err := s.epochBoundaryStateCache.getByRoot(blockRoot) + if err != nil { + return false, err + } + return has, nil +} + +// StateByRootIfCached retrieves a state using the input block root only if the state is already in the cache +func (s *State) StateByRootIfCachedNoCopy(blockRoot [32]byte) state.BeaconState { + if !s.hotStateCache.has(blockRoot) { + return nil + } + state := s.hotStateCache.getWithoutCopy(blockRoot) + return state +} + +// StateByRoot retrieves the state using input block root. +func (s *State) StateByRoot(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.StateByRoot") + defer span.End() + + // Genesis case. If block root is zero hash, short circuit to use genesis cachedState stored in DB. + if blockRoot == params.BeaconConfig().ZeroHash { + return s.beaconDB.GenesisState(ctx) + } + return s.loadStateByRoot(ctx, blockRoot) +} + +// StateByRootInitialSync retrieves the state from the DB for the initial syncing phase. +// It assumes initial syncing using a block list rather than a block tree hence the returned +// state is not copied. +// It invalidates cache for parent root because pre state will get mutated. +// Do not use this method for anything other than initial syncing purpose or block tree is applied. +func (s *State) StateByRootInitialSync(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error) { + // Genesis case. If block root is zero hash, short circuit to use genesis state stored in DB. + if blockRoot == params.BeaconConfig().ZeroHash { + return s.beaconDB.GenesisState(ctx) + } + + // To invalidate cache for parent root because pre state will get mutated. + defer s.hotStateCache.delete(blockRoot) + + if s.hotStateCache.has(blockRoot) { + return s.hotStateCache.getWithoutCopy(blockRoot), nil + } + + cachedInfo, ok, err := s.epochBoundaryStateCache.getByRoot(blockRoot) + if err != nil { + return nil, err + } + if ok { + return cachedInfo.state, nil + } + + startState, err := s.lastAncestorState(ctx, blockRoot) + if err != nil { + return nil, errors.Wrap(err, "could not get ancestor state") + } + if startState == nil || startState.IsNil() { + return nil, errUnknownState + } + summary, err := s.stateSummary(ctx, blockRoot) + if err != nil { + return nil, errors.Wrap(err, "could not get state summary") + } + if startState.Slot() == summary.Slot { + return startState, nil + } + + blks, err := s.LoadBlocks(ctx, startState.Slot()+1, summary.Slot, bytesutil.ToBytes32(summary.Root)) + if err != nil { + return nil, errors.Wrap(err, "could not load blocks") + } + startState, err = s.ReplayBlocks(ctx, startState, blks, summary.Slot) + if err != nil { + return nil, errors.Wrap(err, "could not replay blocks") + } + + return startState, nil +} + +// StateBySlot retrieves the state using input slot. +func (s *State) StateBySlot(ctx context.Context, slot types.Slot) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.StateBySlot") + defer span.End() + + return s.loadStateBySlot(ctx, slot) +} + +// This returns the state summary object of a given block root, it first checks the cache +// then checks the DB. An error is returned if state summary object is nil. +func (s *State) stateSummary(ctx context.Context, blockRoot [32]byte) (*ethpb.StateSummary, error) { + var summary *ethpb.StateSummary + var err error + + summary, err = s.beaconDB.StateSummary(ctx, blockRoot) + if err != nil { + return nil, err + } + + if summary == nil { + return s.RecoverStateSummary(ctx, blockRoot) + } + return summary, nil +} + +// RecoverStateSummary recovers state summary object of a given block root by using the saved block in DB. +func (s *State) RecoverStateSummary(ctx context.Context, blockRoot [32]byte) (*ethpb.StateSummary, error) { + if s.beaconDB.HasBlock(ctx, blockRoot) { + b, err := s.beaconDB.Block(ctx, blockRoot) + if err != nil { + return nil, err + } + summary := ðpb.StateSummary{Slot: b.Block().Slot(), Root: blockRoot[:]} + if err := s.beaconDB.SaveStateSummary(ctx, summary); err != nil { + return nil, err + } + return summary, nil + } + return nil, errors.New("could not find block in DB") +} + +// This loads a beacon state from either the cache or DB then replay blocks up the requested block root. +func (s *State) loadStateByRoot(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.loadStateByRoot") + defer span.End() + + // First, it checks if the state exists in hot state cache. + cachedState := s.hotStateCache.get(blockRoot) + if cachedState != nil && !cachedState.IsNil() { + return cachedState, nil + } + + // Second, it checks if the state exits in epoch boundary state cache. + cachedInfo, ok, err := s.epochBoundaryStateCache.getByRoot(blockRoot) + if err != nil { + return nil, err + } + if ok { + return cachedInfo.state, nil + } + + // Short cut if the cachedState is already in the DB. + if s.beaconDB.HasState(ctx, blockRoot) { + return s.beaconDB.State(ctx, blockRoot) + } + + summary, err := s.stateSummary(ctx, blockRoot) + if err != nil { + return nil, errors.Wrap(err, "could not get state summary") + } + targetSlot := summary.Slot + + // Since the requested state is not in caches, start replaying using the last available ancestor state which is + // retrieved using input block's parent root. + startState, err := s.lastAncestorState(ctx, blockRoot) + if err != nil { + return nil, errors.Wrap(err, "could not get ancestor state") + } + if startState == nil || startState.IsNil() { + return nil, errUnknownBoundaryState + } + + // Return state early if we are retrieving it from our finalized state cache. + if startState.Slot() == targetSlot { + return startState, nil + } + + blks, err := s.LoadBlocks(ctx, startState.Slot()+1, targetSlot, bytesutil.ToBytes32(summary.Root)) + if err != nil { + return nil, errors.Wrap(err, "could not load blocks for hot state using root") + } + + replayBlockCount.Observe(float64(len(blks))) + + return s.ReplayBlocks(ctx, startState, blks, targetSlot) +} + +// This loads a state by slot. +func (s *State) loadStateBySlot(ctx context.Context, slot types.Slot) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.loadStateBySlot") + defer span.End() + + // Return genesis state if slot is 0. + if slot == 0 { + return s.beaconDB.GenesisState(ctx) + } + + // Gather the last saved block root and the slot number. + lastValidRoot, lastValidSlot, err := s.lastSavedBlock(ctx, slot) + if err != nil { + return nil, errors.Wrap(err, "could not get last valid block for hot state using slot") + } + + replayStartState, err := s.loadStateByRoot(ctx, lastValidRoot) + if err != nil { + return nil, err + } + + if lastValidSlot < slot { + replayStartState, err = processSlotsStateGen(ctx, replayStartState, slot) + if err != nil { + return nil, err + } + } + return replayStartState, nil +} + +// This returns the highest available ancestor state of the input block root. +// It recursively look up block's parent until a corresponding state of the block root +// is found in the caches or DB. +// +// There's three ways to derive block parent state: +// 1.) block parent state is the last finalized state +// 2.) block parent state is the epoch boundary state and exists in epoch boundary cache. +// 3.) block parent state is in DB. +func (s *State) lastAncestorState(ctx context.Context, root [32]byte) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.lastAncestorState") + defer span.End() + + if s.isFinalizedRoot(root) && s.finalizedState() != nil { + return s.finalizedState(), nil + } + + b, err := s.beaconDB.Block(ctx, root) + if err != nil { + return nil, err + } + if err := helpers.BeaconBlockIsNil(b); err != nil { + return nil, err + } + + for { + if ctx.Err() != nil { + return nil, ctx.Err() + } + // Is the state a genesis state. + parentRoot := bytesutil.ToBytes32(b.Block().ParentRoot()) + if parentRoot == params.BeaconConfig().ZeroHash { + return s.beaconDB.GenesisState(ctx) + } + + // Does the state exist in the hot state cache. + if s.hotStateCache.has(parentRoot) { + return s.hotStateCache.get(parentRoot), nil + } + + // Does the state exist in finalized info cache. + if s.isFinalizedRoot(parentRoot) { + return s.finalizedState(), nil + } + + // Does the state exist in epoch boundary cache. + cachedInfo, ok, err := s.epochBoundaryStateCache.getByRoot(parentRoot) + if err != nil { + return nil, err + } + if ok { + return cachedInfo.state, nil + } + + // Does the state exists in DB. + if s.beaconDB.HasState(ctx, parentRoot) { + return s.beaconDB.State(ctx, parentRoot) + } + b, err = s.beaconDB.Block(ctx, parentRoot) + if err != nil { + return nil, err + } + if b == nil || b.IsNil() { + return nil, errUnknownBlock + } + } +} diff --git a/beacon-chain/state-proto/stategen/getter_test.go b/beacon-chain/state-proto/stategen/getter_test.go new file mode 100644 index 0000000000..6e49dcf391 --- /dev/null +++ b/beacon-chain/state-proto/stategen/getter_test.go @@ -0,0 +1,596 @@ +package stategen + +import ( + "context" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" + testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestStateByRoot_GenesisState(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + b := util.NewBeaconBlock() + bRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, bRoot)) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) + loadedState, err := service.StateByRoot(ctx, params.BeaconConfig().ZeroHash) // Zero hash is genesis state root. + require.NoError(t, err) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) +} + +func TestStateByRoot_ColdState(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.finalizedInfo.slot = 2 + service.slotsPerArchivedPoint = 1 + + b := util.NewBeaconBlock() + b.Block.Slot = 1 + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + bRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(1)) + require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, bRoot)) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) + loadedState, err := service.StateByRoot(ctx, bRoot) + require.NoError(t, err) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) +} + +func TestStateByRootIfCachedNoCopy_HotState(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + r := [32]byte{'A'} + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: r[:]})) + service.hotStateCache.put(r, beaconState) + + loadedState := service.StateByRootIfCachedNoCopy(r) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) +} + +func TestStateByRootIfCachedNoCopy_ColdState(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.finalizedInfo.slot = 2 + service.slotsPerArchivedPoint = 1 + + b := util.NewBeaconBlock() + b.Block.Slot = 1 + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + bRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(1)) + require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, bRoot)) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) + loadedState := service.StateByRootIfCachedNoCopy(bRoot) + require.NoError(t, err) + require.Equal(t, loadedState, nil) +} + +func TestStateByRoot_HotStateUsingEpochBoundaryCacheNoReplay(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(10)) + blk := util.NewBeaconBlock() + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: blkRoot[:]})) + require.NoError(t, service.epochBoundaryStateCache.put(blkRoot, beaconState)) + loadedState, err := service.StateByRoot(ctx, blkRoot) + require.NoError(t, err) + assert.Equal(t, types.Slot(10), loadedState.Slot(), "Did not correctly load state") +} + +func TestStateByRoot_HotStateUsingEpochBoundaryCacheWithReplay(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + blk := util.NewBeaconBlock() + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.epochBoundaryStateCache.put(blkRoot, beaconState)) + targetSlot := types.Slot(10) + targetBlock := util.NewBeaconBlock() + targetBlock.Block.Slot = 11 + targetBlock.Block.ParentRoot = blkRoot[:] + targetBlock.Block.ProposerIndex = 8 + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(targetBlock))) + targetRoot, err := targetBlock.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: targetSlot, Root: targetRoot[:]})) + loadedState, err := service.StateByRoot(ctx, targetRoot) + require.NoError(t, err) + assert.Equal(t, targetSlot, loadedState.Slot(), "Did not correctly load state") +} + +func TestStateByRoot_HotStateCached(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + r := [32]byte{'A'} + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: r[:]})) + service.hotStateCache.put(r, beaconState) + + loadedState, err := service.StateByRoot(ctx, r) + require.NoError(t, err) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) +} + +func TestStateByRoot_StateByRootInitialSync(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + b := util.NewBeaconBlock() + bRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, bRoot)) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) + loadedState, err := service.StateByRootInitialSync(ctx, params.BeaconConfig().ZeroHash) // Zero hash is genesis state root. + require.NoError(t, err) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) +} + +func TestStateByRootInitialSync_UseEpochStateCache(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + targetSlot := types.Slot(10) + require.NoError(t, beaconState.SetSlot(targetSlot)) + blk := util.NewBeaconBlock() + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.epochBoundaryStateCache.put(blkRoot, beaconState)) + loadedState, err := service.StateByRootInitialSync(ctx, blkRoot) + require.NoError(t, err) + assert.Equal(t, targetSlot, loadedState.Slot(), "Did not correctly load state") +} + +func TestStateByRootInitialSync_UseCache(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + r := [32]byte{'A'} + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: r[:]})) + service.hotStateCache.put(r, beaconState) + + loadedState, err := service.StateByRootInitialSync(ctx, r) + require.NoError(t, err) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) + if service.hotStateCache.has(r) { + t.Error("Hot state cache was not invalidated") + } +} + +func TestStateByRootInitialSync_CanProcessUpTo(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + blk := util.NewBeaconBlock() + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.epochBoundaryStateCache.put(blkRoot, beaconState)) + targetSlot := types.Slot(10) + targetBlk := util.NewBeaconBlock() + targetBlk.Block.Slot = 11 + targetBlk.Block.ParentRoot = blkRoot[:] + targetRoot, err := targetBlk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(targetBlk))) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: targetSlot, Root: targetRoot[:]})) + + loadedState, err := service.StateByRootInitialSync(ctx, targetRoot) + require.NoError(t, err) + assert.Equal(t, targetSlot, loadedState.Slot(), "Did not correctly load state") +} + +func TestStateBySlot_ColdState(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.slotsPerArchivedPoint = params.BeaconConfig().SlotsPerEpoch * 2 + service.finalizedInfo.slot = service.slotsPerArchivedPoint + 1 + + beaconState, pks := util.DeterministicGenesisState(t, 32) + genesisStateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) + assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) + gRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + assert.NoError(t, beaconDB.SaveState(ctx, beaconState, gRoot)) + assert.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot)) + + b, err := util.GenerateFullBlock(beaconState, pks, util.DefaultBlockGenConfig(), 1) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + bRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveState(ctx, beaconState, bRoot)) + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bRoot)) + + r := [32]byte{} + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: service.slotsPerArchivedPoint, Root: r[:]})) + + slot := types.Slot(20) + loadedState, err := service.StateBySlot(ctx, slot) + require.NoError(t, err) + assert.Equal(t, slot, loadedState.Slot(), "Did not correctly save state") +} + +func TestStateBySlot_HotStateDB(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + genesisStateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) + assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) + gRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + assert.NoError(t, beaconDB.SaveState(ctx, beaconState, gRoot)) + assert.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot)) + + slot := types.Slot(10) + loadedState, err := service.StateBySlot(ctx, slot) + require.NoError(t, err) + assert.Equal(t, slot, loadedState.Slot(), "Did not correctly load state") +} + +func TestLoadeStateByRoot_Cached(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + r := [32]byte{'A'} + service.hotStateCache.put(r, beaconState) + + // This tests where hot state was already cached. + loadedState, err := service.loadStateByRoot(ctx, r) + require.NoError(t, err) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) +} + +func TestLoadeStateByRoot_FinalizedState(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + genesisStateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) + assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) + gRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: 0, Root: gRoot[:]})) + + service.finalizedInfo.state = beaconState + service.finalizedInfo.slot = beaconState.Slot() + service.finalizedInfo.root = gRoot + + // This tests where hot state was already cached. + loadedState, err := service.loadStateByRoot(ctx, gRoot) + require.NoError(t, err) + require.DeepSSZEqual(t, loadedState.InnerStateUnsafe(), beaconState.InnerStateUnsafe()) +} + +func TestLoadeStateByRoot_EpochBoundaryStateCanProcess(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + gBlk := util.NewBeaconBlock() + gBlkRoot, err := gBlk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.epochBoundaryStateCache.put(gBlkRoot, beaconState)) + + blk := util.NewBeaconBlock() + blk.Block.Slot = 11 + blk.Block.ProposerIndex = 8 + blk.Block.ParentRoot = gBlkRoot[:] + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(blk))) + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: 10, Root: blkRoot[:]})) + + // This tests where hot state was not cached and needs processing. + loadedState, err := service.loadStateByRoot(ctx, blkRoot) + require.NoError(t, err) + assert.Equal(t, types.Slot(10), loadedState.Slot(), "Did not correctly load state") +} + +func TestLoadeStateByRoot_FromDBBoundaryCase(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + gBlk := util.NewBeaconBlock() + gBlkRoot, err := gBlk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.epochBoundaryStateCache.put(gBlkRoot, beaconState)) + + blk := util.NewBeaconBlock() + blk.Block.Slot = 11 + blk.Block.ProposerIndex = 8 + blk.Block.ParentRoot = gBlkRoot[:] + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(blk))) + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: 10, Root: blkRoot[:]})) + + // This tests where hot state was not cached and needs processing. + loadedState, err := service.loadStateByRoot(ctx, blkRoot) + require.NoError(t, err) + assert.Equal(t, types.Slot(10), loadedState.Slot(), "Did not correctly load state") +} + +func TestLoadeStateBySlot_CanAdvanceSlotUsingDB(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + beaconState, _ := util.DeterministicGenesisState(t, 32) + b := util.NewBeaconBlock() + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + gRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, gRoot)) + require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, gRoot)) + + slot := types.Slot(10) + loadedState, err := service.loadStateBySlot(ctx, slot) + require.NoError(t, err) + assert.Equal(t, slot, loadedState.Slot(), "Did not correctly load state") +} + +func TestLoadeStateBySlot_CanReplayBlock(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + genesis, keys := util.DeterministicGenesisState(t, 64) + genesisBlockRoot := bytesutil.ToBytes32(nil) + require.NoError(t, beaconDB.SaveState(ctx, genesis, genesisBlockRoot)) + stateRoot, err := genesis.HashTreeRoot(ctx) + require.NoError(t, err) + genesisBlk := blocks.NewGenesisBlock(stateRoot[:]) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlk))) + genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisBlkRoot)) + + b1, err := util.GenerateFullBlock(genesis, keys, util.DefaultBlockGenConfig(), 1) + assert.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + r1, err := b1.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: 1, Root: r1[:]})) + service.hotStateCache.put(bytesutil.ToBytes32(b1.Block.ParentRoot), genesis) + + loadedState, err := service.loadStateBySlot(ctx, 2) + require.NoError(t, err) + assert.Equal(t, types.Slot(2), loadedState.Slot(), "Did not correctly load state") +} + +func TestLoadeStateBySlot_DoesntReplayBlockOnRequestedSlot(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + genesis, keys := util.DeterministicGenesisState(t, 64) + genesisBlockRoot := bytesutil.ToBytes32(nil) + require.NoError(t, beaconDB.SaveState(ctx, genesis, genesisBlockRoot)) + stateRoot, err := genesis.HashTreeRoot(ctx) + require.NoError(t, err) + genesisBlk := blocks.NewGenesisBlock(stateRoot[:]) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlk))) + genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisBlkRoot)) + + b1, err := util.GenerateFullBlock(genesis, keys, util.DefaultBlockGenConfig(), 1) + assert.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + r1, err := b1.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: 1, Root: r1[:]})) + service.hotStateCache.put(bytesutil.ToBytes32(b1.Block.ParentRoot), genesis) + + loadedState, err := service.loadStateBySlot(ctx, 1) + require.NoError(t, err) + assert.Equal(t, types.Slot(1), loadedState.Slot(), "Did not correctly load state") + + // Latest block header's state root should not be zero. Zero means the current slot's block has been processed. + require.NotEqual(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(loadedState.LatestBlockHeader().StateRoot)) +} + +func TestLastAncestorState_CanGetUsingDB(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + b0 := util.NewBeaconBlock() + b0.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32) + r0, err := b0.Block.HashTreeRoot() + require.NoError(t, err) + b1 := util.NewBeaconBlock() + b1.Block.Slot = 1 + b1.Block.ParentRoot = bytesutil.PadTo(r0[:], 32) + r1, err := b1.Block.HashTreeRoot() + require.NoError(t, err) + b2 := util.NewBeaconBlock() + b2.Block.Slot = 2 + b2.Block.ParentRoot = bytesutil.PadTo(r1[:], 32) + r2, err := b2.Block.HashTreeRoot() + require.NoError(t, err) + b3 := util.NewBeaconBlock() + b3.Block.Slot = 3 + b3.Block.ParentRoot = bytesutil.PadTo(r2[:], 32) + r3, err := b3.Block.HashTreeRoot() + require.NoError(t, err) + + b1State, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, b1State.SetSlot(1)) + + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b0))) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) + require.NoError(t, service.beaconDB.SaveState(ctx, b1State, r1)) + + lastState, err := service.lastAncestorState(ctx, r3) + require.NoError(t, err) + assert.Equal(t, b1State.Slot(), lastState.Slot(), "Did not get wanted state") +} + +func TestLastAncestorState_CanGetUsingCache(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + b0 := util.NewBeaconBlock() + b0.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32) + r0, err := b0.Block.HashTreeRoot() + require.NoError(t, err) + b1 := util.NewBeaconBlock() + b1.Block.Slot = 1 + b1.Block.ParentRoot = bytesutil.PadTo(r0[:], 32) + r1, err := b1.Block.HashTreeRoot() + require.NoError(t, err) + b2 := util.NewBeaconBlock() + b2.Block.Slot = 2 + b2.Block.ParentRoot = bytesutil.PadTo(r1[:], 32) + r2, err := b2.Block.HashTreeRoot() + require.NoError(t, err) + b3 := util.NewBeaconBlock() + b3.Block.Slot = 3 + b3.Block.ParentRoot = bytesutil.PadTo(r2[:], 32) + r3, err := b3.Block.HashTreeRoot() + require.NoError(t, err) + + b1State, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, b1State.SetSlot(1)) + + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b0))) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) + service.hotStateCache.put(r1, b1State) + + lastState, err := service.lastAncestorState(ctx, r3) + require.NoError(t, err) + assert.Equal(t, b1State.Slot(), lastState.Slot(), "Did not get wanted state") +} + +func TestState_HasState(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + s, err := util.NewBeaconState() + require.NoError(t, err) + rHit1 := [32]byte{1} + rHit2 := [32]byte{2} + rMiss := [32]byte{3} + service.hotStateCache.put(rHit1, s) + require.NoError(t, service.epochBoundaryStateCache.put(rHit2, s)) + + b := util.NewBeaconBlock() + rHit3, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveState(ctx, s, rHit3)) + tt := []struct { + root [32]byte + want bool + }{ + {rHit1, true}, + {rHit2, true}, + {rMiss, false}, + {rHit3, true}, + } + for _, tc := range tt { + got, err := service.HasState(ctx, tc.root) + require.NoError(t, err) + require.Equal(t, tc.want, got) + } +} + +func TestState_HasStateInCache(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + s, err := util.NewBeaconState() + require.NoError(t, err) + rHit1 := [32]byte{1} + rHit2 := [32]byte{2} + rMiss := [32]byte{3} + service.hotStateCache.put(rHit1, s) + require.NoError(t, service.epochBoundaryStateCache.put(rHit2, s)) + + tt := []struct { + root [32]byte + want bool + }{ + {rHit1, true}, + {rHit2, true}, + {rMiss, false}, + } + for _, tc := range tt { + got, err := service.HasStateInCache(ctx, tc.root) + require.NoError(t, err) + require.Equal(t, tc.want, got) + } +} diff --git a/beacon-chain/state-proto/stategen/hot_state_cache.go b/beacon-chain/state-proto/stategen/hot_state_cache.go new file mode 100644 index 0000000000..97fdbed10e --- /dev/null +++ b/beacon-chain/state-proto/stategen/hot_state_cache.go @@ -0,0 +1,87 @@ +package stategen + +import ( + "sync" + + lru "github.com/hashicorp/golang-lru" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" +) + +var ( + // hotStateCacheSize defines the max number of hot state this can cache. + hotStateCacheSize = 32 + // Metrics + hotStateCacheHit = promauto.NewCounter(prometheus.CounterOpts{ + Name: "hot_state_cache_hit", + Help: "The total number of cache hits on the hot state cache.", + }) + hotStateCacheMiss = promauto.NewCounter(prometheus.CounterOpts{ + Name: "hot_state_cache_miss", + Help: "The total number of cache misses on the hot state cache.", + }) +) + +// hotStateCache is used to store the processed beacon state after finalized check point.. +type hotStateCache struct { + cache *lru.Cache + lock sync.RWMutex +} + +// newHotStateCache initializes the map and underlying cache. +func newHotStateCache() *hotStateCache { + return &hotStateCache{ + cache: lruwrpr.New(hotStateCacheSize), + } +} + +// Get returns a cached response via input block root, if any. +// The response is copied by default. +func (c *hotStateCache) get(root [32]byte) state.BeaconState { + c.lock.RLock() + defer c.lock.RUnlock() + item, exists := c.cache.Get(root) + + if exists && item != nil { + hotStateCacheHit.Inc() + return item.(state.BeaconState).Copy() + } + hotStateCacheMiss.Inc() + return nil +} + +// GetWithoutCopy returns a non-copied cached response via input block root. +func (c *hotStateCache) getWithoutCopy(root [32]byte) state.BeaconState { + c.lock.RLock() + defer c.lock.RUnlock() + item, exists := c.cache.Get(root) + if exists && item != nil { + hotStateCacheHit.Inc() + return item.(state.BeaconState) + } + hotStateCacheMiss.Inc() + return nil +} + +// put the response in the cache. +func (c *hotStateCache) put(root [32]byte, state state.BeaconState) { + c.lock.Lock() + defer c.lock.Unlock() + c.cache.Add(root, state) +} + +// has returns true if the key exists in the cache. +func (c *hotStateCache) has(root [32]byte) bool { + c.lock.RLock() + defer c.lock.RUnlock() + return c.cache.Contains(root) +} + +// delete deletes the key exists in the cache. +func (c *hotStateCache) delete(root [32]byte) bool { + c.lock.Lock() + defer c.lock.Unlock() + return c.cache.Remove(root) +} diff --git a/beacon-chain/state/stategen/hot_state_cache_test.go b/beacon-chain/state-proto/stategen/hot_state_cache_test.go similarity index 76% rename from beacon-chain/state/stategen/hot_state_cache_test.go rename to beacon-chain/state-proto/stategen/hot_state_cache_test.go index 6ad61de847..ac56fc61dd 100644 --- a/beacon-chain/state/stategen/hot_state_cache_test.go +++ b/beacon-chain/state-proto/stategen/hot_state_cache_test.go @@ -3,8 +3,8 @@ package stategen import ( "testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" @@ -27,7 +27,7 @@ func TestHotStateCache_RoundTrip(t *testing.T) { res := c.get(root) assert.NotNil(t, s) - assert.DeepEqual(t, res.ToProto(), s.ToProto(), "Expected equal protos to return from cache") + assert.DeepEqual(t, res.CloneInnerState(), s.CloneInnerState(), "Expected equal protos to return from cache") c.delete(root) assert.Equal(t, false, c.has(root), "Cache not supposed to have the object") diff --git a/beacon-chain/state-proto/stategen/init_test.go b/beacon-chain/state-proto/stategen/init_test.go new file mode 100644 index 0000000000..4eb1a29b5a --- /dev/null +++ b/beacon-chain/state-proto/stategen/init_test.go @@ -0,0 +1,12 @@ +package stategen + +import ( + "github.com/prysmaticlabs/prysm/config/params" +) + +func init() { + // Override network name so that hardcoded genesis files are not loaded. + cfg := params.BeaconConfig() + cfg.ConfigName = "test" + params.OverrideBeaconConfig(cfg) +} diff --git a/beacon-chain/state-proto/stategen/log.go b/beacon-chain/state-proto/stategen/log.go new file mode 100644 index 0000000000..b3414dc6cf --- /dev/null +++ b/beacon-chain/state-proto/stategen/log.go @@ -0,0 +1,5 @@ +package stategen + +import "github.com/sirupsen/logrus" + +var log = logrus.WithField("prefix", "state-gen") diff --git a/beacon-chain/state-proto/stategen/metrics.go b/beacon-chain/state-proto/stategen/metrics.go new file mode 100644 index 0000000000..143b251794 --- /dev/null +++ b/beacon-chain/state-proto/stategen/metrics.go @@ -0,0 +1,16 @@ +package stategen + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +var ( + replayBlockCount = promauto.NewHistogram( + prometheus.HistogramOpts{ + Name: "replay_blocks_count", + Help: "The number of blocks to replay to generate a state", + Buckets: []float64{64, 256, 1024, 2048, 4096}, + }, + ) +) diff --git a/beacon-chain/state-proto/stategen/migrate.go b/beacon-chain/state-proto/stategen/migrate.go new file mode 100644 index 0000000000..388c0e18d9 --- /dev/null +++ b/beacon-chain/state-proto/stategen/migrate.go @@ -0,0 +1,119 @@ +package stategen + +import ( + "context" + "encoding/hex" + "fmt" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/sirupsen/logrus" + "go.opencensus.io/trace" +) + +// MigrateToCold advances the finalized info in between the cold and hot state sections. +// It moves the recent finalized states from the hot section to the cold section and +// only preserve the ones that's on archived point. +func (s *State) MigrateToCold(ctx context.Context, fRoot [32]byte) error { + ctx, span := trace.StartSpan(ctx, "stateGen.MigrateToCold") + defer span.End() + + s.finalizedInfo.lock.RLock() + oldFSlot := s.finalizedInfo.slot + s.finalizedInfo.lock.RUnlock() + + fBlock, err := s.beaconDB.Block(ctx, fRoot) + if err != nil { + return err + } + fSlot := fBlock.Block().Slot() + if oldFSlot > fSlot { + return nil + } + + // Start at previous finalized slot, stop at current finalized slot. + // If the slot is on archived point, save the state of that slot to the DB. + for slot := oldFSlot; slot < fSlot; slot++ { + if ctx.Err() != nil { + return ctx.Err() + } + + if slot%s.slotsPerArchivedPoint == 0 && slot != 0 { + cached, exists, err := s.epochBoundaryStateCache.getBySlot(slot) + if err != nil { + return fmt.Errorf("could not get epoch boundary state for slot %d", slot) + } + + var aRoot [32]byte + var aState state.BeaconState + + // When the epoch boundary state is not in cache due to skip slot scenario, + // we have to regenerate the state which will represent epoch boundary. + // By finding the highest available block below epoch boundary slot, we + // generate the state for that block root. + if exists { + aRoot = cached.root + aState = cached.state + } else { + blks, err := s.beaconDB.HighestSlotBlocksBelow(ctx, slot) + if err != nil { + return err + } + // Given the block has been finalized, the db should not have more than one block in a given slot. + // We should error out when this happens. + if len(blks) != 1 { + return errUnknownBlock + } + missingRoot, err := blks[0].Block().HashTreeRoot() + if err != nil { + return err + } + aRoot = missingRoot + // There's no need to generate the state if the state already exists on the DB. + // We can skip saving the state. + if !s.beaconDB.HasState(ctx, aRoot) { + aState, err = s.StateByRoot(ctx, missingRoot) + if err != nil { + return err + } + } + } + + if s.beaconDB.HasState(ctx, aRoot) { + // Remove hot state DB root to prevent it gets deleted later when we turn hot state save DB mode off. + s.saveHotStateDB.lock.Lock() + roots := s.saveHotStateDB.savedStateRoots + for i := 0; i < len(roots); i++ { + if aRoot == roots[i] { + s.saveHotStateDB.savedStateRoots = append(roots[:i], roots[i+1:]...) + // There shouldn't be duplicated roots in `savedStateRoots`. + // Break here is ok. + break + } + } + s.saveHotStateDB.lock.Unlock() + continue + } + + if err := s.beaconDB.SaveState(ctx, aState, aRoot); err != nil { + return err + } + log.WithFields( + logrus.Fields{ + "slot": aState.Slot(), + "root": hex.EncodeToString(bytesutil.Trunc(aRoot[:])), + }).Info("Saved state in DB") + } + } + + // Update finalized info in memory. + fInfo, ok, err := s.epochBoundaryStateCache.getByRoot(fRoot) + if err != nil { + return err + } + if ok { + s.SaveFinalizedState(fSlot, fRoot, fInfo.state) + } + + return nil +} diff --git a/beacon-chain/state-proto/stategen/migrate_test.go b/beacon-chain/state-proto/stategen/migrate_test.go new file mode 100644 index 0000000000..ec2c5d8cc6 --- /dev/null +++ b/beacon-chain/state-proto/stategen/migrate_test.go @@ -0,0 +1,137 @@ +package stategen + +import ( + "context" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" + testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" + logTest "github.com/sirupsen/logrus/hooks/test" +) + +func TestMigrateToCold_CanSaveFinalizedInfo(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + beaconState, _ := util.DeterministicGenesisState(t, 32) + b := util.NewBeaconBlock() + b.Block.Slot = 1 + br, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + require.NoError(t, service.epochBoundaryStateCache.put(br, beaconState)) + require.NoError(t, service.MigrateToCold(ctx, br)) + + wanted := &finalizedInfo{state: beaconState, root: br, slot: 1} + assert.DeepEqual(t, wanted, service.finalizedInfo, "Incorrect finalized info") +} + +func TestMigrateToCold_HappyPath(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.slotsPerArchivedPoint = 1 + beaconState, _ := util.DeterministicGenesisState(t, 32) + stateSlot := types.Slot(1) + require.NoError(t, beaconState.SetSlot(stateSlot)) + b := util.NewBeaconBlock() + b.Block.Slot = 2 + fRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + require.NoError(t, service.epochBoundaryStateCache.put(fRoot, beaconState)) + require.NoError(t, service.MigrateToCold(ctx, fRoot)) + + gotState, err := service.beaconDB.State(ctx, fRoot) + require.NoError(t, err) + assert.DeepSSZEqual(t, beaconState.InnerStateUnsafe(), gotState.InnerStateUnsafe(), "Did not save state") + gotRoot := service.beaconDB.ArchivedPointRoot(ctx, stateSlot/service.slotsPerArchivedPoint) + assert.Equal(t, fRoot, gotRoot, "Did not save archived root") + lastIndex, err := service.beaconDB.LastArchivedSlot(ctx) + require.NoError(t, err) + assert.Equal(t, types.Slot(1), lastIndex, "Did not save last archived index") + + require.LogsContain(t, hook, "Saved state in DB") +} + +func TestMigrateToCold_RegeneratePath(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.slotsPerArchivedPoint = 1 + beaconState, pks := util.DeterministicGenesisState(t, 32) + genesisStateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) + assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) + gRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + assert.NoError(t, beaconDB.SaveState(ctx, beaconState, gRoot)) + assert.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot)) + + b1, err := util.GenerateFullBlock(beaconState, pks, util.DefaultBlockGenConfig(), 1) + require.NoError(t, err) + r1, err := b1.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: 1, Root: r1[:]})) + + b4, err := util.GenerateFullBlock(beaconState, pks, util.DefaultBlockGenConfig(), 4) + require.NoError(t, err) + r4, err := b4.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b4))) + require.NoError(t, service.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Slot: 4, Root: r4[:]})) + service.finalizedInfo = &finalizedInfo{ + slot: 0, + root: genesisStateRoot, + state: beaconState, + } + + require.NoError(t, service.MigrateToCold(ctx, r4)) + + s1, err := service.beaconDB.State(ctx, r1) + require.NoError(t, err) + assert.Equal(t, s1.Slot(), types.Slot(1), "Did not save state") + gotRoot := service.beaconDB.ArchivedPointRoot(ctx, 1/service.slotsPerArchivedPoint) + assert.Equal(t, r1, gotRoot, "Did not save archived root") + lastIndex, err := service.beaconDB.LastArchivedSlot(ctx) + require.NoError(t, err) + assert.Equal(t, types.Slot(1), lastIndex, "Did not save last archived index") + + require.LogsContain(t, hook, "Saved state in DB") +} + +func TestMigrateToCold_StateExistsInDB(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.slotsPerArchivedPoint = 1 + beaconState, _ := util.DeterministicGenesisState(t, 32) + stateSlot := types.Slot(1) + require.NoError(t, beaconState.SetSlot(stateSlot)) + b := util.NewBeaconBlock() + b.Block.Slot = 2 + fRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + require.NoError(t, service.epochBoundaryStateCache.put(fRoot, beaconState)) + require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, fRoot)) + + service.saveHotStateDB.savedStateRoots = [][32]byte{{1}, {2}, {3}, {4}, fRoot} + require.NoError(t, service.MigrateToCold(ctx, fRoot)) + assert.DeepEqual(t, [][32]byte{{1}, {2}, {3}, {4}}, service.saveHotStateDB.savedStateRoots) + assert.LogsDoNotContain(t, hook, "Saved state in DB") +} diff --git a/beacon-chain/state-proto/stategen/mock.go b/beacon-chain/state-proto/stategen/mock.go new file mode 100644 index 0000000000..8dbde0369a --- /dev/null +++ b/beacon-chain/state-proto/stategen/mock.go @@ -0,0 +1,126 @@ +package stategen + +import ( + "context" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" +) + +// MockStateManager is a fake implementation of StateManager. +type MockStateManager struct { + StatesByRoot map[[32]byte]state.BeaconState + StatesBySlot map[types.Slot]state.BeaconState +} + +// NewMockService -- +func NewMockService() *MockStateManager { + return &MockStateManager{ + StatesByRoot: make(map[[32]byte]state.BeaconState), + StatesBySlot: make(map[types.Slot]state.BeaconState), + } +} + +// StateByRootIfCached +func (_ *MockStateManager) StateByRootIfCachedNoCopy(_ [32]byte) state.BeaconState { + panic("implement me") +} + +// Resume -- +func (_ *MockStateManager) Resume(_ context.Context, _ state.BeaconState) (state.BeaconState, error) { + panic("implement me") +} + +// SaveFinalizedState -- +func (_ *MockStateManager) SaveFinalizedState(_ types.Slot, _ [32]byte, _ state.BeaconState) { + panic("implement me") +} + +// MigrateToCold -- +func (_ *MockStateManager) MigrateToCold(_ context.Context, _ [32]byte) error { + panic("implement me") +} + +// ReplayBlocks -- +func (_ *MockStateManager) ReplayBlocks( + _ context.Context, + _ state.BeaconState, + _ []block.SignedBeaconBlock, + _ types.Slot, +) (state.BeaconState, error) { + panic("implement me") +} + +// LoadBlocks -- +func (_ *MockStateManager) LoadBlocks( + _ context.Context, + _, _ types.Slot, + _ [32]byte, +) ([]block.SignedBeaconBlock, error) { + panic("implement me") +} + +// HasState -- +func (_ *MockStateManager) HasState(_ context.Context, _ [32]byte) (bool, error) { + panic("implement me") +} + +// HasStateInCache -- +func (_ *MockStateManager) HasStateInCache(_ context.Context, _ [32]byte) (bool, error) { + panic("implement me") +} + +// StateByRoot -- +func (m *MockStateManager) StateByRoot(_ context.Context, blockRoot [32]byte) (state.BeaconState, error) { + return m.StatesByRoot[blockRoot], nil +} + +// StateByRootInitialSync -- +func (_ *MockStateManager) StateByRootInitialSync(_ context.Context, _ [32]byte) (state.BeaconState, error) { + panic("implement me") +} + +// StateBySlot -- +func (m *MockStateManager) StateBySlot(_ context.Context, slot types.Slot) (state.BeaconState, error) { + return m.StatesBySlot[slot], nil +} + +// RecoverStateSummary -- +func (_ *MockStateManager) RecoverStateSummary( + _ context.Context, + _ [32]byte, +) (*ethpb.StateSummary, error) { + panic("implement me") +} + +// SaveState -- +func (_ *MockStateManager) SaveState(_ context.Context, _ [32]byte, _ state.BeaconState) error { + panic("implement me") +} + +// ForceCheckpoint -- +func (_ *MockStateManager) ForceCheckpoint(_ context.Context, _ []byte) error { + panic("implement me") +} + +// EnableSaveHotStateToDB -- +func (_ *MockStateManager) EnableSaveHotStateToDB(_ context.Context) { + panic("implement me") +} + +// DisableSaveHotStateToDB -- +func (_ *MockStateManager) DisableSaveHotStateToDB(_ context.Context) error { + panic("implement me") +} + +// AddStateForRoot -- +func (m *MockStateManager) AddStateForRoot(state state.BeaconState, blockRoot [32]byte) { + m.StatesByRoot[blockRoot] = state +} + +// AddStateForSlot -- +func (m *MockStateManager) AddStateForSlot(state state.BeaconState, slot types.Slot) { + m.StatesBySlot[slot] = state +} diff --git a/beacon-chain/state-proto/stategen/replay.go b/beacon-chain/state-proto/stategen/replay.go new file mode 100644 index 0000000000..6d4e336bfb --- /dev/null +++ b/beacon-chain/state-proto/stategen/replay.go @@ -0,0 +1,326 @@ +package stategen + +import ( + "context" + "fmt" + "time" + + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" + "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" + prysmTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" + "github.com/prysmaticlabs/prysm/beacon-chain/db/filters" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" + "github.com/prysmaticlabs/prysm/runtime/version" + "github.com/sirupsen/logrus" + "go.opencensus.io/trace" +) + +// ReplayBlocks replays the input blocks on the input state until the target slot is reached. +func (_ *State) ReplayBlocks( + ctx context.Context, + state state.BeaconState, + signed []block.SignedBeaconBlock, + targetSlot types.Slot, +) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.ReplayBlocks") + defer span.End() + var err error + + start := time.Now() + log.WithFields(logrus.Fields{ + "startSlot": state.Slot(), + "endSlot": targetSlot, + "diff": targetSlot - state.Slot(), + }).Debug("Replaying state") + // The input block list is sorted in decreasing slots order. + if len(signed) > 0 { + for i := len(signed) - 1; i >= 0; i-- { + if ctx.Err() != nil { + return nil, ctx.Err() + } + if state.Slot() >= targetSlot { + break + } + // A node shouldn't process the block if the block slot is lower than the state slot. + if state.Slot() >= signed[i].Block().Slot() { + continue + } + state, err = executeStateTransitionStateGen(ctx, state, signed[i]) + if err != nil { + return nil, err + } + } + } + + // If there is skip slots at the end. + if targetSlot > state.Slot() { + state, err = processSlotsStateGen(ctx, state, targetSlot) + if err != nil { + return nil, err + } + } + + duration := time.Since(start) + log.WithFields(logrus.Fields{ + "duration": duration, + }).Debug("Replayed state") + + return state, nil +} + +// LoadBlocks loads the blocks between start slot and end slot by recursively fetching from end block root. +// The Blocks are returned in slot-descending order. +func (s *State) LoadBlocks(ctx context.Context, startSlot, endSlot types.Slot, endBlockRoot [32]byte) ([]block.SignedBeaconBlock, error) { + // Nothing to load for invalid range. + if endSlot < startSlot { + return nil, fmt.Errorf("start slot %d >= end slot %d", startSlot, endSlot) + } + filter := filters.NewFilter().SetStartSlot(startSlot).SetEndSlot(endSlot) + blocks, blockRoots, err := s.beaconDB.Blocks(ctx, filter) + if err != nil { + return nil, err + } + // The retrieved blocks and block roots have to be in the same length given same filter. + if len(blocks) != len(blockRoots) { + return nil, errors.New("length of blocks and roots don't match") + } + // Return early if there's no block given the input. + length := len(blocks) + if length == 0 { + return nil, nil + } + + // The last retrieved block root has to match input end block root. + // Covers the edge case if there's multiple blocks on the same end slot, + // the end root may not be the last index in `blockRoots`. + for length >= 3 && blocks[length-1].Block().Slot() == blocks[length-2].Block().Slot() && blockRoots[length-1] != endBlockRoot { + if ctx.Err() != nil { + return nil, ctx.Err() + } + length-- + if blockRoots[length-2] == endBlockRoot { + length-- + break + } + } + + if blockRoots[length-1] != endBlockRoot { + return nil, errors.New("end block roots don't match") + } + + filteredBlocks := []block.SignedBeaconBlock{blocks[length-1]} + // Starting from second to last index because the last block is already in the filtered block list. + for i := length - 2; i >= 0; i-- { + if ctx.Err() != nil { + return nil, ctx.Err() + } + b := filteredBlocks[len(filteredBlocks)-1] + if bytesutil.ToBytes32(b.Block().ParentRoot()) != blockRoots[i] { + continue + } + filteredBlocks = append(filteredBlocks, blocks[i]) + } + + return filteredBlocks, nil +} + +// executeStateTransitionStateGen applies state transition on input historical state and block for state gen usages. +// There's no signature verification involved given state gen only works with stored block and state in DB. +// If the objects are already in stored in DB, one can omit redundant signature checks and ssz hashing calculations. +// WARNING: This method should not be used on an unverified new block. +func executeStateTransitionStateGen( + ctx context.Context, + state state.BeaconState, + signed block.SignedBeaconBlock, +) (state.BeaconState, error) { + if ctx.Err() != nil { + return nil, ctx.Err() + } + if err := helpers.BeaconBlockIsNil(signed); err != nil { + return nil, err + } + ctx, span := trace.StartSpan(ctx, "stategen.ExecuteStateTransitionStateGen") + defer span.End() + var err error + + // Execute per slots transition. + // Given this is for state gen, a node uses the version process slots without skip slots cache. + state, err = processSlotsStateGen(ctx, state, signed.Block().Slot()) + if err != nil { + return nil, errors.Wrap(err, "could not process slot") + } + + // Execute per block transition. + // Given this is for state gen, a node only cares about the post state without proposer + // and randao signature verifications. + state, err = transition.ProcessBlockForStateRoot(ctx, state, signed) + if err != nil { + return nil, errors.Wrap(err, "could not process block") + } + if signed.Version() == version.Altair { + sa, err := signed.Block().Body().SyncAggregate() + if err != nil { + return nil, err + } + state, err = altair.ProcessSyncAggregate(ctx, state, sa) + if err != nil { + return nil, err + } + } + + return state, nil +} + +// processSlotsStateGen to process old slots for state gen usages. +// There's no skip slot cache involved given state gen only works with already stored block and state in DB. +// WARNING: This method should not be used for future slot. +func processSlotsStateGen(ctx context.Context, state state.BeaconState, slot types.Slot) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stategen.ProcessSlotsStateGen") + defer span.End() + if state == nil || state.IsNil() { + return nil, errUnknownState + } + + if state.Slot() > slot { + err := fmt.Errorf("expected state.slot %d < slot %d", state.Slot(), slot) + return nil, err + } + + if state.Slot() == slot { + return state, nil + } + + var err error + for state.Slot() < slot { + state, err = transition.ProcessSlot(ctx, state) + if err != nil { + return nil, errors.Wrap(err, "could not process slot") + } + if prysmTime.CanProcessEpoch(state) { + switch state.Version() { + case version.Phase0: + state, err = transition.ProcessEpochPrecompute(ctx, state) + if err != nil { + return nil, errors.Wrap(err, "could not process epoch with optimizations") + } + case version.Altair: + state, err = altair.ProcessEpoch(ctx, state) + if err != nil { + return nil, errors.Wrap(err, "could not process epoch with optimization") + } + default: + return nil, errors.New("beacon state should have a version") + } + } + if err := state.SetSlot(state.Slot() + 1); err != nil { + return nil, err + } + + if prysmTime.CanUpgradeToAltair(state.Slot()) { + state, err = altair.UpgradeToAltair(ctx, state) + if err != nil { + return nil, err + } + } + } + + return state, nil +} + +// This finds the last saved block in DB from searching backwards from input slot, +// it returns the block root and the slot of the block. +// This is used by both hot and cold state management. +func (s *State) lastSavedBlock(ctx context.Context, slot types.Slot) ([32]byte, types.Slot, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.lastSavedBlock") + defer span.End() + + // Handle the genesis case where the input slot is 0. + if slot == 0 { + gRoot, err := s.genesisRoot(ctx) + if err != nil { + return [32]byte{}, 0, err + } + return gRoot, 0, nil + } + + lastSaved, err := s.beaconDB.HighestSlotBlocksBelow(ctx, slot) + if err != nil { + return [32]byte{}, 0, err + } + + // Given this is used to query canonical block. There should only be one saved canonical block of a given slot. + if len(lastSaved) != 1 { + return [32]byte{}, 0, fmt.Errorf("highest saved block does not equal to 1, it equals to %d", len(lastSaved)) + } + if lastSaved[0] == nil || lastSaved[0].IsNil() || lastSaved[0].Block().IsNil() { + return [32]byte{}, 0, nil + } + r, err := lastSaved[0].Block().HashTreeRoot() + if err != nil { + return [32]byte{}, 0, err + } + + return r, lastSaved[0].Block().Slot(), nil +} + +// This finds the last saved state in DB from searching backwards from input slot, +// it returns the block root of the block which was used to produce the state. +// This is used by both hot and cold state management. +func (s *State) lastSavedState(ctx context.Context, slot types.Slot) (state.ReadOnlyBeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.lastSavedState") + defer span.End() + + // Handle the genesis case where the input slot is 0. + if slot == 0 { + return s.beaconDB.GenesisState(ctx) + } + + lastSaved, err := s.beaconDB.HighestSlotStatesBelow(ctx, slot+1) + if err != nil { + return nil, err + } + + // Given this is used to query canonical state. There should only be one saved canonical block of a given slot. + if len(lastSaved) != 1 { + return nil, fmt.Errorf("highest saved state does not equal to 1, it equals to %d", len(lastSaved)) + } + if lastSaved[0] == nil { + return nil, errUnknownState + } + + return lastSaved[0], nil +} + +// This returns the genesis root. +func (s *State) genesisRoot(ctx context.Context) ([32]byte, error) { + b, err := s.beaconDB.GenesisBlock(ctx) + if err != nil { + return [32]byte{}, err + } + return b.Block().HashTreeRoot() +} + +// Given the start slot and the end slot, this returns the finalized beacon blocks in between. +// Since hot states don't have finalized blocks, this should ONLY be used for replaying cold state. +func (s *State) loadFinalizedBlocks(ctx context.Context, startSlot, endSlot types.Slot) ([]block.SignedBeaconBlock, error) { + f := filters.NewFilter().SetStartSlot(startSlot).SetEndSlot(endSlot) + bs, bRoots, err := s.beaconDB.Blocks(ctx, f) + if err != nil { + return nil, err + } + if len(bs) != len(bRoots) { + return nil, errors.New("length of blocks and roots don't match") + } + fbs := make([]block.SignedBeaconBlock, 0, len(bs)) + for i := len(bs) - 1; i >= 0; i-- { + if s.beaconDB.IsFinalizedBlock(ctx, bRoots[i]) { + fbs = append(fbs, bs[i]) + } + } + return fbs, nil +} diff --git a/beacon-chain/state-proto/stategen/replay_test.go b/beacon-chain/state-proto/stategen/replay_test.go new file mode 100644 index 0000000000..72846a162c --- /dev/null +++ b/beacon-chain/state-proto/stategen/replay_test.go @@ -0,0 +1,777 @@ +package stategen + +import ( + "context" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/beacon-chain/db" + testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" + "github.com/prysmaticlabs/prysm/runtime/version" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" + "google.golang.org/protobuf/proto" +) + +func TestReplayBlocks_AllSkipSlots(t *testing.T) { + beaconDB := testDB.SetupDB(t) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + genesisBlock := blocks.NewGenesisBlock([]byte{}) + bodyRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ + Slot: genesisBlock.Block.Slot, + ParentRoot: genesisBlock.Block.ParentRoot, + StateRoot: params.BeaconConfig().ZeroHash[:], + BodyRoot: bodyRoot[:], + }) + require.NoError(t, err) + require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))) + cp := beaconState.CurrentJustifiedCheckpoint() + mockRoot := [32]byte{} + copy(mockRoot[:], "hello-world") + cp.Root = mockRoot[:] + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp)) + require.NoError(t, beaconState.AppendCurrentEpochAttestations(ðpb.PendingAttestation{})) + + service := New(beaconDB) + targetSlot := params.BeaconConfig().SlotsPerEpoch - 1 + newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{}, targetSlot) + require.NoError(t, err) + assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots") +} + +func TestReplayBlocks_SameSlot(t *testing.T) { + beaconDB := testDB.SetupDB(t) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + genesisBlock := blocks.NewGenesisBlock([]byte{}) + bodyRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ + Slot: genesisBlock.Block.Slot, + ParentRoot: genesisBlock.Block.ParentRoot, + StateRoot: params.BeaconConfig().ZeroHash[:], + BodyRoot: bodyRoot[:], + }) + require.NoError(t, err) + require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))) + cp := beaconState.CurrentJustifiedCheckpoint() + mockRoot := [32]byte{} + copy(mockRoot[:], "hello-world") + cp.Root = mockRoot[:] + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp)) + require.NoError(t, beaconState.AppendCurrentEpochAttestations(ðpb.PendingAttestation{})) + + service := New(beaconDB) + targetSlot := beaconState.Slot() + newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{}, targetSlot) + require.NoError(t, err) + assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots") +} + +func TestReplayBlocks_LowerSlotBlock(t *testing.T) { + beaconDB := testDB.SetupDB(t) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(1)) + genesisBlock := blocks.NewGenesisBlock([]byte{}) + bodyRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ + Slot: genesisBlock.Block.Slot, + ParentRoot: genesisBlock.Block.ParentRoot, + StateRoot: params.BeaconConfig().ZeroHash[:], + BodyRoot: bodyRoot[:], + }) + require.NoError(t, err) + require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))) + cp := beaconState.CurrentJustifiedCheckpoint() + mockRoot := [32]byte{} + copy(mockRoot[:], "hello-world") + cp.Root = mockRoot[:] + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp)) + require.NoError(t, beaconState.AppendCurrentEpochAttestations(ðpb.PendingAttestation{})) + + service := New(beaconDB) + targetSlot := beaconState.Slot() + b := util.NewBeaconBlock() + b.Block.Slot = beaconState.Slot() - 1 + newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{wrapper.WrappedPhase0SignedBeaconBlock(b)}, targetSlot) + require.NoError(t, err) + assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots") +} + +func TestReplayBlocks_ThroughForkBoundary(t *testing.T) { + params.SetupTestConfigCleanup(t) + bCfg := params.BeaconConfig() + bCfg.AltairForkEpoch = 1 + bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.AltairForkVersion)] = 1 + params.OverrideBeaconConfig(bCfg) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + genesisBlock := blocks.NewGenesisBlock([]byte{}) + bodyRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ + Slot: genesisBlock.Block.Slot, + ParentRoot: genesisBlock.Block.ParentRoot, + StateRoot: params.BeaconConfig().ZeroHash[:], + BodyRoot: bodyRoot[:], + }) + require.NoError(t, err) + + service := New(testDB.SetupDB(t)) + targetSlot := params.BeaconConfig().SlotsPerEpoch + newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{}, targetSlot) + require.NoError(t, err) + + // Verify state is version Altair. + assert.Equal(t, version.Altair, newState.Version()) +} + +func TestLoadBlocks_FirstBranch(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + + roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32)) + require.NoError(t, err) + + filteredBlocks, err := s.LoadBlocks(ctx, 0, 8, roots[len(roots)-1]) + require.NoError(t, err) + + wanted := []*ethpb.SignedBeaconBlock{ + savedBlocks[8], + savedBlocks[6], + savedBlocks[4], + savedBlocks[2], + savedBlocks[1], + savedBlocks[0], + } + + for i, block := range wanted { + if !proto.Equal(block, filteredBlocks[i].Proto()) { + t.Error("Did not get wanted blocks") + } + } +} + +func TestLoadBlocks_SecondBranch(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + + roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32)) + require.NoError(t, err) + + filteredBlocks, err := s.LoadBlocks(ctx, 0, 5, roots[5]) + require.NoError(t, err) + + wanted := []*ethpb.SignedBeaconBlock{ + savedBlocks[5], + savedBlocks[3], + savedBlocks[1], + savedBlocks[0], + } + + for i, block := range wanted { + if !proto.Equal(block, filteredBlocks[i].Proto()) { + t.Error("Did not get wanted blocks") + } + } +} + +func TestLoadBlocks_ThirdBranch(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + + roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32)) + require.NoError(t, err) + + filteredBlocks, err := s.LoadBlocks(ctx, 0, 7, roots[7]) + require.NoError(t, err) + + wanted := []*ethpb.SignedBeaconBlock{ + savedBlocks[7], + savedBlocks[6], + savedBlocks[4], + savedBlocks[2], + savedBlocks[1], + savedBlocks[0], + } + + for i, block := range wanted { + if !proto.Equal(block, filteredBlocks[i].Proto()) { + t.Error("Did not get wanted blocks") + } + } +} + +func TestLoadBlocks_SameSlots(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + + roots, savedBlocks, err := tree2(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32)) + require.NoError(t, err) + + filteredBlocks, err := s.LoadBlocks(ctx, 0, 3, roots[6]) + require.NoError(t, err) + + wanted := []*ethpb.SignedBeaconBlock{ + savedBlocks[6], + savedBlocks[5], + savedBlocks[1], + savedBlocks[0], + } + + for i, block := range wanted { + if !proto.Equal(block, filteredBlocks[i].Proto()) { + t.Error("Did not get wanted blocks") + } + } +} + +func TestLoadBlocks_SameEndSlots(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + + roots, savedBlocks, err := tree3(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32)) + require.NoError(t, err) + + filteredBlocks, err := s.LoadBlocks(ctx, 0, 2, roots[2]) + require.NoError(t, err) + + wanted := []*ethpb.SignedBeaconBlock{ + savedBlocks[2], + savedBlocks[1], + savedBlocks[0], + } + + for i, block := range wanted { + if !proto.Equal(block, filteredBlocks[i].Proto()) { + t.Error("Did not get wanted blocks") + } + } +} + +func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + + roots, savedBlocks, err := tree4(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32)) + require.NoError(t, err) + + filteredBlocks, err := s.LoadBlocks(ctx, 0, 2, roots[1]) + require.NoError(t, err) + + wanted := []*ethpb.SignedBeaconBlock{ + savedBlocks[1], + savedBlocks[0], + } + + for i, block := range wanted { + if !proto.Equal(block, filteredBlocks[i].Proto()) { + t.Error("Did not get wanted blocks") + } + } +} + +func TestLoadBlocks_BadStart(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + + roots, _, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32)) + require.NoError(t, err) + _, err = s.LoadBlocks(ctx, 0, 5, roots[8]) + assert.ErrorContains(t, "end block roots don't match", err) +} + +func TestLastSavedBlock_Genesis(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + finalizedInfo: &finalizedInfo{slot: 128}, + } + + gBlk := util.NewBeaconBlock() + gRoot, err := gBlk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk))) + require.NoError(t, s.beaconDB.SaveGenesisBlockRoot(ctx, gRoot)) + + savedRoot, savedSlot, err := s.lastSavedBlock(ctx, 0) + require.NoError(t, err) + assert.Equal(t, types.Slot(0), savedSlot, "Did not save genesis slot") + assert.Equal(t, savedRoot, savedRoot, "Did not save genesis root") +} + +func TestLastSavedBlock_CanGet(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + finalizedInfo: &finalizedInfo{slot: 128}, + } + + b1 := util.NewBeaconBlock() + b1.Block.Slot = s.finalizedInfo.slot + 5 + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + b2 := util.NewBeaconBlock() + b2.Block.Slot = s.finalizedInfo.slot + 10 + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) + b3 := util.NewBeaconBlock() + b3.Block.Slot = s.finalizedInfo.slot + 20 + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) + + savedRoot, savedSlot, err := s.lastSavedBlock(ctx, s.finalizedInfo.slot+100) + require.NoError(t, err) + assert.Equal(t, s.finalizedInfo.slot+20, savedSlot) + wantedRoot, err := b3.Block.HashTreeRoot() + require.NoError(t, err) + assert.Equal(t, wantedRoot, savedRoot, "Did not save correct root") +} + +func TestLastSavedBlock_NoSavedBlock(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + finalizedInfo: &finalizedInfo{slot: 128}, + } + + root, slot, err := s.lastSavedBlock(ctx, s.finalizedInfo.slot+1) + require.NoError(t, err) + if slot != 0 && root != [32]byte{} { + t.Error("Did not get wanted block") + } +} + +func TestLastSavedState_Genesis(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + finalizedInfo: &finalizedInfo{slot: 128}, + } + + gBlk := util.NewBeaconBlock() + gState, err := util.NewBeaconState() + require.NoError(t, err) + gRoot, err := gBlk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk))) + require.NoError(t, s.beaconDB.SaveGenesisBlockRoot(ctx, gRoot)) + require.NoError(t, s.beaconDB.SaveState(ctx, gState, gRoot)) + + savedState, err := s.lastSavedState(ctx, 0) + require.NoError(t, err) + require.DeepSSZEqual(t, gState.InnerStateUnsafe(), savedState.InnerStateUnsafe()) +} + +func TestLastSavedState_CanGet(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + finalizedInfo: &finalizedInfo{slot: 128}, + } + + b1 := util.NewBeaconBlock() + b1.Block.Slot = s.finalizedInfo.slot + 5 + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + b2 := util.NewBeaconBlock() + b2.Block.Slot = s.finalizedInfo.slot + 10 + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) + b2Root, err := b2.Block.HashTreeRoot() + require.NoError(t, err) + st, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, st.SetSlot(s.finalizedInfo.slot+10)) + + require.NoError(t, s.beaconDB.SaveState(ctx, st, b2Root)) + b3 := util.NewBeaconBlock() + b3.Block.Slot = s.finalizedInfo.slot + 20 + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) + + savedState, err := s.lastSavedState(ctx, s.finalizedInfo.slot+100) + require.NoError(t, err) + require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedState.InnerStateUnsafe()) +} + +func TestLastSavedState_NoSavedBlockState(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + finalizedInfo: &finalizedInfo{slot: 128}, + } + + b1 := util.NewBeaconBlock() + b1.Block.Slot = 127 + require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) + + _, err := s.lastSavedState(ctx, s.finalizedInfo.slot+1) + assert.ErrorContains(t, errUnknownState.Error(), err) +} + +// tree1 constructs the following tree: +// B0 - B1 - - B3 -- B5 +// \- B2 -- B4 -- B6 ----- B8 +// \- B7 +func tree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { + b0 := util.NewBeaconBlock() + b0.Block.Slot = 0 + b0.Block.ParentRoot = genesisRoot + r0, err := b0.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b1 := util.NewBeaconBlock() + b1.Block.Slot = 1 + b1.Block.ParentRoot = r0[:] + r1, err := b1.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b2 := util.NewBeaconBlock() + b2.Block.Slot = 2 + b2.Block.ParentRoot = r1[:] + r2, err := b2.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b3 := util.NewBeaconBlock() + b3.Block.Slot = 3 + b3.Block.ParentRoot = r1[:] + r3, err := b3.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b4 := util.NewBeaconBlock() + b4.Block.Slot = 4 + b4.Block.ParentRoot = r2[:] + r4, err := b4.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b5 := util.NewBeaconBlock() + b5.Block.Slot = 5 + b5.Block.ParentRoot = r3[:] + r5, err := b5.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b6 := util.NewBeaconBlock() + b6.Block.Slot = 6 + b6.Block.ParentRoot = r4[:] + r6, err := b6.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b7 := util.NewBeaconBlock() + b7.Block.Slot = 7 + b7.Block.ParentRoot = r6[:] + r7, err := b7.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b8 := util.NewBeaconBlock() + b8.Block.Slot = 8 + b8.Block.ParentRoot = r6[:] + r8, err := b8.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + st, err := util.NewBeaconState() + require.NoError(t, err) + + returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0) + for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b2, b3, b4, b5, b6, b7, b8} { + beaconBlock := util.NewBeaconBlock() + beaconBlock.Block.Slot = b.Block.Slot + beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) + if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil { + return nil, nil, err + } + if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil { + return nil, nil, err + } + returnedBlocks = append(returnedBlocks, beaconBlock) + } + return [][32]byte{r0, r1, r2, r3, r4, r5, r6, r7, r8}, returnedBlocks, nil +} + +// tree2 constructs the following tree: +// B0 - B1 +// \- B2 +// \- B2 +// \- B2 +// \- B2 -- B3 +func tree2(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { + b0 := util.NewBeaconBlock() + b0.Block.Slot = 0 + b0.Block.ParentRoot = genesisRoot + r0, err := b0.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b1 := util.NewBeaconBlock() + b1.Block.Slot = 1 + b1.Block.ParentRoot = r0[:] + r1, err := b1.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b21 := util.NewBeaconBlock() + b21.Block.Slot = 2 + b21.Block.ParentRoot = r1[:] + b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32) + r21, err := b21.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b22 := util.NewBeaconBlock() + b22.Block.Slot = 2 + b22.Block.ParentRoot = r1[:] + b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32) + r22, err := b22.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b23 := util.NewBeaconBlock() + b23.Block.Slot = 2 + b23.Block.ParentRoot = r1[:] + b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32) + r23, err := b23.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b24 := util.NewBeaconBlock() + b24.Block.Slot = 2 + b24.Block.ParentRoot = r1[:] + b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32) + r24, err := b24.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b3 := util.NewBeaconBlock() + b3.Block.Slot = 3 + b3.Block.ParentRoot = r24[:] + r3, err := b3.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + st, err := util.NewBeaconState() + require.NoError(t, err) + + returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0) + for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b21, b22, b23, b24, b3} { + beaconBlock := util.NewBeaconBlock() + beaconBlock.Block.Slot = b.Block.Slot + beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) + beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32) + if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil { + return nil, nil, err + } + if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil { + return nil, nil, err + } + returnedBlocks = append(returnedBlocks, beaconBlock) + } + return [][32]byte{r0, r1, r21, r22, r23, r24, r3}, returnedBlocks, nil +} + +// tree3 constructs the following tree: +// B0 - B1 +// \- B2 +// \- B2 +// \- B2 +// \- B2 +func tree3(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { + b0 := util.NewBeaconBlock() + b0.Block.Slot = 0 + b0.Block.ParentRoot = genesisRoot + r0, err := b0.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b1 := util.NewBeaconBlock() + b1.Block.Slot = 1 + b1.Block.ParentRoot = r0[:] + r1, err := b1.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b21 := util.NewBeaconBlock() + b21.Block.Slot = 2 + b21.Block.ParentRoot = r1[:] + b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32) + r21, err := b21.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b22 := util.NewBeaconBlock() + b22.Block.Slot = 2 + b22.Block.ParentRoot = r1[:] + b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32) + r22, err := b22.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b23 := util.NewBeaconBlock() + b23.Block.Slot = 2 + b23.Block.ParentRoot = r1[:] + b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32) + r23, err := b23.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b24 := util.NewBeaconBlock() + b24.Block.Slot = 2 + b24.Block.ParentRoot = r1[:] + b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32) + r24, err := b24.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + st, err := util.NewBeaconState() + require.NoError(t, err) + + returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0) + for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b21, b22, b23, b24} { + beaconBlock := util.NewBeaconBlock() + beaconBlock.Block.Slot = b.Block.Slot + beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) + beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32) + if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil { + return nil, nil, err + } + if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil { + return nil, nil, err + } + returnedBlocks = append(returnedBlocks, beaconBlock) + } + + return [][32]byte{r0, r1, r21, r22, r23, r24}, returnedBlocks, nil +} + +// tree4 constructs the following tree: +// B0 +// \- B2 +// \- B2 +// \- B2 +// \- B2 +func tree4(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { + b0 := util.NewBeaconBlock() + b0.Block.Slot = 0 + b0.Block.ParentRoot = genesisRoot + r0, err := b0.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b21 := util.NewBeaconBlock() + b21.Block.Slot = 2 + b21.Block.ParentRoot = r0[:] + b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32) + r21, err := b21.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b22 := util.NewBeaconBlock() + b22.Block.Slot = 2 + b22.Block.ParentRoot = r0[:] + b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32) + r22, err := b22.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b23 := util.NewBeaconBlock() + b23.Block.Slot = 2 + b23.Block.ParentRoot = r0[:] + b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32) + r23, err := b23.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + b24 := util.NewBeaconBlock() + b24.Block.Slot = 2 + b24.Block.ParentRoot = r0[:] + b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32) + r24, err := b24.Block.HashTreeRoot() + if err != nil { + return nil, nil, err + } + st, err := util.NewBeaconState() + require.NoError(t, err) + + returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0) + for _, b := range []*ethpb.SignedBeaconBlock{b0, b21, b22, b23, b24} { + beaconBlock := util.NewBeaconBlock() + beaconBlock.Block.Slot = b.Block.Slot + beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) + beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32) + if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil { + return nil, nil, err + } + if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil { + return nil, nil, err + } + returnedBlocks = append(returnedBlocks, beaconBlock) + } + + return [][32]byte{r0, r21, r22, r23, r24}, returnedBlocks, nil +} + +func TestLoadFinalizedBlocks(t *testing.T) { + beaconDB := testDB.SetupDB(t) + ctx := context.Background() + s := &State{ + beaconDB: beaconDB, + } + gBlock := util.NewBeaconBlock() + gRoot, err := gBlock.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlock))) + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, [32]byte{})) + roots, _, err := tree1(t, beaconDB, gRoot[:]) + require.NoError(t, err) + + filteredBlocks, err := s.loadFinalizedBlocks(ctx, 0, 8) + require.NoError(t, err) + require.Equal(t, 0, len(filteredBlocks)) + require.NoError(t, beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: roots[8][:]})) + + require.NoError(t, s.beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: roots[8][:]})) + filteredBlocks, err = s.loadFinalizedBlocks(ctx, 0, 8) + require.NoError(t, err) + require.Equal(t, 10, len(filteredBlocks)) +} diff --git a/beacon-chain/state-proto/stategen/service.go b/beacon-chain/state-proto/stategen/service.go new file mode 100644 index 0000000000..95cf97ac1d --- /dev/null +++ b/beacon-chain/state-proto/stategen/service.go @@ -0,0 +1,140 @@ +// Package stategen defines functions to regenerate beacon chain states +// by replaying blocks from a stored state checkpoint, useful for +// optimization and reducing a beacon node's resource consumption. +package stategen + +import ( + "context" + "errors" + "sync" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/db" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" + "go.opencensus.io/trace" +) + +var defaultHotStateDBInterval types.Slot = 128 + +// StateManager represents a management object that handles the internal +// logic of maintaining both hot and cold states in DB. +type StateManager interface { + Resume(ctx context.Context, fState state.BeaconState) (state.BeaconState, error) + SaveFinalizedState(fSlot types.Slot, fRoot [32]byte, fState state.BeaconState) + MigrateToCold(ctx context.Context, fRoot [32]byte) error + ReplayBlocks(ctx context.Context, state state.BeaconState, signed []block.SignedBeaconBlock, targetSlot types.Slot) (state.BeaconState, error) + LoadBlocks(ctx context.Context, startSlot, endSlot types.Slot, endBlockRoot [32]byte) ([]block.SignedBeaconBlock, error) + HasState(ctx context.Context, blockRoot [32]byte) (bool, error) + HasStateInCache(ctx context.Context, blockRoot [32]byte) (bool, error) + StateByRoot(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error) + StateByRootIfCachedNoCopy(blockRoot [32]byte) state.BeaconState + StateByRootInitialSync(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error) + StateBySlot(ctx context.Context, slot types.Slot) (state.BeaconState, error) + RecoverStateSummary(ctx context.Context, blockRoot [32]byte) (*ethpb.StateSummary, error) + SaveState(ctx context.Context, root [32]byte, st state.BeaconState) error + ForceCheckpoint(ctx context.Context, root []byte) error + EnableSaveHotStateToDB(_ context.Context) + DisableSaveHotStateToDB(ctx context.Context) error +} + +// State is a concrete implementation of StateManager. +type State struct { + beaconDB db.NoHeadAccessDatabase + slotsPerArchivedPoint types.Slot + hotStateCache *hotStateCache + finalizedInfo *finalizedInfo + epochBoundaryStateCache *epochBoundaryState + saveHotStateDB *saveHotStateDbConfig +} + +// This tracks the config in the event of long non-finality, +// how often does the node save hot states to db? what are +// the saved hot states in db?... etc +type saveHotStateDbConfig struct { + enabled bool + lock sync.Mutex + duration types.Slot + savedStateRoots [][32]byte +} + +// This tracks the finalized point. It's also the point where slot and the block root of +// cold and hot sections of the DB splits. +type finalizedInfo struct { + slot types.Slot + root [32]byte + state state.BeaconState + lock sync.RWMutex +} + +// New returns a new state management object. +func New(beaconDB db.NoHeadAccessDatabase) *State { + return &State{ + beaconDB: beaconDB, + hotStateCache: newHotStateCache(), + finalizedInfo: &finalizedInfo{slot: 0, root: params.BeaconConfig().ZeroHash}, + slotsPerArchivedPoint: params.BeaconConfig().SlotsPerArchivedPoint, + epochBoundaryStateCache: newBoundaryStateCache(), + saveHotStateDB: &saveHotStateDbConfig{ + duration: defaultHotStateDBInterval, + }, + } +} + +// Resume resumes a new state management object from previously saved finalized check point in DB. +func (s *State) Resume(ctx context.Context, fState state.BeaconState) (state.BeaconState, error) { + ctx, span := trace.StartSpan(ctx, "stateGen.Resume") + defer span.End() + + c, err := s.beaconDB.FinalizedCheckpoint(ctx) + if err != nil { + return nil, err + } + fRoot := bytesutil.ToBytes32(c.Root) + // Resume as genesis state if last finalized root is zero hashes. + if fRoot == params.BeaconConfig().ZeroHash { + return s.beaconDB.GenesisState(ctx) + } + + if fState == nil || fState.IsNil() { + return nil, errors.New("finalized state is nil") + } + + go func() { + if err := s.beaconDB.CleanUpDirtyStates(ctx, s.slotsPerArchivedPoint); err != nil { + log.WithError(err).Error("Could not clean up dirty states") + } + }() + + s.finalizedInfo = &finalizedInfo{slot: fState.Slot(), root: fRoot, state: fState.Copy()} + + return fState, nil +} + +// SaveFinalizedState saves the finalized slot, root and state into memory to be used by state gen service. +// This used for migration at the correct start slot and used for hot state play back to ensure +// lower bound to start is always at the last finalized state. +func (s *State) SaveFinalizedState(fSlot types.Slot, fRoot [32]byte, fState state.BeaconState) { + s.finalizedInfo.lock.Lock() + defer s.finalizedInfo.lock.Unlock() + s.finalizedInfo.root = fRoot + s.finalizedInfo.state = fState.Copy() + s.finalizedInfo.slot = fSlot +} + +// Returns true if input root equals to cached finalized root. +func (s *State) isFinalizedRoot(r [32]byte) bool { + s.finalizedInfo.lock.RLock() + defer s.finalizedInfo.lock.RUnlock() + return r == s.finalizedInfo.root +} + +// Returns the cached and copied finalized state. +func (s *State) finalizedState() state.BeaconState { + s.finalizedInfo.lock.RLock() + defer s.finalizedInfo.lock.RUnlock() + return s.finalizedInfo.state.Copy() +} diff --git a/beacon-chain/state-proto/stategen/service_test.go b/beacon-chain/state-proto/stategen/service_test.go new file mode 100644 index 0000000000..e839cca80b --- /dev/null +++ b/beacon-chain/state-proto/stategen/service_test.go @@ -0,0 +1,37 @@ +package stategen + +import ( + "context" + "testing" + + testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestResume(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + b := util.NewBeaconBlock() + require.NoError(t, service.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + root, err := b.Block.HashTreeRoot() + require.NoError(t, err) + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, root)) + require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, root)) + require.NoError(t, service.beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: root[:]})) + + resumeState, err := service.Resume(ctx, beaconState) + require.NoError(t, err) + require.DeepSSZEqual(t, beaconState.InnerStateUnsafe(), resumeState.InnerStateUnsafe()) + assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, service.finalizedInfo.slot, "Did not get watned slot") + assert.Equal(t, service.finalizedInfo.root, root, "Did not get wanted root") + assert.NotNil(t, service.finalizedState(), "Wanted a non nil finalized state") +} diff --git a/beacon-chain/state-proto/stategen/setter.go b/beacon-chain/state-proto/stategen/setter.go new file mode 100644 index 0000000000..06e349eb2f --- /dev/null +++ b/beacon-chain/state-proto/stategen/setter.go @@ -0,0 +1,135 @@ +package stategen + +import ( + "context" + "math" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/time/slots" + "github.com/sirupsen/logrus" + "go.opencensus.io/trace" +) + +// SaveState saves the state in the cache and/or DB. +func (s *State) SaveState(ctx context.Context, root [32]byte, st state.BeaconState) error { + ctx, span := trace.StartSpan(ctx, "stateGen.SaveState") + defer span.End() + + return s.saveStateByRoot(ctx, root, st) +} + +// ForceCheckpoint initiates a cold state save of the given state. This method does not update the +// "last archived state" but simply saves the specified state from the root argument into the DB. +func (s *State) ForceCheckpoint(ctx context.Context, root []byte) error { + ctx, span := trace.StartSpan(ctx, "stateGen.ForceCheckpoint") + defer span.End() + + root32 := bytesutil.ToBytes32(root) + // Before the first finalized check point, the finalized root is zero hash. + // Return early if there hasn't been a finalized check point. + if root32 == params.BeaconConfig().ZeroHash { + return nil + } + + fs, err := s.loadStateByRoot(ctx, root32) + if err != nil { + return err + } + + return s.beaconDB.SaveState(ctx, fs, root32) +} + +// This saves a post beacon state. On the epoch boundary, +// it saves a full state. On an intermediate slot, it saves a back pointer to the +// nearest epoch boundary state. +func (s *State) saveStateByRoot(ctx context.Context, blockRoot [32]byte, st state.BeaconState) error { + ctx, span := trace.StartSpan(ctx, "stateGen.saveStateByRoot") + defer span.End() + + // Duration can't be 0 to prevent panic for division. + duration := uint64(math.Max(float64(s.saveHotStateDB.duration), 1)) + + s.saveHotStateDB.lock.Lock() + if s.saveHotStateDB.enabled && st.Slot().Mod(duration) == 0 { + if err := s.beaconDB.SaveState(ctx, st, blockRoot); err != nil { + s.saveHotStateDB.lock.Unlock() + return err + } + s.saveHotStateDB.savedStateRoots = append(s.saveHotStateDB.savedStateRoots, blockRoot) + + log.WithFields(logrus.Fields{ + "slot": st.Slot(), + "totalHotStateSavedInDB": len(s.saveHotStateDB.savedStateRoots), + }).Info("Saving hot state to DB") + } + s.saveHotStateDB.lock.Unlock() + + // If the hot state is already in cache, one can be sure the state was processed and in the DB. + if s.hotStateCache.has(blockRoot) { + return nil + } + + // Only on an epoch boundary slot, saves epoch boundary state in epoch boundary root state cache. + if slots.IsEpochStart(st.Slot()) { + if err := s.epochBoundaryStateCache.put(blockRoot, st); err != nil { + return err + } + } + + // On an intermediate slots, save state summary. + if err := s.beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{ + Slot: st.Slot(), + Root: blockRoot[:], + }); err != nil { + return err + } + + // Store the copied state in the hot state cache. + s.hotStateCache.put(blockRoot, st) + + return nil +} + +// EnableSaveHotStateToDB enters the mode that saves hot beacon state to the DB. +// This usually gets triggered when there's long duration since finality. +func (s *State) EnableSaveHotStateToDB(_ context.Context) { + s.saveHotStateDB.lock.Lock() + defer s.saveHotStateDB.lock.Unlock() + if s.saveHotStateDB.enabled { + return + } + + s.saveHotStateDB.enabled = true + + log.WithFields(logrus.Fields{ + "enabled": s.saveHotStateDB.enabled, + "slotsInterval": s.saveHotStateDB.duration, + }).Warn("Entering mode to save hot states in DB") +} + +// DisableSaveHotStateToDB exits the mode that saves beacon state to DB for the hot states. +// This usually gets triggered once there's finality after long duration since finality. +func (s *State) DisableSaveHotStateToDB(ctx context.Context) error { + s.saveHotStateDB.lock.Lock() + defer s.saveHotStateDB.lock.Unlock() + if !s.saveHotStateDB.enabled { + return nil + } + + log.WithFields(logrus.Fields{ + "enabled": s.saveHotStateDB.enabled, + "deletedHotStates": len(s.saveHotStateDB.savedStateRoots), + }).Warn("Exiting mode to save hot states in DB") + + // Delete previous saved states in DB as we are turning this mode off. + s.saveHotStateDB.enabled = false + if err := s.beaconDB.DeleteStates(ctx, s.saveHotStateDB.savedStateRoots); err != nil { + return err + } + s.saveHotStateDB.savedStateRoots = nil + + return nil +} diff --git a/beacon-chain/state-proto/stategen/setter_test.go b/beacon-chain/state-proto/stategen/setter_test.go new file mode 100644 index 0000000000..f0dc9ce205 --- /dev/null +++ b/beacon-chain/state-proto/stategen/setter_test.go @@ -0,0 +1,204 @@ +package stategen + +import ( + "context" + "testing" + + testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" + logTest "github.com/sirupsen/logrus/hooks/test" +) + +func TestSaveState_HotStateCanBeSaved(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.slotsPerArchivedPoint = 1 + beaconState, _ := util.DeterministicGenesisState(t, 32) + // This goes to hot section, verify it can save on epoch boundary. + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + + r := [32]byte{'a'} + require.NoError(t, service.SaveState(ctx, r, beaconState)) + + // Should save both state and state summary. + _, ok, err := service.epochBoundaryStateCache.getByRoot(r) + require.NoError(t, err) + assert.Equal(t, true, ok, "Should have saved the state") + assert.Equal(t, true, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary") +} + +func TestSaveState_HotStateCached(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + service := New(beaconDB) + service.slotsPerArchivedPoint = 1 + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + + // Cache the state prior. + r := [32]byte{'a'} + service.hotStateCache.put(r, beaconState) + require.NoError(t, service.SaveState(ctx, r, beaconState)) + + // Should not save the state and state summary. + assert.Equal(t, false, service.beaconDB.HasState(ctx, r), "Should not have saved the state") + assert.Equal(t, false, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary") + require.LogsDoNotContain(t, hook, "Saved full state on epoch boundary") +} + +func TestState_ForceCheckpoint_SavesStateToDatabase(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + svc := New(beaconDB) + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + + r := [32]byte{'a'} + svc.hotStateCache.put(r, beaconState) + + require.Equal(t, false, beaconDB.HasState(ctx, r), "Database has state stored already") + assert.NoError(t, svc.ForceCheckpoint(ctx, r[:])) + assert.Equal(t, true, beaconDB.HasState(ctx, r), "Did not save checkpoint to database") + + // Should not panic with genesis finalized root. + assert.NoError(t, svc.ForceCheckpoint(ctx, params.BeaconConfig().ZeroHash[:])) +} + +func TestSaveState_Alreadyhas(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + r := [32]byte{'A'} + + // Pre cache the hot state. + service.hotStateCache.put(r, beaconState) + require.NoError(t, service.saveStateByRoot(ctx, r, beaconState)) + + // Should not save the state and state summary. + assert.Equal(t, false, service.beaconDB.HasState(ctx, r), "Should not have saved the state") + assert.Equal(t, false, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary") + require.LogsDoNotContain(t, hook, "Saved full state on epoch boundary") +} + +func TestSaveState_CanSaveOnEpochBoundary(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + r := [32]byte{'A'} + + require.NoError(t, service.saveStateByRoot(ctx, r, beaconState)) + + // Should save both state and state summary. + _, ok, err := service.epochBoundaryStateCache.getByRoot(r) + require.NoError(t, err) + require.Equal(t, true, ok, "Did not save epoch boundary state") + assert.Equal(t, true, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary") + // Should have not been saved in DB. + require.Equal(t, false, beaconDB.HasState(ctx, r)) +} + +func TestSaveState_NoSaveNotEpochBoundary(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch-1)) + r := [32]byte{'A'} + b := util.NewBeaconBlock() + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + gRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot)) + require.NoError(t, service.SaveState(ctx, r, beaconState)) + + // Should only save state summary. + assert.Equal(t, false, service.beaconDB.HasState(ctx, r), "Should not have saved the state") + assert.Equal(t, true, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary") + require.LogsDoNotContain(t, hook, "Saved full state on epoch boundary") + // Should have not been saved in DB. + require.Equal(t, false, beaconDB.HasState(ctx, r)) +} + +func TestSaveState_CanSaveHotStateToDB(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + service.EnableSaveHotStateToDB(ctx) + beaconState, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, beaconState.SetSlot(defaultHotStateDBInterval)) + + r := [32]byte{'A'} + require.NoError(t, service.saveStateByRoot(ctx, r, beaconState)) + + require.LogsContain(t, hook, "Saving hot state to DB") + // Should have saved in DB. + require.Equal(t, true, beaconDB.HasState(ctx, r)) +} + +func TestEnableSaveHotStateToDB_Enabled(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + + service.EnableSaveHotStateToDB(ctx) + require.LogsContain(t, hook, "Entering mode to save hot states in DB") + require.Equal(t, true, service.saveHotStateDB.enabled) +} + +func TestEnableSaveHotStateToDB_AlreadyEnabled(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + service.saveHotStateDB.enabled = true + service.EnableSaveHotStateToDB(ctx) + require.LogsDoNotContain(t, hook, "Entering mode to save hot states in DB") + require.Equal(t, true, service.saveHotStateDB.enabled) +} + +func TestEnableSaveHotStateToDB_Disabled(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + service.saveHotStateDB.enabled = true + b := util.NewBeaconBlock() + require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) + r, err := b.Block.HashTreeRoot() + require.NoError(t, err) + service.saveHotStateDB.savedStateRoots = [][32]byte{r} + require.NoError(t, service.DisableSaveHotStateToDB(ctx)) + require.LogsContain(t, hook, "Exiting mode to save hot states in DB") + require.Equal(t, false, service.saveHotStateDB.enabled) + require.Equal(t, 0, len(service.saveHotStateDB.savedStateRoots)) +} + +func TestEnableSaveHotStateToDB_AlreadyDisabled(t *testing.T) { + hook := logTest.NewGlobal() + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + service := New(beaconDB) + require.NoError(t, service.DisableSaveHotStateToDB(ctx)) + require.LogsDoNotContain(t, hook, "Exiting mode to save hot states in DB") + require.Equal(t, false, service.saveHotStateDB.enabled) +} diff --git a/beacon-chain/state-proto/stateutil/BUILD.bazel b/beacon-chain/state-proto/stateutil/BUILD.bazel new file mode 100644 index 0000000000..ebf3950f37 --- /dev/null +++ b/beacon-chain/state-proto/stateutil/BUILD.bazel @@ -0,0 +1,101 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "block_header_root.go", + "eth1_root.go", + "field_root_attestation.go", + "field_root_eth1.go", + "field_root_validator.go", + "field_root_vector.go", + "participation_bit_root.go", + "pending_attestation_root.go", + "reference.go", + "state_hasher.go", + "sync_committee.root.go", + "trie_helpers.go", + "validator_map_handler.go", + "validator_root.go", + ], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil", + visibility = [ + "//beacon-chain:__subpackages__", + "//proto/migration:__subpackages__", + "//proto/prysm/v1alpha1:__subpackages__", + "//proto/testing:__subpackages__", + "//slasher:__subpackages__", + "//testing:__subpackages__", + "//testing/fuzz:__pkg__", + "//tools/blocktree:__pkg__", + "//tools/pcli:__pkg__", + "//validator/client:__pkg__", + ], + deps = [ + "//beacon-chain/core/transition/stateutils:go_default_library", + "//config/features:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//container/trie:go_default_library", + "//crypto/hash:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//math:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "@com_github_dgraph_io_ristretto//:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@io_opencensus_go//trace:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "benchmark_test.go", + "field_root_test.go", + "reference_bench_test.go", + "state_root_test.go", + "stateutil_test.go", + "trie_helpers_test.go", + "validator_root_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//config/features:go_default_library", + "//config/params:go_default_library", + "//crypto/hash:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/interop:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + ], +) + +go_test( + name = "go_benchmark_test", + size = "medium", + srcs = ["benchmark_test.go"], + args = [ + "-test.bench=.", + "-test.benchmem", + "-test.v", + ], + local = True, + tags = [ + "benchmark", + "no-cache", + ], + deps = [ + "//beacon-chain/state-proto/stateutil:go_default_library", + "//crypto/hash:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + ], +) diff --git a/beacon-chain/state-proto/stateutil/benchmark_test.go b/beacon-chain/state-proto/stateutil/benchmark_test.go new file mode 100644 index 0000000000..90a187d08c --- /dev/null +++ b/beacon-chain/state-proto/stateutil/benchmark_test.go @@ -0,0 +1,30 @@ +package stateutil_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/ssz" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func BenchmarkMerkleize_Buffered(b *testing.B) { + roots := make([][32]byte, 8192) + for i := 0; i < 8192; i++ { + roots[0] = [32]byte{byte(i)} + } + + newMerkleize := func(chunks [][32]byte, count uint64, limit uint64) ([32]byte, error) { + leafIndexer := func(i uint64) []byte { + return chunks[i][:] + } + return ssz.Merkleize(ssz.NewHasherFunc(hash.CustomSHA256Hasher()), count, limit, leafIndexer), nil + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := newMerkleize(roots, 8192, 8192) + require.NoError(b, err) + } +} diff --git a/beacon-chain/state-proto/stateutil/block_header_root.go b/beacon-chain/state-proto/stateutil/block_header_root.go new file mode 100644 index 0000000000..4f23c3131a --- /dev/null +++ b/beacon-chain/state-proto/stateutil/block_header_root.go @@ -0,0 +1,34 @@ +package stateutil + +import ( + "encoding/binary" + + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// BlockHeaderRoot computes the HashTreeRoot Merkleization of +// a BeaconBlockHeader struct according to the Ethereum +// Simple Serialize specification. +func BlockHeaderRoot(header *ethpb.BeaconBlockHeader) ([32]byte, error) { + fieldRoots := make([][]byte, 5) + if header != nil { + headerSlotBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(headerSlotBuf, uint64(header.Slot)) + headerSlotRoot := bytesutil.ToBytes32(headerSlotBuf) + fieldRoots[0] = headerSlotRoot[:] + proposerIdxBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(proposerIdxBuf, uint64(header.ProposerIndex)) + proposerIndexRoot := bytesutil.ToBytes32(proposerIdxBuf) + fieldRoots[1] = proposerIndexRoot[:] + parentRoot := bytesutil.ToBytes32(header.ParentRoot) + fieldRoots[2] = parentRoot[:] + stateRoot := bytesutil.ToBytes32(header.StateRoot) + fieldRoots[3] = stateRoot[:] + bodyRoot := bytesutil.ToBytes32(header.BodyRoot) + fieldRoots[4] = bodyRoot[:] + } + return ssz.BitwiseMerkleize(hash.CustomSHA256Hasher(), fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) +} diff --git a/beacon-chain/state-proto/stateutil/eth1_root.go b/beacon-chain/state-proto/stateutil/eth1_root.go new file mode 100644 index 0000000000..9a0c015abd --- /dev/null +++ b/beacon-chain/state-proto/stateutil/eth1_root.go @@ -0,0 +1,116 @@ +package stateutil + +import ( + "bytes" + "encoding/binary" + + "github.com/pkg/errors" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// eth1DataEncKey returns the encoded key in bytes of input `eth1Data`, +// the returned key bytes can be used for caching purposes. +func eth1DataEncKey(eth1Data *ethpb.Eth1Data) []byte { + enc := make([]byte, 0, 96) + if eth1Data != nil { + if len(eth1Data.DepositRoot) > 0 { + depRoot := bytesutil.ToBytes32(eth1Data.DepositRoot) + enc = append(enc, depRoot[:]...) + } + eth1DataCountBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(eth1DataCountBuf, eth1Data.DepositCount) + eth1CountRoot := bytesutil.ToBytes32(eth1DataCountBuf) + enc = append(enc, eth1CountRoot[:]...) + if len(eth1Data.BlockHash) > 0 { + blockHash := bytesutil.ToBytes32(eth1Data.BlockHash) + enc = append(enc, blockHash[:]...) + } + } + return enc +} + +// Eth1DataRootWithHasher returns the hash tree root of input `eth1Data`. +func Eth1DataRootWithHasher(hasher ssz.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) { + if eth1Data == nil { + return [32]byte{}, errors.New("nil eth1 data") + } + + fieldRoots := make([][]byte, 3) + for i := 0; i < len(fieldRoots); i++ { + fieldRoots[i] = make([]byte, 32) + } + if len(eth1Data.DepositRoot) > 0 { + depRoot := bytesutil.ToBytes32(eth1Data.DepositRoot) + fieldRoots[0] = depRoot[:] + } + eth1DataCountBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(eth1DataCountBuf, eth1Data.DepositCount) + eth1CountRoot := bytesutil.ToBytes32(eth1DataCountBuf) + fieldRoots[1] = eth1CountRoot[:] + if len(eth1Data.BlockHash) > 0 { + blockHash := bytesutil.ToBytes32(eth1Data.BlockHash) + fieldRoots[2] = blockHash[:] + } + root, err := ssz.BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + if err != nil { + return [32]byte{}, err + } + return root, nil +} + +// Eth1DatasEncKey returns the encoded key in bytes of input `eth1Data`s, +// the returned key bytes can be used for caching purposes. +func Eth1DatasEncKey(eth1Datas []*ethpb.Eth1Data) ([32]byte, error) { + hasher := hash.CustomSHA256Hasher() + enc := make([]byte, len(eth1Datas)*32) + for i := 0; i < len(eth1Datas); i++ { + eth1, err := Eth1DataRootWithHasher(hasher, eth1Datas[i]) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute eth1data merkleization") + } + copy(enc[(i*32):(i+1)*32], eth1[:]) + } + hashKey := hash.FastSum256(enc) + return hashKey, nil +} + +// Eth1DatasRoot returns the hash tree root of input `eth1Datas`. +func Eth1DatasRoot(eth1Datas []*ethpb.Eth1Data) ([32]byte, error) { + hasher := hash.CustomSHA256Hasher() + eth1VotesRoots := make([][]byte, 0) + for i := 0; i < len(eth1Datas); i++ { + eth1, err := Eth1DataRootWithHasher(hasher, eth1Datas[i]) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute eth1data merkleization") + } + eth1VotesRoots = append(eth1VotesRoots, eth1[:]) + } + eth1Chunks, err := ssz.Pack(eth1VotesRoots) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not chunk eth1 votes roots") + } + + eth1VotesRootsRoot, err := ssz.BitwiseMerkleize( + hasher, + eth1Chunks, + uint64(len(eth1Chunks)), + fieldparams.Eth1DataVotesLength, + ) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute eth1data votes merkleization") + } + eth1VotesRootBuf := new(bytes.Buffer) + if err := binary.Write(eth1VotesRootBuf, binary.LittleEndian, uint64(len(eth1Datas))); err != nil { + return [32]byte{}, errors.Wrap(err, "could not marshal eth1data votes length") + } + // We need to mix in the length of the slice. + eth1VotesRootBufRoot := make([]byte, 32) + copy(eth1VotesRootBufRoot, eth1VotesRootBuf.Bytes()) + root := ssz.MixInLength(eth1VotesRootsRoot, eth1VotesRootBufRoot) + + return root, nil +} diff --git a/beacon-chain/state-proto/stateutil/field_root_attestation.go b/beacon-chain/state-proto/stateutil/field_root_attestation.go new file mode 100644 index 0000000000..b6dbb6f136 --- /dev/null +++ b/beacon-chain/state-proto/stateutil/field_root_attestation.go @@ -0,0 +1,83 @@ +package stateutil + +import ( + "bytes" + "encoding/binary" + "fmt" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/config/features" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// RootsArrayHashTreeRoot computes the Merkle root of arrays of 32-byte hashes, such as [64][32]byte +// according to the Simple Serialize specification of Ethereum. +func RootsArrayHashTreeRoot(vals [][]byte, length uint64, fieldName string) ([32]byte, error) { + if features.Get().EnableSSZCache { + return CachedHasher.arraysRoot(vals, length, fieldName) + } + return NocachedHasher.arraysRoot(vals, length, fieldName) +} + +func (h *stateRootHasher) epochAttestationsRoot(atts []*ethpb.PendingAttestation) ([32]byte, error) { + max := uint64(fieldparams.CurrentEpochAttestationsLength) + if uint64(len(atts)) > max { + return [32]byte{}, fmt.Errorf("epoch attestation exceeds max length %d", max) + } + + hasher := hash.CustomSHA256Hasher() + roots := make([][]byte, len(atts)) + for i := 0; i < len(atts); i++ { + pendingRoot, err := h.pendingAttestationRoot(hasher, atts[i]) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not attestation merkleization") + } + roots[i] = pendingRoot[:] + } + + attsRootsRoot, err := ssz.BitwiseMerkleize( + hasher, + roots, + uint64(len(roots)), + fieldparams.CurrentEpochAttestationsLength, + ) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute epoch attestations merkleization") + } + attsLenBuf := new(bytes.Buffer) + if err := binary.Write(attsLenBuf, binary.LittleEndian, uint64(len(atts))); err != nil { + return [32]byte{}, errors.Wrap(err, "could not marshal epoch attestations length") + } + // We need to mix in the length of the slice. + attsLenRoot := make([]byte, 32) + copy(attsLenRoot, attsLenBuf.Bytes()) + res := ssz.MixInLength(attsRootsRoot, attsLenRoot) + return res, nil +} + +func (h *stateRootHasher) pendingAttestationRoot(hasher ssz.HashFn, att *ethpb.PendingAttestation) ([32]byte, error) { + if att == nil { + return [32]byte{}, errors.New("nil pending attestation") + } + // Marshal attestation to determine if it exists in the cache. + enc := pendingAttEncKey(att) + + // Check if it exists in cache: + if h.rootsCache != nil { + if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok { + return found.([32]byte), nil + } + } + + res, err := PendingAttRootWithHasher(hasher, att) + if err != nil { + return [32]byte{}, err + } + if h.rootsCache != nil { + h.rootsCache.Set(string(enc), res, 32) + } + return res, nil +} diff --git a/beacon-chain/state-proto/stateutil/field_root_eth1.go b/beacon-chain/state-proto/stateutil/field_root_eth1.go new file mode 100644 index 0000000000..de536fb23e --- /dev/null +++ b/beacon-chain/state-proto/stateutil/field_root_eth1.go @@ -0,0 +1,58 @@ +package stateutil + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/config/features" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// Eth1Root computes the HashTreeRoot Merkleization of +// a BeaconBlockHeader struct according to the eth2 +// Simple Serialize specification. +func Eth1Root(hasher ssz.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) { + if eth1Data == nil { + return [32]byte{}, errors.New("nil eth1 data") + } + + enc := eth1DataEncKey(eth1Data) + if features.Get().EnableSSZCache { + if found, ok := CachedHasher.rootsCache.Get(string(enc)); ok && found != nil { + return found.([32]byte), nil + } + } + + root, err := Eth1DataRootWithHasher(hasher, eth1Data) + if err != nil { + return [32]byte{}, err + } + + if features.Get().EnableSSZCache { + CachedHasher.rootsCache.Set(string(enc), root, 32) + } + return root, nil +} + +// eth1DataVotesRoot computes the HashTreeRoot Merkleization of +// a list of Eth1Data structs according to the eth2 +// Simple Serialize specification. +func eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) { + hashKey, err := Eth1DatasEncKey(eth1DataVotes) + if err != nil { + return [32]byte{}, err + } + + if features.Get().EnableSSZCache { + if found, ok := CachedHasher.rootsCache.Get(string(hashKey[:])); ok && found != nil { + return found.([32]byte), nil + } + } + root, err := Eth1DatasRoot(eth1DataVotes) + if err != nil { + return [32]byte{}, err + } + if features.Get().EnableSSZCache { + CachedHasher.rootsCache.Set(string(hashKey[:]), root, 32) + } + return root, nil +} diff --git a/beacon-chain/state-proto/stateutil/field_root_test.go b/beacon-chain/state-proto/stateutil/field_root_test.go new file mode 100644 index 0000000000..3d74deb89e --- /dev/null +++ b/beacon-chain/state-proto/stateutil/field_root_test.go @@ -0,0 +1,23 @@ +package stateutil + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/testing/assert" +) + +func TestArraysTreeRoot_OnlyPowerOf2(t *testing.T) { + _, err := NocachedHasher.arraysRoot([][]byte{}, 1, "testing") + assert.NoError(t, err) + _, err = NocachedHasher.arraysRoot([][]byte{}, 4, "testing") + assert.NoError(t, err) + _, err = NocachedHasher.arraysRoot([][]byte{}, 8, "testing") + assert.NoError(t, err) + _, err = NocachedHasher.arraysRoot([][]byte{}, 10, "testing") + assert.ErrorContains(t, "hash layer is a non power of 2", err) +} + +func TestArraysTreeRoot_ZeroLength(t *testing.T) { + _, err := NocachedHasher.arraysRoot([][]byte{}, 0, "testing") + assert.ErrorContains(t, "zero leaves provided", err) +} diff --git a/beacon-chain/state-proto/stateutil/field_root_validator.go b/beacon-chain/state-proto/stateutil/field_root_validator.go new file mode 100644 index 0000000000..a2283ebbde --- /dev/null +++ b/beacon-chain/state-proto/stateutil/field_root_validator.go @@ -0,0 +1,88 @@ +package stateutil + +import ( + "bytes" + "encoding/binary" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/config/features" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// ValidatorRegistryRoot computes the HashTreeRoot Merkleization of +// a list of validator structs according to the Ethereum +// Simple Serialize specification. +func ValidatorRegistryRoot(vals []*ethpb.Validator) ([32]byte, error) { + if features.Get().EnableSSZCache { + return CachedHasher.validatorRegistryRoot(vals) + } + return NocachedHasher.validatorRegistryRoot(vals) +} + +func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) { + hashKeyElements := make([]byte, len(validators)*32) + roots := make([][32]byte, len(validators)) + emptyKey := hash.FastSum256(hashKeyElements) + hasher := hash.CustomSHA256Hasher() + bytesProcessed := 0 + for i := 0; i < len(validators); i++ { + val, err := h.validatorRoot(hasher, validators[i]) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute validators merkleization") + } + copy(hashKeyElements[bytesProcessed:bytesProcessed+32], val[:]) + roots[i] = val + bytesProcessed += 32 + } + + hashKey := hash.FastSum256(hashKeyElements) + if hashKey != emptyKey && h.rootsCache != nil { + if found, ok := h.rootsCache.Get(string(hashKey[:])); found != nil && ok { + return found.([32]byte), nil + } + } + + validatorsRootsRoot, err := ssz.BitwiseMerkleizeArrays(hasher, roots, uint64(len(roots)), fieldparams.ValidatorRegistryLimit) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute validator registry merkleization") + } + validatorsRootsBuf := new(bytes.Buffer) + if err := binary.Write(validatorsRootsBuf, binary.LittleEndian, uint64(len(validators))); err != nil { + return [32]byte{}, errors.Wrap(err, "could not marshal validator registry length") + } + // We need to mix in the length of the slice. + var validatorsRootsBufRoot [32]byte + copy(validatorsRootsBufRoot[:], validatorsRootsBuf.Bytes()) + res := ssz.MixInLength(validatorsRootsRoot, validatorsRootsBufRoot[:]) + if hashKey != emptyKey && h.rootsCache != nil { + h.rootsCache.Set(string(hashKey[:]), res, 32) + } + return res, nil +} + +func (h *stateRootHasher) validatorRoot(hasher ssz.HashFn, validator *ethpb.Validator) ([32]byte, error) { + if validator == nil { + return [32]byte{}, errors.New("nil validator") + } + + enc := validatorEncKey(validator) + // Check if it exists in cache: + if h.rootsCache != nil { + if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok { + return found.([32]byte), nil + } + } + + valRoot, err := ValidatorRootWithHasher(hasher, validator) + if err != nil { + return [32]byte{}, err + } + + if h.rootsCache != nil { + h.rootsCache.Set(string(enc), valRoot, 32) + } + return valRoot, nil +} diff --git a/beacon-chain/state-proto/stateutil/field_root_vector.go b/beacon-chain/state-proto/stateutil/field_root_vector.go new file mode 100644 index 0000000000..1e9df49d2c --- /dev/null +++ b/beacon-chain/state-proto/stateutil/field_root_vector.go @@ -0,0 +1,156 @@ +package stateutil + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/ssz" +) + +func (h *stateRootHasher) arraysRoot(input [][]byte, length uint64, fieldName string) ([32]byte, error) { + lock.Lock() + defer lock.Unlock() + hashFunc := hash.CustomSHA256Hasher() + if _, ok := layersCache[fieldName]; !ok && h.rootsCache != nil { + depth := ssz.Depth(length) + layersCache[fieldName] = make([][][32]byte, depth+1) + } + + leaves := make([][32]byte, length) + for i, chunk := range input { + copy(leaves[i][:], chunk) + } + bytesProcessed := 0 + changedIndices := make([]int, 0) + prevLeaves, ok := leavesCache[fieldName] + if len(prevLeaves) == 0 || h.rootsCache == nil { + prevLeaves = leaves + } + // Exit early if our previous leaves length don't match with the current set. + // This should never happen but better to be defensive here. + if len(prevLeaves) != len(leaves) { + res, err := h.merkleizeWithCache(leaves, length, fieldName, hashFunc) + if err != nil { + return [32]byte{}, err + } + if h.rootsCache != nil { + leavesCache[fieldName] = leaves + } + return res, nil + } + for i := 0; i < len(leaves); i++ { + // We check if any items changed since the roots were last recomputed. + notEqual := leaves[i] != prevLeaves[i] + if ok && h.rootsCache != nil && notEqual { + changedIndices = append(changedIndices, i) + } + bytesProcessed += 32 + } + if len(changedIndices) > 0 && h.rootsCache != nil { + var rt [32]byte + var err error + // If indices did change since last computation, we only recompute + // the modified branches in the cached Merkle tree for this state field. + chunks := leaves + + // We need to ensure we recompute indices of the Merkle tree which + // changed in-between calls to this function. This check adds an offset + // to the recomputed indices to ensure we do so evenly. + maxChangedIndex := changedIndices[len(changedIndices)-1] + if maxChangedIndex+2 == len(chunks) && maxChangedIndex%2 != 0 { + changedIndices = append(changedIndices, maxChangedIndex+1) + } + for i := 0; i < len(changedIndices); i++ { + rt, err = recomputeRoot(changedIndices[i], chunks, fieldName, hashFunc) + if err != nil { + return [32]byte{}, err + } + } + leavesCache[fieldName] = chunks + return rt, nil + } + + res, err := h.merkleizeWithCache(leaves, length, fieldName, hashFunc) + if err != nil { + return [32]byte{}, err + } + if h.rootsCache != nil { + leavesCache[fieldName] = leaves + } + return res, nil +} + +func recomputeRoot(idx int, chunks [][32]byte, fieldName string, hasher func([]byte) [32]byte) ([32]byte, error) { + items, ok := layersCache[fieldName] + if !ok { + return [32]byte{}, errors.New("could not recompute root as there was no cache found") + } + if items == nil { + return [32]byte{}, errors.New("could not recompute root as there were no items found in the layers cache") + } + layers := items + root := chunks[idx] + layers[0] = chunks + // The merkle tree structure looks as follows: + // [[r1, r2, r3, r4], [parent1, parent2], [root]] + // Using information about the index which changed, idx, we recompute + // only its branch up the tree. + currentIndex := idx + for i := 0; i < len(layers)-1; i++ { + isLeft := currentIndex%2 == 0 + neighborIdx := currentIndex ^ 1 + + neighbor := [32]byte{} + if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) { + neighbor = layers[i][neighborIdx] + } + if isLeft { + parentHash := hasher(append(root[:], neighbor[:]...)) + root = parentHash + } else { + parentHash := hasher(append(neighbor[:], root[:]...)) + root = parentHash + } + parentIdx := currentIndex / 2 + // Update the cached layers at the parent index. + if len(layers[i+1]) == 0 { + layers[i+1] = append(layers[i+1], root) + } else { + layers[i+1][parentIdx] = root + } + currentIndex = parentIdx + } + layersCache[fieldName] = layers + // If there is only a single leaf, we return it (the identity element). + if len(layers[0]) == 1 { + return layers[0][0], nil + } + return root, nil +} + +func (h *stateRootHasher) merkleizeWithCache(leaves [][32]byte, length uint64, + fieldName string, hasher func([]byte) [32]byte) ([32]byte, error) { + if len(leaves) == 0 { + return [32]byte{}, errors.New("zero leaves provided") + } + if len(leaves) == 1 { + return leaves[0], nil + } + hashLayer := leaves + layers := make([][][32]byte, ssz.Depth(length)+1) + if items, ok := layersCache[fieldName]; ok && h.rootsCache != nil { + if len(items[0]) == len(leaves) { + layers = items + } + } + layers[0] = hashLayer + var err error + layers, hashLayer, err = MerkleizeTrieLeaves(layers, hashLayer, hasher) + if err != nil { + return [32]byte{}, err + } + root := hashLayer[0] + if h.rootsCache != nil { + layersCache[fieldName] = layers + } + return root, nil +} diff --git a/beacon-chain/state-proto/stateutil/participation_bit_root.go b/beacon-chain/state-proto/stateutil/participation_bit_root.go new file mode 100644 index 0000000000..4849dbf300 --- /dev/null +++ b/beacon-chain/state-proto/stateutil/participation_bit_root.go @@ -0,0 +1,69 @@ +package stateutil + +import ( + "encoding/binary" + + "github.com/pkg/errors" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/ssz" +) + +// ParticipationBitsRoot computes the HashTreeRoot merkleization of +// participation roots. +func ParticipationBitsRoot(bits []byte) ([32]byte, error) { + hasher := hash.CustomSHA256Hasher() + chunkedRoots, err := packParticipationBits(bits) + if err != nil { + return [32]byte{}, err + } + + limit := (uint64(fieldparams.ValidatorRegistryLimit + 31)) / 32 + if limit == 0 { + if len(bits) == 0 { + limit = 1 + } else { + limit = uint64(len(bits)) + } + } + + bytesRoot, err := ssz.BitwiseMerkleize(hasher, chunkedRoots, uint64(len(chunkedRoots)), limit) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute merkleization") + } + + bytesRootBufRoot := make([]byte, 32) + binary.LittleEndian.PutUint64(bytesRootBufRoot[:8], uint64(len(bits))) + return ssz.MixInLength(bytesRoot, bytesRootBufRoot), nil +} + +// packParticipationBits into chunks. It'll pad the last chunk with zero bytes if +// it does not have length bytes per chunk. +func packParticipationBits(bytes []byte) ([][]byte, error) { + numItems := len(bytes) + var chunks [][]byte + for i := 0; i < numItems; i += 32 { + j := i + 32 + // We create our upper bound index of the chunk, if it is greater than numItems, + // we set it as numItems itself. + if j > numItems { + j = numItems + } + // We create chunks from the list of items based on the + // indices determined above. + chunks = append(chunks, bytes[i:j]) + } + + if len(chunks) == 0 { + return chunks, nil + } + + // Right-pad the last chunk with zero bytes if it does not + // have length bytes. + lastChunk := chunks[len(chunks)-1] + for len(lastChunk) < 32 { + lastChunk = append(lastChunk, 0) + } + chunks[len(chunks)-1] = lastChunk + return chunks, nil +} diff --git a/beacon-chain/state-proto/stateutil/pending_attestation_root.go b/beacon-chain/state-proto/stateutil/pending_attestation_root.go new file mode 100644 index 0000000000..8503be51fc --- /dev/null +++ b/beacon-chain/state-proto/stateutil/pending_attestation_root.go @@ -0,0 +1,138 @@ +package stateutil + +import ( + "encoding/binary" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// PendingAttRootWithHasher describes a method from which the hash tree root +// of a pending attestation is returned. +func PendingAttRootWithHasher(hasher ssz.HashFn, att *ethpb.PendingAttestation) ([32]byte, error) { + var fieldRoots [][32]byte + + // Bitfield. + aggregationRoot, err := ssz.BitlistRoot(hasher, att.AggregationBits, params.BeaconConfig().MaxValidatorsPerCommittee) + if err != nil { + return [32]byte{}, err + } + // Attestation data. + attDataRoot, err := attDataRootWithHasher(hasher, att.Data) + if err != nil { + return [32]byte{}, err + } + inclusionBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(inclusionBuf, uint64(att.InclusionDelay)) + // Inclusion delay. + inclusionRoot := bytesutil.ToBytes32(inclusionBuf) + + proposerBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(proposerBuf, uint64(att.ProposerIndex)) + // Proposer index. + proposerRoot := bytesutil.ToBytes32(proposerBuf) + + fieldRoots = [][32]byte{aggregationRoot, attDataRoot, inclusionRoot, proposerRoot} + + return ssz.BitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) +} + +// pendingAttEncKey returns the encoded key in bytes of input `pendingAttestation`, +// the returned key bytes can be used for caching purposes. +func pendingAttEncKey(att *ethpb.PendingAttestation) []byte { + enc := make([]byte, 2192) + + if att != nil { + copy(enc[0:2048], att.AggregationBits) + + inclusionBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(inclusionBuf, uint64(att.InclusionDelay)) + copy(enc[2048:2056], inclusionBuf) + + attDataBuf := marshalAttData(att.Data) + copy(enc[2056:2184], attDataBuf) + + proposerBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(proposerBuf, uint64(att.ProposerIndex)) + copy(enc[2184:2192], proposerBuf) + } + + return enc +} + +func attDataRootWithHasher(hasher ssz.HashFn, data *ethpb.AttestationData) ([32]byte, error) { + fieldRoots := make([][]byte, 5) + + if data != nil { + // Slot. + slotBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(slotBuf, uint64(data.Slot)) + slotRoot := bytesutil.ToBytes32(slotBuf) + fieldRoots[0] = slotRoot[:] + + // CommitteeIndex. + indexBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(indexBuf, uint64(data.CommitteeIndex)) + interRoot := bytesutil.ToBytes32(indexBuf) + fieldRoots[1] = interRoot[:] + + // Beacon block root. + blockRoot := bytesutil.ToBytes32(data.BeaconBlockRoot) + fieldRoots[2] = blockRoot[:] + + // Source + sourceRoot, err := ssz.CheckpointRoot(hasher, data.Source) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute source checkpoint merkleization") + } + fieldRoots[3] = sourceRoot[:] + + // Target + targetRoot, err := ssz.CheckpointRoot(hasher, data.Target) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute target checkpoint merkleization") + } + fieldRoots[4] = targetRoot[:] + } + + return ssz.BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) +} + +func marshalAttData(data *ethpb.AttestationData) []byte { + enc := make([]byte, 128) + + if data != nil { + // Slot. + slotBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(slotBuf, uint64(data.Slot)) + copy(enc[0:8], slotBuf) + + // Committee index. + indexBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(indexBuf, uint64(data.CommitteeIndex)) + copy(enc[8:16], indexBuf) + + copy(enc[16:48], data.BeaconBlockRoot) + + // Source epoch and root. + if data.Source != nil { + sourceEpochBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(sourceEpochBuf, uint64(data.Source.Epoch)) + copy(enc[48:56], sourceEpochBuf) + copy(enc[56:88], data.Source.Root) + } + + // Target. + if data.Target != nil { + targetEpochBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(targetEpochBuf, uint64(data.Target.Epoch)) + copy(enc[88:96], targetEpochBuf) + copy(enc[96:128], data.Target.Root) + } + } + + return enc +} diff --git a/beacon-chain/state-proto/stateutil/reference.go b/beacon-chain/state-proto/stateutil/reference.go new file mode 100644 index 0000000000..984efb5c8b --- /dev/null +++ b/beacon-chain/state-proto/stateutil/reference.go @@ -0,0 +1,45 @@ +package stateutil + +import "sync" + +// Reference structs are shared across BeaconState copies to understand when the state must use +// copy-on-write for shared fields or may modify a field in place when it holds the only reference +// to the field value. References are tracked in a map of fieldIndex -> *reference. Whenever a state +// releases their reference to the field value, they must decrement the refs. Likewise whenever a +// copy is performed then the state must increment the refs counter. +type Reference struct { + refs uint + lock sync.RWMutex +} + +// NewRef initializes the Reference struct. +func NewRef(refs uint) *Reference { + return &Reference{ + refs: refs, + } +} + +// Refs returns the reference number. +func (r *Reference) Refs() uint { + r.lock.RLock() + defer r.lock.RUnlock() + return r.refs +} + +// AddRef adds 1 to the reference number. +func (r *Reference) AddRef() { + r.lock.Lock() + r.refs++ + r.lock.Unlock() +} + +// MinusRef subtracts 1 to the reference number. +func (r *Reference) MinusRef() { + r.lock.Lock() + // Do not reduce further if object + // already has 0 reference to prevent underflow. + if r.refs > 0 { + r.refs-- + } + r.lock.Unlock() +} diff --git a/beacon-chain/state-proto/stateutil/reference_bench_test.go b/beacon-chain/state-proto/stateutil/reference_bench_test.go new file mode 100644 index 0000000000..1dcad8e012 --- /dev/null +++ b/beacon-chain/state-proto/stateutil/reference_bench_test.go @@ -0,0 +1,15 @@ +package stateutil + +import ( + "math" + "testing" +) + +func BenchmarkReference_MinusRef(b *testing.B) { + ref := &Reference{ + refs: math.MaxUint64, + } + for i := 0; i < b.N; i++ { + ref.MinusRef() + } +} diff --git a/beacon-chain/state-proto/stateutil/state_hasher.go b/beacon-chain/state-proto/stateutil/state_hasher.go new file mode 100644 index 0000000000..8c901069d6 --- /dev/null +++ b/beacon-chain/state-proto/stateutil/state_hasher.go @@ -0,0 +1,548 @@ +package stateutil + +import ( + "context" + "encoding/binary" + "sync" + + "github.com/dgraph-io/ristretto" + "github.com/pkg/errors" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "go.opencensus.io/trace" +) + +var ( + // Set the map size as equal to that of the latest state field count. + leavesCache = make(map[string][][32]byte, params.BeaconConfig().BeaconStateMergeFieldCount) + layersCache = make(map[string][][][32]byte, params.BeaconConfig().BeaconStateMergeFieldCount) + lock sync.RWMutex +) + +const cacheSize = 100000 + +// NocachedHasher references a hasher that will not utilize a cache. +var NocachedHasher *stateRootHasher + +// CachedHasher references a hasher that will utilize a roots cache. +var CachedHasher *stateRootHasher + +func init() { + rootsCache, err := ristretto.NewCache(&ristretto.Config{ + NumCounters: cacheSize, // number of keys to track frequency of (1M). + MaxCost: 1 << 22, // maximum cost of cache (3MB). + // 100,000 roots will take up approximately 3 MB in memory. + BufferItems: 64, // number of keys per Get buffer. + }) + if err != nil { + panic(err) + } + // Temporarily disable roots cache until cache issues can be resolved. + CachedHasher = &stateRootHasher{rootsCache: rootsCache} + NocachedHasher = &stateRootHasher{} +} + +// stateRootHasher defines an object through which we can +// hash the different fields in the state with a few cached layers. +type stateRootHasher struct { + rootsCache *ristretto.Cache +} + +// ComputeFieldRootsWithHasherPhase0 hashes the provided phase 0 state and returns its respective field roots. +func (h *stateRootHasher) ComputeFieldRootsWithHasherPhase0(ctx context.Context, state *ethpb.BeaconState) ([][]byte, error) { + _, span := trace.StartSpan(ctx, "hasher.ComputeFieldRootsWithHasherPhase0") + defer span.End() + + if state == nil { + return nil, errors.New("nil state") + } + hasher := hash.CustomSHA256Hasher() + fieldRoots := make([][]byte, params.BeaconConfig().BeaconStateFieldCount) + + // Genesis time root. + genesisRoot := ssz.Uint64Root(state.GenesisTime) + fieldRoots[0] = genesisRoot[:] + + // Genesis validator root. + r := [32]byte{} + copy(r[:], state.GenesisValidatorsRoot) + fieldRoots[1] = r[:] + + // Slot root. + slotRoot := ssz.Uint64Root(uint64(state.Slot)) + fieldRoots[2] = slotRoot[:] + + // Fork data structure root. + forkHashTreeRoot, err := ssz.ForkRoot(state.Fork) + if err != nil { + return nil, errors.Wrap(err, "could not compute fork merkleization") + } + fieldRoots[3] = forkHashTreeRoot[:] + + // BeaconBlockHeader data structure root. + headerHashTreeRoot, err := BlockHeaderRoot(state.LatestBlockHeader) + if err != nil { + return nil, errors.Wrap(err, "could not compute block header merkleization") + } + fieldRoots[4] = headerHashTreeRoot[:] + + // BlockRoots array root. + blockRootsRoot, err := h.arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength, "BlockRoots") + if err != nil { + return nil, errors.Wrap(err, "could not compute block roots merkleization") + } + fieldRoots[5] = blockRootsRoot[:] + + // StateRoots array root. + stateRootsRoot, err := h.arraysRoot(state.StateRoots, fieldparams.StateRootsLength, "StateRoots") + if err != nil { + return nil, errors.Wrap(err, "could not compute state roots merkleization") + } + fieldRoots[6] = stateRootsRoot[:] + + // HistoricalRoots slice root. + historicalRootsRt, err := ssz.ByteArrayRootWithLimit(state.HistoricalRoots, fieldparams.HistoricalRootsLength) + if err != nil { + return nil, errors.Wrap(err, "could not compute historical roots merkleization") + } + fieldRoots[7] = historicalRootsRt[:] + + // Eth1Data data structure root. + eth1HashTreeRoot, err := Eth1Root(hasher, state.Eth1Data) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data merkleization") + } + fieldRoots[8] = eth1HashTreeRoot[:] + + // Eth1DataVotes slice root. + eth1VotesRoot, err := eth1DataVotesRoot(state.Eth1DataVotes) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data votes merkleization") + } + fieldRoots[9] = eth1VotesRoot[:] + + // Eth1DepositIndex root. + eth1DepositIndexBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(eth1DepositIndexBuf, state.Eth1DepositIndex) + eth1DepositBuf := bytesutil.ToBytes32(eth1DepositIndexBuf) + fieldRoots[10] = eth1DepositBuf[:] + + // Validators slice root. + validatorsRoot, err := h.validatorRegistryRoot(state.Validators) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator registry merkleization") + } + fieldRoots[11] = validatorsRoot[:] + + // Balances slice root. + balancesRoot, err := Uint64ListRootWithRegistryLimit(state.Balances) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator balances merkleization") + } + fieldRoots[12] = balancesRoot[:] + + // RandaoMixes array root. + randaoRootsRoot, err := h.arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength, "RandaoMixes") + if err != nil { + return nil, errors.Wrap(err, "could not compute randao roots merkleization") + } + fieldRoots[13] = randaoRootsRoot[:] + + // Slashings array root. + slashingsRootsRoot, err := ssz.SlashingsRoot(state.Slashings) + if err != nil { + return nil, errors.Wrap(err, "could not compute slashings merkleization") + } + fieldRoots[14] = slashingsRootsRoot[:] + + // PreviousEpochAttestations slice root. + prevAttsRoot, err := h.epochAttestationsRoot(state.PreviousEpochAttestations) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous epoch attestations merkleization") + } + fieldRoots[15] = prevAttsRoot[:] + + // CurrentEpochAttestations slice root. + currAttsRoot, err := h.epochAttestationsRoot(state.CurrentEpochAttestations) + if err != nil { + return nil, errors.Wrap(err, "could not compute current epoch attestations merkleization") + } + fieldRoots[16] = currAttsRoot[:] + + // JustificationBits root. + justifiedBitsRoot := bytesutil.ToBytes32(state.JustificationBits) + fieldRoots[17] = justifiedBitsRoot[:] + + // PreviousJustifiedCheckpoint data structure root. + prevCheckRoot, err := ssz.CheckpointRoot(hasher, state.PreviousJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous justified checkpoint merkleization") + } + fieldRoots[18] = prevCheckRoot[:] + + // CurrentJustifiedCheckpoint data structure root. + currJustRoot, err := ssz.CheckpointRoot(hasher, state.CurrentJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute current justified checkpoint merkleization") + } + fieldRoots[19] = currJustRoot[:] + + // FinalizedCheckpoint data structure root. + finalRoot, err := ssz.CheckpointRoot(hasher, state.FinalizedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute finalized checkpoint merkleization") + } + fieldRoots[20] = finalRoot[:] + return fieldRoots, nil +} + +// ComputeFieldRootsWithHasherAltair hashes the provided altair state and returns its respective field roots. +func (h *stateRootHasher) ComputeFieldRootsWithHasherAltair(ctx context.Context, state *ethpb.BeaconStateAltair) ([][]byte, error) { + _, span := trace.StartSpan(ctx, "hasher.ComputeFieldRootsWithHasherAltair") + defer span.End() + + if state == nil { + return nil, errors.New("nil state") + } + hasher := hash.CustomSHA256Hasher() + fieldRoots := make([][]byte, params.BeaconConfig().BeaconStateAltairFieldCount) + + // Genesis time root. + genesisRoot := ssz.Uint64Root(state.GenesisTime) + fieldRoots[0] = genesisRoot[:] + + // Genesis validator root. + r := [32]byte{} + copy(r[:], state.GenesisValidatorsRoot) + fieldRoots[1] = r[:] + + // Slot root. + slotRoot := ssz.Uint64Root(uint64(state.Slot)) + fieldRoots[2] = slotRoot[:] + + // Fork data structure root. + forkHashTreeRoot, err := ssz.ForkRoot(state.Fork) + if err != nil { + return nil, errors.Wrap(err, "could not compute fork merkleization") + } + fieldRoots[3] = forkHashTreeRoot[:] + + // BeaconBlockHeader data structure root. + headerHashTreeRoot, err := BlockHeaderRoot(state.LatestBlockHeader) + if err != nil { + return nil, errors.Wrap(err, "could not compute block header merkleization") + } + fieldRoots[4] = headerHashTreeRoot[:] + + // BlockRoots array root. + blockRootsRoot, err := h.arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength, "BlockRoots") + if err != nil { + return nil, errors.Wrap(err, "could not compute block roots merkleization") + } + fieldRoots[5] = blockRootsRoot[:] + + // StateRoots array root. + stateRootsRoot, err := h.arraysRoot(state.StateRoots, fieldparams.StateRootsLength, "StateRoots") + if err != nil { + return nil, errors.Wrap(err, "could not compute state roots merkleization") + } + fieldRoots[6] = stateRootsRoot[:] + + // HistoricalRoots slice root. + historicalRootsRt, err := ssz.ByteArrayRootWithLimit(state.HistoricalRoots, fieldparams.HistoricalRootsLength) + if err != nil { + return nil, errors.Wrap(err, "could not compute historical roots merkleization") + } + fieldRoots[7] = historicalRootsRt[:] + + // Eth1Data data structure root. + eth1HashTreeRoot, err := Eth1Root(hasher, state.Eth1Data) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data merkleization") + } + fieldRoots[8] = eth1HashTreeRoot[:] + + // Eth1DataVotes slice root. + eth1VotesRoot, err := eth1DataVotesRoot(state.Eth1DataVotes) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data votes merkleization") + } + fieldRoots[9] = eth1VotesRoot[:] + + // Eth1DepositIndex root. + eth1DepositIndexBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(eth1DepositIndexBuf, state.Eth1DepositIndex) + eth1DepositBuf := bytesutil.ToBytes32(eth1DepositIndexBuf) + fieldRoots[10] = eth1DepositBuf[:] + + // Validators slice root. + validatorsRoot, err := h.validatorRegistryRoot(state.Validators) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator registry merkleization") + } + fieldRoots[11] = validatorsRoot[:] + + // Balances slice root. + balancesRoot, err := Uint64ListRootWithRegistryLimit(state.Balances) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator balances merkleization") + } + fieldRoots[12] = balancesRoot[:] + + // RandaoMixes array root. + randaoRootsRoot, err := h.arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength, "RandaoMixes") + if err != nil { + return nil, errors.Wrap(err, "could not compute randao roots merkleization") + } + fieldRoots[13] = randaoRootsRoot[:] + + // Slashings array root. + slashingsRootsRoot, err := ssz.SlashingsRoot(state.Slashings) + if err != nil { + return nil, errors.Wrap(err, "could not compute slashings merkleization") + } + fieldRoots[14] = slashingsRootsRoot[:] + + // PreviousEpochParticipation slice root. + prevParticipationRoot, err := ParticipationBitsRoot(state.PreviousEpochParticipation) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous epoch participation merkleization") + } + fieldRoots[15] = prevParticipationRoot[:] + + // CurrentEpochParticipation slice root. + currParticipationRoot, err := ParticipationBitsRoot(state.CurrentEpochParticipation) + if err != nil { + return nil, errors.Wrap(err, "could not compute current epoch participation merkleization") + } + fieldRoots[16] = currParticipationRoot[:] + + // JustificationBits root. + justifiedBitsRoot := bytesutil.ToBytes32(state.JustificationBits) + fieldRoots[17] = justifiedBitsRoot[:] + + // PreviousJustifiedCheckpoint data structure root. + prevCheckRoot, err := ssz.CheckpointRoot(hasher, state.PreviousJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous justified checkpoint merkleization") + } + fieldRoots[18] = prevCheckRoot[:] + + // CurrentJustifiedCheckpoint data structure root. + currJustRoot, err := ssz.CheckpointRoot(hasher, state.CurrentJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute current justified checkpoint merkleization") + } + fieldRoots[19] = currJustRoot[:] + + // FinalizedCheckpoint data structure root. + finalRoot, err := ssz.CheckpointRoot(hasher, state.FinalizedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute finalized checkpoint merkleization") + } + fieldRoots[20] = finalRoot[:] + + // Inactivity scores root. + inactivityScoresRoot, err := Uint64ListRootWithRegistryLimit(state.InactivityScores) + if err != nil { + return nil, errors.Wrap(err, "could not compute inactivityScoreRoot") + } + fieldRoots[21] = inactivityScoresRoot[:] + + // Current sync committee root. + currentSyncCommitteeRoot, err := SyncCommitteeRoot(state.CurrentSyncCommittee) + if err != nil { + return nil, errors.Wrap(err, "could not compute sync committee merkleization") + } + fieldRoots[22] = currentSyncCommitteeRoot[:] + + // Next sync committee root. + nextSyncCommitteeRoot, err := SyncCommitteeRoot(state.NextSyncCommittee) + if err != nil { + return nil, errors.Wrap(err, "could not compute sync committee merkleization") + } + fieldRoots[23] = nextSyncCommitteeRoot[:] + + return fieldRoots, nil +} + +// ComputeFieldRootsWithHasherMerge hashes the provided merge state and returns its respective field roots. +func (h *stateRootHasher) ComputeFieldRootsWithHasherMerge(ctx context.Context, state *ethpb.BeaconStateMerge) ([][]byte, error) { + _, span := trace.StartSpan(ctx, "hasher.ComputeFieldRootsWithHasherMerge") + defer span.End() + + if state == nil { + return nil, errors.New("nil state") + } + hasher := hash.CustomSHA256Hasher() + fieldRoots := make([][]byte, params.BeaconConfig().BeaconStateMergeFieldCount) + + // Genesis time root. + genesisRoot := ssz.Uint64Root(state.GenesisTime) + fieldRoots[0] = genesisRoot[:] + + // Genesis validator root. + r := [32]byte{} + copy(r[:], state.GenesisValidatorsRoot) + fieldRoots[1] = r[:] + + // Slot root. + slotRoot := ssz.Uint64Root(uint64(state.Slot)) + fieldRoots[2] = slotRoot[:] + + // Fork data structure root. + forkHashTreeRoot, err := ssz.ForkRoot(state.Fork) + if err != nil { + return nil, errors.Wrap(err, "could not compute fork merkleization") + } + fieldRoots[3] = forkHashTreeRoot[:] + + // BeaconBlockHeader data structure root. + headerHashTreeRoot, err := BlockHeaderRoot(state.LatestBlockHeader) + if err != nil { + return nil, errors.Wrap(err, "could not compute block header merkleization") + } + fieldRoots[4] = headerHashTreeRoot[:] + + // BlockRoots array root. + blockRootsRoot, err := h.arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength, "BlockRoots") + if err != nil { + return nil, errors.Wrap(err, "could not compute block roots merkleization") + } + fieldRoots[5] = blockRootsRoot[:] + + // StateRoots array root. + stateRootsRoot, err := h.arraysRoot(state.StateRoots, fieldparams.StateRootsLength, "StateRoots") + if err != nil { + return nil, errors.Wrap(err, "could not compute state roots merkleization") + } + fieldRoots[6] = stateRootsRoot[:] + + // HistoricalRoots slice root. + historicalRootsRt, err := ssz.ByteArrayRootWithLimit(state.HistoricalRoots, fieldparams.HistoricalRootsLength) + if err != nil { + return nil, errors.Wrap(err, "could not compute historical roots merkleization") + } + fieldRoots[7] = historicalRootsRt[:] + + // Eth1Data data structure root. + eth1HashTreeRoot, err := Eth1Root(hasher, state.Eth1Data) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data merkleization") + } + fieldRoots[8] = eth1HashTreeRoot[:] + + // Eth1DataVotes slice root. + eth1VotesRoot, err := eth1DataVotesRoot(state.Eth1DataVotes) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data votes merkleization") + } + fieldRoots[9] = eth1VotesRoot[:] + + // Eth1DepositIndex root. + eth1DepositIndexBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(eth1DepositIndexBuf, state.Eth1DepositIndex) + eth1DepositBuf := bytesutil.ToBytes32(eth1DepositIndexBuf) + fieldRoots[10] = eth1DepositBuf[:] + + // Validators slice root. + validatorsRoot, err := h.validatorRegistryRoot(state.Validators) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator registry merkleization") + } + fieldRoots[11] = validatorsRoot[:] + + // Balances slice root. + balancesRoot, err := Uint64ListRootWithRegistryLimit(state.Balances) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator balances merkleization") + } + fieldRoots[12] = balancesRoot[:] + + // RandaoMixes array root. + randaoRootsRoot, err := h.arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength, "RandaoMixes") + if err != nil { + return nil, errors.Wrap(err, "could not compute randao roots merkleization") + } + fieldRoots[13] = randaoRootsRoot[:] + + // Slashings array root. + slashingsRootsRoot, err := ssz.SlashingsRoot(state.Slashings) + if err != nil { + return nil, errors.Wrap(err, "could not compute slashings merkleization") + } + fieldRoots[14] = slashingsRootsRoot[:] + + // PreviousEpochParticipation slice root. + prevParticipationRoot, err := ParticipationBitsRoot(state.PreviousEpochParticipation) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous epoch participation merkleization") + } + fieldRoots[15] = prevParticipationRoot[:] + + // CurrentEpochParticipation slice root. + currParticipationRoot, err := ParticipationBitsRoot(state.CurrentEpochParticipation) + if err != nil { + return nil, errors.Wrap(err, "could not compute current epoch participation merkleization") + } + fieldRoots[16] = currParticipationRoot[:] + + // JustificationBits root. + justifiedBitsRoot := bytesutil.ToBytes32(state.JustificationBits) + fieldRoots[17] = justifiedBitsRoot[:] + + // PreviousJustifiedCheckpoint data structure root. + prevCheckRoot, err := ssz.CheckpointRoot(hasher, state.PreviousJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous justified checkpoint merkleization") + } + fieldRoots[18] = prevCheckRoot[:] + + // CurrentJustifiedCheckpoint data structure root. + currJustRoot, err := ssz.CheckpointRoot(hasher, state.CurrentJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute current justified checkpoint merkleization") + } + fieldRoots[19] = currJustRoot[:] + + // FinalizedCheckpoint data structure root. + finalRoot, err := ssz.CheckpointRoot(hasher, state.FinalizedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute finalized checkpoint merkleization") + } + fieldRoots[20] = finalRoot[:] + + // Inactivity scores root. + inactivityScoresRoot, err := Uint64ListRootWithRegistryLimit(state.InactivityScores) + if err != nil { + return nil, errors.Wrap(err, "could not compute inactivityScoreRoot") + } + fieldRoots[21] = inactivityScoresRoot[:] + + // Current sync committee root. + currentSyncCommitteeRoot, err := SyncCommitteeRoot(state.CurrentSyncCommittee) + if err != nil { + return nil, errors.Wrap(err, "could not compute sync committee merkleization") + } + fieldRoots[22] = currentSyncCommitteeRoot[:] + + // Next sync committee root. + nextSyncCommitteeRoot, err := SyncCommitteeRoot(state.NextSyncCommittee) + if err != nil { + return nil, errors.Wrap(err, "could not compute sync committee merkleization") + } + fieldRoots[23] = nextSyncCommitteeRoot[:] + + // Execution payload root. + executionPayloadRoot, err := state.LatestExecutionPayloadHeader.HashTreeRoot() + if err != nil { + return nil, err + } + fieldRoots[24] = executionPayloadRoot[:] + + return fieldRoots, nil +} diff --git a/beacon-chain/state-proto/stateutil/state_root_test.go b/beacon-chain/state-proto/stateutil/state_root_test.go new file mode 100644 index 0000000000..32fa72640c --- /dev/null +++ b/beacon-chain/state-proto/stateutil/state_root_test.go @@ -0,0 +1,82 @@ +package stateutil_test + +import ( + "context" + "reflect" + "strconv" + "testing" + + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/interop" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestState_FieldCount(t *testing.T) { + count := params.BeaconConfig().BeaconStateFieldCount + typ := reflect.TypeOf(ethpb.BeaconState{}) + numFields := 0 + for i := 0; i < typ.NumField(); i++ { + if typ.Field(i).Name == "state" || + typ.Field(i).Name == "sizeCache" || + typ.Field(i).Name == "unknownFields" { + continue + } + numFields++ + } + assert.Equal(t, count, numFields) +} + +func BenchmarkHashTreeRoot_Generic_512(b *testing.B) { + b.StopTimer() + genesisState := setupGenesisState(b, 512) + b.StartTimer() + for i := 0; i < b.N; i++ { + _, err := genesisState.HashTreeRoot() + require.NoError(b, err) + } +} + +func BenchmarkHashTreeRoot_Generic_16384(b *testing.B) { + b.StopTimer() + genesisState := setupGenesisState(b, 16384) + b.StartTimer() + for i := 0; i < b.N; i++ { + _, err := genesisState.HashTreeRoot() + require.NoError(b, err) + } +} + +func BenchmarkHashTreeRoot_Generic_300000(b *testing.B) { + b.StopTimer() + genesisState := setupGenesisState(b, 300000) + b.StartTimer() + for i := 0; i < b.N; i++ { + _, err := genesisState.HashTreeRoot() + require.NoError(b, err) + } +} + +func setupGenesisState(tb testing.TB, count uint64) *ethpb.BeaconState { + genesisState, _, err := interop.GenerateGenesisState(context.Background(), 0, 1) + require.NoError(tb, err, "Could not generate genesis beacon state") + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + genesisState.Validators = append(genesisState.Validators, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + genesisState.Balances = append(genesisState.Balances, params.BeaconConfig().MaxEffectiveBalance) + } + return genesisState +} diff --git a/beacon-chain/state-proto/stateutil/stateutil_test.go b/beacon-chain/state-proto/stateutil/stateutil_test.go new file mode 100644 index 0000000000..821de425c7 --- /dev/null +++ b/beacon-chain/state-proto/stateutil/stateutil_test.go @@ -0,0 +1,13 @@ +package stateutil_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/config/features" +) + +func TestMain(m *testing.M) { + resetCfg := features.InitWithReset(&features.Flags{EnableSSZCache: true}) + defer resetCfg() + m.Run() +} diff --git a/beacon-chain/state-proto/stateutil/sync_committee.root.go b/beacon-chain/state-proto/stateutil/sync_committee.root.go new file mode 100644 index 0000000000..492818a6ff --- /dev/null +++ b/beacon-chain/state-proto/stateutil/sync_committee.root.go @@ -0,0 +1,49 @@ +package stateutil + +import ( + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SyncCommitteeRoot computes the HashTreeRoot Merkleization of a commitee root. +// a SyncCommitteeRoot struct according to the eth2 +// Simple Serialize specification. +func SyncCommitteeRoot(committee *ethpb.SyncCommittee) ([32]byte, error) { + hasher := hash.CustomSHA256Hasher() + var fieldRoots [][32]byte + if committee == nil { + return [32]byte{}, nil + } + + // Field 1: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE] + pubKeyRoots := make([][32]byte, 0) + for _, pubkey := range committee.Pubkeys { + r, err := merkleizePubkey(hasher, pubkey) + if err != nil { + return [32]byte{}, err + } + pubKeyRoots = append(pubKeyRoots, r) + } + pubkeyRoot, err := ssz.BitwiseMerkleizeArrays(hasher, pubKeyRoots, uint64(len(pubKeyRoots)), uint64(len(pubKeyRoots))) + if err != nil { + return [32]byte{}, err + } + + // Field 2: BLSPubkey + aggregateKeyRoot, err := merkleizePubkey(hasher, committee.AggregatePubkey) + if err != nil { + return [32]byte{}, err + } + fieldRoots = [][32]byte{pubkeyRoot, aggregateKeyRoot} + + return ssz.BitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) +} + +func merkleizePubkey(hasher ssz.HashFn, pubkey []byte) ([32]byte, error) { + chunks, err := ssz.Pack([][]byte{pubkey}) + if err != nil { + return [32]byte{}, err + } + return ssz.BitwiseMerkleize(hasher, chunks, uint64(len(chunks)), uint64(len(chunks))) +} diff --git a/beacon-chain/state-proto/stateutil/trie_helpers.go b/beacon-chain/state-proto/stateutil/trie_helpers.go new file mode 100644 index 0000000000..e0c0cdf5eb --- /dev/null +++ b/beacon-chain/state-proto/stateutil/trie_helpers.go @@ -0,0 +1,296 @@ +package stateutil + +import ( + "bytes" + "encoding/binary" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/container/trie" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/ssz" + "github.com/prysmaticlabs/prysm/math" +) + +// ReturnTrieLayer returns the representation of a merkle trie when +// provided with the elements of a fixed sized trie and the corresponding depth of +// it. +func ReturnTrieLayer(elements [][32]byte, length uint64) ([][]*[32]byte, error) { + hasher := hash.CustomSHA256Hasher() + leaves := elements + + if len(leaves) == 1 { + return [][]*[32]byte{{&leaves[0]}}, nil + } + hashLayer := leaves + layers := make([][][32]byte, ssz.Depth(length)+1) + layers[0] = hashLayer + var err error + layers, _, err = MerkleizeTrieLeaves(layers, hashLayer, hasher) + if err != nil { + return nil, err + } + refLayers := make([][]*[32]byte, len(layers)) + for i, val := range layers { + refLayers[i] = make([]*[32]byte, len(val)) + for j, innerVal := range val { + newVal := innerVal + refLayers[i][j] = &newVal + } + } + return refLayers, nil +} + +// ReturnTrieLayerVariable returns the representation of a merkle trie when +// provided with the elements of a variable sized trie and the corresponding depth of +// it. +func ReturnTrieLayerVariable(elements [][32]byte, length uint64) [][]*[32]byte { + hasher := hash.CustomSHA256Hasher() + depth := ssz.Depth(length) + layers := make([][]*[32]byte, depth+1) + // Return zerohash at depth + if len(elements) == 0 { + zerohash := trie.ZeroHashes[depth] + layers[len(layers)-1] = []*[32]byte{&zerohash} + return layers + } + transformedLeaves := make([]*[32]byte, len(elements)) + for i := range elements { + arr := elements[i] + transformedLeaves[i] = &arr + } + layers[0] = transformedLeaves + buffer := bytes.NewBuffer([]byte{}) + buffer.Grow(64) + for i := 0; i < int(depth); i++ { + oddNodeLength := len(layers[i])%2 == 1 + if oddNodeLength { + zerohash := trie.ZeroHashes[i] + layers[i] = append(layers[i], &zerohash) + } + updatedValues := make([]*[32]byte, 0, len(layers[i])/2) + for j := 0; j < len(layers[i]); j += 2 { + buffer.Write(layers[i][j][:]) + buffer.Write(layers[i][j+1][:]) + concat := hasher(buffer.Bytes()) + updatedValues = append(updatedValues, &concat) + buffer.Reset() + } + // remove zerohash node from tree + if oddNodeLength { + layers[i] = layers[i][:len(layers[i])-1] + } + layers[i+1] = updatedValues + } + return layers +} + +// RecomputeFromLayer recomputes specific branches of a fixed sized trie depending on the provided changed indexes. +func RecomputeFromLayer(changedLeaves [][32]byte, changedIdx []uint64, layer [][]*[32]byte) ([32]byte, [][]*[32]byte, error) { + hasher := hash.CustomSHA256Hasher() + for i, idx := range changedIdx { + layer[0][idx] = &changedLeaves[i] + } + + if len(changedIdx) == 0 { + return *layer[0][0], layer, nil + } + + leaves := layer[0] + + // We need to ensure we recompute indices of the Merkle tree which + // changed in-between calls to this function. This check adds an offset + // to the recomputed indices to ensure we do so evenly. + maxChangedIndex := changedIdx[len(changedIdx)-1] + if int(maxChangedIndex+2) == len(leaves) && maxChangedIndex%2 != 0 { + changedIdx = append(changedIdx, maxChangedIndex+1) + } + + root := *layer[0][0] + var err error + + for _, idx := range changedIdx { + root, layer, err = recomputeRootFromLayer(int(idx), layer, leaves, hasher) + if err != nil { + return [32]byte{}, nil, err + } + } + return root, layer, nil +} + +// RecomputeFromLayerVariable recomputes specific branches of a variable sized trie depending on the provided changed indexes. +func RecomputeFromLayerVariable(changedLeaves [][32]byte, changedIdx []uint64, layer [][]*[32]byte) ([32]byte, [][]*[32]byte, error) { + hasher := hash.CustomSHA256Hasher() + if len(changedIdx) == 0 { + return *layer[0][0], layer, nil + } + root := *layer[len(layer)-1][0] + var err error + + for i, idx := range changedIdx { + root, layer, err = recomputeRootFromLayerVariable(int(idx), changedLeaves[i], layer, hasher) + if err != nil { + return [32]byte{}, nil, err + } + } + return root, layer, nil +} + +// this method assumes that the provided trie already has all its elements included +// in the base depth. +func recomputeRootFromLayer(idx int, layers [][]*[32]byte, chunks []*[32]byte, + hasher func([]byte) [32]byte) ([32]byte, [][]*[32]byte, error) { + root := *chunks[idx] + layers[0] = chunks + // The merkle tree structure looks as follows: + // [[r1, r2, r3, r4], [parent1, parent2], [root]] + // Using information about the index which changed, idx, we recompute + // only its branch up the tree. + currentIndex := idx + for i := 0; i < len(layers)-1; i++ { + isLeft := currentIndex%2 == 0 + neighborIdx := currentIndex ^ 1 + + neighbor := [32]byte{} + if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) { + neighbor = *layers[i][neighborIdx] + } + if isLeft { + parentHash := hasher(append(root[:], neighbor[:]...)) + root = parentHash + } else { + parentHash := hasher(append(neighbor[:], root[:]...)) + root = parentHash + } + parentIdx := currentIndex / 2 + // Update the cached layers at the parent index. + rootVal := root + if len(layers[i+1]) == 0 { + layers[i+1] = append(layers[i+1], &rootVal) + } else { + layers[i+1][parentIdx] = &rootVal + } + currentIndex = parentIdx + } + // If there is only a single leaf, we return it (the identity element). + if len(layers[0]) == 1 { + return *layers[0][0], layers, nil + } + return root, layers, nil +} + +// this method assumes that the base branch does not consist of all leaves of the +// trie. Instead missing leaves are assumed to be zerohashes, following the structure +// of a sparse merkle trie. +func recomputeRootFromLayerVariable(idx int, item [32]byte, layers [][]*[32]byte, + hasher func([]byte) [32]byte) ([32]byte, [][]*[32]byte, error) { + for idx >= len(layers[0]) { + zerohash := trie.ZeroHashes[0] + layers[0] = append(layers[0], &zerohash) + } + layers[0][idx] = &item + + currentIndex := idx + root := item + for i := 0; i < len(layers)-1; i++ { + isLeft := currentIndex%2 == 0 + neighborIdx := currentIndex ^ 1 + + neighbor := [32]byte{} + if neighborIdx >= len(layers[i]) { + neighbor = trie.ZeroHashes[i] + } else { + neighbor = *layers[i][neighborIdx] + } + if isLeft { + parentHash := hasher(append(root[:], neighbor[:]...)) + root = parentHash + } else { + parentHash := hasher(append(neighbor[:], root[:]...)) + root = parentHash + } + parentIdx := currentIndex / 2 + if len(layers[i+1]) == 0 || parentIdx >= len(layers[i+1]) { + newItem := root + layers[i+1] = append(layers[i+1], &newItem) + } else { + newItem := root + layers[i+1][parentIdx] = &newItem + } + currentIndex = parentIdx + } + return root, layers, nil +} + +// AddInMixin describes a method from which a lenth mixin is added to the +// provided root. +func AddInMixin(root [32]byte, length uint64) ([32]byte, error) { + rootBuf := new(bytes.Buffer) + if err := binary.Write(rootBuf, binary.LittleEndian, length); err != nil { + return [32]byte{}, errors.Wrap(err, "could not marshal eth1data votes length") + } + // We need to mix in the length of the slice. + rootBufRoot := make([]byte, 32) + copy(rootBufRoot, rootBuf.Bytes()) + return ssz.MixInLength(root, rootBufRoot), nil +} + +// Merkleize 32-byte leaves into a Merkle trie for its adequate depth, returning +// the resulting layers of the trie based on the appropriate depth. This function +// pads the leaves to a length of 32. +func Merkleize(leaves [][]byte) [][][]byte { + hashFunc := hash.CustomSHA256Hasher() + layers := make([][][]byte, ssz.Depth(uint64(len(leaves)))+1) + for len(leaves) != 32 { + leaves = append(leaves, make([]byte, 32)) + } + currentLayer := leaves + layers[0] = currentLayer + + // We keep track of the hash layers of a Merkle trie until we reach + // the top layer of length 1, which contains the single root element. + // [Root] -> Top layer has length 1. + // [E] [F] -> This layer has length 2. + // [A] [B] [C] [D] -> The bottom layer has length 4 (needs to be a power of two). + i := 1 + for len(currentLayer) > 1 && i < len(layers) { + layer := make([][]byte, 0) + for i := 0; i < len(currentLayer); i += 2 { + hashedChunk := hashFunc(append(currentLayer[i], currentLayer[i+1]...)) + layer = append(layer, hashedChunk[:]) + } + currentLayer = layer + layers[i] = currentLayer + i++ + } + return layers +} + +// MerkleizeTrieLeaves merkleize the trie leaves. +func MerkleizeTrieLeaves(layers [][][32]byte, hashLayer [][32]byte, + hasher func([]byte) [32]byte) ([][][32]byte, [][32]byte, error) { + // We keep track of the hash layers of a Merkle trie until we reach + // the top layer of length 1, which contains the single root element. + // [Root] -> Top layer has length 1. + // [E] [F] -> This layer has length 2. + // [A] [B] [C] [D] -> The bottom layer has length 4 (needs to be a power of two). + i := 1 + chunkBuffer := bytes.NewBuffer([]byte{}) + chunkBuffer.Grow(64) + for len(hashLayer) > 1 && i < len(layers) { + layer := make([][32]byte, len(hashLayer)/2) + if !math.IsPowerOf2(uint64(len(hashLayer))) { + return nil, nil, errors.Errorf("hash layer is a non power of 2: %d", len(hashLayer)) + } + for j := 0; j < len(hashLayer); j += 2 { + chunkBuffer.Write(hashLayer[j][:]) + chunkBuffer.Write(hashLayer[j+1][:]) + hashedChunk := hasher(chunkBuffer.Bytes()) + layer[j/2] = hashedChunk + chunkBuffer.Reset() + } + hashLayer = layer + layers[i] = hashLayer + i++ + } + return layers, hashLayer, nil +} diff --git a/beacon-chain/state-proto/stateutil/trie_helpers_test.go b/beacon-chain/state-proto/stateutil/trie_helpers_test.go new file mode 100644 index 0000000000..a1bace93bd --- /dev/null +++ b/beacon-chain/state-proto/stateutil/trie_helpers_test.go @@ -0,0 +1,122 @@ +package stateutil_test + +import ( + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestReturnTrieLayer_OK(t *testing.T) { + newState, _ := util.DeterministicGenesisState(t, 32) + root, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots") + require.NoError(t, err) + blockRts := newState.BlockRoots() + roots := make([][32]byte, 0, len(blockRts)) + for _, rt := range blockRts { + roots = append(roots, bytesutil.ToBytes32(rt)) + } + layers, err := stateutil.ReturnTrieLayer(roots, uint64(len(roots))) + assert.NoError(t, err) + newRoot := *layers[len(layers)-1][0] + assert.Equal(t, root, newRoot) +} + +func TestReturnTrieLayerVariable_OK(t *testing.T) { + newState, _ := util.DeterministicGenesisState(t, 32) + root, err := stateutil.ValidatorRegistryRoot(newState.Validators()) + require.NoError(t, err) + hasher := hash.CustomSHA256Hasher() + validators := newState.Validators() + roots := make([][32]byte, 0, len(validators)) + for _, val := range validators { + rt, err := stateutil.ValidatorRootWithHasher(hasher, val) + require.NoError(t, err) + roots = append(roots, rt) + } + layers := stateutil.ReturnTrieLayerVariable(roots, params.BeaconConfig().ValidatorRegistryLimit) + newRoot := *layers[len(layers)-1][0] + newRoot, err = stateutil.AddInMixin(newRoot, uint64(len(validators))) + require.NoError(t, err) + assert.Equal(t, root, newRoot) +} + +func TestRecomputeFromLayer_FixedSizedArray(t *testing.T) { + newState, _ := util.DeterministicGenesisState(t, 32) + blockRts := newState.BlockRoots() + roots := make([][32]byte, 0, len(blockRts)) + for _, rt := range blockRts { + roots = append(roots, bytesutil.ToBytes32(rt)) + } + layers, err := stateutil.ReturnTrieLayer(roots, uint64(len(roots))) + require.NoError(t, err) + + changedIdx := []uint64{24, 41} + changedRoots := [][32]byte{{'A', 'B', 'C'}, {'D', 'E', 'F'}} + require.NoError(t, newState.UpdateBlockRootAtIndex(changedIdx[0], changedRoots[0])) + require.NoError(t, newState.UpdateBlockRootAtIndex(changedIdx[1], changedRoots[1])) + + expectedRoot, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots") + require.NoError(t, err) + root, _, err := stateutil.RecomputeFromLayer(changedRoots, changedIdx, layers) + require.NoError(t, err) + assert.Equal(t, expectedRoot, root) +} + +func TestRecomputeFromLayer_VariableSizedArray(t *testing.T) { + newState, _ := util.DeterministicGenesisState(t, 32) + validators := newState.Validators() + hasher := hash.CustomSHA256Hasher() + roots := make([][32]byte, 0, len(validators)) + for _, val := range validators { + rt, err := stateutil.ValidatorRootWithHasher(hasher, val) + require.NoError(t, err) + roots = append(roots, rt) + } + layers := stateutil.ReturnTrieLayerVariable(roots, params.BeaconConfig().ValidatorRegistryLimit) + + changedIdx := []uint64{2, 29} + val1, err := newState.ValidatorAtIndex(10) + require.NoError(t, err) + val2, err := newState.ValidatorAtIndex(11) + require.NoError(t, err) + val1.Slashed = true + val1.ExitEpoch = 20 + + val2.Slashed = true + val2.ExitEpoch = 40 + + changedVals := []*ethpb.Validator{val1, val2} + require.NoError(t, newState.UpdateValidatorAtIndex(types.ValidatorIndex(changedIdx[0]), changedVals[0])) + require.NoError(t, newState.UpdateValidatorAtIndex(types.ValidatorIndex(changedIdx[1]), changedVals[1])) + + expectedRoot, err := stateutil.ValidatorRegistryRoot(newState.Validators()) + require.NoError(t, err) + roots = make([][32]byte, 0, len(changedVals)) + for _, val := range changedVals { + rt, err := stateutil.ValidatorRootWithHasher(hasher, val) + require.NoError(t, err) + roots = append(roots, rt) + } + root, _, err := stateutil.RecomputeFromLayerVariable(roots, changedIdx, layers) + require.NoError(t, err) + root, err = stateutil.AddInMixin(root, uint64(len(validators))) + require.NoError(t, err) + assert.Equal(t, expectedRoot, root) +} + +func TestMerkleizeTrieLeaves_BadHashLayer(t *testing.T) { + hashLayer := make([][32]byte, 12) + layers := make([][][32]byte, 20) + _, _, err := stateutil.MerkleizeTrieLeaves(layers, hashLayer, func(bytes []byte) [32]byte { + return [32]byte{} + }) + assert.ErrorContains(t, "hash layer is a non power of 2", err) +} diff --git a/beacon-chain/state-proto/stateutil/validator_map_handler.go b/beacon-chain/state-proto/stateutil/validator_map_handler.go new file mode 100644 index 0000000000..1a741b15dc --- /dev/null +++ b/beacon-chain/state-proto/stateutil/validator_map_handler.go @@ -0,0 +1,72 @@ +package stateutil + +import ( + "sync" + + types "github.com/prysmaticlabs/eth2-types" + coreutils "github.com/prysmaticlabs/prysm/beacon-chain/core/transition/stateutils" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// ValidatorMapHandler is a container to hold the map and a reference tracker for how many +// states shared this. +type ValidatorMapHandler struct { + valIdxMap map[[48]byte]types.ValidatorIndex + mapRef *Reference + *sync.RWMutex +} + +// NewValMapHandler returns a new validator map handler. +func NewValMapHandler(vals []*ethpb.Validator) *ValidatorMapHandler { + return &ValidatorMapHandler{ + valIdxMap: coreutils.ValidatorIndexMap(vals), + mapRef: &Reference{refs: 1}, + RWMutex: new(sync.RWMutex), + } +} + +// AddRef copies the whole map and returns a map handler with the copied map. +func (v *ValidatorMapHandler) AddRef() { + v.mapRef.AddRef() +} + +// IsNil returns true if the underlying validator index map is nil. +func (v *ValidatorMapHandler) IsNil() bool { + return v.mapRef == nil || v.valIdxMap == nil +} + +// Copy the whole map and returns a map handler with the copied map. +func (v *ValidatorMapHandler) Copy() *ValidatorMapHandler { + if v == nil || v.valIdxMap == nil { + return &ValidatorMapHandler{valIdxMap: map[[48]byte]types.ValidatorIndex{}, mapRef: new(Reference), RWMutex: new(sync.RWMutex)} + } + v.RLock() + defer v.RUnlock() + m := make(map[[48]byte]types.ValidatorIndex, len(v.valIdxMap)) + for k, v := range v.valIdxMap { + m[k] = v + } + return &ValidatorMapHandler{ + valIdxMap: m, + mapRef: &Reference{refs: 1}, + RWMutex: new(sync.RWMutex), + } +} + +// Get the validator index using the corresponding public key. +func (v *ValidatorMapHandler) Get(key [48]byte) (types.ValidatorIndex, bool) { + v.RLock() + defer v.RUnlock() + idx, ok := v.valIdxMap[key] + if !ok { + return 0, false + } + return idx, true +} + +// Set the validator index using the corresponding public key. +func (v *ValidatorMapHandler) Set(key [48]byte, index types.ValidatorIndex) { + v.Lock() + defer v.Unlock() + v.valIdxMap[key] = index +} diff --git a/beacon-chain/state-proto/stateutil/validator_root.go b/beacon-chain/state-proto/stateutil/validator_root.go new file mode 100644 index 0000000000..5ad86a6d6d --- /dev/null +++ b/beacon-chain/state-proto/stateutil/validator_root.go @@ -0,0 +1,128 @@ +package stateutil + +import ( + "encoding/binary" + + "github.com/pkg/errors" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// ValidatorRootWithHasher describes a method from which the hash tree root +// of a validator is returned. +func ValidatorRootWithHasher(hasher ssz.HashFn, validator *ethpb.Validator) ([32]byte, error) { + var fieldRoots [][32]byte + if validator != nil { + pubkey := bytesutil.ToBytes48(validator.PublicKey) + withdrawCreds := bytesutil.ToBytes32(validator.WithdrawalCredentials) + effectiveBalanceBuf := [32]byte{} + binary.LittleEndian.PutUint64(effectiveBalanceBuf[:8], validator.EffectiveBalance) + // Slashed. + slashBuf := [32]byte{} + if validator.Slashed { + slashBuf[0] = uint8(1) + } else { + slashBuf[0] = uint8(0) + } + activationEligibilityBuf := [32]byte{} + binary.LittleEndian.PutUint64(activationEligibilityBuf[:8], uint64(validator.ActivationEligibilityEpoch)) + + activationBuf := [32]byte{} + binary.LittleEndian.PutUint64(activationBuf[:8], uint64(validator.ActivationEpoch)) + + exitBuf := [32]byte{} + binary.LittleEndian.PutUint64(exitBuf[:8], uint64(validator.ExitEpoch)) + + withdrawalBuf := [32]byte{} + binary.LittleEndian.PutUint64(withdrawalBuf[:8], uint64(validator.WithdrawableEpoch)) + + // Public key. + pubKeyChunks, err := ssz.Pack([][]byte{pubkey[:]}) + if err != nil { + return [32]byte{}, err + } + pubKeyRoot, err := ssz.BitwiseMerkleize(hasher, pubKeyChunks, uint64(len(pubKeyChunks)), uint64(len(pubKeyChunks))) + if err != nil { + return [32]byte{}, err + } + fieldRoots = [][32]byte{pubKeyRoot, withdrawCreds, effectiveBalanceBuf, slashBuf, activationEligibilityBuf, + activationBuf, exitBuf, withdrawalBuf} + } + return ssz.BitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) +} + +// Uint64ListRootWithRegistryLimit computes the HashTreeRoot Merkleization of +// a list of uint64 and mixed with registry limit. +func Uint64ListRootWithRegistryLimit(balances []uint64) ([32]byte, error) { + hasher := hash.CustomSHA256Hasher() + balancesMarshaling := make([][]byte, 0, len(balances)) + for i := 0; i < len(balances); i++ { + balanceBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(balanceBuf, balances[i]) + balancesMarshaling = append(balancesMarshaling, balanceBuf) + } + balancesChunks, err := ssz.Pack(balancesMarshaling) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not pack balances into chunks") + } + maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) + elemSize := uint64(8) + balLimit := (maxBalCap*elemSize + 31) / 32 + if balLimit == 0 { + if len(balances) == 0 { + balLimit = 1 + } else { + balLimit = uint64(len(balances)) + } + } + balancesRootsRoot, err := ssz.BitwiseMerkleize(hasher, balancesChunks, uint64(len(balancesChunks)), balLimit) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute balances merkleization") + } + + balancesLengthRoot := make([]byte, 32) + binary.LittleEndian.PutUint64(balancesLengthRoot, uint64(len(balances))) + return ssz.MixInLength(balancesRootsRoot, balancesLengthRoot), nil +} + +// validatorEncKey returns the encoded key in bytes of input `validator`, +// the returned key bytes can be used for caching purposes. +func validatorEncKey(validator *ethpb.Validator) []byte { + if validator == nil { + return nil + } + + enc := make([]byte, 122) + pubkey := bytesutil.ToBytes48(validator.PublicKey) + copy(enc[0:48], pubkey[:]) + withdrawCreds := bytesutil.ToBytes32(validator.WithdrawalCredentials) + copy(enc[48:80], withdrawCreds[:]) + effectiveBalanceBuf := [32]byte{} + binary.LittleEndian.PutUint64(effectiveBalanceBuf[:8], validator.EffectiveBalance) + copy(enc[80:88], effectiveBalanceBuf[:8]) + if validator.Slashed { + enc[88] = uint8(1) + } else { + enc[88] = uint8(0) + } + activationEligibilityBuf := [32]byte{} + binary.LittleEndian.PutUint64(activationEligibilityBuf[:8], uint64(validator.ActivationEligibilityEpoch)) + copy(enc[89:97], activationEligibilityBuf[:8]) + + activationBuf := [32]byte{} + binary.LittleEndian.PutUint64(activationBuf[:8], uint64(validator.ActivationEpoch)) + copy(enc[97:105], activationBuf[:8]) + + exitBuf := [32]byte{} + binary.LittleEndian.PutUint64(exitBuf[:8], uint64(validator.ExitEpoch)) + copy(enc[105:113], exitBuf[:8]) + + withdrawalBuf := [32]byte{} + binary.LittleEndian.PutUint64(withdrawalBuf[:8], uint64(validator.WithdrawableEpoch)) + copy(enc[113:121], withdrawalBuf[:8]) + + return enc +} diff --git a/beacon-chain/state/stateutil/validator_root_test.go b/beacon-chain/state-proto/stateutil/validator_root_test.go similarity index 85% rename from beacon-chain/state/stateutil/validator_root_test.go rename to beacon-chain/state-proto/stateutil/validator_root_test.go index 7fc05e26e2..0b6e7dc4e0 100644 --- a/beacon-chain/state/stateutil/validator_root_test.go +++ b/beacon-chain/state-proto/stateutil/validator_root_test.go @@ -3,7 +3,7 @@ package stateutil_test import ( "testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" ) func BenchmarkUint64ListRootWithRegistryLimit(b *testing.B) { diff --git a/beacon-chain/state/types/BUILD.bazel b/beacon-chain/state-proto/types/BUILD.bazel similarity index 96% rename from beacon-chain/state/types/BUILD.bazel rename to beacon-chain/state-proto/types/BUILD.bazel index 23a0642300..f8dc4adcc2 100644 --- a/beacon-chain/state/types/BUILD.bazel +++ b/beacon-chain/state-proto/types/BUILD.bazel @@ -3,7 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = ["types.go"], - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/types", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types", visibility = ["//beacon-chain:__subpackages__"], deps = [ "//runtime/version:go_default_library", diff --git a/beacon-chain/state-proto/types/types.go b/beacon-chain/state-proto/types/types.go new file mode 100644 index 0000000000..53c0253471 --- /dev/null +++ b/beacon-chain/state-proto/types/types.go @@ -0,0 +1,144 @@ +package types + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// FieldIndex represents the relevant field position in the +// state struct for a field. +type FieldIndex int + +// DataType signifies the data type of the field. +type DataType int + +// List of current data types the state supports. +const ( + // BasicArray represents a simple array type for a field. + BasicArray DataType = iota + // CompositeArray represents a variable length array with + // a non primitive type. + CompositeArray + // CompressedArray represents a variable length array which + // can pack multiple elements into a leaf of the underlying + // trie. + CompressedArray +) + +// String returns the name of the field index. +func (f FieldIndex) String(stateVersion int) string { + switch f { + case GenesisTime: + return "genesisTime" + case GenesisValidatorRoot: + return "genesisValidatorRoot" + case Slot: + return "slot" + case Fork: + return "fork" + case LatestBlockHeader: + return "latestBlockHeader" + case BlockRoots: + return "blockRoots" + case StateRoots: + return "stateRoots" + case HistoricalRoots: + return "historicalRoots" + case Eth1Data: + return "eth1Data" + case Eth1DataVotes: + return "eth1DataVotes" + case Eth1DepositIndex: + return "eth1DepositIndex" + case Validators: + return "validators" + case Balances: + return "balances" + case RandaoMixes: + return "randaoMixes" + case Slashings: + return "slashings" + case PreviousEpochAttestations: + if version.Altair == stateVersion || version.Merge == stateVersion { + return "previousEpochParticipationBits" + } + return "previousEpochAttestations" + case CurrentEpochAttestations: + if version.Altair == stateVersion || version.Merge == stateVersion { + return "currentEpochParticipationBits" + } + return "currentEpochAttestations" + case JustificationBits: + return "justificationBits" + case PreviousJustifiedCheckpoint: + return "previousJustifiedCheckpoint" + case CurrentJustifiedCheckpoint: + return "currentJustifiedCheckpoint" + case FinalizedCheckpoint: + return "finalizedCheckpoint" + case InactivityScores: + return "inactivityScores" + case CurrentSyncCommittee: + return "currentSyncCommittee" + case NextSyncCommittee: + return "nextSyncCommittee" + case LatestExecutionPayloadHeader: + return "latestExecutionPayloadHeader" + default: + return "" + } +} + +// ElemsInChunk returns the number of elements in the chunk (number of +// elements that are able to be packed). +func (f FieldIndex) ElemsInChunk() (uint64, error) { + switch f { + case Balances: + return 4, nil + default: + return 0, errors.Errorf("field %d doesn't support element compression", f) + } +} + +// Below we define a set of useful enum values for the field +// indices of the beacon state. For example, genesisTime is the +// 0th field of the beacon state. This is helpful when we are +// updating the Merkle branches up the trie representation +// of the beacon state. The below field indexes correspond +// to the v1 state. +const ( + GenesisTime FieldIndex = iota + GenesisValidatorRoot + Slot + Fork + LatestBlockHeader + BlockRoots + StateRoots + HistoricalRoots + Eth1Data + Eth1DataVotes + Eth1DepositIndex + Validators + Balances + RandaoMixes + Slashings + PreviousEpochAttestations + CurrentEpochAttestations + JustificationBits + PreviousJustifiedCheckpoint + CurrentJustifiedCheckpoint + FinalizedCheckpoint + // State Fields Added in Altair. + InactivityScores + CurrentSyncCommittee + NextSyncCommittee + // State fields added in Merge. + LatestExecutionPayloadHeader +) + +// Altair fields which replaced previous phase 0 fields. +const ( + // Epoch Attestations is switched with participation bits in Altair. + PreviousEpochParticipationBits = PreviousEpochAttestations + CurrentEpochParticipationBits = CurrentEpochAttestations +) diff --git a/beacon-chain/state-proto/types/types_test.go b/beacon-chain/state-proto/types/types_test.go new file mode 100644 index 0000000000..99394d2fd7 --- /dev/null +++ b/beacon-chain/state-proto/types/types_test.go @@ -0,0 +1,36 @@ +package types + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/testing/assert" +) + +func TestStateFieldIndexes(t *testing.T) { + assert.Equal(t, FieldIndex(0), GenesisTime) + assert.Equal(t, FieldIndex(1), GenesisValidatorRoot) + assert.Equal(t, FieldIndex(2), Slot) + assert.Equal(t, FieldIndex(3), Fork) + assert.Equal(t, FieldIndex(4), LatestBlockHeader) + assert.Equal(t, FieldIndex(5), BlockRoots) + assert.Equal(t, FieldIndex(6), StateRoots) + assert.Equal(t, FieldIndex(7), HistoricalRoots) + assert.Equal(t, FieldIndex(8), Eth1Data) + assert.Equal(t, FieldIndex(9), Eth1DataVotes) + assert.Equal(t, FieldIndex(10), Eth1DepositIndex) + assert.Equal(t, FieldIndex(11), Validators) + assert.Equal(t, FieldIndex(12), Balances) + assert.Equal(t, FieldIndex(13), RandaoMixes) + assert.Equal(t, FieldIndex(14), Slashings) + assert.Equal(t, FieldIndex(15), PreviousEpochAttestations) + assert.Equal(t, FieldIndex(15), PreviousEpochParticipationBits) + assert.Equal(t, FieldIndex(16), CurrentEpochAttestations) + assert.Equal(t, FieldIndex(16), CurrentEpochParticipationBits) + assert.Equal(t, FieldIndex(17), JustificationBits) + assert.Equal(t, FieldIndex(18), PreviousJustifiedCheckpoint) + assert.Equal(t, FieldIndex(19), CurrentJustifiedCheckpoint) + assert.Equal(t, FieldIndex(20), FinalizedCheckpoint) + assert.Equal(t, FieldIndex(21), InactivityScores) + assert.Equal(t, FieldIndex(22), CurrentSyncCommittee) + assert.Equal(t, FieldIndex(23), NextSyncCommittee) +} diff --git a/beacon-chain/state-proto/v1/BUILD.bazel b/beacon-chain/state-proto/v1/BUILD.bazel new file mode 100644 index 0000000000..754f6ba529 --- /dev/null +++ b/beacon-chain/state-proto/v1/BUILD.bazel @@ -0,0 +1,106 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "field_roots.go", + "getters_attestation.go", + "getters_block.go", + "getters_checkpoint.go", + "getters_eth1.go", + "getters_misc.go", + "getters_randao.go", + "getters_state.go", + "getters_validator.go", + "proofs.go", + "readonly_validator.go", + "setters_attestation.go", + "setters_block.go", + "setters_checkpoint.go", + "setters_eth1.go", + "setters_misc.go", + "setters_randao.go", + "setters_state.go", + "setters_validator.go", + "state_trie.go", + "types.go", + "unsupported_getters.go", + "unsupported_setters.go", + ], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1", + visibility = [ + "//beacon-chain:__subpackages__", + "//contracts/deposit:__subpackages__", + "//proto/migration:__subpackages__", + "//proto/prysm/v1alpha1:__subpackages__", + "//proto/testing:__subpackages__", + "//runtime/interop:__subpackages__", + "//slasher/rpc:__subpackages__", + "//testing/benchmark:__pkg__", + "//testing/fuzz:__pkg__", + "//testing/spectest:__subpackages__", + "//testing/util:__pkg__", + "//tools/benchmark-files-gen:__pkg__", + "//tools/pcli:__pkg__", + ], + deps = [ + "//beacon-chain/sharedstate:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/fieldtrie:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//config/features:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//container/slice:go_default_library", + "//crypto/hash:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@io_opencensus_go//trace:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + ], +) + +# gazelle:exclude types_bench_test.go +go_test( + name = "go_default_test", + srcs = [ + "getters_attestation_test.go", + "getters_block_test.go", + "getters_test.go", + "getters_validator_test.go", + "proofs_test.go", + "readonly_validator_test.go", + "references_test.go", + "setters_attestation_test.go", + "state_test.go", + "state_trie_test.go", + "types_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//config/features:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//container/trie:go_default_library", + "//encoding/bytesutil:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/interop:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + ], +) diff --git a/beacon-chain/state-proto/v1/doc.go b/beacon-chain/state-proto/v1/doc.go new file mode 100644 index 0000000000..d47c3fb247 --- /dev/null +++ b/beacon-chain/state-proto/v1/doc.go @@ -0,0 +1,40 @@ +// Package v1 defines how the beacon chain state for Ethereum +// functions in the running beacon node, using an advanced, +// immutable implementation of the state data structure. +// +// BeaconState getters may be accessed from inside or outside the package. To +// avoid duplicating locks, we have internal and external versions of the +// getter The external function carries out the short-circuit conditions, +// obtains a read lock, then calls the internal function. The internal function +// carries out the short-circuit conditions and returns the required data +// without further locking, allowing it to be used by other package-level +// functions that already hold a lock. Hence the functions look something +// like this: +// +// func (b *BeaconState) Foo() uint64 { +// // Short-circuit conditions. +// if !b.hasInnerState() { +// return 0 +// } +// +// // Read lock. +// b.lock.RLock() +// defer b.lock.RUnlock() +// +// // Internal getter. +// return b.foo() +// } +// +// func (b *BeaconState) foo() uint64 { +// // Short-circuit conditions. +// if !b.hasInnerState() { +// return 0 +// } +// +// return b.state.foo +// } +// +// Although it is technically possible to remove the short-circuit conditions +// from the external function, that would require every read to obtain a lock +// even if the data was not present, leading to potential slowdowns. +package v1 diff --git a/beacon-chain/state-proto/v1/field_roots.go b/beacon-chain/state-proto/v1/field_roots.go new file mode 100644 index 0000000000..d7e335c08f --- /dev/null +++ b/beacon-chain/state-proto/v1/field_roots.go @@ -0,0 +1,18 @@ +package v1 + +import ( + "context" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/config/features" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// computeFieldRoots returns the hash tree root computations of every field in +// the beacon state as a list of 32 byte roots. +func computeFieldRoots(ctx context.Context, state *ethpb.BeaconState) ([][]byte, error) { + if features.Get().EnableSSZCache { + return stateutil.CachedHasher.ComputeFieldRootsWithHasherPhase0(ctx, state) + } + return stateutil.NocachedHasher.ComputeFieldRootsWithHasherPhase0(ctx, state) +} diff --git a/beacon-chain/state-proto/v1/getters_attestation.go b/beacon-chain/state-proto/v1/getters_attestation.go new file mode 100644 index 0000000000..e7e3bd6901 --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_attestation.go @@ -0,0 +1,55 @@ +package v1 + +import ( + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// PreviousEpochAttestations corresponding to blocks on the beacon chain. +func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.PreviousEpochAttestations == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.previousEpochAttestations(), nil +} + +// previousEpochAttestations corresponding to blocks on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) previousEpochAttestations() []*ethpb.PendingAttestation { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyPendingAttestationSlice(b.state.PreviousEpochAttestations) +} + +// CurrentEpochAttestations corresponding to blocks on the beacon chain. +func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.CurrentEpochAttestations == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.currentEpochAttestations(), nil +} + +// currentEpochAttestations corresponding to blocks on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentEpochAttestations() []*ethpb.PendingAttestation { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyPendingAttestationSlice(b.state.CurrentEpochAttestations) +} diff --git a/beacon-chain/state-proto/v1/getters_attestation_test.go b/beacon-chain/state-proto/v1/getters_attestation_test.go new file mode 100644 index 0000000000..af85b2661a --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_attestation_test.go @@ -0,0 +1,46 @@ +package v1 + +import ( + "testing" + + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_PreviousEpochAttestations(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconState{}) + require.NoError(t, err) + atts, err := s.PreviousEpochAttestations() + require.NoError(t, err) + require.DeepEqual(t, []*ethpb.PendingAttestation(nil), atts) + + want := []*ethpb.PendingAttestation{{ProposerIndex: 100}} + s, err = InitializeFromProto(ðpb.BeaconState{PreviousEpochAttestations: want}) + require.NoError(t, err) + got, err := s.PreviousEpochAttestations() + require.NoError(t, err) + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got[0].ProposerIndex = 101 + require.DeepNotEqual(t, want, got) +} + +func TestBeaconState_CurrentEpochAttestations(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconState{}) + require.NoError(t, err) + atts, err := s.CurrentEpochAttestations() + require.NoError(t, err) + require.DeepEqual(t, []*ethpb.PendingAttestation(nil), atts) + + want := []*ethpb.PendingAttestation{{ProposerIndex: 101}} + s, err = InitializeFromProto(ðpb.BeaconState{CurrentEpochAttestations: want}) + require.NoError(t, err) + got, err := s.CurrentEpochAttestations() + require.NoError(t, err) + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got[0].ProposerIndex = 102 + require.DeepNotEqual(t, want, got) +} diff --git a/beacon-chain/state-proto/v1/getters_block.go b/beacon-chain/state-proto/v1/getters_block.go new file mode 100644 index 0000000000..64baa623cb --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_block.go @@ -0,0 +1,99 @@ +package v1 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// LatestBlockHeader stored within the beacon state. +func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader { + if !b.hasInnerState() { + return nil + } + if b.state.LatestBlockHeader == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.latestBlockHeader() +} + +// latestBlockHeader stored within the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader { + if !b.hasInnerState() { + return nil + } + if b.state.LatestBlockHeader == nil { + return nil + } + + hdr := ðpb.BeaconBlockHeader{ + Slot: b.state.LatestBlockHeader.Slot, + ProposerIndex: b.state.LatestBlockHeader.ProposerIndex, + } + + parentRoot := make([]byte, len(b.state.LatestBlockHeader.ParentRoot)) + bodyRoot := make([]byte, len(b.state.LatestBlockHeader.BodyRoot)) + stateRoot := make([]byte, len(b.state.LatestBlockHeader.StateRoot)) + + copy(parentRoot, b.state.LatestBlockHeader.ParentRoot) + copy(bodyRoot, b.state.LatestBlockHeader.BodyRoot) + copy(stateRoot, b.state.LatestBlockHeader.StateRoot) + hdr.ParentRoot = parentRoot + hdr.BodyRoot = bodyRoot + hdr.StateRoot = stateRoot + return hdr +} + +// BlockRoots kept track of in the beacon state. +func (b *BeaconState) BlockRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.BlockRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.blockRoots() +} + +// blockRoots kept track of in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) blockRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.BlockRoots) +} + +// BlockRootAtIndex retrieves a specific block root based on an +// input index value. +func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.BlockRoots == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.blockRootAtIndex(idx) +} + +// blockRootAtIndex retrieves a specific block root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) blockRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + return bytesutil.SafeCopyRootAtIndex(b.state.BlockRoots, idx) +} diff --git a/beacon-chain/state-proto/v1/getters_block_test.go b/beacon-chain/state-proto/v1/getters_block_test.go new file mode 100644 index 0000000000..aee36ec9b0 --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_block_test.go @@ -0,0 +1,59 @@ +package v1 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_LatestBlockHeader(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconState{}) + require.NoError(t, err) + got := s.LatestBlockHeader() + require.DeepEqual(t, (*ethpb.BeaconBlockHeader)(nil), got) + + want := ðpb.BeaconBlockHeader{Slot: 100} + s, err = InitializeFromProto(ðpb.BeaconState{LatestBlockHeader: want}) + require.NoError(t, err) + got = s.LatestBlockHeader() + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got.Slot = 101 + require.DeepNotEqual(t, want, got) +} + +func TestBeaconState_BlockRoots(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconState{}) + require.NoError(t, err) + got := s.BlockRoots() + require.DeepEqual(t, ([][]byte)(nil), got) + + want := [][]byte{{'a'}} + s, err = InitializeFromProto(ðpb.BeaconState{BlockRoots: want}) + require.NoError(t, err) + got = s.BlockRoots() + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got[0][0] = 'b' + require.DeepNotEqual(t, want, got) +} + +func TestBeaconState_BlockRootAtIndex(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconState{}) + require.NoError(t, err) + got, err := s.BlockRootAtIndex(0) + require.NoError(t, err) + require.DeepEqual(t, ([]byte)(nil), got) + + r := [][]byte{{'a'}} + s, err = InitializeFromProto(ðpb.BeaconState{BlockRoots: r}) + require.NoError(t, err) + got, err = s.BlockRootAtIndex(0) + require.NoError(t, err) + want := bytesutil.PadTo([]byte{'a'}, 32) + require.DeepSSZEqual(t, want, got) +} diff --git a/beacon-chain/state-proto/v1/getters_checkpoint.go b/beacon-chain/state-proto/v1/getters_checkpoint.go new file mode 100644 index 0000000000..70f6237303 --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_checkpoint.go @@ -0,0 +1,160 @@ +package v1 + +import ( + "bytes" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// JustificationBits marking which epochs have been justified in the beacon chain. +func (b *BeaconState) JustificationBits() bitfield.Bitvector4 { + if !b.hasInnerState() { + return nil + } + if b.state.JustificationBits == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.justificationBits() +} + +// justificationBits marking which epochs have been justified in the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) justificationBits() bitfield.Bitvector4 { + if !b.hasInnerState() { + return nil + } + if b.state.JustificationBits == nil { + return nil + } + + res := make([]byte, len(b.state.JustificationBits.Bytes())) + copy(res, b.state.JustificationBits.Bytes()) + return res +} + +// PreviousJustifiedCheckpoint denoting an epoch and block root. +func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.PreviousJustifiedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.previousJustifiedCheckpoint() +} + +// previousJustifiedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) previousJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.PreviousJustifiedCheckpoint) +} + +// CurrentJustifiedCheckpoint denoting an epoch and block root. +func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.CurrentJustifiedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.currentJustifiedCheckpoint() +} + +// currentJustifiedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.CurrentJustifiedCheckpoint) +} + +// MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches +// the current justified checkpoint in state. +func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool { + if !b.hasInnerState() { + return false + } + if b.state.CurrentJustifiedCheckpoint == nil { + return false + } + + if c.Epoch != b.state.CurrentJustifiedCheckpoint.Epoch { + return false + } + return bytes.Equal(c.Root, b.state.CurrentJustifiedCheckpoint.Root) +} + +// MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches +// the previous justified checkpoint in state. +func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool { + if !b.hasInnerState() { + return false + } + if b.state.PreviousJustifiedCheckpoint == nil { + return false + } + + if c.Epoch != b.state.PreviousJustifiedCheckpoint.Epoch { + return false + } + return bytes.Equal(c.Root, b.state.PreviousJustifiedCheckpoint.Root) +} + +// FinalizedCheckpoint denoting an epoch and block root. +func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.FinalizedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.finalizedCheckpoint() +} + +// finalizedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) finalizedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.FinalizedCheckpoint) +} + +// FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint. +func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch { + if !b.hasInnerState() { + return 0 + } + if b.state.FinalizedCheckpoint == nil { + return 0 + } + b.lock.RLock() + defer b.lock.RUnlock() + + return b.state.FinalizedCheckpoint.Epoch +} diff --git a/beacon-chain/state-proto/v1/getters_eth1.go b/beacon-chain/state-proto/v1/getters_eth1.go new file mode 100644 index 0000000000..4f1ad84d12 --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_eth1.go @@ -0,0 +1,91 @@ +package v1 + +import ( + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// Eth1Data corresponding to the proof-of-work chain information stored in the beacon state. +func (b *BeaconState) Eth1Data() *ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1Data == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1Data() +} + +// eth1Data corresponding to the proof-of-work chain information stored in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1Data() *ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1Data == nil { + return nil + } + + return ethpb.CopyETH1Data(b.state.Eth1Data) +} + +// Eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain +// data retrieved from eth1. +func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1DataVotes == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1DataVotes() +} + +// eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain +// data retrieved from eth1. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1DataVotes() []*ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1DataVotes == nil { + return nil + } + + res := make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) + for i := 0; i < len(res); i++ { + res[i] = ethpb.CopyETH1Data(b.state.Eth1DataVotes[i]) + } + return res +} + +// Eth1DepositIndex corresponds to the index of the deposit made to the +// validator deposit contract at the time of this state's eth1 data. +func (b *BeaconState) Eth1DepositIndex() uint64 { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1DepositIndex() +} + +// eth1DepositIndex corresponds to the index of the deposit made to the +// validator deposit contract at the time of this state's eth1 data. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1DepositIndex() uint64 { + if !b.hasInnerState() { + return 0 + } + + return b.state.Eth1DepositIndex +} diff --git a/beacon-chain/state-proto/v1/getters_misc.go b/beacon-chain/state-proto/v1/getters_misc.go new file mode 100644 index 0000000000..b7c9cec335 --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_misc.go @@ -0,0 +1,163 @@ +package v1 + +import ( + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// GenesisTime of the beacon state as a uint64. +func (b *BeaconState) GenesisTime() uint64 { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisTime() +} + +// genesisTime of the beacon state as a uint64. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisTime() uint64 { + if !b.hasInnerState() { + return 0 + } + + return b.state.GenesisTime +} + +// GenesisValidatorRoot of the beacon state. +func (b *BeaconState) GenesisValidatorRoot() []byte { + if !b.hasInnerState() { + return nil + } + if b.state.GenesisValidatorsRoot == nil { + return params.BeaconConfig().ZeroHash[:] + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisValidatorRoot() +} + +// genesisValidatorRoot of the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisValidatorRoot() []byte { + if !b.hasInnerState() { + return nil + } + if b.state.GenesisValidatorsRoot == nil { + return params.BeaconConfig().ZeroHash[:] + } + + root := make([]byte, 32) + copy(root, b.state.GenesisValidatorsRoot) + return root +} + +// Version of the beacon state. This method +// is strictly meant to be used without a lock +// internally. +func (_ *BeaconState) Version() int { + return version.Phase0 +} + +// Slot of the current beacon chain state. +func (b *BeaconState) Slot() types.Slot { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.slot() +} + +// slot of the current beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) slot() types.Slot { + if !b.hasInnerState() { + return 0 + } + + return b.state.Slot +} + +// Fork version of the beacon chain. +func (b *BeaconState) Fork() *ethpb.Fork { + if !b.hasInnerState() { + return nil + } + if b.state.Fork == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.fork() +} + +// fork version of the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) fork() *ethpb.Fork { + if !b.hasInnerState() { + return nil + } + if b.state.Fork == nil { + return nil + } + + prevVersion := make([]byte, len(b.state.Fork.PreviousVersion)) + copy(prevVersion, b.state.Fork.PreviousVersion) + currVersion := make([]byte, len(b.state.Fork.CurrentVersion)) + copy(currVersion, b.state.Fork.CurrentVersion) + return ðpb.Fork{ + PreviousVersion: prevVersion, + CurrentVersion: currVersion, + Epoch: b.state.Fork.Epoch, + } +} + +// HistoricalRoots based on epochs stored in the beacon state. +func (b *BeaconState) HistoricalRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.HistoricalRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.historicalRoots() +} + +// historicalRoots based on epochs stored in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) historicalRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.HistoricalRoots) +} + +// balancesLength returns the length of the balances slice. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) balancesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.Balances == nil { + return 0 + } + + return len(b.state.Balances) +} diff --git a/beacon-chain/state-proto/v1/getters_randao.go b/beacon-chain/state-proto/v1/getters_randao.go new file mode 100644 index 0000000000..b222ceb36b --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_randao.go @@ -0,0 +1,85 @@ +package v1 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" +) + +// RandaoMixes of block proposers on the beacon chain. +func (b *BeaconState) RandaoMixes() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.RandaoMixes == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixes() +} + +// randaoMixes of block proposers on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixes() [][]byte { + if !b.hasInnerState() { + return nil + } + + return bytesutil.SafeCopy2dBytes(b.state.RandaoMixes) +} + +// RandaoMixAtIndex retrieves a specific block root based on an +// input index value. +func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.RandaoMixes == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixAtIndex(idx) +} + +// randaoMixAtIndex retrieves a specific block root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + + return bytesutil.SafeCopyRootAtIndex(b.state.RandaoMixes, idx) +} + +// RandaoMixesLength returns the length of the randao mixes slice. +func (b *BeaconState) RandaoMixesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.RandaoMixes == nil { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixesLength() +} + +// randaoMixesLength returns the length of the randao mixes slice. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.RandaoMixes == nil { + return 0 + } + + return len(b.state.RandaoMixes) +} diff --git a/beacon-chain/state-proto/v1/getters_state.go b/beacon-chain/state-proto/v1/getters_state.go new file mode 100644 index 0000000000..20c435480a --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_state.go @@ -0,0 +1,123 @@ +package v1 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// InnerStateUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) InnerStateUnsafe() interface{} { + if b == nil { + return nil + } + return b.state +} + +// CloneInnerState the beacon state into a protobuf for usage. +func (b *BeaconState) CloneInnerState() interface{} { + if b == nil || b.state == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + return ðpb.BeaconState{ + GenesisTime: b.genesisTime(), + GenesisValidatorsRoot: b.genesisValidatorRoot(), + Slot: b.slot(), + Fork: b.fork(), + LatestBlockHeader: b.latestBlockHeader(), + BlockRoots: b.blockRoots(), + StateRoots: b.stateRoots(), + HistoricalRoots: b.historicalRoots(), + Eth1Data: b.eth1Data(), + Eth1DataVotes: b.eth1DataVotes(), + Eth1DepositIndex: b.eth1DepositIndex(), + Validators: b.validators(), + Balances: b.balances(), + RandaoMixes: b.randaoMixes(), + Slashings: b.slashings(), + PreviousEpochAttestations: b.previousEpochAttestations(), + CurrentEpochAttestations: b.currentEpochAttestations(), + JustificationBits: b.justificationBits(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), + FinalizedCheckpoint: b.finalizedCheckpoint(), + } +} + +// hasInnerState detects if the internal reference to the state data structure +// is populated correctly. Returns false if nil. +func (b *BeaconState) hasInnerState() bool { + return b != nil && b.state != nil +} + +// StateRoots kept track of in the beacon state. +func (b *BeaconState) StateRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.StateRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.stateRoots() +} + +// StateRoots kept track of in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) stateRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.StateRoots) +} + +// StateRootAtIndex retrieves a specific state root based on an +// input index value. +func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.StateRoots == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.stateRootAtIndex(idx) +} + +// stateRootAtIndex retrieves a specific state root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) stateRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + return bytesutil.SafeCopyRootAtIndex(b.state.StateRoots, idx) +} + +// MarshalSSZ marshals the underlying beacon state to bytes. +func (b *BeaconState) MarshalSSZ() ([]byte, error) { + if !b.hasInnerState() { + return nil, errors.New("nil beacon state") + } + return b.state.MarshalSSZ() +} + +// ProtobufBeaconState transforms an input into beacon state in the form of protobuf. +// Error is returned if the input is not type protobuf beacon state. +func ProtobufBeaconState(s interface{}) (*ethpb.BeaconState, error) { + pbState, ok := s.(*ethpb.BeaconState) + if !ok { + return nil, errors.New("input is not type ethpb.BeaconState") + } + return pbState, nil +} diff --git a/beacon-chain/state-proto/v1/getters_test.go b/beacon-chain/state-proto/v1/getters_test.go new file mode 100644 index 0000000000..976bed6a77 --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_test.go @@ -0,0 +1,215 @@ +package v1 + +import ( + "runtime/debug" + "sync" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_SlotDataRace(t *testing.T) { + headState, err := InitializeFromProto(ðpb.BeaconState{Slot: 1}) + require.NoError(t, err) + + wg := sync.WaitGroup{} + wg.Add(2) + go func() { + require.NoError(t, headState.SetSlot(0)) + wg.Done() + }() + go func() { + headState.Slot() + wg.Done() + }() + + wg.Wait() +} + +func TestNilState_NoPanic(t *testing.T) { + var st *BeaconState + defer func() { + if r := recover(); r != nil { + t.Errorf("Method panicked when it was not supposed to: %v\n%v\n", r, string(debug.Stack())) + } + }() + // retrieve elements from nil state + _ = st.GenesisTime() + _ = st.GenesisValidatorRoot() + _ = st.GenesisValidatorRoot() + _ = st.Slot() + _ = st.Fork() + _ = st.LatestBlockHeader() + _ = st.BlockRoots() + _, err := st.BlockRootAtIndex(0) + _ = err + _ = st.StateRoots() + _ = st.HistoricalRoots() + _ = st.Eth1Data() + _ = st.Eth1DataVotes() + _ = st.Eth1DepositIndex() + _, err = st.ValidatorAtIndex(0) + _ = err + _, err = st.ValidatorAtIndexReadOnly(0) + _ = err + _, _ = st.ValidatorIndexByPubkey([48]byte{}) + _ = st.PubkeyAtIndex(0) + _ = st.NumValidators() + _ = st.Balances() + _, err = st.BalanceAtIndex(0) + _ = err + _ = st.BalancesLength() + _ = st.RandaoMixes() + _, err = st.RandaoMixAtIndex(0) + _ = err + _ = st.RandaoMixesLength() + _ = st.Slashings() + _, err = st.PreviousEpochAttestations() + require.NoError(t, err) + _, err = st.CurrentEpochAttestations() + require.NoError(t, err) + _ = st.JustificationBits() + _ = st.PreviousJustifiedCheckpoint() + _ = st.CurrentJustifiedCheckpoint() + _ = st.FinalizedCheckpoint() +} + +func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { + c1 := ðpb.Checkpoint{Epoch: 1} + c2 := ðpb.Checkpoint{Epoch: 2} + beaconState, err := InitializeFromProto(ðpb.BeaconState{CurrentJustifiedCheckpoint: c1}) + require.NoError(t, err) + require.Equal(t, true, beaconState.MatchCurrentJustifiedCheckpoint(c1)) + require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c2)) + require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c1)) + require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c2)) + beaconState.state = nil + require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c1)) +} + +func TestBeaconState_MatchPreviousJustifiedCheckpt(t *testing.T) { + c1 := ðpb.Checkpoint{Epoch: 1} + c2 := ðpb.Checkpoint{Epoch: 2} + beaconState, err := InitializeFromProto(ðpb.BeaconState{PreviousJustifiedCheckpoint: c1}) + require.NoError(t, err) + require.NoError(t, err) + require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c1)) + require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c2)) + require.Equal(t, true, beaconState.MatchPreviousJustifiedCheckpoint(c1)) + require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c2)) + beaconState.state = nil + require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c1)) +} + +func TestBeaconState_MarshalSSZ_NilState(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconState{}) + require.NoError(t, err) + s.state = nil + _, err = s.MarshalSSZ() + require.ErrorContains(t, "nil beacon state", err) +} + +func TestBeaconState_ValidatorByPubkey(t *testing.T) { + keyCreator := func(input []byte) [48]byte { + nKey := [48]byte{} + copy(nKey[:1], input) + return nKey + } + + tests := []struct { + name string + modifyFunc func(b *BeaconState, k [48]byte) + exists bool + expectedIdx types.ValidatorIndex + largestIdxInSet types.ValidatorIndex + }{ + { + name: "retrieve validator", + modifyFunc: func(b *BeaconState, key [48]byte) { + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators from the start", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + }, + exists: true, + expectedIdx: 2, + }, + { + name: "retrieve validator with multiple validators from the start with shared state", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + _ = b.Copy() + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators with shared state", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + n := b.Copy() + // Append to another state + assert.NoError(t, n.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + + }, + exists: false, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators with shared state at boundary", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + n := b.Copy() + // Append to another state + assert.NoError(t, n.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + + }, + exists: false, + expectedIdx: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconState{}) + require.NoError(t, err) + nKey := keyCreator([]byte{'A'}) + tt.modifyFunc(s, nKey) + idx, ok := s.ValidatorIndexByPubkey(nKey) + assert.Equal(t, tt.exists, ok) + assert.Equal(t, tt.expectedIdx, idx) + }) + } +} diff --git a/beacon-chain/state-proto/v1/getters_validator.go b/beacon-chain/state-proto/v1/getters_validator.go new file mode 100644 index 0000000000..6d833c1789 --- /dev/null +++ b/beacon-chain/state-proto/v1/getters_validator.go @@ -0,0 +1,297 @@ +package v1 + +import ( + "fmt" + + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist +// at a given index in the validator's array. +type ValidatorIndexOutOfRangeError struct { + message string +} + +var ( + // ErrNilValidatorsInState returns when accessing validators in the state while the state has a + // nil slice for the validators field. + ErrNilValidatorsInState = errors.New("state has nil validator slice") +) + +// NewValidatorIndexOutOfRangeError creates a new error instance. +func NewValidatorIndexOutOfRangeError(index types.ValidatorIndex) ValidatorIndexOutOfRangeError { + return ValidatorIndexOutOfRangeError{ + message: fmt.Sprintf("index %d out of range", index), + } +} + +// Error returns the underlying error message. +func (e *ValidatorIndexOutOfRangeError) Error() string { + return e.message +} + +// Validators participating in consensus on the beacon chain. +func (b *BeaconState) Validators() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.validators() +} + +// validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) validators() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + res := make([]*ethpb.Validator, len(b.state.Validators)) + for i := 0; i < len(res); i++ { + val := b.state.Validators[i] + if val == nil { + continue + } + res[i] = ethpb.CopyValidator(val) + } + return res +} + +// references of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. This does not +// copy fully and instead just copies the reference. +func (b *BeaconState) validatorsReferences() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + res := make([]*ethpb.Validator, len(b.state.Validators)) + for i := 0; i < len(res); i++ { + validator := b.state.Validators[i] + if validator == nil { + continue + } + // copy validator reference instead. + res[i] = validator + } + return res +} + +// ValidatorAtIndex is the validator at the provided index. +func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.Validators == nil { + return ðpb.Validator{}, nil + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + e := NewValidatorIndexOutOfRangeError(idx) + return nil, &e + } + + b.lock.RLock() + defer b.lock.RUnlock() + + val := b.state.Validators[idx] + return ethpb.CopyValidator(val), nil +} + +// ValidatorAtIndexReadOnly is the validator at the provided index. This method +// doesn't clone the validator. +func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.Validators == nil { + return nil, ErrNilValidatorsInState + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + e := NewValidatorIndexOutOfRangeError(idx) + return nil, &e + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return NewValidator(b.state.Validators[idx]) +} + +// ValidatorIndexByPubkey returns a given validator by its 48-byte public key. +func (b *BeaconState) ValidatorIndexByPubkey(key [48]byte) (types.ValidatorIndex, bool) { + if b == nil || b.valMapHandler == nil || b.valMapHandler.IsNil() { + return 0, false + } + b.lock.RLock() + defer b.lock.RUnlock() + numOfVals := len(b.state.Validators) + + idx, ok := b.valMapHandler.Get(key) + if ok && numOfVals <= int(idx) { + return types.ValidatorIndex(0), false + } + return idx, ok +} + +// PubkeyAtIndex returns the pubkey at the given +// validator index. +func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [48]byte { + if !b.hasInnerState() { + return [48]byte{} + } + if uint64(idx) >= uint64(len(b.state.Validators)) { + return [48]byte{} + } + b.lock.RLock() + defer b.lock.RUnlock() + + if b.state.Validators[idx] == nil { + return [48]byte{} + } + return bytesutil.ToBytes48(b.state.Validators[idx].PublicKey) +} + +// NumValidators returns the size of the validator registry. +func (b *BeaconState) NumValidators() int { + if !b.hasInnerState() { + return 0 + } + b.lock.RLock() + defer b.lock.RUnlock() + + return len(b.state.Validators) +} + +// ReadFromEveryValidator reads values from every validator and applies it to the provided function. +// Warning: This method is potentially unsafe, as it exposes the actual validator registry. +func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if b.state.Validators == nil { + return errors.New("nil validators in state") + } + b.lock.RLock() + validators := b.state.Validators + b.lock.RUnlock() + + for i, v := range validators { + v, err := NewValidator(v) + if err != nil { + return err + } + if err := f(i, v); err != nil { + return err + } + } + return nil +} + +// Balances of validators participating in consensus on the beacon chain. +func (b *BeaconState) Balances() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Balances == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.balances() +} + +// balances of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) balances() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Balances == nil { + return nil + } + + res := make([]uint64, len(b.state.Balances)) + copy(res, b.state.Balances) + return res +} + +// BalanceAtIndex of validator with the provided index. +func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) { + if !b.hasInnerState() { + return 0, ErrNilInnerState + } + if b.state.Balances == nil { + return 0, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + if uint64(len(b.state.Balances)) <= uint64(idx) { + return 0, fmt.Errorf("index of %d does not exist", idx) + } + return b.state.Balances[idx], nil +} + +// BalancesLength returns the length of the balances slice. +func (b *BeaconState) BalancesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.Balances == nil { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.balancesLength() +} + +// Slashings of validators on the beacon chain. +func (b *BeaconState) Slashings() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Slashings == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.slashings() +} + +// slashings of validators on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) slashings() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Slashings == nil { + return nil + } + + res := make([]uint64, len(b.state.Slashings)) + copy(res, b.state.Slashings) + return res +} diff --git a/beacon-chain/state/v1/getters_validator_test.go b/beacon-chain/state-proto/v1/getters_validator_test.go similarity index 88% rename from beacon-chain/state/v1/getters_validator_test.go rename to beacon-chain/state-proto/v1/getters_validator_test.go index cb2834976a..552ba816f4 100644 --- a/beacon-chain/state/v1/getters_validator_test.go +++ b/beacon-chain/state-proto/v1/getters_validator_test.go @@ -3,7 +3,7 @@ package v1_test import ( "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/state-proto/v1/proofs.go b/beacon-chain/state-proto/v1/proofs.go new file mode 100644 index 0000000000..1efbc0dba0 --- /dev/null +++ b/beacon-chain/state-proto/v1/proofs.go @@ -0,0 +1,47 @@ +package v1 + +import ( + "encoding/binary" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" +) + +const ( + finalizedRootIndex = uint64(105) // Precomputed value. +) + +// FinalizedRootGeneralizedIndex for the beacon state. +func FinalizedRootGeneralizedIndex() uint64 { + return finalizedRootIndex +} + +// CurrentSyncCommitteeProof from the state's Merkle trie representation. +func (*BeaconState) CurrentSyncCommitteeProof() ([][]byte, error) { + return nil, errors.New("CurrentSyncCommitteeProof() unsupported for v1 beacon state") +} + +// NextSyncCommitteeProof from the state's Merkle trie representation. +func (*BeaconState) NextSyncCommitteeProof() ([][]byte, error) { + return nil, errors.New("NextSyncCommitteeProof() unsupported for v1 beacon state") +} + +// FinalizedRootProof crafts a Merkle proof for the finalized root +// contained within the finalized checkpoint of a beacon state. +func (b *BeaconState) FinalizedRootProof() ([][]byte, error) { + b.lock.RLock() + defer b.lock.RUnlock() + cpt := b.state.FinalizedCheckpoint + // The epoch field of a finalized checkpoint is the neighbor + // index of the finalized root field in its Merkle tree representation + // of the checkpoint. This neighbor is the first element added to the proof. + epochBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(epochBuf, uint64(cpt.Epoch)) + epochRoot := bytesutil.ToBytes32(epochBuf) + proof := make([][]byte, 0) + proof = append(proof, epochRoot[:]) + branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) + proof = append(proof, branch...) + return proof, nil +} diff --git a/beacon-chain/state/v1/proofs_test.go b/beacon-chain/state-proto/v1/proofs_test.go similarity index 93% rename from beacon-chain/state/v1/proofs_test.go rename to beacon-chain/state-proto/v1/proofs_test.go index 15ab78185a..0632977d89 100644 --- a/beacon-chain/state/v1/proofs_test.go +++ b/beacon-chain/state-proto/v1/proofs_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" diff --git a/beacon-chain/state-proto/v1/readonly_validator.go b/beacon-chain/state-proto/v1/readonly_validator.go new file mode 100644 index 0000000000..e60fd5d1d3 --- /dev/null +++ b/beacon-chain/state-proto/v1/readonly_validator.go @@ -0,0 +1,88 @@ +package v1 + +import ( + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +var ( + // ErrNilWrappedValidator returns when caller attempts to wrap a nil pointer validator. + ErrNilWrappedValidator = errors.New("nil validator cannot be wrapped as readonly") +) + +// readOnlyValidator returns a wrapper that only allows fields from a validator +// to be read, and prevents any modification of internal validator fields. +type readOnlyValidator struct { + validator *ethpb.Validator +} + +var _ = state.ReadOnlyValidator(readOnlyValidator{}) + +// NewValidator initializes the read only wrapper for validator. +func NewValidator(v *ethpb.Validator) (state.ReadOnlyValidator, error) { + rov := readOnlyValidator{ + validator: v, + } + if rov.IsNil() { + return nil, ErrNilWrappedValidator + } + return rov, nil +} + +// EffectiveBalance returns the effective balance of the +// read only validator. +func (v readOnlyValidator) EffectiveBalance() uint64 { + return v.validator.EffectiveBalance +} + +// ActivationEligibilityEpoch returns the activation eligibility epoch of the +// read only validator. +func (v readOnlyValidator) ActivationEligibilityEpoch() types.Epoch { + return v.validator.ActivationEligibilityEpoch +} + +// ActivationEpoch returns the activation epoch of the +// read only validator. +func (v readOnlyValidator) ActivationEpoch() types.Epoch { + return v.validator.ActivationEpoch +} + +// WithdrawableEpoch returns the withdrawable epoch of the +// read only validator. +func (v readOnlyValidator) WithdrawableEpoch() types.Epoch { + return v.validator.WithdrawableEpoch +} + +// ExitEpoch returns the exit epoch of the +// read only validator. +func (v readOnlyValidator) ExitEpoch() types.Epoch { + return v.validator.ExitEpoch +} + +// PublicKey returns the public key of the +// read only validator. +func (v readOnlyValidator) PublicKey() [48]byte { + var pubkey [48]byte + copy(pubkey[:], v.validator.PublicKey) + return pubkey +} + +// WithdrawalCredentials returns the withdrawal credentials of the +// read only validator. +func (v readOnlyValidator) WithdrawalCredentials() []byte { + creds := make([]byte, len(v.validator.WithdrawalCredentials)) + copy(creds, v.validator.WithdrawalCredentials) + return creds +} + +// Slashed returns the read only validator is slashed. +func (v readOnlyValidator) Slashed() bool { + return v.validator.Slashed +} + +// IsNil returns true if the validator is nil. +func (v readOnlyValidator) IsNil() bool { + return v.validator == nil +} diff --git a/beacon-chain/state/v1/readonly_validator_test.go b/beacon-chain/state-proto/v1/readonly_validator_test.go similarity index 97% rename from beacon-chain/state/v1/readonly_validator_test.go rename to beacon-chain/state-proto/v1/readonly_validator_test.go index 6c7cd3c5a0..da6ad9e128 100644 --- a/beacon-chain/state/v1/readonly_validator_test.go +++ b/beacon-chain/state-proto/v1/readonly_validator_test.go @@ -4,7 +4,7 @@ import ( "testing" types "github.com/prysmaticlabs/eth2-types" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" diff --git a/beacon-chain/state-proto/v1/references_test.go b/beacon-chain/state-proto/v1/references_test.go new file mode 100644 index 0000000000..0562d499ff --- /dev/null +++ b/beacon-chain/state-proto/v1/references_test.go @@ -0,0 +1,354 @@ +package v1 + +import ( + "reflect" + "runtime" + "runtime/debug" + "testing" + + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestStateReferenceSharing_Finalizer(t *testing.T) { + // This test showcases the logic on a the RandaoMixes field with the GC finalizer. + + a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{RandaoMixes: [][]byte{[]byte("foo")}}) + require.NoError(t, err) + assert.Equal(t, uint(1), a.sharedFieldReferences[randaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + + func() { + // Create object in a different scope for GC + b := a.Copy() + assert.Equal(t, uint(2), a.sharedFieldReferences[randaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + _ = b + }() + + runtime.GC() // Should run finalizer on object b + assert.Equal(t, uint(1), a.sharedFieldReferences[randaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assert.Equal(t, uint(2), b.sharedFieldReferences[randaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) + if b.sharedFieldReferences[randaoMixes].Refs() != 1 || a.sharedFieldReferences[randaoMixes].Refs() != 1 { + t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + } +} + +func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) { + root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) + a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ + BlockRoots: [][]byte{ + root1[:], + }, + StateRoots: [][]byte{ + root1[:], + }, + }) + require.NoError(t, err) + assertRefCount(t, a, blockRoots, 1) + assertRefCount(t, a, stateRoots, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, blockRoots, 2) + assertRefCount(t, a, stateRoots, 2) + assertRefCount(t, b, blockRoots, 2) + assertRefCount(t, b, stateRoots, 2) + assert.Equal(t, 1, len(b.state.GetBlockRoots()), "No block roots found") + assert.Equal(t, 1, len(b.state.GetStateRoots()), "No state roots found") + + // Assert shared state. + blockRootsA := a.state.GetBlockRoots() + stateRootsA := a.state.GetStateRoots() + blockRootsB := b.state.GetBlockRoots() + stateRootsB := b.state.GetStateRoots() + if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { + t.Errorf("Unexpected number of block roots, want: %v", 1) + } + if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { + t.Errorf("Unexpected number of state roots, want: %v", 1) + } + 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.state.GetBlockRoots(), root1[:]) + assertValNotFound(t, a.state.GetStateRoots(), root1[:]) + assertValFound(t, a.state.GetBlockRoots(), root2[:]) + assertValFound(t, a.state.GetStateRoots(), root2[:]) + assertValFound(t, b.state.GetBlockRoots(), root1[:]) + assertValFound(t, b.state.GetStateRoots(), root1[:]) + if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { + t.Errorf("Unexpected number of block roots, want: %v", 1) + } + if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { + t.Errorf("Unexpected number of state roots, want: %v", 1) + } + assert.DeepEqual(t, root2[:], a.state.GetBlockRoots()[0], "Expected mutation not found") + assert.DeepEqual(t, root2[:], a.state.GetStateRoots()[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, blockRoots, 1) + assertRefCount(t, a, stateRoots, 1) + assertRefCount(t, b, blockRoots, 1) + assertRefCount(t, b, stateRoots, 1) +} + +func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) { + + val1, val2 := []byte("foo"), []byte("bar") + a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ + RandaoMixes: [][]byte{ + val1, + }, + }) + require.NoError(t, err) + assertRefCount(t, a, randaoMixes, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, randaoMixes, 2) + assertRefCount(t, b, randaoMixes, 2) + assert.Equal(t, 1, len(b.state.GetRandaoMixes()), "No randao mixes found") + + // Assert shared state. + mixesA := a.state.GetRandaoMixes() + mixesB := b.state.GetRandaoMixes() + if len(mixesA) != len(mixesB) || len(mixesA) < 1 { + t.Errorf("Unexpected number of mix values, want: %v", 1) + } + 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). + if len(mixesA) != len(mixesB) || len(mixesA) < 1 { + t.Errorf("Unexpected number of mix values, want: %v", 1) + } + assertValFound(t, a.state.GetRandaoMixes(), val2) + assertValNotFound(t, a.state.GetRandaoMixes(), val1) + assertValFound(t, b.state.GetRandaoMixes(), val1) + assertValNotFound(t, b.state.GetRandaoMixes(), val2) + assertValFound(t, mixesB, val1) + assertValNotFound(t, mixesB, val2) + assert.DeepEqual(t, val2, a.state.GetRandaoMixes()[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, randaoMixes, 1) + assertRefCount(t, b, randaoMixes, 1) +} + +func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) { + assertAttFound := func(vals []*ethpb.PendingAttestation, val uint64) { + for i := range vals { + if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) { + return + } + } + t.Log(string(debug.Stack())) + t.Fatalf("Expected attestation not found (%v), want: %v", vals, val) + } + assertAttNotFound := func(vals []*ethpb.PendingAttestation, val uint64) { + for i := range vals { + if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) { + t.Log(string(debug.Stack())) + t.Fatalf("Unexpected attestation found (%v): %v", vals, val) + return + } + } + } + + a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{}) + require.NoError(t, err) + assertRefCount(t, a, previousEpochAttestations, 1) + assertRefCount(t, a, currentEpochAttestations, 1) + + // Update initial state. + atts := []*ethpb.PendingAttestation{ + {AggregationBits: bitfield.NewBitlist(1)}, + {AggregationBits: bitfield.NewBitlist(2)}, + } + a.setPreviousEpochAttestations(atts[:1]) + a.setCurrentEpochAttestations(atts[:1]) + curAtt, err := a.CurrentEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 1, len(curAtt), "Unexpected number of attestations") + preAtt, err := a.PreviousEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 1, len(preAtt), "Unexpected number of attestations") + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, previousEpochAttestations, 2) + assertRefCount(t, a, currentEpochAttestations, 2) + assertRefCount(t, b, previousEpochAttestations, 2) + assertRefCount(t, b, currentEpochAttestations, 2) + assert.Equal(t, 1, len(b.state.GetPreviousEpochAttestations()), "Unexpected number of attestations") + assert.Equal(t, 1, len(b.state.GetCurrentEpochAttestations()), "Unexpected number of attestations") + + // Assert shared state. + curAttsA := a.state.GetCurrentEpochAttestations() + prevAttsA := a.state.GetPreviousEpochAttestations() + curAttsB := b.state.GetCurrentEpochAttestations() + prevAttsB := b.state.GetPreviousEpochAttestations() + if len(curAttsA) != len(curAttsB) || len(curAttsA) < 1 { + t.Errorf("Unexpected number of attestations, want: %v", 1) + } + if len(prevAttsA) != len(prevAttsB) || len(prevAttsA) < 1 { + t.Errorf("Unexpected number of attestations, want: %v", 1) + } + assertAttFound(curAttsA, 1) + assertAttFound(prevAttsA, 1) + assertAttFound(curAttsB, 1) + assertAttFound(prevAttsB, 1) + + // Extends state a attestations. + require.NoError(t, a.AppendCurrentEpochAttestations(atts[1])) + require.NoError(t, a.AppendPreviousEpochAttestations(atts[1])) + curAtt, err = a.CurrentEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 2, len(curAtt), "Unexpected number of attestations") + preAtt, err = a.PreviousEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 2, len(preAtt), "Unexpected number of attestations") + assertAttFound(a.state.GetCurrentEpochAttestations(), 1) + assertAttFound(a.state.GetPreviousEpochAttestations(), 1) + assertAttFound(a.state.GetCurrentEpochAttestations(), 2) + assertAttFound(a.state.GetPreviousEpochAttestations(), 2) + assertAttFound(b.state.GetCurrentEpochAttestations(), 1) + assertAttFound(b.state.GetPreviousEpochAttestations(), 1) + assertAttNotFound(b.state.GetCurrentEpochAttestations(), 2) + assertAttNotFound(b.state.GetPreviousEpochAttestations(), 2) + + // Mutator should only affect calling state: a. + applyToEveryAttestation := func(state *ethpb.BeaconState) { + // One MUST copy on write. + atts = make([]*ethpb.PendingAttestation, len(state.CurrentEpochAttestations)) + copy(atts, state.CurrentEpochAttestations) + state.CurrentEpochAttestations = atts + for i := range state.GetCurrentEpochAttestations() { + att := ethpb.CopyPendingAttestation(state.CurrentEpochAttestations[i]) + att.AggregationBits = bitfield.NewBitlist(3) + state.CurrentEpochAttestations[i] = att + } + + atts = make([]*ethpb.PendingAttestation, len(state.PreviousEpochAttestations)) + copy(atts, state.PreviousEpochAttestations) + state.PreviousEpochAttestations = atts + for i := range state.GetPreviousEpochAttestations() { + att := ethpb.CopyPendingAttestation(state.PreviousEpochAttestations[i]) + att.AggregationBits = bitfield.NewBitlist(3) + state.PreviousEpochAttestations[i] = att + } + } + applyToEveryAttestation(a.state) + + // Assert no shared state mutation occurred only on state a (copy on write). + assertAttFound(a.state.GetCurrentEpochAttestations(), 3) + assertAttFound(a.state.GetPreviousEpochAttestations(), 3) + assertAttNotFound(a.state.GetCurrentEpochAttestations(), 1) + assertAttNotFound(a.state.GetPreviousEpochAttestations(), 1) + assertAttNotFound(a.state.GetCurrentEpochAttestations(), 2) + assertAttNotFound(a.state.GetPreviousEpochAttestations(), 2) + // State b must be unaffected. + assertAttNotFound(b.state.GetCurrentEpochAttestations(), 3) + assertAttNotFound(b.state.GetPreviousEpochAttestations(), 3) + assertAttFound(b.state.GetCurrentEpochAttestations(), 1) + assertAttFound(b.state.GetPreviousEpochAttestations(), 1) + assertAttNotFound(b.state.GetCurrentEpochAttestations(), 2) + assertAttNotFound(b.state.GetPreviousEpochAttestations(), 2) + + // Copy on write happened, reference counters are reset. + assertRefCount(t, a, currentEpochAttestations, 1) + assertRefCount(t, b, currentEpochAttestations, 1) + assertRefCount(t, a, previousEpochAttestations, 1) + assertRefCount(t, b, previousEpochAttestations, 1) +} + +func TestValidatorReferences_RemainsConsistent(t *testing.T) { + a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ + Validators: []*ethpb.Validator{ + {PublicKey: []byte{'A'}}, + {PublicKey: []byte{'B'}}, + {PublicKey: []byte{'C'}}, + {PublicKey: []byte{'D'}}, + {PublicKey: []byte{'E'}}, + }, + }) + require.NoError(t, err) + + // Create a second state. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + + // Update First Validator. + assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}})) + + assert.DeepNotEqual(t, a.state.Validators[0], b.state.Validators[0], "validators are equal when they are supposed to be different") + // Modify all validators from copied state. + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { + return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + })) + + // Ensure reference is properly accounted for. + assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { + assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey()) + return nil + })) +} + +// assertRefCount checks whether reference count for a given state +// at a given index is equal to expected amount. +func assertRefCount(t *testing.T, b *BeaconState, idx types.FieldIndex, want uint) { + if cnt := b.sharedFieldReferences[idx].Refs(); cnt != want { + 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 + } + } +} diff --git a/beacon-chain/state-proto/v1/setters_attestation.go b/beacon-chain/state-proto/v1/setters_attestation.go new file mode 100644 index 0000000000..26de75b54e --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_attestation.go @@ -0,0 +1,98 @@ +package v1 + +import ( + "fmt" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// RotateAttestations sets the previous epoch attestations to the current epoch attestations and +// then clears the current epoch attestations. +func (b *BeaconState) RotateAttestations() error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.setPreviousEpochAttestations(b.currentEpochAttestations()) + b.setCurrentEpochAttestations([]*ethpb.PendingAttestation{}) + return nil +} + +func (b *BeaconState) setPreviousEpochAttestations(val []*ethpb.PendingAttestation) { + b.sharedFieldReferences[previousEpochAttestations].MinusRef() + b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) + + b.state.PreviousEpochAttestations = val + b.markFieldAsDirty(previousEpochAttestations) + b.rebuildTrie[previousEpochAttestations] = true +} + +func (b *BeaconState) setCurrentEpochAttestations(val []*ethpb.PendingAttestation) { + b.sharedFieldReferences[currentEpochAttestations].MinusRef() + b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) + + b.state.CurrentEpochAttestations = val + b.markFieldAsDirty(currentEpochAttestations) + b.rebuildTrie[currentEpochAttestations] = true +} + +// AppendCurrentEpochAttestations for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendCurrentEpochAttestations(val *ethpb.PendingAttestation) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + atts := b.state.CurrentEpochAttestations + max := uint64(fieldparams.CurrentEpochAttestationsLength) + if uint64(len(atts)) >= max { + return fmt.Errorf("current pending attestation exceeds max length %d", max) + } + + if b.sharedFieldReferences[currentEpochAttestations].Refs() > 1 { + // Copy elements in underlying array by reference. + atts = make([]*ethpb.PendingAttestation, len(b.state.CurrentEpochAttestations)) + copy(atts, b.state.CurrentEpochAttestations) + b.sharedFieldReferences[currentEpochAttestations].MinusRef() + b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) + } + + b.state.CurrentEpochAttestations = append(atts, val) + b.markFieldAsDirty(currentEpochAttestations) + b.addDirtyIndices(currentEpochAttestations, []uint64{uint64(len(b.state.CurrentEpochAttestations) - 1)}) + return nil +} + +// AppendPreviousEpochAttestations for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendPreviousEpochAttestations(val *ethpb.PendingAttestation) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + atts := b.state.PreviousEpochAttestations + max := uint64(fieldparams.PreviousEpochAttestationsLength) + if uint64(len(atts)) >= max { + return fmt.Errorf("previous pending attestation exceeds max length %d", max) + } + + if b.sharedFieldReferences[previousEpochAttestations].Refs() > 1 { + atts = make([]*ethpb.PendingAttestation, len(b.state.PreviousEpochAttestations)) + copy(atts, b.state.PreviousEpochAttestations) + b.sharedFieldReferences[previousEpochAttestations].MinusRef() + b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) + } + + b.state.PreviousEpochAttestations = append(atts, val) + b.markFieldAsDirty(previousEpochAttestations) + b.addDirtyIndices(previousEpochAttestations, []uint64{uint64(len(b.state.PreviousEpochAttestations) - 1)}) + return nil +} diff --git a/beacon-chain/state-proto/v1/setters_attestation_test.go b/beacon-chain/state-proto/v1/setters_attestation_test.go new file mode 100644 index 0000000000..45494e7a17 --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_attestation_test.go @@ -0,0 +1,72 @@ +package v1 + +import ( + "context" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_RotateAttestations(t *testing.T) { + st, err := InitializeFromProto(ðpb.BeaconState{ + Slot: 1, + CurrentEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 456}}}, + PreviousEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 123}}}, + }) + require.NoError(t, err) + + require.NoError(t, st.RotateAttestations()) + require.Equal(t, 0, len(st.currentEpochAttestations())) + require.Equal(t, types.Slot(456), st.previousEpochAttestations()[0].Data.Slot) +} + +func TestAppendBeyondIndicesLimit(t *testing.T) { + zeroHash := params.BeaconConfig().ZeroHash + mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockblockRoots); i++ { + mockblockRoots[i] = zeroHash[:] + } + + mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockstateRoots); i++ { + mockstateRoots[i] = zeroHash[:] + } + mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(mockrandaoMixes); i++ { + mockrandaoMixes[i] = zeroHash[:] + } + st, err := InitializeFromProto(ðpb.BeaconState{ + Slot: 1, + CurrentEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 456}}}, + PreviousEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 123}}}, + Validators: []*ethpb.Validator{}, + Eth1Data: ðpb.Eth1Data{}, + BlockRoots: mockblockRoots, + StateRoots: mockstateRoots, + RandaoMixes: mockrandaoMixes, + }) + require.NoError(t, err) + _, err = st.HashTreeRoot(context.Background()) + require.NoError(t, err) + for i := stateTypes.FieldIndex(0); i < stateTypes.FieldIndex(params.BeaconConfig().BeaconStateFieldCount); i++ { + st.dirtyFields[i] = true + } + _, err = st.HashTreeRoot(context.Background()) + require.NoError(t, err) + for i := 0; i < 10; i++ { + assert.NoError(t, st.AppendValidator(ðpb.Validator{})) + } + assert.Equal(t, false, st.rebuildTrie[validators]) + assert.NotEqual(t, len(st.dirtyIndices[validators]), 0) + + for i := 0; i < indicesLimit; i++ { + assert.NoError(t, st.AppendValidator(ðpb.Validator{})) + } + assert.Equal(t, true, st.rebuildTrie[validators]) + assert.Equal(t, len(st.dirtyIndices[validators]), 0) +} diff --git a/beacon-chain/state-proto/v1/setters_block.go b/beacon-chain/state-proto/v1/setters_block.go new file mode 100644 index 0000000000..8e974331df --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_block.go @@ -0,0 +1,68 @@ +package v1 + +import ( + "fmt" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetLatestBlockHeader in the beacon state. +func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.LatestBlockHeader = ethpb.CopyBeaconBlockHeader(val) + b.markFieldAsDirty(latestBlockHeader) + return nil +} + +// SetBlockRoots for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetBlockRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[blockRoots].MinusRef() + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + + b.state.BlockRoots = val + b.markFieldAsDirty(blockRoots) + b.rebuildTrie[blockRoots] = true + return nil +} + +// UpdateBlockRootAtIndex for the beacon state. Updates the block root +// at a specific index to a new value. +func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.BlockRoots)) <= idx { + return fmt.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + r := b.state.BlockRoots + if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { + // Copy elements in underlying array by reference. + r = make([][]byte, len(b.state.BlockRoots)) + copy(r, b.state.BlockRoots) + ref.MinusRef() + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + } + + r[idx] = blockRoot[:] + b.state.BlockRoots = r + + b.markFieldAsDirty(blockRoots) + b.addDirtyIndices(blockRoots, []uint64{idx}) + return nil +} diff --git a/beacon-chain/state-proto/v1/setters_checkpoint.go b/beacon-chain/state-proto/v1/setters_checkpoint.go new file mode 100644 index 0000000000..bf84053ee3 --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_checkpoint.go @@ -0,0 +1,58 @@ +package v1 + +import ( + "github.com/prysmaticlabs/go-bitfield" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetJustificationBits for the beacon state. +func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.JustificationBits = val + b.markFieldAsDirty(justificationBits) + return nil +} + +// SetPreviousJustifiedCheckpoint for the beacon state. +func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.PreviousJustifiedCheckpoint = val + b.markFieldAsDirty(previousJustifiedCheckpoint) + return nil +} + +// SetCurrentJustifiedCheckpoint for the beacon state. +func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.CurrentJustifiedCheckpoint = val + b.markFieldAsDirty(currentJustifiedCheckpoint) + return nil +} + +// SetFinalizedCheckpoint for the beacon state. +func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.FinalizedCheckpoint = val + b.markFieldAsDirty(finalizedCheckpoint) + return nil +} diff --git a/beacon-chain/state-proto/v1/setters_eth1.go b/beacon-chain/state-proto/v1/setters_eth1.go new file mode 100644 index 0000000000..fb9ae92f5b --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_eth1.go @@ -0,0 +1,74 @@ +package v1 + +import ( + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetEth1Data for the beacon state. +func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Eth1Data = val + b.markFieldAsDirty(eth1Data) + return nil +} + +// SetEth1DataVotes for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[eth1DataVotes].MinusRef() + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + + b.state.Eth1DataVotes = val + b.markFieldAsDirty(eth1DataVotes) + b.rebuildTrie[eth1DataVotes] = true + return nil +} + +// SetEth1DepositIndex for the beacon state. +func (b *BeaconState) SetEth1DepositIndex(val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Eth1DepositIndex = val + b.markFieldAsDirty(eth1DepositIndex) + return nil +} + +// AppendEth1DataVotes for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + votes := b.state.Eth1DataVotes + if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { + // Copy elements in underlying array by reference. + votes = make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) + copy(votes, b.state.Eth1DataVotes) + b.sharedFieldReferences[eth1DataVotes].MinusRef() + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + } + + b.state.Eth1DataVotes = append(votes, val) + b.markFieldAsDirty(eth1DataVotes) + b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.state.Eth1DataVotes) - 1)}) + return nil +} diff --git a/beacon-chain/state-proto/v1/setters_misc.go b/beacon-chain/state-proto/v1/setters_misc.go new file mode 100644 index 0000000000..c689ffdf82 --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_misc.go @@ -0,0 +1,187 @@ +package v1 + +import ( + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/features" + "github.com/prysmaticlabs/prysm/crypto/hash" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "google.golang.org/protobuf/proto" +) + +// For our setters, we have a field reference counter through +// which we can track shared field references. This helps when +// performing state copies, as we simply copy the reference to the +// field. When we do need to modify these fields, we +// perform a full copy of the field. This is true of most of our +// fields except for the following below. +// 1) BlockRoots +// 2) StateRoots +// 3) Eth1DataVotes +// 4) RandaoMixes +// 5) HistoricalRoots +// 6) CurrentEpochAttestations +// 7) PreviousEpochAttestations +// 8) Validators +// +// The fields referred to above are instead copied by reference, where +// we simply copy the reference to the underlying object instead of the +// whole object. This is possible due to how we have structured our state +// as we copy the value on read, so as to ensure the underlying object is +// not mutated while it is being accessed during a state read. + +const ( + // This specifies the limit till which we process all dirty indices for a certain field. + // If we have more dirty indices than the threshold, then we rebuild the whole trie. This + // comes due to the fact that O(alogn) > O(n) beyond a certain value of a. + indicesLimit = 8000 +) + +// SetGenesisTime for the beacon state. +func (b *BeaconState) SetGenesisTime(val uint64) error { + b.lock.Lock() + defer b.lock.Unlock() + + b.state.GenesisTime = val + b.markFieldAsDirty(genesisTime) + return nil +} + +// SetGenesisValidatorRoot for the beacon state. +func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error { + b.lock.Lock() + defer b.lock.Unlock() + + b.state.GenesisValidatorsRoot = val + b.markFieldAsDirty(genesisValidatorRoot) + return nil +} + +// SetSlot for the beacon state. +func (b *BeaconState) SetSlot(val types.Slot) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Slot = val + b.markFieldAsDirty(slot) + return nil +} + +// SetFork version for the beacon chain. +func (b *BeaconState) SetFork(val *ethpb.Fork) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + fk, ok := proto.Clone(val).(*ethpb.Fork) + if !ok { + return errors.New("proto.Clone did not return a fork proto") + } + b.state.Fork = fk + b.markFieldAsDirty(fork) + return nil +} + +// SetHistoricalRoots for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[historicalRoots].MinusRef() + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + + b.state.HistoricalRoots = val + b.markFieldAsDirty(historicalRoots) + return nil +} + +// AppendHistoricalRoots for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + roots := b.state.HistoricalRoots + if b.sharedFieldReferences[historicalRoots].Refs() > 1 { + roots = make([][]byte, len(b.state.HistoricalRoots)) + copy(roots, b.state.HistoricalRoots) + b.sharedFieldReferences[historicalRoots].MinusRef() + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + } + + b.state.HistoricalRoots = append(roots, root[:]) + b.markFieldAsDirty(historicalRoots) + return nil +} + +// Recomputes the branch up the index in the Merkle trie representation +// of the beacon state. This method performs slice reads and the caller MUST +// hold the lock before calling this method. +func (b *BeaconState) recomputeRoot(idx int) { + hashFunc := hash.CustomSHA256Hasher() + layers := b.merkleLayers + // The merkle tree structure looks as follows: + // [[r1, r2, r3, r4], [parent1, parent2], [root]] + // Using information about the index which changed, idx, we recompute + // only its branch up the tree. + currentIndex := idx + root := b.merkleLayers[0][idx] + for i := 0; i < len(layers)-1; i++ { + isLeft := currentIndex%2 == 0 + neighborIdx := currentIndex ^ 1 + + neighbor := make([]byte, 32) + if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) { + neighbor = layers[i][neighborIdx] + } + if isLeft { + parentHash := hashFunc(append(root, neighbor...)) + root = parentHash[:] + } else { + parentHash := hashFunc(append(neighbor, root...)) + root = parentHash[:] + } + parentIdx := currentIndex / 2 + // Update the cached layers at the parent index. + layers[i+1][parentIdx] = root + currentIndex = parentIdx + } + b.merkleLayers = layers +} + +func (b *BeaconState) markFieldAsDirty(field stateTypes.FieldIndex) { + b.dirtyFields[field] = true +} + +// addDirtyIndices adds the relevant dirty field indices, so that they +// can be recomputed. +func (b *BeaconState) addDirtyIndices(index stateTypes.FieldIndex, indices []uint64) { + if b.rebuildTrie[index] { + return + } + // Exit early if balance trie computation isn't enabled. + if !features.Get().EnableBalanceTrieComputation && index == balances { + return + } + totalIndicesLen := len(b.dirtyIndices[index]) + len(indices) + if totalIndicesLen > indicesLimit { + b.rebuildTrie[index] = true + b.dirtyIndices[index] = []uint64{} + } else { + b.dirtyIndices[index] = append(b.dirtyIndices[index], indices...) + } +} diff --git a/beacon-chain/state-proto/v1/setters_randao.go b/beacon-chain/state-proto/v1/setters_randao.go new file mode 100644 index 0000000000..6fcd8b6fe9 --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_randao.go @@ -0,0 +1,53 @@ +package v1 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetRandaoMixes for the beacon state. Updates the entire +// randao mixes to a new value by overwriting the previous one. +func (b *BeaconState) SetRandaoMixes(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[randaoMixes].MinusRef() + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + + b.state.RandaoMixes = val + b.markFieldAsDirty(randaoMixes) + b.rebuildTrie[randaoMixes] = true + return nil +} + +// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes +// at a specific index to a new value. +func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.RandaoMixes)) <= idx { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + mixes := b.state.RandaoMixes + if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { + // Copy elements in underlying array by reference. + mixes = make([][]byte, len(b.state.RandaoMixes)) + copy(mixes, b.state.RandaoMixes) + b.sharedFieldReferences[randaoMixes].MinusRef() + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + } + + mixes[idx] = val + b.state.RandaoMixes = mixes + b.markFieldAsDirty(randaoMixes) + b.addDirtyIndices(randaoMixes, []uint64{idx}) + + return nil +} diff --git a/beacon-chain/state-proto/v1/setters_state.go b/beacon-chain/state-proto/v1/setters_state.go new file mode 100644 index 0000000000..969333eebf --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_state.go @@ -0,0 +1,59 @@ +package v1 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetStateRoots for the beacon state. Updates the state roots +// to a new value by overwriting the previous value. +func (b *BeaconState) SetStateRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[stateRoots].MinusRef() + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + + b.state.StateRoots = val + b.markFieldAsDirty(stateRoots) + b.rebuildTrie[stateRoots] = true + return nil +} + +// UpdateStateRootAtIndex for the beacon state. Updates the state root +// at a specific index to a new value. +func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + + b.lock.RLock() + if uint64(len(b.state.StateRoots)) <= idx { + b.lock.RUnlock() + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.RUnlock() + + b.lock.Lock() + defer b.lock.Unlock() + + // Check if we hold the only reference to the shared state roots slice. + r := b.state.StateRoots + if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { + // Copy elements in underlying array by reference. + r = make([][]byte, len(b.state.StateRoots)) + copy(r, b.state.StateRoots) + ref.MinusRef() + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + } + + r[idx] = stateRoot[:] + b.state.StateRoots = r + + b.markFieldAsDirty(stateRoots) + b.addDirtyIndices(stateRoots, []uint64{idx}) + return nil +} diff --git a/beacon-chain/state-proto/v1/setters_validator.go b/beacon-chain/state-proto/v1/setters_validator.go new file mode 100644 index 0000000000..0e987c2b10 --- /dev/null +++ b/beacon-chain/state-proto/v1/setters_validator.go @@ -0,0 +1,228 @@ +package v1 + +import ( + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetValidators for the beacon state. Updates the entire +// to a new value by overwriting the previous one. +func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Validators = val + b.sharedFieldReferences[validators].MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.markFieldAsDirty(validators) + b.rebuildTrie[validators] = true + b.valMapHandler = stateutil.NewValMapHandler(b.state.Validators) + return nil +} + +// ApplyToEveryValidator applies the provided callback function to each validator in the +// validator registry. +func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + v := b.state.Validators + if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + v = b.validatorsReferences() + ref.MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + b.lock.Unlock() + var changedVals []uint64 + for i, val := range v { + changed, newVal, err := f(i, val) + if err != nil { + return err + } + if changed { + changedVals = append(changedVals, uint64(i)) + v[i] = newVal + } + } + + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Validators = v + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, changedVals) + + return nil +} + +// UpdateValidatorAtIndex for the beacon state. Updates the validator +// at a specific index to a new value. +func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + v := b.state.Validators + if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + v = b.validatorsReferences() + ref.MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + + v[idx] = val + b.state.Validators = v + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, []uint64{uint64(idx)}) + + return nil +} + +// SetBalances for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetBalances(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + + b.state.Balances = val + b.markFieldAsDirty(balances) + b.rebuildTrie[balances] = true + return nil +} + +// UpdateBalancesAtIndex for the beacon state. This method updates the balance +// at a specific index to a new value. +func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Balances)) <= uint64(idx) { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + bals := b.state.Balances + if b.sharedFieldReferences[balances].Refs() > 1 { + bals = b.balances() + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + } + + bals[idx] = val + b.state.Balances = bals + b.markFieldAsDirty(balances) + b.addDirtyIndices(balances, []uint64{uint64(idx)}) + return nil +} + +// SetSlashings for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetSlashings(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[slashings].MinusRef() + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + + b.state.Slashings = val + b.markFieldAsDirty(slashings) + return nil +} + +// UpdateSlashingsAtIndex for the beacon state. Updates the slashings +// at a specific index to a new value. +func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Slashings)) <= idx { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + s := b.state.Slashings + if b.sharedFieldReferences[slashings].Refs() > 1 { + s = b.slashings() + b.sharedFieldReferences[slashings].MinusRef() + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + } + + s[idx] = val + + b.state.Slashings = s + + b.markFieldAsDirty(slashings) + return nil +} + +// AppendValidator for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + vals := b.state.Validators + if b.sharedFieldReferences[validators].Refs() > 1 { + vals = b.validatorsReferences() + b.sharedFieldReferences[validators].MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + + // append validator to slice + b.state.Validators = append(vals, val) + valIdx := types.ValidatorIndex(len(b.state.Validators) - 1) + + b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) + + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, []uint64{uint64(valIdx)}) + return nil +} + +// AppendBalance for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendBalance(bal uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + bals := b.state.Balances + if b.sharedFieldReferences[balances].Refs() > 1 { + bals = b.balances() + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + } + + b.state.Balances = append(bals, bal) + balIdx := len(b.state.Balances) - 1 + b.markFieldAsDirty(balances) + b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) + return nil +} diff --git a/beacon-chain/state-proto/v1/state_test.go b/beacon-chain/state-proto/v1/state_test.go new file mode 100644 index 0000000000..d73a4cd5e1 --- /dev/null +++ b/beacon-chain/state-proto/v1/state_test.go @@ -0,0 +1,193 @@ +package v1 + +import ( + "context" + "strconv" + "sync" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" +) + +func TestValidatorMap_DistinctCopy(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + handler := stateutil.NewValMapHandler(vals) + newHandler := handler.Copy() + wantedPubkey := strconv.Itoa(22) + handler.Set(bytesutil.ToBytes48([]byte(wantedPubkey)), 27) + val1, _ := handler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) + val2, _ := newHandler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) + assert.NotEqual(t, val1, val2, "Values are supposed to be unequal due to copy") +} + +func TestBeaconState_NoDeadlock(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + st, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ + Validators: vals, + }) + assert.NoError(t, err) + + wg := new(sync.WaitGroup) + + wg.Add(1) + go func() { + // Continuously lock and unlock the state + // by acquiring the lock. + for i := 0; i < 1000; i++ { + for _, f := range st.stateFieldLeaves { + f.Lock() + if f.Empty() { + f.InsertFieldLayer(make([][]*[32]byte, 10)) + } + f.Unlock() + f.FieldReference().AddRef() + } + } + wg.Done() + }() + // Constantly read from the offending portion + // of the code to ensure there is no possible + // recursive read locking. + for i := 0; i < 1000; i++ { + go func() { + _ = st.FieldReferencesCount() + }() + } + // Test will not terminate in the event of a deadlock. + wg.Wait() +} + +func TestStateTrie_IsNil(t *testing.T) { + var emptyState *BeaconState + assert.Equal(t, true, emptyState.IsNil()) + + emptyProto := &BeaconState{state: nil} + assert.Equal(t, true, emptyProto.IsNil()) + + nonNilState := &BeaconState{state: ðpb.BeaconState{}} + assert.Equal(t, false, nonNilState.IsNil()) +} + +func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + bals := make([]uint64, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + bals = append(bals, params.BeaconConfig().MaxEffectiveBalance) + } + zeroHash := params.BeaconConfig().ZeroHash + mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockblockRoots); i++ { + mockblockRoots[i] = zeroHash[:] + } + + mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockstateRoots); i++ { + mockstateRoots[i] = zeroHash[:] + } + mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(mockrandaoMixes); i++ { + mockrandaoMixes[i] = zeroHash[:] + } + st, err := InitializeFromProto(ðpb.BeaconState{ + Slot: 1, + GenesisValidatorsRoot: make([]byte, 32), + Fork: ðpb.Fork{ + PreviousVersion: make([]byte, 4), + CurrentVersion: make([]byte, 4), + Epoch: 0, + }, + LatestBlockHeader: ðpb.BeaconBlockHeader{ + ParentRoot: make([]byte, fieldparams.RootLength), + StateRoot: make([]byte, fieldparams.RootLength), + BodyRoot: make([]byte, fieldparams.RootLength), + }, + Validators: vals, + Balances: bals, + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + }, + BlockRoots: mockblockRoots, + StateRoots: mockstateRoots, + RandaoMixes: mockrandaoMixes, + JustificationBits: bitfield.NewBitvector4(), + PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), + }) + assert.NoError(t, err) + _, err = st.HashTreeRoot(context.Background()) + assert.NoError(t, err) + + for i := 0; i < 100; i++ { + if i%2 == 0 { + assert.NoError(t, st.UpdateBalancesAtIndex(types.ValidatorIndex(i), 1000)) + } + if i%3 == 0 { + assert.NoError(t, st.AppendBalance(1000)) + } + } + _, err = st.HashTreeRoot(context.Background()) + assert.NoError(t, err) + newRt := bytesutil.ToBytes32(st.merkleLayers[0][balances]) + wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.state.Balances) + assert.NoError(t, err) + assert.Equal(t, wantedRt, newRt, "state roots are unequal") +} diff --git a/beacon-chain/state-proto/v1/state_trie.go b/beacon-chain/state-proto/v1/state_trie.go new file mode 100644 index 0000000000..b53fc99435 --- /dev/null +++ b/beacon-chain/state-proto/v1/state_trie.go @@ -0,0 +1,418 @@ +package v1 + +import ( + "context" + "runtime" + "sort" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/sharedstate" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/features" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/container/slice" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "go.opencensus.io/trace" + "google.golang.org/protobuf/proto" +) + +// InitializeFromProto the beacon state from a protobuf representation. +func InitializeFromProto(st *ethpb.BeaconState) (*BeaconState, error) { + return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState)) +} + +// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer +// and sets it as the inner state of the BeaconState type. +func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (*BeaconState, error) { + if st == nil { + return nil, errors.New("received nil state") + } + + fieldCount := params.BeaconConfig().BeaconStateFieldCount + b := &BeaconState{ + state: st, + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 10), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), + } + + var err error + for i := 0; i < fieldCount; i++ { + b.dirtyFields[types.FieldIndex(i)] = true + b.rebuildTrie[types.FieldIndex(i)] = true + b.dirtyIndices[types.FieldIndex(i)] = []uint64{} + b.stateFieldLeaves[types.FieldIndex(i)], err = fieldtrie.NewFieldTrie(types.FieldIndex(i), types.BasicArray, nil, 0) + if err != nil { + return nil, err + } + } + + // Initialize field reference tracking for shared data. + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) + b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + + sharedstate.StateCount.Inc() + return b, nil +} + +// Copy returns a deep copy of the beacon state. +func (b *BeaconState) Copy() state.BeaconState { + if !b.hasInnerState() { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + fieldCount := params.BeaconConfig().BeaconStateFieldCount + dst := &BeaconState{ + state: ðpb.BeaconState{ + // Primitive types, safe to copy. + GenesisTime: b.state.GenesisTime, + Slot: b.state.Slot, + Eth1DepositIndex: b.state.Eth1DepositIndex, + + // Large arrays, infrequently changed, constant size. + RandaoMixes: b.state.RandaoMixes, + StateRoots: b.state.StateRoots, + BlockRoots: b.state.BlockRoots, + PreviousEpochAttestations: b.state.PreviousEpochAttestations, + CurrentEpochAttestations: b.state.CurrentEpochAttestations, + Slashings: b.state.Slashings, + Eth1DataVotes: b.state.Eth1DataVotes, + + // Large arrays, increases over time. + Validators: b.state.Validators, + Balances: b.state.Balances, + HistoricalRoots: b.state.HistoricalRoots, + + // Everything else, too small to be concerned about, constant size. + Fork: b.fork(), + LatestBlockHeader: b.latestBlockHeader(), + Eth1Data: b.eth1Data(), + JustificationBits: b.justificationBits(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), + FinalizedCheckpoint: b.finalizedCheckpoint(), + GenesisValidatorsRoot: b.genesisValidatorRoot(), + }, + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 10), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + + // Share the reference to validator index map. + valMapHandler: b.valMapHandler, + } + + for field, ref := range b.sharedFieldReferences { + ref.AddRef() + dst.sharedFieldReferences[field] = ref + } + + // Increment ref for validator map + b.valMapHandler.AddRef() + + for i := range b.dirtyFields { + dst.dirtyFields[i] = true + } + + for i := range b.dirtyIndices { + indices := make([]uint64, len(b.dirtyIndices[i])) + copy(indices, b.dirtyIndices[i]) + dst.dirtyIndices[i] = indices + } + + for i := range b.rebuildTrie { + dst.rebuildTrie[i] = true + } + + for fldIdx, fieldTrie := range b.stateFieldLeaves { + dst.stateFieldLeaves[fldIdx] = fieldTrie + if fieldTrie.FieldReference() != nil { + fieldTrie.Lock() + fieldTrie.FieldReference().AddRef() + fieldTrie.Unlock() + } + } + + if b.merkleLayers != nil { + dst.merkleLayers = make([][][]byte, len(b.merkleLayers)) + for i, layer := range b.merkleLayers { + dst.merkleLayers[i] = make([][]byte, len(layer)) + for j, content := range layer { + dst.merkleLayers[i][j] = make([]byte, len(content)) + copy(dst.merkleLayers[i][j], content) + } + } + } + + sharedstate.StateCount.Inc() + // Finalizer runs when dst is being destroyed in garbage collection. + runtime.SetFinalizer(dst, func(b *BeaconState) { + for field, v := range b.sharedFieldReferences { + v.MinusRef() + if b.stateFieldLeaves[field].FieldReference() != nil { + b.stateFieldLeaves[field].FieldReference().MinusRef() + } + + } + for i := 0; i < fieldCount; i++ { + field := types.FieldIndex(i) + delete(b.stateFieldLeaves, field) + delete(b.dirtyIndices, field) + delete(b.dirtyFields, field) + delete(b.sharedFieldReferences, field) + delete(b.stateFieldLeaves, field) + } + sharedstate.StateCount.Sub(1) + }) + return dst +} + +// HashTreeRoot of the beacon state retrieves the Merkle root of the trie +// representation of the beacon state based on the Ethereum Simple Serialize specification. +func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { + ctx, span := trace.StartSpan(ctx, "beaconState.HashTreeRoot") + defer span.End() + + b.lock.Lock() + defer b.lock.Unlock() + + if b.merkleLayers == nil || len(b.merkleLayers) == 0 { + fieldRoots, err := computeFieldRoots(ctx, b.state) + if err != nil { + return [32]byte{}, err + } + layers := stateutil.Merkleize(fieldRoots) + b.merkleLayers = layers + b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateFieldCount) + } + + for field := range b.dirtyFields { + root, err := b.rootSelector(ctx, field) + if err != nil { + return [32]byte{}, err + } + b.merkleLayers[0][field] = root[:] + b.recomputeRoot(int(field)) + delete(b.dirtyFields, field) + } + return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil +} + +// FieldReferencesCount returns the reference count held by each field. This +// also includes the field trie held by each field. +func (b *BeaconState) FieldReferencesCount() map[string]uint64 { + refMap := make(map[string]uint64) + b.lock.RLock() + defer b.lock.RUnlock() + for i, f := range b.sharedFieldReferences { + refMap[i.String(b.Version())] = uint64(f.Refs()) + } + for i, f := range b.stateFieldLeaves { + numOfRefs := uint64(f.FieldReference().Refs()) + f.RLock() + if !f.Empty() { + refMap[i.String(b.Version())+"_trie"] = numOfRefs + } + f.RUnlock() + } + return refMap +} + +// IsNil checks if the state and the underlying proto +// object are nil. +func (b *BeaconState) IsNil() bool { + return b == nil || b.state == nil +} + +func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) { + _, span := trace.StartSpan(ctx, "beaconState.rootSelector") + defer span.End() + span.AddAttributes(trace.StringAttribute("field", field.String(b.Version()))) + + hasher := hash.CustomSHA256Hasher() + switch field { + case genesisTime: + return ssz.Uint64Root(b.state.GenesisTime), nil + case genesisValidatorRoot: + return bytesutil.ToBytes32(b.state.GenesisValidatorsRoot), nil + case slot: + return ssz.Uint64Root(uint64(b.state.Slot)), nil + case eth1DepositIndex: + return ssz.Uint64Root(b.state.Eth1DepositIndex), nil + case fork: + return ssz.ForkRoot(b.state.Fork) + case latestBlockHeader: + return stateutil.BlockHeaderRoot(b.state.LatestBlockHeader) + case blockRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.BlockRoots, fieldparams.BlockRootsLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(blockRoots, b.state.BlockRoots) + case stateRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.StateRoots, fieldparams.StateRootsLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(stateRoots, b.state.StateRoots) + case historicalRoots: + return ssz.ByteArrayRootWithLimit(b.state.HistoricalRoots, fieldparams.HistoricalRootsLength) + case eth1Data: + return stateutil.Eth1Root(hasher, b.state.Eth1Data) + case eth1DataVotes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.state.Eth1DataVotes, + fieldparams.Eth1DataVotesLength, + ) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.state.Eth1DataVotes) + case validators: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.Validators, fieldparams.ValidatorRegistryLimit) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, validators) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(validators, b.state.Validators) + case balances: + if features.Get().EnableBalanceTrieComputation { + if b.rebuildTrie[field] { + maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) + elemSize := uint64(8) + balLimit := (maxBalCap*elemSize + 31) / 32 + err := b.resetFieldTrie(field, b.state.Balances, balLimit) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(balances, b.state.Balances) + } + return stateutil.Uint64ListRootWithRegistryLimit(b.state.Balances) + case randaoMixes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.RandaoMixes, fieldparams.RandaoMixesLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(randaoMixes, b.state.RandaoMixes) + case slashings: + return ssz.SlashingsRoot(b.state.Slashings) + case previousEpochAttestations: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.state.PreviousEpochAttestations, + fieldparams.PreviousEpochAttestationsLength, + ) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.state.PreviousEpochAttestations) + case currentEpochAttestations: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.state.CurrentEpochAttestations, + fieldparams.CurrentEpochAttestationsLength, + ) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.state.CurrentEpochAttestations) + case justificationBits: + return bytesutil.ToBytes32(b.state.JustificationBits), nil + case previousJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.PreviousJustifiedCheckpoint) + case currentJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.CurrentJustifiedCheckpoint) + case finalizedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.FinalizedCheckpoint) + } + return [32]byte{}, errors.New("invalid field index provided") +} + +func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interface{}) ([32]byte, error) { + fTrie := b.stateFieldLeaves[index] + // We can't lock the trie directly because the trie's variable gets reassigned, + // and therefore we would call Unlock() on a different object. + fTrieMutex := fTrie.RWMutex + if fTrie.FieldReference().Refs() > 1 { + fTrieMutex.Lock() + fTrie.FieldReference().MinusRef() + newTrie := fTrie.CopyTrie() + b.stateFieldLeaves[index] = newTrie + fTrie = newTrie + fTrieMutex.Unlock() + } + // remove duplicate indexes + b.dirtyIndices[index] = slice.SetUint64(b.dirtyIndices[index]) + // sort indexes again + sort.Slice(b.dirtyIndices[index], func(i int, j int) bool { + return b.dirtyIndices[index][i] < b.dirtyIndices[index][j] + }) + root, err := fTrie.RecomputeTrie(b.dirtyIndices[index], elements) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[index] = []uint64{} + return root, nil +} + +func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{}, length uint64) error { + fTrie, err := fieldtrie.NewFieldTrie(index, fieldMap[index], elements, length) + if err != nil { + return err + } + b.stateFieldLeaves[index] = fTrie + b.dirtyIndices[index] = []uint64{} + return nil +} diff --git a/beacon-chain/state-proto/v1/state_trie_test.go b/beacon-chain/state-proto/v1/state_trie_test.go new file mode 100644 index 0000000000..7c936c7013 --- /dev/null +++ b/beacon-chain/state-proto/v1/state_trie_test.go @@ -0,0 +1,260 @@ +package v1_test + +import ( + "bytes" + "context" + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + "github.com/prysmaticlabs/prysm/config/features" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestMain(m *testing.M) { + resetCfg := features.InitWithReset(&features.Flags{EnableBalanceTrieComputation: true}) + defer resetCfg() + m.Run() +} + +func TestInitializeFromProto(t *testing.T) { + testState, _ := util.DeterministicGenesisState(t, 64) + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) + require.NoError(t, err) + type test struct { + name string + state *ethpb.BeaconState + error string + } + initTests := []test{ + { + name: "nil state", + state: nil, + error: "received nil state", + }, + { + name: "nil validators", + state: ðpb.BeaconState{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconState{}, + }, + { + name: "full state", + state: pbState, + }, + } + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + _, err := v1.InitializeFromProto(tt.state) + if tt.error != "" { + assert.ErrorContains(t, tt.error, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestInitializeFromProtoUnsafe(t *testing.T) { + testState, _ := util.DeterministicGenesisState(t, 64) + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) + require.NoError(t, err) + type test struct { + name string + state *ethpb.BeaconState + error string + } + initTests := []test{ + { + name: "nil state", + state: nil, + error: "received nil state", + }, + { + name: "nil validators", + state: ðpb.BeaconState{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconState{}, + }, + { + name: "full state", + state: pbState, + }, + } + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + _, err := v1.InitializeFromProtoUnsafe(tt.state) + if tt.error != "" { + assert.ErrorContains(t, tt.error, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestBeaconState_HashTreeRoot(t *testing.T) { + testState, _ := util.DeterministicGenesisState(t, 64) + + type test struct { + name string + stateModify func(beaconState state.BeaconState) (state.BeaconState, error) + error string + } + initTests := []test{ + { + name: "unchanged state", + stateModify: func(beaconState state.BeaconState) (state.BeaconState, error) { + return beaconState, nil + }, + error: "", + }, + { + name: "different slot", + stateModify: func(beaconState state.BeaconState) (state.BeaconState, error) { + if err := beaconState.SetSlot(5); err != nil { + return nil, err + } + return beaconState, nil + }, + error: "", + }, + { + name: "different validator balance", + stateModify: func(beaconState state.BeaconState) (state.BeaconState, error) { + val, err := beaconState.ValidatorAtIndex(5) + if err != nil { + return nil, err + } + val.EffectiveBalance = params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement + if err := beaconState.UpdateValidatorAtIndex(5, val); err != nil { + return nil, err + } + return beaconState, nil + }, + error: "", + }, + } + + var err error + var oldHTR []byte + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + testState, err = tt.stateModify(testState) + assert.NoError(t, err) + root, err := testState.HashTreeRoot(context.Background()) + if err == nil && tt.error != "" { + t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) + } + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) + require.NoError(t, err) + genericHTR, err := pbState.HashTreeRoot() + if err == nil && tt.error != "" { + t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) + } + assert.DeepNotEqual(t, []byte{}, root[:], "Received empty hash tree root") + assert.DeepEqual(t, genericHTR[:], root[:], "Expected hash tree root to match generic") + if len(oldHTR) != 0 && bytes.Equal(root[:], oldHTR) { + t.Errorf("Expected HTR to change, received %#x == old %#x", root, oldHTR) + } + oldHTR = root[:] + }) + } +} + +func TestBeaconState_HashTreeRoot_FieldTrie(t *testing.T) { + testState, _ := util.DeterministicGenesisState(t, 64) + + type test struct { + name string + stateModify func(state.BeaconState) (state.BeaconState, error) + error string + } + initTests := []test{ + { + name: "unchanged state", + stateModify: func(beaconState state.BeaconState) (state.BeaconState, error) { + return beaconState, nil + }, + error: "", + }, + { + name: "different slot", + stateModify: func(beaconState state.BeaconState) (state.BeaconState, error) { + if err := beaconState.SetSlot(5); err != nil { + return nil, err + } + return beaconState, nil + }, + error: "", + }, + { + name: "different validator balance", + stateModify: func(beaconState state.BeaconState) (state.BeaconState, error) { + val, err := beaconState.ValidatorAtIndex(5) + if err != nil { + return nil, err + } + val.EffectiveBalance = params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement + if err := beaconState.UpdateValidatorAtIndex(5, val); err != nil { + return nil, err + } + return beaconState, nil + }, + error: "", + }, + } + + var err error + var oldHTR []byte + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + testState, err = tt.stateModify(testState) + assert.NoError(t, err) + root, err := testState.HashTreeRoot(context.Background()) + if err == nil && tt.error != "" { + t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) + } + pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) + require.NoError(t, err) + genericHTR, err := pbState.HashTreeRoot() + if err == nil && tt.error != "" { + t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) + } + assert.DeepNotEqual(t, []byte{}, root[:], "Received empty hash tree root") + assert.DeepEqual(t, genericHTR[:], root[:], "Expected hash tree root to match generic") + if len(oldHTR) != 0 && bytes.Equal(root[:], oldHTR) { + t.Errorf("Expected HTR to change, received %#x == old %#x", root, oldHTR) + } + oldHTR = root[:] + }) + } +} + +func TestBeaconState_AppendValidator_DoesntMutateCopy(t *testing.T) { + st0, err := util.NewBeaconState() + require.NoError(t, err) + st1 := st0.Copy() + originalCount := st1.NumValidators() + + val := ðpb.Validator{Slashed: true} + assert.NoError(t, st0.AppendValidator(val)) + assert.Equal(t, originalCount, st1.NumValidators(), "st1 NumValidators mutated") + _, ok := st1.ValidatorIndexByPubkey(bytesutil.ToBytes48(val.PublicKey)) + assert.Equal(t, false, ok, "Expected no validator index to be present in st1 for the newly inserted pubkey") +} diff --git a/beacon-chain/state-proto/v1/types.go b/beacon-chain/state-proto/v1/types.go new file mode 100644 index 0000000000..08fc54b6e4 --- /dev/null +++ b/beacon-chain/state-proto/v1/types.go @@ -0,0 +1,78 @@ +package v1 + +import ( + "sync" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// Ensure type BeaconState below implements BeaconState interface. +var _ state.BeaconState = (*BeaconState)(nil) + +func init() { + fieldMap = make(map[types.FieldIndex]types.DataType, params.BeaconConfig().BeaconStateFieldCount) + // Initialize the fixed sized arrays. + fieldMap[types.BlockRoots] = types.BasicArray + fieldMap[types.StateRoots] = types.BasicArray + fieldMap[types.RandaoMixes] = types.BasicArray + + // Initialize the composite arrays. + fieldMap[types.Eth1DataVotes] = types.CompositeArray + fieldMap[types.Validators] = types.CompositeArray + fieldMap[types.PreviousEpochAttestations] = types.CompositeArray + fieldMap[types.CurrentEpochAttestations] = types.CompositeArray + fieldMap[types.Balances] = types.CompressedArray +} + +// fieldMap keeps track of each field +// to its corresponding data type. +var fieldMap map[types.FieldIndex]types.DataType + +// ErrNilInnerState returns when the inner state is nil and no copy set or get +// operations can be performed on state. +var ErrNilInnerState = errors.New("nil inner state") + +// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining +// getters and setters for its respective values and helpful functions such as HashTreeRoot(). +type BeaconState struct { + state *ethpb.BeaconState + lock sync.RWMutex + dirtyFields map[types.FieldIndex]bool + dirtyIndices map[types.FieldIndex][]uint64 + stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie + rebuildTrie map[types.FieldIndex]bool + valMapHandler *stateutil.ValidatorMapHandler + merkleLayers [][][]byte + sharedFieldReferences map[types.FieldIndex]*stateutil.Reference +} + +// Field Aliases for values from the types package. +const ( + genesisTime = types.GenesisTime + genesisValidatorRoot = types.GenesisValidatorRoot + slot = types.Slot + fork = types.Fork + latestBlockHeader = types.LatestBlockHeader + blockRoots = types.BlockRoots + stateRoots = types.StateRoots + historicalRoots = types.HistoricalRoots + eth1Data = types.Eth1Data + eth1DataVotes = types.Eth1DataVotes + eth1DepositIndex = types.Eth1DepositIndex + validators = types.Validators + balances = types.Balances + randaoMixes = types.RandaoMixes + slashings = types.Slashings + previousEpochAttestations = types.PreviousEpochAttestations + currentEpochAttestations = types.CurrentEpochAttestations + justificationBits = types.JustificationBits + previousJustifiedCheckpoint = types.PreviousJustifiedCheckpoint + currentJustifiedCheckpoint = types.CurrentJustifiedCheckpoint + finalizedCheckpoint = types.FinalizedCheckpoint +) diff --git a/beacon-chain/state-proto/v1/types_test.go b/beacon-chain/state-proto/v1/types_test.go new file mode 100644 index 0000000000..316c52a6b8 --- /dev/null +++ b/beacon-chain/state-proto/v1/types_test.go @@ -0,0 +1,231 @@ +package v1_test + +import ( + "context" + "reflect" + "strconv" + "testing" + + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/interop" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + log "github.com/sirupsen/logrus" + "google.golang.org/protobuf/proto" +) + +func TestBeaconState_ProtoBeaconStateCompatibility(t *testing.T) { + params.SetupTestConfigCleanup(t) + params.OverrideBeaconConfig(params.MinimalSpecConfig()) + ctx := context.Background() + genesis := setupGenesisState(t, 64) + customState, err := v1.InitializeFromProto(genesis) + require.NoError(t, err) + cloned, ok := proto.Clone(genesis).(*ethpb.BeaconState) + assert.Equal(t, true, ok, "Object is not of type *ethpb.BeaconState") + custom := customState.CloneInnerState() + assert.DeepSSZEqual(t, cloned, custom) + + r1, err := customState.HashTreeRoot(ctx) + require.NoError(t, err) + beaconState, err := v1.InitializeFromProto(genesis) + require.NoError(t, err) + r2, err := beaconState.HashTreeRoot(context.Background()) + require.NoError(t, err) + assert.Equal(t, r1, r2, "Mismatched roots") + + // We then write to the the state and compare hash tree roots again. + balances := genesis.Balances + balances[0] = 3823 + require.NoError(t, customState.SetBalances(balances)) + r1, err = customState.HashTreeRoot(ctx) + require.NoError(t, err) + genesis.Balances = balances + beaconState, err = v1.InitializeFromProto(genesis) + require.NoError(t, err) + r2, err = beaconState.HashTreeRoot(context.Background()) + require.NoError(t, err) + assert.Equal(t, r1, r2, "Mismatched roots") +} + +func setupGenesisState(tb testing.TB, count uint64) *ethpb.BeaconState { + genesisState, _, err := interop.GenerateGenesisState(context.Background(), 0, count) + require.NoError(tb, err, "Could not generate genesis beacon state") + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + genesisState.Validators = append(genesisState.Validators, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + genesisState.Balances = append(genesisState.Balances, params.BeaconConfig().MaxEffectiveBalance) + } + return genesisState +} + +func BenchmarkCloneValidators_Proto(b *testing.B) { + b.StopTimer() + validators := make([]*ethpb.Validator, 16384) + somePubKey := [48]byte{1, 2, 3} + someRoot := [32]byte{3, 4, 5} + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + PublicKey: somePubKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch, + ActivationEpoch: 3, + ExitEpoch: 4, + WithdrawableEpoch: 5, + } + } + b.StartTimer() + for i := 0; i < b.N; i++ { + cloneValidatorsWithProto(validators) + } +} + +func BenchmarkCloneValidators_Manual(b *testing.B) { + b.StopTimer() + validators := make([]*ethpb.Validator, 16384) + somePubKey := [48]byte{1, 2, 3} + someRoot := [32]byte{3, 4, 5} + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + PublicKey: somePubKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch, + ActivationEpoch: 3, + ExitEpoch: 4, + WithdrawableEpoch: 5, + } + } + b.StartTimer() + for i := 0; i < b.N; i++ { + cloneValidatorsManually(validators) + } +} + +func BenchmarkStateClone_Proto(b *testing.B) { + b.StopTimer() + params.SetupTestConfigCleanup(b) + params.OverrideBeaconConfig(params.MinimalSpecConfig()) + genesis := setupGenesisState(b, 64) + b.StartTimer() + for i := 0; i < b.N; i++ { + _, ok := proto.Clone(genesis).(*ethpb.BeaconState) + assert.Equal(b, true, ok, "Entity is not of type *ethpb.BeaconState") + } +} + +func BenchmarkStateClone_Manual(b *testing.B) { + b.StopTimer() + params.SetupTestConfigCleanup(b) + params.OverrideBeaconConfig(params.MinimalSpecConfig()) + genesis := setupGenesisState(b, 64) + st, err := v1.InitializeFromProto(genesis) + require.NoError(b, err) + b.StartTimer() + for i := 0; i < b.N; i++ { + _ = st.CloneInnerState() + } +} + +func cloneValidatorsWithProto(vals []*ethpb.Validator) []*ethpb.Validator { + var ok bool + res := make([]*ethpb.Validator, len(vals)) + for i := 0; i < len(res); i++ { + res[i], ok = proto.Clone(vals[i]).(*ethpb.Validator) + if !ok { + log.Debug("Entity is not of type *ethpb.Validator") + } + } + return res +} + +func cloneValidatorsManually(vals []*ethpb.Validator) []*ethpb.Validator { + res := make([]*ethpb.Validator, len(vals)) + for i := 0; i < len(res); i++ { + val := vals[i] + res[i] = ðpb.Validator{ + PublicKey: val.PublicKey, + WithdrawalCredentials: val.WithdrawalCredentials, + EffectiveBalance: val.EffectiveBalance, + Slashed: val.Slashed, + ActivationEligibilityEpoch: val.ActivationEligibilityEpoch, + ActivationEpoch: val.ActivationEpoch, + ExitEpoch: val.ExitEpoch, + WithdrawableEpoch: val.WithdrawableEpoch, + } + } + return res +} + +func TestBeaconState_ImmutabilityWithSharedResources(t *testing.T) { + params.SetupTestConfigCleanup(t) + params.OverrideBeaconConfig(params.MinimalSpecConfig()) + genesis := setupGenesisState(t, 64) + a, err := v1.InitializeFromProto(genesis) + require.NoError(t, err) + b := a.Copy() + + // Randao mixes + require.DeepEqual(t, a.RandaoMixes(), b.RandaoMixes(), "Test precondition failed, fields are not equal") + require.NoError(t, a.UpdateRandaoMixesAtIndex(1, []byte("foo"))) + if reflect.DeepEqual(a.RandaoMixes(), b.RandaoMixes()) { + t.Error("Expect a.RandaoMixes() to be different from b.RandaoMixes()") + } + + // Validators + require.DeepEqual(t, a.Validators(), b.Validators(), "Test precondition failed, fields are not equal") + require.NoError(t, a.UpdateValidatorAtIndex(1, ðpb.Validator{Slashed: true})) + if reflect.DeepEqual(a.Validators(), b.Validators()) { + t.Error("Expect a.Validators() to be different from b.Validators()") + } + + // State Roots + require.DeepEqual(t, a.StateRoots(), b.StateRoots(), "Test precondition failed, fields are not equal") + require.NoError(t, a.UpdateStateRootAtIndex(1, bytesutil.ToBytes32([]byte("foo")))) + if reflect.DeepEqual(a.StateRoots(), b.StateRoots()) { + t.Fatal("Expected a.StateRoots() to be different from b.StateRoots()") + } + + // Block Roots + require.DeepEqual(t, a.BlockRoots(), b.BlockRoots(), "Test precondition failed, fields are not equal") + require.NoError(t, a.UpdateBlockRootAtIndex(1, bytesutil.ToBytes32([]byte("foo")))) + if reflect.DeepEqual(a.BlockRoots(), b.BlockRoots()) { + t.Fatal("Expected a.BlockRoots() to be different from b.BlockRoots()") + } +} + +func TestForkManualCopy_OK(t *testing.T) { + params.SetupTestConfigCleanup(t) + params.OverrideBeaconConfig(params.MinimalSpecConfig()) + genesis := setupGenesisState(t, 64) + a, err := v1.InitializeFromProto(genesis) + require.NoError(t, err) + wantedFork := ðpb.Fork{ + PreviousVersion: []byte{'a', 'b', 'c'}, + CurrentVersion: []byte{'d', 'e', 'f'}, + Epoch: 0, + } + require.NoError(t, a.SetFork(wantedFork)) + + pbState, err := v1.ProtobufBeaconState(a.InnerStateUnsafe()) + require.NoError(t, err) + require.DeepEqual(t, pbState.Fork, wantedFork) +} diff --git a/beacon-chain/state-proto/v1/unsupported_getters.go b/beacon-chain/state-proto/v1/unsupported_getters.go new file mode 100644 index 0000000000..3717aab456 --- /dev/null +++ b/beacon-chain/state-proto/v1/unsupported_getters.go @@ -0,0 +1,36 @@ +package v1 + +import ( + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// CurrentEpochParticipation is not supported for phase 0 beacon state. +func (*BeaconState) CurrentEpochParticipation() ([]byte, error) { + return nil, errors.New("CurrentEpochParticipation is not supported for phase 0 beacon state") +} + +// PreviousEpochParticipation is not supported for phase 0 beacon state. +func (*BeaconState) PreviousEpochParticipation() ([]byte, error) { + return nil, errors.New("PreviousEpochParticipation is not supported for phase 0 beacon state") +} + +// InactivityScores is not supported for phase 0 beacon state. +func (*BeaconState) InactivityScores() ([]uint64, error) { + return nil, errors.New("InactivityScores is not supported for phase 0 beacon state") +} + +// CurrentSyncCommittee is not supported for phase 0 beacon state. +func (*BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { + return nil, errors.New("CurrentSyncCommittee is not supported for phase 0 beacon state") +} + +// NextSyncCommittee is not supported for phase 0 beacon state. +func (*BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { + return nil, errors.New("NextSyncCommittee is not supported for phase 0 beacon state") +} + +// LatestExecutionPayloadHeader is not supported for phase 0 beacon state. +func (*BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { + return nil, errors.New("LatestExecutionPayloadHeader is not supported for phase 0 beacon state") +} diff --git a/beacon-chain/state-proto/v1/unsupported_setters.go b/beacon-chain/state-proto/v1/unsupported_setters.go new file mode 100644 index 0000000000..251253519a --- /dev/null +++ b/beacon-chain/state-proto/v1/unsupported_setters.go @@ -0,0 +1,51 @@ +package v1 + +import ( + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// AppendCurrentParticipationBits is not supported for phase 0 beacon state. +func (*BeaconState) AppendCurrentParticipationBits(_ byte) error { + return errors.New("AppendCurrentParticipationBits is not supported for phase 0 beacon state") +} + +// AppendPreviousParticipationBits is not supported for phase 0 beacon state. +func (*BeaconState) AppendPreviousParticipationBits(_ byte) error { + return errors.New("AppendPreviousParticipationBits is not supported for phase 0 beacon state") +} + +// AppendInactivityScore is not supported for phase 0 beacon state. +func (*BeaconState) AppendInactivityScore(_ uint64) error { + return errors.New("AppendInactivityScore is not supported for phase 0 beacon state") +} + +// SetCurrentSyncCommittee is not supported for phase 0 beacon state. +func (*BeaconState) SetCurrentSyncCommittee(_ *ethpb.SyncCommittee) error { + return errors.New("SetCurrentSyncCommittee is not supported for phase 0 beacon state") +} + +// SetNextSyncCommittee is not supported for phase 0 beacon state. +func (*BeaconState) SetNextSyncCommittee(_ *ethpb.SyncCommittee) error { + return errors.New("SetNextSyncCommittee is not supported for phase 0 beacon state") +} + +// SetPreviousParticipationBits is not supported for phase 0 beacon state. +func (*BeaconState) SetPreviousParticipationBits(_ []byte) error { + return errors.New("SetPreviousParticipationBits is not supported for phase 0 beacon state") +} + +// SetCurrentParticipationBits is not supported for phase 0 beacon state. +func (*BeaconState) SetCurrentParticipationBits(_ []byte) error { + return errors.New("SetCurrentParticipationBits is not supported for phase 0 beacon state") +} + +// SetInactivityScores is not supported for phase 0 beacon state. +func (*BeaconState) SetInactivityScores(_ []uint64) error { + return errors.New("SetInactivityScores is not supported for phase 0 beacon state") +} + +// SetLatestExecutionPayloadHeader is not supported for phase 0 beacon state. +func (*BeaconState) SetLatestExecutionPayloadHeader(val *ethpb.ExecutionPayloadHeader) error { + return errors.New("SetLatestExecutionPayloadHeader is not supported for phase 0 beacon state") +} diff --git a/beacon-chain/state-proto/v2/BUILD.bazel b/beacon-chain/state-proto/v2/BUILD.bazel new file mode 100644 index 0000000000..80437bbcb2 --- /dev/null +++ b/beacon-chain/state-proto/v2/BUILD.bazel @@ -0,0 +1,92 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "deprecated_getters.go", + "deprecated_setters.go", + "field_roots.go", + "getters_block.go", + "getters_checkpoint.go", + "getters_eth1.go", + "getters_misc.go", + "getters_participation.go", + "getters_randao.go", + "getters_state.go", + "getters_sync_committee.go", + "getters_validator.go", + "proofs.go", + "setters_block.go", + "setters_checkpoint.go", + "setters_eth1.go", + "setters_misc.go", + "setters_participation.go", + "setters_randao.go", + "setters_state.go", + "setters_sync_committee.go", + "setters_validator.go", + "state_trie.go", + "types.go", + ], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2", + visibility = [ + "//beacon-chain:__subpackages__", + "//proto/migration:__subpackages__", + "//testing/spectest:__subpackages__", + "//testing/util:__pkg__", + ], + deps = [ + "//beacon-chain/sharedstate:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/fieldtrie:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//config/features:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//container/slice:go_default_library", + "//crypto/hash:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@io_opencensus_go//trace:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "deprecated_getters_test.go", + "deprecated_setters_test.go", + "getters_block_test.go", + "getters_test.go", + "getters_validator_test.go", + "proofs_test.go", + "setters_test.go", + "state_trie_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//config/features:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//container/trie:go_default_library", + "//crypto/bls:go_default_library", + "//encoding/bytesutil:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + ], +) diff --git a/beacon-chain/state-proto/v2/deprecated_getters.go b/beacon-chain/state-proto/v2/deprecated_getters.go new file mode 100644 index 0000000000..2257b577e8 --- /dev/null +++ b/beacon-chain/state-proto/v2/deprecated_getters.go @@ -0,0 +1,21 @@ +package v2 + +import ( + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// PreviousEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { + return nil, errors.New("PreviousEpochAttestations is not supported for hard fork 1 beacon state") +} + +// CurrentEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { + return nil, errors.New("CurrentEpochAttestations is not supported for hard fork 1 beacon state") +} + +// LatestExecutionPayloadHeader is not supported for hard fork 1 beacon state. +func (*BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { + return nil, errors.New("LatestExecutionPayloadHeader is not supported for hard fork 1 beacon state") +} diff --git a/beacon-chain/state-proto/v2/deprecated_getters_test.go b/beacon-chain/state-proto/v2/deprecated_getters_test.go new file mode 100644 index 0000000000..6e4aafe62d --- /dev/null +++ b/beacon-chain/state-proto/v2/deprecated_getters_test.go @@ -0,0 +1,19 @@ +package v2 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_CurrentEpochAttestations(t *testing.T) { + s := &BeaconState{} + _, err := s.CurrentEpochAttestations() + require.ErrorContains(t, "CurrentEpochAttestations is not supported for hard fork 1 beacon state", err) +} + +func TestBeaconState_PreviousEpochAttestations(t *testing.T) { + s := &BeaconState{} + _, err := s.PreviousEpochAttestations() + require.ErrorContains(t, "PreviousEpochAttestations is not supported for hard fork 1 beacon state", err) +} diff --git a/beacon-chain/state-proto/v2/deprecated_setters.go b/beacon-chain/state-proto/v2/deprecated_setters.go new file mode 100644 index 0000000000..449bb82098 --- /dev/null +++ b/beacon-chain/state-proto/v2/deprecated_setters.go @@ -0,0 +1,36 @@ +package v2 + +import ( + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetPreviousEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) SetPreviousEpochAttestations(_ []*ethpb.PendingAttestation) error { + return errors.New("SetPreviousEpochAttestations is not supported for hard fork 1 beacon state") +} + +// SetCurrentEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) SetCurrentEpochAttestations(_ []*ethpb.PendingAttestation) error { + return errors.New("SetCurrentEpochAttestations is not supported for hard fork 1 beacon state") +} + +// AppendCurrentEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) AppendCurrentEpochAttestations(_ *ethpb.PendingAttestation) error { + return errors.New("AppendCurrentEpochAttestations is not supported for hard fork 1 beacon state") +} + +// AppendPreviousEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) AppendPreviousEpochAttestations(_ *ethpb.PendingAttestation) error { + return errors.New("AppendPreviousEpochAttestations is not supported for hard fork 1 beacon state") +} + +// RotateAttestations is not supported for HF1 beacon state. +func (*BeaconState) RotateAttestations() error { + return errors.New("RotateAttestations is not supported for hard fork 1 beacon state") +} + +// SetLatestExecutionPayloadHeader is not supported for hard fork 1 beacon state. +func (*BeaconState) SetLatestExecutionPayloadHeader(_ *ethpb.ExecutionPayloadHeader) error { + return errors.New("SetLatestExecutionPayloadHeader is not supported for hard fork 1 beacon state") +} diff --git a/beacon-chain/state-proto/v2/deprecated_setters_test.go b/beacon-chain/state-proto/v2/deprecated_setters_test.go new file mode 100644 index 0000000000..718c4f07b1 --- /dev/null +++ b/beacon-chain/state-proto/v2/deprecated_setters_test.go @@ -0,0 +1,27 @@ +package v2 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_AppendCurrentEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported for hard fork 1 beacon state", s.AppendCurrentEpochAttestations(nil)) +} + +func TestBeaconState_AppendPreviousEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported for hard fork 1 beacon state", s.AppendPreviousEpochAttestations(nil)) +} + +func TestBeaconState_SetCurrentEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "SetCurrentEpochAttestations is not supported for hard fork 1 beacon state", s.SetCurrentEpochAttestations(nil)) +} + +func TestBeaconState_SetPreviousEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "SetPreviousEpochAttestations is not supported for hard fork 1 beacon state", s.SetPreviousEpochAttestations(nil)) +} diff --git a/beacon-chain/state-proto/v2/field_roots.go b/beacon-chain/state-proto/v2/field_roots.go new file mode 100644 index 0000000000..d0fe86f2f8 --- /dev/null +++ b/beacon-chain/state-proto/v2/field_roots.go @@ -0,0 +1,18 @@ +package v2 + +import ( + "context" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/config/features" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// computeFieldRoots returns the hash tree root computations of every field in +// the beacon state as a list of 32 byte roots. +func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateAltair) ([][]byte, error) { + if features.Get().EnableSSZCache { + return stateutil.CachedHasher.ComputeFieldRootsWithHasherAltair(ctx, state) + } + return stateutil.NocachedHasher.ComputeFieldRootsWithHasherAltair(ctx, state) +} diff --git a/beacon-chain/state-proto/v2/getters_block.go b/beacon-chain/state-proto/v2/getters_block.go new file mode 100644 index 0000000000..ad321824b5 --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_block.go @@ -0,0 +1,99 @@ +package v2 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// LatestBlockHeader stored within the beacon state. +func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader { + if !b.hasInnerState() { + return nil + } + if b.state.LatestBlockHeader == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.latestBlockHeader() +} + +// latestBlockHeader stored within the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader { + if !b.hasInnerState() { + return nil + } + if b.state.LatestBlockHeader == nil { + return nil + } + + hdr := ðpb.BeaconBlockHeader{ + Slot: b.state.LatestBlockHeader.Slot, + ProposerIndex: b.state.LatestBlockHeader.ProposerIndex, + } + + parentRoot := make([]byte, len(b.state.LatestBlockHeader.ParentRoot)) + bodyRoot := make([]byte, len(b.state.LatestBlockHeader.BodyRoot)) + stateRoot := make([]byte, len(b.state.LatestBlockHeader.StateRoot)) + + copy(parentRoot, b.state.LatestBlockHeader.ParentRoot) + copy(bodyRoot, b.state.LatestBlockHeader.BodyRoot) + copy(stateRoot, b.state.LatestBlockHeader.StateRoot) + hdr.ParentRoot = parentRoot + hdr.BodyRoot = bodyRoot + hdr.StateRoot = stateRoot + return hdr +} + +// BlockRoots kept track of in the beacon state. +func (b *BeaconState) BlockRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.BlockRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.blockRoots() +} + +// blockRoots kept track of in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) blockRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.BlockRoots) +} + +// BlockRootAtIndex retrieves a specific block root based on an +// input index value. +func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.BlockRoots == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.blockRootAtIndex(idx) +} + +// blockRootAtIndex retrieves a specific block root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) blockRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + return bytesutil.SafeCopyRootAtIndex(b.state.BlockRoots, idx) +} diff --git a/beacon-chain/state-proto/v2/getters_block_test.go b/beacon-chain/state-proto/v2/getters_block_test.go new file mode 100644 index 0000000000..923bd9b5ec --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_block_test.go @@ -0,0 +1,60 @@ +package v2 + +import ( + "testing" + + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_LatestBlockHeader(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateAltair{}) + require.NoError(t, err) + got := s.LatestBlockHeader() + require.DeepEqual(t, (*ethpb.BeaconBlockHeader)(nil), got) + + want := ðpb.BeaconBlockHeader{Slot: 100} + s, err = InitializeFromProto(ðpb.BeaconStateAltair{LatestBlockHeader: want}) + require.NoError(t, err) + got = s.LatestBlockHeader() + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got.Slot = 101 + require.DeepNotEqual(t, want, got) +} + +func TestBeaconState_BlockRoots(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateAltair{}) + require.NoError(t, err) + got := s.BlockRoots() + require.DeepEqual(t, ([][]byte)(nil), got) + + want := [][]byte{{'a'}} + s, err = InitializeFromProto(ðpb.BeaconStateAltair{BlockRoots: want}) + require.NoError(t, err) + got = s.BlockRoots() + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got[0][0] = 'b' + require.DeepNotEqual(t, want, got) +} + +func TestBeaconState_BlockRootAtIndex(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateAltair{}) + require.NoError(t, err) + got, err := s.BlockRootAtIndex(0) + require.NoError(t, err) + require.DeepEqual(t, ([]byte)(nil), got) + + r := [][]byte{{'a'}} + s, err = InitializeFromProto(ðpb.BeaconStateAltair{BlockRoots: r}) + require.NoError(t, err) + got, err = s.BlockRootAtIndex(0) + require.NoError(t, err) + want := bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) + require.DeepSSZEqual(t, want, got) +} diff --git a/beacon-chain/state-proto/v2/getters_checkpoint.go b/beacon-chain/state-proto/v2/getters_checkpoint.go new file mode 100644 index 0000000000..ebea57ec98 --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_checkpoint.go @@ -0,0 +1,160 @@ +package v2 + +import ( + "bytes" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// JustificationBits marking which epochs have been justified in the beacon chain. +func (b *BeaconState) JustificationBits() bitfield.Bitvector4 { + if !b.hasInnerState() { + return nil + } + if b.state.JustificationBits == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.justificationBits() +} + +// justificationBits marking which epochs have been justified in the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) justificationBits() bitfield.Bitvector4 { + if !b.hasInnerState() { + return nil + } + if b.state.JustificationBits == nil { + return nil + } + + res := make([]byte, len(b.state.JustificationBits.Bytes())) + copy(res, b.state.JustificationBits.Bytes()) + return res +} + +// PreviousJustifiedCheckpoint denoting an epoch and block root. +func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.PreviousJustifiedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.previousJustifiedCheckpoint() +} + +// previousJustifiedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) previousJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.PreviousJustifiedCheckpoint) +} + +// CurrentJustifiedCheckpoint denoting an epoch and block root. +func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.CurrentJustifiedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.currentJustifiedCheckpoint() +} + +// currentJustifiedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.CurrentJustifiedCheckpoint) +} + +// MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches +// the current justified checkpoint in state. +func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool { + if !b.hasInnerState() { + return false + } + if b.state.CurrentJustifiedCheckpoint == nil { + return false + } + + if c.Epoch != b.state.CurrentJustifiedCheckpoint.Epoch { + return false + } + return bytes.Equal(c.Root, b.state.CurrentJustifiedCheckpoint.Root) +} + +// MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches +// the previous justified checkpoint in state. +func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool { + if !b.hasInnerState() { + return false + } + if b.state.PreviousJustifiedCheckpoint == nil { + return false + } + + if c.Epoch != b.state.PreviousJustifiedCheckpoint.Epoch { + return false + } + return bytes.Equal(c.Root, b.state.PreviousJustifiedCheckpoint.Root) +} + +// FinalizedCheckpoint denoting an epoch and block root. +func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.FinalizedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.finalizedCheckpoint() +} + +// finalizedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) finalizedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.FinalizedCheckpoint) +} + +// FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint. +func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch { + if !b.hasInnerState() { + return 0 + } + if b.state.FinalizedCheckpoint == nil { + return 0 + } + b.lock.RLock() + defer b.lock.RUnlock() + + return b.state.FinalizedCheckpoint.Epoch +} diff --git a/beacon-chain/state-proto/v2/getters_eth1.go b/beacon-chain/state-proto/v2/getters_eth1.go new file mode 100644 index 0000000000..2b35eed94d --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_eth1.go @@ -0,0 +1,91 @@ +package v2 + +import ( + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// Eth1Data corresponding to the proof-of-work chain information stored in the beacon state. +func (b *BeaconState) Eth1Data() *ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1Data == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1Data() +} + +// eth1Data corresponding to the proof-of-work chain information stored in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1Data() *ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1Data == nil { + return nil + } + + return ethpb.CopyETH1Data(b.state.Eth1Data) +} + +// Eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain +// data retrieved from eth1. +func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1DataVotes == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1DataVotes() +} + +// eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain +// data retrieved from eth1. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1DataVotes() []*ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1DataVotes == nil { + return nil + } + + res := make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) + for i := 0; i < len(res); i++ { + res[i] = ethpb.CopyETH1Data(b.state.Eth1DataVotes[i]) + } + return res +} + +// Eth1DepositIndex corresponds to the index of the deposit made to the +// validator deposit contract at the time of this state's eth1 data. +func (b *BeaconState) Eth1DepositIndex() uint64 { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1DepositIndex() +} + +// eth1DepositIndex corresponds to the index of the deposit made to the +// validator deposit contract at the time of this state's eth1 data. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1DepositIndex() uint64 { + if !b.hasInnerState() { + return 0 + } + + return b.state.Eth1DepositIndex +} diff --git a/beacon-chain/state-proto/v2/getters_misc.go b/beacon-chain/state-proto/v2/getters_misc.go new file mode 100644 index 0000000000..20be2f386b --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_misc.go @@ -0,0 +1,212 @@ +package v2 + +import ( + "time" + + types "github.com/prysmaticlabs/eth2-types" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// GenesisTime of the beacon state as a uint64. +func (b *BeaconState) GenesisTime() uint64 { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisTime() +} + +// genesisTime of the beacon state as a uint64. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisTime() uint64 { + if !b.hasInnerState() { + return 0 + } + + return b.state.GenesisTime +} + +// GenesisValidatorRoot of the beacon state. +func (b *BeaconState) GenesisValidatorRoot() []byte { + if !b.hasInnerState() { + return nil + } + if b.state.GenesisValidatorsRoot == nil { + return params.BeaconConfig().ZeroHash[:] + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisValidatorRoot() +} + +// genesisValidatorRoot of the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisValidatorRoot() []byte { + if !b.hasInnerState() { + return nil + } + if b.state.GenesisValidatorsRoot == nil { + return params.BeaconConfig().ZeroHash[:] + } + + root := make([]byte, fieldparams.RootLength) + copy(root, b.state.GenesisValidatorsRoot) + return root +} + +// GenesisUnixTime returns the genesis time as time.Time. +func (b *BeaconState) GenesisUnixTime() time.Time { + if !b.hasInnerState() { + return time.Unix(0, 0) + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisUnixTime() +} + +// genesisUnixTime returns the genesis time as time.Time. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisUnixTime() time.Time { + if !b.hasInnerState() { + return time.Unix(0, 0) + } + + return time.Unix(int64(b.state.GenesisTime), 0) +} + +// ParentRoot is a convenience method to access state.LatestBlockRoot.ParentRoot. +func (b *BeaconState) ParentRoot() [32]byte { + if !b.hasInnerState() { + return [32]byte{} + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.parentRoot() +} + +// parentRoot is a convenience method to access state.LatestBlockRoot.ParentRoot. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) parentRoot() [32]byte { + if !b.hasInnerState() { + return [32]byte{} + } + + parentRoot := [32]byte{} + copy(parentRoot[:], b.state.LatestBlockHeader.ParentRoot) + return parentRoot +} + +// Version of the beacon state. This method +// is strictly meant to be used without a lock +// internally. +func (_ *BeaconState) Version() int { + return version.Altair +} + +// Slot of the current beacon chain state. +func (b *BeaconState) Slot() types.Slot { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.slot() +} + +// slot of the current beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) slot() types.Slot { + if !b.hasInnerState() { + return 0 + } + + return b.state.Slot +} + +// Fork version of the beacon chain. +func (b *BeaconState) Fork() *ethpb.Fork { + if !b.hasInnerState() { + return nil + } + if b.state.Fork == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.fork() +} + +// fork version of the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) fork() *ethpb.Fork { + if !b.hasInnerState() { + return nil + } + if b.state.Fork == nil { + return nil + } + + prevVersion := make([]byte, len(b.state.Fork.PreviousVersion)) + copy(prevVersion, b.state.Fork.PreviousVersion) + currVersion := make([]byte, len(b.state.Fork.CurrentVersion)) + copy(currVersion, b.state.Fork.CurrentVersion) + return ðpb.Fork{ + PreviousVersion: prevVersion, + CurrentVersion: currVersion, + Epoch: b.state.Fork.Epoch, + } +} + +// HistoricalRoots based on epochs stored in the beacon state. +func (b *BeaconState) HistoricalRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.HistoricalRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.historicalRoots() +} + +// historicalRoots based on epochs stored in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) historicalRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.HistoricalRoots) +} + +// balancesLength returns the length of the balances slice. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) balancesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.Balances == nil { + return 0 + } + + return len(b.state.Balances) +} diff --git a/beacon-chain/state-proto/v2/getters_participation.go b/beacon-chain/state-proto/v2/getters_participation.go new file mode 100644 index 0000000000..9d62b0f203 --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_participation.go @@ -0,0 +1,53 @@ +package v2 + +// CurrentEpochParticipation corresponding to participation bits on the beacon chain. +func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.CurrentEpochParticipation == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.currentEpochParticipation(), nil +} + +// PreviousEpochParticipation corresponding to participation bits on the beacon chain. +func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.PreviousEpochParticipation == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.previousEpochParticipation(), nil +} + +// currentEpochParticipation corresponding to participation bits on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentEpochParticipation() []byte { + if !b.hasInnerState() { + return nil + } + tmp := make([]byte, len(b.state.CurrentEpochParticipation)) + copy(tmp, b.state.CurrentEpochParticipation) + return tmp +} + +// previousEpochParticipation corresponding to participation bits on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) previousEpochParticipation() []byte { + if !b.hasInnerState() { + return nil + } + tmp := make([]byte, len(b.state.PreviousEpochParticipation)) + copy(tmp, b.state.PreviousEpochParticipation) + return tmp +} diff --git a/beacon-chain/state-proto/v2/getters_randao.go b/beacon-chain/state-proto/v2/getters_randao.go new file mode 100644 index 0000000000..8f74d0168d --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_randao.go @@ -0,0 +1,85 @@ +package v2 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" +) + +// RandaoMixes of block proposers on the beacon chain. +func (b *BeaconState) RandaoMixes() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.RandaoMixes == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixes() +} + +// randaoMixes of block proposers on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixes() [][]byte { + if !b.hasInnerState() { + return nil + } + + return bytesutil.SafeCopy2dBytes(b.state.RandaoMixes) +} + +// RandaoMixAtIndex retrieves a specific block root based on an +// input index value. +func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.RandaoMixes == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixAtIndex(idx) +} + +// randaoMixAtIndex retrieves a specific block root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + + return bytesutil.SafeCopyRootAtIndex(b.state.RandaoMixes, idx) +} + +// RandaoMixesLength returns the length of the randao mixes slice. +func (b *BeaconState) RandaoMixesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.RandaoMixes == nil { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixesLength() +} + +// randaoMixesLength returns the length of the randao mixes slice. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.RandaoMixes == nil { + return 0 + } + + return len(b.state.RandaoMixes) +} diff --git a/beacon-chain/state-proto/v2/getters_state.go b/beacon-chain/state-proto/v2/getters_state.go new file mode 100644 index 0000000000..f097a7962f --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_state.go @@ -0,0 +1,126 @@ +package v2 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// InnerStateUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) InnerStateUnsafe() interface{} { + if b == nil { + return nil + } + return b.state +} + +// CloneInnerState the beacon state into a protobuf for usage. +func (b *BeaconState) CloneInnerState() interface{} { + if b == nil || b.state == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + return ðpb.BeaconStateAltair{ + GenesisTime: b.genesisTime(), + GenesisValidatorsRoot: b.genesisValidatorRoot(), + Slot: b.slot(), + Fork: b.fork(), + LatestBlockHeader: b.latestBlockHeader(), + BlockRoots: b.blockRoots(), + StateRoots: b.stateRoots(), + HistoricalRoots: b.historicalRoots(), + Eth1Data: b.eth1Data(), + Eth1DataVotes: b.eth1DataVotes(), + Eth1DepositIndex: b.eth1DepositIndex(), + Validators: b.validators(), + Balances: b.balances(), + RandaoMixes: b.randaoMixes(), + Slashings: b.slashings(), + CurrentEpochParticipation: b.currentEpochParticipation(), + PreviousEpochParticipation: b.previousEpochParticipation(), + JustificationBits: b.justificationBits(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), + FinalizedCheckpoint: b.finalizedCheckpoint(), + InactivityScores: b.inactivityScores(), + CurrentSyncCommittee: b.currentSyncCommittee(), + NextSyncCommittee: b.nextSyncCommittee(), + } +} + +// hasInnerState detects if the internal reference to the state data structure +// is populated correctly. Returns false if nil. +func (b *BeaconState) hasInnerState() bool { + return b != nil && b.state != nil +} + +// StateRoots kept track of in the beacon state. +func (b *BeaconState) StateRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.StateRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.stateRoots() +} + +// StateRoots kept track of in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) stateRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.StateRoots) +} + +// StateRootAtIndex retrieves a specific state root based on an +// input index value. +func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.StateRoots == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.stateRootAtIndex(idx) +} + +// stateRootAtIndex retrieves a specific state root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) stateRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + return bytesutil.SafeCopyRootAtIndex(b.state.StateRoots, idx) +} + +// MarshalSSZ marshals the underlying beacon state to bytes. +func (b *BeaconState) MarshalSSZ() ([]byte, error) { + if !b.hasInnerState() { + return nil, errors.New("nil beacon state") + } + return b.state.MarshalSSZ() +} + +// ProtobufBeaconState transforms an input into beacon state hard fork 1 in the form of protobuf. +// Error is returned if the input is not type protobuf beacon state. +func ProtobufBeaconState(s interface{}) (*ethpb.BeaconStateAltair, error) { + pbState, ok := s.(*ethpb.BeaconStateAltair) + if !ok { + return nil, errors.New("input is not type pb.BeaconStateAltair") + } + return pbState, nil +} diff --git a/beacon-chain/state-proto/v2/getters_sync_committee.go b/beacon-chain/state-proto/v2/getters_sync_committee.go new file mode 100644 index 0000000000..7717cf2b2a --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_sync_committee.go @@ -0,0 +1,69 @@ +package v2 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// currentSyncCommittee of the current sync committee in beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentSyncCommittee() *ethpb.SyncCommittee { + if !b.hasInnerState() { + return nil + } + + return CopySyncCommittee(b.state.CurrentSyncCommittee) +} + +// nextSyncCommittee of the next sync committee in beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) nextSyncCommittee() *ethpb.SyncCommittee { + if !b.hasInnerState() { + return nil + } + + return CopySyncCommittee(b.state.NextSyncCommittee) +} + +// CurrentSyncCommittee of the current sync committee in beacon chain state. +func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { + if !b.hasInnerState() { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + if b.state.CurrentSyncCommittee == nil { + return nil, nil + } + + return b.currentSyncCommittee(), nil +} + +// NextSyncCommittee of the next sync committee in beacon chain state. +func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { + if !b.hasInnerState() { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + if b.state.NextSyncCommittee == nil { + return nil, nil + } + + return b.nextSyncCommittee(), nil +} + +// CopySyncCommittee copies the provided sync committee object. +func CopySyncCommittee(data *ethpb.SyncCommittee) *ethpb.SyncCommittee { + if data == nil { + return nil + } + return ðpb.SyncCommittee{ + Pubkeys: bytesutil.SafeCopy2dBytes(data.Pubkeys), + AggregatePubkey: bytesutil.SafeCopyBytes(data.AggregatePubkey), + } +} diff --git a/beacon-chain/state-proto/v2/getters_test.go b/beacon-chain/state-proto/v2/getters_test.go new file mode 100644 index 0000000000..e2849a0110 --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_test.go @@ -0,0 +1,192 @@ +package v2 + +import ( + "runtime/debug" + "sync" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_SlotDataRace(t *testing.T) { + headState, err := InitializeFromProto(ðpb.BeaconStateAltair{Slot: 1}) + require.NoError(t, err) + + wg := sync.WaitGroup{} + wg.Add(2) + go func() { + require.NoError(t, headState.SetSlot(0)) + wg.Done() + }() + go func() { + headState.Slot() + wg.Done() + }() + + wg.Wait() +} + +func TestNilState_NoPanic(t *testing.T) { + var st *BeaconState + defer func() { + if r := recover(); r != nil { + t.Errorf("Method panicked when it was not supposed to: %v\n%v\n", r, string(debug.Stack())) + } + }() + // retrieve elements from nil state + _ = st.GenesisTime() + _ = st.GenesisValidatorRoot() + _ = st.GenesisUnixTime() + _ = st.GenesisValidatorRoot() + _ = st.Slot() + _ = st.Fork() + _ = st.LatestBlockHeader() + _ = st.ParentRoot() + _ = st.BlockRoots() + _, err := st.BlockRootAtIndex(0) + _ = err + _ = st.StateRoots() + _ = st.HistoricalRoots() + _ = st.Eth1Data() + _ = st.Eth1DataVotes() + _ = st.Eth1DepositIndex() + _, err = st.ValidatorAtIndex(0) + _ = err + _, err = st.ValidatorAtIndexReadOnly(0) + _ = err + _, _ = st.ValidatorIndexByPubkey([48]byte{}) + _ = st.PubkeyAtIndex(0) + _ = st.NumValidators() + _ = st.Balances() + _, err = st.BalanceAtIndex(0) + _ = err + _ = st.BalancesLength() + _ = st.RandaoMixes() + _, err = st.RandaoMixAtIndex(0) + _ = err + _ = st.RandaoMixesLength() + _ = st.Slashings() + _, err = st.CurrentEpochParticipation() + _ = err + _, err = st.PreviousEpochParticipation() + _ = err + _ = st.JustificationBits() + _ = st.PreviousJustifiedCheckpoint() + _ = st.CurrentJustifiedCheckpoint() + _ = st.FinalizedCheckpoint() + _, err = st.CurrentEpochParticipation() + _ = err + _, err = st.PreviousEpochParticipation() + _ = err + _, err = st.InactivityScores() + _ = err + _, err = st.CurrentSyncCommittee() + _ = err + _, err = st.NextSyncCommittee() + _ = err +} + +func TestBeaconState_ValidatorByPubkey(t *testing.T) { + keyCreator := func(input []byte) [48]byte { + nKey := [48]byte{} + copy(nKey[:1], input) + return nKey + } + + tests := []struct { + name string + modifyFunc func(b *BeaconState, k [48]byte) + exists bool + expectedIdx types.ValidatorIndex + largestIdxInSet types.ValidatorIndex + }{ + { + name: "retrieve validator", + modifyFunc: func(b *BeaconState, key [48]byte) { + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators from the start", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + }, + exists: true, + expectedIdx: 2, + }, + { + name: "retrieve validator with multiple validators from the start with shared state", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + _ = b.Copy() + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators with shared state", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + n := b.Copy() + // Append to another state + assert.NoError(t, n.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + + }, + exists: false, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators with shared state at boundary", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + n := b.Copy() + // Append to another state + assert.NoError(t, n.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + + }, + exists: false, + expectedIdx: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateAltair{}) + require.NoError(t, err) + nKey := keyCreator([]byte{'A'}) + tt.modifyFunc(s, nKey) + idx, ok := s.ValidatorIndexByPubkey(nKey) + assert.Equal(t, tt.exists, ok) + assert.Equal(t, tt.expectedIdx, idx) + }) + } +} diff --git a/beacon-chain/state-proto/v2/getters_validator.go b/beacon-chain/state-proto/v2/getters_validator.go new file mode 100644 index 0000000000..c87ad6b4e5 --- /dev/null +++ b/beacon-chain/state-proto/v2/getters_validator.go @@ -0,0 +1,328 @@ +package v2 + +import ( + "fmt" + + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist +// at a given index in the validator's array. +type ValidatorIndexOutOfRangeError struct { + message string +} + +var ( + // ErrNilValidatorsInState returns when accessing validators in the state while the state has a + // nil slice for the validators field. + ErrNilValidatorsInState = errors.New("state has nil validator slice") +) + +// NewValidatorIndexOutOfRangeError creates a new error instance. +func NewValidatorIndexOutOfRangeError(index types.ValidatorIndex) ValidatorIndexOutOfRangeError { + return ValidatorIndexOutOfRangeError{ + message: fmt.Sprintf("index %d out of range", index), + } +} + +// Error returns the underlying error message. +func (e *ValidatorIndexOutOfRangeError) Error() string { + return e.message +} + +// Validators participating in consensus on the beacon chain. +func (b *BeaconState) Validators() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.validators() +} + +// validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) validators() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + res := make([]*ethpb.Validator, len(b.state.Validators)) + for i := 0; i < len(res); i++ { + val := b.state.Validators[i] + if val == nil { + continue + } + res[i] = ethpb.CopyValidator(val) + } + return res +} + +// references of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. This does not +// copy fully and instead just copies the reference. +func (b *BeaconState) validatorsReferences() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + res := make([]*ethpb.Validator, len(b.state.Validators)) + for i := 0; i < len(res); i++ { + validator := b.state.Validators[i] + if validator == nil { + continue + } + // copy validator reference instead. + res[i] = validator + } + return res +} + +// ValidatorAtIndex is the validator at the provided index. +func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.Validators == nil { + return ðpb.Validator{}, nil + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + e := NewValidatorIndexOutOfRangeError(idx) + return nil, &e + } + + b.lock.RLock() + defer b.lock.RUnlock() + + val := b.state.Validators[idx] + return ethpb.CopyValidator(val), nil +} + +// ValidatorAtIndexReadOnly is the validator at the provided index. This method +// doesn't clone the validator. +func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.Validators == nil { + return nil, ErrNilValidatorsInState + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + e := NewValidatorIndexOutOfRangeError(idx) + return nil, &e + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return v1.NewValidator(b.state.Validators[idx]) +} + +// ValidatorIndexByPubkey returns a given validator by its 48-byte public key. +func (b *BeaconState) ValidatorIndexByPubkey(key [48]byte) (types.ValidatorIndex, bool) { + if b == nil || b.valMapHandler == nil || b.valMapHandler.IsNil() { + return 0, false + } + b.lock.RLock() + defer b.lock.RUnlock() + numOfVals := len(b.state.Validators) + + idx, ok := b.valMapHandler.Get(key) + if ok && numOfVals <= int(idx) { + return types.ValidatorIndex(0), false + } + return idx, ok +} + +// PubkeyAtIndex returns the pubkey at the given +// validator index. +func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [48]byte { + if !b.hasInnerState() { + return [48]byte{} + } + if uint64(idx) >= uint64(len(b.state.Validators)) { + return [48]byte{} + } + b.lock.RLock() + defer b.lock.RUnlock() + + if b.state.Validators[idx] == nil { + return [48]byte{} + } + return bytesutil.ToBytes48(b.state.Validators[idx].PublicKey) +} + +// NumValidators returns the size of the validator registry. +func (b *BeaconState) NumValidators() int { + if !b.hasInnerState() { + return 0 + } + b.lock.RLock() + defer b.lock.RUnlock() + + return len(b.state.Validators) +} + +// ReadFromEveryValidator reads values from every validator and applies it to the provided function. +// Warning: This method is potentially unsafe, as it exposes the actual validator registry. +func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if b.state.Validators == nil { + return errors.New("nil validators in state") + } + b.lock.RLock() + validators := b.state.Validators + b.lock.RUnlock() + + for i, v := range validators { + v, err := v1.NewValidator(v) + if err != nil { + return err + } + if err := f(i, v); err != nil { + return err + } + } + return nil +} + +// Balances of validators participating in consensus on the beacon chain. +func (b *BeaconState) Balances() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Balances == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.balances() +} + +// balances of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) balances() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Balances == nil { + return nil + } + + res := make([]uint64, len(b.state.Balances)) + copy(res, b.state.Balances) + return res +} + +// BalanceAtIndex of validator with the provided index. +func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) { + if !b.hasInnerState() { + return 0, ErrNilInnerState + } + if b.state.Balances == nil { + return 0, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + if uint64(len(b.state.Balances)) <= uint64(idx) { + return 0, fmt.Errorf("index of %d does not exist", idx) + } + return b.state.Balances[idx], nil +} + +// BalancesLength returns the length of the balances slice. +func (b *BeaconState) BalancesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.Balances == nil { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.balancesLength() +} + +// Slashings of validators on the beacon chain. +func (b *BeaconState) Slashings() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Slashings == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.slashings() +} + +// slashings of validators on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) slashings() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Slashings == nil { + return nil + } + + res := make([]uint64, len(b.state.Slashings)) + copy(res, b.state.Slashings) + return res +} + +// inactivityScores of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) inactivityScores() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.InactivityScores == nil { + return nil + } + + res := make([]uint64, len(b.state.InactivityScores)) + copy(res, b.state.InactivityScores) + return res +} + +// InactivityScores of validators participating in consensus on the beacon chain. +func (b *BeaconState) InactivityScores() ([]uint64, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.InactivityScores == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.inactivityScores(), nil +} diff --git a/beacon-chain/state/v2/getters_validator_test.go b/beacon-chain/state-proto/v2/getters_validator_test.go similarity index 88% rename from beacon-chain/state/v2/getters_validator_test.go rename to beacon-chain/state-proto/v2/getters_validator_test.go index 454a1bbf66..c0a179a4bb 100644 --- a/beacon-chain/state/v2/getters_validator_test.go +++ b/beacon-chain/state-proto/v2/getters_validator_test.go @@ -3,7 +3,7 @@ package v2_test import ( "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/state-proto/v2/proofs.go b/beacon-chain/state-proto/v2/proofs.go new file mode 100644 index 0000000000..946989500f --- /dev/null +++ b/beacon-chain/state-proto/v2/proofs.go @@ -0,0 +1,60 @@ +package v2 + +import ( + "encoding/binary" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" +) + +const ( + finalizedRootIndex = uint64(105) // Precomputed value. +) + +// FinalizedRootGeneralizedIndex for the beacon state. +func FinalizedRootGeneralizedIndex() uint64 { + return finalizedRootIndex +} + +// CurrentSyncCommitteeGeneralizedIndex for the beacon state. +func CurrentSyncCommitteeGeneralizedIndex() uint64 { + return uint64(currentSyncCommittee) +} + +// NextSyncCommitteeGeneralizedIndex for the beacon state. +func NextSyncCommitteeGeneralizedIndex() uint64 { + return uint64(nextSyncCommittee) +} + +// CurrentSyncCommitteeProof from the state's Merkle trie representation. +func (b *BeaconState) CurrentSyncCommitteeProof() ([][]byte, error) { + b.lock.RLock() + defer b.lock.RUnlock() + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, currentSyncCommittee), nil +} + +// NextSyncCommitteeProof from the state's Merkle trie representation. +func (b *BeaconState) NextSyncCommitteeProof() ([][]byte, error) { + b.lock.RLock() + defer b.lock.RUnlock() + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nextSyncCommittee), nil +} + +// FinalizedRootProof crafts a Merkle proof for the finalized root +// contained within the finalized checkpoint of a beacon state. +func (b *BeaconState) FinalizedRootProof() ([][]byte, error) { + b.lock.RLock() + defer b.lock.RUnlock() + cpt := b.state.FinalizedCheckpoint + // The epoch field of a finalized checkpoint is the neighbor + // index of the finalized root field in its Merkle tree representation + // of the checkpoint. This neighbor is the first element added to the proof. + epochBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(epochBuf, uint64(cpt.Epoch)) + epochRoot := bytesutil.ToBytes32(epochBuf) + proof := make([][]byte, 0) + proof = append(proof, epochRoot[:]) + branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) + proof = append(proof, branch...) + return proof, nil +} diff --git a/beacon-chain/state/v2/proofs_test.go b/beacon-chain/state-proto/v2/proofs_test.go similarity index 97% rename from beacon-chain/state/v2/proofs_test.go rename to beacon-chain/state-proto/v2/proofs_test.go index 83bf7aaab2..9ab4f46cb0 100644 --- a/beacon-chain/state/v2/proofs_test.go +++ b/beacon-chain/state-proto/v2/proofs_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/state-proto/v2/setters_block.go b/beacon-chain/state-proto/v2/setters_block.go new file mode 100644 index 0000000000..ddee0c3851 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_block.go @@ -0,0 +1,68 @@ +package v2 + +import ( + "fmt" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetLatestBlockHeader in the beacon state. +func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.LatestBlockHeader = ethpb.CopyBeaconBlockHeader(val) + b.markFieldAsDirty(latestBlockHeader) + return nil +} + +// SetBlockRoots for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetBlockRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[blockRoots].MinusRef() + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + + b.state.BlockRoots = val + b.markFieldAsDirty(blockRoots) + b.rebuildTrie[blockRoots] = true + return nil +} + +// UpdateBlockRootAtIndex for the beacon state. Updates the block root +// at a specific index to a new value. +func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.BlockRoots)) <= idx { + return fmt.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + r := b.state.BlockRoots + if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { + // Copy elements in underlying array by reference. + r = make([][]byte, len(b.state.BlockRoots)) + copy(r, b.state.BlockRoots) + ref.MinusRef() + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + } + + r[idx] = blockRoot[:] + b.state.BlockRoots = r + + b.markFieldAsDirty(blockRoots) + b.addDirtyIndices(blockRoots, []uint64{idx}) + return nil +} diff --git a/beacon-chain/state-proto/v2/setters_checkpoint.go b/beacon-chain/state-proto/v2/setters_checkpoint.go new file mode 100644 index 0000000000..666ef8fff8 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_checkpoint.go @@ -0,0 +1,58 @@ +package v2 + +import ( + "github.com/prysmaticlabs/go-bitfield" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetJustificationBits for the beacon state. +func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.JustificationBits = val + b.markFieldAsDirty(justificationBits) + return nil +} + +// SetPreviousJustifiedCheckpoint for the beacon state. +func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.PreviousJustifiedCheckpoint = val + b.markFieldAsDirty(previousJustifiedCheckpoint) + return nil +} + +// SetCurrentJustifiedCheckpoint for the beacon state. +func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.CurrentJustifiedCheckpoint = val + b.markFieldAsDirty(currentJustifiedCheckpoint) + return nil +} + +// SetFinalizedCheckpoint for the beacon state. +func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.FinalizedCheckpoint = val + b.markFieldAsDirty(finalizedCheckpoint) + return nil +} diff --git a/beacon-chain/state-proto/v2/setters_eth1.go b/beacon-chain/state-proto/v2/setters_eth1.go new file mode 100644 index 0000000000..d9eb338b51 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_eth1.go @@ -0,0 +1,74 @@ +package v2 + +import ( + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetEth1Data for the beacon state. +func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Eth1Data = val + b.markFieldAsDirty(eth1Data) + return nil +} + +// SetEth1DataVotes for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[eth1DataVotes].MinusRef() + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + + b.state.Eth1DataVotes = val + b.markFieldAsDirty(eth1DataVotes) + b.rebuildTrie[eth1DataVotes] = true + return nil +} + +// SetEth1DepositIndex for the beacon state. +func (b *BeaconState) SetEth1DepositIndex(val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Eth1DepositIndex = val + b.markFieldAsDirty(eth1DepositIndex) + return nil +} + +// AppendEth1DataVotes for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + votes := b.state.Eth1DataVotes + if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { + // Copy elements in underlying array by reference. + votes = make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) + copy(votes, b.state.Eth1DataVotes) + b.sharedFieldReferences[eth1DataVotes].MinusRef() + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + } + + b.state.Eth1DataVotes = append(votes, val) + b.markFieldAsDirty(eth1DataVotes) + b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.state.Eth1DataVotes) - 1)}) + return nil +} diff --git a/beacon-chain/state-proto/v2/setters_misc.go b/beacon-chain/state-proto/v2/setters_misc.go new file mode 100644 index 0000000000..c61f3704ef --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_misc.go @@ -0,0 +1,186 @@ +package v2 + +import ( + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/features" + "github.com/prysmaticlabs/prysm/crypto/hash" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "google.golang.org/protobuf/proto" +) + +// For our setters, we have a field reference counter through +// which we can track shared field references. This helps when +// performing state copies, as we simply copy the reference to the +// field. When we do need to do need to modify these fields, we +// perform a full copy of the field. This is true of most of our +// fields except for the following below. +// 1) BlockRoots +// 2) StateRoots +// 3) Eth1DataVotes +// 4) RandaoMixes +// 5) HistoricalRoots +// 6) CurrentParticipationBits +// 7) PreviousParticipationBits +// +// The fields referred to above are instead copied by reference, where +// we simply copy the reference to the underlying object instead of the +// whole object. This is possible due to how we have structured our state +// as we copy the value on read, so as to ensure the underlying object is +// not mutated while it is being accessed during a state read. + +const ( + // This specifies the limit till which we process all dirty indices for a certain field. + // If we have more dirty indices than the threshold, then we rebuild the whole trie. This + // comes due to the fact that O(alogn) > O(n) beyond a certain value of a. + indicesLimit = 8000 +) + +// SetGenesisTime for the beacon state. +func (b *BeaconState) SetGenesisTime(val uint64) error { + b.lock.Lock() + defer b.lock.Unlock() + + b.state.GenesisTime = val + b.markFieldAsDirty(genesisTime) + return nil +} + +// SetGenesisValidatorRoot for the beacon state. +func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error { + b.lock.Lock() + defer b.lock.Unlock() + + b.state.GenesisValidatorsRoot = val + b.markFieldAsDirty(genesisValidatorRoot) + return nil +} + +// SetSlot for the beacon state. +func (b *BeaconState) SetSlot(val types.Slot) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Slot = val + b.markFieldAsDirty(slot) + return nil +} + +// SetFork version for the beacon chain. +func (b *BeaconState) SetFork(val *ethpb.Fork) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + fk, ok := proto.Clone(val).(*ethpb.Fork) + if !ok { + return errors.New("proto.Clone did not return a fork proto") + } + b.state.Fork = fk + b.markFieldAsDirty(fork) + return nil +} + +// SetHistoricalRoots for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[historicalRoots].MinusRef() + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + + b.state.HistoricalRoots = val + b.markFieldAsDirty(historicalRoots) + return nil +} + +// AppendHistoricalRoots for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + roots := b.state.HistoricalRoots + if b.sharedFieldReferences[historicalRoots].Refs() > 1 { + roots = make([][]byte, len(b.state.HistoricalRoots)) + copy(roots, b.state.HistoricalRoots) + b.sharedFieldReferences[historicalRoots].MinusRef() + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + } + + b.state.HistoricalRoots = append(roots, root[:]) + b.markFieldAsDirty(historicalRoots) + return nil +} + +// Recomputes the branch up the index in the Merkle trie representation +// of the beacon state. This method performs slice reads and the caller MUST +// hold the lock before calling this method. +func (b *BeaconState) recomputeRoot(idx int) { + hashFunc := hash.CustomSHA256Hasher() + layers := b.merkleLayers + // The merkle tree structure looks as follows: + // [[r1, r2, r3, r4], [parent1, parent2], [root]] + // Using information about the index which changed, idx, we recompute + // only its branch up the tree. + currentIndex := idx + root := b.merkleLayers[0][idx] + for i := 0; i < len(layers)-1; i++ { + isLeft := currentIndex%2 == 0 + neighborIdx := currentIndex ^ 1 + + neighbor := make([]byte, 32) + if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) { + neighbor = layers[i][neighborIdx] + } + if isLeft { + parentHash := hashFunc(append(root, neighbor...)) + root = parentHash[:] + } else { + parentHash := hashFunc(append(neighbor, root...)) + root = parentHash[:] + } + parentIdx := currentIndex / 2 + // Update the cached layers at the parent index. + layers[i+1][parentIdx] = root + currentIndex = parentIdx + } + b.merkleLayers = layers +} + +func (b *BeaconState) markFieldAsDirty(field stateTypes.FieldIndex) { + b.dirtyFields[field] = true +} + +// addDirtyIndices adds the relevant dirty field indices, so that they +// can be recomputed. +func (b *BeaconState) addDirtyIndices(index stateTypes.FieldIndex, indices []uint64) { + if b.rebuildTrie[index] { + return + } + // Exit early if balance trie computation isn't enabled. + if !features.Get().EnableBalanceTrieComputation && index == balances { + return + } + totalIndicesLen := len(b.dirtyIndices[index]) + len(indices) + if totalIndicesLen > indicesLimit { + b.rebuildTrie[index] = true + b.dirtyIndices[index] = []uint64{} + } else { + b.dirtyIndices[index] = append(b.dirtyIndices[index], indices...) + } +} diff --git a/beacon-chain/state-proto/v2/setters_participation.go b/beacon-chain/state-proto/v2/setters_participation.go new file mode 100644 index 0000000000..2840b8de07 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_participation.go @@ -0,0 +1,89 @@ +package v2 + +import ( + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetPreviousParticipationBits for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetPreviousParticipationBits(val []byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() + b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) + + b.state.PreviousEpochParticipation = val + b.markFieldAsDirty(previousEpochParticipationBits) + b.rebuildTrie[previousEpochParticipationBits] = true + return nil +} + +// SetCurrentParticipationBits for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetCurrentParticipationBits(val []byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() + b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) + + b.state.CurrentEpochParticipation = val + b.markFieldAsDirty(currentEpochParticipationBits) + b.rebuildTrie[currentEpochParticipationBits] = true + return nil +} + +// AppendCurrentParticipationBits for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendCurrentParticipationBits(val byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + participation := b.state.CurrentEpochParticipation + if b.sharedFieldReferences[currentEpochParticipationBits].Refs() > 1 { + // Copy elements in underlying array by reference. + participation = make([]byte, len(b.state.CurrentEpochParticipation)) + copy(participation, b.state.CurrentEpochParticipation) + b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() + b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) + } + + b.state.CurrentEpochParticipation = append(participation, val) + b.markFieldAsDirty(currentEpochParticipationBits) + b.addDirtyIndices(currentEpochParticipationBits, []uint64{uint64(len(b.state.CurrentEpochParticipation) - 1)}) + return nil +} + +// AppendPreviousParticipationBits for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendPreviousParticipationBits(val byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + bits := b.state.PreviousEpochParticipation + if b.sharedFieldReferences[previousEpochParticipationBits].Refs() > 1 { + bits = make([]byte, len(b.state.PreviousEpochParticipation)) + copy(bits, b.state.PreviousEpochParticipation) + b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() + b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) + } + + b.state.PreviousEpochParticipation = append(bits, val) + b.markFieldAsDirty(previousEpochParticipationBits) + b.addDirtyIndices(previousEpochParticipationBits, []uint64{uint64(len(b.state.PreviousEpochParticipation) - 1)}) + + return nil +} diff --git a/beacon-chain/state-proto/v2/setters_randao.go b/beacon-chain/state-proto/v2/setters_randao.go new file mode 100644 index 0000000000..d44bb0dc91 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_randao.go @@ -0,0 +1,53 @@ +package v2 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetRandaoMixes for the beacon state. Updates the entire +// randao mixes to a new value by overwriting the previous one. +func (b *BeaconState) SetRandaoMixes(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[randaoMixes].MinusRef() + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + + b.state.RandaoMixes = val + b.markFieldAsDirty(randaoMixes) + b.rebuildTrie[randaoMixes] = true + return nil +} + +// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes +// at a specific index to a new value. +func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.RandaoMixes)) <= idx { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + mixes := b.state.RandaoMixes + if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { + // Copy elements in underlying array by reference. + mixes = make([][]byte, len(b.state.RandaoMixes)) + copy(mixes, b.state.RandaoMixes) + b.sharedFieldReferences[randaoMixes].MinusRef() + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + } + + mixes[idx] = val + b.state.RandaoMixes = mixes + b.markFieldAsDirty(randaoMixes) + b.addDirtyIndices(randaoMixes, []uint64{idx}) + + return nil +} diff --git a/beacon-chain/state-proto/v2/setters_state.go b/beacon-chain/state-proto/v2/setters_state.go new file mode 100644 index 0000000000..c9d7baaf91 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_state.go @@ -0,0 +1,59 @@ +package v2 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetStateRoots for the beacon state. Updates the state roots +// to a new value by overwriting the previous value. +func (b *BeaconState) SetStateRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[stateRoots].MinusRef() + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + + b.state.StateRoots = val + b.markFieldAsDirty(stateRoots) + b.rebuildTrie[stateRoots] = true + return nil +} + +// UpdateStateRootAtIndex for the beacon state. Updates the state root +// at a specific index to a new value. +func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + + b.lock.RLock() + if uint64(len(b.state.StateRoots)) <= idx { + b.lock.RUnlock() + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.RUnlock() + + b.lock.Lock() + defer b.lock.Unlock() + + // Check if we hold the only reference to the shared state roots slice. + r := b.state.StateRoots + if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { + // Copy elements in underlying array by reference. + r = make([][]byte, len(b.state.StateRoots)) + copy(r, b.state.StateRoots) + ref.MinusRef() + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + } + + r[idx] = stateRoot[:] + b.state.StateRoots = r + + b.markFieldAsDirty(stateRoots) + b.addDirtyIndices(stateRoots, []uint64{idx}) + return nil +} diff --git a/beacon-chain/state-proto/v2/setters_sync_committee.go b/beacon-chain/state-proto/v2/setters_sync_committee.go new file mode 100644 index 0000000000..c069cf3c12 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_sync_committee.go @@ -0,0 +1,31 @@ +package v2 + +import ( + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetCurrentSyncCommittee for the beacon state. +func (b *BeaconState) SetCurrentSyncCommittee(val *ethpb.SyncCommittee) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.CurrentSyncCommittee = val + b.markFieldAsDirty(currentSyncCommittee) + return nil +} + +// SetNextSyncCommittee for the beacon state. +func (b *BeaconState) SetNextSyncCommittee(val *ethpb.SyncCommittee) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.NextSyncCommittee = val + b.markFieldAsDirty(nextSyncCommittee) + return nil +} diff --git a/beacon-chain/state-proto/v2/setters_test.go b/beacon-chain/state-proto/v2/setters_test.go new file mode 100644 index 0000000000..9f1fd591ba --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_test.go @@ -0,0 +1,161 @@ +package v2 + +import ( + "context" + "strconv" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestAppendBeyondIndicesLimit(t *testing.T) { + zeroHash := params.BeaconConfig().ZeroHash + mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockblockRoots); i++ { + mockblockRoots[i] = zeroHash[:] + } + + mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockstateRoots); i++ { + mockstateRoots[i] = zeroHash[:] + } + mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(mockrandaoMixes); i++ { + mockrandaoMixes[i] = zeroHash[:] + } + st, err := InitializeFromProto(ðpb.BeaconStateAltair{ + Slot: 1, + CurrentEpochParticipation: []byte{}, + PreviousEpochParticipation: []byte{}, + Validators: []*ethpb.Validator{}, + Eth1Data: ðpb.Eth1Data{}, + BlockRoots: mockblockRoots, + StateRoots: mockstateRoots, + RandaoMixes: mockrandaoMixes, + }) + require.NoError(t, err) + _, err = st.HashTreeRoot(context.Background()) + require.NoError(t, err) + for i := stateTypes.FieldIndex(0); i < stateTypes.FieldIndex(params.BeaconConfig().BeaconStateAltairFieldCount); i++ { + st.dirtyFields[i] = true + } + _, err = st.HashTreeRoot(context.Background()) + require.NoError(t, err) + for i := 0; i < 10; i++ { + assert.NoError(t, st.AppendValidator(ðpb.Validator{})) + } + assert.Equal(t, false, st.rebuildTrie[validators]) + assert.NotEqual(t, len(st.dirtyIndices[validators]), 0) + + for i := 0; i < indicesLimit; i++ { + assert.NoError(t, st.AppendValidator(ðpb.Validator{})) + } + assert.Equal(t, true, st.rebuildTrie[validators]) + assert.Equal(t, len(st.dirtyIndices[validators]), 0) +} + +func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + bals := make([]uint64, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + bals = append(bals, params.BeaconConfig().MaxEffectiveBalance) + } + zeroHash := params.BeaconConfig().ZeroHash + mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockblockRoots); i++ { + mockblockRoots[i] = zeroHash[:] + } + + mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockstateRoots); i++ { + mockstateRoots[i] = zeroHash[:] + } + mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(mockrandaoMixes); i++ { + mockrandaoMixes[i] = zeroHash[:] + } + var pubKeys [][]byte + for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSize; i++ { + pubKeys = append(pubKeys, bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength)) + } + st, err := InitializeFromProto(ðpb.BeaconStateAltair{ + Slot: 1, + GenesisValidatorsRoot: make([]byte, 32), + Fork: ðpb.Fork{ + PreviousVersion: make([]byte, 4), + CurrentVersion: make([]byte, 4), + Epoch: 0, + }, + LatestBlockHeader: ðpb.BeaconBlockHeader{ + ParentRoot: make([]byte, fieldparams.RootLength), + StateRoot: make([]byte, fieldparams.RootLength), + BodyRoot: make([]byte, fieldparams.RootLength), + }, + CurrentEpochParticipation: []byte{}, + PreviousEpochParticipation: []byte{}, + Validators: vals, + Balances: bals, + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, 32), + }, + BlockRoots: mockblockRoots, + StateRoots: mockstateRoots, + RandaoMixes: mockrandaoMixes, + JustificationBits: bitfield.NewBitvector4(), + PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), + CurrentSyncCommittee: ðpb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, 48), + }, + NextSyncCommittee: ðpb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, 48), + }, + }) + assert.NoError(t, err) + _, err = st.HashTreeRoot(context.Background()) + assert.NoError(t, err) + + for i := 0; i < 100; i++ { + if i%2 == 0 { + assert.NoError(t, st.UpdateBalancesAtIndex(types.ValidatorIndex(i), 1000)) + } + if i%3 == 0 { + assert.NoError(t, st.AppendBalance(1000)) + } + } + _, err = st.HashTreeRoot(context.Background()) + assert.NoError(t, err) + newRt := bytesutil.ToBytes32(st.merkleLayers[0][balances]) + wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.state.Balances) + assert.NoError(t, err) + assert.Equal(t, wantedRt, newRt, "state roots are unequal") +} diff --git a/beacon-chain/state-proto/v2/setters_validator.go b/beacon-chain/state-proto/v2/setters_validator.go new file mode 100644 index 0000000000..cdc04a7b64 --- /dev/null +++ b/beacon-chain/state-proto/v2/setters_validator.go @@ -0,0 +1,265 @@ +package v2 + +import ( + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetValidators for the beacon state. Updates the entire +// to a new value by overwriting the previous one. +func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Validators = val + b.sharedFieldReferences[validators].MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.markFieldAsDirty(validators) + b.rebuildTrie[validators] = true + b.valMapHandler = stateutil.NewValMapHandler(b.state.Validators) + return nil +} + +// ApplyToEveryValidator applies the provided callback function to each validator in the +// validator registry. +func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + v := b.state.Validators + if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + v = b.validatorsReferences() + ref.MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + b.lock.Unlock() + var changedVals []uint64 + for i, val := range v { + changed, newVal, err := f(i, val) + if err != nil { + return err + } + if changed { + changedVals = append(changedVals, uint64(i)) + v[i] = newVal + } + } + + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Validators = v + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, changedVals) + + return nil +} + +// UpdateValidatorAtIndex for the beacon state. Updates the validator +// at a specific index to a new value. +func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + v := b.state.Validators + if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + v = b.validatorsReferences() + ref.MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + + v[idx] = val + b.state.Validators = v + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, []uint64{uint64(idx)}) + + return nil +} + +// SetBalances for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetBalances(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + + b.state.Balances = val + b.rebuildTrie[balances] = true + b.markFieldAsDirty(balances) + return nil +} + +// UpdateBalancesAtIndex for the beacon state. This method updates the balance +// at a specific index to a new value. +func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Balances)) <= uint64(idx) { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + bals := b.state.Balances + if b.sharedFieldReferences[balances].Refs() > 1 { + bals = b.balances() + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + } + + bals[idx] = val + b.state.Balances = bals + b.markFieldAsDirty(balances) + b.addDirtyIndices(balances, []uint64{uint64(idx)}) + return nil +} + +// SetSlashings for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetSlashings(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[slashings].MinusRef() + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + + b.state.Slashings = val + b.markFieldAsDirty(slashings) + return nil +} + +// UpdateSlashingsAtIndex for the beacon state. Updates the slashings +// at a specific index to a new value. +func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Slashings)) <= idx { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + s := b.state.Slashings + if b.sharedFieldReferences[slashings].Refs() > 1 { + s = b.slashings() + b.sharedFieldReferences[slashings].MinusRef() + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + } + + s[idx] = val + + b.state.Slashings = s + + b.markFieldAsDirty(slashings) + return nil +} + +// AppendValidator for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + vals := b.state.Validators + if b.sharedFieldReferences[validators].Refs() > 1 { + vals = b.validatorsReferences() + b.sharedFieldReferences[validators].MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + + // append validator to slice + b.state.Validators = append(vals, val) + valIdx := types.ValidatorIndex(len(b.state.Validators) - 1) + + b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) + + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, []uint64{uint64(valIdx)}) + return nil +} + +// AppendBalance for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendBalance(bal uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + bals := b.state.Balances + if b.sharedFieldReferences[balances].Refs() > 1 { + bals = b.balances() + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + } + + b.state.Balances = append(bals, bal) + balIdx := len(b.state.Balances) - 1 + b.markFieldAsDirty(balances) + b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) + return nil +} + +// AppendInactivityScore for the beacon state. +func (b *BeaconState) AppendInactivityScore(s uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + scores := b.state.InactivityScores + if b.sharedFieldReferences[inactivityScores].Refs() > 1 { + scores = b.inactivityScores() + b.sharedFieldReferences[inactivityScores].MinusRef() + b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) + } + + b.state.InactivityScores = append(scores, s) + b.markFieldAsDirty(inactivityScores) + return nil +} + +// SetInactivityScores for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetInactivityScores(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[inactivityScores].MinusRef() + b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) + + b.state.InactivityScores = val + b.markFieldAsDirty(inactivityScores) + return nil +} diff --git a/beacon-chain/state-proto/v2/state_trie.go b/beacon-chain/state-proto/v2/state_trie.go new file mode 100644 index 0000000000..6314b2e164 --- /dev/null +++ b/beacon-chain/state-proto/v2/state_trie.go @@ -0,0 +1,428 @@ +package v2 + +import ( + "context" + "io" + "io/ioutil" + "runtime" + "sort" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/sharedstate" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/features" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/container/slice" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "go.opencensus.io/trace" + "google.golang.org/protobuf/proto" +) + +// InitializeFromProto the beacon state from a protobuf representation. +func InitializeFromProto(st *ethpb.BeaconStateAltair) (*BeaconState, error) { + return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateAltair)) +} + +// InitializeFromSSZReader can be used when the source for a serialized BeaconState object +// is an io.Reader. This allows client code to remain agnostic about whether the data comes +// from the network or a file without needing to read the entire state into mem as a large byte slice. +func InitializeFromSSZReader(r io.Reader) (*BeaconState, error) { + b, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + return InitializeFromSSZBytes(b) +} + +// InitializeFromSSZBytes is a convenience method to obtain a BeaconState by unmarshaling +// a slice of bytes containing the ssz-serialized representation of the state. +func InitializeFromSSZBytes(marshaled []byte) (*BeaconState, error) { + st := ðpb.BeaconStateAltair{} + if err := st.UnmarshalSSZ(marshaled); err != nil { + return nil, err + } + return InitializeFromProtoUnsafe(st) +} + +// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer +// and sets it as the inner state of the BeaconState type. +func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error) { + if st == nil { + return nil, errors.New("received nil state") + } + + fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount + b := &BeaconState{ + state: st, + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), + } + + var err error + for i := 0; i < fieldCount; i++ { + b.dirtyFields[types.FieldIndex(i)] = true + b.rebuildTrie[types.FieldIndex(i)] = true + b.dirtyIndices[types.FieldIndex(i)] = []uint64{} + b.stateFieldLeaves[types.FieldIndex(i)], err = fieldtrie.NewFieldTrie(types.FieldIndex(i), types.BasicArray, nil, 0) + if err != nil { + return nil, err + } + } + + // Initialize field reference tracking for shared data. + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + + sharedstate.StateCount.Inc() + return b, nil +} + +// Copy returns a deep copy of the beacon state. +func (b *BeaconState) Copy() state.BeaconState { + if !b.hasInnerState() { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount + + dst := &BeaconState{ + state: ðpb.BeaconStateAltair{ + // Primitive types, safe to copy. + GenesisTime: b.state.GenesisTime, + Slot: b.state.Slot, + Eth1DepositIndex: b.state.Eth1DepositIndex, + + // Large arrays, infrequently changed, constant size. + RandaoMixes: b.state.RandaoMixes, + StateRoots: b.state.StateRoots, + BlockRoots: b.state.BlockRoots, + Slashings: b.state.Slashings, + Eth1DataVotes: b.state.Eth1DataVotes, + + // Large arrays, increases over time. + Validators: b.state.Validators, + Balances: b.state.Balances, + HistoricalRoots: b.state.HistoricalRoots, + PreviousEpochParticipation: b.state.PreviousEpochParticipation, + CurrentEpochParticipation: b.state.CurrentEpochParticipation, + InactivityScores: b.state.InactivityScores, + + // Everything else, too small to be concerned about, constant size. + Fork: b.fork(), + LatestBlockHeader: b.latestBlockHeader(), + Eth1Data: b.eth1Data(), + JustificationBits: b.justificationBits(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), + FinalizedCheckpoint: b.finalizedCheckpoint(), + GenesisValidatorsRoot: b.genesisValidatorRoot(), + CurrentSyncCommittee: b.currentSyncCommittee(), + NextSyncCommittee: b.nextSyncCommittee(), + }, + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + + // Share the reference to validator index map. + valMapHandler: b.valMapHandler, + } + + for field, ref := range b.sharedFieldReferences { + ref.AddRef() + dst.sharedFieldReferences[field] = ref + } + + // Increment ref for validator map + b.valMapHandler.AddRef() + + for i := range b.dirtyFields { + dst.dirtyFields[i] = true + } + + for i := range b.dirtyIndices { + indices := make([]uint64, len(b.dirtyIndices[i])) + copy(indices, b.dirtyIndices[i]) + dst.dirtyIndices[i] = indices + } + + for i := range b.rebuildTrie { + dst.rebuildTrie[i] = true + } + + for fldIdx, fieldTrie := range b.stateFieldLeaves { + dst.stateFieldLeaves[fldIdx] = fieldTrie + if fieldTrie.FieldReference() != nil { + fieldTrie.Lock() + fieldTrie.FieldReference().AddRef() + fieldTrie.Unlock() + } + } + + if b.merkleLayers != nil { + dst.merkleLayers = make([][][]byte, len(b.merkleLayers)) + for i, layer := range b.merkleLayers { + dst.merkleLayers[i] = make([][]byte, len(layer)) + for j, content := range layer { + dst.merkleLayers[i][j] = make([]byte, len(content)) + copy(dst.merkleLayers[i][j], content) + } + } + } + + sharedstate.StateCount.Inc() + // Finalizer runs when dst is being destroyed in garbage collection. + runtime.SetFinalizer(dst, func(b *BeaconState) { + for field, v := range b.sharedFieldReferences { + v.MinusRef() + if b.stateFieldLeaves[field].FieldReference() != nil { + b.stateFieldLeaves[field].FieldReference().MinusRef() + } + } + for i := 0; i < fieldCount; i++ { + field := types.FieldIndex(i) + delete(b.stateFieldLeaves, field) + delete(b.dirtyIndices, field) + delete(b.dirtyFields, field) + delete(b.sharedFieldReferences, field) + delete(b.stateFieldLeaves, field) + } + sharedstate.StateCount.Sub(1) + }) + + return dst +} + +// HashTreeRoot of the beacon state retrieves the Merkle root of the trie +// representation of the beacon state based on the eth2 Simple Serialize specification. +func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { + _, span := trace.StartSpan(ctx, "beaconStateAltair.HashTreeRoot") + defer span.End() + + b.lock.Lock() + defer b.lock.Unlock() + + if b.merkleLayers == nil || len(b.merkleLayers) == 0 { + fieldRoots, err := computeFieldRoots(ctx, b.state) + if err != nil { + return [32]byte{}, err + } + layers := stateutil.Merkleize(fieldRoots) + b.merkleLayers = layers + b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateAltairFieldCount) + } + + for field := range b.dirtyFields { + root, err := b.rootSelector(ctx, field) + if err != nil { + return [32]byte{}, err + } + b.merkleLayers[0][field] = root[:] + b.recomputeRoot(int(field)) + delete(b.dirtyFields, field) + } + return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil +} + +// FieldReferencesCount returns the reference count held by each field. This +// also includes the field trie held by each field. +func (b *BeaconState) FieldReferencesCount() map[string]uint64 { + refMap := make(map[string]uint64) + b.lock.RLock() + defer b.lock.RUnlock() + for i, f := range b.sharedFieldReferences { + refMap[i.String(b.Version())] = uint64(f.Refs()) + } + for i, f := range b.stateFieldLeaves { + numOfRefs := uint64(f.FieldReference().Refs()) + f.RLock() + if !f.Empty() { + refMap[i.String(b.Version())+"_trie"] = numOfRefs + } + f.RUnlock() + } + return refMap +} + +// IsNil checks if the state and the underlying proto +// object are nil. +func (b *BeaconState) IsNil() bool { + return b == nil || b.state == nil +} + +func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) { + _, span := trace.StartSpan(ctx, "beaconState.rootSelector") + defer span.End() + span.AddAttributes(trace.StringAttribute("field", field.String(b.Version()))) + + hasher := hash.CustomSHA256Hasher() + switch field { + case genesisTime: + return ssz.Uint64Root(b.state.GenesisTime), nil + case genesisValidatorRoot: + return bytesutil.ToBytes32(b.state.GenesisValidatorsRoot), nil + case slot: + return ssz.Uint64Root(uint64(b.state.Slot)), nil + case eth1DepositIndex: + return ssz.Uint64Root(b.state.Eth1DepositIndex), nil + case fork: + return ssz.ForkRoot(b.state.Fork) + case latestBlockHeader: + return stateutil.BlockHeaderRoot(b.state.LatestBlockHeader) + case blockRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.BlockRoots, fieldparams.BlockRootsLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(blockRoots, b.state.BlockRoots) + case stateRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.StateRoots, fieldparams.StateRootsLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(stateRoots, b.state.StateRoots) + case historicalRoots: + return ssz.ByteArrayRootWithLimit(b.state.HistoricalRoots, fieldparams.HistoricalRootsLength) + case eth1Data: + return stateutil.Eth1Root(hasher, b.state.Eth1Data) + case eth1DataVotes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.state.Eth1DataVotes, + fieldparams.Eth1DataVotesLength, + ) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.state.Eth1DataVotes) + case validators: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.Validators, fieldparams.ValidatorRegistryLimit) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, validators) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(validators, b.state.Validators) + case balances: + if features.Get().EnableBalanceTrieComputation { + if b.rebuildTrie[field] { + maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) + elemSize := uint64(8) + balLimit := (maxBalCap*elemSize + 31) / 32 + err := b.resetFieldTrie(field, b.state.Balances, balLimit) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(balances, b.state.Balances) + } + return stateutil.Uint64ListRootWithRegistryLimit(b.state.Balances) + case randaoMixes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.RandaoMixes, fieldparams.RandaoMixesLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(randaoMixes, b.state.RandaoMixes) + case slashings: + return ssz.SlashingsRoot(b.state.Slashings) + case previousEpochParticipationBits: + return stateutil.ParticipationBitsRoot(b.state.PreviousEpochParticipation) + case currentEpochParticipationBits: + return stateutil.ParticipationBitsRoot(b.state.CurrentEpochParticipation) + case justificationBits: + return bytesutil.ToBytes32(b.state.JustificationBits), nil + case previousJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.PreviousJustifiedCheckpoint) + case currentJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.CurrentJustifiedCheckpoint) + case finalizedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.FinalizedCheckpoint) + case inactivityScores: + return stateutil.Uint64ListRootWithRegistryLimit(b.state.InactivityScores) + case currentSyncCommittee: + return stateutil.SyncCommitteeRoot(b.state.CurrentSyncCommittee) + case nextSyncCommittee: + return stateutil.SyncCommitteeRoot(b.state.NextSyncCommittee) + } + return [32]byte{}, errors.New("invalid field index provided") +} + +func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interface{}) ([32]byte, error) { + fTrie := b.stateFieldLeaves[index] + // We can't lock the trie directly because the trie's variable gets reassigned, + // and therefore we would call Unlock() on a different object. + fTrieMutex := fTrie.RWMutex + if fTrie.FieldReference().Refs() > 1 { + fTrieMutex.Lock() + fTrie.FieldReference().MinusRef() + newTrie := fTrie.CopyTrie() + b.stateFieldLeaves[index] = newTrie + fTrie = newTrie + fTrieMutex.Unlock() + } + // remove duplicate indexes + b.dirtyIndices[index] = slice.SetUint64(b.dirtyIndices[index]) + // sort indexes again + sort.Slice(b.dirtyIndices[index], func(i int, j int) bool { + return b.dirtyIndices[index][i] < b.dirtyIndices[index][j] + }) + root, err := fTrie.RecomputeTrie(b.dirtyIndices[index], elements) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[index] = []uint64{} + return root, nil +} + +func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{}, length uint64) error { + fTrie, err := fieldtrie.NewFieldTrie(index, fieldMap[index], elements, length) + if err != nil { + return err + } + b.stateFieldLeaves[index] = fTrie + b.dirtyIndices[index] = []uint64{} + return nil +} diff --git a/beacon-chain/state/v2/state_trie_test.go b/beacon-chain/state-proto/v2/state_trie_test.go similarity index 98% rename from beacon-chain/state/v2/state_trie_test.go rename to beacon-chain/state-proto/v2/state_trie_test.go index ede78dc944..d8ccea2077 100644 --- a/beacon-chain/state/v2/state_trie_test.go +++ b/beacon-chain/state-proto/v2/state_trie_test.go @@ -5,7 +5,7 @@ import ( "sync" "testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" "github.com/prysmaticlabs/prysm/config/features" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/state-proto/v2/types.go b/beacon-chain/state-proto/v2/types.go new file mode 100644 index 0000000000..1213650392 --- /dev/null +++ b/beacon-chain/state-proto/v2/types.go @@ -0,0 +1,78 @@ +package v2 + +import ( + "sync" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +func init() { + fieldMap = make(map[types.FieldIndex]types.DataType, params.BeaconConfig().BeaconStateFieldCount) + + // Initialize the fixed sized arrays. + fieldMap[types.BlockRoots] = types.BasicArray + fieldMap[types.StateRoots] = types.BasicArray + fieldMap[types.RandaoMixes] = types.BasicArray + + // Initialize the composite arrays. + fieldMap[types.Eth1DataVotes] = types.CompositeArray + fieldMap[types.Validators] = types.CompositeArray + + // Initialize Compressed Arrays + fieldMap[types.Balances] = types.CompressedArray +} + +// fieldMap keeps track of each field +// to its corresponding data type. +var fieldMap map[types.FieldIndex]types.DataType + +// ErrNilInnerState returns when the inner state is nil and no copy set or get +// operations can be performed on state. +var ErrNilInnerState = errors.New("nil inner state") + +// BeaconState defines a struct containing utilities for the eth2 chain state, defining +// getters and setters for its respective values and helpful functions such as HashTreeRoot(). +type BeaconState struct { + state *ethpb.BeaconStateAltair + lock sync.RWMutex + dirtyFields map[types.FieldIndex]bool + dirtyIndices map[types.FieldIndex][]uint64 + stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie + rebuildTrie map[types.FieldIndex]bool + valMapHandler *stateutil.ValidatorMapHandler + merkleLayers [][][]byte + sharedFieldReferences map[types.FieldIndex]*stateutil.Reference +} + +// Field Aliases for values from the types package. +const ( + genesisTime = types.GenesisTime + genesisValidatorRoot = types.GenesisValidatorRoot + slot = types.Slot + fork = types.Fork + latestBlockHeader = types.LatestBlockHeader + blockRoots = types.BlockRoots + stateRoots = types.StateRoots + historicalRoots = types.HistoricalRoots + eth1Data = types.Eth1Data + eth1DataVotes = types.Eth1DataVotes + eth1DepositIndex = types.Eth1DepositIndex + validators = types.Validators + balances = types.Balances + randaoMixes = types.RandaoMixes + slashings = types.Slashings + previousEpochParticipationBits = types.PreviousEpochParticipationBits + currentEpochParticipationBits = types.CurrentEpochParticipationBits + justificationBits = types.JustificationBits + previousJustifiedCheckpoint = types.PreviousJustifiedCheckpoint + currentJustifiedCheckpoint = types.CurrentJustifiedCheckpoint + finalizedCheckpoint = types.FinalizedCheckpoint + inactivityScores = types.InactivityScores + currentSyncCommittee = types.CurrentSyncCommittee + nextSyncCommittee = types.NextSyncCommittee +) diff --git a/beacon-chain/state-proto/v3/BUILD.bazel b/beacon-chain/state-proto/v3/BUILD.bazel new file mode 100644 index 0000000000..2ca097f45c --- /dev/null +++ b/beacon-chain/state-proto/v3/BUILD.bazel @@ -0,0 +1,92 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "deprecated_getters.go", + "deprecated_setters.go", + "field_roots.go", + "getters_block.go", + "getters_checkpoint.go", + "getters_eth1.go", + "getters_misc.go", + "getters_participation.go", + "getters_payload_header.go", + "getters_randao.go", + "getters_state.go", + "getters_sync_committee.go", + "getters_validator.go", + "proofs.go", + "setters_block.go", + "setters_checkpoint.go", + "setters_eth1.go", + "setters_misc.go", + "setters_participation.go", + "setters_payload_header.go", + "setters_randao.go", + "setters_state.go", + "setters_sync_committee.go", + "setters_validator.go", + "state_trie.go", + "types.go", + ], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3", + visibility = [ + "//beacon-chain:__subpackages__", + "//testing/util:__pkg__", + ], + deps = [ + "//beacon-chain/sharedstate:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/fieldtrie:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//config/features:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//container/slice:go_default_library", + "//crypto/hash:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@io_opencensus_go//trace:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "deprecated_getters_test.go", + "deprecated_setters_test.go", + "getters_block_test.go", + "getters_test.go", + "getters_validator_test.go", + "proofs_test.go", + "setters_test.go", + "state_trie_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/types:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//config/features:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//container/trie:go_default_library", + "//crypto/bls:go_default_library", + "//encoding/bytesutil:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + ], +) diff --git a/beacon-chain/state-proto/v3/deprecated_getters.go b/beacon-chain/state-proto/v3/deprecated_getters.go new file mode 100644 index 0000000000..846ace35e2 --- /dev/null +++ b/beacon-chain/state-proto/v3/deprecated_getters.go @@ -0,0 +1,16 @@ +package v3 + +import ( + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// PreviousEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { + return nil, errors.New("PreviousEpochAttestations is not supported for version Merge beacon state") +} + +// CurrentEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { + return nil, errors.New("CurrentEpochAttestations is not supported for version Merge beacon state") +} diff --git a/beacon-chain/state-proto/v3/deprecated_getters_test.go b/beacon-chain/state-proto/v3/deprecated_getters_test.go new file mode 100644 index 0000000000..3488b284e5 --- /dev/null +++ b/beacon-chain/state-proto/v3/deprecated_getters_test.go @@ -0,0 +1,19 @@ +package v3 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_CurrentEpochAttestations(t *testing.T) { + s := &BeaconState{} + _, err := s.CurrentEpochAttestations() + require.ErrorContains(t, "CurrentEpochAttestations is not supported for version Merge beacon state", err) +} + +func TestBeaconState_PreviousEpochAttestations(t *testing.T) { + s := &BeaconState{} + _, err := s.PreviousEpochAttestations() + require.ErrorContains(t, "PreviousEpochAttestations is not supported for version Merge beacon state", err) +} diff --git a/beacon-chain/state-proto/v3/deprecated_setters.go b/beacon-chain/state-proto/v3/deprecated_setters.go new file mode 100644 index 0000000000..53c61280fd --- /dev/null +++ b/beacon-chain/state-proto/v3/deprecated_setters.go @@ -0,0 +1,31 @@ +package v3 + +import ( + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetPreviousEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) SetPreviousEpochAttestations(_ []*ethpb.PendingAttestation) error { + return errors.New("SetPreviousEpochAttestations is not supported for version Merge beacon state") +} + +// SetCurrentEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) SetCurrentEpochAttestations(_ []*ethpb.PendingAttestation) error { + return errors.New("SetCurrentEpochAttestations is not supported for version Merge beacon state") +} + +// AppendCurrentEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) AppendCurrentEpochAttestations(_ *ethpb.PendingAttestation) error { + return errors.New("AppendCurrentEpochAttestations is not supported for version Merge beacon state") +} + +// AppendPreviousEpochAttestations is not supported for HF1 beacon state. +func (*BeaconState) AppendPreviousEpochAttestations(_ *ethpb.PendingAttestation) error { + return errors.New("AppendPreviousEpochAttestations is not supported for version Merge beacon state") +} + +// RotateAttestations is not supported for HF1 beacon state. +func (*BeaconState) RotateAttestations() error { + return errors.New("RotateAttestations is not supported for version Merge beacon state") +} diff --git a/beacon-chain/state-proto/v3/deprecated_setters_test.go b/beacon-chain/state-proto/v3/deprecated_setters_test.go new file mode 100644 index 0000000000..4fbde1097d --- /dev/null +++ b/beacon-chain/state-proto/v3/deprecated_setters_test.go @@ -0,0 +1,27 @@ +package v3 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_AppendCurrentEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported for version Merge beacon state", s.AppendCurrentEpochAttestations(nil)) +} + +func TestBeaconState_AppendPreviousEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported for version Merge beacon state", s.AppendPreviousEpochAttestations(nil)) +} + +func TestBeaconState_SetCurrentEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "SetCurrentEpochAttestations is not supported for version Merge beacon state", s.SetCurrentEpochAttestations(nil)) +} + +func TestBeaconState_SetPreviousEpochAttestations(t *testing.T) { + s := &BeaconState{} + require.ErrorContains(t, "SetPreviousEpochAttestations is not supported for version Merge beacon state", s.SetPreviousEpochAttestations(nil)) +} diff --git a/beacon-chain/state-proto/v3/field_roots.go b/beacon-chain/state-proto/v3/field_roots.go new file mode 100644 index 0000000000..7eb1c9d075 --- /dev/null +++ b/beacon-chain/state-proto/v3/field_roots.go @@ -0,0 +1,19 @@ +package v3 + +import ( + "context" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/config/features" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// computeFieldRoots returns the hash tree root computations of every field in +// the beacon state as a list of 32 byte roots. +//nolint:deadcode +func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateMerge) ([][]byte, error) { + if features.Get().EnableSSZCache { + return stateutil.CachedHasher.ComputeFieldRootsWithHasherMerge(ctx, state) + } + return stateutil.NocachedHasher.ComputeFieldRootsWithHasherMerge(ctx, state) +} diff --git a/beacon-chain/state-proto/v3/getters_block.go b/beacon-chain/state-proto/v3/getters_block.go new file mode 100644 index 0000000000..b9f4bb5b3e --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_block.go @@ -0,0 +1,99 @@ +package v3 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// LatestBlockHeader stored within the beacon state. +func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader { + if !b.hasInnerState() { + return nil + } + if b.state.LatestBlockHeader == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.latestBlockHeader() +} + +// latestBlockHeader stored within the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader { + if !b.hasInnerState() { + return nil + } + if b.state.LatestBlockHeader == nil { + return nil + } + + hdr := ðpb.BeaconBlockHeader{ + Slot: b.state.LatestBlockHeader.Slot, + ProposerIndex: b.state.LatestBlockHeader.ProposerIndex, + } + + parentRoot := make([]byte, len(b.state.LatestBlockHeader.ParentRoot)) + bodyRoot := make([]byte, len(b.state.LatestBlockHeader.BodyRoot)) + stateRoot := make([]byte, len(b.state.LatestBlockHeader.StateRoot)) + + copy(parentRoot, b.state.LatestBlockHeader.ParentRoot) + copy(bodyRoot, b.state.LatestBlockHeader.BodyRoot) + copy(stateRoot, b.state.LatestBlockHeader.StateRoot) + hdr.ParentRoot = parentRoot + hdr.BodyRoot = bodyRoot + hdr.StateRoot = stateRoot + return hdr +} + +// BlockRoots kept track of in the beacon state. +func (b *BeaconState) BlockRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.BlockRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.blockRoots() +} + +// blockRoots kept track of in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) blockRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.BlockRoots) +} + +// BlockRootAtIndex retrieves a specific block root based on an +// input index value. +func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.BlockRoots == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.blockRootAtIndex(idx) +} + +// blockRootAtIndex retrieves a specific block root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) blockRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + return bytesutil.SafeCopyRootAtIndex(b.state.BlockRoots, idx) +} diff --git a/beacon-chain/state-proto/v3/getters_block_test.go b/beacon-chain/state-proto/v3/getters_block_test.go new file mode 100644 index 0000000000..bb0f88f7ad --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_block_test.go @@ -0,0 +1,59 @@ +package v3 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_LatestBlockHeader(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateMerge{}) + require.NoError(t, err) + got := s.LatestBlockHeader() + require.DeepEqual(t, (*ethpb.BeaconBlockHeader)(nil), got) + + want := ðpb.BeaconBlockHeader{Slot: 100} + s, err = InitializeFromProto(ðpb.BeaconStateMerge{LatestBlockHeader: want}) + require.NoError(t, err) + got = s.LatestBlockHeader() + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got.Slot = 101 + require.DeepNotEqual(t, want, got) +} + +func TestBeaconState_BlockRoots(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateMerge{}) + require.NoError(t, err) + got := s.BlockRoots() + require.DeepEqual(t, ([][]byte)(nil), got) + + want := [][]byte{{'a'}} + s, err = InitializeFromProto(ðpb.BeaconStateMerge{BlockRoots: want}) + require.NoError(t, err) + got = s.BlockRoots() + require.DeepEqual(t, want, got) + + // Test copy does not mutate. + got[0][0] = 'b' + require.DeepNotEqual(t, want, got) +} + +func TestBeaconState_BlockRootAtIndex(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateMerge{}) + require.NoError(t, err) + got, err := s.BlockRootAtIndex(0) + require.NoError(t, err) + require.DeepEqual(t, ([]byte)(nil), got) + + r := [][]byte{{'a'}} + s, err = InitializeFromProto(ðpb.BeaconStateMerge{BlockRoots: r}) + require.NoError(t, err) + got, err = s.BlockRootAtIndex(0) + require.NoError(t, err) + want := bytesutil.PadTo([]byte{'a'}, 32) + require.DeepSSZEqual(t, want, got) +} diff --git a/beacon-chain/state-proto/v3/getters_checkpoint.go b/beacon-chain/state-proto/v3/getters_checkpoint.go new file mode 100644 index 0000000000..f6b6eab16c --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_checkpoint.go @@ -0,0 +1,160 @@ +package v3 + +import ( + "bytes" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// JustificationBits marking which epochs have been justified in the beacon chain. +func (b *BeaconState) JustificationBits() bitfield.Bitvector4 { + if !b.hasInnerState() { + return nil + } + if b.state.JustificationBits == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.justificationBits() +} + +// justificationBits marking which epochs have been justified in the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) justificationBits() bitfield.Bitvector4 { + if !b.hasInnerState() { + return nil + } + if b.state.JustificationBits == nil { + return nil + } + + res := make([]byte, len(b.state.JustificationBits.Bytes())) + copy(res, b.state.JustificationBits.Bytes()) + return res +} + +// PreviousJustifiedCheckpoint denoting an epoch and block root. +func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.PreviousJustifiedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.previousJustifiedCheckpoint() +} + +// previousJustifiedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) previousJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.PreviousJustifiedCheckpoint) +} + +// CurrentJustifiedCheckpoint denoting an epoch and block root. +func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.CurrentJustifiedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.currentJustifiedCheckpoint() +} + +// currentJustifiedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentJustifiedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.CurrentJustifiedCheckpoint) +} + +// MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches +// the current justified checkpoint in state. +func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool { + if !b.hasInnerState() { + return false + } + if b.state.CurrentJustifiedCheckpoint == nil { + return false + } + + if c.Epoch != b.state.CurrentJustifiedCheckpoint.Epoch { + return false + } + return bytes.Equal(c.Root, b.state.CurrentJustifiedCheckpoint.Root) +} + +// MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches +// the previous justified checkpoint in state. +func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool { + if !b.hasInnerState() { + return false + } + if b.state.PreviousJustifiedCheckpoint == nil { + return false + } + + if c.Epoch != b.state.PreviousJustifiedCheckpoint.Epoch { + return false + } + return bytes.Equal(c.Root, b.state.PreviousJustifiedCheckpoint.Root) +} + +// FinalizedCheckpoint denoting an epoch and block root. +func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + if b.state.FinalizedCheckpoint == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.finalizedCheckpoint() +} + +// finalizedCheckpoint denoting an epoch and block root. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) finalizedCheckpoint() *ethpb.Checkpoint { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyCheckpoint(b.state.FinalizedCheckpoint) +} + +// FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint. +func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch { + if !b.hasInnerState() { + return 0 + } + if b.state.FinalizedCheckpoint == nil { + return 0 + } + b.lock.RLock() + defer b.lock.RUnlock() + + return b.state.FinalizedCheckpoint.Epoch +} diff --git a/beacon-chain/state-proto/v3/getters_eth1.go b/beacon-chain/state-proto/v3/getters_eth1.go new file mode 100644 index 0000000000..04449eb9d9 --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_eth1.go @@ -0,0 +1,91 @@ +package v3 + +import ( + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// Eth1Data corresponding to the proof-of-work chain information stored in the beacon state. +func (b *BeaconState) Eth1Data() *ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1Data == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1Data() +} + +// eth1Data corresponding to the proof-of-work chain information stored in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1Data() *ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1Data == nil { + return nil + } + + return ethpb.CopyETH1Data(b.state.Eth1Data) +} + +// Eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain +// data retrieved from eth1. +func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1DataVotes == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1DataVotes() +} + +// eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain +// data retrieved from eth1. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1DataVotes() []*ethpb.Eth1Data { + if !b.hasInnerState() { + return nil + } + if b.state.Eth1DataVotes == nil { + return nil + } + + res := make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) + for i := 0; i < len(res); i++ { + res[i] = ethpb.CopyETH1Data(b.state.Eth1DataVotes[i]) + } + return res +} + +// Eth1DepositIndex corresponds to the index of the deposit made to the +// validator deposit contract at the time of this state's eth1 data. +func (b *BeaconState) Eth1DepositIndex() uint64 { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.eth1DepositIndex() +} + +// eth1DepositIndex corresponds to the index of the deposit made to the +// validator deposit contract at the time of this state's eth1 data. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) eth1DepositIndex() uint64 { + if !b.hasInnerState() { + return 0 + } + + return b.state.Eth1DepositIndex +} diff --git a/beacon-chain/state-proto/v3/getters_misc.go b/beacon-chain/state-proto/v3/getters_misc.go new file mode 100644 index 0000000000..99f82adb3b --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_misc.go @@ -0,0 +1,211 @@ +package v3 + +import ( + "time" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// GenesisTime of the beacon state as a uint64. +func (b *BeaconState) GenesisTime() uint64 { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisTime() +} + +// genesisTime of the beacon state as a uint64. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisTime() uint64 { + if !b.hasInnerState() { + return 0 + } + + return b.state.GenesisTime +} + +// GenesisValidatorRoot of the beacon state. +func (b *BeaconState) GenesisValidatorRoot() []byte { + if !b.hasInnerState() { + return nil + } + if b.state.GenesisValidatorsRoot == nil { + return params.BeaconConfig().ZeroHash[:] + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisValidatorRoot() +} + +// genesisValidatorRoot of the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisValidatorRoot() []byte { + if !b.hasInnerState() { + return nil + } + if b.state.GenesisValidatorsRoot == nil { + return params.BeaconConfig().ZeroHash[:] + } + + root := make([]byte, 32) + copy(root, b.state.GenesisValidatorsRoot) + return root +} + +// GenesisUnixTime returns the genesis time as time.Time. +func (b *BeaconState) GenesisUnixTime() time.Time { + if !b.hasInnerState() { + return time.Unix(0, 0) + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.genesisUnixTime() +} + +// genesisUnixTime returns the genesis time as time.Time. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) genesisUnixTime() time.Time { + if !b.hasInnerState() { + return time.Unix(0, 0) + } + + return time.Unix(int64(b.state.GenesisTime), 0) +} + +// ParentRoot is a convenience method to access state.LatestBlockRoot.ParentRoot. +func (b *BeaconState) ParentRoot() [32]byte { + if !b.hasInnerState() { + return [32]byte{} + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.parentRoot() +} + +// parentRoot is a convenience method to access state.LatestBlockRoot.ParentRoot. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) parentRoot() [32]byte { + if !b.hasInnerState() { + return [32]byte{} + } + + parentRoot := [32]byte{} + copy(parentRoot[:], b.state.LatestBlockHeader.ParentRoot) + return parentRoot +} + +// Version of the beacon state. This method +// is strictly meant to be used without a lock +// internally. +func (_ *BeaconState) Version() int { + return version.Merge +} + +// Slot of the current beacon chain state. +func (b *BeaconState) Slot() types.Slot { + if !b.hasInnerState() { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.slot() +} + +// slot of the current beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) slot() types.Slot { + if !b.hasInnerState() { + return 0 + } + + return b.state.Slot +} + +// Fork version of the beacon chain. +func (b *BeaconState) Fork() *ethpb.Fork { + if !b.hasInnerState() { + return nil + } + if b.state.Fork == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.fork() +} + +// fork version of the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) fork() *ethpb.Fork { + if !b.hasInnerState() { + return nil + } + if b.state.Fork == nil { + return nil + } + + prevVersion := make([]byte, len(b.state.Fork.PreviousVersion)) + copy(prevVersion, b.state.Fork.PreviousVersion) + currVersion := make([]byte, len(b.state.Fork.CurrentVersion)) + copy(currVersion, b.state.Fork.CurrentVersion) + return ðpb.Fork{ + PreviousVersion: prevVersion, + CurrentVersion: currVersion, + Epoch: b.state.Fork.Epoch, + } +} + +// HistoricalRoots based on epochs stored in the beacon state. +func (b *BeaconState) HistoricalRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.HistoricalRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.historicalRoots() +} + +// historicalRoots based on epochs stored in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) historicalRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.HistoricalRoots) +} + +// balancesLength returns the length of the balances slice. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) balancesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.Balances == nil { + return 0 + } + + return len(b.state.Balances) +} diff --git a/beacon-chain/state-proto/v3/getters_participation.go b/beacon-chain/state-proto/v3/getters_participation.go new file mode 100644 index 0000000000..42358b01de --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_participation.go @@ -0,0 +1,53 @@ +package v3 + +// CurrentEpochParticipation corresponding to participation bits on the beacon chain. +func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.CurrentEpochParticipation == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.currentEpochParticipation(), nil +} + +// PreviousEpochParticipation corresponding to participation bits on the beacon chain. +func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.PreviousEpochParticipation == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.previousEpochParticipation(), nil +} + +// currentEpochParticipation corresponding to participation bits on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentEpochParticipation() []byte { + if !b.hasInnerState() { + return nil + } + tmp := make([]byte, len(b.state.CurrentEpochParticipation)) + copy(tmp, b.state.CurrentEpochParticipation) + return tmp +} + +// previousEpochParticipation corresponding to participation bits on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) previousEpochParticipation() []byte { + if !b.hasInnerState() { + return nil + } + tmp := make([]byte, len(b.state.PreviousEpochParticipation)) + copy(tmp, b.state.PreviousEpochParticipation) + return tmp +} diff --git a/beacon-chain/state-proto/v3/getters_payload_header.go b/beacon-chain/state-proto/v3/getters_payload_header.go new file mode 100644 index 0000000000..bfbd893f25 --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_payload_header.go @@ -0,0 +1,30 @@ +package v3 + +import ( + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// LatestExecutionPayloadHeader of the beacon state. +func (b *BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.LatestExecutionPayloadHeader == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.latestExecutionPayloadHeader(), nil +} + +// latestExecutionPayloadHeader of the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) latestExecutionPayloadHeader() *ethpb.ExecutionPayloadHeader { + if !b.hasInnerState() { + return nil + } + + return ethpb.CopyExecutionPayloadHeader(b.state.LatestExecutionPayloadHeader) +} diff --git a/beacon-chain/state-proto/v3/getters_randao.go b/beacon-chain/state-proto/v3/getters_randao.go new file mode 100644 index 0000000000..660e330ab3 --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_randao.go @@ -0,0 +1,85 @@ +package v3 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" +) + +// RandaoMixes of block proposers on the beacon chain. +func (b *BeaconState) RandaoMixes() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.RandaoMixes == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixes() +} + +// randaoMixes of block proposers on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixes() [][]byte { + if !b.hasInnerState() { + return nil + } + + return bytesutil.SafeCopy2dBytes(b.state.RandaoMixes) +} + +// RandaoMixAtIndex retrieves a specific block root based on an +// input index value. +func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.RandaoMixes == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixAtIndex(idx) +} + +// randaoMixAtIndex retrieves a specific block root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + + return bytesutil.SafeCopyRootAtIndex(b.state.RandaoMixes, idx) +} + +// RandaoMixesLength returns the length of the randao mixes slice. +func (b *BeaconState) RandaoMixesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.RandaoMixes == nil { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.randaoMixesLength() +} + +// randaoMixesLength returns the length of the randao mixes slice. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) randaoMixesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.RandaoMixes == nil { + return 0 + } + + return len(b.state.RandaoMixes) +} diff --git a/beacon-chain/state-proto/v3/getters_state.go b/beacon-chain/state-proto/v3/getters_state.go new file mode 100644 index 0000000000..71604daae4 --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_state.go @@ -0,0 +1,127 @@ +package v3 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// InnerStateUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) InnerStateUnsafe() interface{} { + if b == nil { + return nil + } + return b.state +} + +// CloneInnerState the beacon state into a protobuf for usage. +func (b *BeaconState) CloneInnerState() interface{} { + if b == nil || b.state == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + return ðpb.BeaconStateMerge{ + GenesisTime: b.genesisTime(), + GenesisValidatorsRoot: b.genesisValidatorRoot(), + Slot: b.slot(), + Fork: b.fork(), + LatestBlockHeader: b.latestBlockHeader(), + BlockRoots: b.blockRoots(), + StateRoots: b.stateRoots(), + HistoricalRoots: b.historicalRoots(), + Eth1Data: b.eth1Data(), + Eth1DataVotes: b.eth1DataVotes(), + Eth1DepositIndex: b.eth1DepositIndex(), + Validators: b.validators(), + Balances: b.balances(), + RandaoMixes: b.randaoMixes(), + Slashings: b.slashings(), + CurrentEpochParticipation: b.currentEpochParticipation(), + PreviousEpochParticipation: b.previousEpochParticipation(), + JustificationBits: b.justificationBits(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), + FinalizedCheckpoint: b.finalizedCheckpoint(), + InactivityScores: b.inactivityScores(), + CurrentSyncCommittee: b.currentSyncCommittee(), + NextSyncCommittee: b.nextSyncCommittee(), + LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader(), + } +} + +// hasInnerState detects if the internal reference to the state data structure +// is populated correctly. Returns false if nil. +func (b *BeaconState) hasInnerState() bool { + return b != nil && b.state != nil +} + +// StateRoots kept track of in the beacon state. +func (b *BeaconState) StateRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + if b.state.StateRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.stateRoots() +} + +// StateRoots kept track of in the beacon state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) stateRoots() [][]byte { + if !b.hasInnerState() { + return nil + } + return bytesutil.SafeCopy2dBytes(b.state.StateRoots) +} + +// StateRootAtIndex retrieves a specific state root based on an +// input index value. +func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.StateRoots == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.stateRootAtIndex(idx) +} + +// stateRootAtIndex retrieves a specific state root based on an +// input index value. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) stateRootAtIndex(idx uint64) ([]byte, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + return bytesutil.SafeCopyRootAtIndex(b.state.StateRoots, idx) +} + +// MarshalSSZ marshals the underlying beacon state to bytes. +func (b *BeaconState) MarshalSSZ() ([]byte, error) { + if !b.hasInnerState() { + return nil, errors.New("nil beacon state") + } + return b.state.MarshalSSZ() +} + +// ProtobufBeaconState transforms an input into beacon state Merge in the form of protobuf. +// Error is returned if the input is not type protobuf beacon state. +func ProtobufBeaconState(s interface{}) (*ethpb.BeaconStateMerge, error) { + pbState, ok := s.(*ethpb.BeaconStateMerge) + if !ok { + return nil, errors.New("input is not type pb.BeaconStateMerge") + } + return pbState, nil +} diff --git a/beacon-chain/state-proto/v3/getters_sync_committee.go b/beacon-chain/state-proto/v3/getters_sync_committee.go new file mode 100644 index 0000000000..38faf4ac19 --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_sync_committee.go @@ -0,0 +1,69 @@ +package v3 + +import ( + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// currentSyncCommittee of the current sync committee in beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentSyncCommittee() *ethpb.SyncCommittee { + if !b.hasInnerState() { + return nil + } + + return CopySyncCommittee(b.state.CurrentSyncCommittee) +} + +// nextSyncCommittee of the next sync committee in beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) nextSyncCommittee() *ethpb.SyncCommittee { + if !b.hasInnerState() { + return nil + } + + return CopySyncCommittee(b.state.NextSyncCommittee) +} + +// CurrentSyncCommittee of the current sync committee in beacon chain state. +func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { + if !b.hasInnerState() { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + if b.state.CurrentSyncCommittee == nil { + return nil, nil + } + + return b.currentSyncCommittee(), nil +} + +// NextSyncCommittee of the next sync committee in beacon chain state. +func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { + if !b.hasInnerState() { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + if b.state.NextSyncCommittee == nil { + return nil, nil + } + + return b.nextSyncCommittee(), nil +} + +// CopySyncCommittee copies the provided sync committee object. +func CopySyncCommittee(data *ethpb.SyncCommittee) *ethpb.SyncCommittee { + if data == nil { + return nil + } + return ðpb.SyncCommittee{ + Pubkeys: bytesutil.SafeCopy2dBytes(data.Pubkeys), + AggregatePubkey: bytesutil.SafeCopyBytes(data.AggregatePubkey), + } +} diff --git a/beacon-chain/state-proto/v3/getters_test.go b/beacon-chain/state-proto/v3/getters_test.go new file mode 100644 index 0000000000..c96bb51b27 --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_test.go @@ -0,0 +1,192 @@ +package v3 + +import ( + "runtime/debug" + "sync" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestBeaconState_SlotDataRace(t *testing.T) { + headState, err := InitializeFromProto(ðpb.BeaconStateMerge{Slot: 1}) + require.NoError(t, err) + + wg := sync.WaitGroup{} + wg.Add(2) + go func() { + require.NoError(t, headState.SetSlot(0)) + wg.Done() + }() + go func() { + headState.Slot() + wg.Done() + }() + + wg.Wait() +} + +func TestNilState_NoPanic(t *testing.T) { + var st *BeaconState + defer func() { + if r := recover(); r != nil { + t.Errorf("Method panicked when it was not supposed to: %v\n%v\n", r, string(debug.Stack())) + } + }() + // retrieve elements from nil state + _ = st.GenesisTime() + _ = st.GenesisValidatorRoot() + _ = st.GenesisUnixTime() + _ = st.GenesisValidatorRoot() + _ = st.Slot() + _ = st.Fork() + _ = st.LatestBlockHeader() + _ = st.ParentRoot() + _ = st.BlockRoots() + _, err := st.BlockRootAtIndex(0) + _ = err + _ = st.StateRoots() + _ = st.HistoricalRoots() + _ = st.Eth1Data() + _ = st.Eth1DataVotes() + _ = st.Eth1DepositIndex() + _, err = st.ValidatorAtIndex(0) + _ = err + _, err = st.ValidatorAtIndexReadOnly(0) + _ = err + _, _ = st.ValidatorIndexByPubkey([48]byte{}) + _ = st.PubkeyAtIndex(0) + _ = st.NumValidators() + _ = st.Balances() + _, err = st.BalanceAtIndex(0) + _ = err + _ = st.BalancesLength() + _ = st.RandaoMixes() + _, err = st.RandaoMixAtIndex(0) + _ = err + _ = st.RandaoMixesLength() + _ = st.Slashings() + _, err = st.CurrentEpochParticipation() + _ = err + _, err = st.PreviousEpochParticipation() + _ = err + _ = st.JustificationBits() + _ = st.PreviousJustifiedCheckpoint() + _ = st.CurrentJustifiedCheckpoint() + _ = st.FinalizedCheckpoint() + _, err = st.CurrentEpochParticipation() + _ = err + _, err = st.PreviousEpochParticipation() + _ = err + _, err = st.InactivityScores() + _ = err + _, err = st.CurrentSyncCommittee() + _ = err + _, err = st.NextSyncCommittee() + _ = err +} + +func TestBeaconState_ValidatorByPubkey(t *testing.T) { + keyCreator := func(input []byte) [48]byte { + nKey := [48]byte{} + copy(nKey[:1], input) + return nKey + } + + tests := []struct { + name string + modifyFunc func(b *BeaconState, k [48]byte) + exists bool + expectedIdx types.ValidatorIndex + largestIdxInSet types.ValidatorIndex + }{ + { + name: "retrieve validator", + modifyFunc: func(b *BeaconState, key [48]byte) { + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators from the start", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + }, + exists: true, + expectedIdx: 2, + }, + { + name: "retrieve validator with multiple validators from the start with shared state", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + _ = b.Copy() + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + }, + exists: true, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators with shared state", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + key2 := keyCreator([]byte{'D'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key2[:]})) + n := b.Copy() + // Append to another state + assert.NoError(t, n.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + + }, + exists: false, + expectedIdx: 0, + }, + { + name: "retrieve validator with multiple validators with shared state at boundary", + modifyFunc: func(b *BeaconState, key [48]byte) { + key1 := keyCreator([]byte{'C'}) + assert.NoError(t, b.AppendValidator(ðpb.Validator{PublicKey: key1[:]})) + n := b.Copy() + // Append to another state + assert.NoError(t, n.AppendValidator(ðpb.Validator{PublicKey: key[:]})) + + }, + exists: false, + expectedIdx: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s, err := InitializeFromProto(ðpb.BeaconStateMerge{}) + require.NoError(t, err) + nKey := keyCreator([]byte{'A'}) + tt.modifyFunc(s, nKey) + idx, ok := s.ValidatorIndexByPubkey(nKey) + assert.Equal(t, tt.exists, ok) + assert.Equal(t, tt.expectedIdx, idx) + }) + } +} diff --git a/beacon-chain/state-proto/v3/getters_validator.go b/beacon-chain/state-proto/v3/getters_validator.go new file mode 100644 index 0000000000..084e0bf31f --- /dev/null +++ b/beacon-chain/state-proto/v3/getters_validator.go @@ -0,0 +1,328 @@ +package v3 + +import ( + "fmt" + + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist +// at a given index in the validator's array. +type ValidatorIndexOutOfRangeError struct { + message string +} + +var ( + // ErrNilValidatorsInState returns when accessing validators in the state while the state has a + // nil slice for the validators field. + ErrNilValidatorsInState = errors.New("state has nil validator slice") +) + +// NewValidatorIndexOutOfRangeError creates a new error instance. +func NewValidatorIndexOutOfRangeError(index types.ValidatorIndex) ValidatorIndexOutOfRangeError { + return ValidatorIndexOutOfRangeError{ + message: fmt.Sprintf("index %d out of range", index), + } +} + +// Error returns the underlying error message. +func (e *ValidatorIndexOutOfRangeError) Error() string { + return e.message +} + +// Validators participating in consensus on the beacon chain. +func (b *BeaconState) Validators() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.validators() +} + +// validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) validators() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + res := make([]*ethpb.Validator, len(b.state.Validators)) + for i := 0; i < len(res); i++ { + val := b.state.Validators[i] + if val == nil { + continue + } + res[i] = ethpb.CopyValidator(val) + } + return res +} + +// references of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. This does not +// copy fully and instead just copies the reference. +func (b *BeaconState) validatorsReferences() []*ethpb.Validator { + if !b.hasInnerState() { + return nil + } + if b.state.Validators == nil { + return nil + } + + res := make([]*ethpb.Validator, len(b.state.Validators)) + for i := 0; i < len(res); i++ { + validator := b.state.Validators[i] + if validator == nil { + continue + } + // copy validator reference instead. + res[i] = validator + } + return res +} + +// ValidatorAtIndex is the validator at the provided index. +func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.Validators == nil { + return ðpb.Validator{}, nil + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + e := NewValidatorIndexOutOfRangeError(idx) + return nil, &e + } + + b.lock.RLock() + defer b.lock.RUnlock() + + val := b.state.Validators[idx] + return ethpb.CopyValidator(val), nil +} + +// ValidatorAtIndexReadOnly is the validator at the provided index. This method +// doesn't clone the validator. +func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) { + if !b.hasInnerState() { + return nil, ErrNilInnerState + } + if b.state.Validators == nil { + return nil, ErrNilValidatorsInState + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + e := NewValidatorIndexOutOfRangeError(idx) + return nil, &e + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return v1.NewValidator(b.state.Validators[idx]) +} + +// ValidatorIndexByPubkey returns a given validator by its 48-byte public key. +func (b *BeaconState) ValidatorIndexByPubkey(key [48]byte) (types.ValidatorIndex, bool) { + if b == nil || b.valMapHandler == nil || b.valMapHandler.IsNil() { + return 0, false + } + b.lock.RLock() + defer b.lock.RUnlock() + numOfVals := len(b.state.Validators) + + idx, ok := b.valMapHandler.Get(key) + if ok && numOfVals <= int(idx) { + return types.ValidatorIndex(0), false + } + return idx, ok +} + +// PubkeyAtIndex returns the pubkey at the given +// validator index. +func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [48]byte { + if !b.hasInnerState() { + return [48]byte{} + } + if uint64(idx) >= uint64(len(b.state.Validators)) { + return [48]byte{} + } + b.lock.RLock() + defer b.lock.RUnlock() + + if b.state.Validators[idx] == nil { + return [48]byte{} + } + return bytesutil.ToBytes48(b.state.Validators[idx].PublicKey) +} + +// NumValidators returns the size of the validator registry. +func (b *BeaconState) NumValidators() int { + if !b.hasInnerState() { + return 0 + } + b.lock.RLock() + defer b.lock.RUnlock() + + return len(b.state.Validators) +} + +// ReadFromEveryValidator reads values from every validator and applies it to the provided function. +// Warning: This method is potentially unsafe, as it exposes the actual validator registry. +func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if b.state.Validators == nil { + return errors.New("nil validators in state") + } + b.lock.RLock() + validators := b.state.Validators + b.lock.RUnlock() + + for i, v := range validators { + v, err := v1.NewValidator(v) + if err != nil { + return err + } + if err := f(i, v); err != nil { + return err + } + } + return nil +} + +// Balances of validators participating in consensus on the beacon chain. +func (b *BeaconState) Balances() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Balances == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.balances() +} + +// balances of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) balances() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Balances == nil { + return nil + } + + res := make([]uint64, len(b.state.Balances)) + copy(res, b.state.Balances) + return res +} + +// BalanceAtIndex of validator with the provided index. +func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) { + if !b.hasInnerState() { + return 0, ErrNilInnerState + } + if b.state.Balances == nil { + return 0, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + if uint64(len(b.state.Balances)) <= uint64(idx) { + return 0, fmt.Errorf("index of %d does not exist", idx) + } + return b.state.Balances[idx], nil +} + +// BalancesLength returns the length of the balances slice. +func (b *BeaconState) BalancesLength() int { + if !b.hasInnerState() { + return 0 + } + if b.state.Balances == nil { + return 0 + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.balancesLength() +} + +// Slashings of validators on the beacon chain. +func (b *BeaconState) Slashings() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Slashings == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.slashings() +} + +// slashings of validators on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) slashings() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.Slashings == nil { + return nil + } + + res := make([]uint64, len(b.state.Slashings)) + copy(res, b.state.Slashings) + return res +} + +// inactivityScores of validators participating in consensus on the beacon chain. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) inactivityScores() []uint64 { + if !b.hasInnerState() { + return nil + } + if b.state.InactivityScores == nil { + return nil + } + + res := make([]uint64, len(b.state.InactivityScores)) + copy(res, b.state.InactivityScores) + return res +} + +// InactivityScores of validators participating in consensus on the beacon chain. +func (b *BeaconState) InactivityScores() ([]uint64, error) { + if !b.hasInnerState() { + return nil, nil + } + if b.state.InactivityScores == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.inactivityScores(), nil +} diff --git a/beacon-chain/state/v3/getters_validator_test.go b/beacon-chain/state-proto/v3/getters_validator_test.go similarity index 88% rename from beacon-chain/state/v3/getters_validator_test.go rename to beacon-chain/state-proto/v3/getters_validator_test.go index 019f6dc8b8..b8e7181742 100644 --- a/beacon-chain/state/v3/getters_validator_test.go +++ b/beacon-chain/state-proto/v3/getters_validator_test.go @@ -3,7 +3,7 @@ package v3_test import ( "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/state-proto/v3/proofs.go b/beacon-chain/state-proto/v3/proofs.go new file mode 100644 index 0000000000..dd691e6c25 --- /dev/null +++ b/beacon-chain/state-proto/v3/proofs.go @@ -0,0 +1,60 @@ +package v3 + +import ( + "encoding/binary" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" +) + +const ( + finalizedRootIndex = uint64(105) // Precomputed value. +) + +// FinalizedRootGeneralizedIndex for the beacon state. +func FinalizedRootGeneralizedIndex() uint64 { + return finalizedRootIndex +} + +// CurrentSyncCommitteeGeneralizedIndex for the beacon state. +func CurrentSyncCommitteeGeneralizedIndex() uint64 { + return uint64(currentSyncCommittee) +} + +// NextSyncCommitteeGeneralizedIndex for the beacon state. +func NextSyncCommitteeGeneralizedIndex() uint64 { + return uint64(nextSyncCommittee) +} + +// CurrentSyncCommitteeProof from the state's Merkle trie representation. +func (b *BeaconState) CurrentSyncCommitteeProof() ([][]byte, error) { + b.lock.RLock() + defer b.lock.RUnlock() + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, currentSyncCommittee), nil +} + +// NextSyncCommitteeProof from the state's Merkle trie representation. +func (b *BeaconState) NextSyncCommitteeProof() ([][]byte, error) { + b.lock.RLock() + defer b.lock.RUnlock() + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nextSyncCommittee), nil +} + +// FinalizedRootProof crafts a Merkle proof for the finalized root +// contained within the finalized checkpoint of a beacon state. +func (b *BeaconState) FinalizedRootProof() ([][]byte, error) { + b.lock.RLock() + defer b.lock.RUnlock() + cpt := b.state.FinalizedCheckpoint + // The epoch field of a finalized checkpoint is the neighbor + // index of the finalized root field in its Merkle tree representation + // of the checkpoint. This neighbor is the first element added to the proof. + epochBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(epochBuf, uint64(cpt.Epoch)) + epochRoot := bytesutil.ToBytes32(epochBuf) + proof := make([][]byte, 0) + proof = append(proof, epochRoot[:]) + branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) + proof = append(proof, branch...) + return proof, nil +} diff --git a/beacon-chain/state/v3/proofs_test.go b/beacon-chain/state-proto/v3/proofs_test.go similarity index 97% rename from beacon-chain/state/v3/proofs_test.go rename to beacon-chain/state-proto/v3/proofs_test.go index b683023a63..a7ff7eeea8 100644 --- a/beacon-chain/state/v3/proofs_test.go +++ b/beacon-chain/state-proto/v3/proofs_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/beacon-chain/state-proto/v3/setters_block.go b/beacon-chain/state-proto/v3/setters_block.go new file mode 100644 index 0000000000..5a08b311c0 --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_block.go @@ -0,0 +1,68 @@ +package v3 + +import ( + "fmt" + + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetLatestBlockHeader in the beacon state. +func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.LatestBlockHeader = ethpb.CopyBeaconBlockHeader(val) + b.markFieldAsDirty(latestBlockHeader) + return nil +} + +// SetBlockRoots for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetBlockRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[blockRoots].MinusRef() + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + + b.state.BlockRoots = val + b.markFieldAsDirty(blockRoots) + b.rebuildTrie[blockRoots] = true + return nil +} + +// UpdateBlockRootAtIndex for the beacon state. Updates the block root +// at a specific index to a new value. +func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.BlockRoots)) <= idx { + return fmt.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + r := b.state.BlockRoots + if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { + // Copy elements in underlying array by reference. + r = make([][]byte, len(b.state.BlockRoots)) + copy(r, b.state.BlockRoots) + ref.MinusRef() + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + } + + r[idx] = blockRoot[:] + b.state.BlockRoots = r + + b.markFieldAsDirty(blockRoots) + b.addDirtyIndices(blockRoots, []uint64{idx}) + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_checkpoint.go b/beacon-chain/state-proto/v3/setters_checkpoint.go new file mode 100644 index 0000000000..601f89dab6 --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_checkpoint.go @@ -0,0 +1,58 @@ +package v3 + +import ( + "github.com/prysmaticlabs/go-bitfield" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetJustificationBits for the beacon state. +func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.JustificationBits = val + b.markFieldAsDirty(justificationBits) + return nil +} + +// SetPreviousJustifiedCheckpoint for the beacon state. +func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.PreviousJustifiedCheckpoint = val + b.markFieldAsDirty(previousJustifiedCheckpoint) + return nil +} + +// SetCurrentJustifiedCheckpoint for the beacon state. +func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.CurrentJustifiedCheckpoint = val + b.markFieldAsDirty(currentJustifiedCheckpoint) + return nil +} + +// SetFinalizedCheckpoint for the beacon state. +func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.FinalizedCheckpoint = val + b.markFieldAsDirty(finalizedCheckpoint) + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_eth1.go b/beacon-chain/state-proto/v3/setters_eth1.go new file mode 100644 index 0000000000..db768b5a7c --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_eth1.go @@ -0,0 +1,74 @@ +package v3 + +import ( + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetEth1Data for the beacon state. +func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Eth1Data = val + b.markFieldAsDirty(eth1Data) + return nil +} + +// SetEth1DataVotes for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[eth1DataVotes].MinusRef() + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + + b.state.Eth1DataVotes = val + b.markFieldAsDirty(eth1DataVotes) + b.rebuildTrie[eth1DataVotes] = true + return nil +} + +// SetEth1DepositIndex for the beacon state. +func (b *BeaconState) SetEth1DepositIndex(val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Eth1DepositIndex = val + b.markFieldAsDirty(eth1DepositIndex) + return nil +} + +// AppendEth1DataVotes for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + votes := b.state.Eth1DataVotes + if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { + // Copy elements in underlying array by reference. + votes = make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) + copy(votes, b.state.Eth1DataVotes) + b.sharedFieldReferences[eth1DataVotes].MinusRef() + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + } + + b.state.Eth1DataVotes = append(votes, val) + b.markFieldAsDirty(eth1DataVotes) + b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.state.Eth1DataVotes) - 1)}) + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_misc.go b/beacon-chain/state-proto/v3/setters_misc.go new file mode 100644 index 0000000000..2adaf48cb0 --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_misc.go @@ -0,0 +1,186 @@ +package v3 + +import ( + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/features" + "github.com/prysmaticlabs/prysm/crypto/hash" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "google.golang.org/protobuf/proto" +) + +// For our setters, we have a field reference counter through +// which we can track shared field references. This helps when +// performing state copies, as we simply copy the reference to the +// field. When we do need to do need to modify these fields, we +// perform a full copy of the field. This is true of most of our +// fields except for the following below. +// 1) BlockRoots +// 2) StateRoots +// 3) Eth1DataVotes +// 4) RandaoMixes +// 5) HistoricalRoots +// 6) CurrentParticipationBits +// 7) PreviousParticipationBits +// +// The fields referred to above are instead copied by reference, where +// we simply copy the reference to the underlying object instead of the +// whole object. This is possible due to how we have structured our state +// as we copy the value on read, so as to ensure the underlying object is +// not mutated while it is being accessed during a state read. + +const ( + // This specifies the limit till which we process all dirty indices for a certain field. + // If we have more dirty indices than the threshold, then we rebuild the whole trie. This + // comes due to the fact that O(alogn) > O(n) beyond a certain value of a. + indicesLimit = 8000 +) + +// SetGenesisTime for the beacon state. +func (b *BeaconState) SetGenesisTime(val uint64) error { + b.lock.Lock() + defer b.lock.Unlock() + + b.state.GenesisTime = val + b.markFieldAsDirty(genesisTime) + return nil +} + +// SetGenesisValidatorRoot for the beacon state. +func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error { + b.lock.Lock() + defer b.lock.Unlock() + + b.state.GenesisValidatorsRoot = val + b.markFieldAsDirty(genesisValidatorRoot) + return nil +} + +// SetSlot for the beacon state. +func (b *BeaconState) SetSlot(val types.Slot) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Slot = val + b.markFieldAsDirty(slot) + return nil +} + +// SetFork version for the beacon chain. +func (b *BeaconState) SetFork(val *ethpb.Fork) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + fk, ok := proto.Clone(val).(*ethpb.Fork) + if !ok { + return errors.New("proto.Clone did not return a fork proto") + } + b.state.Fork = fk + b.markFieldAsDirty(fork) + return nil +} + +// SetHistoricalRoots for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[historicalRoots].MinusRef() + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + + b.state.HistoricalRoots = val + b.markFieldAsDirty(historicalRoots) + return nil +} + +// AppendHistoricalRoots for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + roots := b.state.HistoricalRoots + if b.sharedFieldReferences[historicalRoots].Refs() > 1 { + roots = make([][]byte, len(b.state.HistoricalRoots)) + copy(roots, b.state.HistoricalRoots) + b.sharedFieldReferences[historicalRoots].MinusRef() + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + } + + b.state.HistoricalRoots = append(roots, root[:]) + b.markFieldAsDirty(historicalRoots) + return nil +} + +// Recomputes the branch up the index in the Merkle trie representation +// of the beacon state. This method performs slice reads and the caller MUST +// hold the lock before calling this method. +func (b *BeaconState) recomputeRoot(idx int) { + hashFunc := hash.CustomSHA256Hasher() + layers := b.merkleLayers + // The merkle tree structure looks as follows: + // [[r1, r2, r3, r4], [parent1, parent2], [root]] + // Using information about the index which changed, idx, we recompute + // only its branch up the tree. + currentIndex := idx + root := b.merkleLayers[0][idx] + for i := 0; i < len(layers)-1; i++ { + isLeft := currentIndex%2 == 0 + neighborIdx := currentIndex ^ 1 + + neighbor := make([]byte, 32) + if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) { + neighbor = layers[i][neighborIdx] + } + if isLeft { + parentHash := hashFunc(append(root, neighbor...)) + root = parentHash[:] + } else { + parentHash := hashFunc(append(neighbor, root...)) + root = parentHash[:] + } + parentIdx := currentIndex / 2 + // Update the cached layers at the parent index. + layers[i+1][parentIdx] = root + currentIndex = parentIdx + } + b.merkleLayers = layers +} + +func (b *BeaconState) markFieldAsDirty(field stateTypes.FieldIndex) { + b.dirtyFields[field] = true +} + +// addDirtyIndices adds the relevant dirty field indices, so that they +// can be recomputed. +func (b *BeaconState) addDirtyIndices(index stateTypes.FieldIndex, indices []uint64) { + if b.rebuildTrie[index] { + return + } + // Exit early if balance trie computation isn't enabled. + if !features.Get().EnableBalanceTrieComputation && index == balances { + return + } + totalIndicesLen := len(b.dirtyIndices[index]) + len(indices) + if totalIndicesLen > indicesLimit { + b.rebuildTrie[index] = true + b.dirtyIndices[index] = []uint64{} + } else { + b.dirtyIndices[index] = append(b.dirtyIndices[index], indices...) + } +} diff --git a/beacon-chain/state-proto/v3/setters_participation.go b/beacon-chain/state-proto/v3/setters_participation.go new file mode 100644 index 0000000000..b22fcc1fbd --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_participation.go @@ -0,0 +1,89 @@ +package v3 + +import ( + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetPreviousParticipationBits for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetPreviousParticipationBits(val []byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() + b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) + + b.state.PreviousEpochParticipation = val + b.markFieldAsDirty(previousEpochParticipationBits) + b.rebuildTrie[previousEpochParticipationBits] = true + return nil +} + +// SetCurrentParticipationBits for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetCurrentParticipationBits(val []byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() + b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) + + b.state.CurrentEpochParticipation = val + b.markFieldAsDirty(currentEpochParticipationBits) + b.rebuildTrie[currentEpochParticipationBits] = true + return nil +} + +// AppendCurrentParticipationBits for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendCurrentParticipationBits(val byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + participation := b.state.CurrentEpochParticipation + if b.sharedFieldReferences[currentEpochParticipationBits].Refs() > 1 { + // Copy elements in underlying array by reference. + participation = make([]byte, len(b.state.CurrentEpochParticipation)) + copy(participation, b.state.CurrentEpochParticipation) + b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() + b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) + } + + b.state.CurrentEpochParticipation = append(participation, val) + b.markFieldAsDirty(currentEpochParticipationBits) + b.addDirtyIndices(currentEpochParticipationBits, []uint64{uint64(len(b.state.CurrentEpochParticipation) - 1)}) + return nil +} + +// AppendPreviousParticipationBits for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendPreviousParticipationBits(val byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + bits := b.state.PreviousEpochParticipation + if b.sharedFieldReferences[previousEpochParticipationBits].Refs() > 1 { + bits = make([]byte, len(b.state.PreviousEpochParticipation)) + copy(bits, b.state.PreviousEpochParticipation) + b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() + b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) + } + + b.state.PreviousEpochParticipation = append(bits, val) + b.markFieldAsDirty(previousEpochParticipationBits) + b.addDirtyIndices(previousEpochParticipationBits, []uint64{uint64(len(b.state.PreviousEpochParticipation) - 1)}) + + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_payload_header.go b/beacon-chain/state-proto/v3/setters_payload_header.go new file mode 100644 index 0000000000..516db0f50f --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_payload_header.go @@ -0,0 +1,16 @@ +package v3 + +import ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + +// SetLatestExecutionPayloadHeader for the beacon state. +func (b *BeaconState) SetLatestExecutionPayloadHeader(val *ethpb.ExecutionPayloadHeader) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.LatestExecutionPayloadHeader = val + b.markFieldAsDirty(latestExecutionPayloadHeader) + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_randao.go b/beacon-chain/state-proto/v3/setters_randao.go new file mode 100644 index 0000000000..db29c1bb71 --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_randao.go @@ -0,0 +1,53 @@ +package v3 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetRandaoMixes for the beacon state. Updates the entire +// randao mixes to a new value by overwriting the previous one. +func (b *BeaconState) SetRandaoMixes(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[randaoMixes].MinusRef() + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + + b.state.RandaoMixes = val + b.markFieldAsDirty(randaoMixes) + b.rebuildTrie[randaoMixes] = true + return nil +} + +// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes +// at a specific index to a new value. +func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.RandaoMixes)) <= idx { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + mixes := b.state.RandaoMixes + if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { + // Copy elements in underlying array by reference. + mixes = make([][]byte, len(b.state.RandaoMixes)) + copy(mixes, b.state.RandaoMixes) + b.sharedFieldReferences[randaoMixes].MinusRef() + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + } + + mixes[idx] = val + b.state.RandaoMixes = mixes + b.markFieldAsDirty(randaoMixes) + b.addDirtyIndices(randaoMixes, []uint64{idx}) + + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_state.go b/beacon-chain/state-proto/v3/setters_state.go new file mode 100644 index 0000000000..848cce747f --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_state.go @@ -0,0 +1,59 @@ +package v3 + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" +) + +// SetStateRoots for the beacon state. Updates the state roots +// to a new value by overwriting the previous value. +func (b *BeaconState) SetStateRoots(val [][]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[stateRoots].MinusRef() + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + + b.state.StateRoots = val + b.markFieldAsDirty(stateRoots) + b.rebuildTrie[stateRoots] = true + return nil +} + +// UpdateStateRootAtIndex for the beacon state. Updates the state root +// at a specific index to a new value. +func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + + b.lock.RLock() + if uint64(len(b.state.StateRoots)) <= idx { + b.lock.RUnlock() + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.RUnlock() + + b.lock.Lock() + defer b.lock.Unlock() + + // Check if we hold the only reference to the shared state roots slice. + r := b.state.StateRoots + if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { + // Copy elements in underlying array by reference. + r = make([][]byte, len(b.state.StateRoots)) + copy(r, b.state.StateRoots) + ref.MinusRef() + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + } + + r[idx] = stateRoot[:] + b.state.StateRoots = r + + b.markFieldAsDirty(stateRoots) + b.addDirtyIndices(stateRoots, []uint64{idx}) + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_sync_committee.go b/beacon-chain/state-proto/v3/setters_sync_committee.go new file mode 100644 index 0000000000..7b5fa8372b --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_sync_committee.go @@ -0,0 +1,31 @@ +package v3 + +import ( + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetCurrentSyncCommittee for the beacon state. +func (b *BeaconState) SetCurrentSyncCommittee(val *ethpb.SyncCommittee) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.CurrentSyncCommittee = val + b.markFieldAsDirty(currentSyncCommittee) + return nil +} + +// SetNextSyncCommittee for the beacon state. +func (b *BeaconState) SetNextSyncCommittee(val *ethpb.SyncCommittee) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.NextSyncCommittee = val + b.markFieldAsDirty(nextSyncCommittee) + return nil +} diff --git a/beacon-chain/state-proto/v3/setters_test.go b/beacon-chain/state-proto/v3/setters_test.go new file mode 100644 index 0000000000..e8c3f58239 --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_test.go @@ -0,0 +1,184 @@ +package v3 + +import ( + "context" + "strconv" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestAppendBeyondIndicesLimit(t *testing.T) { + zeroHash := params.BeaconConfig().ZeroHash + mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockblockRoots); i++ { + mockblockRoots[i] = zeroHash[:] + } + + mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockstateRoots); i++ { + mockstateRoots[i] = zeroHash[:] + } + mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(mockrandaoMixes); i++ { + mockrandaoMixes[i] = zeroHash[:] + } + payload := ðpb.ExecutionPayloadHeader{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + Random: make([]byte, 32), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + } + st, err := InitializeFromProto(ðpb.BeaconStateMerge{ + Slot: 1, + CurrentEpochParticipation: []byte{}, + PreviousEpochParticipation: []byte{}, + Validators: []*ethpb.Validator{}, + Eth1Data: ðpb.Eth1Data{}, + BlockRoots: mockblockRoots, + StateRoots: mockstateRoots, + RandaoMixes: mockrandaoMixes, + LatestExecutionPayloadHeader: payload, + }) + require.NoError(t, err) + _, err = st.HashTreeRoot(context.Background()) + require.NoError(t, err) + for i := stateTypes.FieldIndex(0); i < stateTypes.FieldIndex(params.BeaconConfig().BeaconStateMergeFieldCount); i++ { + st.dirtyFields[i] = true + } + _, err = st.HashTreeRoot(context.Background()) + require.NoError(t, err) + for i := 0; i < 10; i++ { + assert.NoError(t, st.AppendValidator(ðpb.Validator{})) + } + assert.Equal(t, false, st.rebuildTrie[validators]) + assert.NotEqual(t, len(st.dirtyIndices[validators]), 0) + + for i := 0; i < indicesLimit; i++ { + assert.NoError(t, st.AppendValidator(ðpb.Validator{})) + } + assert.Equal(t, true, st.rebuildTrie[validators]) + assert.Equal(t, len(st.dirtyIndices[validators]), 0) +} + +func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + bals := make([]uint64, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [48]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + bals = append(bals, params.BeaconConfig().MaxEffectiveBalance) + } + zeroHash := params.BeaconConfig().ZeroHash + mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockblockRoots); i++ { + mockblockRoots[i] = zeroHash[:] + } + + mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(mockstateRoots); i++ { + mockstateRoots[i] = zeroHash[:] + } + mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(mockrandaoMixes); i++ { + mockrandaoMixes[i] = zeroHash[:] + } + var pubKeys [][]byte + for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSize; i++ { + pubKeys = append(pubKeys, bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength)) + } + payload := ðpb.ExecutionPayloadHeader{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + Random: make([]byte, 32), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + } + st, err := InitializeFromProto(ðpb.BeaconStateMerge{ + Slot: 1, + GenesisValidatorsRoot: make([]byte, 32), + Fork: ðpb.Fork{ + PreviousVersion: make([]byte, 4), + CurrentVersion: make([]byte, 4), + Epoch: 0, + }, + LatestBlockHeader: ðpb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + CurrentEpochParticipation: []byte{}, + PreviousEpochParticipation: []byte{}, + Validators: vals, + Balances: bals, + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + }, + BlockRoots: mockblockRoots, + StateRoots: mockstateRoots, + RandaoMixes: mockrandaoMixes, + JustificationBits: bitfield.NewBitvector4(), + PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, + CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, + FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, + Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), + CurrentSyncCommittee: ðpb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, 48), + }, + NextSyncCommittee: ðpb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, 48), + }, + LatestExecutionPayloadHeader: payload, + }) + assert.NoError(t, err) + _, err = st.HashTreeRoot(context.Background()) + assert.NoError(t, err) + + for i := 0; i < 100; i++ { + if i%2 == 0 { + assert.NoError(t, st.UpdateBalancesAtIndex(types.ValidatorIndex(i), 1000)) + } + if i%3 == 0 { + assert.NoError(t, st.AppendBalance(1000)) + } + } + _, err = st.HashTreeRoot(context.Background()) + assert.NoError(t, err) + newRt := bytesutil.ToBytes32(st.merkleLayers[0][balances]) + wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.state.Balances) + assert.NoError(t, err) + assert.Equal(t, wantedRt, newRt, "state roots are unequal") +} diff --git a/beacon-chain/state-proto/v3/setters_validator.go b/beacon-chain/state-proto/v3/setters_validator.go new file mode 100644 index 0000000000..99ae32a9b1 --- /dev/null +++ b/beacon-chain/state-proto/v3/setters_validator.go @@ -0,0 +1,265 @@ +package v3 + +import ( + "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +// SetValidators for the beacon state. Updates the entire +// to a new value by overwriting the previous one. +func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Validators = val + b.sharedFieldReferences[validators].MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.markFieldAsDirty(validators) + b.rebuildTrie[validators] = true + b.valMapHandler = stateutil.NewValMapHandler(b.state.Validators) + return nil +} + +// ApplyToEveryValidator applies the provided callback function to each validator in the +// validator registry. +func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + v := b.state.Validators + if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + v = b.validatorsReferences() + ref.MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + b.lock.Unlock() + var changedVals []uint64 + for i, val := range v { + changed, newVal, err := f(i, val) + if err != nil { + return err + } + if changed { + changedVals = append(changedVals, uint64(i)) + v[i] = newVal + } + } + + b.lock.Lock() + defer b.lock.Unlock() + + b.state.Validators = v + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, changedVals) + + return nil +} + +// UpdateValidatorAtIndex for the beacon state. Updates the validator +// at a specific index to a new value. +func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Validators)) <= uint64(idx) { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + v := b.state.Validators + if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + v = b.validatorsReferences() + ref.MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + + v[idx] = val + b.state.Validators = v + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, []uint64{uint64(idx)}) + + return nil +} + +// SetBalances for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetBalances(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + + b.state.Balances = val + b.markFieldAsDirty(balances) + b.rebuildTrie[balances] = true + return nil +} + +// UpdateBalancesAtIndex for the beacon state. This method updates the balance +// at a specific index to a new value. +func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Balances)) <= uint64(idx) { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + bals := b.state.Balances + if b.sharedFieldReferences[balances].Refs() > 1 { + bals = b.balances() + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + } + + bals[idx] = val + b.state.Balances = bals + b.markFieldAsDirty(balances) + b.addDirtyIndices(balances, []uint64{uint64(idx)}) + return nil +} + +// SetSlashings for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetSlashings(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[slashings].MinusRef() + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + + b.state.Slashings = val + b.markFieldAsDirty(slashings) + return nil +} + +// UpdateSlashingsAtIndex for the beacon state. Updates the slashings +// at a specific index to a new value. +func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + if uint64(len(b.state.Slashings)) <= idx { + return errors.Errorf("invalid index provided %d", idx) + } + b.lock.Lock() + defer b.lock.Unlock() + + s := b.state.Slashings + if b.sharedFieldReferences[slashings].Refs() > 1 { + s = b.slashings() + b.sharedFieldReferences[slashings].MinusRef() + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + } + + s[idx] = val + + b.state.Slashings = s + + b.markFieldAsDirty(slashings) + return nil +} + +// AppendValidator for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + vals := b.state.Validators + if b.sharedFieldReferences[validators].Refs() > 1 { + vals = b.validatorsReferences() + b.sharedFieldReferences[validators].MinusRef() + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + } + + // append validator to slice + b.state.Validators = append(vals, val) + valIdx := types.ValidatorIndex(len(b.state.Validators) - 1) + + b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) + + b.markFieldAsDirty(validators) + b.addDirtyIndices(validators, []uint64{uint64(valIdx)}) + return nil +} + +// AppendBalance for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendBalance(bal uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + bals := b.state.Balances + if b.sharedFieldReferences[balances].Refs() > 1 { + bals = b.balances() + b.sharedFieldReferences[balances].MinusRef() + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + } + + b.state.Balances = append(bals, bal) + balIdx := len(b.state.Balances) - 1 + b.markFieldAsDirty(balances) + b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) + return nil +} + +// AppendInactivityScore for the beacon state. +func (b *BeaconState) AppendInactivityScore(s uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + scores := b.state.InactivityScores + if b.sharedFieldReferences[inactivityScores].Refs() > 1 { + scores = b.inactivityScores() + b.sharedFieldReferences[inactivityScores].MinusRef() + b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) + } + + b.state.InactivityScores = append(scores, s) + b.markFieldAsDirty(inactivityScores) + return nil +} + +// SetInactivityScores for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetInactivityScores(val []uint64) error { + if !b.hasInnerState() { + return ErrNilInnerState + } + b.lock.Lock() + defer b.lock.Unlock() + + b.sharedFieldReferences[inactivityScores].MinusRef() + b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) + + b.state.InactivityScores = val + b.markFieldAsDirty(inactivityScores) + return nil +} diff --git a/beacon-chain/state-proto/v3/state_trie.go b/beacon-chain/state-proto/v3/state_trie.go new file mode 100644 index 0000000000..3170ef3578 --- /dev/null +++ b/beacon-chain/state-proto/v3/state_trie.go @@ -0,0 +1,390 @@ +package v3 + +import ( + "context" + "runtime" + "sort" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/sharedstate" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/container/slice" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "go.opencensus.io/trace" + "google.golang.org/protobuf/proto" +) + +// InitializeFromProto the beacon state from a protobuf representation. +func InitializeFromProto(st *ethpb.BeaconStateMerge) (*BeaconState, error) { + return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateMerge)) +} + +// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer +// and sets it as the inner state of the BeaconState type. +func InitializeFromProtoUnsafe(st *ethpb.BeaconStateMerge) (*BeaconState, error) { + if st == nil { + return nil, errors.New("received nil state") + } + + fieldCount := params.BeaconConfig().BeaconStateMergeFieldCount + b := &BeaconState{ + state: st, + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), + } + + var err error + for i := 0; i < fieldCount; i++ { + b.dirtyFields[types.FieldIndex(i)] = true + b.rebuildTrie[types.FieldIndex(i)] = true + b.dirtyIndices[types.FieldIndex(i)] = []uint64{} + b.stateFieldLeaves[types.FieldIndex(i)], err = fieldtrie.NewFieldTrie(types.FieldIndex(i), types.BasicArray, nil, 0) + if err != nil { + return nil, err + } + } + + // Initialize field reference tracking for shared data. + b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.sharedFieldReferences[balances] = stateutil.NewRef(1) + b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[latestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Merge. + sharedstate.StateCount.Inc() + return b, nil +} + +// Copy returns a deep copy of the beacon state. +func (b *BeaconState) Copy() state.BeaconState { + if !b.hasInnerState() { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + fieldCount := params.BeaconConfig().BeaconStateMergeFieldCount + + dst := &BeaconState{ + state: ðpb.BeaconStateMerge{ + // Primitive types, safe to copy. + GenesisTime: b.state.GenesisTime, + Slot: b.state.Slot, + Eth1DepositIndex: b.state.Eth1DepositIndex, + + // Large arrays, infrequently changed, constant size. + RandaoMixes: b.state.RandaoMixes, + StateRoots: b.state.StateRoots, + BlockRoots: b.state.BlockRoots, + Slashings: b.state.Slashings, + Eth1DataVotes: b.state.Eth1DataVotes, + + // Large arrays, increases over time. + Validators: b.state.Validators, + Balances: b.state.Balances, + HistoricalRoots: b.state.HistoricalRoots, + PreviousEpochParticipation: b.state.PreviousEpochParticipation, + CurrentEpochParticipation: b.state.CurrentEpochParticipation, + InactivityScores: b.state.InactivityScores, + + // Everything else, too small to be concerned about, constant size. + Fork: b.fork(), + LatestBlockHeader: b.latestBlockHeader(), + Eth1Data: b.eth1Data(), + JustificationBits: b.justificationBits(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), + FinalizedCheckpoint: b.finalizedCheckpoint(), + GenesisValidatorsRoot: b.genesisValidatorRoot(), + CurrentSyncCommittee: b.currentSyncCommittee(), + NextSyncCommittee: b.nextSyncCommittee(), + LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader(), + }, + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + + // Copy on write validator index map. + valMapHandler: b.valMapHandler, + } + + for field, ref := range b.sharedFieldReferences { + ref.AddRef() + dst.sharedFieldReferences[field] = ref + } + + // Increment ref for validator map + b.valMapHandler.AddRef() + + for i := range b.dirtyFields { + dst.dirtyFields[i] = true + } + + for i := range b.dirtyIndices { + indices := make([]uint64, len(b.dirtyIndices[i])) + copy(indices, b.dirtyIndices[i]) + dst.dirtyIndices[i] = indices + } + + for i := range b.rebuildTrie { + dst.rebuildTrie[i] = true + } + + for fldIdx, fieldTrie := range b.stateFieldLeaves { + dst.stateFieldLeaves[fldIdx] = fieldTrie + if fieldTrie.FieldReference() != nil { + fieldTrie.Lock() + fieldTrie.FieldReference().AddRef() + fieldTrie.Unlock() + } + } + + if b.merkleLayers != nil { + dst.merkleLayers = make([][][]byte, len(b.merkleLayers)) + for i, layer := range b.merkleLayers { + dst.merkleLayers[i] = make([][]byte, len(layer)) + for j, content := range layer { + dst.merkleLayers[i][j] = make([]byte, len(content)) + copy(dst.merkleLayers[i][j], content) + } + } + } + sharedstate.StateCount.Inc() + // Finalizer runs when dst is being destroyed in garbage collection. + runtime.SetFinalizer(dst, func(b *BeaconState) { + for field, v := range b.sharedFieldReferences { + v.MinusRef() + if b.stateFieldLeaves[field].FieldReference() != nil { + b.stateFieldLeaves[field].FieldReference().MinusRef() + } + } + for i := 0; i < fieldCount; i++ { + field := types.FieldIndex(i) + delete(b.stateFieldLeaves, field) + delete(b.dirtyIndices, field) + delete(b.dirtyFields, field) + delete(b.sharedFieldReferences, field) + delete(b.stateFieldLeaves, field) + } + sharedstate.StateCount.Sub(1) + }) + + return dst +} + +// HashTreeRoot of the beacon state retrieves the Merkle root of the trie +// representation of the beacon state based on the eth2 Simple Serialize specification. +func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { + _, span := trace.StartSpan(ctx, "BeaconStateMerge.HashTreeRoot") + defer span.End() + + b.lock.Lock() + defer b.lock.Unlock() + + if b.merkleLayers == nil || len(b.merkleLayers) == 0 { + fieldRoots, err := computeFieldRoots(ctx, b.state) + if err != nil { + return [32]byte{}, err + } + layers := stateutil.Merkleize(fieldRoots) + b.merkleLayers = layers + b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateMergeFieldCount) + } + + for field := range b.dirtyFields { + root, err := b.rootSelector(field) + if err != nil { + return [32]byte{}, err + } + b.merkleLayers[0][field] = root[:] + b.recomputeRoot(int(field)) + delete(b.dirtyFields, field) + } + return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil +} + +// FieldReferencesCount returns the reference count held by each field. This +// also includes the field trie held by each field. +func (b *BeaconState) FieldReferencesCount() map[string]uint64 { + refMap := make(map[string]uint64) + b.lock.RLock() + defer b.lock.RUnlock() + for i, f := range b.sharedFieldReferences { + refMap[i.String(b.Version())] = uint64(f.Refs()) + } + for i, f := range b.stateFieldLeaves { + numOfRefs := uint64(f.FieldReference().Refs()) + f.RLock() + if !f.Empty() { + refMap[i.String(b.Version())+"_trie"] = numOfRefs + } + f.RUnlock() + } + return refMap +} + +// IsNil checks if the state and the underlying proto +// object are nil. +func (b *BeaconState) IsNil() bool { + return b == nil || b.state == nil +} + +func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { + hasher := hash.CustomSHA256Hasher() + switch field { + case genesisTime: + return ssz.Uint64Root(b.state.GenesisTime), nil + case genesisValidatorRoot: + return bytesutil.ToBytes32(b.state.GenesisValidatorsRoot), nil + case slot: + return ssz.Uint64Root(uint64(b.state.Slot)), nil + case eth1DepositIndex: + return ssz.Uint64Root(b.state.Eth1DepositIndex), nil + case fork: + return ssz.ForkRoot(b.state.Fork) + case latestBlockHeader: + return stateutil.BlockHeaderRoot(b.state.LatestBlockHeader) + case blockRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.BlockRoots, fieldparams.BlockRootsLength) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[field] = []uint64{} + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(blockRoots, b.state.BlockRoots) + case stateRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.StateRoots, fieldparams.StateRootsLength) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[field] = []uint64{} + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(stateRoots, b.state.StateRoots) + case historicalRoots: + return ssz.ByteArrayRootWithLimit(b.state.HistoricalRoots, fieldparams.HistoricalRootsLength) + case eth1Data: + return stateutil.Eth1Root(hasher, b.state.Eth1Data) + case eth1DataVotes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.state.Eth1DataVotes, + fieldparams.Eth1DataVotesLength, + ) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[field] = []uint64{} + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.state.Eth1DataVotes) + case validators: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.Validators, fieldparams.ValidatorRegistryLimit) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[validators] = []uint64{} + delete(b.rebuildTrie, validators) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(validators, b.state.Validators) + case balances: + return stateutil.Uint64ListRootWithRegistryLimit(b.state.Balances) + case randaoMixes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.state.RandaoMixes, fieldparams.RandaoMixesLength) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[field] = []uint64{} + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(randaoMixes, b.state.RandaoMixes) + case slashings: + return ssz.SlashingsRoot(b.state.Slashings) + case previousEpochParticipationBits: + return stateutil.ParticipationBitsRoot(b.state.PreviousEpochParticipation) + case currentEpochParticipationBits: + return stateutil.ParticipationBitsRoot(b.state.CurrentEpochParticipation) + case justificationBits: + return bytesutil.ToBytes32(b.state.JustificationBits), nil + case previousJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.PreviousJustifiedCheckpoint) + case currentJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.CurrentJustifiedCheckpoint) + case finalizedCheckpoint: + return ssz.CheckpointRoot(hasher, b.state.FinalizedCheckpoint) + case inactivityScores: + return stateutil.Uint64ListRootWithRegistryLimit(b.state.InactivityScores) + case currentSyncCommittee: + return stateutil.SyncCommitteeRoot(b.state.CurrentSyncCommittee) + case nextSyncCommittee: + return stateutil.SyncCommitteeRoot(b.state.NextSyncCommittee) + case latestExecutionPayloadHeader: + return b.state.LatestExecutionPayloadHeader.HashTreeRoot() + } + return [32]byte{}, errors.New("invalid field index provided") +} + +func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interface{}) ([32]byte, error) { + fTrie := b.stateFieldLeaves[index] + if fTrie.FieldReference().Refs() > 1 { + fTrie.Lock() + defer fTrie.Unlock() + fTrie.FieldReference().MinusRef() + newTrie := fTrie.CopyTrie() + b.stateFieldLeaves[index] = newTrie + fTrie = newTrie + } + // remove duplicate indexes + b.dirtyIndices[index] = slice.SetUint64(b.dirtyIndices[index]) + // sort indexes again + sort.Slice(b.dirtyIndices[index], func(i int, j int) bool { + return b.dirtyIndices[index][i] < b.dirtyIndices[index][j] + }) + root, err := fTrie.RecomputeTrie(b.dirtyIndices[index], elements) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[index] = []uint64{} + return root, nil +} + +func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{}, length uint64) error { + fTrie, err := fieldtrie.NewFieldTrie(index, fieldMap[index], elements, length) + if err != nil { + return err + } + b.stateFieldLeaves[index] = fTrie + b.dirtyIndices[index] = []uint64{} + return nil +} diff --git a/beacon-chain/state/v3/state_trie_test.go b/beacon-chain/state-proto/v3/state_trie_test.go similarity index 98% rename from beacon-chain/state/v3/state_trie_test.go rename to beacon-chain/state-proto/v3/state_trie_test.go index 0c5dc67343..62b5282264 100644 --- a/beacon-chain/state/v3/state_trie_test.go +++ b/beacon-chain/state-proto/v3/state_trie_test.go @@ -5,7 +5,7 @@ import ( "sync" "testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" "github.com/prysmaticlabs/prysm/config/features" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/state-proto/v3/types.go b/beacon-chain/state-proto/v3/types.go new file mode 100644 index 0000000000..9b16629ad4 --- /dev/null +++ b/beacon-chain/state-proto/v3/types.go @@ -0,0 +1,77 @@ +package v3 + +import ( + "sync" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/types" + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +func init() { + fieldMap = make(map[types.FieldIndex]types.DataType, params.BeaconConfig().BeaconStateMergeFieldCount) + + // Initialize the fixed sized arrays. + fieldMap[types.BlockRoots] = types.BasicArray + fieldMap[types.StateRoots] = types.BasicArray + fieldMap[types.RandaoMixes] = types.BasicArray + + // Initialize the composite arrays. + fieldMap[types.Eth1DataVotes] = types.CompositeArray + fieldMap[types.Validators] = types.CompositeArray + fieldMap[types.Balances] = types.CompressedArray +} + +// Field Aliases for values from the types package. +const ( + genesisTime = types.GenesisTime + genesisValidatorRoot = types.GenesisValidatorRoot + slot = types.Slot + fork = types.Fork + latestBlockHeader = types.LatestBlockHeader + blockRoots = types.BlockRoots + stateRoots = types.StateRoots + historicalRoots = types.HistoricalRoots + eth1Data = types.Eth1Data + eth1DataVotes = types.Eth1DataVotes + eth1DepositIndex = types.Eth1DepositIndex + validators = types.Validators + balances = types.Balances + randaoMixes = types.RandaoMixes + slashings = types.Slashings + previousEpochParticipationBits = types.PreviousEpochParticipationBits + currentEpochParticipationBits = types.CurrentEpochParticipationBits + justificationBits = types.JustificationBits + previousJustifiedCheckpoint = types.PreviousJustifiedCheckpoint + currentJustifiedCheckpoint = types.CurrentJustifiedCheckpoint + finalizedCheckpoint = types.FinalizedCheckpoint + inactivityScores = types.InactivityScores + currentSyncCommittee = types.CurrentSyncCommittee + nextSyncCommittee = types.NextSyncCommittee + latestExecutionPayloadHeader = types.LatestExecutionPayloadHeader +) + +// fieldMap keeps track of each field +// to its corresponding data type. +var fieldMap map[types.FieldIndex]types.DataType + +// ErrNilInnerState returns when the inner state is nil and no copy set or get +// operations can be performed on state. +var ErrNilInnerState = errors.New("nil inner state") + +// BeaconState defines a struct containing utilities for the eth2 chain state, defining +// getters and setters for its respective values and helpful functions such as HashTreeRoot(). +type BeaconState struct { + state *ethpb.BeaconStateMerge + lock sync.RWMutex + dirtyFields map[types.FieldIndex]bool + dirtyIndices map[types.FieldIndex][]uint64 + stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie + rebuildTrie map[types.FieldIndex]bool + valMapHandler *stateutil.ValidatorMapHandler + merkleLayers [][][]byte + sharedFieldReferences map[types.FieldIndex]*stateutil.Reference +} diff --git a/beacon-chain/sync/BUILD.bazel b/beacon-chain/sync/BUILD.bazel index 88a9a0ff56..388e97c651 100644 --- a/beacon-chain/sync/BUILD.bazel +++ b/beacon-chain/sync/BUILD.bazel @@ -76,8 +76,8 @@ go_library( "//beacon-chain/p2p/encoder:go_default_library", "//beacon-chain/p2p/peers:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//cache/lru:go_default_library", "//cmd/beacon-chain/flags:go_default_library", "//config/features:go_default_library", @@ -184,9 +184,9 @@ go_test( "//beacon-chain/p2p/peers:go_default_library", "//beacon-chain/p2p/testing:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library", "//cache/lru:go_default_library", "//cmd/beacon-chain/flags:go_default_library", diff --git a/beacon-chain/sync/initial-sync/BUILD.bazel b/beacon-chain/sync/initial-sync/BUILD.bazel index f89d7750ea..080d1b0db8 100644 --- a/beacon-chain/sync/initial-sync/BUILD.bazel +++ b/beacon-chain/sync/initial-sync/BUILD.bazel @@ -68,8 +68,8 @@ go_test( "//beacon-chain/p2p/peers:go_default_library", "//beacon-chain/p2p/testing:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//beacon-chain/sync:go_default_library", "//cmd/beacon-chain/flags:go_default_library", "//config/features:go_default_library", diff --git a/beacon-chain/sync/options.go b/beacon-chain/sync/options.go index b05a905e71..003165dae8 100644 --- a/beacon-chain/sync/options.go +++ b/beacon-chain/sync/options.go @@ -11,7 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee" "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" ) type Option func(s *Service) error diff --git a/beacon-chain/sync/pending_attestations_queue_test.go b/beacon-chain/sync/pending_attestations_queue_test.go index 476fb5a843..9f4ab1fecf 100644 --- a/beacon-chain/sync/pending_attestations_queue_test.go +++ b/beacon-chain/sync/pending_attestations_queue_test.go @@ -83,8 +83,7 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) { assert.NoError(t, err) attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee) require.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() - attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) assert.NoError(t, err) @@ -195,8 +194,7 @@ func TestProcessPendingAtts_NoBroadcastWithBadSignature(t *testing.T) { assert.NoError(t, err) attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee) require.NoError(t, err) - gvr := s.GenesisValidatorRoot() - attesterDomain, err := signing.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + attesterDomain, err := signing.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, s.GenesisValidatorRoot()) require.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) assert.NoError(t, err) @@ -269,8 +267,7 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) { assert.NoError(t, err) attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee) require.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() - attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) assert.NoError(t, err) diff --git a/beacon-chain/sync/pending_blocks_queue_test.go b/beacon-chain/sync/pending_blocks_queue_test.go index 6110ebad43..c4627939c7 100644 --- a/beacon-chain/sync/pending_blocks_queue_test.go +++ b/beacon-chain/sync/pending_blocks_queue_test.go @@ -19,7 +19,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers" p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/rand" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/sync/rpc_status_test.go b/beacon-chain/sync/rpc_status_test.go index f171e3e253..ac2697bf7a 100644 --- a/beacon-chain/sync/rpc_status_test.go +++ b/beacon-chain/sync/rpc_status_test.go @@ -19,7 +19,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers" p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/sync/service.go b/beacon-chain/sync/service.go index 6eb094462c..9c2d071e29 100644 --- a/beacon-chain/sync/service.go +++ b/beacon-chain/sync/service.go @@ -29,7 +29,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee" "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" "github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/sync/service_test.go b/beacon-chain/sync/service_test.go index 7f6b2368f4..98263c55d3 100644 --- a/beacon-chain/sync/service_test.go +++ b/beacon-chain/sync/service_test.go @@ -12,7 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/beacon-chain/sync/subscriber_beacon_blocks_test.go b/beacon-chain/sync/subscriber_beacon_blocks_test.go index 10dbf54438..f10a3c5038 100644 --- a/beacon-chain/sync/subscriber_beacon_blocks_test.go +++ b/beacon-chain/sync/subscriber_beacon_blocks_test.go @@ -58,7 +58,7 @@ func TestService_beaconBlockSubscriber(t *testing.T) { check func(*testing.T, *Service) }{ { - name: "valid block", + name: "invalid block does not remove attestations", args: args{ msg: func() *ethpb.SignedBeaconBlock { b := util.NewBeaconBlock() @@ -66,6 +66,7 @@ func TestService_beaconBlockSubscriber(t *testing.T) { return b }(), }, + wantedErr: "nil inner state", check: func(t *testing.T, s *Service) { if s.cfg.attPool.AggregatedAttestationCount() != 0 { t.Error("Expected no attestation in the pool") diff --git a/beacon-chain/sync/validate_aggregate_proof.go b/beacon-chain/sync/validate_aggregate_proof.go index 415e389d20..d4c1245b75 100644 --- a/beacon-chain/sync/validate_aggregate_proof.go +++ b/beacon-chain/sync/validate_aggregate_proof.go @@ -14,7 +14,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -293,8 +293,7 @@ func validateSelectionIndex( return nil, err } - gvRoot := bs.GenesisValidatorRoot() - d, err := signing.Domain(bs.Fork(), epoch, domain, gvRoot[:]) + d, err := signing.Domain(bs.Fork(), epoch, domain, bs.GenesisValidatorRoot()) if err != nil { return nil, err } @@ -322,8 +321,7 @@ func aggSigSet(s state.ReadOnlyBeaconState, a *ethpb.SignedAggregateAttestationA } epoch := slots.ToEpoch(a.Message.Aggregate.Data.Slot) - gvRoot := s.GenesisValidatorRoot() - d, err := signing.Domain(s.Fork(), epoch, params.BeaconConfig().DomainAggregateAndProof, gvRoot[:]) + d, err := signing.Domain(s.Fork(), epoch, params.BeaconConfig().DomainAggregateAndProof, s.GenesisValidatorRoot()) if err != nil { return nil, err } diff --git a/beacon-chain/sync/validate_aggregate_proof_test.go b/beacon-chain/sync/validate_aggregate_proof_test.go index 105e808520..76691467a8 100644 --- a/beacon-chain/sync/validate_aggregate_proof_test.go +++ b/beacon-chain/sync/validate_aggregate_proof_test.go @@ -330,8 +330,7 @@ func TestValidateAggregateAndProof_CanValidate(t *testing.T) { attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee) require.NoError(t, err) assert.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() - attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) assert.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) assert.NoError(t, err) @@ -425,8 +424,7 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) { require.NoError(t, err) attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee) require.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() - attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) require.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) assert.NoError(t, err) @@ -539,8 +537,7 @@ func TestValidateAggregateAndProof_BadBlock(t *testing.T) { attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee) require.NoError(t, err) assert.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() - attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) assert.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) assert.NoError(t, err) @@ -631,8 +628,7 @@ func TestValidateAggregateAndProof_RejectWhenAttEpochDoesntEqualTargetEpoch(t *t attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee) require.NoError(t, err) assert.NoError(t, err) - gvr := beaconState.GenesisValidatorRoot() - attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) assert.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) assert.NoError(t, err) diff --git a/beacon-chain/sync/validate_attester_slashing_test.go b/beacon-chain/sync/validate_attester_slashing_test.go index b9f9d3b397..ca68fe9e16 100644 --- a/beacon-chain/sync/validate_attester_slashing_test.go +++ b/beacon-chain/sync/validate_attester_slashing_test.go @@ -15,7 +15,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -39,8 +39,7 @@ func setupValidAttesterSlashing(t *testing.T) (*ethpb.AttesterSlashing, state.Be }, AttestingIndices: []uint64{0, 1}, }) - gvr := state.GenesisValidatorRoot() - domain, err := signing.Domain(state.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(state.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, state.GenesisValidatorRoot()) require.NoError(t, err) hashTreeRoot, err := signing.ComputeSigningRoot(att1.Data, domain) assert.NoError(t, err) diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index a33f267230..c893288332 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -15,7 +15,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/monitoring/tracing" diff --git a/beacon-chain/sync/validate_beacon_attestation_test.go b/beacon-chain/sync/validate_beacon_attestation_test.go index 8c04357c79..83f5b03f91 100644 --- a/beacon-chain/sync/validate_beacon_attestation_test.go +++ b/beacon-chain/sync/validate_beacon_attestation_test.go @@ -258,8 +258,7 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { if tt.validAttestationSignature { com, err := helpers.BeaconCommitteeFromState(context.Background(), savedState, tt.msg.Data.Slot, tt.msg.Data.CommitteeIndex) require.NoError(t, err) - gvr := savedState.GenesisValidatorRoot() - domain, err := signing.Domain(savedState.Fork(), tt.msg.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, gvr[:]) + domain, err := signing.Domain(savedState.Fork(), tt.msg.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorRoot()) require.NoError(t, err) attRoot, err := signing.ComputeSigningRoot(tt.msg.Data, domain) require.NoError(t, err) diff --git a/beacon-chain/sync/validate_beacon_blocks_test.go b/beacon-chain/sync/validate_beacon_blocks_test.go index 46948b9cdf..e434097f15 100644 --- a/beacon-chain/sync/validate_beacon_blocks_test.go +++ b/beacon-chain/sync/validate_beacon_blocks_test.go @@ -23,7 +23,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" diff --git a/beacon-chain/sync/validate_proposer_slashing_test.go b/beacon-chain/sync/validate_proposer_slashing_test.go index 21421d5616..7cf5b86371 100644 --- a/beacon-chain/sync/validate_proposer_slashing_test.go +++ b/beacon-chain/sync/validate_proposer_slashing_test.go @@ -17,8 +17,8 @@ import ( coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" "github.com/prysmaticlabs/prysm/config/params" diff --git a/beacon-chain/sync/validate_sync_committee_message_test.go b/beacon-chain/sync/validate_sync_committee_message_test.go index 9ac6b13a71..ea65558128 100644 --- a/beacon-chain/sync/validate_sync_committee_message_test.go +++ b/beacon-chain/sync/validate_sync_committee_message_test.go @@ -19,7 +19,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder" mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -319,8 +319,7 @@ func TestService_ValidateSyncCommitteeMessage(t *testing.T) { msg.ValidatorIndex = types.ValidatorIndex(chosenVal) msg.Slot = slots.PrevSlot(hState.Slot()) - gvr := hState.GenesisValidatorRoot() - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, hState.GenesisValidatorRoot()) assert.NoError(t, err) subCommitteeSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount s.cfg.chain = &mockChain.ChainService{ @@ -371,8 +370,7 @@ func TestService_ValidateSyncCommitteeMessage(t *testing.T) { numOfVals := hState.NumValidators() chosenVal := numOfVals - 10 - gvr := hState.GenesisValidatorRoot() - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, hState.GenesisValidatorRoot()) assert.NoError(t, err) rawBytes := p2ptypes.SSZBytes(headRoot[:]) sigRoot, err := signing.ComputeSigningRoot(&rawBytes, d) diff --git a/beacon-chain/sync/validate_sync_contribution_proof_test.go b/beacon-chain/sync/validate_sync_contribution_proof_test.go index eef94e0c91..74a71d3aa5 100644 --- a/beacon-chain/sync/validate_sync_contribution_proof_test.go +++ b/beacon-chain/sync/validate_sync_contribution_proof_test.go @@ -24,8 +24,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder" mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -473,7 +473,7 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { } } gvr := hState.GenesisValidatorRoot() - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr) require.NoError(t, err) subCommitteeSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount s.cfg.chain = &mockChain.ChainService{ @@ -550,7 +550,7 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { msg.Signature = infiniteSig[:] gvr := hState.GenesisValidatorRoot() - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr) assert.NoError(t, err) sigRoot, err := signing.ComputeSigningRoot(msg.Message, d) assert.NoError(t, err) @@ -608,7 +608,7 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { sc, err := hState.CurrentSyncCommittee() assert.NoError(t, err) gvr := hState.GenesisValidatorRoot() - cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr[:]) + cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr) assert.NoError(t, err) for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { coms, err := altair.SyncSubCommitteePubkeys(sc, types.CommitteeIndex(i)) @@ -640,7 +640,7 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { } } - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr) require.NoError(t, err) subCommitteeSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount s.cfg.chain = &mockChain.ChainService{ @@ -693,9 +693,9 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { sc, err := hState.CurrentSyncCommittee() assert.NoError(t, err) gvr := hState.GenesisValidatorRoot() - cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr[:]) + cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr) assert.NoError(t, err) - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr) assert.NoError(t, err) var pubkeys [][]byte for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { @@ -736,7 +736,7 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { } } - pd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr[:]) + pd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr) require.NoError(t, err) subCommitteeSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount s.cfg.chain = &mockChain.ChainService{ @@ -790,9 +790,9 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { sc, err := hState.CurrentSyncCommittee() assert.NoError(t, err) gvr := hState.GenesisValidatorRoot() - cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr[:]) + cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr) assert.NoError(t, err) - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr) assert.NoError(t, err) var pubkeys [][]byte for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { @@ -835,7 +835,7 @@ func TestService_ValidateSyncContributionAndProof(t *testing.T) { } } - pd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr[:]) + pd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr) require.NoError(t, err) subCommitteeSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount s.cfg.chain = &mockChain.ChainService{ @@ -937,9 +937,9 @@ func TestService_ValidateSyncContributionAndProof_Broadcast(t *testing.T) { sc, err := hState.CurrentSyncCommittee() assert.NoError(t, err) gvr := hState.GenesisValidatorRoot() - cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr[:]) + cd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainContributionAndProof, gvr) assert.NoError(t, err) - d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr[:]) + d, err := signing.Domain(hState.Fork(), slots.ToEpoch(hState.Slot()), params.BeaconConfig().DomainSyncCommittee, gvr) assert.NoError(t, err) var pubkeys [][]byte for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { @@ -980,7 +980,7 @@ func TestService_ValidateSyncContributionAndProof_Broadcast(t *testing.T) { } } - pd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr[:]) + pd, err := signing.Domain(hState.Fork(), slots.ToEpoch(slots.PrevSlot(hState.Slot())), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr) require.NoError(t, err) subCommitteeSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount s.cfg.chain = &mockChain.ChainService{ @@ -1060,8 +1060,7 @@ func fillUpBlocksAndState(ctx context.Context, t *testing.T, beaconDB db.Databas } func syncSelectionProofSigningRoot(st state.BeaconState, slot types.Slot, comIdx types.CommitteeIndex) ([32]byte, error) { - gvr := st.GenesisValidatorRoot() - dom, err := signing.Domain(st.Fork(), slots.ToEpoch(slot), params.BeaconConfig().DomainSyncCommitteeSelectionProof, gvr[:]) + dom, err := signing.Domain(st.Fork(), slots.ToEpoch(slot), params.BeaconConfig().DomainSyncCommitteeSelectionProof, st.GenesisValidatorRoot()) if err != nil { return [32]byte{}, err } diff --git a/beacon-chain/sync/validate_voluntary_exit.go b/beacon-chain/sync/validate_voluntary_exit.go index e0474c2e06..00d954f8db 100644 --- a/beacon-chain/sync/validate_voluntary_exit.go +++ b/beacon-chain/sync/validate_voluntary_exit.go @@ -62,8 +62,7 @@ func (s *Service) validateVoluntaryExit(ctx context.Context, pid peer.ID, msg *p if err != nil { return pubsub.ValidationIgnore, err } - gvRoot := headState.GenesisValidatorRoot() - if err := blocks.VerifyExitAndSignature(val, headState.Slot(), headState.Fork(), exit, gvRoot[:]); err != nil { + if err := blocks.VerifyExitAndSignature(val, headState.Slot(), headState.Fork(), exit, headState.GenesisValidatorRoot()); err != nil { return pubsub.ValidationReject, err } diff --git a/beacon-chain/sync/validate_voluntary_exit_test.go b/beacon-chain/sync/validate_voluntary_exit_test.go index 5f3eabc63f..f2749b258a 100644 --- a/beacon-chain/sync/validate_voluntary_exit_test.go +++ b/beacon-chain/sync/validate_voluntary_exit_test.go @@ -17,8 +17,8 @@ import ( coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" "github.com/prysmaticlabs/prysm/config/params" diff --git a/encoding/bytesutil/bytes.go b/encoding/bytesutil/bytes.go index c3733282f9..e3ec106ffb 100644 --- a/encoding/bytesutil/bytes.go +++ b/encoding/bytesutil/bytes.go @@ -3,6 +3,7 @@ package bytesutil import ( "encoding/binary" + "fmt" "math/bits" "regexp" @@ -378,3 +379,17 @@ func IsHex(b []byte) bool { } return hexRegex.Match(b) } + +// SafeCopyRootAtIndex takes a copy of an 32-byte slice in a slice of byte slices. Returns error if index out of range. +func SafeCopyRootAtIndex(input [][]byte, idx uint64) ([]byte, error) { + if input == nil { + return nil, nil + } + + if uint64(len(input)) <= idx { + return nil, fmt.Errorf("index %d out of range", idx) + } + item := make([]byte, 32) + copy(item, input[idx]) + return item, nil +} diff --git a/nogo_config.json b/nogo_config.json index d6299096ff..23184ce6c9 100644 --- a/nogo_config.json +++ b/nogo_config.json @@ -140,9 +140,12 @@ "validator/.*": "" }, "exclude_files": { - "beacon-chain/state/v1/generated.ssz.go": "Exclude generated SSZ file", - "beacon-chain/state/v2/generated.ssz.go": "Exclude generated SSZ file", - "beacon-chain/state/v3/generated.ssz.go": "Exclude generated SSZ file" + "beacon-chain/state-native/v1/generated.ssz.go": "Exclude generated SSZ file", + "beacon-chain/state-native/v2/generated.ssz.go": "Exclude generated SSZ file", + "beacon-chain/state-native/v3/generated.ssz.go": "Exclude generated SSZ file", + "beacon-chain/state-proto/v1/generated.ssz.go": "Exclude generated SSZ file", + "beacon-chain/state-proto/v2/generated.ssz.go": "Exclude generated SSZ file", + "beacon-chain/state-proto/v3/generated.ssz.go": "Exclude generated SSZ file" } }, "properpermissions": { diff --git a/proto/eth/v1/BUILD.bazel b/proto/eth/v1/BUILD.bazel index 0765b7b2f2..88ed7166ce 100644 --- a/proto/eth/v1/BUILD.bazel +++ b/proto/eth/v1/BUILD.bazel @@ -36,7 +36,7 @@ ssz_gen_marshal( go_proto = ":go_proto", includes = [ "@com_github_prysmaticlabs_eth2_types//:go_default_library", - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", ], objs = [ "AggregateAttestationAndProof", @@ -71,7 +71,7 @@ go_proto_library( proto = ":proto", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", "//proto/eth/ext:go_default_library", "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", "@com_github_golang_protobuf//proto:go_default_library", diff --git a/proto/eth/v2/BUILD.bazel b/proto/eth/v2/BUILD.bazel index 38221842ba..e64d6f6816 100644 --- a/proto/eth/v2/BUILD.bazel +++ b/proto/eth/v2/BUILD.bazel @@ -33,7 +33,7 @@ ssz_gen_marshal( includes = [ "//proto/eth/v1:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", ], objs = [ "SignedBeaconBlockAltair", @@ -50,7 +50,7 @@ go_proto_library( proto = ":proto", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", "//proto/eth/ext:go_default_library", "//proto/eth/v1:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", diff --git a/proto/migration/BUILD.bazel b/proto/migration/BUILD.bazel index e8cfae4846..6d5df903c6 100644 --- a/proto/migration/BUILD.bazel +++ b/proto/migration/BUILD.bazel @@ -10,8 +10,8 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/proto/migration", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/eth/v1:go_default_library", "//proto/eth/v2:go_default_library", @@ -31,7 +31,6 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/eth/v1:go_default_library", diff --git a/proto/migration/v1alpha1_to_v1.go b/proto/migration/v1alpha1_to_v1.go index 80b1698f7a..92e119124d 100644 --- a/proto/migration/v1alpha1_to_v1.go +++ b/proto/migration/v1alpha1_to_v1.go @@ -2,7 +2,7 @@ package migration import ( "github.com/pkg/errors" - statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1" ethpbalpha "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -436,30 +436,9 @@ func BeaconStateToV1(state *statev1.BeaconState) (*ethpbv1.BeaconState, error) { } } - gvr := state.GenesisValidatorRoot() - bRoots := make([][]byte, len(state.BlockRoots())) - for i, r := range state.BlockRoots() { - tmp := r - bRoots[i] = tmp[:] - } - sRoots := make([][]byte, len(state.StateRoots())) - for i, r := range state.StateRoots() { - tmp := r - sRoots[i] = tmp[:] - } - hRoots := make([][]byte, len(state.HistoricalRoots())) - for i, r := range state.HistoricalRoots() { - tmp := r - hRoots[i] = tmp[:] - } - mixes := make([][]byte, len(state.RandaoMixes())) - for i, m := range state.RandaoMixes() { - tmp := m - mixes[i] = tmp[:] - } result := ðpbv1.BeaconState{ GenesisTime: state.GenesisTime(), - GenesisValidatorsRoot: gvr[:], + GenesisValidatorsRoot: state.GenesisValidatorRoot(), Slot: state.Slot(), Fork: ðpbv1.Fork{ PreviousVersion: bytesutil.SafeCopyBytes(sourceFork.PreviousVersion), @@ -473,9 +452,9 @@ func BeaconStateToV1(state *statev1.BeaconState) (*ethpbv1.BeaconState, error) { StateRoot: bytesutil.SafeCopyBytes(sourceLatestBlockHeader.StateRoot), BodyRoot: bytesutil.SafeCopyBytes(sourceLatestBlockHeader.BodyRoot), }, - BlockRoots: bRoots, - StateRoots: sRoots, - HistoricalRoots: hRoots, + BlockRoots: bytesutil.SafeCopy2dBytes(state.BlockRoots()), + StateRoots: bytesutil.SafeCopy2dBytes(state.StateRoots()), + HistoricalRoots: bytesutil.SafeCopy2dBytes(state.HistoricalRoots()), Eth1Data: ðpbv1.Eth1Data{ DepositRoot: bytesutil.SafeCopyBytes(sourceEth1Data.DepositRoot), DepositCount: sourceEth1Data.DepositCount, @@ -485,7 +464,7 @@ func BeaconStateToV1(state *statev1.BeaconState) (*ethpbv1.BeaconState, error) { Eth1DepositIndex: state.Eth1DepositIndex(), Validators: resultValidators, Balances: state.Balances(), - RandaoMixes: mixes, + RandaoMixes: bytesutil.SafeCopy2dBytes(state.RandaoMixes()), Slashings: state.Slashings(), PreviousEpochAttestations: resultPrevEpochAtts, CurrentEpochAttestations: resultCurrEpochAtts, diff --git a/proto/migration/v1alpha1_to_v1_test.go b/proto/migration/v1alpha1_to_v1_test.go index df186eb4b8..9e7c14163a 100644 --- a/proto/migration/v1alpha1_to_v1_test.go +++ b/proto/migration/v1alpha1_to_v1_test.go @@ -5,7 +5,6 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1" @@ -438,39 +437,37 @@ func Test_V1AttestationToV1Alpha1(t *testing.T) { assert.DeepEqual(t, v1Root, v1Alpha1Root) } func TestBeaconStateToV1(t *testing.T) { - source, err := util.NewBeaconState(util.FillRootsNaturalOpt, func(state state.BeaconState) error { - require.NoError(t, state.SetGenesisTime(1)) - require.NoError(t, state.SetGenesisValidatorRoot(bytesutil.ToBytes32([]byte("genesisvalidatorroot")))) - require.NoError(t, state.SetSlot(2)) - require.NoError(t, state.SetFork(ðpbalpha.Fork{ + source, err := util.NewBeaconState(util.FillRootsNaturalOpt, func(state *ethpbalpha.BeaconState) error { + state.GenesisTime = 1 + state.GenesisValidatorsRoot = bytesutil.PadTo([]byte("genesisvalidatorroot"), 32) + state.Slot = 2 + state.Fork = ðpbalpha.Fork{ PreviousVersion: bytesutil.PadTo([]byte("123"), 4), CurrentVersion: bytesutil.PadTo([]byte("456"), 4), Epoch: 3, - })) - require.NoError(t, state.SetLatestBlockHeader(ðpbalpha.BeaconBlockHeader{ + } + state.LatestBlockHeader = ðpbalpha.BeaconBlockHeader{ Slot: 4, ProposerIndex: 5, ParentRoot: bytesutil.PadTo([]byte("lbhparentroot"), 32), StateRoot: bytesutil.PadTo([]byte("lbhstateroot"), 32), BodyRoot: bytesutil.PadTo([]byte("lbhbodyroot"), 32), - })) - bRoots := [fieldparams.BlockRootsLength][32]byte{bytesutil.ToBytes32([]byte("blockroots"))} - require.NoError(t, state.SetBlockRoots(&bRoots)) - sRoots := [fieldparams.StateRootsLength][32]byte{bytesutil.ToBytes32([]byte("stateroots"))} - require.NoError(t, state.SetStateRoots(&sRoots)) - require.NoError(t, state.SetHistoricalRoots([][32]byte{bytesutil.ToBytes32([]byte("historicalroots"))})) - require.NoError(t, state.SetEth1Data(ðpbalpha.Eth1Data{ + } + state.BlockRoots = [][]byte{bytesutil.PadTo([]byte("blockroots"), 32)} + state.StateRoots = [][]byte{bytesutil.PadTo([]byte("stateroots"), 32)} + state.HistoricalRoots = [][]byte{bytesutil.PadTo([]byte("historicalroots"), 32)} + state.Eth1Data = ðpbalpha.Eth1Data{ DepositRoot: bytesutil.PadTo([]byte("e1ddepositroot"), 32), DepositCount: 6, BlockHash: bytesutil.PadTo([]byte("e1dblockhash"), 32), - })) - require.NoError(t, state.SetEth1DataVotes([]*ethpbalpha.Eth1Data{{ + } + state.Eth1DataVotes = []*ethpbalpha.Eth1Data{{ DepositRoot: bytesutil.PadTo([]byte("e1dvdepositroot"), 32), DepositCount: 7, BlockHash: bytesutil.PadTo([]byte("e1dvblockhash"), 32), - }})) - require.NoError(t, state.SetEth1DepositIndex(8)) - require.NoError(t, state.SetValidators([]*ethpbalpha.Validator{{ + }} + state.Eth1DepositIndex = 8 + state.Validators = []*ethpbalpha.Validator{{ PublicKey: bytesutil.PadTo([]byte("publickey"), 48), WithdrawalCredentials: bytesutil.PadTo([]byte("withdrawalcredentials"), 32), EffectiveBalance: 9, @@ -479,12 +476,11 @@ func TestBeaconStateToV1(t *testing.T) { ActivationEpoch: 11, ExitEpoch: 12, WithdrawableEpoch: 13, - }})) - require.NoError(t, state.SetBalances([]uint64{14})) - mixes := [fieldparams.RandaoMixesLength][32]byte{bytesutil.ToBytes32([]byte("randaomixes"))} - require.NoError(t, state.SetRandaoMixes(&mixes)) - require.NoError(t, state.SetSlashings([]uint64{15})) - require.NoError(t, state.AppendPreviousEpochAttestations(ðpbalpha.PendingAttestation{ + }} + state.Balances = []uint64{14} + state.RandaoMixes = [][]byte{bytesutil.PadTo([]byte("randaomixes"), 32)} + state.Slashings = []uint64{15} + state.PreviousEpochAttestations = []*ethpbalpha.PendingAttestation{{ AggregationBits: bitfield.Bitlist{16}, Data: ðpbalpha.AttestationData{ Slot: 17, @@ -501,8 +497,8 @@ func TestBeaconStateToV1(t *testing.T) { }, InclusionDelay: 21, ProposerIndex: 22, - })) - require.NoError(t, state.AppendCurrentEpochAttestations(ðpbalpha.PendingAttestation{ + }} + state.CurrentEpochAttestations = []*ethpbalpha.PendingAttestation{{ AggregationBits: bitfield.Bitlist{23}, Data: ðpbalpha.AttestationData{ Slot: 24, @@ -519,20 +515,20 @@ func TestBeaconStateToV1(t *testing.T) { }, InclusionDelay: 28, ProposerIndex: 29, - })) - require.NoError(t, state.SetJustificationBits(bitfield.Bitvector4{1})) - require.NoError(t, state.SetPreviousJustifiedCheckpoint(ðpbalpha.Checkpoint{ + }} + state.JustificationBits = bitfield.Bitvector4{1} + state.PreviousJustifiedCheckpoint = ðpbalpha.Checkpoint{ Epoch: 30, Root: bytesutil.PadTo([]byte("pjcroot"), 32), - })) - require.NoError(t, state.SetCurrentJustifiedCheckpoint(ðpbalpha.Checkpoint{ + } + state.CurrentJustifiedCheckpoint = ðpbalpha.Checkpoint{ Epoch: 31, Root: bytesutil.PadTo([]byte("cjcroot"), 32), - })) - require.NoError(t, state.SetFinalizedCheckpoint(ðpbalpha.Checkpoint{ + } + state.FinalizedCheckpoint = ðpbalpha.Checkpoint{ Epoch: 32, Root: bytesutil.PadTo([]byte("fcroot"), 32), - })) + } return nil }) require.NoError(t, err) @@ -555,18 +551,8 @@ func TestBeaconStateToV1(t *testing.T) { assert.DeepEqual(t, bytesutil.PadTo([]byte("lbhparentroot"), 32), resultLatestBlockHeader.ParentRoot) assert.DeepEqual(t, bytesutil.PadTo([]byte("lbhstateroot"), 32), resultLatestBlockHeader.StateRoot) assert.DeepEqual(t, bytesutil.PadTo([]byte("lbhbodyroot"), 32), resultLatestBlockHeader.BodyRoot) - bRoots := make([][]byte, fieldparams.BlockRootsLength) - for i := 0; i < len(bRoots); i++ { - bRoots[i] = make([]byte, 32) - } - bRoots[0] = bytesutil.PadTo([]byte("blockroots"), 32) - assert.DeepEqual(t, bRoots, result.BlockRoots) - sRoots := make([][]byte, fieldparams.StateRootsLength) - for i := 0; i < len(sRoots); i++ { - sRoots[i] = make([]byte, 32) - } - sRoots[0] = bytesutil.PadTo([]byte("stateroots"), 32) - assert.DeepEqual(t, sRoots, result.StateRoots) + assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("blockroots"), 32)}, result.BlockRoots) + assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("stateroots"), 32)}, result.StateRoots) assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("historicalroots"), 32)}, result.HistoricalRoots) resultEth1Data := result.Eth1Data require.NotNil(t, resultEth1Data) @@ -592,12 +578,7 @@ func TestBeaconStateToV1(t *testing.T) { assert.Equal(t, types.Epoch(12), resultValidator.ExitEpoch) assert.Equal(t, types.Epoch(13), resultValidator.WithdrawableEpoch) assert.DeepEqual(t, []uint64{14}, result.Balances) - mixes := make([][]byte, fieldparams.RandaoMixesLength) - for i := 0; i < len(mixes); i++ { - mixes[i] = make([]byte, 32) - } - mixes[0] = bytesutil.PadTo([]byte("randaomixes"), 32) - assert.DeepEqual(t, mixes, result.RandaoMixes) + assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("randaomixes"), 32)}, result.RandaoMixes) assert.DeepEqual(t, []uint64{15}, result.Slashings) require.Equal(t, 1, len(result.PreviousEpochAttestations)) resultPrevEpochAtt := result.PreviousEpochAttestations[0] diff --git a/proto/migration/v1alpha1_to_v2.go b/proto/migration/v1alpha1_to_v2.go index 64252a5e9f..801404fd54 100644 --- a/proto/migration/v1alpha1_to_v2.go +++ b/proto/migration/v1alpha1_to_v2.go @@ -2,7 +2,7 @@ package migration import ( "github.com/pkg/errors" - statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1" ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2" @@ -89,30 +89,9 @@ func BeaconStateAltairToV2(altairState *statev2.BeaconState) (*ethpbv2.BeaconSta return nil, errors.Wrap(err, "could not get next sync committee") } - gvr := altairState.GenesisValidatorRoot() - bRoots := make([][]byte, len(altairState.BlockRoots())) - for i, r := range altairState.BlockRoots() { - tmp := r - bRoots[i] = tmp[:] - } - sRoots := make([][]byte, len(altairState.StateRoots())) - for i, r := range altairState.StateRoots() { - tmp := r - sRoots[i] = tmp[:] - } - hRoots := make([][]byte, len(altairState.HistoricalRoots())) - for i, r := range altairState.HistoricalRoots() { - tmp := r - hRoots[i] = tmp[:] - } - mixes := make([][]byte, len(altairState.RandaoMixes())) - for i, m := range altairState.RandaoMixes() { - tmp := m - mixes[i] = tmp[:] - } result := ðpbv2.BeaconStateV2{ GenesisTime: altairState.GenesisTime(), - GenesisValidatorsRoot: gvr[:], + GenesisValidatorsRoot: altairState.GenesisValidatorRoot(), Slot: altairState.Slot(), Fork: ðpbv1.Fork{ PreviousVersion: bytesutil.SafeCopyBytes(sourceFork.PreviousVersion), @@ -126,9 +105,9 @@ func BeaconStateAltairToV2(altairState *statev2.BeaconState) (*ethpbv2.BeaconSta StateRoot: bytesutil.SafeCopyBytes(sourceLatestBlockHeader.StateRoot), BodyRoot: bytesutil.SafeCopyBytes(sourceLatestBlockHeader.BodyRoot), }, - BlockRoots: bRoots, - StateRoots: sRoots, - HistoricalRoots: bytesutil.SafeCopy2dBytes(hRoots), + BlockRoots: bytesutil.SafeCopy2dBytes(altairState.BlockRoots()), + StateRoots: bytesutil.SafeCopy2dBytes(altairState.StateRoots()), + HistoricalRoots: bytesutil.SafeCopy2dBytes(altairState.HistoricalRoots()), Eth1Data: ðpbv1.Eth1Data{ DepositRoot: bytesutil.SafeCopyBytes(sourceEth1Data.DepositRoot), DepositCount: sourceEth1Data.DepositCount, @@ -138,7 +117,7 @@ func BeaconStateAltairToV2(altairState *statev2.BeaconState) (*ethpbv2.BeaconSta Eth1DepositIndex: altairState.Eth1DepositIndex(), Validators: resultValidators, Balances: altairState.Balances(), - RandaoMixes: mixes, + RandaoMixes: bytesutil.SafeCopy2dBytes(altairState.RandaoMixes()), Slashings: altairState.Slashings(), PreviousEpochParticipation: bytesutil.SafeCopyBytes(sourcePrevEpochParticipation), CurrentEpochParticipation: bytesutil.SafeCopyBytes(sourceCurrEpochParticipation), diff --git a/proto/prysm/v1alpha1/BUILD.bazel b/proto/prysm/v1alpha1/BUILD.bazel index d0bd0779b6..0e83f210d2 100644 --- a/proto/prysm/v1alpha1/BUILD.bazel +++ b/proto/prysm/v1alpha1/BUILD.bazel @@ -53,7 +53,7 @@ ssz_gen_marshal( go_proto = ":go_proto", includes = [ "@com_github_prysmaticlabs_eth2_types//:go_default_library", - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", ], objs = [ "BeaconBlockAltair", @@ -114,7 +114,7 @@ go_proto_library( proto = ":proto", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", "//proto/eth/ext:go_default_library", "@com_github_golang_protobuf//proto:go_default_library", "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto", diff --git a/proto/testing/BUILD.bazel b/proto/testing/BUILD.bazel index 26d515499c..bdb02996c4 100644 --- a/proto/testing/BUILD.bazel +++ b/proto/testing/BUILD.bazel @@ -52,8 +52,8 @@ go_test( embed = [":go_default_library"], tags = ["spectest"], deps = [ - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//config/fieldparams:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/runtime/interop/BUILD.bazel b/runtime/interop/BUILD.bazel index 83d54479f8..95e8e55428 100644 --- a/runtime/interop/BUILD.bazel +++ b/runtime/interop/BUILD.bazel @@ -12,7 +12,7 @@ go_library( "//async:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", "//crypto/bls:go_default_library", diff --git a/runtime/interop/generate_genesis_state.go b/runtime/interop/generate_genesis_state.go index 75c54b9552..4d18913fb7 100644 --- a/runtime/interop/generate_genesis_state.go +++ b/runtime/interop/generate_genesis_state.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/async" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -65,7 +65,7 @@ func GenerateGenesisStateFromDepositData( return nil, nil, errors.Wrap(err, "could not generate genesis state") } - pbState, err := v1.ProtobufBeaconState(beaconState.ToProto()) + pbState, err := v1.ProtobufBeaconState(beaconState.CloneInnerState()) if err != nil { return nil, nil, err } diff --git a/testing/benchmark/BUILD.bazel b/testing/benchmark/BUILD.bazel index 70120820ad..36ebd4c2d4 100644 --- a/testing/benchmark/BUILD.bazel +++ b/testing/benchmark/BUILD.bazel @@ -7,8 +7,8 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/testing/benchmark", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", diff --git a/testing/benchmark/pregen.go b/testing/benchmark/pregen.go index 286cbde827..61ff0ddb77 100644 --- a/testing/benchmark/pregen.go +++ b/testing/benchmark/pregen.go @@ -7,8 +7,8 @@ import ( "io/ioutil" "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) diff --git a/testing/endtoend/BUILD.bazel b/testing/endtoend/BUILD.bazel index 65ef0b5522..7bbe38b016 100644 --- a/testing/endtoend/BUILD.bazel +++ b/testing/endtoend/BUILD.bazel @@ -33,7 +33,7 @@ go_test( "//beacon-chain/core/transition:go_default_library", "//beacon-chain/db/testing:go_default_library", "//beacon-chain/operations/slashings:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/testing/endtoend/slasher_simulator_e2e_test.go b/testing/endtoend/slasher_simulator_e2e_test.go index 62deb8106d..7ca57bc7ba 100644 --- a/testing/endtoend/slasher_simulator_e2e_test.go +++ b/testing/endtoend/slasher_simulator_e2e_test.go @@ -10,7 +10,7 @@ import ( mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/fuzz/BUILD.bazel b/testing/fuzz/BUILD.bazel index e399a29243..3df76df9e2 100644 --- a/testing/fuzz/BUILD.bazel +++ b/testing/fuzz/BUILD.bazel @@ -15,7 +15,7 @@ ssz_gen_marshal( name = "ssz_generated_files", srcs = ["inputs.go"], includes = [ - "//beacon-chain/state/custom-types:go_default_library", + "//beacon-chain/state-native/custom-types:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", ], @@ -27,7 +27,7 @@ ssz_gen_marshal( IMPORT_PATH = "github.com/prysmaticlabs/prysm/fuzz" COMMON_DEPS = [ - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/features:go_default_library", ] + SSZ_DEPS @@ -85,7 +85,7 @@ go_fuzz_test( "//beacon-chain/p2p:go_default_library", "//beacon-chain/blockchain/testing:go_default_library", "//beacon-chain/cache:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//crypto/rand:go_default_library", ] + COMMON_DEPS, ) @@ -184,8 +184,8 @@ go_library( "//beacon-chain/p2p:go_default_library", "//beacon-chain/p2p/encoder:go_default_library", "//beacon-chain/p2p/testing:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library", "//testing/fuzz/testing:go_default_library", diff --git a/testing/fuzz/block_fuzz.go b/testing/fuzz/block_fuzz.go index 0af7c1d0e9..df27d28ffa 100644 --- a/testing/fuzz/block_fuzz.go +++ b/testing/fuzz/block_fuzz.go @@ -26,8 +26,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/p2p" p2pt "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" powt "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/beacon-chain/sync" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/rand" diff --git a/testing/fuzz/state_fuzz.go b/testing/fuzz/state_fuzz.go index 3c22f02439..1909a4d0ae 100644 --- a/testing/fuzz/state_fuzz.go +++ b/testing/fuzz/state_fuzz.go @@ -5,7 +5,7 @@ import ( "fmt" stateutil "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -43,7 +43,7 @@ func BeaconStateFuzz(input []byte) { } func validateStateHTR(s *v1.BeaconState) { - rawState, ok := s.ToProtoUnsafe().(*ethpb.BeaconState) + rawState, ok := s.InnerStateUnsafe().(*ethpb.BeaconState) if !ok { panic("non valid type assertion") } diff --git a/testing/slasher/simulator/BUILD.bazel b/testing/slasher/simulator/BUILD.bazel index 3565c27463..1f47cae4d1 100644 --- a/testing/slasher/simulator/BUILD.bazel +++ b/testing/slasher/simulator/BUILD.bazel @@ -22,8 +22,8 @@ go_library( "//beacon-chain/db:go_default_library", "//beacon-chain/operations/slashings:go_default_library", "//beacon-chain/slasher:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", @@ -47,7 +47,7 @@ go_test( deps = [ "//beacon-chain/blockchain/testing:go_default_library", "//beacon-chain/db/testing:go_default_library", - "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state-proto/stategen:go_default_library", "//config/params:go_default_library", "//crypto/bls:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/testing/slasher/simulator/attestation_generator.go b/testing/slasher/simulator/attestation_generator.go index d8b2294c1b..90b5c624f1 100644 --- a/testing/slasher/simulator/attestation_generator.go +++ b/testing/slasher/simulator/attestation_generator.go @@ -7,7 +7,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/crypto/rand" @@ -110,12 +110,11 @@ func (s *Simulator) generateAttestationsForSlot( func (s *Simulator) aggregateSigForAttestation( beaconState state.BeaconState, att *ethpb.IndexedAttestation, ) (bls.Signature, error) { - gvRoot := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), att.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, - gvRoot[:], + beaconState.GenesisValidatorRoot(), ) if err != nil { return nil, err diff --git a/testing/slasher/simulator/block_generator.go b/testing/slasher/simulator/block_generator.go index 6a29e6dc87..5d449fa2d7 100644 --- a/testing/slasher/simulator/block_generator.go +++ b/testing/slasher/simulator/block_generator.go @@ -5,7 +5,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/crypto/rand" @@ -72,12 +72,11 @@ func (s *Simulator) signBlockHeader( beaconState state.BeaconState, header *ethpb.SignedBeaconBlockHeader, ) (bls.Signature, error) { - gvRoot := beaconState.GenesisValidatorRoot() domain, err := signing.Domain( beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, - gvRoot[:], + beaconState.GenesisValidatorRoot(), ) if err != nil { return nil, err diff --git a/testing/slasher/simulator/simulator.go b/testing/slasher/simulator/simulator.go index 85c217e4ff..e1e286dbef 100644 --- a/testing/slasher/simulator/simulator.go +++ b/testing/slasher/simulator/simulator.go @@ -13,7 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/beacon-chain/slasher" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/beacon-chain/sync" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/testing/slasher/simulator/simulator_test.go b/testing/slasher/simulator/simulator_test.go index 9aa7c41e3b..eb8732769f 100644 --- a/testing/slasher/simulator/simulator_test.go +++ b/testing/slasher/simulator/simulator_test.go @@ -6,7 +6,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stategen" "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/altair/epoch_processing/BUILD.bazel b/testing/spectest/shared/altair/epoch_processing/BUILD.bazel index 13394f49bd..3f4546e93a 100644 --- a/testing/spectest/shared/altair/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/altair/epoch_processing/BUILD.bazel @@ -24,8 +24,8 @@ go_library( "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/altair/epoch_processing/effective_balance_updates.go b/testing/spectest/shared/altair/epoch_processing/effective_balance_updates.go index 86eae0b877..090f21699e 100644 --- a/testing/spectest/shared/altair/epoch_processing/effective_balance_updates.go +++ b/testing/spectest/shared/altair/epoch_processing/effective_balance_updates.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/eth1_data_reset.go b/testing/spectest/shared/altair/epoch_processing/eth1_data_reset.go index 661e4f7efe..80e846c55a 100644 --- a/testing/spectest/shared/altair/epoch_processing/eth1_data_reset.go +++ b/testing/spectest/shared/altair/epoch_processing/eth1_data_reset.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/helpers.go b/testing/spectest/shared/altair/epoch_processing/helpers.go index ff4444fd1e..eb5ed4269b 100644 --- a/testing/spectest/shared/altair/epoch_processing/helpers.go +++ b/testing/spectest/shared/altair/epoch_processing/helpers.go @@ -8,8 +8,8 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" @@ -59,10 +59,10 @@ func RunEpochOperationTest( t.Fatalf("Failed to unmarshal: %v", err) } - pbState, err := stateAltair.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := stateAltair.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProtoUnsafe(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/altair/epoch_processing/historical_roots_update.go b/testing/spectest/shared/altair/epoch_processing/historical_roots_update.go index 894f1f5da8..09f1be21af 100644 --- a/testing/spectest/shared/altair/epoch_processing/historical_roots_update.go +++ b/testing/spectest/shared/altair/epoch_processing/historical_roots_update.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/inactivity_updates.go b/testing/spectest/shared/altair/epoch_processing/inactivity_updates.go index 44d7ad8d6e..e13d3123a9 100644 --- a/testing/spectest/shared/altair/epoch_processing/inactivity_updates.go +++ b/testing/spectest/shared/altair/epoch_processing/inactivity_updates.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/justification_and_finalization.go b/testing/spectest/shared/altair/epoch_processing/justification_and_finalization.go index 1333351f23..a1a419961b 100644 --- a/testing/spectest/shared/altair/epoch_processing/justification_and_finalization.go +++ b/testing/spectest/shared/altair/epoch_processing/justification_and_finalization.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/participation_flag_updates.go b/testing/spectest/shared/altair/epoch_processing/participation_flag_updates.go index 6332c88896..522ea46253 100644 --- a/testing/spectest/shared/altair/epoch_processing/participation_flag_updates.go +++ b/testing/spectest/shared/altair/epoch_processing/participation_flag_updates.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/randao_mixes_reset.go b/testing/spectest/shared/altair/epoch_processing/randao_mixes_reset.go index a7cfb8020f..e2e622eeaa 100644 --- a/testing/spectest/shared/altair/epoch_processing/randao_mixes_reset.go +++ b/testing/spectest/shared/altair/epoch_processing/randao_mixes_reset.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/registry_updates.go b/testing/spectest/shared/altair/epoch_processing/registry_updates.go index b0c3e59f1e..a6f4034c38 100644 --- a/testing/spectest/shared/altair/epoch_processing/registry_updates.go +++ b/testing/spectest/shared/altair/epoch_processing/registry_updates.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/rewards_and_penalties.go b/testing/spectest/shared/altair/epoch_processing/rewards_and_penalties.go index 48a95a0dd8..74fd340a51 100644 --- a/testing/spectest/shared/altair/epoch_processing/rewards_and_penalties.go +++ b/testing/spectest/shared/altair/epoch_processing/rewards_and_penalties.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/epoch_processing/slashings.go b/testing/spectest/shared/altair/epoch_processing/slashings.go index 617eca09b7..c4b48661cd 100644 --- a/testing/spectest/shared/altair/epoch_processing/slashings.go +++ b/testing/spectest/shared/altair/epoch_processing/slashings.go @@ -6,7 +6,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" diff --git a/testing/spectest/shared/altair/epoch_processing/slashings_reset.go b/testing/spectest/shared/altair/epoch_processing/slashings_reset.go index 459925f3d4..b4c0ea8c92 100644 --- a/testing/spectest/shared/altair/epoch_processing/slashings_reset.go +++ b/testing/spectest/shared/altair/epoch_processing/slashings_reset.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/altair/finality/BUILD.bazel b/testing/spectest/shared/altair/finality/BUILD.bazel index 07a6795cef..ab95ec16bc 100644 --- a/testing/spectest/shared/altair/finality/BUILD.bazel +++ b/testing/spectest/shared/altair/finality/BUILD.bazel @@ -9,8 +9,8 @@ go_library( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/altair/finality/finality.go b/testing/spectest/shared/altair/finality/finality.go index 24905fd083..5c4031281f 100644 --- a/testing/spectest/shared/altair/finality/finality.go +++ b/testing/spectest/shared/altair/finality/finality.go @@ -8,8 +8,8 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/require" @@ -73,7 +73,7 @@ func RunFinalityTest(t *testing.T, config string) { require.NoError(t, err, "Failed to decompress") postBeaconState := ðpb.BeaconStateAltair{} require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := stateAltair.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := stateAltair.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { t.Fatal("Post state does not match expected") diff --git a/testing/spectest/shared/altair/fork/BUILD.bazel b/testing/spectest/shared/altair/fork/BUILD.bazel index 7f6d94e58a..bb2006f971 100644 --- a/testing/spectest/shared/altair/fork/BUILD.bazel +++ b/testing/spectest/shared/altair/fork/BUILD.bazel @@ -13,9 +13,9 @@ go_library( "//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", diff --git a/testing/spectest/shared/altair/fork/transition.go b/testing/spectest/shared/altair/fork/transition.go index 006f427689..877b875a07 100644 --- a/testing/spectest/shared/altair/fork/transition.go +++ b/testing/spectest/shared/altair/fork/transition.go @@ -9,9 +9,9 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" "github.com/prysmaticlabs/prysm/config/params" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" @@ -122,7 +122,7 @@ func RunForkTransitionTest(t *testing.T, config string) { postBeaconState := ðpb.BeaconStateAltair{} require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := stateAltair.ProtobufBeaconState(altairState.ToProto()) + pbState, err := stateAltair.ProtobufBeaconState(altairState.CloneInnerState()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { t.Fatal("Post state does not match expected") diff --git a/testing/spectest/shared/altair/fork/upgrade_to_altair.go b/testing/spectest/shared/altair/fork/upgrade_to_altair.go index 9f2a08f374..23847691c2 100644 --- a/testing/spectest/shared/altair/fork/upgrade_to_altair.go +++ b/testing/spectest/shared/altair/fork/upgrade_to_altair.go @@ -8,8 +8,8 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - statealtair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + statealtair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" @@ -40,7 +40,7 @@ func RunUpgradeToAltair(t *testing.T, config string) { require.NoError(t, err) postState, err := altair.UpgradeToAltair(context.Background(), preState) require.NoError(t, err) - postStateFromFunction, err := statealtair.ProtobufBeaconState(postState.ToProtoUnsafe()) + postStateFromFunction, err := statealtair.ProtobufBeaconState(postState.InnerStateUnsafe()) require.NoError(t, err) postStateFile, err := util.BazelFileBytes(path.Join(folderPath, "post.ssz_snappy")) diff --git a/testing/spectest/shared/altair/operations/BUILD.bazel b/testing/spectest/shared/altair/operations/BUILD.bazel index baa7f1f917..0fdc28074b 100644 --- a/testing/spectest/shared/altair/operations/BUILD.bazel +++ b/testing/spectest/shared/altair/operations/BUILD.bazel @@ -20,8 +20,8 @@ go_library( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/validators:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/block:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", diff --git a/testing/spectest/shared/altair/operations/attestation.go b/testing/spectest/shared/altair/operations/attestation.go index efa9e702b8..4a77f6f60e 100644 --- a/testing/spectest/shared/altair/operations/attestation.go +++ b/testing/spectest/shared/altair/operations/attestation.go @@ -9,7 +9,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/altair/operations/attester_slashing.go b/testing/spectest/shared/altair/operations/attester_slashing.go index 489e78df3b..dc0558c0fb 100644 --- a/testing/spectest/shared/altair/operations/attester_slashing.go +++ b/testing/spectest/shared/altair/operations/attester_slashing.go @@ -8,7 +8,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/altair/operations/block_header.go b/testing/spectest/shared/altair/operations/block_header.go index 0a34394df7..7286b06e0c 100644 --- a/testing/spectest/shared/altair/operations/block_header.go +++ b/testing/spectest/shared/altair/operations/block_header.go @@ -10,7 +10,7 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" @@ -63,10 +63,10 @@ func RunBlockHeaderTest(t *testing.T, config string) { postBeaconState := ðpb.BeaconStateAltair{} require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := stateAltair.ProtobufBeaconState(beaconState.ToProto()) + pbState, err := stateAltair.ProtobufBeaconState(beaconState.CloneInnerState()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProto(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.CloneInnerState(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/altair/operations/deposit.go b/testing/spectest/shared/altair/operations/deposit.go index 143a9c2ae4..2e5277f66b 100644 --- a/testing/spectest/shared/altair/operations/deposit.go +++ b/testing/spectest/shared/altair/operations/deposit.go @@ -7,7 +7,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/altair/operations/helpers.go b/testing/spectest/shared/altair/operations/helpers.go index ea125aadd5..9b0932c8ec 100644 --- a/testing/spectest/shared/altair/operations/helpers.go +++ b/testing/spectest/shared/altair/operations/helpers.go @@ -10,8 +10,8 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" @@ -69,10 +69,10 @@ func RunBlockOperationTest( if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { t.Fatalf("Failed to unmarshal: %v", err) } - pbState, err := stateAltair.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := stateAltair.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProtoUnsafe(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/altair/operations/proposer_slashing.go b/testing/spectest/shared/altair/operations/proposer_slashing.go index 14abcb876f..53f93ffacc 100644 --- a/testing/spectest/shared/altair/operations/proposer_slashing.go +++ b/testing/spectest/shared/altair/operations/proposer_slashing.go @@ -8,7 +8,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/altair/operations/sync_committee.go b/testing/spectest/shared/altair/operations/sync_committee.go index 65916ad856..84dd2f7e7d 100644 --- a/testing/spectest/shared/altair/operations/sync_committee.go +++ b/testing/spectest/shared/altair/operations/sync_committee.go @@ -7,7 +7,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/altair/operations/voluntary_exit.go b/testing/spectest/shared/altair/operations/voluntary_exit.go index 6ec080fc3c..06bdd2fbcc 100644 --- a/testing/spectest/shared/altair/operations/voluntary_exit.go +++ b/testing/spectest/shared/altair/operations/voluntary_exit.go @@ -7,7 +7,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/altair/rewards/BUILD.bazel b/testing/spectest/shared/altair/rewards/BUILD.bazel index 4def4684b3..c06c1cb52d 100644 --- a/testing/spectest/shared/altair/rewards/BUILD.bazel +++ b/testing/spectest/shared/altair/rewards/BUILD.bazel @@ -9,7 +9,7 @@ go_library( deps = [ "//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/altair/rewards/rewards_penalties.go b/testing/spectest/shared/altair/rewards/rewards_penalties.go index 678b3badb9..72717d22de 100644 --- a/testing/spectest/shared/altair/rewards/rewards_penalties.go +++ b/testing/spectest/shared/altair/rewards/rewards_penalties.go @@ -12,7 +12,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" diff --git a/testing/spectest/shared/altair/sanity/BUILD.bazel b/testing/spectest/shared/altair/sanity/BUILD.bazel index 8f569ba165..cf031a710d 100644 --- a/testing/spectest/shared/altair/sanity/BUILD.bazel +++ b/testing/spectest/shared/altair/sanity/BUILD.bazel @@ -13,8 +13,8 @@ go_library( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/altair/sanity/block_processing.go b/testing/spectest/shared/altair/sanity/block_processing.go index d7df096fad..bdffd8c15a 100644 --- a/testing/spectest/shared/altair/sanity/block_processing.go +++ b/testing/spectest/shared/altair/sanity/block_processing.go @@ -13,8 +13,8 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/require" @@ -92,10 +92,10 @@ func RunBlockProcessingTest(t *testing.T, config, folderPath string) { postBeaconState := ðpb.BeaconStateAltair{} require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := stateAltair.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := stateAltair.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProtoUnsafe(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/altair/sanity/slot_processing.go b/testing/spectest/shared/altair/sanity/slot_processing.go index 99fb0b87b9..4d7084c4e0 100644 --- a/testing/spectest/shared/altair/sanity/slot_processing.go +++ b/testing/spectest/shared/altair/sanity/slot_processing.go @@ -7,7 +7,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" @@ -52,7 +52,7 @@ func RunSlotProcessingTests(t *testing.T, config string) { postState, err := transition.ProcessSlots(context.Background(), beaconState, beaconState.Slot().Add(uint64(slotsCount))) require.NoError(t, err) - pbState, err := stateAltair.ProtobufBeaconState(postState.ToProto()) + pbState, err := stateAltair.ProtobufBeaconState(postState.CloneInnerState()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { diff, _ := messagediff.PrettyDiff(beaconState, postBeaconState) diff --git a/testing/spectest/shared/altair/ssz_static/BUILD.bazel b/testing/spectest/shared/altair/ssz_static/BUILD.bazel index a20fa4b549..e62dd35ebb 100644 --- a/testing/spectest/shared/altair/ssz_static/BUILD.bazel +++ b/testing/spectest/shared/altair/ssz_static/BUILD.bazel @@ -7,7 +7,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/testing/spectest/shared/altair/ssz_static", visibility = ["//testing/spectest:__subpackages__"], deps = [ - "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/altair/ssz_static/ssz_static.go b/testing/spectest/shared/altair/ssz_static/ssz_static.go index ff544833f2..ef93195f6a 100644 --- a/testing/spectest/shared/altair/ssz_static/ssz_static.go +++ b/testing/spectest/shared/altair/ssz_static/ssz_static.go @@ -9,7 +9,7 @@ import ( fssz "github.com/ferranbt/fastssz" "github.com/golang/snappy" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" diff --git a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel index 6569928e5f..075e998e88 100644 --- a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel @@ -22,8 +22,8 @@ go_library( "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/phase0/epoch_processing/effective_balance_updates.go b/testing/spectest/shared/phase0/epoch_processing/effective_balance_updates.go index bfbc8c1ea5..8f9b35e2d8 100644 --- a/testing/spectest/shared/phase0/epoch_processing/effective_balance_updates.go +++ b/testing/spectest/shared/phase0/epoch_processing/effective_balance_updates.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/eth1_data_reset.go b/testing/spectest/shared/phase0/epoch_processing/eth1_data_reset.go index a65f5c8e4f..c06bede2e0 100644 --- a/testing/spectest/shared/phase0/epoch_processing/eth1_data_reset.go +++ b/testing/spectest/shared/phase0/epoch_processing/eth1_data_reset.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/helpers.go b/testing/spectest/shared/phase0/epoch_processing/helpers.go index 84ee305175..e05cea37bd 100644 --- a/testing/spectest/shared/phase0/epoch_processing/helpers.go +++ b/testing/spectest/shared/phase0/epoch_processing/helpers.go @@ -8,8 +8,8 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" @@ -58,7 +58,7 @@ func RunEpochOperationTest( t.Fatalf("Failed to unmarshal: %v", err) } - pbState, err := v1.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { t.Fatal("Post state does not match expected") diff --git a/testing/spectest/shared/phase0/epoch_processing/historical_roots_update.go b/testing/spectest/shared/phase0/epoch_processing/historical_roots_update.go index 54ee7862f9..03768d111c 100644 --- a/testing/spectest/shared/phase0/epoch_processing/historical_roots_update.go +++ b/testing/spectest/shared/phase0/epoch_processing/historical_roots_update.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/justification_and_finalization.go b/testing/spectest/shared/phase0/epoch_processing/justification_and_finalization.go index a50ef87a9d..dc79739ee6 100644 --- a/testing/spectest/shared/phase0/epoch_processing/justification_and_finalization.go +++ b/testing/spectest/shared/phase0/epoch_processing/justification_and_finalization.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/participation_record_updates.go b/testing/spectest/shared/phase0/epoch_processing/participation_record_updates.go index 77c8971900..2eeaa7a9b6 100644 --- a/testing/spectest/shared/phase0/epoch_processing/participation_record_updates.go +++ b/testing/spectest/shared/phase0/epoch_processing/participation_record_updates.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/randao_mixes_reset.go b/testing/spectest/shared/phase0/epoch_processing/randao_mixes_reset.go index 1201f29acd..536c71dc7d 100644 --- a/testing/spectest/shared/phase0/epoch_processing/randao_mixes_reset.go +++ b/testing/spectest/shared/phase0/epoch_processing/randao_mixes_reset.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/registry_updates.go b/testing/spectest/shared/phase0/epoch_processing/registry_updates.go index 7c2832f7cd..3a4129d906 100644 --- a/testing/spectest/shared/phase0/epoch_processing/registry_updates.go +++ b/testing/spectest/shared/phase0/epoch_processing/registry_updates.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/rewards_and_penalties.go b/testing/spectest/shared/phase0/epoch_processing/rewards_and_penalties.go index c07779b5b7..90d2741b79 100644 --- a/testing/spectest/shared/phase0/epoch_processing/rewards_and_penalties.go +++ b/testing/spectest/shared/phase0/epoch_processing/rewards_and_penalties.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/epoch_processing/slashings.go b/testing/spectest/shared/phase0/epoch_processing/slashings.go index 3155d87a52..fa5e69bbe9 100644 --- a/testing/spectest/shared/phase0/epoch_processing/slashings.go +++ b/testing/spectest/shared/phase0/epoch_processing/slashings.go @@ -8,7 +8,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" diff --git a/testing/spectest/shared/phase0/epoch_processing/slashings_reset.go b/testing/spectest/shared/phase0/epoch_processing/slashings_reset.go index 6d67bacd45..413744afdb 100644 --- a/testing/spectest/shared/phase0/epoch_processing/slashings_reset.go +++ b/testing/spectest/shared/phase0/epoch_processing/slashings_reset.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" ) diff --git a/testing/spectest/shared/phase0/finality/BUILD.bazel b/testing/spectest/shared/phase0/finality/BUILD.bazel index 61201d8b9f..f3dd1476b2 100644 --- a/testing/spectest/shared/phase0/finality/BUILD.bazel +++ b/testing/spectest/shared/phase0/finality/BUILD.bazel @@ -9,8 +9,8 @@ go_library( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/phase0/finality/runner.go b/testing/spectest/shared/phase0/finality/runner.go index f308c12d3c..2347801be2 100644 --- a/testing/spectest/shared/phase0/finality/runner.go +++ b/testing/spectest/shared/phase0/finality/runner.go @@ -8,8 +8,8 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/require" @@ -72,10 +72,10 @@ func RunFinalityTest(t *testing.T, config string) { require.NoError(t, err, "Failed to decompress") postBeaconState := ðpb.BeaconState{} require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := v1.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProtoUnsafe(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/phase0/operations/BUILD.bazel b/testing/spectest/shared/phase0/operations/BUILD.bazel index f091afdca2..ac037af344 100644 --- a/testing/spectest/shared/phase0/operations/BUILD.bazel +++ b/testing/spectest/shared/phase0/operations/BUILD.bazel @@ -18,8 +18,8 @@ go_library( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/validators:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/block:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", diff --git a/testing/spectest/shared/phase0/operations/attestation.go b/testing/spectest/shared/phase0/operations/attestation.go index 7417353480..ab66adb2ec 100644 --- a/testing/spectest/shared/phase0/operations/attestation.go +++ b/testing/spectest/shared/phase0/operations/attestation.go @@ -8,7 +8,7 @@ import ( "github.com/golang/snappy" "github.com/pkg/errors" b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/phase0/operations/attester_slashing.go b/testing/spectest/shared/phase0/operations/attester_slashing.go index c887ee8a4b..ffa0b375b7 100644 --- a/testing/spectest/shared/phase0/operations/attester_slashing.go +++ b/testing/spectest/shared/phase0/operations/attester_slashing.go @@ -8,7 +8,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/phase0/operations/block_header.go b/testing/spectest/shared/phase0/operations/block_header.go index 1de37ee8af..6698f2228c 100644 --- a/testing/spectest/shared/phase0/operations/block_header.go +++ b/testing/spectest/shared/phase0/operations/block_header.go @@ -10,7 +10,7 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" @@ -64,10 +64,10 @@ func RunBlockHeaderTest(t *testing.T, config string) { postBeaconState := ðpb.BeaconState{} require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := v1.ProtobufBeaconState(beaconState.ToProto()) + pbState, err := v1.ProtobufBeaconState(beaconState.CloneInnerState()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProto(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.CloneInnerState(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/phase0/operations/deposit.go b/testing/spectest/shared/phase0/operations/deposit.go index fc17b51789..146080fe7c 100644 --- a/testing/spectest/shared/phase0/operations/deposit.go +++ b/testing/spectest/shared/phase0/operations/deposit.go @@ -7,7 +7,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/phase0/operations/helpers.go b/testing/spectest/shared/phase0/operations/helpers.go index 7adf89b489..58253cfa4f 100644 --- a/testing/spectest/shared/phase0/operations/helpers.go +++ b/testing/spectest/shared/phase0/operations/helpers.go @@ -10,8 +10,8 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" @@ -67,10 +67,10 @@ func RunBlockOperationTest( if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { t.Fatalf("Failed to unmarshal: %v", err) } - pbState, err := v1.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProtoUnsafe(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/phase0/operations/proposer_slashing.go b/testing/spectest/shared/phase0/operations/proposer_slashing.go index 64de7727d4..e1d22f9afa 100644 --- a/testing/spectest/shared/phase0/operations/proposer_slashing.go +++ b/testing/spectest/shared/phase0/operations/proposer_slashing.go @@ -8,7 +8,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/phase0/operations/voluntary_exit.go b/testing/spectest/shared/phase0/operations/voluntary_exit.go index 398b1f323b..e31d54095e 100644 --- a/testing/spectest/shared/phase0/operations/voluntary_exit.go +++ b/testing/spectest/shared/phase0/operations/voluntary_exit.go @@ -7,7 +7,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" "github.com/prysmaticlabs/prysm/testing/require" diff --git a/testing/spectest/shared/phase0/rewards/BUILD.bazel b/testing/spectest/shared/phase0/rewards/BUILD.bazel index 83e40043ef..8b2c958fed 100644 --- a/testing/spectest/shared/phase0/rewards/BUILD.bazel +++ b/testing/spectest/shared/phase0/rewards/BUILD.bazel @@ -9,7 +9,7 @@ go_library( deps = [ "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/phase0/rewards/rewards_penalties.go b/testing/spectest/shared/phase0/rewards/rewards_penalties.go index bdd604d915..ff33a7414f 100644 --- a/testing/spectest/shared/phase0/rewards/rewards_penalties.go +++ b/testing/spectest/shared/phase0/rewards/rewards_penalties.go @@ -11,7 +11,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" diff --git a/testing/spectest/shared/phase0/sanity/BUILD.bazel b/testing/spectest/shared/phase0/sanity/BUILD.bazel index 95da1ab321..66371b980e 100644 --- a/testing/spectest/shared/phase0/sanity/BUILD.bazel +++ b/testing/spectest/shared/phase0/sanity/BUILD.bazel @@ -13,8 +13,8 @@ go_library( deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/phase0/sanity/block_processing.go b/testing/spectest/shared/phase0/sanity/block_processing.go index d1e55896da..151de7eb39 100644 --- a/testing/spectest/shared/phase0/sanity/block_processing.go +++ b/testing/spectest/shared/phase0/sanity/block_processing.go @@ -12,8 +12,8 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "github.com/prysmaticlabs/prysm/testing/require" @@ -90,10 +90,10 @@ func RunBlockProcessingTest(t *testing.T, config, folderPath string) { postBeaconState := ðpb.BeaconState{} require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := v1.ProtobufBeaconState(beaconState.ToProtoUnsafe()) + pbState, err := v1.ProtobufBeaconState(beaconState.InnerStateUnsafe()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { - diff, _ := messagediff.PrettyDiff(beaconState.ToProtoUnsafe(), postBeaconState) + diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState) t.Log(diff) t.Fatal("Post state does not match expected") } diff --git a/testing/spectest/shared/phase0/sanity/slot_processing.go b/testing/spectest/shared/phase0/sanity/slot_processing.go index 2c55f8460e..3a98f65460 100644 --- a/testing/spectest/shared/phase0/sanity/slot_processing.go +++ b/testing/spectest/shared/phase0/sanity/slot_processing.go @@ -7,7 +7,7 @@ import ( "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" @@ -52,7 +52,7 @@ func RunSlotProcessingTests(t *testing.T, config string) { postState, err := transition.ProcessSlots(context.Background(), beaconState, beaconState.Slot().Add(uint64(slotsCount))) require.NoError(t, err) - pbState, err := v1.ProtobufBeaconState(postState.ToProto()) + pbState, err := v1.ProtobufBeaconState(postState.CloneInnerState()) require.NoError(t, err) if !proto.Equal(pbState, postBeaconState) { diff, _ := messagediff.PrettyDiff(beaconState, postBeaconState) diff --git a/testing/spectest/shared/phase0/ssz_static/BUILD.bazel b/testing/spectest/shared/phase0/ssz_static/BUILD.bazel index 2668769d4e..59a260284b 100644 --- a/testing/spectest/shared/phase0/ssz_static/BUILD.bazel +++ b/testing/spectest/shared/phase0/ssz_static/BUILD.bazel @@ -7,7 +7,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/testing/spectest/shared/phase0/ssz_static", visibility = ["//testing/spectest:__subpackages__"], deps = [ - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/phase0/ssz_static/ssz_static.go b/testing/spectest/shared/phase0/ssz_static/ssz_static.go index d9dda481f3..abceba5442 100644 --- a/testing/spectest/shared/phase0/ssz_static/ssz_static.go +++ b/testing/spectest/shared/phase0/ssz_static/ssz_static.go @@ -9,7 +9,7 @@ import ( fssz "github.com/ferranbt/fastssz" "github.com/golang/snappy" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/spectest/utils" diff --git a/testing/util/BUILD.bazel b/testing/util/BUILD.bazel index 57741dab44..f4ca6dc6f9 100644 --- a/testing/util/BUILD.bazel +++ b/testing/util/BUILD.bazel @@ -28,11 +28,11 @@ go_library( "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/transition:go_default_library", "//beacon-chain/p2p/types:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/v2:go_default_library", - "//beacon-chain/state/v3:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/stateutil:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", + "//beacon-chain/state-proto/v2:go_default_library", + "//beacon-chain/state-proto/v3:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", diff --git a/testing/util/altair.go b/testing/util/altair.go index ac86440014..4b31700b1c 100644 --- a/testing/util/altair.go +++ b/testing/util/altair.go @@ -14,9 +14,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -87,29 +87,28 @@ func buildGenesisBeaconState(genesisTime uint64, preState state.BeaconStateAltai return nil, errors.New("no eth1data provided for genesis state") } - var randaoMixes [fieldparams.RandaoMixesLength][32]byte + randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) for i := 0; i < len(randaoMixes); i++ { - var h [32]byte - copy(h[:], eth1Data.BlockHash) + h := make([]byte, 32) + copy(h, eth1Data.BlockHash) randaoMixes[i] = h } - zeroHash32 := params.BeaconConfig().ZeroHash - zeroHash := zeroHash32[:] + zeroHash := params.BeaconConfig().ZeroHash[:] activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) for i := 0; i < len(activeIndexRoots); i++ { activeIndexRoots[i] = zeroHash } - var blockRoots [fieldparams.BlockRootsLength][32]byte + blockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) for i := 0; i < len(blockRoots); i++ { - blockRoots[i] = zeroHash32 + blockRoots[i] = zeroHash } - var stateRoots [fieldparams.StateRootsLength][32]byte + stateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) for i := 0; i < len(stateRoots); i++ { - stateRoots[i] = zeroHash32 + stateRoots[i] = zeroHash } slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector) @@ -131,6 +130,53 @@ func buildGenesisBeaconState(genesisTime uint64, preState state.BeaconStateAltai if err != nil { return nil, err } + st := ðpb.BeaconStateAltair{ + // Misc fields. + Slot: 0, + GenesisTime: genesisTime, + GenesisValidatorsRoot: genesisValidatorsRoot[:], + + Fork: ðpb.Fork{ + PreviousVersion: params.BeaconConfig().GenesisForkVersion, + CurrentVersion: params.BeaconConfig().GenesisForkVersion, + Epoch: 0, + }, + + // Validator registry fields. + Validators: preState.Validators(), + Balances: preState.Balances(), + PreviousEpochParticipation: prevEpochParticipation, + CurrentEpochParticipation: currEpochParticipation, + InactivityScores: scores, + + // Randomness and committees. + RandaoMixes: randaoMixes, + + // Finality. + PreviousJustifiedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + CurrentJustifiedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + JustificationBits: []byte{0}, + FinalizedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + + HistoricalRoots: [][]byte{}, + BlockRoots: blockRoots, + StateRoots: stateRoots, + Slashings: slashings, + + // Eth1 data. + Eth1Data: eth1Data, + Eth1DataVotes: []*ethpb.Eth1Data{}, + Eth1DepositIndex: preState.Eth1DepositIndex(), + } bodyRoot, err := (ðpb.BeaconBlockBodyAltair{ RandaoReveal: make([]byte, 96), @@ -148,166 +194,53 @@ func buildGenesisBeaconState(genesisTime uint64, preState state.BeaconStateAltai return nil, errors.Wrap(err, "could not hash tree root empty block body") } + st.LatestBlockHeader = ðpb.BeaconBlockHeader{ + ParentRoot: zeroHash, + StateRoot: zeroHash, + BodyRoot: bodyRoot[:], + } + var pubKeys [][]byte for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSize; i++ { pubKeys = append(pubKeys, bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength)) } - - s, err := stateAltair.Initialize() - if err != nil { - return nil, errors.Wrap(err, "could not initialize state from proto state") - } - - if err = s.SetGenesisTime(genesisTime); err != nil { - return nil, errors.Wrap(err, "could not set genesis time") - } - if err = s.SetGenesisValidatorRoot(genesisValidatorsRoot); err != nil { - return nil, errors.Wrap(err, "could not set genesis validators root") - } - if err = s.SetSlot(0); err != nil { - return nil, errors.Wrap(err, "could not set slot") - } - if err = s.SetFork(ðpb.Fork{ - PreviousVersion: params.BeaconConfig().GenesisForkVersion, - CurrentVersion: params.BeaconConfig().GenesisForkVersion, - Epoch: 0, - }); err != nil { - return nil, errors.Wrap(err, "could not set fork") - } - if err = s.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ - ParentRoot: zeroHash, - StateRoot: zeroHash, - BodyRoot: bodyRoot[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set latest block header") - } - if err = s.SetBlockRoots(&blockRoots); err != nil { - return nil, errors.Wrap(err, "could not set block roots") - } - if err = s.SetStateRoots(&stateRoots); err != nil { - return nil, errors.Wrap(err, "could not set state roots") - } - if err = s.SetHistoricalRoots([][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set historical roots") - } - if err = s.SetEth1Data(eth1Data); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = s.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data votes") - } - if err = s.SetEth1Data(eth1Data); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = s.SetEth1DepositIndex(preState.Eth1DepositIndex()); err != nil { - return nil, errors.Wrap(err, "could not set eth1 deposit index") - } - if err = s.SetValidators(preState.Validators()); err != nil { - return nil, errors.Wrap(err, "could not set validators") - } - if err = s.SetBalances(preState.Balances()); err != nil { - return nil, errors.Wrap(err, "could not set balances") - } - if err = s.SetRandaoMixes(&randaoMixes); err != nil { - return nil, errors.Wrap(err, "could not set randao mixes") - } - if err = s.SetPreviousParticipationBits(prevEpochParticipation); err != nil { - return nil, errors.Wrap(err, "could not set previous epoch participation") - } - if err = s.SetCurrentParticipationBits(currEpochParticipation); err != nil { - return nil, errors.Wrap(err, "could not set current epoch participation") - } - if err = s.SetInactivityScores(scores); err != nil { - return nil, errors.Wrap(err, "could not set inactivity scores") - } - if err = s.SetSlashings(slashings); err != nil { - return nil, errors.Wrap(err, "could not set slashings") - } - if err = s.SetJustificationBits([]byte{0}); err != nil { - return nil, errors.Wrap(err, "could not set justification bits") - } - if err = s.SetPreviousJustifiedCheckpoint(ðpb.Checkpoint{ - Epoch: 0, - Root: params.BeaconConfig().ZeroHash[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set previous justified checkpoint") - } - if err = s.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{ - Epoch: 0, - Root: params.BeaconConfig().ZeroHash[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set current justified checkpoint") - } - if err = s.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: 0, - Root: params.BeaconConfig().ZeroHash[:], - }); err != nil { - return nil, errors.Wrap(err, "could not set finalized checkpoint") - } - if err = s.SetCurrentSyncCommittee(ðpb.SyncCommittee{ + st.CurrentSyncCommittee = ðpb.SyncCommittee{ Pubkeys: pubKeys, AggregatePubkey: bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength), - }); err != nil { - return nil, errors.Wrap(err, "could not set current sync committee") } - if err = s.SetNextSyncCommittee(ðpb.SyncCommittee{ + st.NextSyncCommittee = ðpb.SyncCommittee{ Pubkeys: bytesutil.SafeCopy2dBytes(pubKeys), AggregatePubkey: bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength), - }); err != nil { - return nil, errors.Wrap(err, "could not set next sync committee") } - return s, nil + return stateAltair.InitializeFromProto(st) } func emptyGenesisState() (state.BeaconStateAltair, error) { - s, err := stateAltair.Initialize() - if err != nil { - return nil, errors.Wrap(err, "could not initialize state from proto state") - } + st := ðpb.BeaconStateAltair{ + // Misc fields. + Slot: 0, + Fork: ðpb.Fork{ + PreviousVersion: params.BeaconConfig().GenesisForkVersion, + CurrentVersion: params.BeaconConfig().AltairForkVersion, + Epoch: 0, + }, + // Validator registry fields. + Validators: []*ethpb.Validator{}, + Balances: []uint64{}, + InactivityScores: []uint64{}, - if err = s.SetSlot(0); err != nil { - return nil, errors.Wrap(err, "could not set slot") - } - if err = s.SetFork(ðpb.Fork{ - PreviousVersion: params.BeaconConfig().GenesisForkVersion, - CurrentVersion: params.BeaconConfig().AltairForkVersion, - Epoch: 0, - }); err != nil { - return nil, errors.Wrap(err, "could not set fork") - } - if err = s.SetHistoricalRoots([][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set historical roots") - } - if err = s.SetEth1Data(ðpb.Eth1Data{}); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = s.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data votes") - } - if err = s.SetEth1DepositIndex(0); err != nil { - return nil, errors.Wrap(err, "could not set eth1 deposit index") - } - if err = s.SetValidators([]*ethpb.Validator{}); err != nil { - return nil, errors.Wrap(err, "could not set validators") - } - if err = s.SetBalances([]uint64{}); err != nil { - return nil, errors.Wrap(err, "could not set balances") - } - if err = s.SetInactivityScores([]uint64{}); err != nil { - return nil, errors.Wrap(err, "could not set inactivity scores") - } - if err = s.SetPreviousParticipationBits([]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set previous participation bits") - } - if err = s.SetCurrentParticipationBits([]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set current participation bits") - } - if err = s.SetJustificationBits([]byte{0}); err != nil { - return nil, errors.Wrap(err, "could not set justification bits") - } + JustificationBits: []byte{0}, + HistoricalRoots: [][]byte{}, + CurrentEpochParticipation: []byte{}, + PreviousEpochParticipation: []byte{}, - return s, nil + // Eth1 data. + Eth1Data: ðpb.Eth1Data{}, + Eth1DataVotes: []*ethpb.Eth1Data{}, + Eth1DepositIndex: 0, + } + return stateAltair.InitializeFromProto(st) } // NewBeaconBlockAltair creates a beacon block with minimum marshalable fields. @@ -354,8 +287,7 @@ func BlockSignatureAltair( return nil, err } block.StateRoot = s[:] - gvRoot := bState.GenesisValidatorRoot() - domain, err := signing.Domain(bState.Fork(), time.CurrentEpoch(bState), params.BeaconConfig().DomainBeaconProposer, gvRoot[:]) + domain, err := signing.Domain(bState.Fork(), time.CurrentEpoch(bState), params.BeaconConfig().DomainBeaconProposer, bState.GenesisValidatorRoot()) if err != nil { return nil, err } diff --git a/testing/util/attestation.go b/testing/util/attestation.go index fad63c2f8c..fd7a79e4db 100644 --- a/testing/util/attestation.go +++ b/testing/util/attestation.go @@ -11,9 +11,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "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" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v2" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -70,7 +70,7 @@ func GenerateAttestations( var headState state.BeaconState switch bState.Version() { case version.Phase0: - pbState, err := v1.ProtobufBeaconState(bState.ToProto()) + pbState, err := v1.ProtobufBeaconState(bState.CloneInnerState()) if err != nil { return nil, err } @@ -80,7 +80,7 @@ func GenerateAttestations( } headState = state.BeaconState(genState) case version.Altair: - pbState, err := v2.ProtobufBeaconState(bState.ToProto()) + pbState, err := v2.ProtobufBeaconState(bState.CloneInnerState()) if err != nil { return nil, err } @@ -151,8 +151,7 @@ func GenerateAttestations( ) } - gvRoot := bState.GenesisValidatorRoot() - domain, err := signing.Domain(bState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, gvRoot[:]) + domain, err := signing.Domain(bState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, bState.GenesisValidatorRoot()) if err != nil { return nil, err } diff --git a/testing/util/bellatrix.go b/testing/util/bellatrix.go index 5b92c11205..e6421e62bd 100644 --- a/testing/util/bellatrix.go +++ b/testing/util/bellatrix.go @@ -7,7 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/testing/util/block.go b/testing/util/block.go index 2c31e5e017..db03e7fb0b 100644 --- a/testing/util/block.go +++ b/testing/util/block.go @@ -9,7 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/testing/util/deposits.go b/testing/util/deposits.go index dd37a05894..fc68d29689 100644 --- a/testing/util/deposits.go +++ b/testing/util/deposits.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/crypto/bls" diff --git a/testing/util/helpers.go b/testing/util/helpers.go index 596334d3e2..210da1d431 100644 --- a/testing/util/helpers.go +++ b/testing/util/helpers.go @@ -11,7 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/crypto/rand" @@ -46,8 +46,7 @@ func BlockSignature( return nil, err } block.StateRoot = s[:] - gvRoot := bState.GenesisValidatorRoot() - domain, err := signing.Domain(bState.Fork(), time.CurrentEpoch(bState), params.BeaconConfig().DomainBeaconProposer, gvRoot[:]) + domain, err := signing.Domain(bState.Fork(), time.CurrentEpoch(bState), params.BeaconConfig().DomainBeaconProposer, bState.GenesisValidatorRoot()) if err != nil { return nil, err } diff --git a/testing/util/merge_state.go b/testing/util/merge_state.go index 7c74c62b22..b1c29155bd 100644 --- a/testing/util/merge_state.go +++ b/testing/util/merge_state.go @@ -7,9 +7,9 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/stateutil" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v3" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" diff --git a/testing/util/state.go b/testing/util/state.go index 487737c797..40805d6a06 100644 --- a/testing/util/state.go +++ b/testing/util/state.go @@ -4,21 +4,18 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" 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 state.BeaconState) error { +func FillRootsNaturalOpt(state *ethpb.BeaconState) error { rootsLen := params.MainnetConfig().SlotsPerHistoricalRoot roots := make([][]byte, rootsLen) for i := types.Slot(0); i < rootsLen; i++ { @@ -33,85 +30,59 @@ func FillRootsNaturalOpt(state state.BeaconState) error { } roots[j] = h } - var stateRoots [fieldparams.StateRootsLength][32]byte - for i := range stateRoots { - stateRoots[i] = bytesutil.ToBytes32(roots[i]) - } - if err := state.SetStateRoots(&stateRoots); err != nil { - return errors.Wrap(err, "could not set state roots") - } - var blockRoots [fieldparams.BlockRootsLength][32]byte - for i := range blockRoots { - blockRoots[i] = bytesutil.ToBytes32(roots[i]) - } - if err := state.SetBlockRoots(&blockRoots); err != nil { - return errors.Wrap(err, "could not set block roots") - } + state.StateRoots = roots + state.BlockRoots = roots return nil } // NewBeaconState creates a beacon state with minimum marshalable fields. -func NewBeaconState(options ...func(beaconState state.BeaconState) error) (*v1.BeaconState, error) { - var st, err = v1.Initialize() - if err != nil { - return nil, err - } - - if err = st.SetFork(ðpb.Fork{ - PreviousVersion: make([]byte, 4), - CurrentVersion: make([]byte, 4), - }); err != nil { - return nil, errors.Wrap(err, "could not set fork") - } - if err = st.SetLatestBlockHeader(HydrateBeaconHeader(ðpb.BeaconBlockHeader{})); err != nil { - return nil, errors.Wrap(err, "could not set latest block header") - } - if err = st.SetHistoricalRoots([][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set historical roots") - } - if err = st.SetBlockRoots(&[fieldparams.BlockRootsLength][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set block roots") - } - if err = st.SetStateRoots(&[fieldparams.StateRootsLength][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set state roots") - } - if err = st.SetEth1Data(ðpb.Eth1Data{ - DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, 32), - }); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data") - } - if err = st.SetEth1DataVotes(make([]*ethpb.Eth1Data, 0)); err != nil { - return nil, errors.Wrap(err, "could not set eth1 data votes") - } - if err = st.SetValidators(make([]*ethpb.Validator, 0)); err != nil { - return nil, errors.Wrap(err, "could not set validators") - } - if err = st.SetRandaoMixes(&[fieldparams.RandaoMixesLength][32]byte{}); err != nil { - return nil, errors.Wrap(err, "could not set randao mixes") - } - if err = st.SetSlashings(make([]uint64, params.MainnetConfig().EpochsPerSlashingsVector)); err != nil { - return nil, errors.Wrap(err, "could not set slashings") - } - if err = st.SetJustificationBits(bitfield.Bitvector4{0x0}); err != nil { - return nil, errors.Wrap(err, "could not set justification bits") - } - if err = st.SetPreviousJustifiedCheckpoint(ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}); err != nil { - return nil, errors.Wrap(err, "could not set previous justified checkpoint") - } - if err = st.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}); err != nil { - return nil, errors.Wrap(err, "could not set current justified checkpoint") - } - if err = st.SetFinalizedCheckpoint(ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}); err != nil { - return nil, errors.Wrap(err, "could not set finalized checkpoint") +func NewBeaconState(options ...func(state *ethpb.BeaconState) error) (*v1.BeaconState, error) { + seed := ðpb.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: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, 32), + }, + Fork: ðpb.Fork{ + PreviousVersion: make([]byte, 4), + CurrentVersion: make([]byte, 4), + }, + Eth1DataVotes: make([]*ethpb.Eth1Data, 0), + HistoricalRoots: make([][]byte, 0), + JustificationBits: bitfield.Bitvector4{0x0}, + FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + LatestBlockHeader: HydrateBeaconHeader(ðpb.BeaconBlockHeader{}), + PreviousEpochAttestations: make([]*ethpb.PendingAttestation, 0), + CurrentEpochAttestations: make([]*ethpb.PendingAttestation, 0), + PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, } for _, opt := range options { - err = opt(st) + 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 } + +// 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 +} diff --git a/testing/util/sync_aggregate.go b/testing/util/sync_aggregate.go index b8972bea36..8cb2abf336 100644 --- a/testing/util/sync_aggregate.go +++ b/testing/util/sync_aggregate.go @@ -5,7 +5,7 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" p2pType "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -52,8 +52,7 @@ func generateSyncAggregate(bState state.BeaconState, privs []bls.SecretKey, pare if !ok { continue } - gvRoot := st.GenesisValidatorRoot() - d, err := signing.Domain(st.Fork(), slots.ToEpoch(st.Slot()), params.BeaconConfig().DomainSyncCommittee, gvRoot[:]) + d, err := signing.Domain(st.Fork(), slots.ToEpoch(st.Slot()), params.BeaconConfig().DomainSyncCommittee, st.GenesisValidatorRoot()) if err != nil { return nil, err } diff --git a/tools/benchmark-files-gen/BUILD.bazel b/tools/benchmark-files-gen/BUILD.bazel index b23aa4d89c..cc1638b210 100644 --- a/tools/benchmark-files-gen/BUILD.bazel +++ b/tools/benchmark-files-gen/BUILD.bazel @@ -12,8 +12,8 @@ go_library( "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-native:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//config/params:go_default_library", "//io/file:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/tools/benchmark-files-gen/main.go b/tools/benchmark-files-gen/main.go index 3637e2b354..e484b11487 100644 --- a/tools/benchmark-files-gen/main.go +++ b/tools/benchmark-files-gen/main.go @@ -14,8 +14,8 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/io/file" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/tools/exploredb/BUILD.bazel b/tools/exploredb/BUILD.bazel index 4a90aee61c..e2bb4fe6eb 100644 --- a/tools/exploredb/BUILD.bazel +++ b/tools/exploredb/BUILD.bazel @@ -8,7 +8,7 @@ go_library( visibility = ["//visibility:private"], deps = [ "//beacon-chain/db/kv:go_default_library", - "//beacon-chain/state:go_default_library", + "//beacon-chain/state-native:go_default_library", "//config/params:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/tools/exploredb/main.go b/tools/exploredb/main.go index 7a2b1f2e60..c2bad6761e 100644 --- a/tools/exploredb/main.go +++ b/tools/exploredb/main.go @@ -20,7 +20,7 @@ import ( "github.com/dustin/go-humanize" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/db/kv" - "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -326,34 +326,15 @@ func printStates(stateC <-chan *modifiedState, doneC chan<- bool) { log.Infof("value : compressed size = %s", humanize.Bytes(mst.valueSize)) t := time.Unix(int64(st.GenesisTime()), 0) log.Infof("genesis_time : %s", t.Format(time.UnixDate)) - gvRoot := st.GenesisValidatorRoot() - log.Infof("genesis_validators_root : %s", hexutils.BytesToHex(gvRoot[:])) + log.Infof("genesis_validators_root : %s", hexutils.BytesToHex(st.GenesisValidatorRoot())) log.Infof("slot : %d", st.Slot()) log.Infof("fork : previous_version = %b, current_version = %b", st.Fork().PreviousVersion, st.Fork().CurrentVersion) log.Infof("latest_block_header : sizeSSZ = %s", humanize.Bytes(uint64(st.LatestBlockHeader().SizeSSZ()))) - blockRoots := st.BlockRoots() - bRoots := make([][]byte, len(blockRoots)) - for i := range bRoots { - tmp := blockRoots[i] - bRoots[i] = tmp[:] - } - size, count := sizeAndCountOfByteList(bRoots) + size, count := sizeAndCountOfByteList(st.BlockRoots()) log.Infof("block_roots : size = %s, count = %d", humanize.Bytes(size), count) - stateRoots := st.StateRoots() - sRoots := make([][]byte, len(stateRoots)) - for i := range sRoots { - tmp := stateRoots[i] - sRoots[i] = tmp[:] - } - size, count = sizeAndCountOfByteList(sRoots) + size, count = sizeAndCountOfByteList(st.StateRoots()) log.Infof("state_roots : size = %s, count = %d", humanize.Bytes(size), count) - historicalRoots := st.HistoricalRoots() - hRoots := make([][]byte, len(historicalRoots)) - for i := range hRoots { - tmp := historicalRoots[i] - hRoots[i] = tmp[:] - } - size, count = sizeAndCountOfByteList(hRoots) + size, count = sizeAndCountOfByteList(st.HistoricalRoots()) log.Infof("historical_roots : size = %s, count = %d", humanize.Bytes(size), count) log.Infof("eth1_data : sizeSSZ = %s", humanize.Bytes(uint64(st.Eth1Data().SizeSSZ()))) size, count = sizeAndCountGeneric(st.Eth1DataVotes(), nil) @@ -363,13 +344,7 @@ func printStates(stateC <-chan *modifiedState, doneC chan<- bool) { log.Infof("validators : sizeSSZ = %s, count = %d", humanize.Bytes(size), count) size, count = sizeAndCountOfUin64List(st.Balances()) log.Infof("balances : size = %s, count = %d", humanize.Bytes(size), count) - randaoMixes := st.RandaoMixes() - mixes := make([][]byte, len(randaoMixes)) - for i := range mixes { - tmp := randaoMixes[i] - mixes[i] = tmp[:] - } - size, count = sizeAndCountOfByteList(mixes) + size, count = sizeAndCountOfByteList(st.RandaoMixes()) log.Infof("randao_mixes : size = %s, count = %d", humanize.Bytes(size), count) size, count = sizeAndCountOfUin64List(st.Slashings()) log.Infof("slashings : size = %s, count = %d", humanize.Bytes(size), count) diff --git a/tools/pcli/BUILD.bazel b/tools/pcli/BUILD.bazel index 09a70d3561..93566a3079 100644 --- a/tools/pcli/BUILD.bazel +++ b/tools/pcli/BUILD.bazel @@ -11,7 +11,7 @@ go_library( visibility = ["//visibility:private"], deps = [ "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state-proto/v1:go_default_library", "//encoding/ssz:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", diff --git a/tools/pcli/main.go b/tools/pcli/main.go index f40009ffa9..6d61f0ea8e 100644 --- a/tools/pcli/main.go +++ b/tools/pcli/main.go @@ -12,7 +12,7 @@ import ( fssz "github.com/ferranbt/fastssz" "github.com/kr/pretty" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state-proto/v1" "github.com/prysmaticlabs/prysm/encoding/ssz" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" @@ -191,8 +191,8 @@ func main() { if err := dataFetcher(expectedPostStatePath, expectedState); err != nil { log.Fatal(err) } - if !ssz.DeepEqual(expectedState, postState.ToProtoUnsafe()) { - diff, _ := messagediff.PrettyDiff(expectedState, postState.ToProtoUnsafe()) + if !ssz.DeepEqual(expectedState, postState.InnerStateUnsafe()) { + diff, _ := messagediff.PrettyDiff(expectedState, postState.InnerStateUnsafe()) log.Errorf("Derived state differs from provided post state: %s", diff) } }