Skip to content

Commit

Permalink
poc complete
Browse files Browse the repository at this point in the history
  • Loading branch information
rkapka committed Nov 3, 2024
1 parent 568d96b commit 1efdb38
Show file tree
Hide file tree
Showing 19 changed files with 440 additions and 127 deletions.
1 change: 1 addition & 0 deletions beacon-chain/blockchain/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ go_library(
"//beacon-chain/forkchoice:go_default_library",
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
"//beacon-chain/forkchoice/types:go_default_library",
"//beacon-chain/light-client:go_default_library",
"//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/blstoexec:go_default_library",
"//beacon-chain/operations/slashings:go_default_library",
Expand Down
8 changes: 8 additions & 0 deletions beacon-chain/blockchain/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice"
light_client "github.com/prysmaticlabs/prysm/v5/beacon-chain/light-client"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/blstoexec"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/slashings"
Expand Down Expand Up @@ -205,3 +206,10 @@ func WithSyncChecker(checker Checker) Option {
return nil
}
}

func WithLightClientStore(lcs *light_client.Store) Option {
return func(s *Service) error {
s.lcStore = lcs
return nil
}
}
4 changes: 3 additions & 1 deletion beacon-chain/blockchain/process_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ func (s *Service) postBlockProcess(cfg *postBlockProcessConfig) error {
if s.inRegularSync() {
defer s.handleSecondFCUCall(cfg, fcuArgs)
}
defer s.sendLightClientFeeds(cfg)
if features.Get().EnableLightClient && slots.ToEpoch(s.CurrentSlot()) >= params.BeaconConfig().AltairForkEpoch {
defer s.processLightClientUpdates(cfg)
}
defer s.sendStateFeedOnBlock(cfg)
defer reportProcessingTime(startTime)
defer reportAttestationInclusion(cfg.roblock.Block())
Expand Down
121 changes: 58 additions & 63 deletions beacon-chain/blockchain/process_block_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree"
forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/features"
field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
Expand Down Expand Up @@ -114,69 +113,30 @@ func (s *Service) sendStateFeedOnBlock(cfg *postBlockProcessConfig) {
})
}

// sendLightClientFeeds sends the light client feeds when feature flag is enabled.
func (s *Service) sendLightClientFeeds(cfg *postBlockProcessConfig) {
if features.Get().EnableLightClient {
if _, err := s.sendLightClientOptimisticUpdate(cfg.ctx, cfg.roblock, cfg.postState); err != nil {
log.WithError(err).Error("Failed to send light client optimistic update")
}

// Get the finalized checkpoint
finalized := s.ForkChoicer().FinalizedCheckpoint()

// LightClientFinalityUpdate needs super majority
s.tryPublishLightClientFinalityUpdate(cfg.ctx, cfg.roblock, finalized, cfg.postState)
func (s *Service) processLightClientUpdates(cfg *postBlockProcessConfig) {
if err := s.processLightClientOptimisticUpdate(cfg.ctx, cfg.roblock, cfg.postState); err != nil {
log.WithError(err).Error("Failed to process light client optimistic update")
}
if err := s.processLightClientFinalityUpdate(cfg.ctx, cfg.roblock, cfg.postState); err != nil {
log.WithError(err).Error("Failed to process light client finality update")
}
}

func (s *Service) tryPublishLightClientFinalityUpdate(
func (s *Service) processLightClientFinalityUpdate(
ctx context.Context,
signed interfaces.ReadOnlySignedBeaconBlock,
finalized *forkchoicetypes.Checkpoint,
postState state.BeaconState,
) {
if finalized.Epoch <= s.lastPublishedLightClientEpoch {
return
}

config := params.BeaconConfig()
if finalized.Epoch < config.AltairForkEpoch {
return
}

syncAggregate, err := signed.Block().Body().SyncAggregate()
if err != nil || syncAggregate == nil {
return
}

// LightClientFinalityUpdate needs super majority
if syncAggregate.SyncCommitteeBits.Count()*3 < config.SyncCommitteeSize*2 {
return
}

_, err = s.sendLightClientFinalityUpdate(ctx, signed, postState)
if err != nil {
log.WithError(err).Error("Failed to send light client finality update")
} else {
s.lastPublishedLightClientEpoch = finalized.Epoch
}
}

// sendLightClientFinalityUpdate sends a light client finality update notification to the state feed.
func (s *Service) sendLightClientFinalityUpdate(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock,
postState state.BeaconState) (int, error) {
// Get attested state
) error {
attestedRoot := signed.Block().ParentRoot()
attestedBlock, err := s.cfg.BeaconDB.Block(ctx, attestedRoot)
if err != nil {
return 0, errors.Wrap(err, "could not get attested block")
return errors.Wrap(err, "could not get attested block")
}
attestedState, err := s.cfg.StateGen.StateByRoot(ctx, attestedRoot)
if err != nil {
return 0, errors.Wrap(err, "could not get attested state")
return errors.Wrap(err, "could not get attested state")
}

// Get finalized block
var finalizedBlock interfaces.ReadOnlySignedBeaconBlock
finalizedCheckPoint := attestedState.FinalizedCheckpoint()
if finalizedCheckPoint != nil {
Expand All @@ -197,28 +157,51 @@ func (s *Service) sendLightClientFinalityUpdate(ctx context.Context, signed inte
finalizedBlock,
)
if err != nil {
return 0, errors.Wrap(err, "could not create light client update")
return errors.Wrap(err, "could not create light client update")
}

// Send event
return s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
maxActiveParticipants := update.SyncAggregate().SyncCommitteeBits.Len()
numActiveParticipants := update.SyncAggregate().SyncCommitteeBits.Count()
hasSupermajority := numActiveParticipants*3 >= maxActiveParticipants*2

last := s.lcStore.LastLCFinalityUpdate
if last != nil {
// The finalized_header.beacon.slot is greater than that of all previously forwarded finality_updates,
// or it matches the highest previously forwarded slot and also has a sync_aggregate indicating supermajority (> 2/3)
// sync committee participation while the previously forwarded finality_update for that slot did not indicate supermajority
slot := last.FinalizedHeader().Beacon().Slot
lastMaxActiveParticipants := last.SyncAggregate().SyncCommitteeBits.Len()
lastNumActiveParticipants := last.SyncAggregate().SyncCommitteeBits.Count()
lastHasSupermajority := lastNumActiveParticipants*3 >= lastMaxActiveParticipants*2

if update.FinalizedHeader().Beacon().Slot < slot {
return nil
}
if update.FinalizedHeader().Beacon().Slot == slot && (lastHasSupermajority || !hasSupermajority) {
return nil
}
}

s.lcStore.LastLCFinalityUpdate = update

s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.LightClientFinalityUpdate,
Data: update,
}), nil
})

return nil
}

// sendLightClientOptimisticUpdate sends a light client optimistic update notification to the state feed.
func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock,
postState state.BeaconState) (int, error) {
// Get attested state
func (s *Service) processLightClientOptimisticUpdate(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock,
postState state.BeaconState) error {
attestedRoot := signed.Block().ParentRoot()
attestedBlock, err := s.cfg.BeaconDB.Block(ctx, attestedRoot)
if err != nil {
return 0, errors.Wrap(err, "could not get attested block")
return errors.Wrap(err, "could not get attested block")
}
attestedState, err := s.cfg.StateGen.StateByRoot(ctx, attestedRoot)
if err != nil {
return 0, errors.Wrap(err, "could not get attested state")
return errors.Wrap(err, "could not get attested state")
}

update, err := lightclient.NewLightClientOptimisticUpdateFromBeaconState(
Expand All @@ -230,13 +213,25 @@ func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed in
attestedBlock,
)
if err != nil {
return 0, errors.Wrap(err, "could not create light client update")
return errors.Wrap(err, "could not create light client update")
}

return s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
last := s.lcStore.LastLCOptimisticUpdate
if last != nil {
// The attested_header.beacon.slot is greater than that of all previously forwarded optimistic_updates
if update.AttestedHeader().Beacon().Slot <= last.AttestedHeader().Beacon().Slot {
return nil
}
}

s.lcStore.LastLCOptimisticUpdate = update

s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.LightClientOptimisticUpdate,
Data: update,
}), nil
})

return nil
}

// updateCachesPostBlockProcessing updates the next slot cache and handles the epoch
Expand Down
40 changes: 20 additions & 20 deletions beacon-chain/blockchain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
f "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice"
forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types"
light_client "github.com/prysmaticlabs/prysm/v5/beacon-chain/light-client"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/blstoexec"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/slashings"
Expand All @@ -38,7 +39,6 @@ import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
Expand All @@ -49,25 +49,25 @@ import (
// Service represents a service that handles the internal
// logic of managing the full PoS beacon chain.
type Service struct {
cfg *config
ctx context.Context
cancel context.CancelFunc
genesisTime time.Time
head *head
headLock sync.RWMutex
originBlockRoot [32]byte // genesis root, or weak subjectivity checkpoint root, depending on how the node is initialized
boundaryRoots [][32]byte
checkpointStateCache *cache.CheckpointStateCache
initSyncBlocks map[[32]byte]interfaces.ReadOnlySignedBeaconBlock
initSyncBlocksLock sync.RWMutex
wsVerifier *WeakSubjectivityVerifier
clockSetter startup.ClockSetter
clockWaiter startup.ClockWaiter
syncComplete chan struct{}
blobNotifiers *blobNotifierMap
blockBeingSynced *currentlySyncingBlock
blobStorage *filesystem.BlobStorage
lastPublishedLightClientEpoch primitives.Epoch
cfg *config
ctx context.Context
cancel context.CancelFunc
genesisTime time.Time
head *head
headLock sync.RWMutex
originBlockRoot [32]byte // genesis root, or weak subjectivity checkpoint root, depending on how the node is initialized
boundaryRoots [][32]byte
checkpointStateCache *cache.CheckpointStateCache
initSyncBlocks map[[32]byte]interfaces.ReadOnlySignedBeaconBlock
initSyncBlocksLock sync.RWMutex
wsVerifier *WeakSubjectivityVerifier
clockSetter startup.ClockSetter
clockWaiter startup.ClockWaiter
syncComplete chan struct{}
blobNotifiers *blobNotifierMap
blockBeingSynced *currentlySyncingBlock
blobStorage *filesystem.BlobStorage
lcStore *light_client.Store
}

// config options for the service.
Expand Down
9 changes: 9 additions & 0 deletions beacon-chain/light-client/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("@prysm//tools/go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = ["store.go"],
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/light-client",
visibility = ["//visibility:public"],
deps = ["//consensus-types/interfaces:go_default_library"],
)
12 changes: 12 additions & 0 deletions beacon-chain/light-client/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package light_client

import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
)

type Store struct {
// lcFinalityUpdateLock sync.Mutex
LastLCFinalityUpdate interfaces.LightClientFinalityUpdate
// lcOptimisticUpdateLock sync.Mutex
LastLCOptimisticUpdate interfaces.LightClientOptimisticUpdate
}
1 change: 1 addition & 0 deletions beacon-chain/node/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ go_library(
"//beacon-chain/execution:go_default_library",
"//beacon-chain/forkchoice:go_default_library",
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
"//beacon-chain/light-client:go_default_library",
"//beacon-chain/monitor:go_default_library",
"//beacon-chain/node/registration:go_default_library",
"//beacon-chain/operations/attestations:go_default_library",
Expand Down
5 changes: 5 additions & 0 deletions beacon-chain/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice"
doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree"
light_client "github.com/prysmaticlabs/prysm/v5/beacon-chain/light-client"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/monitor"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/node/registration"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
Expand Down Expand Up @@ -121,6 +122,7 @@ type BeaconNode struct {
BlobStorageOptions []filesystem.BlobStorageOption
verifyInitWaiter *verification.InitializerWaiter
syncChecker *initialsync.SyncChecker
lcStore *light_client.Store
}

// New creates a new node instance, sets up configuration options, and registers
Expand Down Expand Up @@ -157,6 +159,7 @@ func New(cliCtx *cli.Context, cancel context.CancelFunc, opts ...Option) (*Beaco
serviceFlagOpts: &serviceFlagOpts{},
initialSyncComplete: make(chan struct{}),
syncChecker: &initialsync.SyncChecker{},
lcStore: &light_client.Store{},
}

for _, opt := range opts {
Expand Down Expand Up @@ -763,6 +766,7 @@ func (b *BeaconNode) registerBlockchainService(fc forkchoice.ForkChoicer, gs *st
blockchain.WithTrackedValidatorsCache(b.trackedValidatorsCache),
blockchain.WithPayloadIDCache(b.payloadIDCache),
blockchain.WithSyncChecker(b.syncChecker),
blockchain.WithLightClientStore(b.lcStore),
)

blockchainService, err := blockchain.NewService(b.ctx, opts...)
Expand Down Expand Up @@ -846,6 +850,7 @@ func (b *BeaconNode) registerSyncService(initialSyncComplete chan struct{}, bFil
regularsync.WithBlobStorage(b.BlobStorage),
regularsync.WithVerifierWaiter(b.verifyInitWaiter),
regularsync.WithAvailableBlocker(bFillStore),
regularsync.WithLightClientStore(b.lcStore),
)
return b.services.RegisterService(rs)
}
Expand Down
12 changes: 6 additions & 6 deletions beacon-chain/p2p/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ func (r LightClientBootstrapReq) UnmarshalSSZ(buf []byte) error {

// LightClientUpdatesByRangeReq specifies the block by roots request type.
type LightClientUpdatesByRangeReq struct {
startPeriod uint64
count uint64
StartPeriod uint64
Count uint64
}

// MarshalSSZTo marshals the light client updates by range request with the provided byte slice.
Expand All @@ -266,8 +266,8 @@ func (r *LightClientUpdatesByRangeReq) MarshalSSZTo(dst []byte) ([]byte, error)
// MarshalSSZ Marshals the light client updates by range request type into the serialized object.
func (r *LightClientUpdatesByRangeReq) MarshalSSZ() ([]byte, error) {
buf := make([]byte, 0, r.SizeSSZ())
binary.LittleEndian.AppendUint64(buf, r.startPeriod)
binary.LittleEndian.AppendUint64(buf, r.count)
binary.LittleEndian.AppendUint64(buf, r.StartPeriod)
binary.LittleEndian.AppendUint64(buf, r.Count)
return buf, nil
}

Expand All @@ -283,7 +283,7 @@ func (r *LightClientUpdatesByRangeReq) UnmarshalSSZ(buf []byte) error {
if bufLen != lightClientUpdatesByRangeReqLength {
return errors.Errorf("expected buffer with length of %d but received length %d", lightClientUpdatesByRangeReqLength, bufLen)
}
r.startPeriod = binary.LittleEndian.Uint64(buf[0:8])
r.count = binary.LittleEndian.Uint64(buf[8:16])
r.StartPeriod = binary.LittleEndian.Uint64(buf[0:8])
r.Count = binary.LittleEndian.Uint64(buf[8:16])
return nil
}
Loading

0 comments on commit 1efdb38

Please sign in to comment.