Skip to content

Commit

Permalink
Caplin: process new attesting indicies before block comes in to avoid…
Browse files Browse the repository at this point in the history
… occasiona Reorg (#10085)
  • Loading branch information
Giulio2002 authored Apr 29, 2024
1 parent b766820 commit dee2191
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 57 deletions.
18 changes: 15 additions & 3 deletions cl/phase1/forkchoice/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ type ForkChoiceStorageReader interface {
JustifiedCheckpoint() solid.Checkpoint
JustifiedSlot() uint64
ProposerBoostRoot() common.Hash
GetStateAtBlockRoot(blockRoot libcommon.Hash, alwaysCopy bool) (*state.CachingBeaconState, error)
GetFinalityCheckpoints(blockRoot libcommon.Hash) (bool, solid.Checkpoint, solid.Checkpoint, solid.Checkpoint)
GetStateAtBlockRoot(
blockRoot libcommon.Hash,
alwaysCopy bool,
) (*state.CachingBeaconState, error)
GetFinalityCheckpoints(
blockRoot libcommon.Hash,
) (bool, solid.Checkpoint, solid.Checkpoint, solid.Checkpoint)
GetSyncCommittees(period uint64) (*solid.SyncCommittee, *solid.SyncCommittee, bool)
GetBeaconCommitee(slot, committeeIndex uint64) ([]uint64, error)
Slot() uint64
Expand Down Expand Up @@ -60,8 +65,15 @@ type ForkChoiceStorageReader interface {
type ForkChoiceStorageWriter interface {
OnAttestation(attestation *solid.Attestation, fromBlock, insert bool) error
OnAttesterSlashing(attesterSlashing *cltypes.AttesterSlashing, test bool) error
OnBlock(ctx context.Context, block *cltypes.SignedBeaconBlock, newPayload bool, fullValidation bool, checkDataAvaibility bool) error
OnBlock(
ctx context.Context,
block *cltypes.SignedBeaconBlock,
newPayload bool,
fullValidation bool,
checkDataAvaibility bool,
) error
AddPreverifiedBlobSidecar(blobSidecar *cltypes.BlobSidecar) error
OnTick(time uint64)
SetSynced(synced bool)
ProcessAttestingIndicies(attestation *solid.Attestation, attestionIndicies []uint64)
}
82 changes: 65 additions & 17 deletions cl/phase1/forkchoice/mock_services/forkchoice_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,17 +172,27 @@ func (f *ForkChoiceStorageMock) ProposerBoostRoot() common.Hash {
return f.ProposerBoostRootVal
}

func (f *ForkChoiceStorageMock) GetStateAtBlockRoot(blockRoot common.Hash, alwaysCopy bool) (*state.CachingBeaconState, error) {
func (f *ForkChoiceStorageMock) GetStateAtBlockRoot(
blockRoot common.Hash,
alwaysCopy bool,
) (*state.CachingBeaconState, error) {
return f.StateAtBlockRootVal[blockRoot], nil
}

func (f *ForkChoiceStorageMock) GetFinalityCheckpoints(blockRoot common.Hash) (bool, solid.Checkpoint, solid.Checkpoint, solid.Checkpoint) {
oneNil := f.GetFinalityCheckpointsVal[blockRoot][0] != nil && f.GetFinalityCheckpointsVal[blockRoot][1] != nil && f.GetFinalityCheckpointsVal[blockRoot][2] != nil
func (f *ForkChoiceStorageMock) GetFinalityCheckpoints(
blockRoot common.Hash,
) (bool, solid.Checkpoint, solid.Checkpoint, solid.Checkpoint) {
oneNil := f.GetFinalityCheckpointsVal[blockRoot][0] != nil &&
f.GetFinalityCheckpointsVal[blockRoot][1] != nil &&
f.GetFinalityCheckpointsVal[blockRoot][2] != nil
return oneNil, f.GetFinalityCheckpointsVal[blockRoot][0], f.GetFinalityCheckpointsVal[blockRoot][1], f.GetFinalityCheckpointsVal[blockRoot][2]
}

func (f *ForkChoiceStorageMock) GetSyncCommittees(period uint64) (*solid.SyncCommittee, *solid.SyncCommittee, bool) {
return f.GetSyncCommitteesVal[period][0], f.GetSyncCommitteesVal[period][1], f.GetSyncCommitteesVal[period][0] != nil && f.GetSyncCommitteesVal[period][1] != nil
func (f *ForkChoiceStorageMock) GetSyncCommittees(
period uint64,
) (*solid.SyncCommittee, *solid.SyncCommittee, bool) {
return f.GetSyncCommitteesVal[period][0], f.GetSyncCommitteesVal[period][1], f.GetSyncCommitteesVal[period][0] != nil &&
f.GetSyncCommitteesVal[period][1] != nil
}

func (f *ForkChoiceStorageMock) GetBeaconCommitee(slot, committeeIndex uint64) ([]uint64, error) {
Expand All @@ -200,17 +210,32 @@ func (f *ForkChoiceStorageMock) Time() uint64 {
return f.TimeVal
}

func (f *ForkChoiceStorageMock) OnAttestation(attestation *solid.Attestation, fromBlock, insert bool) error {
func (f *ForkChoiceStorageMock) OnAttestation(
attestation *solid.Attestation,
fromBlock, insert bool,
) error {
f.Pool.AttestationsPool.Insert(attestation.Signature(), attestation)
return nil
}

func (f *ForkChoiceStorageMock) OnAttesterSlashing(attesterSlashing *cltypes.AttesterSlashing, test bool) error {
f.Pool.AttesterSlashingsPool.Insert(pool.ComputeKeyForAttesterSlashing(attesterSlashing), attesterSlashing)
func (f *ForkChoiceStorageMock) OnAttesterSlashing(
attesterSlashing *cltypes.AttesterSlashing,
test bool,
) error {
f.Pool.AttesterSlashingsPool.Insert(
pool.ComputeKeyForAttesterSlashing(attesterSlashing),
attesterSlashing,
)
return nil
}

func (f *ForkChoiceStorageMock) OnBlock(ctx context.Context, block *cltypes.SignedBeaconBlock, newPayload bool, fullValidation bool, checkDataAvaiability bool) error {
func (f *ForkChoiceStorageMock) OnBlock(
ctx context.Context,
block *cltypes.SignedBeaconBlock,
newPayload bool,
fullValidation bool,
checkDataAvaiability bool,
) error {
return nil
}

Expand Down Expand Up @@ -250,43 +275,60 @@ func (f *ForkChoiceStorageMock) SetSynced(synced bool) {
panic("implement me")
}

func (f *ForkChoiceStorageMock) GetLightClientBootstrap(blockRoot common.Hash) (*cltypes.LightClientBootstrap, bool) {
func (f *ForkChoiceStorageMock) GetLightClientBootstrap(
blockRoot common.Hash,
) (*cltypes.LightClientBootstrap, bool) {
return f.LightClientBootstraps[blockRoot], f.LightClientBootstraps[blockRoot] != nil
}

func (f *ForkChoiceStorageMock) NewestLightClientUpdate() *cltypes.LightClientUpdate {
return f.NewestLCUpdate
}

func (f *ForkChoiceStorageMock) GetLightClientUpdate(period uint64) (*cltypes.LightClientUpdate, bool) {
func (f *ForkChoiceStorageMock) GetLightClientUpdate(
period uint64,
) (*cltypes.LightClientUpdate, bool) {
return f.LCUpdates[period], f.LCUpdates[period] != nil
}

func (f *ForkChoiceStorageMock) GetHeader(blockRoot libcommon.Hash) (*cltypes.BeaconBlockHeader, bool) {
func (f *ForkChoiceStorageMock) GetHeader(
blockRoot libcommon.Hash,
) (*cltypes.BeaconBlockHeader, bool) {
return f.Headers[blockRoot], f.Headers[blockRoot] != nil
}

func (f *ForkChoiceStorageMock) GetBalances(blockRoot libcommon.Hash) (solid.Uint64ListSSZ, error) {
panic("implement me")
}

func (f *ForkChoiceStorageMock) GetInactivitiesScores(blockRoot libcommon.Hash) (solid.Uint64ListSSZ, error) {
func (f *ForkChoiceStorageMock) GetInactivitiesScores(
blockRoot libcommon.Hash,
) (solid.Uint64ListSSZ, error) {
panic("implement me")
}

func (f *ForkChoiceStorageMock) GetPreviousPartecipationIndicies(blockRoot libcommon.Hash) (*solid.BitList, error) {
func (f *ForkChoiceStorageMock) GetPreviousPartecipationIndicies(
blockRoot libcommon.Hash,
) (*solid.BitList, error) {
panic("implement me")
}

func (f *ForkChoiceStorageMock) GetValidatorSet(blockRoot libcommon.Hash) (*solid.ValidatorSet, error) {
func (f *ForkChoiceStorageMock) GetValidatorSet(
blockRoot libcommon.Hash,
) (*solid.ValidatorSet, error) {
panic("implement me")
}

func (f *ForkChoiceStorageMock) GetCurrentPartecipationIndicies(blockRoot libcommon.Hash) (*solid.BitList, error) {
func (f *ForkChoiceStorageMock) GetCurrentPartecipationIndicies(
blockRoot libcommon.Hash,
) (*solid.BitList, error) {
panic("implement me")
}

func (f *ForkChoiceStorageMock) GetPublicKeyForValidator(blockRoot libcommon.Hash, idx uint64) (libcommon.Bytes48, error) {
func (f *ForkChoiceStorageMock) GetPublicKeyForValidator(
blockRoot libcommon.Hash,
idx uint64,
) (libcommon.Bytes48, error) {
panic("implement me")
}

Expand All @@ -301,3 +343,9 @@ func (f *ForkChoiceStorageMock) AddPreverifiedBlobSidecar(msg *cltypes.BlobSidec
func (f *ForkChoiceStorageMock) ValidateOnAttestation(attestation *solid.Attestation) error {
panic("implement me")
}

func (f *ForkChoiceStorageMock) ProcessAttestingIndicies(
attestation *solid.Attestation,
attestionIndicies []uint64,
) {
}
53 changes: 44 additions & 9 deletions cl/phase1/forkchoice/on_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ var (
)

// OnAttestation processes incoming attestations.
func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBlock bool, insert bool) error {
func (f *ForkChoiceStore) OnAttestation(
attestation *solid.Attestation,
fromBlock bool,
insert bool,
) error {
if !f.synced.Load() {
return nil
}
Expand Down Expand Up @@ -42,7 +46,11 @@ func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBloc
target := data.Target()

if headState == nil {
attestationIndicies, err = f.verifyAttestationWithCheckpointState(target, attestation, fromBlock)
attestationIndicies, err = f.verifyAttestationWithCheckpointState(
target,
attestation,
fromBlock,
)
} else {
attestationIndicies, err = f.verifyAttestationWithState(headState, attestation, fromBlock)
}
Expand All @@ -56,7 +64,20 @@ func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBloc
return nil
}

func (f *ForkChoiceStore) verifyAttestationWithCheckpointState(target solid.Checkpoint, attestation *solid.Attestation, fromBlock bool) (attestationIndicies []uint64, err error) {
func (f *ForkChoiceStore) ProcessAttestingIndicies(
attestation *solid.Attestation,
attestionIndicies []uint64,
) {
f.mu.Lock()
defer f.mu.Unlock()
f.processAttestingIndicies(attestation, attestionIndicies)
}

func (f *ForkChoiceStore) verifyAttestationWithCheckpointState(
target solid.Checkpoint,
attestation *solid.Attestation,
fromBlock bool,
) (attestationIndicies []uint64, err error) {
data := attestation.AttestantionData()
targetState, err := f.getCheckpointState(target)
if err != nil {
Expand All @@ -67,7 +88,10 @@ func (f *ForkChoiceStore) verifyAttestationWithCheckpointState(target solid.Chec
return nil, fmt.Errorf("target state does not exist")
}
// Now we need to find the attesting indicies.
attestationIndicies, err = targetState.getAttestingIndicies(&data, attestation.AggregationBits())
attestationIndicies, err = targetState.getAttestingIndicies(
&data,
attestation.AggregationBits(),
)
if err != nil {
return nil, err
}
Expand All @@ -88,7 +112,11 @@ func (f *ForkChoiceStore) verifyAttestationWithCheckpointState(target solid.Chec
return attestationIndicies, nil
}

func (f *ForkChoiceStore) verifyAttestationWithState(s *state.CachingBeaconState, attestation *solid.Attestation, fromBlock bool) (attestationIndicies []uint64, err error) {
func (f *ForkChoiceStore) verifyAttestationWithState(
s *state.CachingBeaconState,
attestation *solid.Attestation,
fromBlock bool,
) (attestationIndicies []uint64, err error) {
data := attestation.AttestantionData()
if err != nil {
return nil, err
Expand Down Expand Up @@ -127,7 +155,8 @@ func (f *ForkChoiceStore) setLatestMessage(index uint64, message LatestMessage)
}

func (f *ForkChoiceStore) getLatestMessage(validatorIndex uint64) (LatestMessage, bool) {
if validatorIndex >= uint64(len(f.latestMessages)) || f.latestMessages[validatorIndex] == (LatestMessage{}) {
if validatorIndex >= uint64(len(f.latestMessages)) ||
f.latestMessages[validatorIndex] == (LatestMessage{}) {
return LatestMessage{}, false
}
return f.latestMessages[validatorIndex], true
Expand Down Expand Up @@ -157,7 +186,10 @@ func (f *ForkChoiceStore) setUnequivocating(validatorIndex uint64) {
f.equivocatingIndicies[index] |= 1 << uint(subIndex)
}

func (f *ForkChoiceStore) processAttestingIndicies(attestation *solid.Attestation, indicies []uint64) {
func (f *ForkChoiceStore) processAttestingIndicies(
attestation *solid.Attestation,
indicies []uint64,
) {
beaconBlockRoot := attestation.AttestantionData().BeaconBlockRoot()
target := attestation.AttestantionData().Target()

Expand All @@ -184,7 +216,8 @@ func (f *ForkChoiceStore) ValidateOnAttestation(attestation *solid.Attestation)
if _, has := f.forkGraph.GetHeader(target.BlockRoot()); !has {
return fmt.Errorf("target root is missing")
}
if blockHeader, has := f.forkGraph.GetHeader(attestation.AttestantionData().BeaconBlockRoot()); !has || blockHeader.Slot > attestation.AttestantionData().Slot() {
if blockHeader, has := f.forkGraph.GetHeader(attestation.AttestantionData().BeaconBlockRoot()); !has ||
blockHeader.Slot > attestation.AttestantionData().Slot() {
return fmt.Errorf("bad attestation data")
}
// LMD vote must be consistent with FFG vote target
Expand All @@ -200,7 +233,9 @@ func (f *ForkChoiceStore) ValidateOnAttestation(attestation *solid.Attestation)
return nil
}

func (f *ForkChoiceStore) validateTargetEpochAgainstCurrentTime(attestation *solid.Attestation) error {
func (f *ForkChoiceStore) validateTargetEpochAgainstCurrentTime(
attestation *solid.Attestation,
) error {
target := attestation.AttestantionData().Target()
// Attestations must be from the current or previous epoch
currentEpoch := f.computeEpochAtSlot(f.Slot())
Expand Down
Loading

0 comments on commit dee2191

Please sign in to comment.