Compare commits

...

21 Commits

Author SHA1 Message Date
terence tsao
e2422647d0 More errors. Still not done 2022-12-12 16:53:25 +08:00
terence tsao
f0ea14158e Merge branch 'develop' of github.com:prysmaticlabs/prysm into dev-payload-interfaces-no-panic 2022-12-12 16:02:04 +08:00
terence tsao
c228a3e0f6 Nishant's feedback 2022-12-12 16:01:27 +08:00
terencechain
09619c388f Remove Test_IsExecutionEnabledCapella (#11752)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-11 22:59:12 +00:00
Patrice Vignola
1531313603 Fix DeepSource errors in proposer_bellatrix.go (#11739)
* Fix DeepSource errors in

* Omit receiver name

* Address PR comments

* Remove unused variable

* Fix more DeepSource errors

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-10 10:27:07 +00:00
Potuz
babfc66c5b Check BLS changes when requesting from pool (#11718)
* Check BLS changes when requesting from pool

* Terence's suggestions

* Radek's suggestion

Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2022-12-09 14:41:45 +00:00
terencechain
cb9b5e8f6e Use payload attribute type for engine-API (#11719)
* Add payload attribute type

* Gazelle

* Fix test

* Use new payload attribute type

* Fix test

* Fix test

* Update beacon-chain/execution/engine_client.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Feedbacks

* Fix suggestion

* Update argument, fix test

* Return emptyAttri instead of nil

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-08 21:39:45 +00:00
james-prysm
145eb5a8e4 add m1 chip info (#11736) 2022-12-08 15:20:32 -06:00
Preston Van Loon
7510f584cb beacondb: Remove cache look up and lock request from boltdb transaction for state summaries (#11745)
* Remove cache look up from bolt transaction

* remove bogus line, oops

* Remove independent cache lookup entirely and just use HasStateSummary

* Rm newline
2022-12-08 19:32:04 +00:00
Patrice Vignola
dbeb3ee886 Onboard validator's Beacon REST API usage to e2e tests (#11704)
* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Onboard validator's Beacon REST API usage to e2e tests

* Remove unused variables

* Remove use_beacon_api tags

* Fix DeepSource errors

* Revert unneeded changes

* Revert evaluator changes

* Revert import reordering

* Address PR comments

* Remove all REST API e2e tests except minimal one

* Fix validator pointing to inexisting beacon node port

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-08 14:38:56 +00:00
Preston Van Loon
ca2618110f e2e: Print process IDs for debugging. (#11734)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-08 04:48:16 +00:00
Nishant Das
642c399b9d Add Back Cross Client Option (#11738)
* add changes

* remove env var

* fix
2022-12-07 22:20:35 -06:00
Manu NALEPA
6eee539425 Add REST implementation for Validator's WaitForActivation (Ethereum Protocol Fellowship) (#11671)
* Implement REST `WaitForActivation`

* Activation: Factorize tests

* Fix PR comments

* `missingPubKeys`: Replace map by slice (no need to have a map here)

* Fix typo

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2022-12-07 19:20:11 +00:00
james-prysm
bd82eb873c Fix to Post Submit E2E (#11733) 2022-12-07 18:19:44 +01:00
Nishant Das
62455b7bcb Fix Lint and Minor Bugs in E2E (#11730) 2022-12-07 05:31:53 +00:00
terence tsao
52d48b05f7 Started replacing panics with errors 2022-11-25 08:10:08 -08:00
terencechain
da7876a88a Merge branch 'develop' into inphi/dev-payload-interface 2022-11-25 07:35:08 -08:00
inphi
1863a16c25 fix test for fuzzing 2022-11-21 15:29:13 -05:00
inphi
99dba6d51b Fix spectest build errors 2022-11-21 14:52:55 -05:00
inphi
28c5d6d2cb Merge remote-tracking branch 'origin/develop' into inphi/dev-payload-interface 2022-11-21 14:40:15 -05:00
inphi
eeef4f473c Opaque payload header interface in beacon state
fixes #11604
2022-11-16 13:11:42 -05:00
169 changed files with 2341 additions and 768 deletions

View File

@@ -230,9 +230,3 @@ build --modify_execution_info='GoStdlib.*=+no-remote-cache'
# Set bazel gotag
build --define gotags=bazel
# Build the binary with Beacon API calls for the validator
build --flag_alias=use_beacon_api=//validator/client/validator-client-factory:use_beacon_api
build:beacon_api --use_beacon_api
build:beacon_api --define=gotags=use_beacon_api

View File

@@ -64,6 +64,7 @@ go_library(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",

View File

@@ -181,7 +181,7 @@ func (s *Service) HeadState(ctx context.Context) (state.BeaconState, error) {
span.AddAttributes(trace.BoolAttribute("cache_hit", ok))
if ok {
return s.headState(ctx), nil
return s.headState(ctx)
}
return s.cfg.StateGen.StateByRoot(ctx, s.headRoot())
@@ -195,7 +195,11 @@ func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch types.Epoch)
if !s.hasHeadState() {
return []types.ValidatorIndex{}, nil
}
return helpers.ActiveValidatorIndices(ctx, s.headState(ctx), epoch)
hs, err := s.headState(ctx)
if err != nil {
return nil, err
}
return helpers.ActiveValidatorIndices(ctx, hs, epoch)
}
// HeadGenesisValidatorsRoot returns genesis validators root of the head state.

View File

@@ -198,7 +198,11 @@ 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")
s1, err := headState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := s.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepEqual(t, s1, s2, "Incorrect head state received")
}
func TestGenesisTime_CanRetrieve(t *testing.T) {

View File

@@ -19,8 +19,6 @@ var (
errInvalidNilSummary = errors.New("nil summary returned from the DB")
// errWrongBlockCount is returned when the wrong number of blocks or block roots is used
errWrongBlockCount = errors.New("wrong number of blocks or block roots")
// block is not a valid optimistic candidate block
errNotOptimisticCandidate = errors.New("block is not suitable for optimistic sync")
// errBlockNotFoundInCacheOrDB is returned when a block is not found in the cache or DB.
errBlockNotFoundInCacheOrDB = errors.New("block not found in cache or db")
// errNilStateFromStategen is returned when a nil state is returned from the state generator.

View File

@@ -15,9 +15,11 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/time/slots"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
@@ -67,10 +69,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
}
nextSlot := s.CurrentSlot() + 1 // Cache payload ID for next slot proposer.
hasAttr, attr, proposerId, err := s.getPayloadAttribute(ctx, arg.headState, nextSlot)
if err != nil {
log.WithError(err).Error("Could not get head payload attribute")
}
hasAttr, attr, proposerId := s.getPayloadAttribute(ctx, arg.headState, nextSlot)
payloadID, lastValidHash, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, attr)
if err != nil {
@@ -149,7 +148,8 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
log.WithError(err).Error("Could not set head root to valid")
return nil, nil
}
if hasAttr && payloadID != nil { // If the forkchoice update call has an attribute, update the proposer payload ID cache.
// If the forkchoice update call has an attribute, update the proposer payload ID cache.
if hasAttr && payloadID != nil {
var pId [8]byte
copy(pId[:], payloadID[:])
s.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nextSlot, proposerId, pId, arg.headRoot)
@@ -182,7 +182,7 @@ func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, er
// notifyNewPayload signals execution engine on a new payload.
// It returns true if the EL has returned VALID for the block
func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
postStateHeader interfaces.ExecutionData, blk interfaces.SignedBeaconBlock) (bool, error) {
postStateHeader interfaces.ExecutionDataHeader, blk interfaces.SignedBeaconBlock) (bool, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.notifyNewPayload")
defer span.End()
@@ -250,22 +250,29 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
// getPayloadAttributes returns the payload attributes for the given state and slot.
// The attribute is required to initiate a payload build process in the context of an `engine_forkchoiceUpdated` call.
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot types.Slot) (bool, *enginev1.PayloadAttributes, types.ValidatorIndex, error) {
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot types.Slot) (bool, payloadattribute.Attributer, types.ValidatorIndex) {
emptyAttri := payloadattribute.EmptyWithVersion(st.Version())
// Root is `[32]byte{}` since we are retrieving proposer ID of a given slot. During insertion at assignment the root was not known.
proposerID, _, ok := s.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, [32]byte{} /* root */)
if !ok { // There's no need to build attribute if there is no proposer for slot.
return false, nil, 0, nil
return false, emptyAttri, 0
}
// Get previous randao.
st = st.Copy()
st, err := transition.ProcessSlotsIfPossible(ctx, st, slot)
st, err := st.Copy()
if err != nil {
return false, nil, 0, err
log.WithError(err).Error("Could not copy state")
return false, emptyAttri, 0
}
st, err = transition.ProcessSlotsIfPossible(ctx, st, slot)
if err != nil {
log.WithError(err).Error("Could not process slots to get payload attribute")
return false, emptyAttri, 0
}
prevRando, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
if err != nil {
return false, nil, 0, nil
log.WithError(err).Error("Could not get randao mix to get payload attribute")
return false, emptyAttri, 0
}
// Get fee recipient.
@@ -283,7 +290,8 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
"Please refer to our documentation for instructions")
}
case err != nil:
return false, nil, 0, errors.Wrap(err, "could not get fee recipient in db")
log.WithError(err).Error("Could not get fee recipient to get payload attribute")
return false, emptyAttri, 0
default:
feeRecipient = recipient
}
@@ -291,14 +299,44 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
// Get timestamp.
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
if err != nil {
return false, nil, 0, err
log.WithError(err).Error("Could not get timestamp to get payload attribute")
return false, emptyAttri, 0
}
attr := &enginev1.PayloadAttributes{
Timestamp: uint64(t.Unix()),
PrevRandao: prevRando,
SuggestedFeeRecipient: feeRecipient.Bytes(),
var attr payloadattribute.Attributer
switch st.Version() {
case version.Capella:
withdrawals, err := st.ExpectedWithdrawals()
if err != nil {
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
return false, emptyAttri, 0
}
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
Timestamp: uint64(t.Unix()),
PrevRandao: prevRando,
SuggestedFeeRecipient: feeRecipient.Bytes(),
Withdrawals: withdrawals,
})
if err != nil {
log.WithError(err).Error("Could not get payload attribute")
return false, emptyAttri, 0
}
case version.Bellatrix:
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
Timestamp: uint64(t.Unix()),
PrevRandao: prevRando,
SuggestedFeeRecipient: feeRecipient.Bytes(),
})
if err != nil {
log.WithError(err).Error("Could not get payload attribute")
return false, emptyAttri, 0
}
default:
log.WithField("version", st.Version()).Error("Could not get payload attribute due to unknown state version")
return false, emptyAttri, 0
}
return true, attr, proposerID, nil
return true, attr, proposerID
}
// removeInvalidBlockAndState removes the invalid block and its corresponding state from the cache and DB.

View File

@@ -792,8 +792,8 @@ func Test_GetPayloadAttribute(t *testing.T) {
// Cache miss
service, err := NewService(ctx, opts...)
require.NoError(t, err)
hasPayload, _, vId, err := service.getPayloadAttribute(ctx, nil, 0)
require.NoError(t, err)
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
hasPayload, _, vId := service.getPayloadAttribute(ctx, st, 0)
require.Equal(t, false, hasPayload)
require.Equal(t, types.ValidatorIndex(0), vId)
@@ -801,24 +801,65 @@ func Test_GetPayloadAttribute(t *testing.T) {
suggestedVid := types.ValidatorIndex(1)
slot := types.Slot(1)
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
st, _ := util.DeterministicGenesisState(t, 1)
hook := logTest.NewGlobal()
hasPayload, attr, vId, err := service.getPayloadAttribute(ctx, st, slot)
require.NoError(t, err)
hasPayload, attr, vId := service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient).String())
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
require.LogsContain(t, hook, "Fee recipient is currently using the burn address")
// Cache hit, advance state, has fee recipient
suggestedAddr := common.HexToAddress("123")
require.NoError(t, service.cfg.BeaconDB.SaveFeeRecipientsByValidatorIDs(ctx, []types.ValidatorIndex{suggestedVid}, []common.Address{suggestedAddr}))
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
hasPayload, attr, vId, err = service.getPayloadAttribute(ctx, st, slot)
require.NoError(t, err)
hasPayload, attr, vId = service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient))
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
}
func Test_GetPayloadAttributeV2(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
opts := []Option{
WithDatabase(beaconDB),
WithStateGen(stategen.New(beaconDB, doublylinkedtree.New())),
WithProposerIdsCache(cache.NewProposerPayloadIDsCache()),
}
// Cache miss
service, err := NewService(ctx, opts...)
require.NoError(t, err)
st, _ := util.DeterministicGenesisStateCapella(t, 1)
hasPayload, _, vId := service.getPayloadAttribute(ctx, st, 0)
require.Equal(t, false, hasPayload)
require.Equal(t, types.ValidatorIndex(0), vId)
// Cache hit, advance state, no fee recipient
suggestedVid := types.ValidatorIndex(1)
slot := types.Slot(1)
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
hook := logTest.NewGlobal()
hasPayload, attr, vId := service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
require.LogsContain(t, hook, "Fee recipient is currently using the burn address")
a, err := attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))
// Cache hit, advance state, has fee recipient
suggestedAddr := common.HexToAddress("123")
require.NoError(t, service.cfg.BeaconDB.SaveFeeRecipientsByValidatorIDs(ctx, []types.ValidatorIndex{suggestedVid}, []common.Address{suggestedAddr}))
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
hasPayload, attr, vId = service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
a, err = attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))
}
func Test_UpdateLastValidatedCheckpoint(t *testing.T) {

View File

@@ -201,11 +201,15 @@ func (s *Service) setHead(root [32]byte, block interfaces.SignedBeaconBlock, sta
if err != nil {
return err
}
copiedState, err := state.Copy()
if err != nil {
return err
}
s.head = &head{
slot: block.Block().Slot(),
root: root,
block: bCp,
state: state.Copy(),
state: copiedState,
}
return nil
}
@@ -258,7 +262,7 @@ func (s *Service) headBlock() (interfaces.SignedBeaconBlock, error) {
// This returns the head state.
// It does a full copy on head state for immutability.
// This is a lock free version.
func (s *Service) headState(ctx context.Context) state.BeaconState {
func (s *Service) headState(ctx context.Context) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.headState")
defer span.End()

View File

@@ -89,7 +89,13 @@ func TestSaveHead_Different(t *testing.T) {
pb, err := headBlock.Proto()
require.NoError(t, err)
assert.DeepEqual(t, newHeadSignedBlock, pb, "Head did not change")
assert.DeepSSZEqual(t, headState.ToProto(), service.headState(ctx).ToProto(), "Head did not change")
headStateProto, err := headState.ToProto()
require.NoError(t, err)
hs, err := service.headState(ctx)
require.NoError(t, err)
serviceHeadStateProto, err := hs.ToProto()
require.NoError(t, err)
assert.DeepSSZEqual(t, headStateProto, serviceHeadStateProto, "Head did not change")
}
func TestSaveHead_Different_Reorg(t *testing.T) {
@@ -147,7 +153,13 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
pb, err := headBlock.Proto()
require.NoError(t, err)
assert.DeepEqual(t, newHeadSignedBlock, pb, "Head did not change")
assert.DeepSSZEqual(t, headState.ToProto(), service.headState(ctx).ToProto(), "Head did not change")
headStateProto, err := headState.ToProto()
require.NoError(t, err)
hs, err := service.headState(ctx)
require.NoError(t, err)
serviceHeadStateProto, err := hs.ToProto()
require.NoError(t, err)
assert.DeepSSZEqual(t, headStateProto, serviceHeadStateProto, "Head did not change")
require.LogsContain(t, hook, "Chain reorg occurred")
require.LogsContain(t, hook, "distance=1")
require.LogsContain(t, hook, "depth=1")
@@ -501,7 +513,7 @@ func TestUpdateHead_noSavedChanges(t *testing.T) {
bellatrixState, _ := util.DeterministicGenesisStateBellatrix(t, 2)
require.NoError(t, beaconDB.SaveState(ctx, bellatrixState, bellatrixBlkRoot))
service.cfg.StateGen.SaveFinalizedState(0, bellatrixBlkRoot, bellatrixState)
require.NoError(t, service.cfg.StateGen.SaveFinalizedState(0, bellatrixBlkRoot, bellatrixState))
headRoot := service.headRoot()
require.Equal(t, [32]byte{}, headRoot)

View File

@@ -338,7 +338,11 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
return err
}
default:
return errors.Errorf("invalid state type provided: %T", headState.ToProtoUnsafe())
st, err := headState.ToProtoUnsafe()
if err != nil {
return err
}
return errors.Errorf("invalid state type provided: %T", st)
}
prevEpochActiveBalances.Set(float64(b.ActivePrevEpoch))
prevEpochSourceBalances.Set(float64(b.PrevEpochAttested))

View File

@@ -146,7 +146,8 @@ func TestStore_OnAttestation_Ok_DoublyLinkedTree(t *testing.T) {
att, err := util.GenerateAttestations(genesisState, pks, 1, 0, false)
require.NoError(t, err)
tRoot := bytesutil.ToBytes32(att[0].Data.Target.Root)
copied := genesisState.Copy()
copied, err := genesisState.Copy()
require.NoError(t, err)
copied, err = transition.ProcessSlots(ctx, copied, 1)
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, tRoot))
@@ -256,7 +257,11 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
cached, err = service.checkpointStateCache.StateByCheckpoint(newCheckpoint)
require.NoError(t, err)
require.DeepSSZEqual(t, returned.ToProtoUnsafe(), cached.ToProtoUnsafe())
s1, err := returned.ToProtoUnsafe()
require.NoError(t, err)
s2, err := cached.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2)
}
func TestAttEpoch_MatchPrevEpoch(t *testing.T) {

View File

@@ -282,11 +282,11 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
return nil
}
func getStateVersionAndPayload(st state.BeaconState) (int, interfaces.ExecutionData, error) {
func getStateVersionAndPayload(st state.BeaconState) (int, interfaces.ExecutionDataHeader, error) {
if st == nil {
return 0, nil, errors.New("nil state")
}
var preStateHeader interfaces.ExecutionData
var preStateHeader interfaces.ExecutionDataHeader
var err error
preStateVersion := st.Version()
switch preStateVersion {
@@ -344,7 +344,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
}
type versionAndHeader struct {
version int
header interfaces.ExecutionData
header interfaces.ExecutionDataHeader
}
preVersionAndHeaders := make([]*versionAndHeader, len(blks))
postVersionAndHeaders := make([]*versionAndHeader, len(blks))
@@ -366,7 +366,11 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
}
// Save potential boundary states.
if slots.IsEpochStart(preState.Slot()) {
boundaries[blockRoots[i]] = preState.Copy()
st, err := preState.Copy()
if err != nil {
return err
}
boundaries[blockRoots[i]] = st
}
jCheckpoints[i] = preState.CurrentJustifiedCheckpoint()
fCheckpoints[i] = preState.FinalizedCheckpoint()
@@ -476,8 +480,11 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState state.Beaco
defer span.End()
if postState.Slot()+1 == s.nextEpochBoundarySlot {
copied := postState.Copy()
copied, err := transition.ProcessSlots(ctx, copied, copied.Slot()+1)
copied, err := postState.Copy()
if err != nil {
return err
}
copied, err = transition.ProcessSlots(ctx, copied, copied.Slot()+1)
if err != nil {
return err
}
@@ -627,7 +634,7 @@ func (s *Service) pruneCanonicalAttsFromPool(ctx context.Context, r [32]byte, b
}
// validateMergeTransitionBlock validates the merge transition block.
func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion int, stateHeader interfaces.ExecutionData, blk interfaces.SignedBeaconBlock) error {
func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion int, stateHeader interfaces.ExecutionDataHeader, blk interfaces.SignedBeaconBlock) error {
// Skip validation if block is older than Bellatrix.
if blocks.IsPreBellatrixVersion(blk.Block().Version()) {
return nil
@@ -654,7 +661,7 @@ func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion
// Skip validation if the block is not a merge transition block.
// To reach here. The payload must be non-empty. If the state header is empty then it's at transition.
empty, err := consensusblocks.IsEmptyExecutionData(stateHeader)
empty, err := consensusblocks.IsEmptyExecutionDataHeader(stateHeader)
if err != nil {
return err
}
@@ -718,8 +725,12 @@ func (s *Service) fillMissingBlockPayloadId(ctx context.Context, ti time.Time) e
if err != nil {
return err
} else {
hs, err := s.headState(ctx)
if err != nil {
return err
}
if _, err := s.notifyForkchoiceUpdate(ctx, &notifyForkchoiceUpdateArg{
headState: s.headState(ctx),
headState: hs,
headRoot: s.headRoot(),
headBlock: headBlock.Block(),
}); err != nil {

View File

@@ -66,7 +66,9 @@ func TestStore_OnBlock(t *testing.T) {
require.NoError(t, err)
st, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
copiedSt, err := st.Copy()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copiedSt, validGenesisRoot))
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
require.NoError(t, err)
random := util.NewBeaconBlock()
@@ -76,11 +78,23 @@ func TestStore_OnBlock(t *testing.T) {
randomParentRoot, err := random.Block.HashTreeRoot()
assert.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), randomParentRoot))
copiedSt1, err := st.Copy()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copiedSt1, randomParentRoot))
randomParentRoot2 := roots[1]
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2}))
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)))
copiedSt2, err := st.Copy()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copiedSt2, bytesutil.ToBytes32(randomParentRoot2)))
c1, err := st.Copy()
require.NoError(t, err)
c2, err := st.Copy()
require.NoError(t, err)
c3, err := st.Copy()
require.NoError(t, err)
c4, err := st.Copy()
require.NoError(t, err)
tests := []struct {
name string
blk *ethpb.SignedBeaconBlock
@@ -91,7 +105,7 @@ func TestStore_OnBlock(t *testing.T) {
{
name: "parent block root does not have a state",
blk: util.NewBeaconBlock(),
s: st.Copy(),
s: c1,
wantErrString: "could not reconstruct parent state",
},
{
@@ -102,7 +116,7 @@ func TestStore_OnBlock(t *testing.T) {
b.Block.Slot = params.BeaconConfig().FarFutureSlot
return b
}(),
s: st.Copy(),
s: c2,
wantErrString: "is in the far distant future",
},
{
@@ -112,7 +126,7 @@ func TestStore_OnBlock(t *testing.T) {
b.Block.ParentRoot = randomParentRoot[:]
return b
}(),
s: st.Copy(),
s: c3,
wantErrString: "is not a descendant of the current finalized block",
},
{
@@ -123,7 +137,7 @@ func TestStore_OnBlock(t *testing.T) {
b.Block.ParentRoot = randomParentRoot2
return b
}(),
s: st.Copy(),
s: c4,
wantErrString: "block is equal or earlier than finalized block, slot 0 < slot 0",
},
}
@@ -157,7 +171,8 @@ func TestStore_OnBlockBatch(t *testing.T) {
st, keys := util.DeterministicGenesisState(t, 64)
require.NoError(t, service.saveGenesisData(ctx, st))
bState := st.Copy()
bState, err := st.Copy()
require.NoError(t, err)
var blks []interfaces.SignedBeaconBlock
var blkRoots [][32]byte
@@ -200,7 +215,8 @@ func TestStore_OnBlockBatch_NotifyNewPayload(t *testing.T) {
require.NoError(t, err)
st, keys := util.DeterministicGenesisState(t, 64)
require.NoError(t, service.saveGenesisData(ctx, st))
bState := st.Copy()
bState, err := st.Copy()
require.NoError(t, err)
var blks []interfaces.SignedBeaconBlock
var blkRoots [][32]byte
@@ -370,7 +386,9 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
copied, err := st.Copy()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, validGenesisRoot))
// Define a tree branch, slot 63 <- 64 <- 65
b63 := util.NewBeaconBlock()
@@ -429,7 +447,9 @@ func TestFillForkChoiceMissingBlocks_FinalizedSibling(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
copied, err := st.Copy()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, validGenesisRoot))
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
require.NoError(t, err)
@@ -523,17 +543,25 @@ func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byt
if err := beaconDB.SaveBlock(context.Background(), wsb); err != nil {
return nil, err
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
copied1, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied1, bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
return nil, errors.Wrap(err, "could not save state")
}
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), r1); err != nil {
copied2, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied2, r1); err != nil {
return nil, err
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), r7); err != nil {
copied3, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied3, r7); err != nil {
return nil, err
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), r8); err != nil {
copied4, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied4, r8); err != nil {
return nil, err
}
return [][]byte{r0[:], r1[:], nil, r3[:], r4[:], r5[:], r6[:], r7[:], r8[:]}, nil
@@ -824,7 +852,8 @@ func TestOnBlock_CanFinalize_WithOnTick(t *testing.T) {
require.NoError(t, service.saveGenesisData(ctx, gs))
require.NoError(t, fcs.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{Root: service.originBlockRoot}))
testState := gs.Copy()
testState, err := gs.Copy()
require.NoError(t, err)
for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
blk, err := util.GenerateFullBlock(testState, keys, util.DefaultBlockGenConfig(), i)
require.NoError(t, err)
@@ -873,7 +902,8 @@ func TestOnBlock_CanFinalize(t *testing.T) {
gs, keys := util.DeterministicGenesisState(t, 32)
require.NoError(t, service.saveGenesisData(ctx, gs))
testState := gs.Copy()
testState, err := gs.Copy()
require.NoError(t, err)
for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
blk, err := util.GenerateFullBlock(testState, keys, util.DefaultBlockGenConfig(), i)
require.NoError(t, err)
@@ -975,7 +1005,8 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) {
gs, keys := util.DeterministicGenesisState(t, 32)
require.NoError(t, service.saveGenesisData(ctx, gs))
testState := gs.Copy()
testState, err := gs.Copy()
require.NoError(t, err)
for i := types.Slot(1); i < params.BeaconConfig().SlotsPerEpoch; i++ {
blk, err := util.GenerateFullBlock(testState, keys, util.DefaultBlockGenConfig(), i)
require.NoError(t, err)
@@ -1000,7 +1031,8 @@ func TestInsertFinalizedDeposits(t *testing.T) {
gs, _ := util.DeterministicGenesisState(t, 32)
require.NoError(t, service.saveGenesisData(ctx, gs))
gs = gs.Copy()
gs, err = gs.Copy()
require.NoError(t, err)
assert.NoError(t, gs.SetEth1Data(&ethpb.Eth1Data{DepositCount: 10}))
assert.NoError(t, gs.SetEth1DepositIndex(8))
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
@@ -1034,11 +1066,13 @@ func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) {
gs, _ := util.DeterministicGenesisState(t, 32)
require.NoError(t, service.saveGenesisData(ctx, gs))
gs = gs.Copy()
gs, err = gs.Copy()
require.NoError(t, err)
assert.NoError(t, gs.SetEth1Data(&ethpb.Eth1Data{DepositCount: 7}))
assert.NoError(t, gs.SetEth1DepositIndex(6))
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
gs2 := gs.Copy()
gs2, err := gs.Copy()
require.NoError(t, err)
assert.NoError(t, gs2.SetEth1Data(&ethpb.Eth1Data{DepositCount: 15}))
assert.NoError(t, gs2.SetEth1DepositIndex(13))
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}, gs2))

View File

@@ -109,7 +109,8 @@ func TestProcessAttestations_Ok(t *testing.T) {
atts, err := util.GenerateAttestations(genesisState, pks, 1, 0, false)
require.NoError(t, err)
tRoot := bytesutil.ToBytes32(atts[0].Data.Target.Root)
copied := genesisState.Copy()
copied, err := genesisState.Copy()
require.NoError(t, err)
copied, err = transition.ProcessSlots(ctx, copied, 1)
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, tRoot))
@@ -212,7 +213,8 @@ func TestService_ProcessAttestationsAndUpdateHead(t *testing.T) {
service.genesisTime = prysmTime.Now().Add(-2 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
genesisState, pks := util.DeterministicGenesisState(t, 64)
require.NoError(t, service.saveGenesisData(ctx, genesisState))
copied := genesisState.Copy()
copied, err := genesisState.Copy()
require.NoError(t, err)
// Generate a new block for attesters to attest
blk, err := util.GenerateFullBlock(copied, pks, util.DefaultBlockGenConfig(), 1)
require.NoError(t, err)
@@ -269,7 +271,8 @@ func TestService_UpdateHead_NoAtts(t *testing.T) {
service.genesisTime = prysmTime.Now().Add(-2 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
genesisState, pks := util.DeterministicGenesisState(t, 64)
require.NoError(t, service.saveGenesisData(ctx, genesisState))
copied := genesisState.Copy()
copied, err := genesisState.Copy()
require.NoError(t, err)
// Generate a new block
blk, err := util.GenerateFullBlock(copied, pks, util.DefaultBlockGenConfig(), 1)
require.NoError(t, err)

View File

@@ -33,7 +33,7 @@ func TestService_ReceiveBlock(t *testing.T) {
assert.NoError(t, err)
return blk
}
params.SetupTestConfigCleanupWithLock(t)
//params.SetupTestConfigCleanupWithLock(t)
bc := params.BeaconConfig().Copy()
bc.ShardCommitteePeriod = 0 // Required for voluntary exits test in reasonable time.
params.OverrideBeaconConfig(bc)

View File

@@ -431,7 +431,9 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState state.Beacon
}
s.originBlockRoot = genesisBlkRoot
s.cfg.StateGen.SaveFinalizedState(0 /*slot*/, genesisBlkRoot, genesisState)
if err := s.cfg.StateGen.SaveFinalizedState(0 /*slot*/, genesisBlkRoot, genesisState); err != nil {
return err
}
if err := s.cfg.ForkChoiceStore.InsertNode(ctx, genesisState, genesisBlkRoot); err != nil {
log.WithError(err).Fatal("Could not process genesis block for fork choice")

View File

@@ -83,7 +83,9 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
srv.Stop()
})
bState, _ := util.DeterministicGenesisState(t, 10)
pbState, err := state_native.ProtobufBeaconStatePhase0(bState.ToProtoUnsafe())
pbUnsafe, err := bState.ToProtoUnsafe()
require.NoError(t, err)
pbState, err := state_native.ProtobufBeaconStatePhase0(pbUnsafe)
require.NoError(t, err)
mockTrie, err := trie.NewTrie(0)
require.NoError(t, err)
@@ -325,7 +327,11 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
assert.DeepEqual(t, headBlock, pb, "Head block incorrect")
s, err := c.HeadState(ctx)
require.NoError(t, err)
assert.DeepSSZEqual(t, headState.ToProtoUnsafe(), s.ToProtoUnsafe(), "Head state incorrect")
s1, err := headState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := s.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, s1, s2, "Head state incorrect")
assert.Equal(t, c.HeadSlot(), headBlock.Block.Slot, "Head slot incorrect")
r, err := c.HeadRoot(context.Background())
require.NoError(t, err)
@@ -380,7 +386,11 @@ 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")
s1, err := headState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := s.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, s1, s2, "Head state incorrect")
assert.Equal(t, genesisRoot, c.originBlockRoot, "Genesis block root incorrect")
pb, err := c.head.block.Proto()
require.NoError(t, err)

View File

@@ -33,9 +33,13 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
s, err = cache.StateByCheckpoint(cp1)
require.NoError(t, err)
pbState1, err := state_native.ProtobufBeaconStatePhase0(s.ToProtoUnsafe())
pbs1, err := s.ToProtoUnsafe()
require.NoError(t, err)
pbstate, err := state_native.ProtobufBeaconStatePhase0(st.ToProtoUnsafe())
pbState1, err := state_native.ProtobufBeaconStatePhase0(pbs1)
require.NoError(t, err)
pbs2, err := st.ToProtoUnsafe()
require.NoError(t, err)
pbstate, err := state_native.ProtobufBeaconStatePhase0(pbs2)
require.NoError(t, err)
if !proto.Equal(pbState1, pbstate) {
t.Error("incorrectly cached state")
@@ -50,11 +54,19 @@ 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")
sProto, err := s.ToProto()
require.NoError(t, err)
st2Proto, err := st2.ToProto()
require.NoError(t, err)
assert.DeepEqual(t, st2Proto, sProto, "incorrectly cached state")
s, err = cache.StateByCheckpoint(cp1)
require.NoError(t, err)
assert.DeepEqual(t, st.ToProto(), s.ToProto(), "incorrectly cached state")
stProto, err := st.ToProto()
require.NoError(t, err)
sProto, err = s.ToProto()
require.NoError(t, err)
assert.DeepEqual(t, stProto, sProto, "incorrectly cached state")
}
func TestCheckpointStateCache_MaxSize(t *testing.T) {

View File

@@ -94,7 +94,11 @@ func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (state.BeaconState,
if exists && item != nil {
skipSlotCacheHit.Inc()
span.AddAttributes(trace.BoolAttribute("hit", true))
return item.(state.BeaconState).Copy(), nil
c, err := item.(state.BeaconState).Copy()
if err != nil {
return nil, err
}
return c, nil
}
skipSlotCacheMiss.Inc()
span.AddAttributes(trace.BoolAttribute("hit", false))
@@ -132,10 +136,15 @@ func (c *SkipSlotCache) MarkNotInProgress(r [32]byte) {
}
// Put the response in the cache.
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state state.BeaconState) {
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state state.BeaconState) error {
if c.disabled {
return
return nil
}
// Copy state so cached value is not mutated.
c.cache.Add(r, state.Copy())
cpy, err := state.Copy()
if err != nil {
return err
}
c.cache.Add(r, cpy)
return nil
}

View File

@@ -28,10 +28,14 @@ func TestSkipSlotCache_RoundTrip(t *testing.T) {
})
require.NoError(t, err)
c.Put(ctx, r, s)
require.NoError(t, c.Put(ctx, r, s))
c.MarkNotInProgress(r)
res, err := c.Get(ctx, r)
require.NoError(t, err)
assert.DeepEqual(t, res.ToProto(), s.ToProto(), "Expected equal protos to return from cache")
resProto, err := res.ToProto()
require.NoError(t, err)
sProto, err := s.ToProto()
require.NoError(t, err)
assert.DeepEqual(t, resProto, sProto, "Expected equal protos to return from cache")
}

View File

@@ -307,7 +307,8 @@ func TestProcessRewardsAndPenaltiesPrecompute_InactivityLeak(t *testing.T) {
require.NoError(t, err)
validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
sCopy := s.Copy()
sCopy, err := s.Copy()
require.NoError(t, err)
s, err = ProcessRewardsAndPenaltiesPrecompute(s, balance, validators)
require.NoError(t, err)

View File

@@ -72,7 +72,8 @@ func TestTranslateParticipation(t *testing.T) {
func TestUpgradeToAltair(t *testing.T) {
st, _ := util.DeterministicGenesisState(t, params.BeaconConfig().MaxValidatorsPerCommittee)
preForkState := st.Copy()
preForkState, err := st.Copy()
require.NoError(t, err)
aState, err := altair.UpgradeToAltair(context.Background(), st)
require.NoError(t, err)

View File

@@ -41,7 +41,7 @@ func IsMergeTransitionComplete(st state.BeaconState) (bool, error) {
if err != nil {
return false, err
}
isEmpty, err := blocks.IsEmptyExecutionData(h)
isEmpty, err := blocks.IsEmptyExecutionDataHeader(h)
if err != nil {
return false, err
}
@@ -96,8 +96,8 @@ func IsExecutionEnabled(st state.BeaconState, body interfaces.BeaconBlockBody) (
// IsExecutionEnabledUsingHeader returns true if the execution is enabled using post processed payload header and block body.
// This is an optimized version of IsExecutionEnabled where beacon state is not required as an argument.
func IsExecutionEnabledUsingHeader(header interfaces.ExecutionData, body interfaces.BeaconBlockBody) (bool, error) {
isEmpty, err := blocks.IsEmptyExecutionData(header)
func IsExecutionEnabledUsingHeader(header interfaces.ExecutionDataHeader, body interfaces.BeaconBlockBody) (bool, error) {
isEmpty, err := blocks.IsEmptyExecutionDataHeader(header)
if err != nil {
return false, err
}
@@ -120,7 +120,7 @@ func IsPreBellatrixVersion(v int) bool {
// # Verify consistency of the parent hash with respect to the previous execution payload header
// if is_merge_complete(state):
// assert payload.parent_hash == state.latest_execution_payload_header.block_hash
func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload interfaces.ExecutionData) error {
func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload interfaces.ExecutionDataHeader) error {
complete, err := IsMergeTransitionComplete(st)
if err != nil {
return err
@@ -223,7 +223,7 @@ func ProcessPayload(st state.BeaconState, payload interfaces.ExecutionData) (sta
}
// ValidatePayloadHeaderWhenMergeCompletes validates the payload header when the merge completes.
func ValidatePayloadHeaderWhenMergeCompletes(st state.BeaconState, header interfaces.ExecutionData) error {
func ValidatePayloadHeaderWhenMergeCompletes(st state.BeaconState, header interfaces.ExecutionDataHeader) error {
// Skip validation if the state is not merge compatible.
complete, err := IsMergeTransitionComplete(st)
if err != nil {
@@ -244,7 +244,7 @@ func ValidatePayloadHeaderWhenMergeCompletes(st state.BeaconState, header interf
}
// ValidatePayloadHeader validates the payload header.
func ValidatePayloadHeader(st state.BeaconState, header interfaces.ExecutionData) error {
func ValidatePayloadHeader(st state.BeaconState, header interfaces.ExecutionDataHeader) error {
// Validate header's random mix matches with state in current epoch
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
if err != nil {
@@ -266,7 +266,7 @@ func ValidatePayloadHeader(st state.BeaconState, header interfaces.ExecutionData
}
// ProcessPayloadHeader processes the payload header.
func ProcessPayloadHeader(st state.BeaconState, header interfaces.ExecutionData) (state.BeaconState, error) {
func ProcessPayloadHeader(st state.BeaconState, header interfaces.ExecutionDataHeader) (state.BeaconState, error) {
if err := ValidatePayloadHeaderWhenMergeCompletes(st, header); err != nil {
return nil, err
}

View File

@@ -350,16 +350,6 @@ func Test_IsExecutionEnabled(t *testing.T) {
}
}
func Test_IsExecutionEnabledCapella(t *testing.T) {
st, _ := util.DeterministicGenesisStateCapella(t, 1)
blk := util.NewBeaconBlockCapella()
body, err := consensusblocks.NewBeaconBlockBody(blk.Block.Body)
require.NoError(t, err)
got, err := blocks.IsExecutionEnabled(st, body)
require.NoError(t, err)
require.Equal(t, false, got)
}
func Test_IsExecutionEnabledUsingHeader(t *testing.T) {
tests := []struct {
name string
@@ -747,7 +737,8 @@ func Test_ValidatePayloadHeader(t *testing.T) {
func Test_ValidatePayloadHeaderWhenMergeCompletes(t *testing.T) {
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
emptySt := st.Copy()
emptySt, err := st.Copy()
require.NoError(t, err)
wrappedHeader, err := consensusblocks.WrappedExecutionPayloadHeader(&enginev1.ExecutionPayloadHeader{BlockHash: []byte{'a'}})
require.NoError(t, err)
require.NoError(t, st.SetLatestExecutionPayloadHeader(wrappedHeader))

View File

@@ -2,7 +2,6 @@ package blocks
import (
"bytes"
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
@@ -153,7 +152,6 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
}
func BLSChangesSignatureBatch(
ctx context.Context,
st state.ReadOnlyBeaconState,
changes []*ethpb.SignedBLSToExecutionChange,
) (*bls.SignatureBatch, error) {
@@ -172,9 +170,6 @@ func BLSChangesSignatureBatch(
return nil, err
}
for i, change := range changes {
if ctx.Err() != nil {
return nil, ctx.Err()
}
batch.Signatures[i] = change.Signature
publicKey, err := bls.PublicKeyFromBytes(change.Message.FromBlsPubkey)
if err != nil {

View File

@@ -1,7 +1,6 @@
package blocks_test
import (
"context"
"math/rand"
"testing"
@@ -746,7 +745,7 @@ func TestBLSChangesSignatureBatch(t *testing.T) {
}
signedChanges[i] = signed
}
batch, err := blocks.BLSChangesSignatureBatch(context.Background(), st, signedChanges)
batch, err := blocks.BLSChangesSignatureBatch(st, signedChanges)
require.NoError(t, err)
verify, err := batch.Verify()
require.NoError(t, err)

View File

@@ -15,7 +15,8 @@ import (
func TestUpgradeToCapella(t *testing.T) {
st, _ := util.DeterministicGenesisStateBellatrix(t, params.BeaconConfig().MaxValidatorsPerCommittee)
preForkState := st.Copy()
preForkState, err := st.Copy()
require.NoError(t, err)
mSt, err := capella.UpgradeToCapella(st)
require.NoError(t, err)

View File

@@ -14,7 +14,8 @@ import (
func TestUpgradeToBellatrix(t *testing.T) {
st, _ := util.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
preForkState := st.Copy()
preForkState, err := st.Copy()
require.NoError(t, err)
mSt, err := execution.UpgradeToBellatrix(st)
require.NoError(t, err)

View File

@@ -50,7 +50,9 @@ func TestExecuteAltairStateTransitionNoVerify_FullProcess(t *testing.T) {
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1))
nextSlotState, err := transition.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1)
c, err := beaconState.Copy()
require.NoError(t, err)
nextSlotState, err := transition.ProcessSlots(context.Background(), c, beaconState.Slot()+1)
require.NoError(t, err)
parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
@@ -96,7 +98,8 @@ func TestExecuteAltairStateTransitionNoVerify_FullProcess(t *testing.T) {
require.NoError(t, err)
block.Block.StateRoot = stateRoot[:]
c := beaconState.Copy()
c, err = beaconState.Copy()
require.NoError(t, err)
sig, err := util.BlockSignatureAltair(c, block.Block, privKeys)
require.NoError(t, err)
block.Signature = sig.Marshal()
@@ -137,7 +140,9 @@ func TestExecuteAltairStateTransitionNoVerifySignature_CouldNotVerifyStateRoot(t
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1))
nextSlotState, err := transition.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1)
c, err := beaconState.Copy()
require.NoError(t, err)
nextSlotState, err := transition.ProcessSlots(context.Background(), c, beaconState.Slot()+1)
require.NoError(t, err)
parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
@@ -184,7 +189,8 @@ func TestExecuteAltairStateTransitionNoVerifySignature_CouldNotVerifyStateRoot(t
require.NoError(t, err)
block.Block.StateRoot = stateRoot[:]
c := beaconState.Copy()
c, err = beaconState.Copy()
require.NoError(t, err)
sig, err := util.BlockSignatureAltair(c, block.Block, privKeys)
require.NoError(t, err)
block.Signature = sig.Marshal()
@@ -235,7 +241,8 @@ func createFullAltairBlockWithOperations(t *testing.T) (state.BeaconState,
sCom, err := altair.NextSyncCommittee(context.Background(), beaconState)
assert.NoError(t, err)
assert.NoError(t, beaconState.SetCurrentSyncCommittee(sCom))
tState := beaconState.Copy()
tState, err := beaconState.Copy()
assert.NoError(t, err)
blk, err := util.GenerateFullBlockAltair(tState, privKeys,
&util.BlockGenConfig{NumAttestations: 1, NumVoluntaryExits: 0, NumDeposits: 0}, 1)
require.NoError(t, err)

View File

@@ -52,7 +52,9 @@ func TestExecuteBellatrixStateTransitionNoVerify_FullProcess(t *testing.T) {
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1))
nextSlotState, err := transition.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1)
copied, err := beaconState.Copy()
require.NoError(t, err)
nextSlotState, err := transition.ProcessSlots(context.Background(), copied, beaconState.Slot()+1)
require.NoError(t, err)
parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
@@ -98,7 +100,8 @@ func TestExecuteBellatrixStateTransitionNoVerify_FullProcess(t *testing.T) {
require.NoError(t, err)
block.Block.StateRoot = stateRoot[:]
c := beaconState.Copy()
c, err := beaconState.Copy()
require.NoError(t, err)
sig, err := util.BlockSignature(c, block.Block, privKeys)
require.NoError(t, err)
block.Signature = sig.Marshal()
@@ -139,7 +142,9 @@ func TestExecuteBellatrixStateTransitionNoVerifySignature_CouldNotVerifyStateRoo
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1))
nextSlotState, err := transition.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1)
copied, err := beaconState.Copy()
require.NoError(t, err)
nextSlotState, err := transition.ProcessSlots(context.Background(), copied, beaconState.Slot()+1)
require.NoError(t, err)
parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
@@ -186,7 +191,8 @@ func TestExecuteBellatrixStateTransitionNoVerifySignature_CouldNotVerifyStateRoo
require.NoError(t, err)
block.Block.StateRoot = stateRoot[:]
c := beaconState.Copy()
c, err := beaconState.Copy()
require.NoError(t, err)
sig, err := util.BlockSignature(c, block.Block, privKeys)
require.NoError(t, err)
block.Signature = sig.Marshal()

View File

@@ -25,7 +25,8 @@ func BenchmarkExecuteStateTransition_FullBlock(b *testing.B) {
defer undo()
beaconState, err := benchmark.PreGenState1Epoch()
require.NoError(b, err)
cleanStates := clonedStates(beaconState)
cleanStates, err := clonedStates(beaconState)
require.NoError(b, err)
block, err := benchmark.PreGenFullBlock()
require.NoError(b, err)
@@ -45,7 +46,8 @@ func BenchmarkExecuteStateTransition_WithCache(b *testing.B) {
beaconState, err := benchmark.PreGenState1Epoch()
require.NoError(b, err)
cleanStates := clonedStates(beaconState)
cleanStates, err := clonedStates(beaconState)
require.NoError(b, err)
block, err := benchmark.PreGenFullBlock()
require.NoError(b, err)
@@ -88,7 +90,9 @@ func BenchmarkProcessEpoch_2FullEpochs(b *testing.B) {
for i := 0; i < b.N; i++ {
// ProcessEpochPrecompute is the optimized version of process epoch. It's enabled by default
// at run time.
_, err := coreState.ProcessEpochPrecompute(context.Background(), beaconState.Copy())
copied, err := beaconState.Copy()
require.NoError(b, err)
_, err = coreState.ProcessEpochPrecompute(context.Background(), copied)
require.NoError(b, err)
}
}
@@ -124,7 +128,9 @@ func BenchmarkHashTreeRootState_FullState(b *testing.B) {
func BenchmarkMarshalState_FullState(b *testing.B) {
beaconState, err := benchmark.PreGenstateFullEpochs()
require.NoError(b, err)
natState, err := state_native.ProtobufBeaconStatePhase0(beaconState.ToProtoUnsafe())
pb, err := beaconState.ToProtoUnsafe()
require.NoError(b, err)
natState, err := state_native.ProtobufBeaconStatePhase0(pb)
require.NoError(b, err)
b.Run("Proto_Marshal", func(b *testing.B) {
b.ResetTimer()
@@ -148,7 +154,9 @@ func BenchmarkMarshalState_FullState(b *testing.B) {
func BenchmarkUnmarshalState_FullState(b *testing.B) {
beaconState, err := benchmark.PreGenstateFullEpochs()
require.NoError(b, err)
natState, err := state_native.ProtobufBeaconStatePhase0(beaconState.ToProtoUnsafe())
pb, err := beaconState.ToProtoUnsafe()
require.NoError(b, err)
natState, err := state_native.ProtobufBeaconStatePhase0(pb)
require.NoError(b, err)
protoObject, err := proto.Marshal(natState)
require.NoError(b, err)
@@ -173,10 +181,14 @@ func BenchmarkUnmarshalState_FullState(b *testing.B) {
})
}
func clonedStates(beaconState state.BeaconState) []state.BeaconState {
func clonedStates(beaconState state.BeaconState) ([]state.BeaconState, error) {
clonedStates := make([]state.BeaconState, runAmount)
var err error
for i := 0; i < runAmount; i++ {
clonedStates[i] = beaconState.Copy()
clonedStates[i], err = beaconState.Copy()
if err != nil {
return nil, err
}
}
return clonedStates
return clonedStates, nil
}

View File

@@ -20,7 +20,9 @@ func TestSkipSlotCache_OK(t *testing.T) {
transition.SkipSlotCache.Enable()
defer transition.SkipSlotCache.Disable()
bState, privs := util.DeterministicGenesisState(t, params.MinimalSpecConfig().MinGenesisActiveValidatorCount)
pbState, err := state_native.ProtobufBeaconStatePhase0(bState.ToProto())
bStateProto, err := bState.ToProto()
require.NoError(t, err)
pbState, err := state_native.ProtobufBeaconStatePhase0(bStateProto)
require.NoError(t, err)
originalState, err := state_native.InitializeFromProtoPhase0(pbState)
require.NoError(t, err)
@@ -42,12 +44,18 @@ func TestSkipSlotCache_OK(t *testing.T) {
bState, err = transition.ExecuteStateTransition(context.Background(), bState, wsb)
require.NoError(t, err, "Could not process state transition")
assert.DeepEqual(t, originalState.ToProto(), bState.ToProto(), "Skipped slots cache leads to different states")
originalStateProto, err := originalState.ToProto()
require.NoError(t, err)
bStateProto, err = bState.ToProto()
require.NoError(t, err)
assert.DeepEqual(t, originalStateProto, bStateProto, "Skipped slots cache leads to different states")
}
func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
bState, privs := util.DeterministicGenesisState(t, params.MinimalSpecConfig().MinGenesisActiveValidatorCount)
pbState, err := state_native.ProtobufBeaconStatePhase0(bState.ToProto())
bStateProto, err := bState.ToProto()
require.NoError(t, err)
pbState, err := state_native.ProtobufBeaconStatePhase0(bStateProto)
require.NoError(t, err)
originalState, err := state_native.InitializeFromProtoPhase0(pbState)
require.NoError(t, err)
@@ -70,7 +78,9 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
// Create two shallow but different forks
var s1, s0 state.BeaconState
{
blk, err := util.GenerateFullBlock(originalState.Copy(), privs, blkCfg, originalState.Slot()+10)
c0, err := originalState.Copy()
require.NoError(t, err)
blk, err := util.GenerateFullBlock(c0, privs, blkCfg, originalState.Slot()+10)
require.NoError(t, err)
copy(blk.Block.Body.Graffiti, "block 1")
signature, err := util.BlockSignature(originalState, blk.Block, privs)
@@ -78,12 +88,14 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
blk.Signature = signature.Marshal()
wsb, err := blocks.NewSignedBeaconBlock(blk)
require.NoError(t, err)
s1, err = transition.ExecuteStateTransition(context.Background(), originalState.Copy(), wsb)
s1, err = transition.ExecuteStateTransition(context.Background(), c0, wsb)
require.NoError(t, err, "Could not run state transition")
}
{
blk, err := util.GenerateFullBlock(originalState.Copy(), privs, blkCfg, originalState.Slot()+10)
c1, err := originalState.Copy()
require.NoError(t, err)
blk, err := util.GenerateFullBlock(c1, privs, blkCfg, originalState.Slot()+10)
require.NoError(t, err)
copy(blk.Block.Body.Graffiti, "block 2")
signature, err := util.BlockSignature(originalState, blk.Block, privs)
@@ -91,7 +103,7 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
blk.Signature = signature.Marshal()
wsb, err := blocks.NewSignedBeaconBlock(blk)
require.NoError(t, err)
s0, err = transition.ExecuteStateTransition(context.Background(), originalState.Copy(), wsb)
s0, err = transition.ExecuteStateTransition(context.Background(), c1, wsb)
require.NoError(t, err, "Could not run state transition")
}
@@ -116,28 +128,38 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
} else {
st = s0
}
setups = append(setups, st.Copy())
c, err := st.Copy()
require.NoError(t, err)
setups = append(setups, c)
}
problemSlot := s1.Slot() + 2
expected1, err := transition.ProcessSlots(context.Background(), s1.Copy(), problemSlot)
s1Copied, err := s1.Copy()
require.NoError(t, err)
expected1, err := transition.ProcessSlots(context.Background(), s1Copied, problemSlot)
require.NoError(t, err)
expectedRoot1, err := expected1.HashTreeRoot(context.Background())
require.NoError(t, err)
t.Logf("chain 1 (even i) expected root %x at slot %d", expectedRoot1[:], problemSlot)
tmp1, err := transition.ProcessSlots(context.Background(), expected1.Copy(), problemSlot+1)
expectedS1Copied, err := expected1.Copy()
require.NoError(t, err)
tmp1, err := transition.ProcessSlots(context.Background(), expectedS1Copied, 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")
expected2, err := transition.ProcessSlots(context.Background(), s0.Copy(), problemSlot)
s0Copied, err := s0.Copy()
require.NoError(t, err)
expected2, err := transition.ProcessSlots(context.Background(), s0Copied, problemSlot)
require.NoError(t, err)
expectedRoot2, err := expected2.HashTreeRoot(context.Background())
require.NoError(t, err)
t.Logf("chain 2 (odd i) expected root %x at slot %d", expectedRoot2[:], problemSlot)
tmp2, err := transition.ProcessSlots(context.Background(), expected2.Copy(), problemSlot+1)
expectedS2Copied, err := expected2.Copy()
require.NoError(t, err)
tmp2, err := transition.ProcessSlots(context.Background(), expectedS2Copied, 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")

View File

@@ -98,9 +98,13 @@ func TestGenesisState_HashEquality(t *testing.T) {
state, err := transition.GenesisBeaconState(context.Background(), deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
require.NoError(t, err)
pbState1, err := state_native.ProtobufBeaconStatePhase0(state1.ToProto())
state1Proto, err := state1.ToProto()
require.NoError(t, err)
pbstate, err := state_native.ProtobufBeaconStatePhase0(state.ToProto())
stateProto, err := state.ToProto()
require.NoError(t, err)
pbState1, err := state_native.ProtobufBeaconStatePhase0(state1Proto)
require.NoError(t, err)
pbstate, err := state_native.ProtobufBeaconStatePhase0(stateProto)
require.NoError(t, err)
root1, err1 := hash.HashProto(pbState1)

View File

@@ -41,7 +41,7 @@ func NextSlotState(_ context.Context, root []byte) (state.BeaconState, error) {
}
nextSlotCacheHit.Inc()
// Returning copied state.
return nsc.state.Copy(), nil
return nsc.state.Copy()
}
// UpdateNextSlotCache updates the `nextSlotCache`. It saves the input state after advancing the state slot by 1
@@ -49,8 +49,12 @@ func NextSlotState(_ context.Context, root []byte) (state.BeaconState, error) {
// This is useful to call after successfully processing a block.
func UpdateNextSlotCache(ctx context.Context, root []byte, state state.BeaconState) error {
// Advancing one slot by using a copied state.
copied := state.Copy()
copied, err := ProcessSlots(ctx, copied, copied.Slot()+1)
copied, err := state.Copy()
if err != nil {
return err
}
copied, err = ProcessSlots(ctx, copied, copied.Slot()+1)
if err != nil {
return err
}

View File

@@ -239,7 +239,7 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
tracing.AnnotateError(span, ctx.Err())
// Cache last best value.
if highestSlot < state.Slot() {
if SkipSlotCache.Put(ctx, key, state); err != nil {
if err := SkipSlotCache.Put(ctx, key, state); err != nil {
log.WithError(err).Error("Failed to put skip slot cache value")
}
}
@@ -299,7 +299,10 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
}
if highestSlot < state.Slot() {
SkipSlotCache.Put(ctx, key, state)
err := SkipSlotCache.Put(ctx, key, state)
if err != nil {
return nil, err
}
}
return state, nil

View File

@@ -127,10 +127,12 @@ func CalculateStateRoot(
}
// Copy state to avoid mutating the state reference.
state = state.Copy()
state, err := state.Copy()
if err != nil {
return [32]byte{}, err
}
// Execute per slots transition.
var err error
parentRoot := signed.Block().ParentRoot()
state, err = ProcessSlotsUsingNextSlotCache(ctx, state, parentRoot[:], signed.Block().Slot())
if err != nil {
@@ -205,7 +207,7 @@ func ProcessBlockNoVerifyAnySig(
if err != nil {
return nil, nil, errors.Wrap(err, "could not get BLSToExecutionChanges")
}
cSet, err := b.BLSChangesSignatureBatch(ctx, st, changes)
cSet, err := b.BLSChangesSignatureBatch(st, changes)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get BLSToExecutionChanges signatures")
}

View File

@@ -39,7 +39,9 @@ func TestExecuteStateTransitionNoVerify_FullProcess(t *testing.T) {
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1))
nextSlotState, err := transition.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1)
copied, err := beaconState.Copy()
require.NoError(t, err)
nextSlotState, err := transition.ProcessSlots(context.Background(), copied, beaconState.Slot()+1)
require.NoError(t, err)
parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
@@ -95,7 +97,9 @@ func TestExecuteStateTransitionNoVerifySignature_CouldNotVerifyStateRoot(t *test
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1))
nextSlotState, err := transition.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1)
copied, err := beaconState.Copy()
require.NoError(t, err)
nextSlotState, err := transition.ProcessSlots(context.Background(), copied, beaconState.Slot()+1)
require.NoError(t, err)
parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)

View File

@@ -76,7 +76,9 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1))
nextSlotState, err := transition.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1)
copied, err := beaconState.Copy()
require.NoError(t, err)
nextSlotState, err := transition.ProcessSlots(context.Background(), copied, beaconState.Slot()+1)
require.NoError(t, err)
parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
@@ -339,7 +341,8 @@ func createFullBlockWithOperations(t *testing.T) (state.BeaconState,
require.NoError(t, beaconState.SetLatestBlockHeader(header))
parentRoot, err := beaconState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(beaconState.Slot()+1))
randaoReveal, err := util.RandaoReveal(copied, currentEpoch, privKeys)
require.NoError(t, err)

View File

@@ -328,8 +328,8 @@ func (s *Store) SaveBlocks(ctx context.Context, blks []interfaces.SignedBeaconBl
func (s *Store) SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveHeadBlockRoot")
defer span.End()
hasStateSummary := s.HasStateSummary(ctx, blockRoot)
return s.db.Update(func(tx *bolt.Tx) error {
hasStateSummary := s.hasStateSummaryBytes(tx, blockRoot)
hasStateInDB := tx.Bucket(stateBucket).Get(blockRoot[:]) != nil
if !(hasStateInDB || hasStateSummary) {
return errors.New("no state or state summary found with head block root")

View File

@@ -59,9 +59,9 @@ func (s *Store) SaveJustifiedCheckpoint(ctx context.Context, checkpoint *ethpb.C
if err != nil {
return err
}
hasStateSummary := s.HasStateSummary(ctx, bytesutil.ToBytes32(checkpoint.Root))
return s.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(checkpointBucket)
hasStateSummary := s.hasStateSummaryBytes(tx, bytesutil.ToBytes32(checkpoint.Root))
hasStateInDB := tx.Bucket(stateBucket).Get(checkpoint.Root) != nil
if !(hasStateInDB || hasStateSummary) {
log.Warnf("Recovering state summary for justified root: %#x", bytesutil.Trunc(checkpoint.Root))
@@ -82,9 +82,9 @@ func (s *Store) SaveFinalizedCheckpoint(ctx context.Context, checkpoint *ethpb.C
if err != nil {
return err
}
hasStateSummary := s.HasStateSummary(ctx, bytesutil.ToBytes32(checkpoint.Root))
return s.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(checkpointBucket)
hasStateSummary := s.hasStateSummaryBytes(tx, bytesutil.ToBytes32(checkpoint.Root))
hasStateInDB := tx.Bucket(stateBucket).Get(checkpoint.Root) != nil
if !(hasStateInDB || hasStateSummary) {
log.Warnf("Recovering state summary for finalized root: %#x", bytesutil.Trunc(checkpoint.Root))

View File

@@ -92,7 +92,9 @@ func Test_migrateStateValidators(t *testing.T) {
assert.NoError(t, hashErr)
individualHashes = append(individualHashes, hash[:])
}
pbState, err := state_native.ProtobufBeaconStatePhase0(st.ToProtoUnsafe())
s, err := st.ToProtoUnsafe()
assert.NoError(t, err)
pbState, err := state_native.ProtobufBeaconStatePhase0(s)
assert.NoError(t, err)
validatorsFoundCount := 0
for _, val := range pbState.Validators {
@@ -138,7 +140,11 @@ 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")
s1, err := rcvdState.ToProtoUnsafe()
assert.NoError(t, err)
s2, err := state.ToProtoUnsafe()
assert.NoError(t, err)
require.DeepSSZEqual(t, s1, s2, "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
@@ -151,7 +157,9 @@ 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 := state_native.ProtobufBeaconStatePhase0(rcvdState.ToProtoUnsafe())
s3, err := rcvdState.ToProtoUnsafe()
assert.NoError(t, err)
pbState, err := state_native.ProtobufBeaconStatePhase0(s3)
assert.NoError(t, err)
validatorsFoundCount := 0
for _, val := range pbState.Validators {
@@ -241,7 +249,11 @@ 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")
s1, err := rcvdState.ToProtoUnsafe()
assert.NoError(t, err)
s2, err := state.ToProtoUnsafe()
assert.NoError(t, err)
require.DeepSSZEqual(t, s1, s2, "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
@@ -254,7 +266,9 @@ 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 := state_native.ProtobufBeaconStateAltair(rcvdState.ToProtoUnsafe())
s3, err := rcvdState.ToProtoUnsafe()
assert.NoError(t, err)
pbState, err := state_native.ProtobufBeaconStateAltair(s3)
assert.NoError(t, err)
validatorsFoundCount := 0
for _, val := range pbState.Validators {

View File

@@ -189,7 +189,11 @@ func getValidators(states []state.ReadOnlyBeaconState) ([][]byte, map[string]*et
validatorsEntries := make(map[string]*ethpb.Validator) // It's a map to make sure that you store only new validator entries.
validatorKeys := make([][]byte, len(states)) // For every state, this stores a compressed list of validator keys.
for i, st := range states {
pb, ok := st.ToProtoUnsafe().(withValidators)
p, err := st.ToProtoUnsafe()
if err != nil {
return nil, nil, err
}
pb, ok := p.(withValidators)
if !ok {
return nil, nil, errors.New("could not cast state to interface with GetValidators()")
}
@@ -228,7 +232,11 @@ func (s *Store) saveStatesEfficientInternal(ctx context.Context, tx *bolt.Tx, bl
// 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) {
p, err := states[i].ToProtoUnsafe()
if err != nil {
return err
}
switch rawType := p.(type) {
case *ethpb.BeaconState:
pbState, err := statenative.ProtobufBeaconStatePhase0(rawType)
if err != nil {
@@ -534,15 +542,19 @@ 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) {
p, err := st.ToProtoUnsafe()
if err != nil {
return nil, err
}
switch p.(type) {
case *ethpb.BeaconState:
rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconState)
rState, ok := p.(*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 := p.(*ethpb.BeaconStateAltair)
if !ok {
return nil, errors.New("non valid inner state")
}
@@ -555,7 +567,7 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er
}
return snappy.Encode(nil, append(altairKey, rawObj...)), nil
case *ethpb.BeaconStateBellatrix:
rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateBellatrix)
rState, ok := p.(*ethpb.BeaconStateBellatrix)
if !ok {
return nil, errors.New("non valid inner state")
}
@@ -568,7 +580,7 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er
}
return snappy.Encode(nil, append(bellatrixKey, rawObj...)), nil
case *ethpb.BeaconStateCapella:
rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateCapella)
rState, ok := p.(*ethpb.BeaconStateCapella)
if !ok {
return nil, errors.New("non valid inner state")
}

View File

@@ -67,9 +67,14 @@ func (s *Store) HasStateSummary(ctx context.Context, blockRoot [32]byte) bool {
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasStateSummary")
defer span.End()
if s.stateSummaryCache.has(blockRoot) {
return true
}
var hasSummary bool
if err := s.db.View(func(tx *bolt.Tx) error {
hasSummary = s.hasStateSummaryBytes(tx, blockRoot)
enc := tx.Bucket(stateSummaryBucket).Get(blockRoot[:])
hasSummary = len(enc) > 0
return nil
}); err != nil {
return false
@@ -77,14 +82,6 @@ func (s *Store) HasStateSummary(ctx context.Context, blockRoot [32]byte) bool {
return hasSummary
}
func (s *Store) hasStateSummaryBytes(tx *bolt.Tx, blockRoot [32]byte) bool {
if s.stateSummaryCache.has(blockRoot) {
return true
}
enc := tx.Bucket(stateSummaryBucket).Get(blockRoot[:])
return len(enc) > 0
}
// This saves all cached state summary objects to DB, and clears up the cache.
func (s *Store) saveCachedStateSummariesDB(ctx context.Context) error {
summaries := s.stateSummaryCache.getAll()

View File

@@ -44,7 +44,11 @@ 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")
s1, err := st.ToProtoUnsafe()
require.NoError(t, err)
s2, err := savedS.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2, "saved state and retrieved state are not matching")
savedS, err = db.State(context.Background(), [32]byte{'B'})
require.NoError(t, err)
@@ -77,7 +81,11 @@ 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")
s1, err := st.ToProtoUnsafe()
require.NoError(t, err)
s2, err := savedS.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2, "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 {
@@ -129,7 +137,11 @@ 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")
s1, err := st.ToProtoUnsafe()
require.NoError(t, err)
s2, err := savedS.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2, "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 {
@@ -239,7 +251,11 @@ 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")
s1, err := st.ToProtoUnsafe()
require.NoError(t, err)
s2, err := savedS.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2, "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 {
@@ -360,7 +376,11 @@ 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")
s1, err := st.ToProtoUnsafe()
require.NoError(t, err)
s2, err := savedGenesisS.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, s1, s2, "Did not retrieve saved state")
require.NoError(t, db.SaveGenesisBlockRoot(context.Background(), [32]byte{'C'}))
}
@@ -481,7 +501,8 @@ 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, err := st.ToProtoUnsafe()
require.NoError(t, err)
require.NoError(t, db.SaveState(context.Background(), st, r))
b.Block.Slot = 100
@@ -493,7 +514,8 @@ 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, err := st.ToProtoUnsafe()
require.NoError(t, err)
require.NoError(t, db.SaveState(context.Background(), st, r1))
b.Block.Slot = 1000
@@ -505,21 +527,27 @@ 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, err := st.ToProtoUnsafe()
require.NoError(t, err)
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)
want, err := highest[0].ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, want, s0)
highest, err = db.HighestSlotStatesBelow(context.Background(), 101)
require.NoError(t, err)
assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), s1)
want, err = highest[0].ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, want, s1)
highest, err = db.HighestSlotStatesBelow(context.Background(), 1001)
require.NoError(t, err)
assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), s2)
want, err = highest[0].ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, want, s2)
}
func TestStore_GenesisState_CanGetHighestBelow(t *testing.T) {
@@ -546,14 +574,24 @@ 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())
want, err := highest[0].ToProtoUnsafe()
require.NoError(t, err)
gotSt, err := st.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, want, gotSt)
highest, err = db.HighestSlotStatesBelow(context.Background(), 1)
require.NoError(t, err)
assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), genesisState.ToProtoUnsafe())
gs, err := genesisState.ToProtoUnsafe()
require.NoError(t, err)
want, err = highest[0].ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, want, gs)
highest, err = db.HighestSlotStatesBelow(context.Background(), 0)
require.NoError(t, err)
assert.DeepSSZEqual(t, highest[0].ToProtoUnsafe(), genesisState.ToProtoUnsafe())
want, err = highest[0].ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, want, gs)
}
func TestStore_CleanUpDirtyStates_AboveThreshold(t *testing.T) {
@@ -680,7 +718,11 @@ func TestAltairState_CanSaveRetrieve(t *testing.T) {
savedS, err := db.State(context.Background(), r)
require.NoError(t, err)
require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe())
s0, err := st.ToProtoUnsafe()
require.NoError(t, err)
s1, err := savedS.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s0, s1)
savedS, err = db.State(context.Background(), [32]byte{'B'})
require.NoError(t, err)
@@ -830,8 +872,11 @@ func TestStateBellatrix_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")
s0, err := st.ToProtoUnsafe()
require.NoError(t, err)
s1, err := savedS.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s0, s1, "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 {
@@ -873,8 +918,11 @@ func TestBellatrixState_CanSaveRetrieve(t *testing.T) {
savedS, err := db.State(context.Background(), r)
require.NoError(t, err)
require.DeepSSZEqual(t, st.ToProtoUnsafe(), savedS.ToProtoUnsafe())
s0, err := st.ToProtoUnsafe()
require.NoError(t, err)
s1, err := savedS.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s0, s1)
savedS, err = db.State(context.Background(), [32]byte{'B'})
require.NoError(t, err)

View File

@@ -38,9 +38,9 @@ func (s *Store) SaveLastValidatedCheckpoint(ctx context.Context, checkpoint *eth
if err != nil {
return err
}
hasStateSummary := s.HasStateSummary(ctx, bytesutil.ToBytes32(checkpoint.Root))
return s.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(checkpointBucket)
hasStateSummary := s.hasStateSummaryBytes(tx, bytesutil.ToBytes32(checkpoint.Root))
hasStateInDB := tx.Bucket(stateBucket).Get(checkpoint.Root) != nil
if !(hasStateInDB || hasStateSummary) {
log.Warnf("Recovering state summary for last validated root: %#x", bytesutil.Trunc(checkpoint.Root))

View File

@@ -51,6 +51,26 @@ func TestStore_LastValidatedCheckpoint_Recover(t *testing.T) {
assert.Equal(t, true, proto.Equal(cp, retrieved), "Wanted %v, received %v", cp, retrieved)
}
func BenchmarkStore_SaveLastValidatedCheckpoint(b *testing.B) {
db := setupDB(b)
ctx := context.Background()
root := bytesutil.ToBytes32([]byte{'A'})
cp := &ethpb.Checkpoint{
Epoch: 10,
Root: root[:],
}
st, err := util.NewBeaconState()
require.NoError(b, err)
require.NoError(b, st.SetSlot(1))
require.NoError(b, db.SaveState(ctx, st, root))
db.stateSummaryCache.clear()
b.ResetTimer()
for i := 0; i < b.N; i++ {
require.NoError(b, db.SaveLastValidatedCheckpoint(ctx, cp))
}
}
func TestStore_LastValidatedCheckpoint_DefaultIsFinalized(t *testing.T) {
db := setupDB(t)
ctx := context.Background()

View File

@@ -41,6 +41,7 @@ go_library(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//container/trie:go_default_library",
"//contracts/deposit:go_default_library",
"//crypto/hash:go_default_library",
@@ -52,6 +53,7 @@ go_library(
"//network/authorization:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//time:go_default_library",
"//time/slots:go_default_library",
"@com_github_ethereum_go_ethereum//:go_default_library",
@@ -108,6 +110,7 @@ go_test(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/trie:go_default_library",
"//contracts/deposit:go_default_library",

View File

@@ -19,8 +19,10 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -30,6 +32,8 @@ const (
NewPayloadMethod = "engine_newPayloadV1"
// ForkchoiceUpdatedMethod v1 request string for JSON-RPC.
ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1"
// ForkchoiceUpdatedMethodV2 v2 request string for JSON-RPC.
ForkchoiceUpdatedMethodV2 = "engine_forkchoiceUpdatedV2"
// GetPayloadMethod v1 request string for JSON-RPC.
GetPayloadMethod = "engine_getPayloadV1"
// ExchangeTransitionConfigurationMethod v1 request string for JSON-RPC.
@@ -66,7 +70,7 @@ type ExecutionPayloadReconstructor interface {
type EngineCaller interface {
NewPayload(ctx context.Context, payload interfaces.ExecutionData) ([]byte, error)
ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
) (*pb.PayloadIDBytes, []byte, error)
GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error)
ExchangeTransitionConfiguration(
@@ -114,7 +118,7 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
// ForkchoiceUpdated calls the engine_forkchoiceUpdatedV1 method via JSON-RPC.
func (s *Service) ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
) (*pb.PayloadIDBytes, []byte, error) {
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ForkchoiceUpdated")
defer span.End()
@@ -127,9 +131,31 @@ func (s *Service) ForkchoiceUpdated(
ctx, cancel := context.WithDeadline(ctx, d)
defer cancel()
result := &ForkchoiceUpdatedResponse{}
err := s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, attrs)
if err != nil {
return nil, nil, handleRPCError(err)
if attrs == nil {
return nil, nil, errors.New("nil payload attributer")
}
switch attrs.Version() {
case version.Bellatrix:
a, err := attrs.PbV1()
if err != nil {
return nil, nil, err
}
err = s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, a)
if err != nil {
return nil, nil, handleRPCError(err)
}
case version.Capella:
a, err := attrs.PbV2()
if err != nil {
return nil, nil, err
}
err = s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethodV2, state, a)
if err != nil {
return nil, nil, handleRPCError(err)
}
default:
return nil, nil, fmt.Errorf("unknown payload attribute version: %v", attrs.Version())
}
if result.Status == nil {

View File

@@ -24,6 +24,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/testing/assert"
@@ -72,7 +73,19 @@ func TestClient_IPC(t *testing.T) {
t.Run(ForkchoiceUpdatedMethod, func(t *testing.T) {
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, &pb.PayloadAttributes{})
p, err := payloadattribute.New(&pb.PayloadAttributes{})
require.NoError(t, err)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
})
t.Run(ForkchoiceUpdatedMethodV2, func(t *testing.T) {
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
p, err := payloadattribute.New(&pb.PayloadAttributesV2{})
require.NoError(t, err)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
@@ -168,12 +181,38 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
srv := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
})
t.Run(ForkchoiceUpdatedMethodV2+" VALID status", func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
HeadBlockHash: []byte("head"),
SafeBlockHash: []byte("safe"),
FinalizedBlockHash: []byte("finalized"),
}
payloadAttributes := &pb.PayloadAttributesV2{
Timestamp: 1,
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
Withdrawals: []*pb.Withdrawal{{ValidatorIndex: 1, Amount: 1}},
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
srv := forkchoiceUpdateSetupV2(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
@@ -189,12 +228,38 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedSyncingResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrAcceptedSyncingPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, []byte(nil), validHash)
})
t.Run(ForkchoiceUpdatedMethodV2+" SYNCING status", func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
HeadBlockHash: []byte("head"),
SafeBlockHash: []byte("safe"),
FinalizedBlockHash: []byte("finalized"),
}
payloadAttributes := &pb.PayloadAttributesV2{
Timestamp: 1,
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
Withdrawals: []*pb.Withdrawal{{ValidatorIndex: 1, Amount: 1}},
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedSyncingResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
srv := forkchoiceUpdateSetupV2(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrAcceptedSyncingPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, []byte(nil), validHash)
@@ -210,12 +275,14 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedInvalidResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrInvalidPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
@@ -231,12 +298,14 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedAcceptedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrUnknownPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, []byte(nil), validHash)
@@ -1362,6 +1431,18 @@ func (*testEngineService) ForkchoiceUpdatedV1(
return item
}
func (*testEngineService) ForkchoiceUpdatedV2(
_ context.Context, _ *pb.ForkchoiceState, _ *pb.PayloadAttributes,
) *ForkchoiceUpdatedResponse {
fix := fixtures()
item, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
if !ok {
panic("not found")
}
item.Status.Status = pb.PayloadStatus_VALID
return item
}
func (*testEngineService) NewPayloadV1(
_ context.Context, _ *pb.ExecutionPayload,
) *pb.PayloadStatus {
@@ -1412,6 +1493,45 @@ func forkchoiceUpdateSetup(t *testing.T, fcs *pb.ForkchoiceState, att *pb.Payloa
return service
}
func forkchoiceUpdateSetupV2(t *testing.T, fcs *pb.ForkchoiceState, att *pb.PayloadAttributesV2, res *ForkchoiceUpdatedResponse) *Service {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
enc, err := io.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)
forkChoiceStateReq, err := json.Marshal(fcs)
require.NoError(t, err)
payloadAttrsReq, err := json.Marshal(att)
require.NoError(t, err)
// We expect the JSON string RPC request contains the right arguments.
require.Equal(t, true, strings.Contains(
jsonRequestString, string(forkChoiceStateReq),
))
require.Equal(t, true, strings.Contains(
jsonRequestString, string(payloadAttrsReq),
))
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": res,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
service := &Service{}
service.rpcClient = rpcClient
return service
}
func newPayloadSetup(t *testing.T, status *pb.PayloadStatus, payload *pb.ExecutionPayload) *Service {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")

View File

@@ -551,7 +551,11 @@ func (s *Service) processChainStartIfReady(ctx context.Context, blockHash [32]by
// savePowchainData saves all powchain related metadata to disk.
func (s *Service) savePowchainData(ctx context.Context) error {
pbState, err := statenative.ProtobufBeaconStatePhase0(s.preGenesisState.ToProtoUnsafe())
st, err := s.preGenesisState.ToProtoUnsafe()
if err != nil {
return err
}
pbState, err := statenative.ProtobufBeaconStatePhase0(st)
if err != nil {
return err
}

View File

@@ -777,7 +777,11 @@ 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 := native.ProtobufBeaconStatePhase0(s.preGenesisState.ToProtoUnsafe())
st, err := s.preGenesisState.ToProtoUnsafe()
if err != nil {
return err
}
pbState, err := native.ProtobufBeaconStatePhase0(st)
if err != nil {
return err
}

View File

@@ -20,6 +20,7 @@ go_library(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",

View File

@@ -11,6 +11,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
)
@@ -43,7 +44,7 @@ func (e *EngineClient) NewPayload(_ context.Context, _ interfaces.ExecutionData)
// ForkchoiceUpdated --
func (e *EngineClient) ForkchoiceUpdated(
_ context.Context, fcs *pb.ForkchoiceState, _ *pb.PayloadAttributes,
_ context.Context, fcs *pb.ForkchoiceState, _ payloadattribute.Attributer,
) (*pb.PayloadIDBytes, []byte, error) {
if e.OverrideValidHash != [32]byte{} && bytesutil.ToBytes32(fcs.HeadBlockHash) == e.OverrideValidHash {
return e.PayloadIDBytes, e.ForkChoiceUpdatedResp, nil

View File

@@ -11,10 +11,15 @@ go_library(
"//beacon-chain:__subpackages__",
],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/doubly-linked-list:go_default_library",
"//crypto/bls/blst:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)
@@ -24,8 +29,15 @@ go_test(
srcs = ["pool_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/core/time:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/bls/common:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/ssz:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",

View File

@@ -4,17 +4,22 @@ import (
"math"
"sync"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v3/config/params"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
doublylinkedlist "github.com/prysmaticlabs/prysm/v3/container/doubly-linked-list"
"github.com/prysmaticlabs/prysm/v3/crypto/bls/blst"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/sirupsen/logrus"
)
// PoolManager maintains pending and seen BLS-to-execution-change objects.
// This pool is used by proposers to insert BLS-to-execution-change objects into new blocks.
type PoolManager interface {
PendingBLSToExecChanges() ([]*ethpb.SignedBLSToExecutionChange, error)
BLSToExecChangesForInclusion() ([]*ethpb.SignedBLSToExecutionChange, error)
BLSToExecChangesForInclusion(state.BeaconState) ([]*ethpb.SignedBLSToExecutionChange, error)
InsertBLSToExecChange(change *ethpb.SignedBLSToExecutionChange)
MarkIncluded(change *ethpb.SignedBLSToExecutionChange) error
ValidatorExists(idx types.ValidatorIndex) bool
@@ -58,25 +63,69 @@ func (p *Pool) PendingBLSToExecChanges() ([]*ethpb.SignedBLSToExecutionChange, e
// BLSToExecChangesForInclusion returns objects that are ready for inclusion at the given slot.
// This method will not return more than the block enforced MaxBlsToExecutionChanges.
func (p *Pool) BLSToExecChangesForInclusion() ([]*ethpb.SignedBLSToExecutionChange, error) {
func (p *Pool) BLSToExecChangesForInclusion(st state.BeaconState) ([]*ethpb.SignedBLSToExecutionChange, error) {
p.lock.RLock()
defer p.lock.RUnlock()
length := int(math.Min(float64(params.BeaconConfig().MaxBlsToExecutionChanges), float64(p.pending.Len())))
result := make([]*ethpb.SignedBLSToExecutionChange, length)
result := make([]*ethpb.SignedBLSToExecutionChange, 0, length)
node := p.pending.First()
var err error
for i := 0; node != nil && i < length; i++ {
result[i], err = node.Value()
for node != nil && len(result) < length {
change, err := node.Value()
if err != nil {
p.lock.RUnlock()
return nil, err
}
_, err = blocks.ValidateBLSToExecutionChange(st, change)
if err != nil {
logrus.WithError(err).Warning("removing invalid BLSToExecutionChange from pool")
// MarkIncluded removes the invalid change from the pool
p.lock.RUnlock()
if err := p.MarkIncluded(change); err != nil {
return nil, errors.Wrap(err, "could not mark BLSToExecutionChange as included")
}
p.lock.RLock()
} else {
result = append(result, change)
}
node, err = node.Next()
if err != nil {
p.lock.RUnlock()
return nil, err
}
}
return result, nil
p.lock.RUnlock()
if len(result) == 0 {
return result, nil
}
// We now verify the signatures in batches
cSet, err := blocks.BLSChangesSignatureBatch(st, result)
if err != nil {
logrus.WithError(err).Warning("could not get BLSToExecutionChanges signatures")
} else {
ok, err := cSet.Verify()
if err != nil {
logrus.WithError(err).Warning("could not batch verify BLSToExecutionChanges signatures")
} else if ok {
return result, nil
}
}
// Batch signature failed, check signatures individually
verified := make([]*ethpb.SignedBLSToExecutionChange, 0, length)
for i, sig := range cSet.Signatures {
signature, err := blst.SignatureFromBytes(sig)
if err != nil {
logrus.WithError(err).Warning("could not get signature from bytes")
continue
}
if !signature.Verify(cSet.PublicKeys[i], cSet.Messages[i][:]) {
logrus.Warning("removing BLSToExecutionChange with invalid signature from pool")
if err := p.MarkIncluded(result[i]); err != nil {
return nil, errors.Wrap(err, "could not mark BLSToExecutionChange as included")
}
} else {
verified = append(verified, result[i])
}
}
return verified, nil
}
// InsertBLSToExecChange inserts an object into the pool.

View File

@@ -3,8 +3,15 @@ package blstoexec
import (
"testing"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v3/config/params"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
"github.com/prysmaticlabs/prysm/v3/crypto/bls/common"
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
eth "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/testing/assert"
"github.com/prysmaticlabs/prysm/v3/testing/require"
@@ -36,42 +43,89 @@ func TestPendingBLSToExecChanges(t *testing.T) {
}
func TestBLSToExecChangesForInclusion(t *testing.T) {
spb := &eth.BeaconStateCapella{
Fork: &eth.Fork{
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
}
numValidators := 2 * params.BeaconConfig().MaxBlsToExecutionChanges
validators := make([]*eth.Validator, numValidators)
blsChanges := make([]*eth.BLSToExecutionChange, numValidators)
spb.Balances = make([]uint64, numValidators)
privKeys := make([]common.SecretKey, numValidators)
maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance
executionAddress := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13}
for i := range validators {
v := &eth.Validator{}
v.EffectiveBalance = maxEffectiveBalance
v.WithdrawableEpoch = params.BeaconConfig().FarFutureEpoch
v.WithdrawalCredentials = make([]byte, 32)
priv, err := bls.RandKey()
require.NoError(t, err)
privKeys[i] = priv
pubkey := priv.PublicKey().Marshal()
message := &eth.BLSToExecutionChange{
ToExecutionAddress: executionAddress,
ValidatorIndex: types.ValidatorIndex(i),
FromBlsPubkey: pubkey,
}
hashFn := ssz.NewHasherFunc(hash.CustomSHA256Hasher())
digest := hashFn.Hash(pubkey)
digest[0] = params.BeaconConfig().BLSWithdrawalPrefixByte
copy(v.WithdrawalCredentials, digest[:])
validators[i] = v
blsChanges[i] = message
}
spb.Validators = validators
st, err := state_native.InitializeFromProtoCapella(spb)
require.NoError(t, err)
signedChanges := make([]*eth.SignedBLSToExecutionChange, numValidators)
for i, message := range blsChanges {
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, privKeys[i])
require.NoError(t, err)
signed := &eth.SignedBLSToExecutionChange{
Message: message,
Signature: signature,
}
signedChanges[i] = signed
}
t.Run("empty pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges-1; i++ {
pool.InsertBLSToExecChange(&eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: types.ValidatorIndex(i),
},
})
}
changes, err := pool.BLSToExecChangesForInclusion()
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges-1), len(changes))
assert.Equal(t, 0, len(changes))
})
t.Run("Less than MaxBlsToExecutionChanges in pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges-1; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges)-1, len(changes))
})
t.Run("MaxBlsToExecutionChanges in pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges; i++ {
pool.InsertBLSToExecChange(&eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: types.ValidatorIndex(i),
},
})
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion()
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
})
t.Run("more than MaxBlsToExecutionChanges in pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges+1; i++ {
pool.InsertBLSToExecChange(&eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: types.ValidatorIndex(i),
},
})
for i := uint64(0); i < numValidators; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion()
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
// We want FIFO semantics, which means validator with index 16 shouldn't be returned
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
@@ -79,6 +133,30 @@ func TestBLSToExecChangesForInclusion(t *testing.T) {
assert.NotEqual(t, types.ValidatorIndex(16), ch.Message.ValidatorIndex)
}
})
t.Run("One Bad change", func(t *testing.T) {
pool := NewPool()
saveByte := signedChanges[1].Message.FromBlsPubkey[5]
signedChanges[1].Message.FromBlsPubkey[5] = 0xff
for i := uint64(0); i < numValidators; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
assert.Equal(t, types.ValidatorIndex(2), changes[1].Message.ValidatorIndex)
signedChanges[1].Message.FromBlsPubkey[5] = saveByte
})
t.Run("One Bad Signature", func(t *testing.T) {
pool := NewPool()
copy(signedChanges[1].Signature, signedChanges[2].Signature)
for i := uint64(0); i < numValidators; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges)-1, len(changes))
assert.Equal(t, types.ValidatorIndex(2), changes[1].Message.ValidatorIndex)
})
}
func TestInsertBLSToExecChange(t *testing.T) {

View File

@@ -115,7 +115,9 @@ func TestSszNetworkEncoder_DecodeWithMultipleFrames(t *testing.T) {
maxChunkSize := uint64(1 << 22)
encoder.MaxChunkSize = maxChunkSize
params.OverrideBeaconNetworkConfig(c)
_, err := e.EncodeWithMaxLength(buf, st.ToProtoUnsafe().(*ethpb.BeaconState))
pb, err := st.ToProtoUnsafe()
require.NoError(t, err)
_, err = e.EncodeWithMaxLength(buf, pb.(*ethpb.BeaconState))
require.NoError(t, err)
// Max snappy block size
if buf.Len() <= 76490 {

View File

@@ -492,8 +492,9 @@ func TestSubmitAttesterSlashing_AcrossFork(t *testing.T) {
},
}
newBs := bs.Copy()
newBs, err := transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch)
newBs, err := bs.Copy()
require.NoError(t, err)
newBs, err = transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
for _, att := range []*ethpbv1.IndexedAttestation{slashing.Attestation_1, slashing.Attestation_2} {
@@ -659,8 +660,9 @@ func TestSubmitProposerSlashing_AcrossFork(t *testing.T) {
},
}
newBs := bs.Copy()
newBs, err := transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch)
newBs, err := bs.Copy()
require.NoError(t, err)
newBs, err = transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
for _, h := range []*ethpbv1.SignedBeaconBlockHeader{slashing.SignedHeader_1, slashing.SignedHeader_2} {
@@ -787,8 +789,9 @@ func TestSubmitVoluntaryExit_AcrossFork(t *testing.T) {
Signature: make([]byte, 96),
}
newBs := bs.Copy()
newBs, err := transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)+1))
newBs, err := bs.Copy()
require.NoError(t, err)
newBs, err = transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)+1))
require.NoError(t, err)
sb, err := signing.ComputeDomainAndSign(newBs, exit.Message.Epoch, exit.Message, params.BeaconConfig().DomainVoluntaryExit, keys[0])

View File

@@ -239,7 +239,10 @@ func (bs *Server) ListValidators(
return nil, err
}
if s > reqState.Slot() {
reqState = reqState.Copy()
reqState, err = reqState.Copy()
if err != nil {
return nil, err
}
reqState, err = transition.ProcessSlots(ctx, reqState, s)
if err != nil {
return nil, status.Errorf(

View File

@@ -1907,7 +1907,8 @@ func TestGetValidatorPerformance_Indices(t *testing.T) {
SyncChecker: &mockSync.Sync{IsSyncing: false},
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
}
c := headState.Copy()
c, err := headState.Copy()
require.NoError(t, err)
vp, bp, err := precompute.New(ctx, c)
require.NoError(t, err)
vp, bp, err = precompute.ProcessAttestations(ctx, c, vp, bp)
@@ -1977,7 +1978,8 @@ func TestGetValidatorPerformance_IndicesPubkeys(t *testing.T) {
SyncChecker: &mockSync.Sync{IsSyncing: false},
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
}
c := headState.Copy()
c, err := headState.Copy()
require.NoError(t, err)
vp, bp, err := precompute.New(ctx, c)
require.NoError(t, err)
vp, bp, err = precompute.ProcessAttestations(ctx, c, vp, bp)

View File

@@ -59,6 +59,7 @@ go_library(
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//container/trie:go_default_library",
"//contracts/deposit:go_default_library",
"//crypto/bls:go_default_library",

View File

@@ -16,7 +16,6 @@ import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv"
"github.com/prysmaticlabs/prysm/v3/config/params"
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
coreBlock "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
@@ -155,7 +154,7 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Sl
return nil, fmt.Errorf("incorrect timestamp %d != %d", bid.Message.Header.Timestamp, uint64(t.Unix()))
}
if err := vs.validateBuilderSignature(bid); err != nil {
if err := validateBuilderSignature(bid); err != nil {
return nil, errors.Wrap(err, "could not validate builder signature")
}
@@ -212,7 +211,7 @@ func (vs *Server) buildBlindBlock(ctx context.Context, b *ethpb.BeaconBlockAltai
// bellatrix blind block. The output block will contain the full payload. The original header block
// will be returned the block builder is not configured.
func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.SignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
if err := coreBlock.BeaconBlockIsNil(b); err != nil {
if err := consensusblocks.BeaconBlockIsNil(b); err != nil {
return nil, err
}
@@ -331,7 +330,7 @@ func (vs *Server) readyForBuilder(ctx context.Context) (bool, error) {
if err != nil {
return false, err
}
if err = coreBlock.BeaconBlockIsNil(b); err != nil {
if err = consensusblocks.BeaconBlockIsNil(b); err != nil {
return false, err
}
return blocks.IsExecutionBlock(b.Block().Body())
@@ -445,7 +444,7 @@ func (vs *Server) validatorRegistered(ctx context.Context, id types.ValidatorInd
}
// Validates builder signature and returns an error if the signature is invalid.
func (vs *Server) validateBuilderSignature(bid *ethpb.SignedBuilderBid) error {
func validateBuilderSignature(bid *ethpb.SignedBuilderBid) error {
d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder,
nil, /* fork version */
nil /* genesis val root */)

View File

@@ -34,7 +34,6 @@ import (
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
v1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/testing/require"
@@ -915,7 +914,6 @@ func TestServer_validatorRegistered(t *testing.T) {
}
func TestServer_validateBuilderSignature(t *testing.T) {
s := &Server{}
sk, err := bls.RandKey()
require.NoError(t, err)
bid := &ethpb.BuilderBid{
@@ -943,10 +941,10 @@ func TestServer_validateBuilderSignature(t *testing.T) {
Message: bid,
Signature: sk.Sign(sr[:]).Marshal(),
}
require.NoError(t, s.validateBuilderSignature(sBid))
require.NoError(t, validateBuilderSignature(sBid))
sBid.Message.Value = make([]byte, 32)
require.ErrorIs(t, s.validateBuilderSignature(sBid), signing.ErrSigFailedToVerify)
require.ErrorIs(t, validateBuilderSignature(sBid), signing.ErrSigFailedToVerify)
}
func TestServer_circuitBreakBuilder(t *testing.T) {
@@ -1010,7 +1008,7 @@ func createState(
BlockRoots: make([][]byte, 1),
CurrentJustifiedCheckpoint: justified,
FinalizedCheckpoint: finalized,
LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{
LatestExecutionPayloadHeader: &v1.ExecutionPayloadHeader{
BlockHash: payloadHash[:],
},
LatestBlockHeader: &ethpb.BeaconBlockHeader{

View File

@@ -17,6 +17,7 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
@@ -154,7 +155,13 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
PrevRandao: random,
SuggestedFeeRecipient: feeRecipient.Bytes(),
}
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, p)
// This will change in subsequent hardforks like Capella.
pa, err := payloadattribute.New(p)
if err != nil {
return nil, err
}
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, pa)
if err != nil {
return nil, errors.Wrap(err, "could not prepare payload")
}

View File

@@ -20,7 +20,7 @@ type BeaconState interface {
ReadOnlyBeaconState
ReadOnlyWithdrawals
WriteOnlyBeaconState
Copy() BeaconState
Copy() (BeaconState, error)
HashTreeRoot(ctx context.Context) ([32]byte, error)
FutureForkStub
StateProver
@@ -50,8 +50,8 @@ type ReadOnlyBeaconState interface {
ReadOnlyBalances
ReadOnlyCheckpoint
ReadOnlyAttestations
ToProtoUnsafe() interface{}
ToProto() interface{}
ToProtoUnsafe() (interface{}, error)
ToProto() (interface{}, error)
GenesisTime() uint64
GenesisValidatorsRoot() []byte
Slot() types.Slot
@@ -63,7 +63,7 @@ type ReadOnlyBeaconState interface {
MarshalSSZ() ([]byte, error)
IsNil() bool
Version() int
LatestExecutionPayloadHeader() (interfaces.ExecutionData, error)
LatestExecutionPayloadHeader() (interfaces.ExecutionDataHeader, error)
}
// WriteOnlyBeaconState defines a struct which only has write access to beacon state methods.
@@ -85,7 +85,7 @@ type WriteOnlyBeaconState interface {
SetSlashings(val []uint64) error
UpdateSlashingsAtIndex(idx, val uint64) error
AppendHistoricalRoots(root [32]byte) error
SetLatestExecutionPayloadHeader(payload interfaces.ExecutionData) error
SetLatestExecutionPayloadHeader(payload interfaces.ExecutionDataHeader) error
SetNextWithdrawalIndex(i uint64) error
SetNextWithdrawalValidatorIndex(i types.ValidatorIndex) error
}

View File

@@ -10,45 +10,44 @@ import (
customtypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native/custom-types"
nativetypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
eth2types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
// 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 {
version int
genesisTime uint64
genesisValidatorsRoot [32]byte
slot eth2types.Slot
fork *ethpb.Fork
latestBlockHeader *ethpb.BeaconBlockHeader
blockRoots *customtypes.BlockRoots
stateRoots *customtypes.StateRoots
historicalRoots customtypes.HistoricalRoots
eth1Data *ethpb.Eth1Data
eth1DataVotes []*ethpb.Eth1Data
eth1DepositIndex uint64
validators []*ethpb.Validator
balances []uint64
randaoMixes *customtypes.RandaoMixes
slashings []uint64
previousEpochAttestations []*ethpb.PendingAttestation
currentEpochAttestations []*ethpb.PendingAttestation
previousEpochParticipation []byte
currentEpochParticipation []byte
justificationBits bitfield.Bitvector4
previousJustifiedCheckpoint *ethpb.Checkpoint
currentJustifiedCheckpoint *ethpb.Checkpoint
finalizedCheckpoint *ethpb.Checkpoint
inactivityScores []uint64
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader
latestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex eth2types.ValidatorIndex
version int
genesisTime uint64 `ssz-gen:"true"`
genesisValidatorsRoot [32]byte `ssz-gen:"true" ssz-size:"32"`
slot eth2types.Slot `ssz-gen:"true"`
fork *ethpb.Fork `ssz-gen:"true"`
latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"`
blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"8192,32"`
stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"8192,32"`
historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"`
eth1Data *ethpb.Eth1Data `ssz-gen:"true"`
eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"2048"`
eth1DepositIndex uint64 `ssz-gen:"true"`
validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"`
balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"65536,32"`
slashings []uint64 `ssz-gen:"true" ssz-size:"8192"`
previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"`
currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"`
previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"`
previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
inactivityScores []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
currentSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"`
nextSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"`
latestExecutionPayloadHeader interfaces.ExecutionDataHeader `ssz-gen:"true"`
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex eth2types.ValidatorIndex
lock sync.RWMutex
dirtyFields map[nativetypes.FieldIndex]bool

View File

@@ -10,45 +10,44 @@ import (
customtypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native/custom-types"
nativetypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
eth2types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
// 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 {
version int
genesisTime uint64
genesisValidatorsRoot [32]byte
slot eth2types.Slot
fork *ethpb.Fork
latestBlockHeader *ethpb.BeaconBlockHeader
blockRoots *customtypes.BlockRoots
stateRoots *customtypes.StateRoots
historicalRoots customtypes.HistoricalRoots
eth1Data *ethpb.Eth1Data
eth1DataVotes []*ethpb.Eth1Data
eth1DepositIndex uint64
validators []*ethpb.Validator
balances []uint64
randaoMixes *customtypes.RandaoMixes
slashings []uint64
previousEpochAttestations []*ethpb.PendingAttestation
currentEpochAttestations []*ethpb.PendingAttestation
previousEpochParticipation []byte
currentEpochParticipation []byte
justificationBits bitfield.Bitvector4
previousJustifiedCheckpoint *ethpb.Checkpoint
currentJustifiedCheckpoint *ethpb.Checkpoint
finalizedCheckpoint *ethpb.Checkpoint
inactivityScores []uint64
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader
latestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex eth2types.ValidatorIndex
version int
genesisTime uint64
genesisValidatorsRoot [32]byte
slot eth2types.Slot
fork *ethpb.Fork
latestBlockHeader *ethpb.BeaconBlockHeader
blockRoots *customtypes.BlockRoots
stateRoots *customtypes.StateRoots
historicalRoots customtypes.HistoricalRoots
eth1Data *ethpb.Eth1Data
eth1DataVotes []*ethpb.Eth1Data
eth1DepositIndex uint64
validators []*ethpb.Validator
balances []uint64
randaoMixes *customtypes.RandaoMixes
slashings []uint64
previousEpochAttestations []*ethpb.PendingAttestation
currentEpochAttestations []*ethpb.PendingAttestation
previousEpochParticipation []byte
currentEpochParticipation []byte
justificationBits bitfield.Bitvector4
previousJustifiedCheckpoint *ethpb.Checkpoint
currentJustifiedCheckpoint *ethpb.Checkpoint
finalizedCheckpoint *ethpb.Checkpoint
inactivityScores []uint64
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
latestExecutionPayloadHeader interfaces.ExecutionDataHeader
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex eth2types.ValidatorIndex
lock sync.RWMutex
dirtyFields map[nativetypes.FieldIndex]bool

View File

@@ -1,6 +1,8 @@
package state_native
import (
"fmt"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
@@ -9,28 +11,37 @@ import (
)
// LatestExecutionPayloadHeader of the beacon state.
func (b *BeaconState) LatestExecutionPayloadHeader() (interfaces.ExecutionData, error) {
func (b *BeaconState) LatestExecutionPayloadHeader() (interfaces.ExecutionDataHeader, error) {
if b.version < version.Bellatrix {
return nil, errNotSupported("LatestExecutionPayloadHeader", b.version)
}
if b.latestExecutionPayloadHeader == nil || b.latestExecutionPayloadHeader.IsNil() {
return nil, nil
}
b.lock.RLock()
defer b.lock.RUnlock()
if b.version == version.Bellatrix {
return blocks.WrappedExecutionPayloadHeader(b.latestExecutionPayloadHeaderVal())
}
return blocks.WrappedExecutionPayloadHeaderCapella(b.latestExecutionPayloadHeaderCapellaVal())
return b.latestExecutionPayloadHeaderVal()
}
// latestExecutionPayloadHeaderVal of the beacon state.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) latestExecutionPayloadHeaderVal() *enginev1.ExecutionPayloadHeader {
return ethpb.CopyExecutionPayloadHeader(b.latestExecutionPayloadHeader)
}
func (b *BeaconState) latestExecutionPayloadHeaderVal() (interfaces.ExecutionDataHeader, error) {
if b.latestExecutionPayloadHeader == nil {
return nil, nil
}
// latestExecutionPayloadHeaderCapellaVal of the beacon state.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) latestExecutionPayloadHeaderCapellaVal() *enginev1.ExecutionPayloadHeaderCapella {
return ethpb.CopyExecutionPayloadHeaderCapella(b.latestExecutionPayloadHeaderCapella)
headerProto := b.latestExecutionPayloadHeader.Proto()
switch h := headerProto.(type) {
case *enginev1.ExecutionPayloadHeader:
headerCopy := ethpb.CopyExecutionPayloadHeader(h)
return blocks.WrappedExecutionPayloadHeader(headerCopy)
case *enginev1.ExecutionPayloadHeaderCapella:
headerCopy := ethpb.CopyExecutionPayloadHeaderCapella(h)
return blocks.WrappedExecutionPayloadHeaderCapella(headerCopy)
default:
return nil, fmt.Errorf("invalid payload header in beacon state: %T", headerProto)
}
}

View File

@@ -4,15 +4,16 @@ import (
"fmt"
"github.com/pkg/errors"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
)
// ToProtoUnsafe returns the pointer value of the underlying
// beacon state proto object, bypassing immutability. Use with care.
func (b *BeaconState) ToProtoUnsafe() interface{} {
func (b *BeaconState) ToProtoUnsafe() (interface{}, error) {
if b == nil {
return nil
return nil, nil
}
gvrCopy := b.genesisValidatorsRoot
@@ -41,7 +42,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
}
}, nil
case version.Altair:
return &ethpb.BeaconStateAltair{
GenesisTime: b.genesisTime,
@@ -68,8 +69,12 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
InactivityScores: b.inactivityScores,
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
}
}, nil
case version.Bellatrix:
execHeader, ok := b.latestExecutionPayloadHeader.Proto().(*enginev1.ExecutionPayloadHeader)
if !ok {
return nil, errors.New("unexpected execution payload")
}
return &ethpb.BeaconStateBellatrix{
GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
@@ -95,9 +100,13 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
InactivityScores: b.inactivityScores,
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,
}
LatestExecutionPayloadHeader: execHeader,
}, nil
case version.Capella:
execHeader, ok := b.latestExecutionPayloadHeader.Proto().(*enginev1.ExecutionPayloadHeaderCapella)
if !ok {
return nil, errors.New("unexpected execution payload")
}
return &ethpb.BeaconStateCapella{
GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
@@ -123,19 +132,19 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
InactivityScores: b.inactivityScores,
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderCapella,
LatestExecutionPayloadHeader: execHeader,
NextWithdrawalIndex: b.nextWithdrawalIndex,
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
}
}, nil
default:
return nil
return nil, nil
}
}
// ToProto the beacon state into a protobuf for usage.
func (b *BeaconState) ToProto() interface{} {
func (b *BeaconState) ToProto() (interface{}, error) {
if b == nil {
return nil
return nil, nil
}
b.lock.RLock()
@@ -167,7 +176,7 @@ func (b *BeaconState) ToProto() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
}
}, nil
case version.Altair:
return &ethpb.BeaconStateAltair{
GenesisTime: b.genesisTime,
@@ -194,8 +203,16 @@ func (b *BeaconState) ToProto() interface{} {
InactivityScores: b.inactivityScoresVal(),
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
}
}, nil
case version.Bellatrix:
execHeader, err := b.latestExecutionPayloadHeaderVal()
if err != nil {
return nil, err
}
headerProto, ok := execHeader.Proto().(*enginev1.ExecutionPayloadHeader)
if !ok {
return nil, errors.New("unexpected execution payload")
}
return &ethpb.BeaconStateBellatrix{
GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
@@ -221,9 +238,17 @@ func (b *BeaconState) ToProto() interface{} {
InactivityScores: b.inactivityScoresVal(),
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(),
}
LatestExecutionPayloadHeader: headerProto,
}, nil
case version.Capella:
execHeader, err := b.latestExecutionPayloadHeaderVal()
if err != nil {
return nil, err
}
headerProto, ok := execHeader.Proto().(*enginev1.ExecutionPayloadHeaderCapella)
if !ok {
return nil, errors.New("unexpected execution payload")
}
return &ethpb.BeaconStateCapella{
GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
@@ -249,12 +274,12 @@ func (b *BeaconState) ToProto() interface{} {
InactivityScores: b.inactivityScoresVal(),
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderCapellaVal(),
LatestExecutionPayloadHeader: headerProto,
NextWithdrawalIndex: b.nextWithdrawalIndex,
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
}
}, nil
default:
return nil
return nil, nil
}
}

View File

@@ -229,7 +229,7 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
fieldRoots[nativetypes.NextSyncCommittee.RealPosition()] = nextSyncCommitteeRoot[:]
}
if state.version == version.Bellatrix {
if state.version >= version.Bellatrix {
// Execution payload root.
executionPayloadRoot, err := state.latestExecutionPayloadHeader.HashTreeRoot()
if err != nil {
@@ -239,13 +239,6 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
}
if state.version == version.Capella {
// Execution payload root.
executionPayloadRoot, err := state.latestExecutionPayloadHeaderCapella.HashTreeRoot()
if err != nil {
return nil, err
}
fieldRoots[nativetypes.LatestExecutionPayloadHeaderCapella.RealPosition()] = executionPayloadRoot[:]
// Next withdrawal index root.
nextWithdrawalIndexRoot := make([]byte, 32)
binary.LittleEndian.PutUint64(nextWithdrawalIndexRoot, state.nextWithdrawalIndex)

View File

@@ -26,7 +26,8 @@ func TestStateReferenceSharing_Finalizer_Phase0(t *testing.T) {
func() {
// Create object in a different scope for GC
b := a.Copy()
b, err := a.Copy()
require.NoError(t, err)
assert.Equal(t, uint(2), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes")
_ = b
}()
@@ -34,7 +35,8 @@ func TestStateReferenceSharing_Finalizer_Phase0(t *testing.T) {
runtime.GC() // Should run finalizer on object b
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!")
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
@@ -55,7 +57,8 @@ func TestStateReferenceSharing_Finalizer_Altair(t *testing.T) {
func() {
// Create object in a different scope for GC
b := a.Copy()
b, err := a.Copy()
require.NoError(t, err)
assert.Equal(t, uint(2), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes")
_ = b
}()
@@ -63,7 +66,8 @@ func TestStateReferenceSharing_Finalizer_Altair(t *testing.T) {
runtime.GC() // Should run finalizer on object b
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!")
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
@@ -84,7 +88,8 @@ func TestStateReferenceSharing_Finalizer_Bellatrix(t *testing.T) {
func() {
// Create object in a different scope for GC
b := a.Copy()
b, err := a.Copy()
require.NoError(t, err)
assert.Equal(t, uint(2), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes")
_ = b
}()
@@ -92,7 +97,8 @@ func TestStateReferenceSharing_Finalizer_Bellatrix(t *testing.T) {
runtime.GC() // Should run finalizer on object b
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!")
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
@@ -113,7 +119,8 @@ func TestStateReferenceSharing_Finalizer_Capella(t *testing.T) {
func() {
// Create object in a different scope for GC
b := a.Copy()
b, err := a.Copy()
require.NoError(t, err)
assert.Equal(t, uint(2), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes")
_ = b
}()
@@ -121,7 +128,8 @@ func TestStateReferenceSharing_Finalizer_Capella(t *testing.T) {
runtime.GC() // Should run finalizer on object b
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!")
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
@@ -149,7 +157,8 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation_Phase0(t *testing.T) {
assertRefCount(t, a, nativetypes.StateRoots, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.BlockRoots, 2)
@@ -208,7 +217,8 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation_Altair(t *testing.T) {
assertRefCount(t, a, nativetypes.StateRoots, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.BlockRoots, 2)
@@ -267,7 +277,8 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation_Bellatrix(t *testing.T) {
assertRefCount(t, a, nativetypes.StateRoots, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.BlockRoots, 2)
@@ -326,7 +337,8 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation_Capella(t *testing.T) {
assertRefCount(t, a, nativetypes.StateRoots, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.BlockRoots, 2)
@@ -381,7 +393,8 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Phase0(t *testing.T) {
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.RandaoMixes, 2)
@@ -425,7 +438,8 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Altair(t *testing.T) {
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.RandaoMixes, 2)
@@ -469,7 +483,8 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Bellatrix(t *testing.T) {
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.RandaoMixes, 2)
@@ -513,7 +528,8 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Capella(t *testing.T) {
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.RandaoMixes, 2)
@@ -585,7 +601,8 @@ func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) {
assert.Equal(t, 1, len(preAtt), "Unexpected number of attestations")
// Copy, increases reference count.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assertRefCount(t, a, nativetypes.PreviousEpochAttestations, 2)
@@ -723,7 +740,8 @@ func TestValidatorReferences_RemainsConsistent_Phase0(t *testing.T) {
require.Equal(t, true, ok)
// Create a second state.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
@@ -758,7 +776,8 @@ func TestValidatorReferences_RemainsConsistent_Altair(t *testing.T) {
require.Equal(t, true, ok)
// Create a second state.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
@@ -793,7 +812,8 @@ func TestValidatorReferences_RemainsConsistent_Capella(t *testing.T) {
require.Equal(t, true, ok)
// Create a second state.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
@@ -828,7 +848,8 @@ func TestValidatorReferences_RemainsConsistent_Bellatrix(t *testing.T) {
require.Equal(t, true, ok)
// Create a second state.
copied := a.Copy()
copied, err := a.Copy()
require.NoError(t, err)
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)

View File

@@ -1,17 +1,20 @@
package state_native
import (
"github.com/pkg/errors"
nativetypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native/types"
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
_ "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
)
// SetLatestExecutionPayloadHeader for the beacon state.
func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionData) error {
func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDataHeader) error {
headerCopy, err := blocks.CopyExecutionDataHeader(val)
if err != nil {
return err
}
b.lock.Lock()
defer b.lock.Unlock()
@@ -19,32 +22,7 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa
return errNotSupported("SetLatestExecutionPayloadHeader", b.version)
}
switch header := val.Proto().(type) {
case *enginev1.ExecutionPayload:
latest, err := consensusblocks.PayloadToHeader(val)
if err != nil {
return errors.Wrap(err, "could not convert payload to header")
}
b.latestExecutionPayloadHeader = latest
b.markFieldAsDirty(nativetypes.LatestExecutionPayloadHeader)
return nil
case *enginev1.ExecutionPayloadCapella:
latest, err := consensusblocks.PayloadToHeaderCapella(val)
if err != nil {
return errors.Wrap(err, "could not convert payload to header")
}
b.latestExecutionPayloadHeaderCapella = latest
b.markFieldAsDirty(nativetypes.LatestExecutionPayloadHeaderCapella)
return nil
case *enginev1.ExecutionPayloadHeader:
b.latestExecutionPayloadHeader = header
b.markFieldAsDirty(nativetypes.LatestExecutionPayloadHeader)
return nil
case *enginev1.ExecutionPayloadHeaderCapella:
b.latestExecutionPayloadHeaderCapella = header
b.markFieldAsDirty(nativetypes.LatestExecutionPayloadHeaderCapella)
return nil
default:
return errors.New("value must be an execution payload header")
}
b.latestExecutionPayloadHeader = headerCopy
b.markFieldAsDirty(nativetypes.LatestExecutionPayloadHeader)
return nil
}

View File

@@ -8,7 +8,10 @@ import (
var errAssertionFailed = errors.New("failed to convert interface to proto state")
func (b *BeaconState) MarshalSSZ() ([]byte, error) {
proto := b.ToProto()
proto, err := b.ToProto()
if err != nil {
return nil, err
}
s, ok := proto.(ssz.Marshaler)
if !ok {

View File

@@ -14,6 +14,8 @@ import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/types"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v3/container/slice"
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
@@ -78,8 +80,7 @@ var altairFields = []nativetypes.FieldIndex{
var bellatrixFields = append(altairFields, nativetypes.LatestExecutionPayloadHeader)
var capellaFields = append(
altairFields,
nativetypes.LatestExecutionPayloadHeaderCapella,
bellatrixFields,
nativetypes.NextWithdrawalIndex,
nativetypes.NextWithdrawalValidatorIndex,
)
@@ -310,6 +311,14 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
var initialPayloadHeader interfaces.ExecutionDataHeader
if st.LatestExecutionPayloadHeader != nil {
var err error
initialPayloadHeader, err = blocks.WrappedExecutionPayloadHeader(st.LatestExecutionPayloadHeader)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap latest execution payload header")
}
}
fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount
b := &BeaconState{
@@ -338,7 +347,7 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
inactivityScores: st.InactivityScores,
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeader: st.LatestExecutionPayloadHeader,
latestExecutionPayloadHeader: initialPayloadHeader,
dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount),
@@ -402,37 +411,45 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
var initialPayloadHeader interfaces.ExecutionDataHeader
if st.LatestExecutionPayloadHeader != nil {
var err error
initialPayloadHeader, err = blocks.WrappedExecutionPayloadHeaderCapella(st.LatestExecutionPayloadHeader)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap latest execution payload header")
}
}
fieldCount := params.BeaconConfig().BeaconStateCapellaFieldCount
b := &BeaconState{
version: version.Capella,
genesisTime: st.GenesisTime,
genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot),
slot: st.Slot,
fork: st.Fork,
latestBlockHeader: st.LatestBlockHeader,
blockRoots: &bRoots,
stateRoots: &sRoots,
historicalRoots: hRoots,
eth1Data: st.Eth1Data,
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
randaoMixes: &mixes,
slashings: st.Slashings,
previousEpochParticipation: st.PreviousEpochParticipation,
currentEpochParticipation: st.CurrentEpochParticipation,
justificationBits: st.JustificationBits,
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeaderCapella: st.LatestExecutionPayloadHeader,
nextWithdrawalIndex: st.NextWithdrawalIndex,
nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex,
version: version.Capella,
genesisTime: st.GenesisTime,
genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot),
slot: st.Slot,
fork: st.Fork,
latestBlockHeader: st.LatestBlockHeader,
blockRoots: &bRoots,
stateRoots: &sRoots,
historicalRoots: hRoots,
eth1Data: st.Eth1Data,
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
randaoMixes: &mixes,
slashings: st.Slashings,
previousEpochParticipation: st.PreviousEpochParticipation,
currentEpochParticipation: st.CurrentEpochParticipation,
justificationBits: st.JustificationBits,
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeader: initialPayloadHeader,
nextWithdrawalIndex: st.NextWithdrawalIndex,
nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex,
dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount),
@@ -465,7 +482,7 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[nativetypes.InactivityScores] = stateutil.NewRef(1)
b.sharedFieldReferences[nativetypes.LatestExecutionPayloadHeaderCapella] = stateutil.NewRef(1) // New in Capella.
b.sharedFieldReferences[nativetypes.LatestExecutionPayloadHeader] = stateutil.NewRef(1)
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
@@ -474,7 +491,7 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
}
// Copy returns a deep copy of the beacon state.
func (b *BeaconState) Copy() state.BeaconState {
func (b *BeaconState) Copy() (state.BeaconState, error) {
b.lock.RLock()
defer b.lock.RUnlock()
@@ -490,6 +507,11 @@ func (b *BeaconState) Copy() state.BeaconState {
fieldCount = params.BeaconConfig().BeaconStateCapellaFieldCount
}
// TODO: may panic!
header, err := b.latestExecutionPayloadHeaderVal()
if err != nil {
return nil, errors.Wrap(err, "failed to get latest execution payload header")
}
dst := &BeaconState{
version: b.version,
@@ -518,18 +540,17 @@ func (b *BeaconState) Copy() state.BeaconState {
inactivityScores: b.inactivityScores,
// Everything else, too small to be concerned about, constant size.
genesisValidatorsRoot: b.genesisValidatorsRoot,
justificationBits: b.justificationBitsVal(),
fork: b.forkVal(),
latestBlockHeader: b.latestBlockHeaderVal(),
eth1Data: b.eth1DataVal(),
previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
finalizedCheckpoint: b.finalizedCheckpointVal(),
currentSyncCommittee: b.currentSyncCommitteeVal(),
nextSyncCommittee: b.nextSyncCommitteeVal(),
latestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(),
latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapellaVal(),
genesisValidatorsRoot: b.genesisValidatorsRoot,
justificationBits: b.justificationBitsVal(),
fork: b.forkVal(),
latestBlockHeader: b.latestBlockHeaderVal(),
eth1Data: b.eth1DataVal(),
previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
finalizedCheckpoint: b.finalizedCheckpointVal(),
currentSyncCommittee: b.currentSyncCommitteeVal(),
nextSyncCommittee: b.nextSyncCommitteeVal(),
latestExecutionPayloadHeader: header,
dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount),
@@ -596,7 +617,7 @@ func (b *BeaconState) Copy() state.BeaconState {
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
runtime.SetFinalizer(dst, finalizerCleanup)
return dst
return dst, nil
}
// HashTreeRoot of the beacon state retrieves the Merkle root of the trie
@@ -827,8 +848,6 @@ func (b *BeaconState) rootSelector(ctx context.Context, field nativetypes.FieldI
return stateutil.SyncCommitteeRoot(b.nextSyncCommittee)
case nativetypes.LatestExecutionPayloadHeader:
return b.latestExecutionPayloadHeader.HashTreeRoot()
case nativetypes.LatestExecutionPayloadHeaderCapella:
return b.latestExecutionPayloadHeaderCapella.HashTreeRoot()
case nativetypes.NextWithdrawalIndex:
return ssz.Uint64Root(b.nextWithdrawalIndex), nil
case nativetypes.NextWithdrawalValidatorIndex:

View File

@@ -65,8 +65,6 @@ func (f FieldIndex) String(_ int) string {
return "nextSyncCommittee"
case LatestExecutionPayloadHeader:
return "latestExecutionPayloadHeader"
case LatestExecutionPayloadHeaderCapella:
return "LatestExecutionPayloadHeaderCapella"
case NextWithdrawalIndex:
return "NextWithdrawalIndex"
case NextWithdrawalValidatorIndex:
@@ -128,7 +126,7 @@ func (f FieldIndex) RealPosition() int {
return 22
case NextSyncCommittee:
return 23
case LatestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella:
case LatestExecutionPayloadHeader:
return 24
case NextWithdrawalIndex:
return 25
@@ -188,7 +186,6 @@ const (
CurrentSyncCommittee
NextSyncCommittee
LatestExecutionPayloadHeader
LatestExecutionPayloadHeaderCapella
NextWithdrawalIndex
NextWithdrawalValidatorIndex
)

View File

@@ -26,7 +26,9 @@ func TestBeaconState_ProtoBeaconStateCompatibility(t *testing.T) {
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.ToProto()
customStateProto, err := customState.ToProto()
require.NoError(t, err)
custom := customStateProto
assert.DeepSSZEqual(t, cloned, custom)
r1, err := customState.HashTreeRoot(ctx)
@@ -141,7 +143,8 @@ func BenchmarkStateClone_Manual(b *testing.B) {
require.NoError(b, err)
b.StartTimer()
for i := 0; i < b.N; i++ {
_ = st.ToProto()
_, err = st.ToProto()
require.NoError(b, err)
}
}

View File

@@ -99,9 +99,13 @@ func (e *epochBoundaryState) getByBlockRootLockFree(r [32]byte) (*rootStateInfo,
return nil, false, errNotRootStateInfo
}
copiedState, err := s.state.Copy()
if err != nil {
return nil, false, err
}
return &rootStateInfo{
root: r,
state: s.state.Copy(),
state: copiedState,
}, true, nil
}
@@ -138,9 +142,13 @@ func (e *epochBoundaryState) put(blockRoot [32]byte, s state.BeaconState) error
}); err != nil {
return err
}
copiedState, err := s.Copy()
if err != nil {
return err
}
if err := e.rootStateCache.AddIfNotPresent(&rootStateInfo{
root: blockRoot,
state: s.Copy(),
state: copiedState,
}); err != nil {
return err
}

View File

@@ -35,7 +35,11 @@ func TestEpochBoundaryStateCache_CanSaveAndDelete(t *testing.T) {
got, exists, err = e.getByBlockRoot([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")
s1, err := s.ToProtoUnsafe()
require.NoError(t, err)
s2, err := got.state.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, s2, s2, "Should have the same state")
got, exists, err = e.getBySlot(2)
require.NoError(t, err)
@@ -45,7 +49,11 @@ func TestEpochBoundaryStateCache_CanSaveAndDelete(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")
s1, err = s.ToProtoUnsafe()
require.NoError(t, err)
s2, err = got.state.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, s1, s2, "Should have the same state")
require.NoError(t, e.delete(r))
got, exists, err = e.getByBlockRoot([32]byte{'b'})

View File

@@ -187,7 +187,10 @@ func (s *State) loadStateByRoot(ctx context.Context, blockRoot [32]byte) (state.
defer span.End()
// First, it checks if the state exists in hot state cache.
cachedState := s.hotStateCache.get(blockRoot)
cachedState, err := s.hotStateCache.get(blockRoot)
if err != nil {
return nil, err
}
if cachedState != nil && !cachedState.IsNil() {
return cachedState, nil
}
@@ -248,8 +251,12 @@ func (s *State) latestAncestor(ctx context.Context, blockRoot [32]byte) (state.B
ctx, span := trace.StartSpan(ctx, "stateGen.latestAncestor")
defer span.End()
if s.isFinalizedRoot(blockRoot) && s.finalizedState() != nil {
return s.finalizedState(), nil
fState, err := s.finalizedState()
if err != nil {
return nil, err
}
if s.isFinalizedRoot(blockRoot) && fState != nil {
return fState, nil
}
b, err := s.beaconDB.Block(ctx, blockRoot)
@@ -279,12 +286,12 @@ func (s *State) latestAncestor(ctx context.Context, blockRoot [32]byte) (state.B
}
// Does the state exist in the hot state cache.
if s.hotStateCache.has(parentRoot) {
return s.hotStateCache.get(parentRoot), nil
return s.hotStateCache.get(parentRoot)
}
// Does the state exist in finalized info cache.
if s.isFinalizedRoot(parentRoot) {
return s.finalizedState(), nil
return s.finalizedState()
}
// Does the state exist in epoch boundary cache.

View File

@@ -30,7 +30,11 @@ 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())
s1, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2)
}
func TestStateByRoot_ColdState(t *testing.T) {
@@ -53,7 +57,11 @@ 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())
s1, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2)
bal, err := service.BalancesByRoot(ctx, bRoot)
require.NoError(t, err)
@@ -75,7 +83,11 @@ func TestStateByRootIfCachedNoCopy_HotState(t *testing.T) {
service.hotStateCache.put(r, beaconState)
loadedState := service.StateByRootIfCachedNoCopy(r)
require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe())
s1, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2)
}
func TestStateByRootIfCachedNoCopy_ColdState(t *testing.T) {
@@ -157,7 +169,11 @@ func TestStateByRoot_HotStateCached(t *testing.T) {
loadedState, err := service.StateByRoot(ctx, r)
require.NoError(t, err)
require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe())
s1, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s1, s2)
}
func TestDeleteStateFromCaches(t *testing.T) {
@@ -203,7 +219,11 @@ 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())
s0, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s1, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s0, s1)
}
func TestStateByRootInitialSync_UseEpochStateCache(t *testing.T) {
@@ -237,7 +257,11 @@ func TestStateByRootInitialSync_UseCache(t *testing.T) {
loadedState, err := service.StateByRootInitialSync(ctx, r)
require.NoError(t, err)
require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe())
s0, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s1, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s0, s1)
if service.hotStateCache.has(r) {
t.Error("Hot state cache was not invalidated")
}
@@ -279,7 +303,11 @@ 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())
s0, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s1, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s0, s1)
}
func TestLoadeStateByRoot_FinalizedState(t *testing.T) {
@@ -303,7 +331,11 @@ 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())
s0, err := loadedState.ToProtoUnsafe()
require.NoError(t, err)
s1, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
require.DeepSSZEqual(t, s0, s1)
}
func TestLoadeStateByRoot_EpochBoundaryStateCanProcess(t *testing.T) {

View File

@@ -39,21 +39,28 @@ func newHotStateCache() *hotStateCache {
// Get returns a cached response via input block root, if any.
// The response is copied by default.
func (c *hotStateCache) get(blockRoot [32]byte) state.BeaconState {
func (c *hotStateCache) get(blockRoot [32]byte) (state.BeaconState, error) {
c.lock.RLock()
defer c.lock.RUnlock()
item, exists := c.cache.Get(blockRoot)
copiedState, err := item.(state.BeaconState).Copy()
if err != nil {
return nil, err
}
if exists && item != nil {
hotStateCacheHit.Inc()
return item.(state.BeaconState).Copy()
return copiedState, nil
}
hotStateCacheMiss.Inc()
return nil
return nil, nil
}
func (c *hotStateCache) ByBlockRoot(r [32]byte) (state.BeaconState, error) {
st := c.get(r)
st, err := c.get(r)
if err != nil {
return nil, err
}
if st == nil {
return nil, ErrNotInCache
}

View File

@@ -13,11 +13,12 @@ import (
func TestHotStateCache_RoundTrip(t *testing.T) {
c := newHotStateCache()
root := [32]byte{'A'}
s := c.get(root)
s, err := c.get(root)
require.NoError(t, err)
assert.Equal(t, state.BeaconState(nil), s)
assert.Equal(t, false, c.has(root), "Empty cache has an object")
s, err := state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{
s, err = state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{
Slot: 10,
})
require.NoError(t, err)
@@ -25,9 +26,14 @@ func TestHotStateCache_RoundTrip(t *testing.T) {
c.put(root, s)
assert.Equal(t, true, c.has(root), "Empty cache does not have an object")
res := c.get(root)
res, err := c.get(root)
require.NoError(t, err)
assert.NotNil(t, s)
assert.DeepEqual(t, res.ToProto(), s.ToProto(), "Expected equal protos to return from cache")
resProto, err := res.ToProto()
require.NoError(t, err)
sProto, err := s.ToProto()
require.NoError(t, err)
assert.DeepEqual(t, resProto, sProto, "Expected equal protos to return from cache")
c.delete(root)
assert.Equal(t, false, c.has(root), "Cache not supposed to have the object")

View File

@@ -115,7 +115,9 @@ func (s *State) MigrateToCold(ctx context.Context, fRoot [32]byte) error {
return err
}
if ok {
s.SaveFinalizedState(fSlot, fRoot, fInfo.state)
if err := s.SaveFinalizedState(fSlot, fRoot, fInfo.state); err != nil {
return err
}
}
return nil

View File

@@ -53,7 +53,11 @@ 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")
s1, err := beaconState.ToProtoUnsafe()
require.NoError(t, err)
s2, err := gotState.ToProtoUnsafe()
require.NoError(t, err)
assert.DeepSSZEqual(t, s1, s2, "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)
@@ -145,7 +149,8 @@ func TestMigrateToCold_ParallelCalls(t *testing.T) {
service := New(beaconDB, doublylinkedtree.New())
service.slotsPerArchivedPoint = 1
beaconState, pks := util.DeterministicGenesisState(t, 32)
genState := beaconState.Copy()
genState, err := beaconState.Copy()
require.NoError(t, err)
genesisStateRoot, err := beaconState.HashTreeRoot(ctx)
require.NoError(t, err)
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])

View File

@@ -32,7 +32,7 @@ func (_ *MockStateManager) Resume(_ context.Context, _ state.BeaconState) (state
}
// SaveFinalizedState --
func (_ *MockStateManager) SaveFinalizedState(_ types.Slot, _ [32]byte, _ state.BeaconState) {
func (_ *MockStateManager) SaveFinalizedState(_ types.Slot, _ [32]byte, _ state.BeaconState) error {
panic("implement me")
}

View File

@@ -140,7 +140,7 @@ func (m *mockHistory) Block(_ context.Context, blockRoot [32]byte) (interfaces.S
func (m *mockHistory) StateOrError(_ context.Context, blockRoot [32]byte) (state.BeaconState, error) {
if s, ok := m.states[blockRoot]; ok {
return s.Copy(), nil
return s.Copy()
}
return nil, db.ErrNotFoundState
}
@@ -213,9 +213,12 @@ func newMockHistory(t *testing.T, hist []mockHistorySpec, current types.Slot) *m
// add genesis block as canonical
mh.addBlock(pr, gb, true)
// add genesis state, indexed by unapplied genesis block - genesis block is never really processed...
mh.addState(pr, gs.Copy())
s0, err := gs.Copy()
require.NoError(t, err)
mh.addState(pr, s0)
ps := gs.Copy()
ps, err := gs.Copy()
require.NoError(t, err)
for _, spec := range hist {
// call process_slots and process_block separately, because process_slots updates values used in randao mix
// which influences proposer_index.
@@ -259,7 +262,8 @@ func newMockHistory(t *testing.T, hist []mockHistorySpec, current types.Slot) *m
mh.hideState(pr, s)
}
mh.addBlock(pr, b, spec.canonicalBlock)
ps = s.Copy()
ps, err = s.Copy()
require.NoError(t, err)
}
require.NoError(t, mh.validateRoots())

View File

@@ -449,7 +449,9 @@ func tree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte,
if err := beaconDB.SaveBlock(context.Background(), wsb); err != nil {
return nil, nil, err
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
copied, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied, bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
return nil, nil, err
}
returnedBlocks = append(returnedBlocks, beaconBlock)
@@ -532,7 +534,9 @@ func tree2(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte,
if err := beaconDB.SaveBlock(context.Background(), wsb); err != nil {
return nil, nil, err
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
copied, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied, bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
return nil, nil, err
}
returnedBlocks = append(returnedBlocks, beaconBlock)
@@ -608,7 +612,9 @@ func tree3(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte,
if err := beaconDB.SaveBlock(context.Background(), wsb); err != nil {
return nil, nil, err
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
copied, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied, bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
return nil, nil, err
}
returnedBlocks = append(returnedBlocks, beaconBlock)
@@ -678,7 +684,9 @@ func tree4(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte,
if err := beaconDB.SaveBlock(context.Background(), wsb); err != nil {
return nil, nil, err
}
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
copied, err := st.Copy()
require.NoError(t, err)
if err := beaconDB.SaveState(context.Background(), copied, bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
return nil, nil, err
}
returnedBlocks = append(returnedBlocks, beaconBlock)

View File

@@ -30,7 +30,7 @@ type StateManager interface {
DeleteStateFromCaches(ctx context.Context, blockRoot [32]byte) error
ForceCheckpoint(ctx context.Context, root []byte) error
SaveState(ctx context.Context, blockRoot [32]byte, st state.BeaconState) error
SaveFinalizedState(fSlot types.Slot, fRoot [32]byte, fState state.BeaconState)
SaveFinalizedState(fSlot types.Slot, fRoot [32]byte, fState state.BeaconState) error
MigrateToCold(ctx context.Context, fRoot [32]byte) error
StateByRoot(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
BalancesByRoot(context.Context, [32]byte) ([]uint64, error)
@@ -126,7 +126,11 @@ func (s *State) Resume(ctx context.Context, fState state.BeaconState) (state.Bea
}
}()
s.finalizedInfo = &finalizedInfo{slot: fState.Slot(), root: fRoot, state: fState.Copy()}
copiedSt, err := fState.Copy()
if err != nil {
return nil, err
}
s.finalizedInfo = &finalizedInfo{slot: fState.Slot(), root: fRoot, state: copiedSt}
return fState, nil
}
@@ -134,12 +138,17 @@ func (s *State) Resume(ctx context.Context, fState state.BeaconState) (state.Bea
// 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) {
func (s *State) SaveFinalizedState(fSlot types.Slot, fRoot [32]byte, fState state.BeaconState) error {
s.finalizedInfo.lock.Lock()
defer s.finalizedInfo.lock.Unlock()
s.finalizedInfo.root = fRoot
s.finalizedInfo.state = fState.Copy()
copiedState, err := fState.Copy()
if err != nil {
return err
}
s.finalizedInfo.state = copiedState
s.finalizedInfo.slot = fSlot
return nil
}
// Returns true if input root equals to cached finalized root.
@@ -150,7 +159,7 @@ func (s *State) isFinalizedRoot(r [32]byte) bool {
}
// Returns the cached and copied finalized state.
func (s *State) finalizedState() state.BeaconState {
func (s *State) finalizedState() (state.BeaconState, error) {
s.finalizedInfo.lock.RLock()
defer s.finalizedInfo.lock.RUnlock()
return s.finalizedInfo.state.Copy()

View File

@@ -141,7 +141,8 @@ func VerifyBeaconStateValidatorByPubkey(t *testing.T, factory getState) {
key1 := keyCreator([]byte{'C'})
key2 := keyCreator([]byte{'D'})
assert.NoError(t, b.AppendValidator(&ethpb.Validator{PublicKey: key[:]}))
_ = b.Copy()
_, err := b.Copy()
require.NoError(t, err)
assert.NoError(t, b.AppendValidator(&ethpb.Validator{PublicKey: key1[:]}))
assert.NoError(t, b.AppendValidator(&ethpb.Validator{PublicKey: key2[:]}))
},
@@ -155,7 +156,8 @@ func VerifyBeaconStateValidatorByPubkey(t *testing.T, factory getState) {
key2 := keyCreator([]byte{'D'})
assert.NoError(t, b.AppendValidator(&ethpb.Validator{PublicKey: key1[:]}))
assert.NoError(t, b.AppendValidator(&ethpb.Validator{PublicKey: key2[:]}))
n := b.Copy()
n, err := b.Copy()
require.NoError(t, err)
// Append to another state
assert.NoError(t, n.AppendValidator(&ethpb.Validator{PublicKey: key[:]}))
@@ -168,7 +170,8 @@ func VerifyBeaconStateValidatorByPubkey(t *testing.T, factory getState) {
modifyFunc: func(b state.BeaconState, key [fieldparams.BLSPubkeyLength]byte) {
key1 := keyCreator([]byte{'C'})
assert.NoError(t, b.AppendValidator(&ethpb.Validator{PublicKey: key1[:]}))
n := b.Copy()
n, err := b.Copy()
require.NoError(t, err)
// Append to another state
assert.NoError(t, n.AppendValidator(&ethpb.Validator{PublicKey: key[:]}))

View File

@@ -724,7 +724,8 @@ func TestService_ProcessPendingBlockOnCorrectSlot(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -802,7 +803,8 @@ func TestService_ProcessBadPendingBlocks(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)

View File

@@ -648,7 +648,8 @@ func TestStatusRPCRequest_FinalizedBlockSkippedSlots(t *testing.T) {
expectedFinalizedEpoch := tt.expectedFinalizedEpoch
headSlot := tt.headSlot
nState := bState.Copy()
nState, err := bState.Copy()
require.NoError(t, err)
// Set up a head state with data we expect.
head := blocksTillHead[len(blocksTillHead)-1]
headRoot, err := head.Block().HashTreeRoot()

View File

@@ -41,7 +41,8 @@ func FuzzValidateBeaconBlockPubSub_Phase0(f *testing.F) {
require.NoError(f, err)
require.NoError(f, db.SaveState(ctx, beaconState, bRoot))
require.NoError(f, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(f, err)
require.NoError(f, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(f, err)
@@ -122,7 +123,8 @@ func FuzzValidateBeaconBlockPubSub_Altair(f *testing.F) {
require.NoError(f, err)
require.NoError(f, db.SaveState(ctx, beaconState, bRoot))
require.NoError(f, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(f, err)
require.NoError(f, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(f, err)
@@ -203,7 +205,8 @@ func FuzzValidateBeaconBlockPubSub_Bellatrix(f *testing.F) {
require.NoError(f, err)
require.NoError(f, db.SaveState(ctx, beaconState, bRoot))
require.NoError(f, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(f, err)
require.NoError(f, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(f, err)

View File

@@ -53,7 +53,8 @@ func TestValidateBeaconBlockPubSub_InvalidSignature(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -157,7 +158,8 @@ func TestValidateBeaconBlockPubSub_CanRecoverStateSummary(t *testing.T) {
bRoot, err := parentBlock.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -221,7 +223,8 @@ func TestValidateBeaconBlockPubSub_IsInCache(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(context.Background(), copied)
require.NoError(t, err)
@@ -287,7 +290,8 @@ func TestValidateBeaconBlockPubSub_ValidProposerSignature(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -352,7 +356,8 @@ func TestValidateBeaconBlockPubSub_WithLookahead(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
// The next block is only 1 epoch ahead so as to not induce a new seed.
blkSlot := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(coreTime.NextEpoch(copied)))
copied, err = transition.ProcessSlots(context.Background(), copied, blkSlot)
@@ -420,7 +425,8 @@ func TestValidateBeaconBlockPubSub_AdvanceEpochsForState(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
// The next block is at least 2 epochs ahead to induce shuffling and a new seed.
blkSlot := params.BeaconConfig().SlotsPerEpoch * 2
copied, err = transition.ProcessSlots(context.Background(), copied, blkSlot)
@@ -529,7 +535,8 @@ func TestValidateBeaconBlockPubSub_IgnoreAndQueueBlocksFromNearFuture(t *testing
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -819,7 +826,8 @@ func TestValidateBeaconBlockPubSub_ParentNotFinalizedDescendant(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -883,7 +891,8 @@ func TestValidateBeaconBlockPubSub_InvalidParentBlock(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -981,7 +990,8 @@ func TestValidateBeaconBlockPubSub_RejectBlocksFromBadParent(t *testing.T) {
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
// The next block is at least 2 epochs ahead to induce shuffling and a new seed.
blkSlot := params.BeaconConfig().SlotsPerEpoch * 2
copied, err = transition.ProcessSlots(context.Background(), copied, blkSlot)
@@ -1090,7 +1100,8 @@ func TestValidateBeaconBlockPubSub_ValidExecutionPayload(t *testing.T) {
require.NoError(t, beaconState.SetGenesisTime(uint64(presentTime)))
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -1161,7 +1172,8 @@ func TestValidateBeaconBlockPubSub_InvalidPayloadTimestamp(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -1265,7 +1277,8 @@ func Test_validateBellatrixBeaconBlockParentValidation(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)
@@ -1321,7 +1334,8 @@ func Test_validateBeaconBlockProcessingWhenParentIsOptimistic(t *testing.T) {
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
copied, err := beaconState.Copy()
require.NoError(t, err)
require.NoError(t, copied.SetSlot(1))
proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied)
require.NoError(t, err)

View File

@@ -57,7 +57,7 @@ func (s *Service) validateBlsToExecutionChange(ctx context.Context, pid peer.ID,
return pubsub.ValidationReject, err
}
// Validate the signature of the message using our batch gossip verifier.
sigBatch, err := blocks.BLSChangesSignatureBatch(ctx, st, []*ethpb.SignedBLSToExecutionChange{blsChange})
sigBatch, err := blocks.BLSChangesSignatureBatch(st, []*ethpb.SignedBLSToExecutionChange{blsChange})
if err != nil {
return pubsub.ValidationReject, err
}

View File

@@ -1035,7 +1035,8 @@ func fillUpBlocksAndState(ctx context.Context, t *testing.T, beaconDB db.Databas
assert.NoError(t, gs.SetCurrentSyncCommittee(sCom))
assert.NoError(t, beaconDB.SaveGenesisData(context.Background(), gs))
testState := gs.Copy()
testState, err := gs.Copy()
assert.NoError(t, err)
hRoot := [32]byte{}
for i := types.Slot(1); i <= params.BeaconConfig().SlotsPerEpoch; i++ {
blk, err := util.GenerateFullBlockAltair(testState, keys, util.DefaultBlockGenConfig(), i)

View File

@@ -5,10 +5,7 @@ go_library(
srcs = [
"flags.go",
"interop.go",
] + select({
"//validator/client/validator-client-factory:beacon_api_usage": ["beacon_api_flags.go"],
"//conditions:default": ["grpc_flags.go"],
}),
],
importpath = "github.com/prysmaticlabs/prysm/v3/cmd/validator/flags",
visibility = [
"//cmd/prysmctl:__subpackages__",

View File

@@ -1,8 +0,0 @@
//go:build use_beacon_api
// +build use_beacon_api
package flags
const (
BuiltWithBeaconApi = true
)

View File

@@ -1,8 +0,0 @@
//go:build !use_beacon_api
// +build !use_beacon_api
package flags
const (
BuiltWithBeaconApi = false
)

View File

@@ -49,6 +49,7 @@ func startNode(ctx *cli.Context) error {
var appFlags = []cli.Flag{
flags.BeaconRPCProviderFlag,
flags.BeaconRPCGatewayProviderFlag,
flags.BeaconRESTApiProviderFlag,
flags.CertFlag,
flags.GraffitiFlag,
flags.DisablePenaltyRewardLogFlag,
@@ -112,11 +113,6 @@ var appFlags = []cli.Flag{
}
func init() {
// Append the Beacon REST API flags
if flags.BuiltWithBeaconApi {
appFlags = append(appFlags, flags.BeaconRESTApiProviderFlag)
}
appFlags = cmd.WrapFlags(append(appFlags, features.ValidatorFlags...))
}

View File

@@ -86,6 +86,7 @@ var appHelpFlagGroups = []flagGroup{
Flags: []cli.Flag{
flags.BeaconRPCProviderFlag,
flags.BeaconRPCGatewayProviderFlag,
flags.BeaconRESTApiProviderFlag,
flags.CertFlag,
flags.EnableWebFlag,
flags.DisablePenaltyRewardLogFlag,
@@ -128,16 +129,6 @@ var appHelpFlagGroups = []flagGroup{
}
func init() {
// Append the Beacon REST API flags
if flags.BuiltWithBeaconApi {
for groupIndex := range appHelpFlagGroups {
group := &appHelpFlagGroups[groupIndex]
if group.Name == "validator" {
group.Flags = append(group.Flags, flags.BeaconRESTApiProviderFlag)
}
}
}
cli.AppHelpTemplate = appHelpTemplate
type helpData struct {

Some files were not shown because too many files have changed in this diff Show More