# Week 5 Hi everyone, this week I wasn't able to attend EthCC at Brussels due to Visa issues and I had a few blockers in my PRs which only Mr. Radek would be able to solve. Due to him being present at EthCC, he wasn't able to reply much except a few things here and there. One was to add relevant tests to the ``is_better_update`` PR I opened last week. ## Implementation and Testing of the ``is_better_update`` function Reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#is_better_update My implementation in Prysm: ```go func IsBetterUpdate(newUpdate, oldUpdate *ethpbv2.LightClientUpdate) bool { maxActiveParticipants := newUpdate.SyncAggregate.SyncCommitteeBits.Len() newNumActiveParticipants := newUpdate.SyncAggregate.SyncCommitteeBits.Count() oldNumActiveParticipants := oldUpdate.SyncAggregate.SyncCommitteeBits.Count() 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.SyncCommitteePeriod(slots.ToEpoch(newUpdate.AttestedHeader.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(newUpdate.SignatureSlot))) oldHasRelevantSyncCommittee := IsSyncCommitteeUpdate(oldUpdate) && (slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.AttestedHeader.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.SignatureSlot))) 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) 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 } ``` This implementation requires 2 other much smaller helper functions `is_sync_committee_update` and `is_finality_update` which I had to implement too. Reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#is_sync_committee_update ```go func IsSyncCommitteeUpdate(update *ethpbv2.LightClientUpdate) bool { nextSyncCommitteeBranch := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth) return !reflect.DeepEqual(update.NextSyncCommitteeBranch, nextSyncCommitteeBranch) } ``` Reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#is_finality_update ```go func IsFinalityUpdate(update *ethpbv2.LightClientUpdate) bool { finalityBranch := make([][]byte, blockchain.FinalityBranchNumOfLeaves) return !reflect.DeepEqual(update.FinalityBranch, finalityBranch) } ``` Now coming to the implementation of `is_better_update` , each return statement inside an `if` requires 2 tests, one which satisfies the condition of the `if` statement and another that doesn't. I have setup the functions required to run the tests and have written one test which satisfies the condition of the following `if` statement: ```go if newHasSupermajority != oldHasSupermajority { return newHasSupermajority } ``` Right now, there are some issues in the test as it is failing. Mr Radek is yet to review it. Once I figure out the fix I'll be updating the code here too. Also I didn't link the functions used to setup the test as it would make this document too big but you can find them [here](https://github.com/rupam-04/prysm/blob/7d9a99c83f5020adbf6a9ea032d0ead53cff9703/beacon-chain/rpc/eth/light-client/helpers_test.go#L19-#L260).