feat: implement `is_better_update` for light client (#14186)

* feat: implement ``is_better_update`` for light client

* replace ``!=`` with ``!reflect.DeepEqual``

* chore: import constant instead of redeclaring and some minor fixes

* feat: add test for ``newHasSupermajority != oldHasSupermajority``

* chore: capitalise first letter of function names

* refactor: rewrite test setups in a more readable manner

* two test cases

* feat: add tests for ``IsBetterUpdate``

* refactor: remove double import

* wording fix 1

Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>

* wording fix 2

Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>

* minor fixes

* fix: change function names to lowercase and fix dependencies

---------

Co-authored-by: rkapka <radoslaw.kapka@gmail.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
Rupam Dey
2024-07-24 00:46:53 +05:30
committed by GitHub
parent b108d5bf54
commit cd8907f76c
5 changed files with 528 additions and 5 deletions

View File

@@ -16,7 +16,7 @@ import (
)
const (
finalityBranchNumOfLeaves = 6
FinalityBranchNumOfLeaves = 6
)
// CreateLightClientFinalityUpdate - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_finality_update
@@ -215,8 +215,8 @@ func NewLightClientFinalityUpdateFromBeaconState(
BodyRoot: make([]byte, 32),
}
finalityBranch = make([][]byte, finalityBranchNumOfLeaves)
for i := 0; i < finalityBranchNumOfLeaves; i++ {
finalityBranch = make([][]byte, FinalityBranchNumOfLeaves)
for i := 0; i < FinalityBranchNumOfLeaves; i++ {
finalityBranch[i] = make([]byte, 32)
}
}

View File

@@ -153,7 +153,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) {
require.DeepSSZEqual(t, zeroHash, update.FinalizedHeader.ParentRoot, "Finalized header parent root is not zero")
require.DeepSSZEqual(t, zeroHash, update.FinalizedHeader.StateRoot, "Finalized header state root is not zero")
require.DeepSSZEqual(t, zeroHash, update.FinalizedHeader.BodyRoot, "Finalized header body root is not zero")
require.Equal(t, finalityBranchNumOfLeaves, len(update.FinalityBranch), "Invalid finality branch leaves")
require.Equal(t, FinalityBranchNumOfLeaves, len(update.FinalityBranch), "Invalid finality branch leaves")
for _, leaf := range update.FinalityBranch {
require.DeepSSZEqual(t, zeroHash, leaf, "Leaf is not zero")
}

View File

@@ -34,20 +34,28 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["handlers_test.go"],
srcs = [
"handlers_test.go",
"helpers_test.go",
],
embed = [":go_default_library"],
deps = [
"//api/server/structs:go_default_library",
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",

View File

@@ -3,6 +3,7 @@ package lightclient
import (
"context"
"fmt"
"reflect"
"strconv"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -311,3 +312,64 @@ func newLightClientUpdateToJSON(input *v2.LightClientUpdate) *structs.LightClien
SignatureSlot: strconv.FormatUint(uint64(input.SignatureSlot), 10),
}
}
func IsSyncCommitteeUpdate(update *v2.LightClientUpdate) bool {
nextSyncCommitteeBranch := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth)
return !reflect.DeepEqual(update.NextSyncCommitteeBranch, nextSyncCommitteeBranch)
}
func IsFinalityUpdate(update *v2.LightClientUpdate) bool {
finalityBranch := make([][]byte, blockchain.FinalityBranchNumOfLeaves)
return !reflect.DeepEqual(update.FinalityBranch, finalityBranch)
}
func IsBetterUpdate(newUpdate, oldUpdate *v2.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.SyncCommitteePeriod(slots.ToEpoch(newUpdate.FinalizedHeader.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(newUpdate.AttestedHeader.Slot))
oldHasSyncCommitteeFinality := slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.FinalizedHeader.Slot)) == slots.SyncCommitteePeriod(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
}

View File

@@ -0,0 +1,453 @@
package lightclient
import (
"testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
)
// When the update has relevant sync committee
func createNonEmptySyncCommitteeBranch() [][]byte {
res := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth)
res[0] = []byte("xyz")
return res
}
// When the update has finality
func createNonEmptyFinalityBranch() [][]byte {
res := make([][]byte, blockchain.FinalityBranchNumOfLeaves)
res[0] = []byte("xyz")
return res
}
func TestIsBetterUpdate(t *testing.T) {
testCases := []struct {
name string
oldUpdate *ethpbv2.LightClientUpdate
newUpdate *ethpbv2.LightClientUpdate
expectedResult bool
}{
{
name: "new has supermajority but old doesn't",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1]
},
},
expectedResult: true,
},
{
name: "old has supermajority but new doesn't",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1]
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
},
},
expectedResult: false,
},
{
name: "new doesn't have supermajority and newNumActiveParticipants is greater than oldNumActiveParticipants",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
},
},
expectedResult: true,
},
{
name: "new doesn't have supermajority and newNumActiveParticipants is lesser than oldNumActiveParticipants",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
},
expectedResult: false,
},
{
name: "new has relevant sync committee but old doesn't",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: make([][]byte, fieldparams.NextSyncCommitteeBranchDepth),
SignatureSlot: 9999,
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000001,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 1000000,
},
expectedResult: true,
},
{
name: "old has relevant sync committee but new doesn't",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000001,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 1000000,
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: make([][]byte, fieldparams.NextSyncCommitteeBranchDepth),
SignatureSlot: 9999,
},
expectedResult: false,
},
{
name: "new has finality but old doesn't",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: make([][]byte, blockchain.FinalityBranchNumOfLeaves),
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
},
expectedResult: true,
},
{
name: "old has finality but new doesn't",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: make([][]byte, blockchain.FinalityBranchNumOfLeaves),
},
expectedResult: false,
},
{
name: "new has finality and sync committee finality both but old doesn't have sync committee finality",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 999999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 999999,
},
},
expectedResult: true,
},
{
name: "new has finality but doesn't have sync committee finality and old has sync committee finality",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 999999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 999999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
expectedResult: false,
},
{
name: "new has more active participants than old",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
expectedResult: true,
},
{
name: "new has less active participants than old",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
expectedResult: false,
},
{
name: "new's attested header's slot is lesser than old's attested header's slot",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 999999,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
expectedResult: true,
},
{
name: "new's attested header's slot is greater than old's attested header's slot",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 999999,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
expectedResult: false,
},
{
name: "none of the above conditions are met and new signature's slot is lesser than old signature's slot",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9998,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
expectedResult: true,
},
{
name: "none of the above conditions are met and new signature's slot is greater than old signature's slot",
oldUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9998,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
},
AttestedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 1000000,
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: createNonEmptyFinalityBranch(),
FinalizedHeader: &ethpbv1.BeaconBlockHeader{
Slot: 9999,
},
},
expectedResult: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
assert.Equal(t, testCase.expectedResult, IsBetterUpdate(testCase.newUpdate, testCase.oldUpdate))
})
}
}