mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
5569a68452
* Value assigned to a variable is never read before being overwritten * The result of append is not used anywhere * Suspicious assignment of range-loop vars detected * Unused method receiver detected * Revert "Auxiliary commit to revert individual files from 54edcb445484a2e5d79612e19af8e949b8861253" This reverts commit bbd1e1beabf7b0c5cfc4f514dcc820062ad6c063. * Method modifies receiver * Fix test * Duplicate imports detected * Incorrectly formatted error string * Types of function parameters can be combined * One more "Unused method receiver detected" * Unused parameter detected in function
83 lines
2.6 KiB
Go
83 lines
2.6 KiB
Go
package blockchain
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
|
)
|
|
|
|
var errNilStateFromStategen = errors.New("justified state can't be nil")
|
|
|
|
type stateBalanceCache struct {
|
|
sync.Mutex
|
|
balances []uint64
|
|
root [32]byte
|
|
stateGen stateByRooter
|
|
}
|
|
|
|
type stateByRooter interface {
|
|
StateByRoot(context.Context, [32]byte) (state.BeaconState, error)
|
|
}
|
|
|
|
// newStateBalanceCache exists to remind us that stateBalanceCache needs a stagegen
|
|
// to avoid nil pointer bugs when updating the cache in the read path (get())
|
|
func newStateBalanceCache(sg *stategen.State) (*stateBalanceCache, error) {
|
|
if sg == nil {
|
|
return nil, errors.New("can't initialize state balance cache without stategen")
|
|
}
|
|
return &stateBalanceCache{stateGen: sg}, nil
|
|
}
|
|
|
|
// update is called by get() when the requested root doesn't match
|
|
// the previously read value. This cache assumes we only want to cache one
|
|
// set of balances for a single root (the current justified root).
|
|
//
|
|
// warning: this is not thread-safe on its own, relies on get() for locking
|
|
func (c *stateBalanceCache) update(ctx context.Context, justifiedRoot [32]byte) ([]uint64, error) {
|
|
stateBalanceCacheMiss.Inc()
|
|
justifiedState, err := c.stateGen.StateByRoot(ctx, justifiedRoot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if justifiedState == nil || justifiedState.IsNil() {
|
|
return nil, errNilStateFromStategen
|
|
}
|
|
epoch := time.CurrentEpoch(justifiedState)
|
|
|
|
justifiedBalances := make([]uint64, justifiedState.NumValidators())
|
|
var balanceAccumulator = func(idx int, val state.ReadOnlyValidator) error {
|
|
if helpers.IsActiveValidatorUsingTrie(val, epoch) {
|
|
justifiedBalances[idx] = val.EffectiveBalance()
|
|
} else {
|
|
justifiedBalances[idx] = 0
|
|
}
|
|
return nil
|
|
}
|
|
if err := justifiedState.ReadFromEveryValidator(balanceAccumulator); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c.balances = justifiedBalances
|
|
c.root = justifiedRoot
|
|
return c.balances, nil
|
|
}
|
|
|
|
// getBalances takes an explicit justifiedRoot so it can invalidate the singleton cache key
|
|
// when the justified root changes, and takes a context so that the long-running stategen
|
|
// read path can connect to the upstream cancellation/timeout chain.
|
|
func (c *stateBalanceCache) get(ctx context.Context, justifiedRoot [32]byte) ([]uint64, error) {
|
|
c.Lock()
|
|
defer c.Unlock()
|
|
if justifiedRoot == c.root {
|
|
stateBalanceCacheHit.Inc()
|
|
return c.balances, nil
|
|
}
|
|
|
|
return c.update(ctx, justifiedRoot)
|
|
}
|