mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-11 14:28:09 -05:00
Compare commits
16 Commits
moveCoreMe
...
versionRef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd51e70b74 | ||
|
|
5ee66a4a68 | ||
|
|
f4c7fb6182 | ||
|
|
077dcdc643 | ||
|
|
1fa864cb1a | ||
|
|
6357860cc2 | ||
|
|
cc1ea81d4a | ||
|
|
dd65622441 | ||
|
|
6c39301f33 | ||
|
|
5b12f5a27d | ||
|
|
105d73d59b | ||
|
|
db687bf56d | ||
|
|
f0403afb25 | ||
|
|
3f309968d4 | ||
|
|
52acaceb3f | ||
|
|
5216402f66 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -35,3 +35,6 @@ bin
|
||||
|
||||
# p2p metaData
|
||||
metaData
|
||||
|
||||
# execution API authentication
|
||||
jwt.hex
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
[](https://buildkite.com/prysmatic-labs/prysm)
|
||||
[](https://goreportcard.com/report/github.com/prysmaticlabs/prysm)
|
||||
[](https://github.com/ethereum/consensus-specs/tree/v1.1.10)
|
||||
[](https://github.com/ethereum/consensus-specs/tree/v1.2.0-rc.1)
|
||||
[](https://github.com/ethereum/execution-apis/tree/v1.0.0-alpha.9/src/engine)
|
||||
[](https://discord.gg/CTYGPUJ)
|
||||
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the [Ethereum Consensus](https://ethereum.org/en/eth2/) specification, developed by [Prysmatic Labs](https://prysmaticlabs.com). See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz/detect"
|
||||
"github.com/prysmaticlabs/prysm/io/file"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/mod/semver"
|
||||
@@ -56,7 +55,7 @@ func (o *OriginData) BlockBytes() []byte {
|
||||
}
|
||||
|
||||
func fname(prefix string, vu *detect.VersionedUnmarshaler, slot types.Slot, root [32]byte) string {
|
||||
return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, vu.Config.ConfigName, version.String(vu.Fork), slot, root)
|
||||
return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, vu.Config.ConfigName, vu.Fork.String(), slot, root)
|
||||
}
|
||||
|
||||
// DownloadFinalizedData downloads the most recently finalized state, and the block most recently applied to that state.
|
||||
@@ -70,7 +69,7 @@ func DownloadFinalizedData(ctx context.Context, client *Client) (*OriginData, er
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error detecting chain config for finalized state")
|
||||
}
|
||||
log.Printf("detected supported config in remote finalized state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
log.Printf("detected supported config in remote finalized state, name=%s, fork=%s", vu.Config.ConfigName, vu.Fork.String())
|
||||
s, err := vu.UnmarshalBeaconState(sb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error unmarshaling finalized state to correct version")
|
||||
@@ -194,7 +193,7 @@ func computeBackwardsCompatible(ctx context.Context, client *Client) (*WeakSubje
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error detecting chain config for beacon state")
|
||||
}
|
||||
log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", vu.Config.ConfigName, vu.Fork.String())
|
||||
|
||||
s, err := vu.UnmarshalBeaconState(sb)
|
||||
if err != nil {
|
||||
@@ -245,7 +244,7 @@ func getWeakSubjectivityEpochFromHead(ctx context.Context, client *Client) (type
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "error detecting chain config for beacon state")
|
||||
}
|
||||
log.Printf("detected supported config in remote head state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
log.Printf("detected supported config in remote head state, name=%s, fork=%s", vu.Config.ConfigName, vu.Fork.String())
|
||||
headState, err := vu.UnmarshalBeaconState(headBytes)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "error unmarshaling state to correct version")
|
||||
|
||||
@@ -29,7 +29,7 @@ go_test(
|
||||
data = glob(["testdata/**"]),
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -98,7 +98,7 @@ func TestClient_RegisterValidator(t *testing.T) {
|
||||
}
|
||||
reg := ð.SignedValidatorRegistrationV1{
|
||||
Message: ð.ValidatorRegistrationV1{
|
||||
FeeRecipient: ezDecode(t, fieldparams.EthBurnAddressHex),
|
||||
FeeRecipient: ezDecode(t, params.BeaconConfig().EthBurnAddressHex),
|
||||
GasLimit: 23,
|
||||
Timestamp: 42,
|
||||
Pubkey: ezDecode(t, "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"),
|
||||
|
||||
@@ -337,7 +337,7 @@ func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 104, [32]byte{'e'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
@@ -349,10 +349,19 @@ func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
||||
require.DeepEqual(t, []types.Slot{102, 103, 104}, slots)
|
||||
}
|
||||
|
||||
//
|
||||
// A <- B <- C
|
||||
// \ \
|
||||
// \ ---------- E
|
||||
// ---------- D
|
||||
|
||||
func TestService_ChainHeads_DoublyLinkedTree(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
@@ -20,6 +19,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -142,7 +142,7 @@ func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, er
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if blocks.IsPreBellatrixVersion(blk.Block().Version()) {
|
||||
if blk.Block().Version().IsPreBellatrix() {
|
||||
return params.BeaconConfig().ZeroHash, nil
|
||||
}
|
||||
payload, err := blk.Block().Body().ExecutionPayload()
|
||||
@@ -154,14 +154,14 @@ func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, er
|
||||
|
||||
// notifyForkchoiceUpdate 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,
|
||||
func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion version.ForkVersion,
|
||||
postStateHeader *ethpb.ExecutionPayloadHeader, blk interfaces.SignedBeaconBlock) (bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.notifyNewPayload")
|
||||
defer span.End()
|
||||
|
||||
// Execution payload is only supported in Bellatrix and beyond. Pre
|
||||
// merge blocks are never optimistic
|
||||
if blocks.IsPreBellatrixVersion(postStateVersion) {
|
||||
if postStateVersion.IsPreBellatrix() {
|
||||
return true, nil
|
||||
}
|
||||
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||
@@ -270,10 +270,10 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
||||
recipient, err := s.cfg.BeaconDB.FeeRecipientByValidatorID(ctx, proposerID)
|
||||
switch {
|
||||
case errors.Is(err, kv.ErrNotFoundFeeRecipient):
|
||||
if feeRecipient.String() == fieldparams.EthBurnAddressHex {
|
||||
if feeRecipient.String() == params.BeaconConfig().EthBurnAddressHex {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"validatorIndex": proposerID,
|
||||
"burnAddress": fieldparams.EthBurnAddressHex,
|
||||
"burnAddress": params.BeaconConfig().EthBurnAddressHex,
|
||||
}).Warn("Fee recipient is currently using the burn address, " +
|
||||
"you will not be rewarded transaction fees on this setting. " +
|
||||
"Please set a different eth address as the fee recipient. " +
|
||||
|
||||
@@ -806,7 +806,7 @@ func Test_GetPayloadAttribute(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, hasPayload)
|
||||
require.Equal(t, suggestedVid, vId)
|
||||
require.Equal(t, fieldparams.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
|
||||
|
||||
@@ -67,7 +67,7 @@ func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, justif
|
||||
log = log.WithField("justifiedEpoch", justified.Epoch)
|
||||
log = log.WithField("justifiedRoot", fmt.Sprintf("0x%s...", hex.EncodeToString(justified.Root)[:8]))
|
||||
log = log.WithField("parentRoot", fmt.Sprintf("0x%s...", hex.EncodeToString(block.ParentRoot())[:8]))
|
||||
log = log.WithField("version", version.String(block.Version()))
|
||||
log = log.WithField("version", block.Version().String())
|
||||
log = log.WithField("sinceSlotStartTime", prysmTime.Now().Sub(startTime))
|
||||
log = log.WithField("chainServiceProcessedTime", prysmTime.Now().Sub(receivedTime))
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -263,11 +262,11 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
|
||||
currentEth1DataDepositCount.Set(float64(postState.Eth1Data().DepositCount))
|
||||
processedDepositsCount.Set(float64(postState.Eth1DepositIndex() + 1))
|
||||
|
||||
var b *types.Balance
|
||||
var v []*types.Validator
|
||||
var b *precompute.Balance
|
||||
var v []*precompute.Validator
|
||||
var err error
|
||||
switch headState.Version() {
|
||||
case version.Phase0:
|
||||
switch {
|
||||
case headState.Version().IsPhase0Compatible():
|
||||
// Validator participation should be viewed on the canonical chain.
|
||||
v, b, err = precompute.New(ctx, headState)
|
||||
if err != nil {
|
||||
@@ -277,7 +276,7 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case version.Altair, version.Bellatrix:
|
||||
case headState.Version().IsParticipationBitsCompatible():
|
||||
v, b, err = altair.InitializePrecomputeValidators(ctx, headState)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -317,15 +317,15 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
return s.handleEpochBoundary(ctx, postState)
|
||||
}
|
||||
|
||||
func getStateVersionAndPayload(st state.BeaconState) (int, *ethpb.ExecutionPayloadHeader, error) {
|
||||
func getStateVersionAndPayload(st state.BeaconState) (version.ForkVersion, *ethpb.ExecutionPayloadHeader, error) {
|
||||
if st == nil {
|
||||
return 0, nil, errors.New("nil state")
|
||||
}
|
||||
var preStateHeader *ethpb.ExecutionPayloadHeader
|
||||
var err error
|
||||
preStateVersion := st.Version()
|
||||
switch preStateVersion {
|
||||
case version.Phase0, version.Altair:
|
||||
switch {
|
||||
case preStateVersion.IsPreBellatrix():
|
||||
default:
|
||||
preStateHeader, err = st.LatestExecutionPayloadHeader()
|
||||
if err != nil {
|
||||
@@ -378,7 +378,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
Messages: [][32]byte{},
|
||||
}
|
||||
type versionAndHeader struct {
|
||||
version int
|
||||
version version.ForkVersion
|
||||
header *ethpb.ExecutionPayloadHeader
|
||||
}
|
||||
preVersionAndHeaders := make([]*versionAndHeader, len(blks))
|
||||
@@ -459,9 +459,12 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
if err := s.cfg.ForkChoiceStore.InsertNode(ctx, preState, lastBR); err != nil {
|
||||
return errors.Wrap(err, "could not insert last block in batch to forkchoice")
|
||||
}
|
||||
// Prune forkchoice store
|
||||
if err := s.cfg.ForkChoiceStore.Prune(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(fCheckpoints[len(blks)-1].Root))); err != nil {
|
||||
return errors.Wrap(err, "could not prune fork choice nodes")
|
||||
// Prune forkchoice store only if the new finalized checkpoint is higher
|
||||
// than the finalized checkpoint in forkchoice store.
|
||||
if fCheckpoints[len(blks)-1].Epoch > s.cfg.ForkChoiceStore.FinalizedEpoch() {
|
||||
if err := s.cfg.ForkChoiceStore.Prune(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(fCheckpoints[len(blks)-1].Root))); err != nil {
|
||||
return errors.Wrap(err, "could not prune fork choice nodes")
|
||||
}
|
||||
}
|
||||
|
||||
// Set their optimistic status
|
||||
@@ -681,9 +684,9 @@ 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 *ethpb.ExecutionPayloadHeader, blk interfaces.SignedBeaconBlock) error {
|
||||
func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion version.ForkVersion, stateHeader *ethpb.ExecutionPayloadHeader, blk interfaces.SignedBeaconBlock) error {
|
||||
// Skip validation if block is older than Bellatrix.
|
||||
if blocks.IsPreBellatrixVersion(blk.Block().Version()) {
|
||||
if blk.Block().Version().IsPreBellatrix() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -698,7 +701,7 @@ func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion
|
||||
|
||||
// Handle case where pre-state is Altair but block contains payload.
|
||||
// To reach here, the block must have contained a valid payload.
|
||||
if blocks.IsPreBellatrixVersion(stateVersion) {
|
||||
if stateVersion.IsPreBellatrix() {
|
||||
return s.validateMergeBlock(ctx, blk)
|
||||
}
|
||||
|
||||
|
||||
@@ -343,6 +343,69 @@ func TestStore_OnBlockBatch_ProtoArray(t *testing.T) {
|
||||
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedEpoch())
|
||||
}
|
||||
|
||||
func TestStore_OnBlockBatch_PruneOK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
wsb, err := wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
|
||||
st, keys := util.DeterministicGenesisState(t, 64)
|
||||
|
||||
bState := st.Copy()
|
||||
|
||||
var blks []interfaces.SignedBeaconBlock
|
||||
var blkRoots [][32]byte
|
||||
var firstState state.BeaconState
|
||||
for i := 1; i < 128; i++ {
|
||||
b, err := util.GenerateFullBlock(bState, keys, util.DefaultBlockGenConfig(), types.Slot(i))
|
||||
require.NoError(t, err)
|
||||
wsb, err := wrapper.WrappedSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
bState, err = transition.ExecuteStateTransition(ctx, bState, wsb)
|
||||
if i == 32 {
|
||||
firstState = bState.Copy()
|
||||
}
|
||||
require.NoError(t, err)
|
||||
root, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(root, wsb)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
blks = append(blks, wsb)
|
||||
blkRoots = append(blkRoots, root)
|
||||
}
|
||||
|
||||
for i := 0; i < 32; i++ {
|
||||
require.NoError(t, beaconDB.SaveBlock(context.Background(), blks[i]))
|
||||
}
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: blkRoots[31][:], Epoch: 1}, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: blkRoots[31][:], Epoch: 1}, [32]byte{'b'})
|
||||
require.NoError(t, service.cfg.StateGen.SaveState(ctx, blkRoots[31], firstState))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, firstState, blkRoots[31]))
|
||||
err = service.onBlockBatch(ctx, blks[32:], blkRoots[32:])
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestStore_OnBlockBatch_DoublyLinkedTree(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
@@ -206,7 +206,7 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
||||
s.store = store.New(justified, finalized)
|
||||
|
||||
var forkChoicer f.ForkChoicer
|
||||
fRoot := bytesutil.ToBytes32(finalized.Root)
|
||||
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
forkChoicer = doublylinkedtree.New(justified.Epoch, finalized.Epoch)
|
||||
} else {
|
||||
|
||||
@@ -11,6 +11,7 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/feed:go_default_library",
|
||||
"//beacon-chain/core/feed/block:go_default_library",
|
||||
"//beacon-chain/core/feed/operation:go_default_library",
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
|
||||
opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
||||
@@ -39,7 +40,7 @@ type ChainService struct {
|
||||
CurrentJustifiedCheckPoint *ethpb.Checkpoint
|
||||
PreviousJustifiedCheckPoint *ethpb.Checkpoint
|
||||
Slot *types.Slot // Pointer because 0 is a useful value, so checking against it can be incorrect.
|
||||
Balance *types.Balance
|
||||
Balance *precompute.Balance
|
||||
CanonicalRoots map[[32]byte]bool
|
||||
Fork *ethpb.Fork
|
||||
ETH1Data *ethpb.Eth1Data
|
||||
@@ -337,7 +338,7 @@ func (s *ChainService) CurrentSlot() types.Slot {
|
||||
}
|
||||
|
||||
// Participation mocks the same method in the chain service.
|
||||
func (s *ChainService) Participation(_ uint64) *types.Balance {
|
||||
func (s *ChainService) Participation(_ uint64) *precompute.Balance {
|
||||
return s.Balance
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ load("@prysm//tools/go:def.bzl", "go_library")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"error.go",
|
||||
"metric.go",
|
||||
"option.go",
|
||||
"service.go",
|
||||
],
|
||||
@@ -10,13 +12,19 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client/builder:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//network:go_default_library",
|
||||
"//network/authorization:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
7
beacon-chain/builder/error.go
Normal file
7
beacon-chain/builder/error.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package builder
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
var (
|
||||
ErrNotRunning = errors.New("builder is not running")
|
||||
)
|
||||
37
beacon-chain/builder/metric.go
Normal file
37
beacon-chain/builder/metric.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
|
||||
var (
|
||||
submitBlindedBlockLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "submit_blinded_block_latency_milliseconds",
|
||||
Help: "Captures RPC latency for submitting blinded block in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
getHeaderLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "get_header_latency_milliseconds",
|
||||
Help: "Captures RPC latency for get header in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
getStatusLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "get_status_latency_milliseconds",
|
||||
Help: "Captures RPC latency for get status in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
registerValidatorLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "register_validator_latency_milliseconds",
|
||||
Help: "Captures RPC latency for register validator in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
)
|
||||
@@ -1,6 +1,7 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
"github.com/prysmaticlabs/prysm/network/authorization"
|
||||
@@ -26,6 +27,14 @@ func WithBuilderEndpoints(endpoint string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDatabase sets the database for the beacon chain builder service.
|
||||
func WithDatabase(database db.HeadAccessDatabase) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.beaconDB = database
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func covertEndPoint(ep string) network.Endpoint {
|
||||
return network.Endpoint{
|
||||
Url: ep,
|
||||
|
||||
@@ -2,26 +2,33 @@ package builder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/api/client/builder"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
v1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// BlockBuilder defines the interface for interacting with the block builder
|
||||
type BlockBuilder interface {
|
||||
SubmitBlindedBlock(ctx context.Context, block *ethpb.SignedBlindedBeaconBlockBellatrix) (*v1.ExecutionPayload, error)
|
||||
GetHeader(ctx context.Context, slot types.Slot, parentHash [32]byte, pubKey [48]byte) (*ethpb.SignedBuilderBid, error)
|
||||
Status() error
|
||||
Status(ctx context.Context) error
|
||||
RegisterValidator(ctx context.Context, reg *ethpb.SignedValidatorRegistrationV1) error
|
||||
}
|
||||
|
||||
// config defines a config struct for dependencies into the service.
|
||||
type config struct {
|
||||
builderEndpoint network.Endpoint
|
||||
beaconDB db.HeadAccessDatabase
|
||||
headFetcher blockchain.HeadFetcher
|
||||
}
|
||||
|
||||
// Service defines a service that provides a client for interacting with the beacon chain and MEV relay network.
|
||||
@@ -56,22 +63,59 @@ func (*Service) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubmitBlindedBlock is currently a stub.
|
||||
func (*Service) SubmitBlindedBlock(context.Context, *ethpb.SignedBlindedBeaconBlockBellatrix) (*v1.ExecutionPayload, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
// SubmitBlindedBlock submits a blinded block to the builder relay network.
|
||||
func (s *Service) SubmitBlindedBlock(ctx context.Context, b *ethpb.SignedBlindedBeaconBlockBellatrix) (*v1.ExecutionPayload, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "builder.SubmitBlindedBlock")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
submitBlindedBlockLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
return s.c.SubmitBlindedBlock(ctx, b)
|
||||
}
|
||||
|
||||
// GetHeader is currently a stub.
|
||||
func (*Service) GetHeader(context.Context, types.Slot, [32]byte, [48]byte) (*ethpb.SignedBuilderBid, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
// GetHeader retrieves the header for a given slot and parent hash from the builder relay network.
|
||||
func (s *Service) GetHeader(ctx context.Context, slot types.Slot, parentHash [32]byte, pubKey [48]byte) (*ethpb.SignedBuilderBid, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "builder.GetHeader")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
getHeaderLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
return s.c.GetHeader(ctx, slot, parentHash, pubKey)
|
||||
}
|
||||
|
||||
// Status is currently a stub.
|
||||
func (*Service) Status() error {
|
||||
return errors.New("not implemented")
|
||||
// Status retrieves the status of the builder relay network.
|
||||
func (s *Service) Status(ctx context.Context) error {
|
||||
ctx, span := trace.StartSpan(ctx, "builder.Status")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
getStatusLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
return s.c.Status(ctx)
|
||||
}
|
||||
|
||||
// RegisterValidator is currently a stub.
|
||||
func (*Service) RegisterValidator(context.Context, *ethpb.SignedValidatorRegistrationV1) error {
|
||||
return errors.New("not implemented")
|
||||
// RegisterValidator registers a validator with the builder relay network.
|
||||
// It also saves the registration object to the DB.
|
||||
func (s *Service) RegisterValidator(ctx context.Context, reg *ethpb.SignedValidatorRegistrationV1) error {
|
||||
ctx, span := trace.StartSpan(ctx, "builder.RegisterValidator")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
registerValidatorLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
idx, exists := s.cfg.headFetcher.HeadPublicKeyToValidatorIndex(bytesutil.ToBytes48(reg.Message.Pubkey))
|
||||
if !exists {
|
||||
return nil // If the pubkey is not found, it is not a validator. Do nothing.
|
||||
}
|
||||
if err := s.c.RegisterValidator(ctx, reg); err != nil {
|
||||
return errors.Wrap(err, "could not register validator")
|
||||
}
|
||||
|
||||
return s.cfg.beaconDB.SaveRegistrationsByValidatorIDs(ctx, []types.ValidatorIndex{idx}, []*ethpb.ValidatorRegistrationV1{reg.Message})
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (c *SyncCommitteeHeadStateCache) Put(slot types.Slot, st state.BeaconState)
|
||||
return ErrNilValueProvided
|
||||
}
|
||||
|
||||
if st.Version() == version.Phase0 {
|
||||
if st.Version().IsPhase0Compatible() {
|
||||
return ErrIncorrectType
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/core/epoch:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
|
||||
@@ -9,17 +9,16 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/math"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// InitializePrecomputeValidators precomputes individual validator for its attested balances and the total sum of validators attested balances of the epoch.
|
||||
func InitializePrecomputeValidators(ctx context.Context, beaconState state.BeaconState) ([]*types.Validator, *types.Balance, error) {
|
||||
func InitializePrecomputeValidators(ctx context.Context, beaconState state.BeaconState) ([]*precompute.Validator, *precompute.Balance, error) {
|
||||
_, span := trace.StartSpan(ctx, "altair.InitializePrecomputeValidators")
|
||||
defer span.End()
|
||||
vals := make([]*types.Validator, beaconState.NumValidators())
|
||||
bal := &types.Balance{}
|
||||
vals := make([]*precompute.Validator, beaconState.NumValidators())
|
||||
bal := &precompute.Balance{}
|
||||
prevEpoch := time.PrevEpoch(beaconState)
|
||||
currentEpoch := time.CurrentEpoch(beaconState)
|
||||
inactivityScores, err := beaconState.InactivityScores()
|
||||
@@ -34,7 +33,7 @@ func InitializePrecomputeValidators(ctx context.Context, beaconState state.Beaco
|
||||
}
|
||||
if err := beaconState.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
|
||||
// Set validator's balance, inactivity score and slashed/withdrawable status.
|
||||
v := &types.Validator{
|
||||
v := &precompute.Validator{
|
||||
CurrentEpochEffectiveBalance: val.EffectiveBalance(),
|
||||
InactivityScore: inactivityScores[idx],
|
||||
IsSlashed: val.Slashed(),
|
||||
@@ -75,18 +74,57 @@ func InitializePrecomputeValidators(ctx context.Context, beaconState state.Beaco
|
||||
func ProcessInactivityScores(
|
||||
ctx context.Context,
|
||||
beaconState state.BeaconState,
|
||||
vals []*types.Validator,
|
||||
) (state.BeaconState, []*types.Validator, error) {
|
||||
vals []*precompute.Validator,
|
||||
) (state.BeaconState, []*precompute.Validator, error) {
|
||||
_, span := trace.StartSpan(ctx, "altair.ProcessInactivityScores")
|
||||
defer span.End()
|
||||
|
||||
currEpoch := time.CurrentEpoch(beaconState)
|
||||
prevEpoch := time.PrevEpoch(beaconState)
|
||||
finalizedEpoch := beaconState.FinalizedCheckpointEpoch()
|
||||
vals, err := beaconState.ProcessInactivityScores(ctx, currEpoch, prevEpoch, finalizedEpoch, vals)
|
||||
cfg := params.BeaconConfig()
|
||||
if time.CurrentEpoch(beaconState) == cfg.GenesisEpoch {
|
||||
return beaconState, vals, nil
|
||||
}
|
||||
|
||||
inactivityScores, err := beaconState.InactivityScores()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
bias := cfg.InactivityScoreBias
|
||||
recoveryRate := cfg.InactivityScoreRecoveryRate
|
||||
prevEpoch := time.PrevEpoch(beaconState)
|
||||
finalizedEpoch := beaconState.FinalizedCheckpointEpoch()
|
||||
for i, v := range vals {
|
||||
if !precompute.EligibleForRewards(v) {
|
||||
continue
|
||||
}
|
||||
|
||||
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
|
||||
// Decrease inactivity score when validator gets target correct.
|
||||
if v.InactivityScore > 0 {
|
||||
v.InactivityScore -= 1
|
||||
}
|
||||
} else {
|
||||
v.InactivityScore, err = math.Add64(v.InactivityScore, bias)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !helpers.IsInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
score := recoveryRate
|
||||
// Prevents underflow below 0.
|
||||
if score > v.InactivityScore {
|
||||
score = v.InactivityScore
|
||||
}
|
||||
v.InactivityScore -= score
|
||||
}
|
||||
inactivityScores[i] = v.InactivityScore
|
||||
}
|
||||
|
||||
if err := beaconState.SetInactivityScores(inactivityScores); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return beaconState, vals, nil
|
||||
}
|
||||
|
||||
@@ -103,9 +141,9 @@ func ProcessInactivityScores(
|
||||
func ProcessEpochParticipation(
|
||||
ctx context.Context,
|
||||
beaconState state.BeaconState,
|
||||
bal *types.Balance,
|
||||
vals []*types.Validator,
|
||||
) ([]*types.Validator, *types.Balance, error) {
|
||||
bal *precompute.Balance,
|
||||
vals []*precompute.Validator,
|
||||
) ([]*precompute.Validator, *precompute.Balance, error) {
|
||||
_, span := trace.StartSpan(ctx, "altair.ProcessEpochParticipation")
|
||||
defer span.End()
|
||||
|
||||
@@ -171,8 +209,8 @@ func ProcessEpochParticipation(
|
||||
// This is an optimized version by passing in precomputed validator attesting records and and total epoch balances.
|
||||
func ProcessRewardsAndPenaltiesPrecompute(
|
||||
beaconState state.BeaconState,
|
||||
bal *types.Balance,
|
||||
vals []*types.Validator,
|
||||
bal *precompute.Balance,
|
||||
vals []*precompute.Validator,
|
||||
) (state.BeaconState, error) {
|
||||
// Don't process rewards and penalties in genesis epoch.
|
||||
cfg := params.BeaconConfig()
|
||||
@@ -215,7 +253,7 @@ func ProcessRewardsAndPenaltiesPrecompute(
|
||||
|
||||
// AttestationsDelta computes and returns the rewards and penalties differences for individual validators based on the
|
||||
// voting records.
|
||||
func AttestationsDelta(beaconState state.BeaconState, bal *types.Balance, vals []*types.Validator) (rewards, penalties []uint64, err error) {
|
||||
func AttestationsDelta(beaconState state.BeaconState, bal *precompute.Balance, vals []*precompute.Validator) (rewards, penalties []uint64, err error) {
|
||||
numOfVals := beaconState.NumValidators()
|
||||
rewards = make([]uint64, numOfVals)
|
||||
penalties = make([]uint64, numOfVals)
|
||||
@@ -247,8 +285,8 @@ func AttestationsDelta(beaconState state.BeaconState, bal *types.Balance, vals [
|
||||
}
|
||||
|
||||
func attestationDelta(
|
||||
bal *types.Balance,
|
||||
val *types.Validator,
|
||||
bal *precompute.Balance,
|
||||
val *precompute.Validator,
|
||||
baseRewardMultiplier, inactivityDenominator uint64,
|
||||
inactivityLeak bool) (reward, penalty uint64, err error) {
|
||||
eligible := val.IsActivePrevEpoch || (val.IsSlashed && !val.IsWithdrawableCurrentEpoch)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
|
||||
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
|
||||
@@ -34,29 +35,29 @@ func TestInitializeEpochValidators_Ok(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
v, b, err := InitializePrecomputeValidators(context.Background(), s)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsSlashed: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InactivityScore: 0,
|
||||
}, v[0], "Incorrect validator 0 status")
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InactivityScore: 1,
|
||||
}, v[1], "Incorrect validator 1 status")
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsActivePrevEpoch: true,
|
||||
IsActiveCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InactivityScore: 2,
|
||||
}, v[2], "Incorrect validator 2 status")
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsActivePrevEpoch: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InactivityScore: 3,
|
||||
}, v[3], "Incorrect validator 3 status")
|
||||
|
||||
wantedBalances := &types.Balance{
|
||||
wantedBalances := &precompute.Balance{
|
||||
ActiveCurrentEpoch: 100,
|
||||
ActivePrevEpoch: 200,
|
||||
}
|
||||
@@ -95,13 +96,13 @@ func TestProcessEpochParticipation(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, &types.Validator{
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: true,
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}, validators[0])
|
||||
require.DeepEqual(t, &types.Validator{
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: true,
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
@@ -110,7 +111,7 @@ func TestProcessEpochParticipation(t *testing.T) {
|
||||
IsPrevEpochAttester: true,
|
||||
IsPrevEpochSourceAttester: true,
|
||||
}, validators[1])
|
||||
require.DeepEqual(t, &types.Validator{
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: true,
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
@@ -121,7 +122,7 @@ func TestProcessEpochParticipation(t *testing.T) {
|
||||
IsCurrentEpochTargetAttester: true,
|
||||
IsPrevEpochTargetAttester: true,
|
||||
}, validators[2])
|
||||
require.DeepEqual(t, &types.Validator{
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: true,
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
@@ -173,13 +174,13 @@ func TestProcessEpochParticipation_InactiveValidator(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
validators, balance, err = ProcessEpochParticipation(context.Background(), st, balance, validators)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, &types.Validator{
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: false,
|
||||
IsActivePrevEpoch: false,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}, validators[0])
|
||||
require.DeepEqual(t, &types.Validator{
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: false,
|
||||
IsActivePrevEpoch: true,
|
||||
IsPrevEpochAttester: true,
|
||||
@@ -188,7 +189,7 @@ func TestProcessEpochParticipation_InactiveValidator(t *testing.T) {
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}, validators[1])
|
||||
require.DeepEqual(t, &types.Validator{
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: true,
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
@@ -412,7 +413,7 @@ func TestProcessRewardsAndPenaltiesPrecompute_BadState(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
|
||||
require.NoError(t, err)
|
||||
_, err = ProcessRewardsAndPenaltiesPrecompute(s, balance, []*types.Validator{})
|
||||
_, err = ProcessRewardsAndPenaltiesPrecompute(s, balance, []*precompute.Validator{})
|
||||
require.ErrorContains(t, "validator registries not the same length as state's validator registries", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/slashings"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -79,11 +78,11 @@ func ProcessAttesterSlashing(
|
||||
cfg := params.BeaconConfig()
|
||||
var slashingQuotient uint64
|
||||
switch {
|
||||
case beaconState.Version() == version.Phase0:
|
||||
case beaconState.Version().IsPhase0Compatible():
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotient
|
||||
case beaconState.Version() == version.Altair:
|
||||
case beaconState.Version().IsAltairCompatible():
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
case beaconState.Version() == version.Bellatrix:
|
||||
case beaconState.Version().IsBellatrixCompatible():
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix
|
||||
default:
|
||||
return nil, errors.New("unknown state version")
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -33,7 +32,7 @@ func IsMergeTransitionComplete(st state.BeaconState) (bool, error) {
|
||||
if st == nil {
|
||||
return false, errors.New("nil state")
|
||||
}
|
||||
if IsPreBellatrixVersion(st.Version()) {
|
||||
if st.Version().IsPreBellatrix() {
|
||||
return false, nil
|
||||
}
|
||||
h, err := st.LatestExecutionPayloadHeader()
|
||||
@@ -86,7 +85,7 @@ func IsExecutionEnabled(st state.BeaconState, body interfaces.BeaconBlockBody) (
|
||||
if st == nil || body == nil {
|
||||
return false, errors.New("nil state or block body")
|
||||
}
|
||||
if IsPreBellatrixVersion(st.Version()) {
|
||||
if st.Version().IsPreBellatrix() {
|
||||
return false, nil
|
||||
}
|
||||
header, err := st.LatestExecutionPayloadHeader()
|
||||
@@ -105,11 +104,6 @@ func IsExecutionEnabledUsingHeader(header *ethpb.ExecutionPayloadHeader, body in
|
||||
return IsExecutionBlock(body)
|
||||
}
|
||||
|
||||
// IsPreBellatrixVersion returns true if input version is before bellatrix fork.
|
||||
func IsPreBellatrixVersion(v int) bool {
|
||||
return v < version.Bellatrix
|
||||
}
|
||||
|
||||
// ValidatePayloadWhenMergeCompletes validates if payload is valid versus input beacon state.
|
||||
// These validation steps ONLY apply to post merge.
|
||||
//
|
||||
@@ -276,7 +270,7 @@ func ProcessPayloadHeader(st state.BeaconState, header *ethpb.ExecutionPayloadHe
|
||||
// GetBlockPayloadHash returns the hash of the execution payload of the block
|
||||
func GetBlockPayloadHash(blk interfaces.BeaconBlock) ([32]byte, error) {
|
||||
payloadHash := [32]byte{}
|
||||
if IsPreBellatrixVersion(blk.Version()) {
|
||||
if blk.Version().IsPreBellatrix() {
|
||||
return payloadHash, nil
|
||||
}
|
||||
payload, err := blk.Body().ExecutionPayload()
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
@@ -77,11 +76,11 @@ func ProcessProposerSlashing(
|
||||
cfg := params.BeaconConfig()
|
||||
var slashingQuotient uint64
|
||||
switch {
|
||||
case beaconState.Version() == version.Phase0:
|
||||
case beaconState.Version().IsPhase0Compatible():
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotient
|
||||
case beaconState.Version() == version.Altair:
|
||||
case beaconState.Version().IsAltairCompatible():
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
case beaconState.Version() == version.Bellatrix:
|
||||
case beaconState.Version().IsBellatrixCompatible():
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix
|
||||
default:
|
||||
return nil, errors.New("unknown state version")
|
||||
|
||||
@@ -8,6 +8,7 @@ go_library(
|
||||
"new.go",
|
||||
"reward_penalty.go",
|
||||
"slashing.go",
|
||||
"type.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute",
|
||||
visibility = [
|
||||
|
||||
@@ -22,13 +22,13 @@ import (
|
||||
func ProcessAttestations(
|
||||
ctx context.Context,
|
||||
state state.ReadOnlyBeaconState,
|
||||
vp []*types.Validator,
|
||||
pBal *types.Balance,
|
||||
) ([]*types.Validator, *types.Balance, error) {
|
||||
vp []*Validator,
|
||||
pBal *Balance,
|
||||
) ([]*Validator, *Balance, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "precomputeEpoch.ProcessAttestations")
|
||||
defer span.End()
|
||||
|
||||
v := &types.Validator{}
|
||||
v := &Validator{}
|
||||
var err error
|
||||
|
||||
prevAtt, err := state.PreviousEpochAttestations()
|
||||
@@ -141,7 +141,7 @@ func SameHead(state state.ReadOnlyBeaconState, a *ethpb.PendingAttestation) (boo
|
||||
}
|
||||
|
||||
// UpdateValidator updates pre computed validator store.
|
||||
func UpdateValidator(vp []*types.Validator, record *types.Validator, indices []uint64, a *ethpb.PendingAttestation, aSlot types.Slot) []*types.Validator {
|
||||
func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *ethpb.PendingAttestation, aSlot types.Slot) []*Validator {
|
||||
inclusionSlot := aSlot + a.InclusionDelay
|
||||
|
||||
for _, i := range indices {
|
||||
@@ -171,7 +171,7 @@ func UpdateValidator(vp []*types.Validator, record *types.Validator, indices []u
|
||||
}
|
||||
|
||||
// UpdateBalance updates pre computed balance store.
|
||||
func UpdateBalance(vp []*types.Validator, bBal *types.Balance, stateVersion int) *types.Balance {
|
||||
func UpdateBalance(vp []*Validator, bBal *Balance, stateVersion version.ForkVersion) *Balance {
|
||||
for _, v := range vp {
|
||||
if !v.IsSlashed {
|
||||
if v.IsCurrentEpochAttester {
|
||||
@@ -180,10 +180,10 @@ func UpdateBalance(vp []*types.Validator, bBal *types.Balance, stateVersion int)
|
||||
if v.IsCurrentEpochTargetAttester {
|
||||
bBal.CurrentEpochTargetAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if stateVersion == version.Phase0 && v.IsPrevEpochAttester {
|
||||
if stateVersion.IsPhase0Compatible() && v.IsPrevEpochAttester {
|
||||
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if (stateVersion == version.Altair || stateVersion == version.Bellatrix) && v.IsPrevEpochSourceAttester {
|
||||
if stateVersion.IsHigherOrEqualToAltair() && v.IsPrevEpochSourceAttester {
|
||||
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if v.IsPrevEpochTargetAttester {
|
||||
@@ -200,7 +200,7 @@ func UpdateBalance(vp []*types.Validator, bBal *types.Balance, stateVersion int)
|
||||
|
||||
// EnsureBalancesLowerBound ensures all the balances such as active current epoch, active previous epoch and more
|
||||
// have EffectiveBalanceIncrement(1 eth) as a lower bound.
|
||||
func EnsureBalancesLowerBound(bBal *types.Balance) *types.Balance {
|
||||
func EnsureBalancesLowerBound(bBal *Balance) *Balance {
|
||||
ebi := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
if ebi > bBal.ActiveCurrentEpoch {
|
||||
bBal.ActiveCurrentEpoch = ebi
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
@@ -19,36 +18,36 @@ import (
|
||||
|
||||
func TestUpdateValidator_Works(t *testing.T) {
|
||||
e := params.BeaconConfig().FarFutureSlot
|
||||
vp := []*types.Validator{{}, {InclusionSlot: e}, {}, {InclusionSlot: e}, {}, {InclusionSlot: e}}
|
||||
record := &types.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true,
|
||||
vp := []*precompute.Validator{{}, {InclusionSlot: e}, {}, {InclusionSlot: e}, {}, {InclusionSlot: e}}
|
||||
record := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true,
|
||||
IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, IsPrevEpochHeadAttester: true}
|
||||
a := ðpb.PendingAttestation{InclusionDelay: 1, ProposerIndex: 2}
|
||||
|
||||
// Indices 1 3 and 5 attested
|
||||
vp = precompute.UpdateValidator(vp, record, []uint64{1, 3, 5}, a, 100)
|
||||
|
||||
wanted := &types.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true,
|
||||
wanted := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true,
|
||||
IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, IsPrevEpochHeadAttester: true,
|
||||
ProposerIndex: 2, InclusionDistance: 1, InclusionSlot: 101}
|
||||
wantedVp := []*types.Validator{{}, wanted, {}, wanted, {}, wanted}
|
||||
wantedVp := []*precompute.Validator{{}, wanted, {}, wanted, {}, wanted}
|
||||
assert.DeepEqual(t, wantedVp, vp, "Incorrect attesting validator calculations")
|
||||
}
|
||||
|
||||
func TestUpdateValidator_InclusionOnlyCountsPrevEpoch(t *testing.T) {
|
||||
e := params.BeaconConfig().FarFutureSlot
|
||||
vp := []*types.Validator{{InclusionSlot: e}}
|
||||
record := &types.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true}
|
||||
vp := []*precompute.Validator{{InclusionSlot: e}}
|
||||
record := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true}
|
||||
a := ðpb.PendingAttestation{InclusionDelay: 1, ProposerIndex: 2}
|
||||
|
||||
// Verify inclusion info doesnt get updated.
|
||||
vp = precompute.UpdateValidator(vp, record, []uint64{0}, a, 100)
|
||||
wanted := &types.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true, InclusionSlot: e}
|
||||
wantedVp := []*types.Validator{wanted}
|
||||
wanted := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true, InclusionSlot: e}
|
||||
wantedVp := []*precompute.Validator{wanted}
|
||||
assert.DeepEqual(t, wantedVp, vp, "Incorrect attesting validator calculations")
|
||||
}
|
||||
|
||||
func TestUpdateBalance(t *testing.T) {
|
||||
vp := []*types.Validator{
|
||||
vp := []*precompute.Validator{
|
||||
{IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsCurrentEpochTargetAttester: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsCurrentEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
@@ -58,7 +57,7 @@ func TestUpdateBalance(t *testing.T) {
|
||||
{IsPrevEpochAttester: true, IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsSlashed: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
}
|
||||
wantedPBal := &types.Balance{
|
||||
wantedPBal := &precompute.Balance{
|
||||
ActiveCurrentEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
ActivePrevEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
CurrentEpochAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
@@ -67,12 +66,12 @@ func TestUpdateBalance(t *testing.T) {
|
||||
PrevEpochTargetAttested: 100 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
PrevEpochHeadAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
}
|
||||
pBal := precompute.UpdateBalance(vp, &types.Balance{}, version.Phase0)
|
||||
pBal := precompute.UpdateBalance(vp, &precompute.Balance{}, version.Phase0)
|
||||
assert.DeepEqual(t, wantedPBal, pBal, "Incorrect balance calculations")
|
||||
}
|
||||
|
||||
func TestUpdateBalanceBellatrixVersion(t *testing.T) {
|
||||
vp := []*types.Validator{
|
||||
vp := []*precompute.Validator{
|
||||
{IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsCurrentEpochTargetAttester: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsCurrentEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
@@ -82,7 +81,7 @@ func TestUpdateBalanceBellatrixVersion(t *testing.T) {
|
||||
{IsPrevEpochAttester: true, IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsSlashed: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
}
|
||||
wantedPBal := &types.Balance{
|
||||
wantedPBal := &precompute.Balance{
|
||||
ActiveCurrentEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
ActivePrevEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
CurrentEpochAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
@@ -91,7 +90,7 @@ func TestUpdateBalanceBellatrixVersion(t *testing.T) {
|
||||
PrevEpochTargetAttested: 100 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
PrevEpochHeadAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
}
|
||||
pBal := precompute.UpdateBalance(vp, &types.Balance{}, version.Bellatrix)
|
||||
pBal := precompute.UpdateBalance(vp, &precompute.Balance{}, version.Bellatrix)
|
||||
assert.DeepEqual(t, wantedPBal, pBal, "Incorrect balance calculations")
|
||||
}
|
||||
|
||||
@@ -200,11 +199,11 @@ func TestProcessAttestations(t *testing.T) {
|
||||
err = beaconState.AppendCurrentEpochAttestations(ðpb.PendingAttestation{Data: att2.Data, AggregationBits: bf, InclusionDelay: 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
pVals := make([]*types.Validator, validators)
|
||||
pVals := make([]*precompute.Validator, validators)
|
||||
for i := 0; i < len(pVals); i++ {
|
||||
pVals[i] = &types.Validator{CurrentEpochEffectiveBalance: 100}
|
||||
pVals[i] = &precompute.Validator{CurrentEpochEffectiveBalance: 100}
|
||||
}
|
||||
pVals, _, err = precompute.ProcessAttestations(context.Background(), beaconState, pVals, &types.Balance{})
|
||||
pVals, _, err = precompute.ProcessAttestations(context.Background(), beaconState, pVals, &precompute.Balance{})
|
||||
require.NoError(t, err)
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(context.Background(), beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
||||
@@ -228,7 +227,7 @@ func TestProcessAttestations(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEnsureBalancesLowerBound(t *testing.T) {
|
||||
b := &types.Balance{}
|
||||
b := &precompute.Balance{}
|
||||
b = precompute.EnsureBalancesLowerBound(b)
|
||||
balanceIncrement := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
assert.Equal(t, balanceIncrement, b.ActiveCurrentEpoch, "Did not get wanted active current balance")
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
@@ -45,7 +44,7 @@ func UnrealizedCheckpoints(st state.BeaconState) (*ethpb.Checkpoint, *ethpb.Chec
|
||||
// previous_target_balance = get_attesting_balance(state, previous_attestations)
|
||||
// current_target_balance = get_attesting_balance(state, current_attestations)
|
||||
// weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance)
|
||||
func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal *types.Balance) (state.BeaconState, error) {
|
||||
func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal *Balance) (state.BeaconState, error) {
|
||||
canProcessSlot, err := slots.EpochStart(2 /*epoch*/)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestProcessJustificationAndFinalizationPreCompute_ConsecutiveEpochs(t *test
|
||||
state, err := v1.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &types.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
|
||||
require.NoError(t, err)
|
||||
rt := [32]byte{byte(64)}
|
||||
@@ -80,7 +80,7 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *te
|
||||
state, err := v1.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &types.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
|
||||
require.NoError(t, err)
|
||||
rt := [32]byte{byte(64)}
|
||||
@@ -116,7 +116,7 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testi
|
||||
state, err := v1.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &types.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
|
||||
require.NoError(t, err)
|
||||
rt := [32]byte{byte(64)}
|
||||
|
||||
@@ -11,19 +11,18 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// New gets called at the beginning of process epoch cycle to return
|
||||
// pre computed instances of validators attesting records and total
|
||||
// balances attested in an epoch.
|
||||
func New(ctx context.Context, s state.BeaconState) ([]*types.Validator, *types.Balance, error) {
|
||||
func New(ctx context.Context, s state.BeaconState) ([]*Validator, *Balance, error) {
|
||||
_, span := trace.StartSpan(ctx, "precomputeEpoch.New")
|
||||
defer span.End()
|
||||
|
||||
pValidators := make([]*types.Validator, s.NumValidators())
|
||||
pBal := &types.Balance{}
|
||||
pValidators := make([]*Validator, s.NumValidators())
|
||||
pBal := &Balance{}
|
||||
|
||||
currentEpoch := time.CurrentEpoch(s)
|
||||
prevEpoch := time.PrevEpoch(s)
|
||||
@@ -31,7 +30,7 @@ func New(ctx context.Context, s state.BeaconState) ([]*types.Validator, *types.B
|
||||
if err := s.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
|
||||
// Was validator withdrawable or slashed
|
||||
withdrawable := prevEpoch+1 >= val.WithdrawableEpoch()
|
||||
pVal := &types.Validator{
|
||||
pVal := &Validator{
|
||||
IsSlashed: val.Slashed(),
|
||||
IsWithdrawableCurrentEpoch: withdrawable,
|
||||
CurrentEpochEffectiveBalance: val.EffectiveBalance(),
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
@@ -32,33 +31,33 @@ func TestNew(t *testing.T) {
|
||||
e := params.BeaconConfig().FarFutureSlot
|
||||
v, b, err := precompute.New(context.Background(), s)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsSlashed: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InclusionDistance: e,
|
||||
InclusionSlot: e,
|
||||
}, v[0], "Incorrect validator 0 status")
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InclusionDistance: e,
|
||||
InclusionSlot: e,
|
||||
}, v[1], "Incorrect validator 1 status")
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: true,
|
||||
IsActivePrevEpoch: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InclusionDistance: e,
|
||||
InclusionSlot: e,
|
||||
}, v[2], "Incorrect validator 2 status")
|
||||
assert.DeepEqual(t, &types.Validator{
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
IsActivePrevEpoch: true,
|
||||
CurrentEpochEffectiveBalance: 100,
|
||||
InclusionDistance: e,
|
||||
InclusionSlot: e,
|
||||
}, v[3], "Incorrect validator 3 status")
|
||||
|
||||
wantedBalances := &types.Balance{
|
||||
wantedBalances := &precompute.Balance{
|
||||
ActiveCurrentEpoch: 100,
|
||||
ActivePrevEpoch: 200,
|
||||
}
|
||||
|
||||
@@ -10,15 +10,15 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/math"
|
||||
)
|
||||
|
||||
type attesterRewardsFunc func(state.ReadOnlyBeaconState, *types.Balance, []*types.Validator) ([]uint64, []uint64, error)
|
||||
type proposerRewardsFunc func(state.ReadOnlyBeaconState, *types.Balance, []*types.Validator) ([]uint64, error)
|
||||
type attesterRewardsFunc func(state.ReadOnlyBeaconState, *Balance, []*Validator) ([]uint64, []uint64, error)
|
||||
type proposerRewardsFunc func(state.ReadOnlyBeaconState, *Balance, []*Validator) ([]uint64, error)
|
||||
|
||||
// ProcessRewardsAndPenaltiesPrecompute processes the rewards and penalties of individual validator.
|
||||
// This is an optimized version by passing in precomputed validator attesting records and and total epoch balances.
|
||||
func ProcessRewardsAndPenaltiesPrecompute(
|
||||
state state.BeaconState,
|
||||
pBal *types.Balance,
|
||||
vp []*types.Validator,
|
||||
pBal *Balance,
|
||||
vp []*Validator,
|
||||
attRewardsFunc attesterRewardsFunc,
|
||||
proRewardsFunc proposerRewardsFunc,
|
||||
) (state.BeaconState, error) {
|
||||
@@ -65,7 +65,7 @@ func ProcessRewardsAndPenaltiesPrecompute(
|
||||
|
||||
// AttestationsDelta computes and returns the rewards and penalties differences for individual validators based on the
|
||||
// voting records.
|
||||
func AttestationsDelta(state state.ReadOnlyBeaconState, pBal *types.Balance, vp []*types.Validator) ([]uint64, []uint64, error) {
|
||||
func AttestationsDelta(state state.ReadOnlyBeaconState, pBal *Balance, vp []*Validator) ([]uint64, []uint64, error) {
|
||||
numOfVals := state.NumValidators()
|
||||
rewards := make([]uint64, numOfVals)
|
||||
penalties := make([]uint64, numOfVals)
|
||||
@@ -79,7 +79,7 @@ func AttestationsDelta(state state.ReadOnlyBeaconState, pBal *types.Balance, vp
|
||||
return rewards, penalties, nil
|
||||
}
|
||||
|
||||
func attestationDelta(pBal *types.Balance, sqrtActiveCurrentEpoch uint64, v *types.Validator, prevEpoch, finalizedEpoch types.Epoch) (uint64, uint64) {
|
||||
func attestationDelta(pBal *Balance, sqrtActiveCurrentEpoch uint64, v *Validator, prevEpoch, finalizedEpoch types.Epoch) (uint64, uint64) {
|
||||
if !EligibleForRewards(v) || pBal.ActiveCurrentEpoch == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
@@ -156,7 +156,7 @@ func attestationDelta(pBal *types.Balance, sqrtActiveCurrentEpoch uint64, v *typ
|
||||
|
||||
// ProposersDelta computes and returns the rewards and penalties differences for individual validators based on the
|
||||
// proposer inclusion records.
|
||||
func ProposersDelta(state state.ReadOnlyBeaconState, pBal *types.Balance, vp []*types.Validator) ([]uint64, error) {
|
||||
func ProposersDelta(state state.ReadOnlyBeaconState, pBal *Balance, vp []*Validator) ([]uint64, error) {
|
||||
numofVals := state.NumValidators()
|
||||
rewards := make([]uint64, numofVals)
|
||||
|
||||
@@ -190,6 +190,6 @@ func ProposersDelta(state state.ReadOnlyBeaconState, pBal *types.Balance, vp []*
|
||||
//
|
||||
// Spec code:
|
||||
// if is_active_validator(v, previous_epoch) or (v.slashed and previous_epoch + 1 < v.withdrawable_epoch)
|
||||
func EligibleForRewards(v *types.Validator) bool {
|
||||
func EligibleForRewards(v *Validator) bool {
|
||||
return v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
|
||||
}
|
||||
|
||||
@@ -307,8 +307,8 @@ func TestProposerDeltaPrecompute_HappyCase(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerIndex := types.ValidatorIndex(1)
|
||||
b := &types.Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*types.Validator{
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex},
|
||||
}
|
||||
r, err := ProposersDelta(beaconState, b, v)
|
||||
@@ -329,8 +329,8 @@ func TestProposerDeltaPrecompute_ValidatorIndexOutOfRange(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerIndex := types.ValidatorIndex(validatorCount)
|
||||
b := &types.Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*types.Validator{
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex},
|
||||
}
|
||||
_, err = ProposersDelta(beaconState, b, v)
|
||||
@@ -345,8 +345,8 @@ func TestProposerDeltaPrecompute_SlashedCase(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerIndex := types.ValidatorIndex(1)
|
||||
b := &types.Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*types.Validator{
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex, IsSlashed: true},
|
||||
}
|
||||
r, err := ProposersDelta(beaconState, b, v)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// ProcessSlashingsPrecompute processes the slashed validators during epoch processing.
|
||||
// This is an optimized version by passing in precomputed total epoch balances.
|
||||
func ProcessSlashingsPrecompute(s state.BeaconState, pBal *types.Balance) error {
|
||||
func ProcessSlashingsPrecompute(s state.BeaconState, pBal *Balance) error {
|
||||
currentEpoch := time.CurrentEpoch(s)
|
||||
exitLength := params.BeaconConfig().EpochsPerSlashingsVector
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
@@ -22,7 +21,7 @@ func TestProcessSlashingsPrecompute_NotSlashedWithSlashedTrue(t *testing.T) {
|
||||
Slashings: []uint64{0, 1e9},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pBal := &types.Balance{ActiveCurrentEpoch: params.BeaconConfig().MaxEffectiveBalance}
|
||||
pBal := &precompute.Balance{ActiveCurrentEpoch: params.BeaconConfig().MaxEffectiveBalance}
|
||||
require.NoError(t, precompute.ProcessSlashingsPrecompute(s, pBal))
|
||||
|
||||
wanted := params.BeaconConfig().MaxEffectiveBalance
|
||||
@@ -37,7 +36,7 @@ func TestProcessSlashingsPrecompute_NotSlashedWithSlashedFalse(t *testing.T) {
|
||||
Slashings: []uint64{0, 1e9},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pBal := &types.Balance{ActiveCurrentEpoch: params.BeaconConfig().MaxEffectiveBalance}
|
||||
pBal := &precompute.Balance{ActiveCurrentEpoch: params.BeaconConfig().MaxEffectiveBalance}
|
||||
require.NoError(t, precompute.ProcessSlashingsPrecompute(s, pBal))
|
||||
|
||||
wanted := params.BeaconConfig().MaxEffectiveBalance
|
||||
@@ -121,7 +120,7 @@ func TestProcessSlashingsPrecompute_SlashedLess(t *testing.T) {
|
||||
}
|
||||
ab += b
|
||||
}
|
||||
pBal := &types.Balance{ActiveCurrentEpoch: ab}
|
||||
pBal := &precompute.Balance{ActiveCurrentEpoch: ab}
|
||||
|
||||
original := proto.Clone(tt.state)
|
||||
state, err := v1.InitializeFromProto(tt.state)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
package types
|
||||
package precompute
|
||||
|
||||
import types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
|
||||
// Validator stores the pre computation of individual validator's attesting records these records
|
||||
// consist of attestation votes, block inclusion record. Pre computing and storing such record
|
||||
@@ -28,11 +30,11 @@ type Validator struct {
|
||||
// CurrentEpochEffectiveBalance is how much effective balance this validator has current epoch.
|
||||
CurrentEpochEffectiveBalance uint64
|
||||
// InclusionSlot is the slot of when the attestation gets included in the chain.
|
||||
InclusionSlot Slot
|
||||
InclusionSlot types.Slot
|
||||
// InclusionDistance is the distance between the assigned slot and this validator's attestation was included in block.
|
||||
InclusionDistance Slot
|
||||
InclusionDistance types.Slot
|
||||
// ProposerIndex is the index of proposer at slot where this validator's attestation was included.
|
||||
ProposerIndex ValidatorIndex
|
||||
ProposerIndex types.ValidatorIndex
|
||||
// BeforeEpochTransitionBalance is the validator balance prior to epoch transition.
|
||||
BeforeEpochTransitionBalance uint64
|
||||
// AfterEpochTransitionBalance is the validator balance after epoch transition.
|
||||
@@ -9,7 +9,6 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -48,7 +47,7 @@ func NextEpoch(state state.ReadOnlyBeaconState) types.Epoch {
|
||||
|
||||
// HigherEqualThanAltairVersionAndEpoch returns if the input state `s` has a higher version number than Altair state and input epoch `e` is higher equal than fork epoch.
|
||||
func HigherEqualThanAltairVersionAndEpoch(s state.BeaconState, e types.Epoch) bool {
|
||||
return s.Version() >= version.Altair && e >= params.BeaconConfig().AltairForkEpoch
|
||||
return s.Version().IsHigherOrEqualToAltair() && e >= params.BeaconConfig().AltairForkEpoch
|
||||
}
|
||||
|
||||
// CanUpgradeToAltair returns true if the input `slot` can upgrade to Altair.
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/math"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -248,14 +247,14 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
return nil, errors.Wrap(err, "could not process slot")
|
||||
}
|
||||
if time.CanProcessEpoch(state) {
|
||||
switch state.Version() {
|
||||
case version.Phase0:
|
||||
switch {
|
||||
case state.Version().IsPhase0Compatible():
|
||||
state, err = ProcessEpochPrecompute(ctx, state)
|
||||
if err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return nil, errors.Wrap(err, "could not process epoch with optimizations")
|
||||
}
|
||||
case version.Altair, version.Bellatrix:
|
||||
case state.Version().IsHigherOrEqualToAltair():
|
||||
state, err = altair.ProcessEpoch(ctx, state)
|
||||
if err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -232,13 +231,13 @@ func ProcessOperationsNoVerifyAttsSigs(
|
||||
}
|
||||
|
||||
var err error
|
||||
switch signedBeaconBlock.Version() {
|
||||
case version.Phase0:
|
||||
switch {
|
||||
case signedBeaconBlock.Version().IsPhase0Compatible():
|
||||
state, err = phase0Operations(ctx, state, signedBeaconBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case version.Altair, version.Bellatrix:
|
||||
case signedBeaconBlock.Version().IsHigherOrEqualToAltair():
|
||||
state, err = altairOperations(ctx, state, signedBeaconBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -329,7 +328,7 @@ func ProcessBlockForStateRoot(
|
||||
return nil, errors.Wrap(err, "could not process block operation")
|
||||
}
|
||||
|
||||
if signed.Block().Version() == version.Phase0 {
|
||||
if signed.Block().Version().IsPhase0Compatible() {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -23,14 +23,14 @@ type ReadOnlyDatabase interface {
|
||||
Block(ctx context.Context, blockRoot [32]byte) (interfaces.SignedBeaconBlock, error)
|
||||
Blocks(ctx context.Context, f *filters.QueryFilter) ([]interfaces.SignedBeaconBlock, [][32]byte, error)
|
||||
BlockRoots(ctx context.Context, f *filters.QueryFilter) ([][32]byte, error)
|
||||
BlocksBySlot(ctx context.Context, slot types.Slot) (bool, []interfaces.SignedBeaconBlock, error)
|
||||
BlocksBySlot(ctx context.Context, slot types.Slot) ([]interfaces.SignedBeaconBlock, error)
|
||||
BlockRootsBySlot(ctx context.Context, slot types.Slot) (bool, [][32]byte, error)
|
||||
HasBlock(ctx context.Context, blockRoot [32]byte) bool
|
||||
GenesisBlock(ctx context.Context) (interfaces.SignedBeaconBlock, error)
|
||||
GenesisBlockRoot(ctx context.Context) ([32]byte, error)
|
||||
IsFinalizedBlock(ctx context.Context, blockRoot [32]byte) bool
|
||||
FinalizedChildBlock(ctx context.Context, blockRoot [32]byte) (interfaces.SignedBeaconBlock, error)
|
||||
HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]interfaces.SignedBeaconBlock, error)
|
||||
HighestRootsBelowSlot(ctx context.Context, slot types.Slot) (types.Slot, [][32]byte, error)
|
||||
// State related methods.
|
||||
State(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
|
||||
StateOrError(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
|
||||
@@ -86,6 +86,7 @@ type NoHeadAccessDatabase interface {
|
||||
RunMigrations(ctx context.Context) error
|
||||
// Fee reicipients operations.
|
||||
SaveFeeRecipientsByValidatorIDs(ctx context.Context, ids []types.ValidatorIndex, addrs []common.Address) error
|
||||
SaveRegistrationsByValidatorIDs(ctx context.Context, ids []types.ValidatorIndex, regs []*ethpb.ValidatorRegistrationV1) error
|
||||
|
||||
CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint types.Slot) error
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/container/slice"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -185,17 +184,19 @@ func (s *Store) HasBlock(ctx context.Context, blockRoot [32]byte) bool {
|
||||
}
|
||||
|
||||
// BlocksBySlot retrieves a list of beacon blocks and its respective roots by slot.
|
||||
func (s *Store) BlocksBySlot(ctx context.Context, slot types.Slot) (bool, []interfaces.SignedBeaconBlock, error) {
|
||||
func (s *Store) BlocksBySlot(ctx context.Context, slot types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.BlocksBySlot")
|
||||
defer span.End()
|
||||
blocks := make([]interfaces.SignedBeaconBlock, 0)
|
||||
|
||||
blocks := make([]interfaces.SignedBeaconBlock, 0)
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(blocksBucket)
|
||||
|
||||
keys := blockRootsBySlot(ctx, tx, slot)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
encoded := bkt.Get(keys[i])
|
||||
roots, err := blockRootsBySlot(ctx, tx, slot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve blocks by slot")
|
||||
}
|
||||
for _, r := range roots {
|
||||
encoded := bkt.Get(r[:])
|
||||
blk, err := unmarshalBlock(ctx, encoded)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -204,7 +205,7 @@ func (s *Store) BlocksBySlot(ctx context.Context, slot types.Slot) (bool, []inte
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return len(blocks) > 0, blocks, err
|
||||
return blocks, err
|
||||
}
|
||||
|
||||
// BlockRootsBySlot retrieves a list of beacon block roots by slot
|
||||
@@ -213,11 +214,9 @@ func (s *Store) BlockRootsBySlot(ctx context.Context, slot types.Slot) (bool, []
|
||||
defer span.End()
|
||||
blockRoots := make([][32]byte, 0)
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
keys := blockRootsBySlot(ctx, tx, slot)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
blockRoots = append(blockRoots, bytesutil.ToBytes32(keys[i]))
|
||||
}
|
||||
return nil
|
||||
var err error
|
||||
blockRoots, err = blockRootsBySlot(ctx, tx, slot)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return false, nil, errors.Wrap(err, "could not retrieve block roots by slot")
|
||||
@@ -398,14 +397,17 @@ func (s *Store) SaveBackfillBlockRoot(ctx context.Context, blockRoot [32]byte) e
|
||||
})
|
||||
}
|
||||
|
||||
// HighestSlotBlocksBelow returns the block with the highest slot below the input slot from the db.
|
||||
func (s *Store) HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.HighestSlotBlocksBelow")
|
||||
// HighestRootsBelowSlot returns roots from the database slot index from the highest slot below the input slot.
|
||||
// The slot value at the beginning of the return list is the slot where the roots were found. This is helpful so that
|
||||
// calling code can make decisions based on the slot without resolving the blocks to discover their slot (for instance
|
||||
// checking which root is canonical in fork choice, which operates purely on roots,
|
||||
// then if no canonical block is found, continuing to search through lower slots).
|
||||
func (s *Store) HighestRootsBelowSlot(ctx context.Context, slot types.Slot) (fs types.Slot, roots [][32]byte, err error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.HighestRootsBelowSlot")
|
||||
defer span.End()
|
||||
|
||||
var root [32]byte
|
||||
sk := bytesutil.Uint64ToBytesBigEndian(uint64(slot))
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
err = s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(blockSlotIndicesBucket)
|
||||
c := bkt.Cursor()
|
||||
// The documentation for Seek says:
|
||||
@@ -430,34 +432,28 @@ func (s *Store) HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]
|
||||
if r == nil {
|
||||
continue
|
||||
}
|
||||
bs := bytesutil.BytesToSlotBigEndian(sl)
|
||||
fs = bytesutil.BytesToSlotBigEndian(sl)
|
||||
// Iterating through the index using .Prev will move from higher to lower, so the first key we find behind
|
||||
// the requested slot must be the highest block below that slot.
|
||||
if slot > bs {
|
||||
root = bytesutil.ToBytes32(r)
|
||||
break
|
||||
if slot > fs {
|
||||
roots, err = splitRoots(r)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error parsing packed roots %#x", r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return 0, nil, err
|
||||
}
|
||||
if len(roots) == 0 || (len(roots) == 1 && roots[0] == params.BeaconConfig().ZeroHash) {
|
||||
gr, err := s.GenesisBlockRoot(ctx)
|
||||
return 0, [][32]byte{gr}, err
|
||||
}
|
||||
|
||||
var blk interfaces.SignedBeaconBlock
|
||||
if root != params.BeaconConfig().ZeroHash {
|
||||
blk, err = s.Block(ctx, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if blk == nil || blk.IsNil() {
|
||||
blk, err = s.GenesisBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return []interfaces.SignedBeaconBlock{blk}, nil
|
||||
return fs, roots, nil
|
||||
}
|
||||
|
||||
// FeeRecipientByValidatorID returns the fee recipient for a validator id.
|
||||
@@ -681,21 +677,22 @@ func blockRootsBySlotRange(
|
||||
}
|
||||
|
||||
// blockRootsBySlot retrieves the block roots by slot
|
||||
func blockRootsBySlot(ctx context.Context, tx *bolt.Tx, slot types.Slot) [][]byte {
|
||||
func blockRootsBySlot(ctx context.Context, tx *bolt.Tx, slot types.Slot) ([][32]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "BeaconDB.blockRootsBySlot")
|
||||
defer span.End()
|
||||
|
||||
roots := make([][]byte, 0)
|
||||
bkt := tx.Bucket(blockSlotIndicesBucket)
|
||||
key := bytesutil.SlotToBytesBigEndian(slot)
|
||||
c := bkt.Cursor()
|
||||
k, v := c.Seek(key)
|
||||
if k != nil && bytes.Equal(k, key) {
|
||||
for i := 0; i < len(v); i += 32 {
|
||||
roots = append(roots, v[i:i+32])
|
||||
r, err := splitRoots(v)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "corrupt value in block slot index for slot=%d", slot)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
return roots
|
||||
return [][32]byte{}, nil
|
||||
}
|
||||
|
||||
// createBlockIndicesFromBlock takes in a beacon block and returns
|
||||
@@ -796,14 +793,14 @@ func marshalBlock(_ context.Context, blk interfaces.SignedBeaconBlock) ([]byte,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch blk.Version() {
|
||||
case version.BellatrixBlind:
|
||||
switch {
|
||||
case blk.Version().IsBlindedBlockCompatible():
|
||||
return snappy.Encode(nil, append(bellatrixBlindKey, obj...)), nil
|
||||
case version.Bellatrix:
|
||||
case blk.Version().IsBellatrixCompatible():
|
||||
return snappy.Encode(nil, append(bellatrixKey, obj...)), nil
|
||||
case version.Altair:
|
||||
case blk.Version().IsAltairCompatible():
|
||||
return snappy.Encode(nil, append(altairKey, obj...)), nil
|
||||
case version.Phase0:
|
||||
case blk.Version().IsPhase0Compatible():
|
||||
return snappy.Encode(nil, obj), nil
|
||||
default:
|
||||
return nil, errors.New("Unknown block version")
|
||||
|
||||
@@ -517,18 +517,32 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
||||
require.NoError(t, db.SaveBlock(ctx, block2))
|
||||
require.NoError(t, db.SaveBlock(ctx, block3))
|
||||
|
||||
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
|
||||
_, roots, err := db.HighestRootsBelowSlot(ctx, 2)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
|
||||
assert.Equal(t, true, proto.Equal(block1.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
|
||||
highestAt, err = db.HighestSlotBlocksBelow(ctx, 11)
|
||||
assert.Equal(t, false, len(roots) <= 0, "Got empty highest at slice")
|
||||
require.Equal(t, 1, len(roots))
|
||||
root := roots[0]
|
||||
b, err := db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
|
||||
assert.Equal(t, true, proto.Equal(block2.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
|
||||
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
|
||||
assert.Equal(t, true, proto.Equal(block1.Proto(), b.Proto()), "Wanted: %v, received: %v", block1, b)
|
||||
|
||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 11)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
|
||||
assert.Equal(t, true, proto.Equal(block3.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block3, highestAt[0])
|
||||
assert.Equal(t, false, len(roots) <= 0, "Got empty highest at slice")
|
||||
require.Equal(t, 1, len(roots))
|
||||
root = roots[0]
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(block2.Proto(), b.Proto()), "Wanted: %v, received: %v", block2, b)
|
||||
|
||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 101)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, len(roots) <= 0, "Got empty highest at slice")
|
||||
require.Equal(t, 1, len(roots))
|
||||
root = roots[0]
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(block3.Proto(), b.Proto()), "Wanted: %v, received: %v", block3, b)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -549,15 +563,29 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(ctx, block1))
|
||||
|
||||
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
|
||||
_, roots, err := db.HighestRootsBelowSlot(ctx, 2)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(block1.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
|
||||
highestAt, err = db.HighestSlotBlocksBelow(ctx, 1)
|
||||
require.Equal(t, 1, len(roots))
|
||||
root := roots[0]
|
||||
b, err := db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
|
||||
highestAt, err = db.HighestSlotBlocksBelow(ctx, 0)
|
||||
assert.Equal(t, true, proto.Equal(block1.Proto(), b.Proto()), "Wanted: %v, received: %v", block1, b)
|
||||
|
||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
|
||||
require.Equal(t, 1, len(roots))
|
||||
root = roots[0]
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), b.Proto()), "Wanted: %v, received: %v", genesisBlock, b)
|
||||
|
||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(roots))
|
||||
root = roots[0]
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), b.Proto()), "Wanted: %v, received: %v", genesisBlock, b)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -638,22 +666,21 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) {
|
||||
r3, err := b3.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
hasBlocks, retrievedBlocks, err := db.BlocksBySlot(ctx, 1)
|
||||
retrievedBlocks, err := db.BlocksBySlot(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none")
|
||||
assert.Equal(t, false, hasBlocks, "Expected no blocks")
|
||||
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 20)
|
||||
retrievedBlocks, err = db.BlocksBySlot(ctx, 20)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(b1.Proto(), retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b1, retrievedBlocks[0])
|
||||
assert.Equal(t, true, hasBlocks, "Expected to have blocks")
|
||||
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 100)
|
||||
assert.Equal(t, true, len(retrievedBlocks) > 0, "Expected to have blocks")
|
||||
retrievedBlocks, err = db.BlocksBySlot(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
if len(retrievedBlocks) != 2 {
|
||||
t.Fatalf("Expected 2 blocks, received %d blocks", len(retrievedBlocks))
|
||||
}
|
||||
assert.Equal(t, true, proto.Equal(b2.Proto(), retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b2, retrievedBlocks[0])
|
||||
assert.Equal(t, true, proto.Equal(b3.Proto(), retrievedBlocks[1].Proto()), "Wanted: %v, received: %v", b3, retrievedBlocks[1])
|
||||
assert.Equal(t, true, hasBlocks, "Expected to have blocks")
|
||||
assert.Equal(t, true, len(retrievedBlocks) > 0, "Expected to have blocks")
|
||||
|
||||
hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -99,3 +101,16 @@ func deleteValueForIndices(ctx context.Context, indicesByBucket map[string][]byt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errMisalignedRootList = errors.New("incorrectly packed root list, length is not a multiple of 32")
|
||||
|
||||
func splitRoots(b []byte) ([][32]byte, error) {
|
||||
rl := make([][32]byte, 0)
|
||||
if len(b)%32 != 0 {
|
||||
return nil, errors.Wrapf(errMisalignedRootList, "root list len=%d", len(b))
|
||||
}
|
||||
for s, f := 0, 32; f <= len(b); s, f = f, f+32 {
|
||||
rl = append(rl, bytesutil.ToBytes32(b[s:f]))
|
||||
}
|
||||
return rl, nil
|
||||
}
|
||||
|
||||
@@ -138,3 +138,60 @@ func Test_deleteValueForIndices(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testPack(bs [][32]byte) []byte {
|
||||
r := make([]byte, 0)
|
||||
for _, b := range bs {
|
||||
r = append(r, b[:]...)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func TestSplitRoots(t *testing.T) {
|
||||
bt := make([][32]byte, 0)
|
||||
for _, x := range []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} {
|
||||
var b [32]byte
|
||||
for i := 0; i < 32; i++ {
|
||||
b[i] = x
|
||||
}
|
||||
bt = append(bt, b)
|
||||
}
|
||||
cases := []struct {
|
||||
name string
|
||||
b []byte
|
||||
expect [][32]byte
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "misaligned",
|
||||
b: make([]byte, 61),
|
||||
err: errMisalignedRootList,
|
||||
},
|
||||
{
|
||||
name: "happy",
|
||||
b: testPack(bt[0:5]),
|
||||
expect: bt[0:5],
|
||||
},
|
||||
{
|
||||
name: "single",
|
||||
b: testPack([][32]byte{bt[0]}),
|
||||
expect: [][32]byte{bt[0]},
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
b: []byte{},
|
||||
expect: [][32]byte{},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
r, err := splitRoots(c.b)
|
||||
if c.err != nil {
|
||||
require.ErrorIs(t, err, c.err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, c.expect, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz/detect"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// SaveOrigin loads an ssz serialized Block & BeaconState from an io.Reader
|
||||
@@ -38,7 +37,7 @@ func (s *Store) SaveOrigin(ctx context.Context, serState, serBlock []byte) error
|
||||
return fmt.Errorf("config mismatch, beacon node configured to connect to %s, detected state is for %s", params.BeaconConfig().ConfigName, cf.Config.ConfigName)
|
||||
}
|
||||
|
||||
log.Infof("detected supported config for state & block version, config name=%s, fork name=%s", cf.Config.ConfigName, version.String(cf.Fork))
|
||||
log.Infof("detected supported config for state & block version, config name=%s, fork name=%s", cf.Config.ConfigName, cf.Fork.String())
|
||||
state, err := cf.UnmarshalBeaconState(serState)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize origin state w/ bytes + config+fork")
|
||||
|
||||
@@ -435,6 +435,8 @@ func (f *ForkChoice) CommonAncestorRoot(ctx context.Context, r1 [32]byte, r2 [32
|
||||
if n1.slot > n2.slot {
|
||||
n1 = n1.parent
|
||||
// Reaches the end of the tree and unable to find common ancestor.
|
||||
// This should not happen at runtime as the finalized
|
||||
// node has to be a common ancestor
|
||||
if n1 == nil {
|
||||
return [32]byte{}, forkchoice.ErrUnknownCommonAncestor
|
||||
}
|
||||
|
||||
@@ -535,9 +535,17 @@ func TestStore_CommonAncestor(t *testing.T) {
|
||||
require.ErrorIs(t, err, ErrNilNode)
|
||||
_, err = f.CommonAncestorRoot(ctx, [32]byte{'z'}, [32]byte{'a'})
|
||||
require.ErrorIs(t, err, ErrNilNode)
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 100, [32]byte{'y'}, [32]byte{'z'}, [32]byte{}, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
n := &Node{
|
||||
slot: 100,
|
||||
root: [32]byte{'y'},
|
||||
justifiedEpoch: 1,
|
||||
unrealizedJustifiedEpoch: 1,
|
||||
finalizedEpoch: 1,
|
||||
unrealizedFinalizedEpoch: 1,
|
||||
optimistic: true,
|
||||
}
|
||||
|
||||
f.store.nodeByRoot[[32]byte{'y'}] = n
|
||||
// broken link
|
||||
_, err = f.CommonAncestorRoot(ctx, [32]byte{'y'}, [32]byte{'a'})
|
||||
require.ErrorIs(t, err, forkchoice.ErrUnknownCommonAncestor)
|
||||
|
||||
@@ -125,19 +125,20 @@ func (s *Store) insert(ctx context.Context,
|
||||
|
||||
s.nodeByPayload[payloadHash] = n
|
||||
s.nodeByRoot[root] = n
|
||||
if parent != nil {
|
||||
if parent == nil {
|
||||
if s.treeRootNode == nil {
|
||||
s.treeRootNode = n
|
||||
s.headNode = n
|
||||
} else {
|
||||
return errInvalidParentRoot
|
||||
}
|
||||
} else {
|
||||
parent.children = append(parent.children, n)
|
||||
if err := s.treeRootNode.updateBestDescendant(ctx, s.justifiedEpoch, s.finalizedEpoch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Set the node as root if the store was empty
|
||||
if s.treeRootNode == nil {
|
||||
s.treeRootNode = n
|
||||
s.headNode = n
|
||||
}
|
||||
|
||||
// Update metrics.
|
||||
processedBlockCount.Inc()
|
||||
nodeCount.Set(float64(len(s.nodeByRoot)))
|
||||
|
||||
@@ -10,21 +10,21 @@ var (
|
||||
prometheus.HistogramOpts{
|
||||
Name: "new_payload_v1_latency_milliseconds",
|
||||
Help: "Captures RPC latency for newPayloadV1 in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000},
|
||||
},
|
||||
)
|
||||
getPayloadLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "get_payload_v1_latency_milliseconds",
|
||||
Help: "Captures RPC latency for getPayloadV1 in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000},
|
||||
},
|
||||
)
|
||||
forkchoiceUpdatedLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "forkchoice_updated_v1_latency_milliseconds",
|
||||
Help: "Captures RPC latency for forkchoiceUpdatedV1 in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000},
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -70,10 +70,14 @@ func (bs *Server) GetWeakSubjectivity(ctx context.Context, _ *empty.Empty) (*eth
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not get weak subjectivity slot: %v", err)
|
||||
}
|
||||
cbr, cb, err := bs.CanonicalHistory.BlockForSlot(ctx, wsSlot)
|
||||
cbr, err := bs.CanonicalHistory.BlockRootForSlot(ctx, wsSlot)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, fmt.Sprintf("could not find highest block below slot %d", wsSlot))
|
||||
}
|
||||
cb, err := bs.BeaconDB.Block(ctx, cbr)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, fmt.Sprintf("block with root %#x from slot index %d not found in db", cbr, wsSlot))
|
||||
}
|
||||
stateRoot := bytesutil.ToBytes32(cb.Block().StateRoot())
|
||||
log.Printf("weak subjectivity checkpoint reported as epoch=%d, block root=%#x, state root=%#x", wsEpoch, cbr, stateRoot)
|
||||
return ðpbv1.WeakSubjectivityResponse{
|
||||
@@ -150,7 +154,7 @@ func (bs *Server) ListBlockHeaders(ctx context.Context, req *ethpbv1.BlockHeader
|
||||
if req.Slot != nil {
|
||||
slot = *req.Slot
|
||||
}
|
||||
_, blks, err = bs.BeaconDB.BlocksBySlot(ctx, slot)
|
||||
blks, err = bs.BeaconDB.BlocksBySlot(ctx, slot)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve blocks for slot %d: %v", req.Slot, err)
|
||||
}
|
||||
@@ -754,7 +758,7 @@ func (bs *Server) blockFromBlockID(ctx context.Context, blockId []byte) (interfa
|
||||
e := newBlockIdParseError(err)
|
||||
return nil, &e
|
||||
}
|
||||
_, blks, err := bs.BeaconDB.BlocksBySlot(ctx, types.Slot(slot))
|
||||
blks, err := bs.BeaconDB.BlocksBySlot(ctx, types.Slot(slot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not retrieve blocks for slot %d", slot)
|
||||
}
|
||||
|
||||
@@ -1527,8 +1527,8 @@ func TestServer_GetBlockSSZ(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
ok, blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, ok)
|
||||
blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blocks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blocks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
@@ -1567,8 +1567,8 @@ func TestServer_GetBlockSSZV2(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
ok, blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, ok)
|
||||
blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blocks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blocks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
@@ -1606,8 +1606,8 @@ func TestServer_GetBlockSSZV2(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
ok, blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, ok)
|
||||
blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blocks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blocks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
@@ -1645,8 +1645,8 @@ func TestServer_GetBlockSSZV2(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
ok, blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, ok)
|
||||
blocks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blocks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blocks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/proto/migration"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -24,7 +23,7 @@ func (ds *Server) GetBeaconState(ctx context.Context, req *ethpbv1.StateRequest)
|
||||
return nil, helpers.PrepareStateFetchGRPCError(err)
|
||||
}
|
||||
|
||||
if beaconSt.Version() != version.Phase0 {
|
||||
if beaconSt.Version().IsHigherOrEqualToAltair() {
|
||||
return nil, status.Error(codes.Internal, "State has incorrect type")
|
||||
}
|
||||
protoSt, err := migration.BeaconStateToProto(beaconSt)
|
||||
@@ -69,8 +68,8 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
switch beaconSt.Version() {
|
||||
case version.Phase0:
|
||||
switch {
|
||||
case beaconSt.Version().IsAltairCompatible():
|
||||
protoSt, err := migration.BeaconStateToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
@@ -82,7 +81,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
case version.Altair:
|
||||
case beaconSt.Version().IsAltairCompatible():
|
||||
protoState, err := migration.BeaconStateAltairToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
@@ -94,7 +93,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
case version.Bellatrix:
|
||||
case beaconSt.Version().IsBellatrixCompatible():
|
||||
protoState, err := migration.BeaconStateBellatrixToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
@@ -126,12 +125,12 @@ func (ds *Server) GetBeaconStateSSZV2(ctx context.Context, req *ethpbv2.StateReq
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal state into SSZ: %v", err)
|
||||
}
|
||||
var ver ethpbv2.Version
|
||||
switch st.Version() {
|
||||
case version.Phase0:
|
||||
switch {
|
||||
case st.Version().IsPhase0Compatible():
|
||||
ver = ethpbv2.Version_PHASE0
|
||||
case version.Altair:
|
||||
case st.Version().IsAltairCompatible():
|
||||
ver = ethpbv2.Version_ALTAIR
|
||||
case version.Bellatrix:
|
||||
case st.Version().IsBellatrixCompatible():
|
||||
ver = ethpbv2.Version_BELLATRIX
|
||||
default:
|
||||
return nil, status.Error(codes.Internal, "Unsupported state version")
|
||||
|
||||
@@ -209,11 +209,11 @@ func (bs *Server) listBlocksForRoot(ctx context.Context, _ *ethpb.ListBlocksRequ
|
||||
|
||||
// listBlocksForSlot retrieves all blocks for the provided slot.
|
||||
func (bs *Server) listBlocksForSlot(ctx context.Context, req *ethpb.ListBlocksRequest, q *ethpb.ListBlocksRequest_Slot) ([]blockContainer, int, string, error) {
|
||||
hasBlocks, blks, err := bs.BeaconDB.BlocksBySlot(ctx, q.Slot)
|
||||
blks, err := bs.BeaconDB.BlocksBySlot(ctx, q.Slot)
|
||||
if err != nil {
|
||||
return nil, 0, strconv.Itoa(0), status.Errorf(codes.Internal, "Could not retrieve blocks for slot %d: %v", q.Slot, err)
|
||||
}
|
||||
if !hasBlocks {
|
||||
if len(blks) == 0 {
|
||||
return []blockContainer{}, 0, strconv.Itoa(0), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -516,8 +516,8 @@ func (bs *Server) GetValidatorParticipation(
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", endSlot, err))
|
||||
}
|
||||
var v []*types.Validator
|
||||
var b *types.Balance
|
||||
var v []*precompute.Validator
|
||||
var b *precompute.Balance
|
||||
switch beaconState.Version() {
|
||||
case version.Phase0:
|
||||
v, b, err = precompute.New(ctx, beaconState)
|
||||
@@ -680,7 +680,7 @@ func (bs *Server) GetValidatorPerformance(
|
||||
return nil, status.Errorf(codes.Internal, "Could not process slots up to %d: %v", currSlot, err)
|
||||
}
|
||||
}
|
||||
var validatorSummary []*types.Validator
|
||||
var validatorSummary []*precompute.Validator
|
||||
switch headState.Version() {
|
||||
case version.Phase0:
|
||||
vp, bp, err := precompute.New(ctx, headState)
|
||||
@@ -862,8 +862,8 @@ func (bs *Server) GetIndividualVotes(
|
||||
return filteredIndices[i] < filteredIndices[j]
|
||||
})
|
||||
|
||||
var v []*types.Validator
|
||||
var bal *types.Balance
|
||||
var v []*precompute.Validator
|
||||
var bal *precompute.Balance
|
||||
switch st.Version() {
|
||||
case version.Phase0:
|
||||
v, bal, err = precompute.New(ctx, st)
|
||||
|
||||
@@ -127,10 +127,10 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
case errors.As(err, kv.ErrNotFoundFeeRecipient):
|
||||
// If fee recipient is not found in DB and not set from beacon node CLI,
|
||||
// use the burn address.
|
||||
if feeRecipient.String() == fieldparams.EthBurnAddressHex {
|
||||
if feeRecipient.String() == params.BeaconConfig().EthBurnAddressHex {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"validatorIndex": vIdx,
|
||||
"burnAddress": fieldparams.EthBurnAddressHex,
|
||||
"burnAddress": params.BeaconConfig().EthBurnAddressHex,
|
||||
}).Warn("Fee recipient is currently using the burn address, " +
|
||||
"you will not be rewarded transaction fees on this setting. " +
|
||||
"Please set a different eth address as the fee recipient. " +
|
||||
|
||||
@@ -292,11 +292,11 @@ func (p *StateProvider) stateRootBySlot(ctx context.Context, slot types.Slot) ([
|
||||
if slot > currentSlot {
|
||||
return nil, errors.New("slot cannot be in the future")
|
||||
}
|
||||
found, blks, err := p.BeaconDB.BlocksBySlot(ctx, slot)
|
||||
blks, err := p.BeaconDB.BlocksBySlot(ctx, slot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get blocks")
|
||||
}
|
||||
if !found {
|
||||
if len(blks) == 0 {
|
||||
return nil, errors.New("no block exists")
|
||||
}
|
||||
if len(blks) != 1 {
|
||||
|
||||
@@ -13,6 +13,7 @@ go_library(
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["inactivity_scores.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/core",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//math:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -1,57 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/math"
|
||||
)
|
||||
|
||||
func ProcessInactivityScores(ctx context.Context,
|
||||
inactivityScores []uint64,
|
||||
currentEpoch, previousEpoch, finalizedEpoch types.Epoch,
|
||||
vals []*types.Validator,
|
||||
) ([]uint64, []*types.Validator, error) {
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
if currentEpoch == cfg.GenesisEpoch {
|
||||
return inactivityScores, vals, nil
|
||||
}
|
||||
|
||||
bias := cfg.InactivityScoreBias
|
||||
recoveryRate := cfg.InactivityScoreRecoveryRate
|
||||
|
||||
var err error
|
||||
for i, v := range vals {
|
||||
if !precompute.EligibleForRewards(v) {
|
||||
continue
|
||||
}
|
||||
|
||||
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
|
||||
// Decrease inactivity score when validator gets target correct.
|
||||
if v.InactivityScore > 0 {
|
||||
v.InactivityScore -= 1
|
||||
}
|
||||
} else {
|
||||
v.InactivityScore, err = math.Add64(v.InactivityScore, bias)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !helpers.IsInInactivityLeak(previousEpoch, finalizedEpoch) {
|
||||
score := recoveryRate
|
||||
// Prevents underflow below 0.
|
||||
if score > v.InactivityScore {
|
||||
score = v.InactivityScore
|
||||
}
|
||||
v.InactivityScore -= score
|
||||
}
|
||||
inactivityScores[i] = v.InactivityScore
|
||||
}
|
||||
|
||||
return inactivityScores, vals, nil
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// BeaconState has read and write access to beacon state methods.
|
||||
@@ -59,7 +60,7 @@ type ReadOnlyBeaconState interface {
|
||||
FieldReferencesCount() map[string]uint64
|
||||
MarshalSSZ() ([]byte, error)
|
||||
IsNil() bool
|
||||
Version() int
|
||||
Version() version.ForkVersion
|
||||
LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error)
|
||||
}
|
||||
|
||||
@@ -73,7 +74,6 @@ type WriteOnlyBeaconState interface {
|
||||
WriteOnlyBalances
|
||||
WriteOnlyCheckpoint
|
||||
WriteOnlyAttestations
|
||||
CoreProcessors
|
||||
SetGenesisTime(val uint64) error
|
||||
SetGenesisValidatorsRoot(val []byte) error
|
||||
SetSlot(val types.Slot) error
|
||||
@@ -236,9 +236,3 @@ type FutureForkStub interface {
|
||||
NextSyncCommittee() (*ethpb.SyncCommittee, error)
|
||||
SetNextSyncCommittee(val *ethpb.SyncCommittee) error
|
||||
}
|
||||
|
||||
type CoreProcessors interface {
|
||||
ProcessInactivityScores(ctx context.Context,
|
||||
currentEpoch, previousEpoch, finalizedEpoch types.Epoch,
|
||||
vals []*types.Validator) ([]*types.Validator, error)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/core:go_default_library",
|
||||
"//beacon-chain/state/fieldtrie:go_default_library",
|
||||
"//beacon-chain/state/state-native/custom-types:go_default_library",
|
||||
"//beacon-chain/state/state-native/types:go_default_library",
|
||||
|
||||
@@ -13,12 +13,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// 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
|
||||
version version.ForkVersion
|
||||
genesisTime uint64 `ssz-gen:"true"`
|
||||
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
|
||||
slot eth2types.Slot `ssz-gen:"true"`
|
||||
|
||||
@@ -13,12 +13,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// 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
|
||||
version version.ForkVersion
|
||||
genesisTime uint64 `ssz-gen:"true"`
|
||||
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
|
||||
slot eth2types.Slot `ssz-gen:"true"`
|
||||
|
||||
@@ -2,12 +2,11 @@ package state_native
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// PreviousEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) {
|
||||
if b.version != version.Phase0 {
|
||||
if !b.version.IsPhase0Compatible() {
|
||||
return nil, errNotSupported("PreviousEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
@@ -29,7 +28,7 @@ func (b *BeaconState) previousEpochAttestationsVal() []*ethpb.PendingAttestation
|
||||
|
||||
// CurrentEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) {
|
||||
if b.version != version.Phase0 {
|
||||
if !b.version.IsPhase0Compatible() {
|
||||
return nil, errNotSupported("CurrentEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package state_native
|
||||
import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// GenesisTime of the beacon state as a uint64.
|
||||
@@ -24,7 +25,7 @@ func (b *BeaconState) GenesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (b *BeaconState) Version() int {
|
||||
func (b *BeaconState) Version() version.ForkVersion {
|
||||
return b.version
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,11 @@ package state_native
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// CurrentEpochParticipation corresponding to participation bits on the beacon chain.
|
||||
func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) {
|
||||
if b.version == version.Phase0 {
|
||||
if !b.version.IsParticipationBitsCompatible() {
|
||||
return nil, errNotSupported("CurrentEpochParticipation", b.version)
|
||||
}
|
||||
|
||||
@@ -24,7 +23,7 @@ func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) {
|
||||
|
||||
// PreviousEpochParticipation corresponding to participation bits on the beacon chain.
|
||||
func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) {
|
||||
if b.version == version.Phase0 {
|
||||
if !b.version.IsParticipationBitsCompatible() {
|
||||
return nil, errNotSupported("PreviousEpochParticipation", b.version)
|
||||
}
|
||||
|
||||
@@ -42,7 +41,7 @@ func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) {
|
||||
// current epoch and target attested in previous epoch. This function is used to
|
||||
// compute the "unrealized justification" that a synced Beacon Block will have.
|
||||
func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) {
|
||||
if b.version == version.Phase0 {
|
||||
if !b.version.IsParticipationBitsCompatible() {
|
||||
return 0, 0, 0, errNotSupported("UnrealizedCheckpointBalances", b.version)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,11 @@ package state_native
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// LatestExecutionPayloadHeader of the beacon state.
|
||||
func (b *BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) {
|
||||
if b.version == version.Phase0 || b.version == version.Altair {
|
||||
if !b.version.IsExecutionPayloadCompatible() {
|
||||
return nil, errNotSupported("LatestExecutionPayloadHeader", b.version)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
|
||||
gvrCopy := b.genesisValidatorsRoot
|
||||
|
||||
switch b.version {
|
||||
case version.Phase0:
|
||||
switch {
|
||||
case b.version.IsPhase0Compatible():
|
||||
return ðpb.BeaconState{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
@@ -42,7 +42,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint,
|
||||
}
|
||||
case version.Altair:
|
||||
case b.version.IsAltairCompatible():
|
||||
return ðpb.BeaconStateAltair{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
@@ -69,7 +69,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
CurrentSyncCommittee: b.currentSyncCommittee,
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
}
|
||||
case version.Bellatrix:
|
||||
case b.version.IsBellatrixCompatible():
|
||||
return ðpb.BeaconStateBellatrix{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/core"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
@@ -243,26 +240,3 @@ func (b *BeaconState) SetInactivityScores(val []uint64) error {
|
||||
b.markFieldAsDirty(nativetypes.InactivityScores)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) ProcessInactivityScores(ctx context.Context,
|
||||
currentEpoch, previousEpoch, finalizedEpoch types.Epoch, vals []*types.Validator) ([]*types.Validator, error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("ProcessInactivityScores", b.version)
|
||||
}
|
||||
scores := b.inactivityScores
|
||||
if b.sharedFieldReferences[nativetypes.InactivityScores].Refs() > 1 {
|
||||
scores = b.inactivityScoresVal()
|
||||
b.sharedFieldReferences[nativetypes.InactivityScores].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.InactivityScores] = stateutil.NewRef(1)
|
||||
}
|
||||
var err error
|
||||
scores, vals, err = core.ProcessInactivityScores(ctx, scores, currentEpoch, previousEpoch, finalizedEpoch, vals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.inactivityScores = scores
|
||||
b.markFieldAsDirty(nativetypes.InactivityScores)
|
||||
return vals, err
|
||||
}
|
||||
|
||||
@@ -199,6 +199,8 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
|
||||
b.sharedFieldReferences[nativetypes.CurrentEpochAttestations] = stateutil.NewRef(1)
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -287,6 +289,8 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
|
||||
b.sharedFieldReferences[nativetypes.InactivityScores] = stateutil.NewRef(1) // New in Altair.
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -377,6 +381,8 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
|
||||
b.sharedFieldReferences[nativetypes.LatestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Bellatrix.
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -495,31 +501,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(dst, func(b *BeaconState) {
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
|
||||
}
|
||||
for i := range b.dirtyFields {
|
||||
delete(b.dirtyFields, i)
|
||||
}
|
||||
for i := range b.rebuildTrie {
|
||||
delete(b.rebuildTrie, i)
|
||||
}
|
||||
for i := range b.dirtyIndices {
|
||||
delete(b.dirtyIndices, i)
|
||||
}
|
||||
for i := range b.sharedFieldReferences {
|
||||
delete(b.sharedFieldReferences, i)
|
||||
}
|
||||
for i := range b.stateFieldLeaves {
|
||||
delete(b.stateFieldLeaves, i)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
})
|
||||
runtime.SetFinalizer(dst, finalizerCleanup)
|
||||
return dst
|
||||
}
|
||||
|
||||
@@ -792,3 +774,29 @@ func (b *BeaconState) resetFieldTrie(index nativetypes.FieldIndex, elements inte
|
||||
b.dirtyIndices[index] = []uint64{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func finalizerCleanup(b *BeaconState) {
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
|
||||
}
|
||||
for i := range b.dirtyFields {
|
||||
delete(b.dirtyFields, i)
|
||||
}
|
||||
for i := range b.rebuildTrie {
|
||||
delete(b.rebuildTrie, i)
|
||||
}
|
||||
for i := range b.dirtyIndices {
|
||||
delete(b.dirtyIndices, i)
|
||||
}
|
||||
for i := range b.sharedFieldReferences {
|
||||
delete(b.sharedFieldReferences, i)
|
||||
}
|
||||
for i := range b.stateFieldLeaves {
|
||||
delete(b.stateFieldLeaves, i)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,6 @@ func init() {
|
||||
// to its corresponding data type.
|
||||
var fieldMap map[nativetypes.FieldIndex]types.DataType
|
||||
|
||||
func errNotSupported(funcName string, ver int) error {
|
||||
return fmt.Errorf("%s is not supported for %s", funcName, version.String(ver))
|
||||
func errNotSupported(funcName string, ver version.ForkVersion) error {
|
||||
return fmt.Errorf("%s is not supported for %s", funcName, ver.String())
|
||||
}
|
||||
|
||||
@@ -5,5 +5,8 @@ go_library(
|
||||
srcs = ["types.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@com_github_pkg_errors//:go_default_library"],
|
||||
deps = [
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ package types
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// FieldIndex represents the relevant field position in the
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
type FieldIndex int
|
||||
|
||||
// String returns the name of the field index.
|
||||
func (f FieldIndex) String(_ int) string {
|
||||
func (f FieldIndex) String(_ version.ForkVersion) string {
|
||||
switch f {
|
||||
case GenesisTime:
|
||||
return "genesisTime"
|
||||
|
||||
@@ -33,7 +33,6 @@ go_library(
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//crypto/rand:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//monitoring/tracing:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
|
||||
@@ -157,10 +157,9 @@ func (s *State) loadStateByRoot(ctx context.Context, blockRoot [32]byte) (state.
|
||||
ctx, span := trace.StartSpan(ctx, "stateGen.loadStateByRoot")
|
||||
defer span.End()
|
||||
|
||||
val := ctx.Value("migrate")
|
||||
// First, it checks if the state exists in hot state cache.
|
||||
cachedState := s.hotStateCache.get(blockRoot)
|
||||
if cachedState != nil && !cachedState.IsNil() && val == nil {
|
||||
if cachedState != nil && !cachedState.IsNil() {
|
||||
return cachedState, nil
|
||||
}
|
||||
|
||||
@@ -169,7 +168,7 @@ func (s *State) loadStateByRoot(ctx context.Context, blockRoot [32]byte) (state.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok && val == nil {
|
||||
if ok {
|
||||
return cachedInfo.state, nil
|
||||
}
|
||||
|
||||
@@ -223,7 +222,6 @@ func (s *State) LastAncestorState(ctx context.Context, blockRoot [32]byte) (stat
|
||||
if s.isFinalizedRoot(blockRoot) && s.finalizedState() != nil {
|
||||
return s.finalizedState(), nil
|
||||
}
|
||||
val := ctx.Value("migrate")
|
||||
|
||||
b, err := s.beaconDB.Block(ctx, blockRoot)
|
||||
if err != nil {
|
||||
@@ -250,7 +248,7 @@ func (s *State) LastAncestorState(ctx context.Context, blockRoot [32]byte) (stat
|
||||
return nil, errors.Wrapf(ErrNoDataForSlot, "slot %d not in db due to checkpoint sync", ps)
|
||||
}
|
||||
// Does the state exist in the hot state cache.
|
||||
if s.hotStateCache.has(parentRoot) && val == nil {
|
||||
if s.hotStateCache.has(parentRoot) {
|
||||
return s.hotStateCache.get(parentRoot), nil
|
||||
}
|
||||
|
||||
@@ -264,7 +262,7 @@ func (s *State) LastAncestorState(ctx context.Context, blockRoot [32]byte) (stat
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok && val == nil {
|
||||
if ok {
|
||||
return cachedInfo.state, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -46,73 +46,58 @@ func (c *CanonicalHistory) ReplayerForSlot(target types.Slot) Replayer {
|
||||
return &stateReplayer{chainer: c, method: forSlot, target: target}
|
||||
}
|
||||
|
||||
func (c *CanonicalHistory) BlockForSlot(ctx context.Context, target types.Slot) ([32]byte, interfaces.SignedBeaconBlock, error) {
|
||||
currentSlot := c.cs.CurrentSlot()
|
||||
if target > currentSlot {
|
||||
return [32]byte{}, nil, errors.Wrap(ErrFutureSlotRequested, fmt.Sprintf("requested=%d, current=%d", target, currentSlot))
|
||||
func (c *CanonicalHistory) BlockRootForSlot(ctx context.Context, target types.Slot) ([32]byte, error) {
|
||||
if currentSlot := c.cs.CurrentSlot(); target > currentSlot {
|
||||
return [32]byte{}, errors.Wrap(ErrFutureSlotRequested, fmt.Sprintf("requested=%d, current=%d", target, currentSlot))
|
||||
}
|
||||
for target > 0 {
|
||||
|
||||
slotAbove := target + 1
|
||||
// don't bother searching for candidate roots when we know the target slot is genesis
|
||||
for slotAbove > 1 {
|
||||
if ctx.Err() != nil {
|
||||
return [32]byte{}, nil, errors.Wrap(ctx.Err(), "context canceled during canonicalBlockForSlot")
|
||||
return [32]byte{}, errors.Wrap(ctx.Err(), "context canceled during canonicalBlockForSlot")
|
||||
}
|
||||
hbs, err := c.h.HighestSlotBlocksBelow(ctx, target+1)
|
||||
slot, roots, err := c.h.HighestRootsBelowSlot(ctx, slotAbove)
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, errors.Wrap(err, fmt.Sprintf("error finding highest block w/ slot <= %d", target))
|
||||
return [32]byte{}, errors.Wrap(err, fmt.Sprintf("error finding highest block w/ slot < %d", slotAbove))
|
||||
}
|
||||
if len(hbs) == 0 {
|
||||
return [32]byte{}, nil, errors.Wrap(ErrNoBlocksBelowSlot, fmt.Sprintf("slot=%d", target))
|
||||
if len(roots) == 0 {
|
||||
return [32]byte{}, errors.Wrap(ErrNoBlocksBelowSlot, fmt.Sprintf("slot=%d", slotAbove))
|
||||
}
|
||||
r, b, err := c.bestForSlot(ctx, hbs)
|
||||
r, err := c.bestForSlot(ctx, roots)
|
||||
if err == nil {
|
||||
// we found a valid, canonical block!
|
||||
return r, b, nil
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// we found a block, but it wasn't considered canonical - keep looking
|
||||
if errors.Is(err, ErrNoCanonicalBlockForSlot) {
|
||||
// break once we've seen slot 0 (and prevent underflow)
|
||||
if hbs[0].Block().Slot() == params.BeaconConfig().GenesisSlot {
|
||||
if slot == params.BeaconConfig().GenesisSlot {
|
||||
break
|
||||
}
|
||||
target = hbs[0].Block().Slot() - 1
|
||||
slotAbove = slot
|
||||
continue
|
||||
}
|
||||
return [32]byte{}, nil, err
|
||||
return [32]byte{}, err
|
||||
}
|
||||
b, err := c.h.GenesisBlock(ctx)
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, errors.Wrap(err, "db error while retrieving genesis block")
|
||||
}
|
||||
root, _, err := c.bestForSlot(ctx, []interfaces.SignedBeaconBlock{b})
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, errors.Wrap(err, "problem retrieving genesis block")
|
||||
}
|
||||
return root, b, nil
|
||||
|
||||
return c.h.GenesisBlockRoot(ctx)
|
||||
}
|
||||
|
||||
// bestForSlot encapsulates several messy realities of the underlying db code, looping through multiple blocks,
|
||||
// performing null/validity checks, and using CanonicalChecker to only pick canonical blocks.
|
||||
func (c *CanonicalHistory) bestForSlot(ctx context.Context, hbs []interfaces.SignedBeaconBlock) ([32]byte, interfaces.SignedBeaconBlock, error) {
|
||||
for _, b := range hbs {
|
||||
if wrapper.BeaconBlockIsNil(b) != nil {
|
||||
continue
|
||||
}
|
||||
root, err := b.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
// use this error message to wrap a sentinel error for error type matching
|
||||
wrapped := errors.Wrap(ErrInvalidDBBlock, err.Error())
|
||||
msg := fmt.Sprintf("could not compute hash_tree_root for block at slot=%d", b.Block().Slot())
|
||||
return [32]byte{}, nil, errors.Wrap(wrapped, msg)
|
||||
}
|
||||
func (c *CanonicalHistory) bestForSlot(ctx context.Context, roots [][32]byte) ([32]byte, error) {
|
||||
for _, root := range roots {
|
||||
canon, err := c.cc.IsCanonical(ctx, root)
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, errors.Wrap(err, "replayer could not check if block is canonical")
|
||||
return [32]byte{}, errors.Wrap(err, "replayer could not check if block is canonical")
|
||||
}
|
||||
if canon {
|
||||
return root, b, nil
|
||||
return root, nil
|
||||
}
|
||||
}
|
||||
return [32]byte{}, nil, errors.Wrap(ErrNoCanonicalBlockForSlot, "no good block for slot")
|
||||
return [32]byte{}, errors.Wrap(ErrNoCanonicalBlockForSlot, "no good block for slot")
|
||||
}
|
||||
|
||||
// ChainForSlot creates a value that satisfies the Replayer interface via db queries
|
||||
@@ -122,9 +107,13 @@ func (c *CanonicalHistory) bestForSlot(ctx context.Context, hbs []interfaces.Sig
|
||||
func (c *CanonicalHistory) chainForSlot(ctx context.Context, target types.Slot) (state.BeaconState, []interfaces.SignedBeaconBlock, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "canonicalChainer.chainForSlot")
|
||||
defer span.End()
|
||||
_, b, err := c.BlockForSlot(ctx, target)
|
||||
r, err := c.BlockRootForSlot(ctx, target)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, fmt.Sprintf("unable to find replay data for slot=%d", target))
|
||||
return nil, nil, errors.Wrapf(err, "no canonical block root found below slot=%d", target)
|
||||
}
|
||||
b, err := c.h.Block(ctx, r)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "unable to retrieve canonical block for slot, root=%#x", r)
|
||||
}
|
||||
s, descendants, err := c.ancestorChain(ctx, b)
|
||||
if err != nil {
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
@@ -21,7 +19,7 @@ func TestBlockForSlotFuture(t *testing.T) {
|
||||
ch := &CanonicalHistory{
|
||||
cs: &mockCurrentSlotter{Slot: 0},
|
||||
}
|
||||
_, _, err := ch.BlockForSlot(context.Background(), 1)
|
||||
_, err := ch.BlockRootForSlot(context.Background(), 1)
|
||||
require.ErrorIs(t, err, ErrFutureSlotRequested)
|
||||
}
|
||||
|
||||
@@ -34,84 +32,54 @@ func TestChainForSlotFuture(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBestForSlot(t *testing.T) {
|
||||
nilBlock, err := wrapper.WrappedSignedBeaconBlock(ðpb.SignedBeaconBlock{})
|
||||
require.NoError(t, err)
|
||||
nilBody, err := wrapper.WrappedSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{}})
|
||||
require.NoError(t, err)
|
||||
derp := errors.New("fake hash tree root method no hash good")
|
||||
badHTR := &mock.SignedBeaconBlock{BeaconBlock: &mock.BeaconBlock{HtrErr: derp, BeaconBlockBody: &mock.BeaconBlockBody{}}}
|
||||
var goodHTR [32]byte
|
||||
copy(goodHTR[:], []byte{23})
|
||||
var betterHTR [32]byte
|
||||
copy(betterHTR[:], []byte{42})
|
||||
good := &mock.SignedBeaconBlock{BeaconBlock: &mock.BeaconBlock{BeaconBlockBody: &mock.BeaconBlockBody{}, Htr: goodHTR}}
|
||||
better := &mock.SignedBeaconBlock{BeaconBlock: &mock.BeaconBlock{BeaconBlockBody: &mock.BeaconBlockBody{}, Htr: betterHTR}}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
err error
|
||||
blocks []interfaces.SignedBeaconBlock
|
||||
best interfaces.SignedBeaconBlock
|
||||
roots [][32]byte
|
||||
root [32]byte
|
||||
cc CanonicalChecker
|
||||
}{
|
||||
{
|
||||
name: "empty list",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
blocks: []interfaces.SignedBeaconBlock{},
|
||||
name: "empty list",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
roots: [][32]byte{},
|
||||
},
|
||||
{
|
||||
name: "empty SignedBeaconBlock",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
blocks: []interfaces.SignedBeaconBlock{nil},
|
||||
name: "IsCanonical fail",
|
||||
roots: [][32]byte{goodHTR, betterHTR},
|
||||
cc: &mockCanonicalChecker{is: true, err: derp},
|
||||
err: derp,
|
||||
},
|
||||
{
|
||||
name: "empty BeaconBlock",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
blocks: []interfaces.SignedBeaconBlock{nilBlock},
|
||||
name: "all non-canonical",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
roots: [][32]byte{goodHTR, betterHTR},
|
||||
cc: &mockCanonicalChecker{is: false},
|
||||
},
|
||||
{
|
||||
name: "empty BeaconBlockBody",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
blocks: []interfaces.SignedBeaconBlock{nilBody},
|
||||
name: "one canonical",
|
||||
cc: &mockCanonicalChecker{is: true},
|
||||
root: goodHTR,
|
||||
roots: [][32]byte{goodHTR},
|
||||
},
|
||||
{
|
||||
name: "bad HTR",
|
||||
err: ErrInvalidDBBlock,
|
||||
blocks: []interfaces.SignedBeaconBlock{badHTR},
|
||||
name: "all canonical",
|
||||
cc: &mockCanonicalChecker{is: true},
|
||||
root: betterHTR,
|
||||
roots: [][32]byte{betterHTR, goodHTR},
|
||||
},
|
||||
{
|
||||
name: "IsCanonical fail",
|
||||
blocks: []interfaces.SignedBeaconBlock{good, better},
|
||||
cc: &mockCanonicalChecker{is: true, err: derp},
|
||||
err: derp,
|
||||
},
|
||||
{
|
||||
name: "all non-canonical",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
blocks: []interfaces.SignedBeaconBlock{good, better},
|
||||
cc: &mockCanonicalChecker{is: false},
|
||||
},
|
||||
{
|
||||
name: "one canonical",
|
||||
blocks: []interfaces.SignedBeaconBlock{good},
|
||||
cc: &mockCanonicalChecker{is: true},
|
||||
root: goodHTR,
|
||||
best: good,
|
||||
},
|
||||
{
|
||||
name: "all canonical",
|
||||
blocks: []interfaces.SignedBeaconBlock{better, good},
|
||||
cc: &mockCanonicalChecker{is: true},
|
||||
root: betterHTR,
|
||||
best: better,
|
||||
},
|
||||
{
|
||||
name: "first wins",
|
||||
blocks: []interfaces.SignedBeaconBlock{good, better},
|
||||
cc: &mockCanonicalChecker{is: true},
|
||||
root: goodHTR,
|
||||
best: good,
|
||||
name: "first wins",
|
||||
cc: &mockCanonicalChecker{is: true},
|
||||
root: goodHTR,
|
||||
roots: [][32]byte{goodHTR, betterHTR},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
@@ -121,10 +89,9 @@ func TestBestForSlot(t *testing.T) {
|
||||
chk = c.cc
|
||||
}
|
||||
ch := &CanonicalHistory{cc: chk}
|
||||
r, b, err := ch.bestForSlot(context.Background(), c.blocks)
|
||||
r, err := ch.bestForSlot(context.Background(), c.roots)
|
||||
if c.err == nil {
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, c.best, b)
|
||||
require.Equal(t, c.root, r)
|
||||
} else {
|
||||
require.ErrorIs(t, err, c.err)
|
||||
@@ -164,13 +131,11 @@ func TestCanonicalBlockForSlotHappy(t *testing.T) {
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
bs, err := hist.HighestSlotBlocksBelow(ctx, c.slot+1)
|
||||
_, rs, err := hist.HighestRootsBelowSlot(ctx, c.slot+1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(bs), 1)
|
||||
r, err := bs[0].Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hist.slotMap[c.highest], r)
|
||||
cr, _, err := ch.BlockForSlot(ctx, c.slot)
|
||||
require.Equal(t, len(rs), 1)
|
||||
require.Equal(t, hist.slotMap[c.highest], rs[0])
|
||||
cr, err := ch.BlockRootForSlot(ctx, c.slot)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hist.slotMap[c.canon], cr)
|
||||
})
|
||||
@@ -187,47 +152,49 @@ func TestCanonicalBlockForSlotNonHappy(t *testing.T) {
|
||||
}
|
||||
hist := newMockHistory(t, specs, end+1)
|
||||
|
||||
genesis, err := hist.GenesisBlockRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
slotOrderObserved := make([]types.Slot, 0)
|
||||
derp := errors.New("HighestSlotBlocksBelow don't work")
|
||||
derp := errors.New("HighestRootsBelowSlot don't work")
|
||||
// since only the end block and genesis are canonical, once the slot drops below
|
||||
// end, we should always get genesis
|
||||
cases := []struct {
|
||||
name string
|
||||
slot types.Slot
|
||||
canon CanonicalChecker
|
||||
overrideHighest func(context.Context, types.Slot) ([]interfaces.SignedBeaconBlock, error)
|
||||
overrideHighest func(context.Context, types.Slot) (types.Slot, [][32]byte, error)
|
||||
slotOrderExpected []types.Slot
|
||||
err error
|
||||
root [32]byte
|
||||
}{
|
||||
{
|
||||
name: "HighestSlotBlocksBelow not called for genesis",
|
||||
overrideHighest: func(_ context.Context, _ types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
return nil, derp
|
||||
name: "HighestRootsBelowSlot not called for genesis",
|
||||
overrideHighest: func(_ context.Context, _ types.Slot) (types.Slot, [][32]byte, error) {
|
||||
return 0, [][32]byte{}, derp
|
||||
},
|
||||
root: hist.slotMap[0],
|
||||
},
|
||||
{
|
||||
name: "wrapped error from HighestSlotBlocksBelow returned",
|
||||
name: "wrapped error from HighestRootsBelowSlot returned",
|
||||
err: derp,
|
||||
overrideHighest: func(_ context.Context, _ types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
return nil, derp
|
||||
overrideHighest: func(_ context.Context, _ types.Slot) (types.Slot, [][32]byte, error) {
|
||||
return 0, [][32]byte{}, derp
|
||||
},
|
||||
slot: end,
|
||||
},
|
||||
{
|
||||
name: "HighestSlotBlocksBelow empty list",
|
||||
name: "HighestRootsBelowSlot empty list",
|
||||
err: ErrNoBlocksBelowSlot,
|
||||
overrideHighest: func(_ context.Context, _ types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
return []interfaces.SignedBeaconBlock{}, nil
|
||||
overrideHighest: func(_ context.Context, _ types.Slot) (types.Slot, [][32]byte, error) {
|
||||
return 0, [][32]byte{}, nil
|
||||
},
|
||||
slot: end,
|
||||
},
|
||||
{
|
||||
name: "HighestSlotBlocksBelow no canonical",
|
||||
err: ErrNoCanonicalBlockForSlot,
|
||||
name: "HighestRootsBelowSlot no canonical",
|
||||
canon: &mockCanonicalChecker{is: false},
|
||||
slot: end,
|
||||
root: genesis,
|
||||
},
|
||||
{
|
||||
name: "slot ordering correct - only genesis canonical",
|
||||
@@ -237,11 +204,11 @@ func TestCanonicalBlockForSlotNonHappy(t *testing.T) {
|
||||
}
|
||||
return false, nil
|
||||
}},
|
||||
overrideHighest: func(_ context.Context, s types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
overrideHighest: func(_ context.Context, s types.Slot) (types.Slot, [][32]byte, error) {
|
||||
slotOrderObserved = append(slotOrderObserved, s)
|
||||
// this allows the mock HighestSlotBlocksBelow to continue to execute now that we've recorded
|
||||
// this allows the mock HighestRootsBelowSlot to continue to execute now that we've recorded
|
||||
// the slot in our channel
|
||||
return nil, errFallThroughOverride
|
||||
return 0, nil, errFallThroughOverride
|
||||
},
|
||||
slotOrderExpected: []types.Slot{156, 155, 150, 100},
|
||||
slot: end,
|
||||
@@ -255,11 +222,11 @@ func TestCanonicalBlockForSlotNonHappy(t *testing.T) {
|
||||
}
|
||||
return false, nil
|
||||
}},
|
||||
overrideHighest: func(_ context.Context, s types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
overrideHighest: func(_ context.Context, s types.Slot) (types.Slot, [][32]byte, error) {
|
||||
slotOrderObserved = append(slotOrderObserved, s)
|
||||
// this allows the mock HighestSlotBlocksBelow to continue to execute now that we've recorded
|
||||
// this allows the mock HighestRootsBelowSlot to continue to execute now that we've recorded
|
||||
// the slot in our channel
|
||||
return nil, errFallThroughOverride
|
||||
return 0, nil, errFallThroughOverride
|
||||
},
|
||||
slotOrderExpected: []types.Slot{156, 155, 150},
|
||||
slot: end,
|
||||
@@ -274,14 +241,14 @@ func TestCanonicalBlockForSlotNonHappy(t *testing.T) {
|
||||
}
|
||||
ch := &CanonicalHistory{h: hist, cc: canon, cs: hist}
|
||||
hist.overrideHighestSlotBlocksBelow = c.overrideHighest
|
||||
r, _, err := ch.BlockForSlot(ctx, c.slot)
|
||||
r, err := ch.BlockRootForSlot(ctx, c.slot)
|
||||
if c.err == nil {
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
require.ErrorIs(t, err, c.err)
|
||||
}
|
||||
if len(c.slotOrderExpected) > 0 {
|
||||
require.Equal(t, len(c.slotOrderExpected), len(slotOrderObserved), "HighestSlotBlocksBelow not called the expected number of times")
|
||||
require.Equal(t, len(c.slotOrderExpected), len(slotOrderObserved), "HighestRootsBelowSlot not called the expected number of times")
|
||||
for i := range c.slotOrderExpected {
|
||||
require.Equal(t, c.slotOrderExpected[i], slotOrderObserved[i])
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package stategen
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
@@ -38,10 +39,11 @@ func (s *State) MigrateToCold(ctx context.Context, fRoot [32]byte) error {
|
||||
}
|
||||
|
||||
if slot%s.slotsPerArchivedPoint == 0 && slot != 0 {
|
||||
cached, exists := &rootStateInfo{}, false
|
||||
if s.slotsPerArchivedPoint == 10000 {
|
||||
exists = true
|
||||
cached, exists, err := s.epochBoundaryStateCache.getBySlot(slot)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get epoch boundary state for slot %d", slot)
|
||||
}
|
||||
|
||||
var aRoot [32]byte
|
||||
var aState state.BeaconState
|
||||
|
||||
@@ -53,25 +55,20 @@ func (s *State) MigrateToCold(ctx context.Context, fRoot [32]byte) error {
|
||||
aRoot = cached.root
|
||||
aState = cached.state
|
||||
} else {
|
||||
blks, err := s.beaconDB.HighestSlotBlocksBelow(ctx, slot)
|
||||
_, roots, err := s.beaconDB.HighestRootsBelowSlot(ctx, slot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Given the block has been finalized, the db should not have more than one block in a given slot.
|
||||
// We should error out when this happens.
|
||||
if len(blks) != 1 {
|
||||
if len(roots) != 1 {
|
||||
return errUnknownBlock
|
||||
}
|
||||
missingRoot, err := blks[0].Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
aRoot = missingRoot
|
||||
aRoot = roots[0]
|
||||
// There's no need to generate the state if the state already exists in the DB.
|
||||
// We can skip saving the state.
|
||||
if !s.beaconDB.HasState(ctx, aRoot) {
|
||||
ctx = context.WithValue(ctx, "migrate", "yes")
|
||||
aState, err = s.StateByRoot(ctx, missingRoot)
|
||||
aState, err = s.StateByRoot(ctx, aRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ type mockHistory struct {
|
||||
states map[[32]byte]state.BeaconState
|
||||
hiddenStates map[[32]byte]state.BeaconState
|
||||
current types.Slot
|
||||
overrideHighestSlotBlocksBelow func(context.Context, types.Slot) ([]interfaces.SignedBeaconBlock, error)
|
||||
overrideHighestSlotBlocksBelow func(context.Context, types.Slot) (types.Slot, [][32]byte, error)
|
||||
}
|
||||
|
||||
type slotList []types.Slot
|
||||
@@ -98,13 +98,13 @@ func (m slotList) Swap(i, j int) {
|
||||
m[i], m[j] = m[j], m[i]
|
||||
}
|
||||
|
||||
var errFallThroughOverride = errors.New("override yielding control back to real HighestSlotBlocksBelow")
|
||||
var errFallThroughOverride = errors.New("override yielding control back to real HighestRootsBelowSlot")
|
||||
|
||||
func (m *mockHistory) HighestSlotBlocksBelow(_ context.Context, slot types.Slot) ([]interfaces.SignedBeaconBlock, error) {
|
||||
func (m *mockHistory) HighestRootsBelowSlot(_ context.Context, slot types.Slot) (types.Slot, [][32]byte, error) {
|
||||
if m.overrideHighestSlotBlocksBelow != nil {
|
||||
s, err := m.overrideHighestSlotBlocksBelow(context.Background(), slot)
|
||||
s, r, err := m.overrideHighestSlotBlocksBelow(context.Background(), slot)
|
||||
if !errors.Is(err, errFallThroughOverride) {
|
||||
return s, err
|
||||
return s, r, err
|
||||
}
|
||||
}
|
||||
if len(m.slotIndex) == 0 && len(m.slotMap) > 0 {
|
||||
@@ -115,20 +115,20 @@ func (m *mockHistory) HighestSlotBlocksBelow(_ context.Context, slot types.Slot)
|
||||
}
|
||||
for _, s := range m.slotIndex {
|
||||
if s < slot {
|
||||
return []interfaces.SignedBeaconBlock{m.blocks[m.slotMap[s]]}, nil
|
||||
return s, [][32]byte{m.slotMap[s]}, nil
|
||||
}
|
||||
}
|
||||
return []interfaces.SignedBeaconBlock{}, nil
|
||||
return 0, [][32]byte{}, nil
|
||||
}
|
||||
|
||||
var errGenesisBlockNotFound = errors.New("canonical genesis block not found in db")
|
||||
|
||||
func (m *mockHistory) GenesisBlock(_ context.Context) (interfaces.SignedBeaconBlock, error) {
|
||||
func (m *mockHistory) GenesisBlockRoot(_ context.Context) ([32]byte, error) {
|
||||
genesisRoot, ok := m.slotMap[0]
|
||||
if !ok {
|
||||
return nil, errGenesisBlockNotFound
|
||||
return [32]byte{}, errGenesisBlockNotFound
|
||||
}
|
||||
return m.blocks[genesisRoot], nil
|
||||
return genesisRoot, nil
|
||||
}
|
||||
|
||||
func (m *mockHistory) Block(_ context.Context, blockRoot [32]byte) (interfaces.SignedBeaconBlock, error) {
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/crypto/rand"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
@@ -42,11 +41,6 @@ func (_ *State) ReplayBlocks(
|
||||
"endSlot": targetSlot,
|
||||
"diff": targetSlot - state.Slot(),
|
||||
}).Debug("Replaying state")
|
||||
val := ctx.Value("migrate")
|
||||
if val != nil {
|
||||
log.Debug("Migrating state and replaying blocks")
|
||||
}
|
||||
gen := rand.NewDeterministicGenerator()
|
||||
// The input block list is sorted in decreasing slots order.
|
||||
if len(signed) > 0 {
|
||||
for i := len(signed) - 1; i >= 0; i-- {
|
||||
@@ -60,10 +54,6 @@ func (_ *State) ReplayBlocks(
|
||||
if state.Slot() >= signed[i].Block().Slot() {
|
||||
continue
|
||||
}
|
||||
if val != nil {
|
||||
nm := gen.Int63n(5500)
|
||||
time.Sleep(time.Duration(nm) * time.Millisecond)
|
||||
}
|
||||
state, err = executeStateTransitionStateGen(ctx, state, signed[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -153,6 +143,9 @@ func executeStateTransitionStateGen(
|
||||
state state.BeaconState,
|
||||
signed interfaces.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
if err := wrapper.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -218,7 +211,7 @@ func ReplayProcessSlots(ctx context.Context, state state.BeaconState, slot types
|
||||
return nil, errors.Wrap(err, "could not process epoch")
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported beacon state version: %s", version.String(state.Version()))
|
||||
return nil, fmt.Errorf("unsupported beacon state version: %s", state.Version().String())
|
||||
}
|
||||
}
|
||||
if err := state.SetSlot(state.Slot() + 1); err != nil {
|
||||
|
||||
@@ -27,8 +27,8 @@ const (
|
||||
|
||||
// HistoryAccessor describes the minimum set of database methods needed to support the ReplayerBuilder.
|
||||
type HistoryAccessor interface {
|
||||
HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]interfaces.SignedBeaconBlock, error)
|
||||
GenesisBlock(ctx context.Context) (interfaces.SignedBeaconBlock, error)
|
||||
HighestRootsBelowSlot(ctx context.Context, slot types.Slot) (types.Slot, [][32]byte, error)
|
||||
GenesisBlockRoot(ctx context.Context) ([32]byte, error)
|
||||
Block(ctx context.Context, blockRoot [32]byte) (interfaces.SignedBeaconBlock, error)
|
||||
StateOrError(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/transition/stateutils:go_default_library",
|
||||
"//beacon-chain/state/types:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
|
||||
@@ -4,12 +4,10 @@ import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||
pmath "github.com/prysmaticlabs/prysm/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -86,26 +84,34 @@ func Uint64ListRootWithRegistryLimit(balances []uint64) ([32]byte, error) {
|
||||
|
||||
// PackUint64IntoChunks packs a list of uint64 values into 32 byte roots.
|
||||
func PackUint64IntoChunks(vals []uint64) ([][32]byte, error) {
|
||||
numOfElems, err := types.Balances.ElemsInChunk()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iNumOfElems, err := pmath.Int(numOfElems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
numOfChunks := len(vals) / iNumOfElems
|
||||
if len(vals)%iNumOfElems != 0 {
|
||||
// Initialize how many uint64 values we can pack
|
||||
// into a single chunk(32 bytes). Each uint64 value
|
||||
// would take up 8 bytes.
|
||||
numOfElems := 4
|
||||
sizeOfElem := 32 / numOfElems
|
||||
// Determine total number of chunks to be
|
||||
// allocated to provided list of unsigned
|
||||
// 64-bit integers.
|
||||
numOfChunks := len(vals) / numOfElems
|
||||
// Add an extra chunk if the list size
|
||||
// is not a perfect multiple of the number
|
||||
// of elements.
|
||||
if len(vals)%numOfElems != 0 {
|
||||
numOfChunks++
|
||||
}
|
||||
balanceChunks := make([][32]byte, numOfChunks)
|
||||
chunkList := make([][32]byte, numOfChunks)
|
||||
for idx, b := range vals {
|
||||
startIdx := idx / iNumOfElems
|
||||
chunkIdx := idx % iNumOfElems
|
||||
sizeOfElem := 32 / iNumOfElems
|
||||
chunkPos := chunkIdx * sizeOfElem
|
||||
binary.LittleEndian.PutUint64(balanceChunks[startIdx][chunkPos:chunkPos+8], b)
|
||||
// In order to determine how to pack in the uint64 value by index into
|
||||
// our chunk list we need to determine a few things.
|
||||
// 1) The chunk which the particular uint64 value corresponds to.
|
||||
// 2) The position of the value in the chunk itself.
|
||||
//
|
||||
// Once we have determined these 2 values we can simply find the correct
|
||||
// section of contiguous bytes to insert the value in the chunk.
|
||||
chunkIdx := idx / numOfElems
|
||||
idxInChunk := idx % numOfElems
|
||||
chunkPos := idxInChunk * sizeOfElem
|
||||
binary.LittleEndian.PutUint64(chunkList[chunkIdx][chunkPos:chunkPos+sizeOfElem], b)
|
||||
}
|
||||
|
||||
return balanceChunks, nil
|
||||
return chunkList, nil
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ const (
|
||||
|
||||
// BeaconStateField represents a field of the beacon state.
|
||||
type BeaconStateField interface {
|
||||
String(stateVersion int) string
|
||||
String(stateVersion version.ForkVersion) string
|
||||
RealPosition() int
|
||||
ElemsInChunk() (uint64, error)
|
||||
Native() bool
|
||||
}
|
||||
|
||||
// String returns the name of the field index.
|
||||
func (f FieldIndex) String(stateVersion int) string {
|
||||
func (f FieldIndex) String(stateVersion version.ForkVersion) string {
|
||||
switch f {
|
||||
case GenesisTime:
|
||||
return "genesisTime"
|
||||
@@ -67,12 +67,12 @@ func (f FieldIndex) String(stateVersion int) string {
|
||||
case Slashings:
|
||||
return "slashings"
|
||||
case PreviousEpochAttestations:
|
||||
if version.Altair == stateVersion || version.Bellatrix == stateVersion {
|
||||
if stateVersion.IsParticipationBitsCompatible() {
|
||||
return "previousEpochParticipationBits"
|
||||
}
|
||||
return "previousEpochAttestations"
|
||||
case CurrentEpochAttestations:
|
||||
if version.Altair == stateVersion || version.Bellatrix == stateVersion {
|
||||
if stateVersion.IsParticipationBitsCompatible() {
|
||||
return "currentEpochParticipationBits"
|
||||
}
|
||||
return "currentEpochAttestations"
|
||||
|
||||
@@ -63,7 +63,7 @@ func (b *BeaconState) genesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (_ *BeaconState) Version() int {
|
||||
func (_ *BeaconState) Version() version.ForkVersion {
|
||||
return version.Phase0
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,8 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -174,24 +176,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(dst, func(b *BeaconState) {
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
|
||||
}
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
delete(b.dirtyIndices, field)
|
||||
delete(b.dirtyFields, field)
|
||||
delete(b.sharedFieldReferences, field)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
})
|
||||
runtime.SetFinalizer(dst, finalizerCleanup)
|
||||
return dst
|
||||
}
|
||||
|
||||
@@ -439,3 +424,22 @@ func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{
|
||||
b.dirtyIndices[index] = []uint64{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func finalizerCleanup(b *BeaconState) {
|
||||
fieldCount := params.BeaconConfig().BeaconStateFieldCount
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
delete(b.dirtyIndices, field)
|
||||
delete(b.dirtyFields, field)
|
||||
delete(b.sharedFieldReferences, field)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -62,8 +59,3 @@ func (*BeaconState) SetInactivityScores(_ []uint64) error {
|
||||
func (*BeaconState) SetLatestExecutionPayloadHeader(val *ethpb.ExecutionPayloadHeader) error {
|
||||
return errors.New("SetLatestExecutionPayloadHeader is not supported for phase 0 beacon state")
|
||||
}
|
||||
|
||||
func (b *BeaconState) ProcessInactivityScores(ctx context.Context,
|
||||
currentEpoch, previousEpoch, finalizedEpoch types.Epoch, vals []*types.Validator) ([]*types.Validator, error) {
|
||||
return nil, errors.New("ProcessInactivityScores is not supported for phase 0 beacon state")
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/core:go_default_library",
|
||||
"//beacon-chain/state/fieldtrie:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
|
||||
@@ -64,7 +64,7 @@ func (b *BeaconState) genesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (_ *BeaconState) Version() int {
|
||||
func (_ *BeaconState) Version() version.ForkVersion {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/core"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
@@ -266,26 +263,3 @@ func (b *BeaconState) SetInactivityScores(val []uint64) error {
|
||||
b.markFieldAsDirty(inactivityScores)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) ProcessInactivityScores(ctx context.Context,
|
||||
currentEpoch, previousEpoch, finalizedEpoch types.Epoch, vals []*types.Validator) ([]*types.Validator, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
scores := b.state.InactivityScores
|
||||
if b.sharedFieldReferences[inactivityScores].Refs() > 1 {
|
||||
scores = b.inactivityScores()
|
||||
b.sharedFieldReferences[inactivityScores].MinusRef()
|
||||
b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1)
|
||||
}
|
||||
var err error
|
||||
scores, vals, err = core.ProcessInactivityScores(ctx, scores, currentEpoch, previousEpoch, finalizedEpoch, vals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.state.InactivityScores = scores
|
||||
b.markFieldAsDirty(inactivityScores)
|
||||
return vals, err
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (state.BeaconState,
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -179,23 +181,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(dst, func(b *BeaconState) {
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
delete(b.dirtyIndices, field)
|
||||
delete(b.dirtyFields, field)
|
||||
delete(b.sharedFieldReferences, field)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
})
|
||||
runtime.SetFinalizer(dst, finalizerCleanup)
|
||||
|
||||
return dst
|
||||
}
|
||||
@@ -426,3 +412,22 @@ func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{
|
||||
b.dirtyIndices[index] = []uint64{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func finalizerCleanup(b *BeaconState) {
|
||||
fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
delete(b.dirtyIndices, field)
|
||||
delete(b.dirtyFields, field)
|
||||
delete(b.sharedFieldReferences, field)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
go test fuzz v1
|
||||
[]byte("")
|
||||
uint64(117)
|
||||
@@ -37,7 +37,6 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/core:go_default_library",
|
||||
"//beacon-chain/state/fieldtrie:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
|
||||
@@ -63,7 +63,7 @@ func (b *BeaconState) genesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (_ *BeaconState) Version() int {
|
||||
func (_ *BeaconState) Version() version.ForkVersion {
|
||||
return version.Bellatrix
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/core"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
@@ -266,26 +263,3 @@ func (b *BeaconState) SetInactivityScores(val []uint64) error {
|
||||
b.markFieldAsDirty(inactivityScores)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) ProcessInactivityScores(ctx context.Context,
|
||||
currentEpoch, previousEpoch, finalizedEpoch types.Epoch, vals []*types.Validator) ([]*types.Validator, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
scores := b.state.InactivityScores
|
||||
if b.sharedFieldReferences[inactivityScores].Refs() > 1 {
|
||||
scores = b.inactivityScores()
|
||||
b.sharedFieldReferences[inactivityScores].MinusRef()
|
||||
b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1)
|
||||
}
|
||||
var err error
|
||||
scores, vals, err = core.ProcessInactivityScores(ctx, scores, currentEpoch, previousEpoch, finalizedEpoch, vals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.state.InactivityScores = scores
|
||||
b.markFieldAsDirty(inactivityScores)
|
||||
return vals, err
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[latestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Bellatrix.
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -179,23 +181,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
}
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(dst, func(b *BeaconState) {
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
delete(b.dirtyIndices, field)
|
||||
delete(b.dirtyFields, field)
|
||||
delete(b.sharedFieldReferences, field)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
})
|
||||
runtime.SetFinalizer(dst, finalizerCleanup)
|
||||
|
||||
return dst
|
||||
}
|
||||
@@ -421,3 +407,22 @@ func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{
|
||||
b.dirtyIndices[index] = []uint64{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func finalizerCleanup(b *BeaconState) {
|
||||
fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount
|
||||
for field, v := range b.sharedFieldReferences {
|
||||
v.MinusRef()
|
||||
if b.stateFieldLeaves[field].FieldReference() != nil {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
delete(b.dirtyIndices, field)
|
||||
delete(b.dirtyFields, field)
|
||||
delete(b.sharedFieldReferences, field)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
}
|
||||
state.StateCount.Sub(1)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user