-
Notifications
You must be signed in to change notification settings - Fork 988
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement is_better_update
for light client
#14186
Changes from 1 commit
382e5c1
1829feb
59ce8d9
4aa16ee
b71f03c
7d9a99c
3e1bf3b
9829356
6e9cbcb
f7036ec
b103007
187d390
a31c8f7
d57fb0b
022f56b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
is_better_update
for light client
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,11 +13,16 @@ import ( | |
"github.com/prysmaticlabs/prysm/v5/config/params" | ||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" | ||
v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" | ||
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" | ||
v2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" | ||
"github.com/prysmaticlabs/prysm/v5/proto/migration" | ||
"github.com/prysmaticlabs/prysm/v5/time/slots" | ||
) | ||
|
||
const ( | ||
finalityBranchNumOfLeaves = 6 | ||
) | ||
|
||
// createLightClientBootstrap - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_bootstrap | ||
// def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These specs are needed for all the four functions. |
||
// | ||
|
@@ -311,3 +316,74 @@ func newLightClientUpdateToJSON(input *v2.LightClientUpdate) *structs.LightClien | |
SignatureSlot: strconv.FormatUint(uint64(input.SignatureSlot), 10), | ||
} | ||
} | ||
|
||
func isSyncCommitteeUpdate(update *ethpbv2.LightClientUpdate) bool { | ||
nextSyncCommitteeBranch := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth) | ||
return update.NextSyncCommitteeBranch != nextSyncCommitteeBranch | ||
rupam-04 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
func isFinalityUpdate(update *ethpbv2.LightClientUpdate) bool { | ||
finalityBranch := make([][]byte, finalityBranchNumOfLeaves) | ||
return update.FinalityBranch != finalityBranch | ||
rupam-04 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
func isBetterUpdate(newUpdate, oldUpdate *ethpbv2.LightClientUpdate) bool { | ||
maxActiveParticipants := newUpdate.SyncAggregate.SyncCommitteeBits.Len() | ||
newNumActiveParticipants := uint64(0) | ||
for i := uint64(0); i < maxActiveParticipants; i++ { | ||
if newUpdate.SyncAggregate.SyncCommitteeBits.BitAt(i) { | ||
newNumActiveParticipants += 1 | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
oldNumActiveParticipants := uint64(0) | ||
for i := uint64(0); i < oldUpdate.SyncAggregate.SyncCommitteeBits.Len(); i++ { | ||
if oldUpdate.SyncAggregate.SyncCommitteeBits.BitAt(i) { | ||
oldNumActiveParticipants += 1 | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
newHasSupermajority := newNumActiveParticipants*3 >= maxActiveParticipants*2 | ||
oldHasSupermajority := oldNumActiveParticipants*3 >= maxActiveParticipants*2 | ||
|
||
if newHasSupermajority != oldHasSupermajority { | ||
return newHasSupermajority | ||
} | ||
if !newHasSupermajority && newNumActiveParticipants != oldNumActiveParticipants { | ||
return newNumActiveParticipants > oldNumActiveParticipants | ||
} | ||
|
||
// Compare presence of relevant sync committee | ||
newHasRelevantSyncCommittee := isSyncCommitteeUpdate(newUpdate) && (slots.ToEpoch(newUpdate.AttestedHeader.Slot) == slots.ToEpoch(newUpdate.SignatureSlot)) | ||
oldHasRelevantSyncCommittee := isSyncCommitteeUpdate(oldUpdate) && (slots.ToEpoch(oldUpdate.AttestedHeader.Slot) == slots.ToEpoch(oldUpdate.SignatureSlot)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From what I saw the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comparing epochs like this won't work because the two compared epochs don't have to be equal. It is enough that they are from the same sync committee period. You should use |
||
|
||
if newHasRelevantSyncCommittee != oldHasRelevantSyncCommittee { | ||
return newHasRelevantSyncCommittee | ||
} | ||
|
||
// Compare indication of any finality | ||
newHasFinality := isFinalityUpdate(newUpdate) | ||
oldHasFinality := isFinalityUpdate(oldUpdate) | ||
if newHasFinality != oldHasFinality { | ||
return newHasFinality | ||
} | ||
|
||
// Compare sync committee finality | ||
if newHasFinality { | ||
newHasSyncCommitteeFinality := slots.ToEpoch(newUpdate.FinalizedHeader.Slot) == slots.ToEpoch(newUpdate.AttestedHeader.Slot) | ||
oldHasSyncCommitteeFinality := slots.ToEpoch(oldUpdate.FinalizedHeader.Slot) == slots.ToEpoch(oldUpdate.AttestedHeader.Slot) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above |
||
|
||
if newHasSyncCommitteeFinality != oldHasSyncCommitteeFinality { | ||
return newHasSyncCommitteeFinality | ||
} | ||
} | ||
|
||
// Tiebreaker 1: Sync committee participation beyond supermajority | ||
if newNumActiveParticipants != oldNumActiveParticipants { | ||
return newNumActiveParticipants > oldNumActiveParticipants | ||
} | ||
|
||
// Tiebreaker 2: Prefer older data (fewer changes to best) | ||
if newUpdate.AttestedHeader.Slot != oldUpdate.AttestedHeader.Slot { | ||
return newUpdate.AttestedHeader.Slot < oldUpdate.AttestedHeader.Slot | ||
} | ||
return newUpdate.SignatureSlot < oldUpdate.SignatureSlot | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same constant is defined in
beacon-chain/blockchain/lightclient.go
. We should not duplicate constants because then we have to maintain the correct value in more than one place. The correct way is to export the existing one by making it upper-case, and using it in this package.