Block backfilling (#12968)

* backfill service

* fix bug where origin state is never unlocked

* support mvslice states

* use renamed interface

* refactor db code to skip block cache for backfill

* lint

* add test for verifier.verify

* enable service in service init test

* cancellation cleanup

* adding nil checks to configset juggling

* assume blocks are available by default

As long as we're sure the AvailableBlocker is initialized correctly
during node startup, defaulting to assuming we aren't in a checkpoint
sync simplifies things greatly for tests.

* block saving path refactor and bugfix

* fix fillback test

* fix BackfillStatus init tests

---------

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
This commit is contained in:
kasey
2024-01-23 01:54:30 -06:00
committed by GitHub
parent 3187a05a76
commit 1df173e701
59 changed files with 2886 additions and 536 deletions

View File

@@ -121,6 +121,7 @@ type ReadOnlyValidators interface {
ValidatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Validator, error)
ValidatorAtIndexReadOnly(idx primitives.ValidatorIndex) (ReadOnlyValidator, error)
ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]byte) (primitives.ValidatorIndex, bool)
PublicKeys() ([][fieldparams.BLSPubkeyLength]byte, error)
PubkeyAtIndex(idx primitives.ValidatorIndex) [fieldparams.BLSPubkeyLength]byte
NumValidators() int
ReadFromEveryValidator(f func(idx int, val ReadOnlyValidator) error) error

View File

@@ -181,6 +181,27 @@ func (b *BeaconState) PubkeyAtIndex(idx primitives.ValidatorIndex) [fieldparams.
return bytesutil.ToBytes48(v.PublicKey)
}
// PublicKeys builds a list of all validator public keys, with each key's index aligned to its validator index.
func (b *BeaconState) PublicKeys() ([][fieldparams.BLSPubkeyLength]byte, error) {
b.lock.RLock()
defer b.lock.RUnlock()
l := b.validatorsLen()
res := make([][fieldparams.BLSPubkeyLength]byte, l)
for i := 0; i < l; i++ {
if features.Get().EnableExperimentalState {
val, err := b.validatorsMultiValue.At(b, uint64(i))
if err != nil {
return nil, err
}
copy(res[i][:], val.PublicKey)
} else {
copy(res[i][:], b.validators[i].PublicKey)
}
}
return res, nil
}
// NumValidators returns the size of the validator registry.
func (b *BeaconState) NumValidators() int {
b.lock.RLock()

View File

@@ -31,7 +31,7 @@ go_library(
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/forkchoice:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/sync/backfill:go_default_library",
"//beacon-chain/sync/backfill/coverage:go_default_library",
"//cache/lru:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",

View File

@@ -332,9 +332,8 @@ func (s *State) CombinedCache() *CombinedCache {
}
func (s *State) slotAvailable(slot primitives.Slot) bool {
// default to assuming node was initialized from genesis - backfill only needs to be specified for checkpoint sync
if s.backfillStatus == nil {
if s.avb == nil {
return true
}
return s.backfillStatus.SlotCovered(slot)
return s.avb.AvailableBlock(slot)
}

View File

@@ -13,7 +13,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/forkchoice"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/backfill"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/backfill/coverage"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
@@ -51,7 +51,7 @@ type State struct {
finalizedInfo *finalizedInfo
epochBoundaryStateCache *epochBoundaryState
saveHotStateDB *saveHotStateDbConfig
backfillStatus *backfill.Status
avb coverage.AvailableBlocker
migrationLock *sync.Mutex
fc forkchoice.ForkChoicer
}
@@ -78,9 +78,11 @@ type finalizedInfo struct {
// Option is a functional option for controlling the initialization of a *State value
type Option func(*State)
func WithBackfillStatus(bfs *backfill.Status) Option {
// WithAvailableBlocker gives stategen an AvailableBlocker, which is used to determine if a given
// block is available. This is necessary because backfill creates a hole in the block history.
func WithAvailableBlocker(avb coverage.AvailableBlocker) Option {
return func(sg *State) {
sg.backfillStatus = bfs
sg.avb = avb
}
}