mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-23 03:51:29 +00:00
28596d669b
* Use proposer index cache for blob verification * add unit test * Fix test --------- Co-authored-by: terence tsao <terence@prysmaticlabs.com>
107 lines
3.7 KiB
Go
107 lines
3.7 KiB
Go
package verification
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/kzg"
|
|
forkchoicetypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/forkchoice/types"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/startup"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
|
)
|
|
|
|
// Forkchoicer represents the forkchoice methods that the verifiers need.
|
|
// Note that forkchoice is used here in a lock-free fashion, assuming that a version of forkchoice
|
|
// is given that internally handles the details of locking the underlying store.
|
|
type Forkchoicer interface {
|
|
FinalizedCheckpoint() *forkchoicetypes.Checkpoint
|
|
HasNode([32]byte) bool
|
|
IsCanonical(root [32]byte) bool
|
|
Slot([32]byte) (primitives.Slot, error)
|
|
TargetRootForEpoch([32]byte, primitives.Epoch) ([32]byte, error)
|
|
}
|
|
|
|
// StateByRooter describes a stategen-ish type that can produce arbitrary states by their root
|
|
type StateByRooter interface {
|
|
StateByRoot(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
|
|
}
|
|
|
|
// sharedResources provides access to resources that are required by different verification types.
|
|
// for example, sidecar verification and block verification share the block signature verification cache.
|
|
type sharedResources struct {
|
|
clock *startup.Clock
|
|
fc Forkchoicer
|
|
sc SignatureCache
|
|
pc ProposerCache
|
|
sr StateByRooter
|
|
}
|
|
|
|
// Initializer is used to create different Verifiers.
|
|
// Verifiers require access to stateful data structures, like caches,
|
|
// and it is Initializer's job to provides access to those.
|
|
type Initializer struct {
|
|
shared *sharedResources
|
|
}
|
|
|
|
// NewBlobVerifier creates a BlobVerifier for a single blob, with the given set of requirements.
|
|
func (ini *Initializer) NewBlobVerifier(b blocks.ROBlob, reqs []Requirement) *ROBlobVerifier {
|
|
return &ROBlobVerifier{
|
|
sharedResources: ini.shared,
|
|
blob: b,
|
|
results: newResults(reqs...),
|
|
verifyBlobCommitment: kzg.Verify,
|
|
}
|
|
}
|
|
|
|
// InitializerWaiter provides an Initializer once all dependent resources are ready
|
|
// via the WaitForInitializer method.
|
|
type InitializerWaiter struct {
|
|
sync.RWMutex
|
|
ready bool
|
|
cw startup.ClockWaiter
|
|
ini *Initializer
|
|
}
|
|
|
|
// NewInitializerWaiter creates an InitializerWaiter which can be used to obtain an Initializer once async dependencies are ready.
|
|
func NewInitializerWaiter(cw startup.ClockWaiter, fc Forkchoicer, sr StateByRooter) *InitializerWaiter {
|
|
pc := newPropCache()
|
|
// signature cache is initialized in WaitForInitializer, since we need the genesis validators root, which can be obtained from startup.Clock.
|
|
shared := &sharedResources{
|
|
fc: fc,
|
|
pc: pc,
|
|
sr: sr,
|
|
}
|
|
return &InitializerWaiter{cw: cw, ini: &Initializer{shared: shared}}
|
|
}
|
|
|
|
// WaitForInitializer ensures that asynchronous initialization of the shared resources the initializer
|
|
// depends on has completed before the underlying Initializer is accessible by client code.
|
|
func (w *InitializerWaiter) WaitForInitializer(ctx context.Context) (*Initializer, error) {
|
|
if err := w.waitForReady(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
// We wait until this point to initialize the signature cache because here we have access to the genesis validator root.
|
|
vr := w.ini.shared.clock.GenesisValidatorsRoot()
|
|
sc := newSigCache(vr[:], DefaultSignatureCacheSize)
|
|
w.ini.shared.sc = sc
|
|
return w.ini, nil
|
|
}
|
|
|
|
func (w *InitializerWaiter) waitForReady(ctx context.Context) error {
|
|
w.Lock()
|
|
defer w.Unlock()
|
|
if w.ready {
|
|
return nil
|
|
}
|
|
|
|
clock, err := w.cw.WaitForClock(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
w.ini.shared.clock = clock
|
|
w.ready = true
|
|
return nil
|
|
}
|