Aditya's PR 18 (#11945)

* Aditya's PR 18

This PR implements PR18. There is still a missing piece which is
consistency of head with finalized checkpoint. I will think on ways to
enforce this.

* prune finalized incompatible

* don't check finalization on viable for head

* unit tests fixes

* gazelle

* remove finalized epoch from viableForHead

* remove finalized epoch from leadsToViableHead

* use non-slashed indices

* function rename

* lint fixes

* lint fixes

* lint fixes
This commit is contained in:
Potuz
2023-02-05 09:40:07 -03:00
committed by GitHub
parent 4f6cb3209d
commit 0d6e8718fd
15 changed files with 146 additions and 82 deletions

View File

@@ -39,7 +39,7 @@ type mockBalanceByRooter struct {
var _ balanceByRooter = &mockBalanceByRooter{}
func (m mockBalanceByRooter) BalancesByRoot(_ context.Context, _ [32]byte) ([]uint64, error) {
func (m mockBalanceByRooter) ActiveNonSlashedBalancesByRoot(_ context.Context, _ [32]byte) ([]uint64, error) {
st := m.state
if st == nil || st.IsNil() {
return nil, errors.New("nil state")

View File

@@ -16,7 +16,7 @@ type stateBalanceCache struct {
}
type balanceByRooter interface {
BalancesByRoot(context.Context, [32]byte) ([]uint64, error)
ActiveNonSlashedBalancesByRoot(context.Context, [32]byte) ([]uint64, error)
}
// newStateBalanceCache exists to remind us that stateBalanceCache needs a state gen
@@ -36,7 +36,7 @@ func newStateBalanceCache(sg *stategen.State) (*stateBalanceCache, error) {
func (c *stateBalanceCache) update(ctx context.Context, justifiedRoot [32]byte) ([]uint64, error) {
stateBalanceCacheMiss.Inc()
justifiedBalances, err := c.stateGen.BalancesByRoot(ctx, justifiedRoot)
justifiedBalances, err := c.stateGen.ActiveNonSlashedBalancesByRoot(ctx, justifiedRoot)
if err != nil {
return nil, errors.Wrap(err, "could not get balances")
}

View File

@@ -43,6 +43,12 @@ func IsActiveValidatorUsingTrie(validator state.ReadOnlyValidator, epoch primiti
return checkValidatorActiveStatus(validator.ActivationEpoch(), validator.ExitEpoch(), epoch)
}
// IsActiveNonSlashedValidatorUsingTrie checks if a read only validator is active and not slashed
func IsActiveNonSlashedValidatorUsingTrie(validator state.ReadOnlyValidator, epoch primitives.Epoch) bool {
active := checkValidatorActiveStatus(validator.ActivationEpoch(), validator.ExitEpoch(), epoch)
return active && !validator.Slashed()
}
func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch primitives.Epoch) bool {
return activationEpoch <= epoch && epoch < exitEpoch
}

View File

@@ -56,6 +56,34 @@ func TestIsActiveValidatorUsingTrie_OK(t *testing.T) {
}
}
func TestIsActiveNonSlashedValidatorUsingTrie_OK(t *testing.T) {
tests := []struct {
a primitives.Epoch
s bool
b bool
}{
{a: 0, s: false, b: false},
{a: 10, s: false, b: true},
{a: 100, s: false, b: false},
{a: 1000, s: false, b: false},
{a: 64, s: false, b: true},
{a: 0, s: true, b: false},
{a: 10, s: true, b: false},
{a: 100, s: true, b: false},
{a: 1000, s: true, b: false},
{a: 64, s: true, b: false},
}
for _, test := range tests {
val := &ethpb.Validator{ActivationEpoch: 10, ExitEpoch: 100}
val.Slashed = test.s
beaconState, err := state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{Validators: []*ethpb.Validator{val}})
require.NoError(t, err)
readOnlyVal, err := beaconState.ValidatorAtIndexReadOnly(0)
require.NoError(t, err)
assert.Equal(t, test.b, IsActiveNonSlashedValidatorUsingTrie(readOnlyVal, test.a), "IsActiveNonSlashedValidatorUsingTrie(%d)", test.a)
}
}
func TestIsSlashableValidator_OK(t *testing.T) {
tests := []struct {
name string

View File

@@ -168,37 +168,42 @@ func (f *ForkChoice) updateCheckpoints(ctx context.Context, jc, fc *ethpb.Checkp
f.store.bestJustifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: jc.Epoch,
Root: bytesutil.ToBytes32(jc.Root)}
}
currentSlot := slots.CurrentSlot(f.store.genesisTime)
if slots.SinceEpochStarts(currentSlot) < params.BeaconConfig().SafeSlotsToUpdateJustified {
f.store.prevJustifiedCheckpoint = f.store.justifiedCheckpoint
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: jc.Epoch,
Root: bytesutil.ToBytes32(jc.Root)}
} else {
currentJcp := f.store.justifiedCheckpoint
currentRoot := currentJcp.Root
if currentRoot == params.BeaconConfig().ZeroHash {
currentRoot = f.store.originRoot
}
jSlot, err := slots.EpochStart(currentJcp.Epoch)
if err != nil {
f.store.checkpointsLock.Unlock()
return err
}
jcRoot := bytesutil.ToBytes32(jc.Root)
// Releasing here the checkpoints lock because
// AncestorRoot acquires a lock on nodes and that can
// cause a double lock.
f.store.checkpointsLock.Unlock()
root, err := f.AncestorRoot(ctx, jcRoot, jSlot)
if err != nil {
return err
}
f.store.checkpointsLock.Lock()
if root == currentRoot {
if !features.Get().EnableDefensivePull {
currentSlot := slots.CurrentSlot(f.store.genesisTime)
if slots.SinceEpochStarts(currentSlot) < params.BeaconConfig().SafeSlotsToUpdateJustified {
f.store.prevJustifiedCheckpoint = f.store.justifiedCheckpoint
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: jc.Epoch,
Root: jcRoot}
Root: bytesutil.ToBytes32(jc.Root)}
} else {
currentJcp := f.store.justifiedCheckpoint
currentRoot := currentJcp.Root
if currentRoot == params.BeaconConfig().ZeroHash {
currentRoot = f.store.originRoot
}
jSlot, err := slots.EpochStart(currentJcp.Epoch)
if err != nil {
f.store.checkpointsLock.Unlock()
return err
}
jcRoot := bytesutil.ToBytes32(jc.Root)
// Releasing here the checkpoints lock because
// AncestorRoot acquires a lock on nodes and that can
// cause a double lock.
f.store.checkpointsLock.Unlock()
root, err := f.AncestorRoot(ctx, jcRoot, jSlot)
if err != nil {
return err
}
f.store.checkpointsLock.Lock()
if root == currentRoot {
f.store.prevJustifiedCheckpoint = f.store.justifiedCheckpoint
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: jc.Epoch,
Root: jcRoot}
}
}
} else {
f.store.prevJustifiedCheckpoint = f.store.justifiedCheckpoint
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: jc.Epoch, Root: bytesutil.ToBytes32(jc.Root)}
}
}
// Update finalization
@@ -208,8 +213,10 @@ func (f *ForkChoice) updateCheckpoints(ctx context.Context, jc, fc *ethpb.Checkp
}
f.store.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: fc.Epoch,
Root: bytesutil.ToBytes32(fc.Root)}
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: jc.Epoch,
Root: bytesutil.ToBytes32(jc.Root)}
if !features.Get().EnableDefensivePull {
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: jc.Epoch,
Root: bytesutil.ToBytes32(jc.Root)}
}
f.store.checkpointsLock.Unlock()
return f.store.prune(ctx)
}

View File

@@ -54,7 +54,7 @@ func (n *Node) updateBestDescendant(ctx context.Context, justifiedEpoch, finaliz
if err := child.updateBestDescendant(ctx, justifiedEpoch, finalizedEpoch, currentEpoch); err != nil {
return err
}
childLeadsToViableHead := child.leadsToViableHead(justifiedEpoch, finalizedEpoch, currentEpoch)
childLeadsToViableHead := child.leadsToViableHead(justifiedEpoch, currentEpoch)
if childLeadsToViableHead && !hasViableDescendant {
// The child leads to a viable head, but the current
// parent's best child doesn't.
@@ -89,25 +89,21 @@ func (n *Node) updateBestDescendant(ctx context.Context, justifiedEpoch, finaliz
// viableForHead returns true if the node is viable to head.
// Any node with different finalized or justified epoch than
// the ones in fork choice store should not be viable to head.
func (n *Node) viableForHead(justifiedEpoch, finalizedEpoch, currentEpoch primitives.Epoch) bool {
func (n *Node) viableForHead(justifiedEpoch, currentEpoch primitives.Epoch) bool {
justified := justifiedEpoch == n.justifiedEpoch || justifiedEpoch == 0
finalized := finalizedEpoch == n.finalizedEpoch || finalizedEpoch == 0
if features.Get().EnableDefensivePull && !justified && justifiedEpoch+1 == currentEpoch {
if n.unrealizedJustifiedEpoch+1 >= currentEpoch {
if n.unrealizedJustifiedEpoch+1 >= currentEpoch && n.justifiedEpoch+2 >= currentEpoch {
justified = true
}
if n.unrealizedFinalizedEpoch >= finalizedEpoch {
finalized = true
}
}
return justified && finalized
return justified
}
func (n *Node) leadsToViableHead(justifiedEpoch, finalizedEpoch, currentEpoch primitives.Epoch) bool {
func (n *Node) leadsToViableHead(justifiedEpoch, currentEpoch primitives.Epoch) bool {
if n.bestDescendant == nil {
return n.viableForHead(justifiedEpoch, finalizedEpoch, currentEpoch)
return n.viableForHead(justifiedEpoch, currentEpoch)
}
return n.bestDescendant.viableForHead(justifiedEpoch, finalizedEpoch, currentEpoch)
return n.bestDescendant.viableForHead(justifiedEpoch, currentEpoch)
}
// setNodeAndParentValidated sets the current node and all the ancestors as validated (i.e. non-optimistic).

View File

@@ -144,18 +144,16 @@ func TestNode_ViableForHead(t *testing.T) {
tests := []struct {
n *Node
justifiedEpoch primitives.Epoch
finalizedEpoch primitives.Epoch
want bool
}{
{&Node{}, 0, 0, true},
{&Node{}, 1, 0, false},
{&Node{}, 0, 1, false},
{&Node{finalizedEpoch: 1, justifiedEpoch: 1}, 1, 1, true},
{&Node{finalizedEpoch: 1, justifiedEpoch: 1}, 2, 2, false},
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, 3, true},
{&Node{}, 0, true},
{&Node{}, 1, false},
{&Node{finalizedEpoch: 1, justifiedEpoch: 1}, 1, true},
{&Node{finalizedEpoch: 1, justifiedEpoch: 1}, 2, false},
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, true},
}
for _, tc := range tests {
got := tc.n.viableForHead(tc.justifiedEpoch, tc.finalizedEpoch, 5)
got := tc.n.viableForHead(tc.justifiedEpoch, 5)
assert.Equal(t, tc.want, got)
}
}
@@ -179,10 +177,10 @@ func TestNode_LeadsToViableHead(t *testing.T) {
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
require.Equal(t, true, f.store.treeRootNode.leadsToViableHead(4, 3, 5))
require.Equal(t, true, f.store.nodeByRoot[indexToHash(5)].leadsToViableHead(4, 3, 5))
require.Equal(t, false, f.store.nodeByRoot[indexToHash(2)].leadsToViableHead(4, 3, 5))
require.Equal(t, false, f.store.nodeByRoot[indexToHash(4)].leadsToViableHead(4, 3, 5))
require.Equal(t, true, f.store.treeRootNode.leadsToViableHead(4, 5))
require.Equal(t, true, f.store.nodeByRoot[indexToHash(5)].leadsToViableHead(4, 5))
require.Equal(t, false, f.store.nodeByRoot[indexToHash(2)].leadsToViableHead(4, 5))
require.Equal(t, false, f.store.nodeByRoot[indexToHash(4)].leadsToViableHead(4, 5))
}
func TestNode_SetFullyValidated(t *testing.T) {

View File

@@ -86,7 +86,7 @@ func (s *Store) head(ctx context.Context) ([32]byte, error) {
bestDescendant = justifiedNode
}
currentEpoch := slots.EpochsSinceGenesis(time.Unix(int64(s.genesisTime), 0))
if !bestDescendant.viableForHead(s.justifiedCheckpoint.Epoch, s.finalizedCheckpoint.Epoch, currentEpoch) {
if !bestDescendant.viableForHead(s.justifiedCheckpoint.Epoch, currentEpoch) {
s.allTipsAreInvalid = true
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch, justified Epoch %d, %d != %d, %d",
bestDescendant.slot, bestDescendant.weight/10e9, bestDescendant.finalizedEpoch, bestDescendant.justifiedEpoch, s.finalizedCheckpoint.Epoch, s.justifiedCheckpoint.Epoch)
@@ -218,8 +218,8 @@ func (s *Store) prune(ctx context.Context) error {
defer s.nodesLock.Unlock()
s.checkpointsLock.RLock()
finalizedRoot := s.finalizedCheckpoint.Root
finalizedEpoch := s.finalizedCheckpoint.Epoch
s.checkpointsLock.RUnlock()
finalizedNode, ok := s.nodeByRoot[finalizedRoot]
if !ok || finalizedNode == nil {
return errors.WithMessage(errUnknownFinalizedRoot, fmt.Sprintf("%#x", finalizedRoot))
@@ -238,6 +238,22 @@ func (s *Store) prune(ctx context.Context) error {
s.treeRootNode = finalizedNode
prunedCount.Inc()
// Prune all children of the finalized checkpoint block that are incompatible with it
checkpointMaxSlot, err := slots.EpochStart(finalizedEpoch)
if err != nil {
return errors.Wrap(err, "could not compute epoch start")
}
if finalizedNode.slot == checkpointMaxSlot {
return nil
}
for _, child := range finalizedNode.children {
if child != nil && child.slot <= checkpointMaxSlot {
if err := s.pruneFinalizedNodeByRootMap(ctx, child, finalizedNode); err != nil {
return errors.Wrap(err, "could not prune incompatible finalized child")
}
}
}
return nil
}

View File

@@ -5,6 +5,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/epoch/precompute"
forkchoicetypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/types"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v3/config/features"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
@@ -55,12 +56,14 @@ func (f *ForkChoice) updateUnrealizedCheckpoints() {
if node.justifiedEpoch > f.store.justifiedCheckpoint.Epoch {
f.store.prevJustifiedCheckpoint = f.store.justifiedCheckpoint
f.store.justifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
if node.justifiedEpoch > f.store.bestJustifiedCheckpoint.Epoch {
if !features.Get().EnableDefensivePull && node.justifiedEpoch > f.store.bestJustifiedCheckpoint.Epoch {
f.store.bestJustifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
}
}
if node.finalizedEpoch > f.store.finalizedCheckpoint.Epoch {
f.store.justifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
if !features.Get().EnableDefensivePull {
f.store.justifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
}
f.store.finalizedCheckpoint = f.store.unrealizedFinalizedCheckpoint
}
}

View File

@@ -187,7 +187,7 @@ func TestStore_NoDeadLock(t *testing.T) {
require.Equal(t, primitives.Epoch(1), f.FinalizedCheckpoint().Epoch)
}
// Epoch 1 | Epoch 2
// Epoch 2 | Epoch 3
// |
// -- D (late)
// / |
@@ -203,31 +203,31 @@ func TestStore_ForkNextEpoch(t *testing.T) {
})
defer resetCfg()
f := setup(0, 0)
f := setup(1, 0)
ctx := context.Background()
// Epoch 1 blocks (D does not arrive)
state, blkRoot, err := prepareForkchoiceState(ctx, 92, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0)
state, blkRoot, err := prepareForkchoiceState(ctx, 92, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
state, blkRoot, err = prepareForkchoiceState(ctx, 93, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0)
state, blkRoot, err = prepareForkchoiceState(ctx, 93, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
state, blkRoot, err = prepareForkchoiceState(ctx, 94, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 0, 0)
state, blkRoot, err = prepareForkchoiceState(ctx, 94, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
// Epoch 2 blocks
state, blkRoot, err = prepareForkchoiceState(ctx, 96, [32]byte{'e'}, [32]byte{'c'}, [32]byte{'E'}, 0, 0)
state, blkRoot, err = prepareForkchoiceState(ctx, 96, [32]byte{'e'}, [32]byte{'c'}, [32]byte{'E'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
state, blkRoot, err = prepareForkchoiceState(ctx, 97, [32]byte{'f'}, [32]byte{'e'}, [32]byte{'F'}, 0, 0)
state, blkRoot, err = prepareForkchoiceState(ctx, 97, [32]byte{'f'}, [32]byte{'e'}, [32]byte{'F'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
state, blkRoot, err = prepareForkchoiceState(ctx, 98, [32]byte{'g'}, [32]byte{'f'}, [32]byte{'G'}, 0, 0)
state, blkRoot, err = prepareForkchoiceState(ctx, 98, [32]byte{'g'}, [32]byte{'f'}, [32]byte{'G'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
state, blkRoot, err = prepareForkchoiceState(ctx, 99, [32]byte{'h'}, [32]byte{'g'}, [32]byte{'H'}, 0, 0)
state, blkRoot, err = prepareForkchoiceState(ctx, 99, [32]byte{'h'}, [32]byte{'g'}, [32]byte{'H'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
@@ -236,10 +236,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
headRoot, err := f.Head(ctx, []uint64{100})
require.NoError(t, err)
require.Equal(t, [32]byte{'h'}, headRoot)
require.Equal(t, primitives.Epoch(0), f.JustifiedCheckpoint().Epoch)
require.Equal(t, primitives.Epoch(1), f.JustifiedCheckpoint().Epoch)
// D arrives late, D is head
state, blkRoot, err = prepareForkchoiceState(ctx, 95, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0)
state, blkRoot, err = prepareForkchoiceState(ctx, 95, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 1, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 2))

View File

@@ -123,7 +123,9 @@ func TestVotes_CanFindHead(t *testing.T) {
// 4
// /
// 5 <- head, justified epoch = 2
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 2)
//
// We set this node's slot to be 64 so that when prunning below we do not prune its child
state, blkRoot, err = prepareForkchoiceState(context.Background(), 2*params.BeaconConfig().SlotsPerEpoch, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 2)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))

View File

@@ -65,9 +65,9 @@ func (s *State) StateByRoot(ctx context.Context, blockRoot [32]byte) (state.Beac
return s.loadStateByRoot(ctx, blockRoot)
}
// BalancesByRoot retrieves the effective balances of all validators at the
// ActiveNonSlashedBalancesByRoot retrieves the effective balances of all active and non-slashed validators at the
// state with a given root
func (s *State) BalancesByRoot(ctx context.Context, blockRoot [32]byte) ([]uint64, error) {
func (s *State) ActiveNonSlashedBalancesByRoot(ctx context.Context, blockRoot [32]byte) ([]uint64, error) {
st, err := s.StateByRoot(ctx, blockRoot)
if err != nil {
return nil, err
@@ -79,7 +79,7 @@ func (s *State) BalancesByRoot(ctx context.Context, blockRoot [32]byte) ([]uint6
balances := make([]uint64, st.NumValidators())
var balanceAccretor = func(idx int, val state.ReadOnlyValidator) error {
if helpers.IsActiveValidatorUsingTrie(val, epoch) {
if helpers.IsActiveNonSlashedValidatorUsingTrie(val, epoch) {
balances[idx] = val.EffectiveBalance()
} else {
balances[idx] = 0

View File

@@ -48,6 +48,14 @@ func TestStateByRoot_ColdState(t *testing.T) {
require.NoError(t, err)
beaconState, _ := util.DeterministicGenesisState(t, 32)
require.NoError(t, beaconState.SetSlot(1))
val, err := beaconState.ValidatorAtIndex(0)
require.NoError(t, err)
val.Slashed = true
require.NoError(t, beaconState.UpdateValidatorAtIndex(0, val))
roval, err := beaconState.ValidatorAtIndexReadOnly(0)
require.NoError(t, err)
require.Equal(t, true, roval.Slashed())
require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, bRoot))
util.SaveBlock(t, ctx, service.beaconDB, b)
require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot))
@@ -55,12 +63,13 @@ func TestStateByRoot_ColdState(t *testing.T) {
require.NoError(t, err)
require.DeepSSZEqual(t, loadedState.ToProtoUnsafe(), beaconState.ToProtoUnsafe())
bal, err := service.BalancesByRoot(ctx, bRoot)
bal, err := service.ActiveNonSlashedBalancesByRoot(ctx, bRoot)
require.NoError(t, err)
require.Equal(t, 32, len(bal))
for i := range bal {
require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, bal[i])
for _, balance := range bal[1:] {
require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, balance)
}
require.Equal(t, uint64(0), bal[0])
}
func TestStateByRootIfCachedNoCopy_HotState(t *testing.T) {

View File

@@ -52,7 +52,7 @@ func (m *MockStateManager) StateByRoot(_ context.Context, blockRoot [32]byte) (s
}
// BalancesByRoot --
func (*MockStateManager) BalancesByRoot(_ context.Context, _ [32]byte) ([]uint64, error) {
func (*MockStateManager) ActiveNonSlashedBalancesByRoot(_ context.Context, _ [32]byte) ([]uint64, error) {
return []uint64{}, nil
}

View File

@@ -33,7 +33,7 @@ type StateManager interface {
SaveFinalizedState(fSlot primitives.Slot, fRoot [32]byte, fState state.BeaconState)
MigrateToCold(ctx context.Context, fRoot [32]byte) error
StateByRoot(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
BalancesByRoot(context.Context, [32]byte) ([]uint64, error)
ActiveNonSlashedBalancesByRoot(context.Context, [32]byte) ([]uint64, error)
StateByRootIfCachedNoCopy(blockRoot [32]byte) state.BeaconState
StateByRootInitialSync(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
}
@@ -96,8 +96,7 @@ func New(beaconDB db.NoHeadAccessDatabase, fc forkchoice.ForkChoicer, opts ...St
for _, o := range opts {
o(s)
}
fc.SetBalancesByRooter(s.BalancesByRoot)
fc.SetBalancesByRooter(s.ActiveNonSlashedBalancesByRoot)
return s
}