mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 21:08:10 -05:00
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:
@@ -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",
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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 := ðpbv2.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 := ðpbv2.LightClientOptimisticUpdateWithVersion{
|
||||
Version: ethpbv2.Version(signed.Version()),
|
||||
Data: CreateLightClientOptimisticUpdate(update),
|
||||
Data: lightclient.CreateLightClientOptimisticUpdate(update),
|
||||
}
|
||||
|
||||
return s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
|
||||
31
beacon-chain/core/light-client/BUILD.bazel
Normal file
31
beacon-chain/core/light-client/BUILD.bazel
Normal 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",
|
||||
],
|
||||
)
|
||||
@@ -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 (
|
||||
54
beacon-chain/core/light-client/lightclient_test.go
Normal file
54
beacon-chain/core/light-client/lightclient_test.go
Normal 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")
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
],
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -107,6 +107,7 @@ var Buckets = [][]byte{
|
||||
powchainBucket,
|
||||
stateSummaryBucket,
|
||||
stateValidatorsBucket,
|
||||
lightClientUpdatesBucket,
|
||||
// Indices buckets.
|
||||
blockSlotIndicesBucket,
|
||||
stateSlotIndicesBucket,
|
||||
|
||||
79
beacon-chain/db/kv/lightclient.go
Normal file
79
beacon-chain/db/kv/lightclient.go
Normal 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
|
||||
}
|
||||
648
beacon-chain/db/kv/lightclient_test.go
Normal file
648
beacon-chain/db/kv/lightclient_test.go
Normal 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 := ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
}
|
||||
|
||||
period := uint64(1)
|
||||
err := db.SaveLightClientUpdate(ctx, period, ðpbv2.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: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.LightClientUpdate{
|
||||
AttestedHeader: nil,
|
||||
NextSyncCommittee: nil,
|
||||
NextSyncCommitteeBranch: nil,
|
||||
FinalizedHeader: nil,
|
||||
FinalityBranch: nil,
|
||||
SyncAggregate: nil,
|
||||
SignatureSlot: 11,
|
||||
},
|
||||
},
|
||||
{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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 := ðpbv2.LightClientUpdateWithVersion{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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 := ðpbv2.LightClientUpdateWithVersion{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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 := ðpbv2.LightClientUpdateWithVersion{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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 := ðpbv2.LightClientUpdateWithVersion{
|
||||
Version: 1,
|
||||
Data: ðpbv2.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))
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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: ðpbv2.LightClientUpdate{
|
||||
SyncAggregate: ðpbv1.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,
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
147
proto/eth/v2/beacon_lightclient.pb.go
generated
147
proto/eth/v2/beacon_lightclient.pb.go
generated
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
117
testing/util/lightclient.go
Normal 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")
|
||||
}
|
||||
Reference in New Issue
Block a user