create light-client-updates bucket (#14266)

* create light-client-updates bucket

* Electra committe validation for aggregate and proof (#14317)

* Electra committe validation for aggregate and proof

* review

* update comments

* Refactor get local payload (#14327)

* Refactor get local payload

* Fix go lint: new line

* add lightclient db kv functions

* lightclient db tests

* move blockchain/lightclient.go to core/light-client package

* add comparison check for start and end period

* create testing/utils/lightcilent.go

* lightclient db tests

* fix imports and usages

* fix imports and usages in process_block_helpers

* fix bazel dependencies

* remove unnecessary nil check

* add more tests for lightclient kv functions

* refactor tests

* refactor kv.LightClientUpdates

* fix db to return every update that is available in the requested range

* run gazzele fix

* return empty map in case of empty db

* fix goimports errors

* goimports

* Revert "Auxiliary commit to revert individual files from aa7ce6f37cb6767cf11642b022b2ce59d42ae621"

This reverts commit 33c707f5bd164386449dc14ff27d95ad5f195161.

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: terence <terence@prysmaticlabs.com>
Co-authored-by: rkapka <radoslaw.kapka@gmail.com>
This commit is contained in:
Bastin
2024-08-22 18:00:18 +02:00
committed by GitHub
parent 2fa3547644
commit 022a53f8f2
22 changed files with 1115 additions and 237 deletions

View File

@@ -13,7 +13,6 @@ go_library(
"head.go",
"head_sync_committee_info.go",
"init_sync_process_block.go",
"lightclient.go",
"log.go",
"merge_ascii_art.go",
"metrics.go",
@@ -48,6 +47,7 @@ go_library(
"//beacon-chain/core/feed:go_default_library",
"//beacon-chain/core/feed/state:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/light-client:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/transition:go_default_library",
@@ -84,7 +84,6 @@ go_library(
"//proto/engine/v1:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/migration:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
"//runtime/version:go_default_library",
@@ -117,7 +116,6 @@ go_test(
"head_test.go",
"init_sync_process_block_test.go",
"init_test.go",
"lightclient_test.go",
"log_test.go",
"metrics_test.go",
"mock_test.go",
@@ -174,7 +172,6 @@ go_test(
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//testing/assert:go_default_library",

View File

@@ -1,160 +0,0 @@
package blockchain
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util"
)
type testlc struct {
t *testing.T
ctx context.Context
state state.BeaconState
block interfaces.ReadOnlySignedBeaconBlock
attestedState state.BeaconState
attestedHeader *ethpb.BeaconBlockHeader
}
func newTestLc(t *testing.T) *testlc {
return &testlc{t: t}
}
func (l *testlc) setupTest() *testlc {
ctx := context.Background()
slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
attestedState, err := util.NewBeaconStateCapella()
require.NoError(l.t, err)
err = attestedState.SetSlot(slot)
require.NoError(l.t, err)
parent := util.NewBeaconBlockCapella()
parent.Block.Slot = slot
signedParent, err := blocks.NewSignedBeaconBlock(parent)
require.NoError(l.t, err)
parentHeader, err := signedParent.Header()
require.NoError(l.t, err)
attestedHeader := parentHeader.Header
err = attestedState.SetLatestBlockHeader(attestedHeader)
require.NoError(l.t, err)
attestedStateRoot, err := attestedState.HashTreeRoot(ctx)
require.NoError(l.t, err)
// get a new signed block so the root is updated with the new state root
parent.Block.StateRoot = attestedStateRoot[:]
signedParent, err = blocks.NewSignedBeaconBlock(parent)
require.NoError(l.t, err)
state, err := util.NewBeaconStateCapella()
require.NoError(l.t, err)
err = state.SetSlot(slot)
require.NoError(l.t, err)
parentRoot, err := signedParent.Block().HashTreeRoot()
require.NoError(l.t, err)
block := util.NewBeaconBlockCapella()
block.Block.Slot = slot
block.Block.ParentRoot = parentRoot[:]
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
}
signedBlock, err := blocks.NewSignedBeaconBlock(block)
require.NoError(l.t, err)
h, err := signedBlock.Header()
require.NoError(l.t, err)
err = state.SetLatestBlockHeader(h.Header)
require.NoError(l.t, err)
stateRoot, err := state.HashTreeRoot(ctx)
require.NoError(l.t, err)
// get a new signed block so the root is updated with the new state root
block.Block.StateRoot = stateRoot[:]
signedBlock, err = blocks.NewSignedBeaconBlock(block)
require.NoError(l.t, err)
l.state = state
l.attestedState = attestedState
l.attestedHeader = attestedHeader
l.block = signedBlock
l.ctx = ctx
return l
}
func (l *testlc) checkAttestedHeader(update *ethpbv2.LightClientUpdate) {
require.Equal(l.t, l.attestedHeader.Slot, update.AttestedHeader.Slot, "Attested header slot is not equal")
require.Equal(l.t, l.attestedHeader.ProposerIndex, update.AttestedHeader.ProposerIndex, "Attested header proposer index is not equal")
require.DeepSSZEqual(l.t, l.attestedHeader.ParentRoot, update.AttestedHeader.ParentRoot, "Attested header parent root is not equal")
require.DeepSSZEqual(l.t, l.attestedHeader.BodyRoot, update.AttestedHeader.BodyRoot, "Attested header body root is not equal")
attestedStateRoot, err := l.attestedState.HashTreeRoot(l.ctx)
require.NoError(l.t, err)
require.DeepSSZEqual(l.t, attestedStateRoot[:], update.AttestedHeader.StateRoot, "Attested header state root is not equal")
}
func (l *testlc) checkSyncAggregate(update *ethpbv2.LightClientUpdate) {
syncAggregate, err := l.block.Block().Body().SyncAggregate()
require.NoError(l.t, err)
require.DeepSSZEqual(l.t, syncAggregate.SyncCommitteeBits, update.SyncAggregate.SyncCommitteeBits, "SyncAggregate bits is not equal")
require.DeepSSZEqual(l.t, syncAggregate.SyncCommitteeSignature, update.SyncAggregate.SyncCommitteeSignature, "SyncAggregate signature is not equal")
}
func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) {
l := newTestLc(t).setupTest()
update, err := NewLightClientOptimisticUpdateFromBeaconState(l.ctx, l.state, l.block, l.attestedState)
require.NoError(t, err)
require.NotNil(t, update, "update is nil")
require.Equal(t, l.block.Block().Slot(), update.SignatureSlot, "Signature slot is not equal")
l.checkSyncAggregate(update)
l.checkAttestedHeader(update)
require.Equal(t, (*v1.BeaconBlockHeader)(nil), update.FinalizedHeader, "Finalized header is not nil")
require.DeepSSZEqual(t, ([][]byte)(nil), update.FinalityBranch, "Finality branch is not nil")
}
func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) {
l := newTestLc(t).setupTest()
update, err := NewLightClientFinalityUpdateFromBeaconState(l.ctx, l.state, l.block, l.attestedState, nil)
require.NoError(t, err)
require.NotNil(t, update, "update is nil")
require.Equal(t, l.block.Block().Slot(), update.SignatureSlot, "Signature slot is not equal")
l.checkSyncAggregate(update)
l.checkAttestedHeader(update)
zeroHash := params.BeaconConfig().ZeroHash[:]
require.NotNil(t, update.FinalizedHeader, "Finalized header is nil")
require.Equal(t, primitives.Slot(0), update.FinalizedHeader.Slot, "Finalized header slot is not zero")
require.Equal(t, primitives.ValidatorIndex(0), update.FinalizedHeader.ProposerIndex, "Finalized header proposer index is not zero")
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")
for _, leaf := range update.FinalityBranch {
require.DeepSSZEqual(t, zeroHash, leaf, "Leaf is not zero")
}
}

View File

@@ -5,6 +5,8 @@ import (
"fmt"
"time"
lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed"
@@ -176,7 +178,7 @@ func (s *Service) sendLightClientFinalityUpdate(ctx context.Context, signed inte
}
}
update, err := NewLightClientFinalityUpdateFromBeaconState(
update, err := lightclient.NewLightClientFinalityUpdateFromBeaconState(
ctx,
postState,
signed,
@@ -191,7 +193,7 @@ func (s *Service) sendLightClientFinalityUpdate(ctx context.Context, signed inte
// Return the result
result := &ethpbv2.LightClientFinalityUpdateWithVersion{
Version: ethpbv2.Version(signed.Version()),
Data: CreateLightClientFinalityUpdate(update),
Data: lightclient.CreateLightClientFinalityUpdate(update),
}
// Send event
@@ -211,7 +213,7 @@ func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed in
return 0, errors.Wrap(err, "could not get attested state")
}
update, err := NewLightClientOptimisticUpdateFromBeaconState(
update, err := lightclient.NewLightClientOptimisticUpdateFromBeaconState(
ctx,
postState,
signed,
@@ -225,7 +227,7 @@ func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed in
// Return the result
result := &ethpbv2.LightClientOptimisticUpdateWithVersion{
Version: ethpbv2.Version(signed.Version()),
Data: CreateLightClientOptimisticUpdate(update),
Data: lightclient.CreateLightClientOptimisticUpdate(update),
}
return s.cfg.StateNotifier.StateFeed().Send(&feed.Event{

View File

@@ -0,0 +1,31 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["lightclient.go"],
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state:go_default_library",
"//config/params:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/migration:go_default_library",
"//time/slots:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["lightclient_test.go"],
deps = [
":go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//proto/eth/v1:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
],
)

View File

@@ -1,18 +1,20 @@
package blockchain
package light_client
import (
"bytes"
"context"
"fmt"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
"github.com/prysmaticlabs/prysm/v5/proto/migration"
"github.com/prysmaticlabs/prysm/v5/time/slots"
"context"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
)
const (

View File

@@ -0,0 +1,54 @@
package light_client_test
import (
"testing"
lightClient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util"
v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
)
func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) {
l := util.NewTestLightClient(t).SetupTest()
update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState)
require.NoError(t, err)
require.NotNil(t, update, "update is nil")
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot, "Signature slot is not equal")
l.CheckSyncAggregate(update)
l.CheckAttestedHeader(update)
require.Equal(t, (*v1.BeaconBlockHeader)(nil), update.FinalizedHeader, "Finalized header is not nil")
require.DeepSSZEqual(t, ([][]byte)(nil), update.FinalityBranch, "Finality branch is not nil")
}
func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) {
l := util.NewTestLightClient(t).SetupTest()
update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, nil)
require.NoError(t, err)
require.NotNil(t, update, "update is nil")
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot, "Signature slot is not equal")
l.CheckSyncAggregate(update)
l.CheckAttestedHeader(update)
zeroHash := params.BeaconConfig().ZeroHash[:]
require.NotNil(t, update.FinalizedHeader, "Finalized header is nil")
require.Equal(t, primitives.Slot(0), update.FinalizedHeader.Slot, "Finalized header slot is not zero")
require.Equal(t, primitives.ValidatorIndex(0), update.FinalizedHeader.ProposerIndex, "Finalized header proposer index is not zero")
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, lightClient.FinalityBranchNumOfLeaves, len(update.FinalityBranch), "Invalid finality branch leaves")
for _, leaf := range update.FinalityBranch {
require.DeepSSZEqual(t, zeroHash, leaf, "Leaf is not zero")
}
}

View File

@@ -18,6 +18,7 @@ go_library(
"//consensus-types/primitives:go_default_library",
"//monitoring/backup:go_default_library",
"//proto/dbval:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
],

View File

@@ -7,6 +7,8 @@ import (
"context"
"io"
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filters"
slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types"
@@ -56,6 +58,9 @@ type ReadOnlyDatabase interface {
// Fee recipients operations.
FeeRecipientByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (common.Address, error)
RegistrationByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (*ethpb.ValidatorRegistrationV1, error)
// light client operations
LightClientUpdates(ctx context.Context, startPeriod, endPeriod uint64) (map[uint64]*ethpbv2.LightClientUpdateWithVersion, error)
LightClientUpdate(ctx context.Context, period uint64) (*ethpbv2.LightClientUpdateWithVersion, error)
// origin checkpoint sync support
OriginCheckpointBlockRoot(ctx context.Context) ([32]byte, error)
@@ -92,6 +97,8 @@ type NoHeadAccessDatabase interface {
// Fee recipients operations.
SaveFeeRecipientsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, addrs []common.Address) error
SaveRegistrationsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, regs []*ethpb.ValidatorRegistrationV1) error
// light client operations
SaveLightClientUpdate(ctx context.Context, period uint64, update *ethpbv2.LightClientUpdateWithVersion) error
CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint primitives.Slot) error
}

View File

@@ -16,6 +16,7 @@ go_library(
"genesis.go",
"key.go",
"kv.go",
"lightclient.go",
"log.go",
"migration.go",
"migration_archived_index.go",
@@ -51,6 +52,7 @@ go_library(
"//monitoring/progress:go_default_library",
"//monitoring/tracing:go_default_library",
"//proto/dbval:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//time:go_default_library",
@@ -87,6 +89,7 @@ go_test(
"genesis_test.go",
"init_test.go",
"kv_test.go",
"lightclient_test.go",
"migration_archived_index_test.go",
"migration_block_slot_index_test.go",
"migration_state_validators_test.go",
@@ -113,6 +116,7 @@ go_test(
"//encoding/bytesutil:go_default_library",
"//proto/dbval:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/testing:go_default_library",
"//runtime/version:go_default_library",

View File

@@ -107,6 +107,7 @@ var Buckets = [][]byte{
powchainBucket,
stateSummaryBucket,
stateValidatorsBucket,
lightClientUpdatesBucket,
// Indices buckets.
blockSlotIndicesBucket,
stateSlotIndicesBucket,

View File

@@ -0,0 +1,79 @@
package kv
import (
"context"
"encoding/binary"
"fmt"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
bolt "go.etcd.io/bbolt"
"go.opencensus.io/trace"
)
func (s *Store) SaveLightClientUpdate(ctx context.Context, period uint64, update *ethpbv2.LightClientUpdateWithVersion) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.saveLightClientUpdate")
defer span.End()
return s.db.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket(lightClientUpdatesBucket)
updateMarshalled, err := encode(ctx, update)
if err != nil {
return err
}
return bkt.Put(bytesutil.Uint64ToBytesBigEndian(period), updateMarshalled)
})
}
func (s *Store) LightClientUpdates(ctx context.Context, startPeriod, endPeriod uint64) (map[uint64]*ethpbv2.LightClientUpdateWithVersion, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.LightClientUpdates")
defer span.End()
if startPeriod > endPeriod {
return nil, fmt.Errorf("start period %d is greater than end period %d", startPeriod, endPeriod)
}
updates := make(map[uint64]*ethpbv2.LightClientUpdateWithVersion)
err := s.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(lightClientUpdatesBucket)
c := bkt.Cursor()
firstPeriodInDb, _ := c.First()
if firstPeriodInDb == nil {
return nil
}
for k, v := c.Seek(bytesutil.Uint64ToBytesBigEndian(startPeriod)); k != nil && binary.BigEndian.Uint64(k) <= endPeriod; k, v = c.Next() {
currentPeriod := binary.BigEndian.Uint64(k)
var update ethpbv2.LightClientUpdateWithVersion
if err := decode(ctx, v, &update); err != nil {
return err
}
updates[currentPeriod] = &update
}
return nil
})
if err != nil {
return nil, err
}
return updates, err
}
func (s *Store) LightClientUpdate(ctx context.Context, period uint64) (*ethpbv2.LightClientUpdateWithVersion, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.LightClientUpdate")
defer span.End()
var update ethpbv2.LightClientUpdateWithVersion
err := s.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(lightClientUpdatesBucket)
updateBytes := bkt.Get(bytesutil.Uint64ToBytesBigEndian(period))
if updateBytes == nil {
return nil
}
return decode(ctx, updateBytes, &update)
})
return &update, err
}

View File

@@ -0,0 +1,648 @@
package kv
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
"github.com/prysmaticlabs/prysm/v5/testing/require"
)
func TestStore_LightclientUpdate_CanSaveRetrieve(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
update := &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
}
period := uint64(1)
err := db.SaveLightClientUpdate(ctx, period, &ethpbv2.LightClientUpdateWithVersion{
Version: 1,
Data: update,
})
require.NoError(t, err)
// Retrieve the update
retrievedUpdate, err := db.LightClientUpdate(ctx, period)
require.NoError(t, err)
require.Equal(t, update.SignatureSlot, retrievedUpdate.Data.SignatureSlot, "retrieved update does not match saved update")
}
func TestStore_LightclientUpdates_canRetrieveRange(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
updates := []*ethpbv2.LightClientUpdateWithVersion{
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 8,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 9,
},
},
}
for i, update := range updates {
err := db.SaveLightClientUpdate(ctx, uint64(i+1), update)
require.NoError(t, err)
}
// Retrieve the updates
retrievedUpdatesMap, err := db.LightClientUpdates(ctx, 1, 3)
require.NoError(t, err)
require.Equal(t, len(updates), len(retrievedUpdatesMap), "retrieved updates do not match saved updates")
for i, update := range updates {
require.Equal(t, update.Data.SignatureSlot, retrievedUpdatesMap[uint64(i+1)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_EndPeriodSmallerThanStartPeriod(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
updates := []*ethpbv2.LightClientUpdateWithVersion{
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 8,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 9,
},
},
}
for i, update := range updates {
err := db.SaveLightClientUpdate(ctx, uint64(i+1), update)
require.NoError(t, err)
}
// Retrieve the updates
retrievedUpdates, err := db.LightClientUpdates(ctx, 3, 1)
require.NotNil(t, err)
require.Equal(t, err.Error(), "start period 3 is greater than end period 1")
require.IsNil(t, retrievedUpdates)
}
func TestStore_LightClientUpdate_EndPeriodEqualToStartPeriod(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
updates := []*ethpbv2.LightClientUpdateWithVersion{
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 8,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 9,
},
},
}
for i, update := range updates {
err := db.SaveLightClientUpdate(ctx, uint64(i+1), update)
require.NoError(t, err)
}
// Retrieve the updates
retrievedUpdates, err := db.LightClientUpdates(ctx, 2, 2)
require.NoError(t, err)
require.Equal(t, 1, len(retrievedUpdates))
require.Equal(t, updates[1].Data.SignatureSlot, retrievedUpdates[2].Data.SignatureSlot, "retrieved update does not match saved update")
}
func TestStore_LightClientUpdate_StartPeriodBeforeFirstUpdate(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
updates := []*ethpbv2.LightClientUpdateWithVersion{
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 8,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 9,
},
},
}
for i, update := range updates {
err := db.SaveLightClientUpdate(ctx, uint64(i+2), update)
require.NoError(t, err)
}
// Retrieve the updates
retrievedUpdates, err := db.LightClientUpdates(ctx, 0, 4)
require.NoError(t, err)
require.Equal(t, 3, len(retrievedUpdates))
for i, update := range updates {
require.Equal(t, update.Data.SignatureSlot, retrievedUpdates[uint64(i+2)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_EndPeriodAfterLastUpdate(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
updates := []*ethpbv2.LightClientUpdateWithVersion{
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 8,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 9,
},
},
}
for i, update := range updates {
err := db.SaveLightClientUpdate(ctx, uint64(i+1), update)
require.NoError(t, err)
}
// Retrieve the updates
retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 6)
require.NoError(t, err)
require.Equal(t, 3, len(retrievedUpdates))
for i, update := range updates {
require.Equal(t, update.Data.SignatureSlot, retrievedUpdates[uint64(i+1)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_PartialUpdates(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
updates := []*ethpbv2.LightClientUpdateWithVersion{
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 8,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 9,
},
},
}
for i, update := range updates {
err := db.SaveLightClientUpdate(ctx, uint64(i+1), update)
require.NoError(t, err)
}
// Retrieve the updates
retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 2)
require.NoError(t, err)
require.Equal(t, 2, len(retrievedUpdates))
for i, update := range updates[:2] {
require.Equal(t, update.Data.SignatureSlot, retrievedUpdates[uint64(i+1)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_MissingPeriods_SimpleData(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
updates := []*ethpbv2.LightClientUpdateWithVersion{
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 7,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 8,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 11,
},
},
{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: 12,
},
},
}
for _, update := range updates {
err := db.SaveLightClientUpdate(ctx, uint64(update.Data.SignatureSlot), update)
require.NoError(t, err)
}
// Retrieve the updates
retrievedUpdates, err := db.LightClientUpdates(ctx, 7, 12)
require.NoError(t, err)
require.Equal(t, 4, len(retrievedUpdates))
for _, update := range updates {
require.Equal(t, update.Data.SignatureSlot, retrievedUpdates[uint64(update.Data.SignatureSlot)].Data.SignatureSlot, "retrieved update does not match saved update")
}
// Retrieve the updates from the middle
retrievedUpdates, err = db.LightClientUpdates(ctx, 8, 12)
require.NoError(t, err)
require.Equal(t, 3, len(retrievedUpdates))
require.Equal(t, updates[1].Data.SignatureSlot, retrievedUpdates[8].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, updates[2].Data.SignatureSlot, retrievedUpdates[11].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, updates[3].Data.SignatureSlot, retrievedUpdates[12].Data.SignatureSlot, "retrieved update does not match saved update")
// Retrieve the updates from after the missing period
retrievedUpdates, err = db.LightClientUpdates(ctx, 11, 12)
require.NoError(t, err)
require.Equal(t, 2, len(retrievedUpdates))
require.Equal(t, updates[2].Data.SignatureSlot, retrievedUpdates[11].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, updates[3].Data.SignatureSlot, retrievedUpdates[12].Data.SignatureSlot, "retrieved update does not match saved update")
//retrieve the updates from before the missing period to after the missing period
retrievedUpdates, err = db.LightClientUpdates(ctx, 3, 15)
require.NoError(t, err)
require.Equal(t, 4, len(retrievedUpdates))
require.Equal(t, updates[0].Data.SignatureSlot, retrievedUpdates[7].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, updates[1].Data.SignatureSlot, retrievedUpdates[8].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, updates[2].Data.SignatureSlot, retrievedUpdates[11].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, updates[3].Data.SignatureSlot, retrievedUpdates[12].Data.SignatureSlot, "retrieved update does not match saved update")
}
func TestStore_LightClientUpdate_EmptyDB(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
// Retrieve the updates
retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 3)
require.IsNil(t, err)
require.Equal(t, 0, len(retrievedUpdates))
}
func TestStore_LightClientUpdate_MissingPeriodsAtTheEnd_SimpleData(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
for i := 1; i < 4; i++ {
update := &ethpbv2.LightClientUpdateWithVersion{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: primitives.Slot(uint64(i)),
},
}
err := db.SaveLightClientUpdate(ctx, uint64(i), update)
require.NoError(t, err)
}
for i := 7; i < 10; i++ {
update := &ethpbv2.LightClientUpdateWithVersion{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: primitives.Slot(uint64(i)),
},
}
err := db.SaveLightClientUpdate(ctx, uint64(i), update)
require.NoError(t, err)
}
// Retrieve the updates from 1 to 5
retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 5)
require.NoError(t, err)
require.Equal(t, 3, len(retrievedUpdates))
require.Equal(t, primitives.Slot(1), retrievedUpdates[1].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, primitives.Slot(2), retrievedUpdates[2].Data.SignatureSlot, "retrieved update does not match saved update")
require.Equal(t, primitives.Slot(3), retrievedUpdates[3].Data.SignatureSlot, "retrieved update does not match saved update")
}
func setupLightClientTestDB(t *testing.T) (*Store, context.Context) {
db := setupDB(t)
ctx := context.Background()
for i := 10; i < 101; i++ { // 10 to 100
update := &ethpbv2.LightClientUpdateWithVersion{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: primitives.Slot(uint64(i)),
},
}
err := db.SaveLightClientUpdate(ctx, uint64(i), update)
require.NoError(t, err)
}
for i := 110; i < 201; i++ { // 110 to 200
update := &ethpbv2.LightClientUpdateWithVersion{
Version: 1,
Data: &ethpbv2.LightClientUpdate{
AttestedHeader: nil,
NextSyncCommittee: nil,
NextSyncCommitteeBranch: nil,
FinalizedHeader: nil,
FinalityBranch: nil,
SyncAggregate: nil,
SignatureSlot: primitives.Slot(uint64(i)),
},
}
err := db.SaveLightClientUpdate(ctx, uint64(i), update)
require.NoError(t, err)
}
return db, ctx
}
func TestStore_LightClientUpdate_MissingPeriodsInTheMiddleDistributed(t *testing.T) {
db, ctx := setupLightClientTestDB(t)
// Retrieve the updates - should fail because of missing periods in the middle
retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 300)
require.NoError(t, err)
require.Equal(t, 91*2, len(retrievedUpdates))
for i := 10; i < 101; i++ {
require.Equal(t, primitives.Slot(uint64(i)), retrievedUpdates[uint64(i)].Data.SignatureSlot, "retrieved update does not match saved update")
}
for i := 110; i < 201; i++ {
require.Equal(t, primitives.Slot(uint64(i)), retrievedUpdates[uint64(i)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_RetrieveValidRangeFromStart(t *testing.T) {
db, ctx := setupLightClientTestDB(t)
// retrieve 1 to 100 - should work because all periods are present after the firstPeriodInDB > startPeriod
retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 100)
require.NoError(t, err)
require.Equal(t, 91, len(retrievedUpdates))
for i := 10; i < 101; i++ {
require.Equal(t, primitives.Slot(uint64(i)), retrievedUpdates[uint64(i)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_RetrieveValidRangeInTheMiddle(t *testing.T) {
db, ctx := setupLightClientTestDB(t)
// retrieve 110 to 200 - should work because all periods are present
retrievedUpdates, err := db.LightClientUpdates(ctx, 110, 200)
require.NoError(t, err)
require.Equal(t, 91, len(retrievedUpdates))
for i := 110; i < 201; i++ {
require.Equal(t, primitives.Slot(uint64(i)), retrievedUpdates[uint64(i)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_MissingPeriodInTheMiddleConcentrated(t *testing.T) {
db, ctx := setupLightClientTestDB(t)
// retrieve 100 to 200
retrievedUpdates, err := db.LightClientUpdates(ctx, 100, 200)
require.NoError(t, err)
require.Equal(t, 92, len(retrievedUpdates))
require.Equal(t, primitives.Slot(100), retrievedUpdates[100].Data.SignatureSlot, "retrieved update does not match saved update")
for i := 110; i < 201; i++ {
require.Equal(t, primitives.Slot(uint64(i)), retrievedUpdates[uint64(i)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_MissingPeriodsAtTheEnd(t *testing.T) {
db, ctx := setupLightClientTestDB(t)
// retrieve 10 to 109
retrievedUpdates, err := db.LightClientUpdates(ctx, 10, 109)
require.NoError(t, err)
require.Equal(t, 91, len(retrievedUpdates))
for i := 10; i < 101; i++ {
require.Equal(t, primitives.Slot(uint64(i)), retrievedUpdates[uint64(i)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_MissingPeriodsAtTheBeginning(t *testing.T) {
db, ctx := setupLightClientTestDB(t)
// retrieve 105 to 200
retrievedUpdates, err := db.LightClientUpdates(ctx, 105, 200)
require.NoError(t, err)
require.Equal(t, 91, len(retrievedUpdates))
for i := 110; i < 201; i++ {
require.Equal(t, primitives.Slot(uint64(i)), retrievedUpdates[uint64(i)].Data.SignatureSlot, "retrieved update does not match saved update")
}
}
func TestStore_LightClientUpdate_StartPeriodGreaterThanLastPeriod(t *testing.T) {
db, ctx := setupLightClientTestDB(t)
// retrieve 300 to 400
retrievedUpdates, err := db.LightClientUpdates(ctx, 300, 400)
require.NoError(t, err)
require.Equal(t, 0, len(retrievedUpdates))
}

View File

@@ -17,6 +17,9 @@ var (
feeRecipientBucket = []byte("fee-recipient")
registrationBucket = []byte("registration")
// Light Client Updates Bucket
lightClientUpdatesBucket = []byte("light-client-updates")
// Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations.
slotsHasObjectBucket = []byte("slots-has-objects")
// Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations.

View File

@@ -815,6 +815,7 @@ func (s *Service) lightClientEndpoints(blocker lookup.Blocker, stater lookup.Sta
Blocker: blocker,
Stater: stater,
HeadFetcher: s.cfg.HeadFetcher,
BeaconDB: s.cfg.BeaconDB,
}
const namespace = "lightclient"

View File

@@ -12,6 +12,8 @@ go_library(
deps = [
"//api/server/structs:go_default_library",
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/core/light-client:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/rpc/eth/shared:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/state:go_default_library",
@@ -41,9 +43,9 @@ go_test(
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/core/light-client:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/fieldparams:go_default_library",

View File

@@ -6,9 +6,10 @@ import (
"reflect"
"strconv"
lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
@@ -152,7 +153,7 @@ func createLightClientUpdate(
block interfaces.ReadOnlySignedBeaconBlock,
attestedState state.BeaconState,
finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientUpdate, error) {
result, err := blockchain.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock)
result, err := lightclient.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock)
if err != nil {
return nil, err
}
@@ -210,7 +211,7 @@ func newLightClientFinalityUpdateFromBeaconState(
block interfaces.ReadOnlySignedBeaconBlock,
attestedState state.BeaconState,
finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientUpdate, error) {
result, err := blockchain.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock)
result, err := lightclient.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock)
if err != nil {
return nil, err
}
@@ -223,7 +224,7 @@ func newLightClientOptimisticUpdateFromBeaconState(
state state.BeaconState,
block interfaces.ReadOnlySignedBeaconBlock,
attestedState state.BeaconState) (*structs.LightClientUpdate, error) {
result, err := blockchain.NewLightClientOptimisticUpdateFromBeaconState(ctx, state, block, attestedState)
result, err := lightclient.NewLightClientOptimisticUpdateFromBeaconState(ctx, state, block, attestedState)
if err != nil {
return nil, err
}
@@ -319,7 +320,7 @@ func IsSyncCommitteeUpdate(update *v2.LightClientUpdate) bool {
}
func IsFinalityUpdate(update *v2.LightClientUpdate) bool {
finalityBranch := make([][]byte, blockchain.FinalityBranchNumOfLeaves)
finalityBranch := make([][]byte, lightclient.FinalityBranchNumOfLeaves)
return !reflect.DeepEqual(update.FinalityBranch, finalityBranch)
}

View File

@@ -3,7 +3,8 @@ package lightclient
import (
"testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
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"
@@ -19,7 +20,7 @@ func createNonEmptySyncCommitteeBranch() [][]byte {
// When the update has finality
func createNonEmptyFinalityBranch() [][]byte {
res := make([][]byte, blockchain.FinalityBranchNumOfLeaves)
res := make([][]byte, lightclient.FinalityBranchNumOfLeaves)
res[0] = []byte("xyz")
return res
}
@@ -146,7 +147,7 @@ func TestIsBetterUpdate(t *testing.T) {
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: make([][]byte, blockchain.FinalityBranchNumOfLeaves),
FinalityBranch: make([][]byte, lightclient.FinalityBranchNumOfLeaves),
},
newUpdate: &ethpbv2.LightClientUpdate{
SyncAggregate: &ethpbv1.SyncAggregate{
@@ -183,7 +184,7 @@ func TestIsBetterUpdate(t *testing.T) {
},
NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(),
SignatureSlot: 9999,
FinalityBranch: make([][]byte, blockchain.FinalityBranchNumOfLeaves),
FinalityBranch: make([][]byte, lightclient.FinalityBranchNumOfLeaves),
},
expectedResult: false,
},

View File

@@ -2,6 +2,7 @@ package lightclient
import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup"
)
@@ -9,4 +10,5 @@ type Server struct {
Blocker lookup.Blocker
Stater lookup.Stater
HeadFetcher blockchain.HeadFetcher
BeaconDB db.HeadAccessDatabase
}

View File

@@ -434,6 +434,61 @@ func (x *LightClientOptimisticUpdate) GetSignatureSlot() github_com_prysmaticlab
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0)
}
type LightClientUpdateWithVersion struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"`
Data *LightClientUpdate `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
}
func (x *LightClientUpdateWithVersion) Reset() {
*x = LightClientUpdateWithVersion{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LightClientUpdateWithVersion) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LightClientUpdateWithVersion) ProtoMessage() {}
func (x *LightClientUpdateWithVersion) ProtoReflect() protoreflect.Message {
mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LightClientUpdateWithVersion.ProtoReflect.Descriptor instead.
func (*LightClientUpdateWithVersion) Descriptor() ([]byte, []int) {
return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{6}
}
func (x *LightClientUpdateWithVersion) GetVersion() Version {
if x != nil {
return x.Version
}
return Version_PHASE0
}
func (x *LightClientUpdateWithVersion) GetData() *LightClientUpdate {
if x != nil {
return x.Data
}
return nil
}
var File_proto_eth_v2_beacon_lightclient_proto protoreflect.FileDescriptor
var file_proto_eth_v2_beacon_lightclient_proto_rawDesc = []byte{
@@ -560,16 +615,25 @@ var file_proto_eth_v2_beacon_lightclient_proto_rawDesc = []byte{
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e,
0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74,
0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61,
0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x42, 0x83, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32,
0x42, 0x12, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73,
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0x8a, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x67,
0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69,
0x74, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a,
0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69,
0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x83, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x12, 0x53,
0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72,
0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (
@@ -584,7 +648,7 @@ func file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP() []byte {
return file_proto_eth_v2_beacon_lightclient_proto_rawDescData
}
var file_proto_eth_v2_beacon_lightclient_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_proto_eth_v2_beacon_lightclient_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_proto_eth_v2_beacon_lightclient_proto_goTypes = []interface{}{
(*LightClientBootstrap)(nil), // 0: ethereum.eth.v2.LightClientBootstrap
(*LightClientUpdate)(nil), // 1: ethereum.eth.v2.LightClientUpdate
@@ -592,32 +656,35 @@ var file_proto_eth_v2_beacon_lightclient_proto_goTypes = []interface{}{
(*LightClientFinalityUpdate)(nil), // 3: ethereum.eth.v2.LightClientFinalityUpdate
(*LightClientOptimisticUpdateWithVersion)(nil), // 4: ethereum.eth.v2.LightClientOptimisticUpdateWithVersion
(*LightClientOptimisticUpdate)(nil), // 5: ethereum.eth.v2.LightClientOptimisticUpdate
(*v1.BeaconBlockHeader)(nil), // 6: ethereum.eth.v1.BeaconBlockHeader
(*SyncCommittee)(nil), // 7: ethereum.eth.v2.SyncCommittee
(*v1.SyncAggregate)(nil), // 8: ethereum.eth.v1.SyncAggregate
(Version)(0), // 9: ethereum.eth.v2.Version
(*LightClientUpdateWithVersion)(nil), // 6: ethereum.eth.v2.LightClientUpdateWithVersion
(*v1.BeaconBlockHeader)(nil), // 7: ethereum.eth.v1.BeaconBlockHeader
(*SyncCommittee)(nil), // 8: ethereum.eth.v2.SyncCommittee
(*v1.SyncAggregate)(nil), // 9: ethereum.eth.v1.SyncAggregate
(Version)(0), // 10: ethereum.eth.v2.Version
}
var file_proto_eth_v2_beacon_lightclient_proto_depIdxs = []int32{
6, // 0: ethereum.eth.v2.LightClientBootstrap.header:type_name -> ethereum.eth.v1.BeaconBlockHeader
7, // 1: ethereum.eth.v2.LightClientBootstrap.current_sync_committee:type_name -> ethereum.eth.v2.SyncCommittee
6, // 2: ethereum.eth.v2.LightClientUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
7, // 3: ethereum.eth.v2.LightClientUpdate.next_sync_committee:type_name -> ethereum.eth.v2.SyncCommittee
6, // 4: ethereum.eth.v2.LightClientUpdate.finalized_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
8, // 5: ethereum.eth.v2.LightClientUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate
9, // 6: ethereum.eth.v2.LightClientFinalityUpdateWithVersion.version:type_name -> ethereum.eth.v2.Version
7, // 0: ethereum.eth.v2.LightClientBootstrap.header:type_name -> ethereum.eth.v1.BeaconBlockHeader
8, // 1: ethereum.eth.v2.LightClientBootstrap.current_sync_committee:type_name -> ethereum.eth.v2.SyncCommittee
7, // 2: ethereum.eth.v2.LightClientUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
8, // 3: ethereum.eth.v2.LightClientUpdate.next_sync_committee:type_name -> ethereum.eth.v2.SyncCommittee
7, // 4: ethereum.eth.v2.LightClientUpdate.finalized_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
9, // 5: ethereum.eth.v2.LightClientUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate
10, // 6: ethereum.eth.v2.LightClientFinalityUpdateWithVersion.version:type_name -> ethereum.eth.v2.Version
3, // 7: ethereum.eth.v2.LightClientFinalityUpdateWithVersion.data:type_name -> ethereum.eth.v2.LightClientFinalityUpdate
6, // 8: ethereum.eth.v2.LightClientFinalityUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
6, // 9: ethereum.eth.v2.LightClientFinalityUpdate.finalized_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
8, // 10: ethereum.eth.v2.LightClientFinalityUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate
9, // 11: ethereum.eth.v2.LightClientOptimisticUpdateWithVersion.version:type_name -> ethereum.eth.v2.Version
7, // 8: ethereum.eth.v2.LightClientFinalityUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
7, // 9: ethereum.eth.v2.LightClientFinalityUpdate.finalized_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
9, // 10: ethereum.eth.v2.LightClientFinalityUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate
10, // 11: ethereum.eth.v2.LightClientOptimisticUpdateWithVersion.version:type_name -> ethereum.eth.v2.Version
5, // 12: ethereum.eth.v2.LightClientOptimisticUpdateWithVersion.data:type_name -> ethereum.eth.v2.LightClientOptimisticUpdate
6, // 13: ethereum.eth.v2.LightClientOptimisticUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
8, // 14: ethereum.eth.v2.LightClientOptimisticUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate
15, // [15:15] is the sub-list for method output_type
15, // [15:15] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
7, // 13: ethereum.eth.v2.LightClientOptimisticUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
9, // 14: ethereum.eth.v2.LightClientOptimisticUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate
10, // 15: ethereum.eth.v2.LightClientUpdateWithVersion.version:type_name -> ethereum.eth.v2.Version
1, // 16: ethereum.eth.v2.LightClientUpdateWithVersion.data:type_name -> ethereum.eth.v2.LightClientUpdate
17, // [17:17] is the sub-list for method output_type
17, // [17:17] is the sub-list for method input_type
17, // [17:17] is the sub-list for extension type_name
17, // [17:17] is the sub-list for extension extendee
0, // [0:17] is the sub-list for field type_name
}
func init() { file_proto_eth_v2_beacon_lightclient_proto_init() }
@@ -700,6 +767,18 @@ func file_proto_eth_v2_beacon_lightclient_proto_init() {
return nil
}
}
file_proto_eth_v2_beacon_lightclient_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LightClientUpdateWithVersion); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -707,7 +786,7 @@ func file_proto_eth_v2_beacon_lightclient_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_eth_v2_beacon_lightclient_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumMessages: 7,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -30,41 +30,46 @@ option php_namespace = "Ethereum\\Eth\\v2";
// Beacon LightClient API related messages.
message LightClientBootstrap {
v1.BeaconBlockHeader header = 1;
SyncCommittee current_sync_committee = 2;
repeated bytes current_sync_committee_branch = 3;
v1.BeaconBlockHeader header = 1;
SyncCommittee current_sync_committee = 2;
repeated bytes current_sync_committee_branch = 3;
}
message LightClientUpdate {
v1.BeaconBlockHeader attested_header = 1;
SyncCommittee next_sync_committee = 2;
repeated bytes next_sync_committee_branch = 3;
v1.BeaconBlockHeader finalized_header = 4;
repeated bytes finality_branch = 5;
v1.SyncAggregate sync_aggregate = 6;
uint64 signature_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
v1.BeaconBlockHeader attested_header = 1;
SyncCommittee next_sync_committee = 2;
repeated bytes next_sync_committee_branch = 3;
v1.BeaconBlockHeader finalized_header = 4;
repeated bytes finality_branch = 5;
v1.SyncAggregate sync_aggregate = 6;
uint64 signature_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
}
message LightClientFinalityUpdateWithVersion {
v2.Version version = 1;
LightClientFinalityUpdate data = 2;
v2.Version version = 1;
LightClientFinalityUpdate data = 2;
}
message LightClientFinalityUpdate {
v1.BeaconBlockHeader attested_header = 1;
v1.BeaconBlockHeader finalized_header = 2;
repeated bytes finality_branch = 3;
v1.SyncAggregate sync_aggregate = 4;
uint64 signature_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
v1.BeaconBlockHeader attested_header = 1;
v1.BeaconBlockHeader finalized_header = 2;
repeated bytes finality_branch = 3;
v1.SyncAggregate sync_aggregate = 4;
uint64 signature_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
}
message LightClientOptimisticUpdateWithVersion {
v2.Version version = 1;
LightClientOptimisticUpdate data = 2;
v2.Version version = 1;
LightClientOptimisticUpdate data = 2;
}
message LightClientOptimisticUpdate {
v1.BeaconBlockHeader attested_header = 1;
v1.SyncAggregate sync_aggregate = 2;
uint64 signature_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
v1.BeaconBlockHeader attested_header = 1;
v1.SyncAggregate sync_aggregate = 2;
uint64 signature_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
}
message LightClientUpdateWithVersion {
v2.Version version = 1;
LightClientUpdate data = 2;
}

View File

@@ -20,6 +20,7 @@ go_library(
"electra_block.go",
"electra_state.go",
"helpers.go",
"lightclient.go",
"merge.go",
"state.go",
"sync_aggregate.go",

117
testing/util/lightclient.go Normal file
View File

@@ -0,0 +1,117 @@
package util
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/require"
)
type TestLightClient struct {
T *testing.T
Ctx context.Context
State state.BeaconState
Block interfaces.ReadOnlySignedBeaconBlock
AttestedState state.BeaconState
AttestedHeader *ethpb.BeaconBlockHeader
}
func NewTestLightClient(t *testing.T) *TestLightClient {
return &TestLightClient{T: t}
}
func (l *TestLightClient) SetupTest() *TestLightClient {
ctx := context.Background()
slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
attestedState, err := NewBeaconStateCapella()
require.NoError(l.T, err)
err = attestedState.SetSlot(slot)
require.NoError(l.T, err)
parent := NewBeaconBlockCapella()
parent.Block.Slot = slot
signedParent, err := blocks.NewSignedBeaconBlock(parent)
require.NoError(l.T, err)
parentHeader, err := signedParent.Header()
require.NoError(l.T, err)
attestedHeader := parentHeader.Header
err = attestedState.SetLatestBlockHeader(attestedHeader)
require.NoError(l.T, err)
attestedStateRoot, err := attestedState.HashTreeRoot(ctx)
require.NoError(l.T, err)
// get a new signed block so the root is updated with the new state root
parent.Block.StateRoot = attestedStateRoot[:]
signedParent, err = blocks.NewSignedBeaconBlock(parent)
require.NoError(l.T, err)
state, err := NewBeaconStateCapella()
require.NoError(l.T, err)
err = state.SetSlot(slot)
require.NoError(l.T, err)
parentRoot, err := signedParent.Block().HashTreeRoot()
require.NoError(l.T, err)
block := NewBeaconBlockCapella()
block.Block.Slot = slot
block.Block.ParentRoot = parentRoot[:]
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
}
signedBlock, err := blocks.NewSignedBeaconBlock(block)
require.NoError(l.T, err)
h, err := signedBlock.Header()
require.NoError(l.T, err)
err = state.SetLatestBlockHeader(h.Header)
require.NoError(l.T, err)
stateRoot, err := state.HashTreeRoot(ctx)
require.NoError(l.T, err)
// get a new signed block so the root is updated with the new state root
block.Block.StateRoot = stateRoot[:]
signedBlock, err = blocks.NewSignedBeaconBlock(block)
require.NoError(l.T, err)
l.State = state
l.AttestedState = attestedState
l.AttestedHeader = attestedHeader
l.Block = signedBlock
l.Ctx = ctx
return l
}
func (l *TestLightClient) CheckAttestedHeader(update *ethpbv2.LightClientUpdate) {
require.Equal(l.T, l.AttestedHeader.Slot, update.AttestedHeader.Slot, "Attested header slot is not equal")
require.Equal(l.T, l.AttestedHeader.ProposerIndex, update.AttestedHeader.ProposerIndex, "Attested header proposer index is not equal")
require.DeepSSZEqual(l.T, l.AttestedHeader.ParentRoot, update.AttestedHeader.ParentRoot, "Attested header parent root is not equal")
require.DeepSSZEqual(l.T, l.AttestedHeader.BodyRoot, update.AttestedHeader.BodyRoot, "Attested header body root is not equal")
attestedStateRoot, err := l.AttestedState.HashTreeRoot(l.Ctx)
require.NoError(l.T, err)
require.DeepSSZEqual(l.T, attestedStateRoot[:], update.AttestedHeader.StateRoot, "Attested header state root is not equal")
}
func (l *TestLightClient) CheckSyncAggregate(update *ethpbv2.LightClientUpdate) {
syncAggregate, err := l.Block.Block().Body().SyncAggregate()
require.NoError(l.T, err)
require.DeepSSZEqual(l.T, syncAggregate.SyncCommitteeBits, update.SyncAggregate.SyncCommitteeBits, "SyncAggregate bits is not equal")
require.DeepSSZEqual(l.T, syncAggregate.SyncCommitteeSignature, update.SyncAggregate.SyncCommitteeSignature, "SyncAggregate signature is not equal")
}