From bddcc158e4551a2d673ce3ebd693f48d78961dc2 Mon Sep 17 00:00:00 2001 From: Bastin <43618253+Inspector-Butters@users.noreply.github.com> Date: Tue, 1 Jul 2025 23:40:18 +0200 Subject: [PATCH] Fix LC versioning bug (#15400) * fix versioning * changelog * fix blockchain tests * fix linter issue * fix spec tests * fix default lc update version * fix lc header version * gzl * clean up the code * Update testing/spectest/shared/common/light_client/update_ranking.go Co-authored-by: Preston Van Loon * add fulu set up in update ranking * pass att block to createDefaultLCUpdate * address comments * linter * Update lightclient.go * sort imports --------- Co-authored-by: Preston Van Loon --- beacon-chain/blockchain/process_block_test.go | 18 +- beacon-chain/core/light-client/BUILD.bazel | 2 +- beacon-chain/core/light-client/helpers.go | 243 ++++++++++ beacon-chain/core/light-client/lightclient.go | 452 ++++-------------- .../core/light-client/lightclient_test.go | 92 ++-- beacon-chain/db/kv/lightclient.go | 15 + beacon-chain/db/kv/lightclient_test.go | 67 ++- beacon-chain/rpc/eth/light-client/BUILD.bazel | 2 +- .../rpc/eth/light-client/handlers_test.go | 290 +++++++++-- changelog/bastin_fix-lc-versioning.md | 3 + consensus-types/light-client/bootstrap.go | 9 +- .../light-client/finality_update.go | 10 +- .../light-client/optimistic_update.go | 8 +- consensus-types/light-client/update.go | 9 +- ..._light_client__single_merkle_proof_test.go | 2 +- ...ctra__light_client__update_ranking_test.go | 2 +- .../shared/common/light_client/BUILD.bazel | 1 + .../common/light_client/update_ranking.go | 19 + 18 files changed, 744 insertions(+), 500 deletions(-) create mode 100644 beacon-chain/core/light-client/helpers.go create mode 100644 changelog/bastin_fix-lc-versioning.md diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index 21303f45d9..98206502c7 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -2796,7 +2796,7 @@ func TestProcessLightClientUpdate(t *testing.T) { period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) // create and save old update - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(l.AttestedBlock) require.NoError(t, err) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) @@ -2848,7 +2848,7 @@ func TestProcessLightClientUpdate(t *testing.T) { period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) // create and save old update - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(l.AttestedBlock) require.NoError(t, err) scb := make([]byte, 64) @@ -2954,7 +2954,7 @@ func TestProcessLightClientUpdate(t *testing.T) { period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) // create and save old update - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(l.AttestedBlock) require.NoError(t, err) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) @@ -3006,7 +3006,7 @@ func TestProcessLightClientUpdate(t *testing.T) { period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) // create and save old update - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(l.AttestedBlock) require.NoError(t, err) scb := make([]byte, 64) @@ -3112,7 +3112,7 @@ func TestProcessLightClientUpdate(t *testing.T) { period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) // create and save old update - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(l.AttestedBlock) require.NoError(t, err) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) @@ -3164,7 +3164,7 @@ func TestProcessLightClientUpdate(t *testing.T) { period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) // create and save old update - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(l.AttestedBlock) require.NoError(t, err) scb := make([]byte, 64) @@ -3647,7 +3647,7 @@ func TestProcessLightClientOptimisticUpdate(t *testing.T) { expectedVersion = version.Altair case 2: forkEpoch = uint64(params.BeaconConfig().BellatrixForkEpoch) - expectedVersion = version.Altair + expectedVersion = version.Bellatrix case 3: forkEpoch = uint64(params.BeaconConfig().CapellaForkEpoch) expectedVersion = version.Capella @@ -3656,7 +3656,7 @@ func TestProcessLightClientOptimisticUpdate(t *testing.T) { expectedVersion = version.Deneb case 5: forkEpoch = uint64(params.BeaconConfig().ElectraForkEpoch) - expectedVersion = version.Deneb + expectedVersion = version.Electra default: t.Errorf("Unsupported fork version %s", version.String(testVersion)) } @@ -3801,7 +3801,7 @@ func TestProcessLightClientFinalityUpdate(t *testing.T) { expectedVersion = version.Altair case 2: forkEpoch = uint64(params.BeaconConfig().BellatrixForkEpoch) - expectedVersion = version.Altair + expectedVersion = version.Bellatrix case 3: forkEpoch = uint64(params.BeaconConfig().CapellaForkEpoch) expectedVersion = version.Capella diff --git a/beacon-chain/core/light-client/BUILD.bazel b/beacon-chain/core/light-client/BUILD.bazel index b22c964bd3..223c5e53c5 100644 --- a/beacon-chain/core/light-client/BUILD.bazel +++ b/beacon-chain/core/light-client/BUILD.bazel @@ -3,6 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "helpers.go", "lightclient.go", "store.go", ], @@ -41,7 +42,6 @@ go_test( "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/light-client:go_default_library", - "//consensus-types/primitives:go_default_library", "//encoding/ssz:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/core/light-client/helpers.go b/beacon-chain/core/light-client/helpers.go new file mode 100644 index 0000000000..c2d0ab2d59 --- /dev/null +++ b/beacon-chain/core/light-client/helpers.go @@ -0,0 +1,243 @@ +package light_client + +import ( + "context" + "fmt" + + "github.com/OffchainLabs/prysm/v6/beacon-chain/execution" + fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" + "github.com/OffchainLabs/prysm/v6/config/params" + "github.com/OffchainLabs/prysm/v6/consensus-types/blocks" + "github.com/OffchainLabs/prysm/v6/consensus-types/interfaces" + light_client "github.com/OffchainLabs/prysm/v6/consensus-types/light-client" + "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" + enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1" + pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" + "github.com/OffchainLabs/prysm/v6/runtime/version" + "github.com/OffchainLabs/prysm/v6/time/slots" + "github.com/pkg/errors" + "google.golang.org/protobuf/proto" +) + +func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces.LightClientBootstrap, error) { + currentEpoch := slots.ToEpoch(currentSlot) + syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize + pubKeys := make([][]byte, syncCommitteeSize) + for i := uint64(0); i < syncCommitteeSize; i++ { + pubKeys[i] = make([]byte, fieldparams.BLSPubkeyLength) + } + currentSyncCommittee := &pb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), + } + + var currentSyncCommitteeBranch [][]byte + if currentEpoch >= params.BeaconConfig().ElectraForkEpoch { + currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepthElectra) + } else { + currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepth) + } + for i := 0; i < len(currentSyncCommitteeBranch); i++ { + currentSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength) + } + + executionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) + for i := 0; i < fieldparams.ExecutionBranchDepth; i++ { + executionBranch[i] = make([]byte, 32) + } + + var m proto.Message + if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + m = &pb.LightClientBootstrapAltair{ + Header: &pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{}, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { + m = &pb.LightClientBootstrapCapella{ + Header: &pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderCapella{}, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else if currentEpoch < params.BeaconConfig().ElectraForkEpoch { + m = &pb.LightClientBootstrapDeneb{ + Header: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else { + m = &pb.LightClientBootstrapElectra{ + Header: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } + + return light_client.NewWrappedBootstrap(m) +} + +func makeExecutionAndProofDeneb(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*enginev1.ExecutionPayloadHeaderDeneb, [][]byte, error) { + if blk.Version() < version.Capella { + p, err := execution.EmptyExecutionPayloadHeader(version.Deneb) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get payload header") + } + payloadHeader, ok := p.(*enginev1.ExecutionPayloadHeaderDeneb) + if !ok { + return nil, nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderDeneb{}) + } + payloadProof := emptyPayloadProof() + + return payloadHeader, payloadProof, nil + } + + payload, err := blk.Block().Body().Execution() + if err != nil { + return nil, nil, errors.Wrap(err, "could not get execution payload") + } + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get withdrawals root") + } + + payloadHeader := &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: 0, + ExcessBlobGas: 0, + } + + if blk.Version() >= version.Deneb { + blobGasUsed, err := payload.BlobGasUsed() + if err != nil { + return nil, nil, errors.Wrap(err, "could not get blob gas used") + } + excessBlobGas, err := payload.ExcessBlobGas() + if err != nil { + return nil, nil, errors.Wrap(err, "could not get excess blob gas") + } + + payloadHeader.BlobGasUsed = blobGasUsed + payloadHeader.ExcessBlobGas = excessBlobGas + } + + payloadProof, err := blocks.PayloadProof(ctx, blk.Block()) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get execution payload proof") + } + + return payloadHeader, payloadProof, nil +} + +func makeExecutionAndProofCapella(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*enginev1.ExecutionPayloadHeaderCapella, [][]byte, error) { + if blk.Version() > version.Capella { + return nil, nil, fmt.Errorf("unsupported block version %s for capella execution payload", version.String(blk.Version())) + } + if blk.Version() < version.Capella { + p, err := execution.EmptyExecutionPayloadHeader(version.Capella) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get payload header") + } + payloadHeader, ok := p.(*enginev1.ExecutionPayloadHeaderCapella) + if !ok { + return nil, nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderCapella{}) + } + payloadProof := emptyPayloadProof() + + return payloadHeader, payloadProof, nil + } + + payload, err := blk.Block().Body().Execution() + if err != nil { + return nil, nil, errors.Wrap(err, "could not get execution payload") + } + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get withdrawals root") + } + + payloadHeader := &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + payloadProof, err := blocks.PayloadProof(ctx, blk.Block()) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get execution payload proof") + } + + return payloadHeader, payloadProof, nil +} + +func makeBeaconBlockHeader(blk interfaces.ReadOnlySignedBeaconBlock) (*pb.BeaconBlockHeader, error) { + parentRoot := blk.Block().ParentRoot() + stateRoot := blk.Block().StateRoot() + bodyRoot, err := blk.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + return &pb.BeaconBlockHeader{ + Slot: blk.Block().Slot(), + ProposerIndex: blk.Block().ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + }, nil +} + +func emptyPayloadProof() [][]byte { + branch := interfaces.LightClientExecutionBranch{} + proof := make([][]byte, len(branch)) + for i, b := range branch { + proof[i] = b[:] + } + return proof +} diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go index da793ee564..f85596d2e2 100644 --- a/beacon-chain/core/light-client/lightclient.go +++ b/beacon-chain/core/light-client/lightclient.go @@ -6,12 +6,10 @@ import ( "fmt" "reflect" - "github.com/OffchainLabs/prysm/v6/beacon-chain/execution" "github.com/OffchainLabs/prysm/v6/beacon-chain/state" fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" "github.com/OffchainLabs/prysm/v6/config/params" consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" - "github.com/OffchainLabs/prysm/v6/consensus-types/blocks" "github.com/OffchainLabs/prysm/v6/consensus-types/interfaces" light_client "github.com/OffchainLabs/prysm/v6/consensus-types/light-client" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" @@ -163,13 +161,13 @@ func NewLightClientUpdateFromBeaconState( updateAttestedPeriod := slots.SyncCommitteePeriod(slots.ToEpoch(attestedBlock.Block().Slot())) // update = LightClientUpdate() - result, err := CreateDefaultLightClientUpdate(currentSlot, attestedState) + result, err := CreateDefaultLightClientUpdate(attestedBlock) if err != nil { return nil, errors.Wrap(err, "could not create default light client update") } // update.attested_header = block_to_light_client_header(attested_block) - attestedLightClientHeader, err := BlockToLightClientHeader(ctx, currentSlot, attestedBlock) + attestedLightClientHeader, err := BlockToLightClientHeader(ctx, attestedBlock.Version(), attestedBlock) if err != nil { return nil, errors.Wrap(err, "could not get attested light client header") } @@ -210,7 +208,7 @@ func NewLightClientUpdateFromBeaconState( // if finalized_block.message.slot != GENESIS_SLOT if finalizedBlock.Block().Slot() != 0 { // update.finalized_header = block_to_light_client_header(finalized_block) - finalizedLightClientHeader, err := BlockToLightClientHeader(ctx, currentSlot, finalizedBlock) + finalizedLightClientHeader, err := BlockToLightClientHeader(ctx, attestedBlock.Version(), finalizedBlock) if err != nil { return nil, errors.Wrap(err, "could not get finalized light client header") } @@ -247,9 +245,7 @@ func NewLightClientUpdateFromBeaconState( return result, nil } -func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState state.BeaconState) (interfaces.LightClientUpdate, error) { - currentEpoch := slots.ToEpoch(currentSlot) - +func CreateDefaultLightClientUpdate(attestedBlock interfaces.ReadOnlySignedBeaconBlock) (interfaces.LightClientUpdate, error) { syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize pubKeys := make([][]byte, syncCommitteeSize) for i := uint64(0); i < syncCommitteeSize; i++ { @@ -261,7 +257,7 @@ func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState s } var nextSyncCommitteeBranch [][]byte - if attestedState.Version() >= version.Electra { + if attestedBlock.Version() >= version.Electra { nextSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepthElectra) } else { nextSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepth) @@ -276,7 +272,7 @@ func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState s } var finalityBranch [][]byte - if attestedState.Version() >= version.Electra { + if attestedBlock.Version() >= version.Electra { finalityBranch = make([][]byte, fieldparams.FinalityBranchDepthElectra) } else { finalityBranch = make([][]byte, fieldparams.FinalityBranchDepth) @@ -286,10 +282,12 @@ func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState s } var m proto.Message - if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + switch attestedBlock.Version() { + case version.Altair, version.Bellatrix: m = &pb.LightClientUpdateAltair{ AttestedHeader: &pb.LightClientHeaderAltair{ Beacon: &pb.BeaconBlockHeader{ + Slot: attestedBlock.Block().Slot(), ParentRoot: make([]byte, 32), StateRoot: make([]byte, 32), BodyRoot: make([]byte, 32), @@ -310,10 +308,11 @@ func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState s SyncCommitteeSignature: make([]byte, 96), }, } - } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { + case version.Capella: m = &pb.LightClientUpdateCapella{ AttestedHeader: &pb.LightClientHeaderCapella{ Beacon: &pb.BeaconBlockHeader{ + Slot: attestedBlock.Block().Slot(), ParentRoot: make([]byte, 32), StateRoot: make([]byte, 32), BodyRoot: make([]byte, 32), @@ -362,10 +361,11 @@ func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState s SyncCommitteeSignature: make([]byte, 96), }, } - } else if currentEpoch < params.BeaconConfig().ElectraForkEpoch { + case version.Deneb: m = &pb.LightClientUpdateDeneb{ AttestedHeader: &pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ + Slot: attestedBlock.Block().Slot(), ParentRoot: make([]byte, 32), StateRoot: make([]byte, 32), BodyRoot: make([]byte, 32), @@ -418,120 +418,65 @@ func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState s SyncCommitteeSignature: make([]byte, 96), }, } - } else { - if attestedState.Version() >= version.Electra { - m = &pb.LightClientUpdateElectra{ - AttestedHeader: &pb.LightClientHeaderDeneb{ - Beacon: &pb.BeaconBlockHeader{ - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - BodyRoot: make([]byte, 32), - }, - Execution: &enginev1.ExecutionPayloadHeaderDeneb{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - WithdrawalsRoot: make([]byte, fieldparams.RootLength), - GasLimit: 0, - GasUsed: 0, - }, - ExecutionBranch: executionBranch, + case version.Electra, version.Fulu: + m = &pb.LightClientUpdateElectra{ + AttestedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: attestedBlock.Block().Slot(), + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), }, - NextSyncCommittee: nextSyncCommittee, - NextSyncCommitteeBranch: nextSyncCommitteeBranch, - FinalityBranch: finalityBranch, - FinalizedHeader: &pb.LightClientHeaderDeneb{ - Beacon: &pb.BeaconBlockHeader{ - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - BodyRoot: make([]byte, 32), - }, - Execution: &enginev1.ExecutionPayloadHeaderDeneb{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - WithdrawalsRoot: make([]byte, fieldparams.RootLength), - GasLimit: 0, - GasUsed: 0, - }, - ExecutionBranch: executionBranch, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, }, - SyncAggregate: &pb.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, 96), + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + FinalizedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), }, - } - } else { - m = &pb.LightClientUpdateDeneb{ - AttestedHeader: &pb.LightClientHeaderDeneb{ - Beacon: &pb.BeaconBlockHeader{ - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - BodyRoot: make([]byte, 32), - }, - Execution: &enginev1.ExecutionPayloadHeaderDeneb{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - WithdrawalsRoot: make([]byte, fieldparams.RootLength), - GasLimit: 0, - GasUsed: 0, - }, - ExecutionBranch: executionBranch, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, }, - NextSyncCommittee: nextSyncCommittee, - NextSyncCommitteeBranch: nextSyncCommitteeBranch, - FinalityBranch: finalityBranch, - FinalizedHeader: &pb.LightClientHeaderDeneb{ - Beacon: &pb.BeaconBlockHeader{ - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - BodyRoot: make([]byte, 32), - }, - Execution: &enginev1.ExecutionPayloadHeaderDeneb{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - WithdrawalsRoot: make([]byte, fieldparams.RootLength), - GasLimit: 0, - GasUsed: 0, - }, - ExecutionBranch: executionBranch, - }, - SyncAggregate: &pb.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, 96), - }, - } + ExecutionBranch: executionBranch, + }, + SyncAggregate: &pb.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, 96), + }, } + default: + return nil, errors.Errorf("unsupported beacon chain version %s", version.String(attestedBlock.Version())) } return light_client.NewWrappedUpdate(m) @@ -575,189 +520,52 @@ func ComputeWithdrawalsRoot(payload interfaces.ExecutionData) ([]byte, error) { func BlockToLightClientHeader( ctx context.Context, - currentSlot primitives.Slot, - block interfaces.ReadOnlySignedBeaconBlock, + attestedBlockVersion int, // this is the version that the light client header should be in, based on the attested block. + block interfaces.ReadOnlySignedBeaconBlock, // this block is either the attested block, or the finalized block. + // in case of the latter, we might need to upgrade it to the attested block's version. ) (interfaces.LightClientHeader, error) { - var m proto.Message - currentEpoch := slots.ToEpoch(currentSlot) - blockEpoch := slots.ToEpoch(block.Block().Slot()) - parentRoot := block.Block().ParentRoot() - stateRoot := block.Block().StateRoot() - bodyRoot, err := block.Block().Body().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "could not get body root") + if block.Version() > attestedBlockVersion { + return nil, errors.Errorf("block version %s is greater than attested block version %s", version.String(block.Version()), version.String(attestedBlockVersion)) } - if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + beacon, err := makeBeaconBlockHeader(block) + if err != nil { + return nil, errors.Wrap(err, "could not make beacon block header") + } + + var m proto.Message + switch attestedBlockVersion { + case version.Altair, version.Bellatrix: m = &pb.LightClientHeaderAltair{ - Beacon: &pb.BeaconBlockHeader{ - Slot: block.Block().Slot(), - ProposerIndex: block.Block().ProposerIndex(), - ParentRoot: parentRoot[:], - StateRoot: stateRoot[:], - BodyRoot: bodyRoot[:], - }, + Beacon: beacon, } - } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { - var payloadHeader *enginev1.ExecutionPayloadHeaderCapella - var payloadProof [][]byte - - if blockEpoch < params.BeaconConfig().CapellaForkEpoch { - var ok bool - - p, err := execution.EmptyExecutionPayloadHeader(version.Capella) - if err != nil { - return nil, errors.Wrap(err, "could not get payload header") - } - payloadHeader, ok = p.(*enginev1.ExecutionPayloadHeaderCapella) - if !ok { - return nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderCapella{}) - } - payloadProof = emptyPayloadProof() - } else { - payload, err := block.Block().Body().Execution() - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload") - } - transactionsRoot, err := ComputeTransactionsRoot(payload) - if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - - payloadHeader = &enginev1.ExecutionPayloadHeaderCapella{ - ParentHash: payload.ParentHash(), - FeeRecipient: payload.FeeRecipient(), - StateRoot: payload.StateRoot(), - ReceiptsRoot: payload.ReceiptsRoot(), - LogsBloom: payload.LogsBloom(), - PrevRandao: payload.PrevRandao(), - BlockNumber: payload.BlockNumber(), - GasLimit: payload.GasLimit(), - GasUsed: payload.GasUsed(), - Timestamp: payload.Timestamp(), - ExtraData: payload.ExtraData(), - BaseFeePerGas: payload.BaseFeePerGas(), - BlockHash: payload.BlockHash(), - TransactionsRoot: transactionsRoot, - WithdrawalsRoot: withdrawalsRoot, - } - - payloadProof, err = blocks.PayloadProof(ctx, block.Block()) - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload proof") - } + case version.Capella: + payloadHeader, payloadProof, err := makeExecutionAndProofCapella(ctx, block) + if err != nil { + return nil, errors.Wrap(err, "could not make execution payload header and proof") } - m = &pb.LightClientHeaderCapella{ - Beacon: &pb.BeaconBlockHeader{ - Slot: block.Block().Slot(), - ProposerIndex: block.Block().ProposerIndex(), - ParentRoot: parentRoot[:], - StateRoot: stateRoot[:], - BodyRoot: bodyRoot[:], - }, + Beacon: beacon, Execution: payloadHeader, ExecutionBranch: payloadProof, } - } else { - var payloadHeader *enginev1.ExecutionPayloadHeaderDeneb - var payloadProof [][]byte - - if blockEpoch < params.BeaconConfig().CapellaForkEpoch { - var ok bool - - p, err := execution.EmptyExecutionPayloadHeader(version.Deneb) - if err != nil { - return nil, errors.Wrap(err, "could not get payload header") - } - payloadHeader, ok = p.(*enginev1.ExecutionPayloadHeaderDeneb) - if !ok { - return nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderDeneb{}) - } - payloadProof = emptyPayloadProof() - } else { - payload, err := block.Block().Body().Execution() - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload") - } - transactionsRoot, err := ComputeTransactionsRoot(payload) - if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - - var blobGasUsed uint64 - var excessBlobGas uint64 - - if blockEpoch >= params.BeaconConfig().DenebForkEpoch { - blobGasUsed, err = payload.BlobGasUsed() - if err != nil { - return nil, errors.Wrap(err, "could not get blob gas used") - } - excessBlobGas, err = payload.ExcessBlobGas() - if err != nil { - return nil, errors.Wrap(err, "could not get excess blob gas") - } - } - - payloadHeader = &enginev1.ExecutionPayloadHeaderDeneb{ - ParentHash: payload.ParentHash(), - FeeRecipient: payload.FeeRecipient(), - StateRoot: payload.StateRoot(), - ReceiptsRoot: payload.ReceiptsRoot(), - LogsBloom: payload.LogsBloom(), - PrevRandao: payload.PrevRandao(), - BlockNumber: payload.BlockNumber(), - GasLimit: payload.GasLimit(), - GasUsed: payload.GasUsed(), - Timestamp: payload.Timestamp(), - ExtraData: payload.ExtraData(), - BaseFeePerGas: payload.BaseFeePerGas(), - BlockHash: payload.BlockHash(), - TransactionsRoot: transactionsRoot, - WithdrawalsRoot: withdrawalsRoot, - BlobGasUsed: blobGasUsed, - ExcessBlobGas: excessBlobGas, - } - - payloadProof, err = blocks.PayloadProof(ctx, block.Block()) - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload proof") - } + case version.Deneb, version.Electra, version.Fulu: + payloadHeader, payloadProof, err := makeExecutionAndProofDeneb(ctx, block) + if err != nil { + return nil, errors.Wrap(err, "could not make execution payload header and proof") } - m = &pb.LightClientHeaderDeneb{ - Beacon: &pb.BeaconBlockHeader{ - Slot: block.Block().Slot(), - ProposerIndex: block.Block().ProposerIndex(), - ParentRoot: parentRoot[:], - StateRoot: stateRoot[:], - BodyRoot: bodyRoot[:], - }, + Beacon: beacon, Execution: payloadHeader, ExecutionBranch: payloadProof, } + default: + return nil, fmt.Errorf("unsupported attested block version %s", version.String(attestedBlockVersion)) } return light_client.NewWrappedHeader(m) } -func emptyPayloadProof() [][]byte { - branch := interfaces.LightClientExecutionBranch{} - proof := make([][]byte, len(branch)) - for i, b := range branch { - proof[i] = b[:] - } - return proof -} - func HasRelevantSyncCommittee(update interfaces.LightClientUpdate) (bool, error) { if update.Version() >= version.Electra { branch, err := update.NextSyncCommitteeBranchElectra() @@ -909,7 +717,7 @@ func NewLightClientBootstrapFromBeaconState( return nil, errors.Wrap(err, "could not create default light client bootstrap") } - lightClientHeader, err := BlockToLightClientHeader(ctx, currentSlot, block) + lightClientHeader, err := BlockToLightClientHeader(ctx, state.Version(), block) if err != nil { return nil, errors.Wrap(err, "could not convert block to light client header") } @@ -942,78 +750,6 @@ func NewLightClientBootstrapFromBeaconState( return bootstrap, nil } -func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces.LightClientBootstrap, error) { - currentEpoch := slots.ToEpoch(currentSlot) - syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize - pubKeys := make([][]byte, syncCommitteeSize) - for i := uint64(0); i < syncCommitteeSize; i++ { - pubKeys[i] = make([]byte, fieldparams.BLSPubkeyLength) - } - currentSyncCommittee := &pb.SyncCommittee{ - Pubkeys: pubKeys, - AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), - } - - var currentSyncCommitteeBranch [][]byte - if currentEpoch >= params.BeaconConfig().ElectraForkEpoch { - currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepthElectra) - } else { - currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepth) - } - for i := 0; i < len(currentSyncCommitteeBranch); i++ { - currentSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength) - } - - executionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) - for i := 0; i < fieldparams.ExecutionBranchDepth; i++ { - executionBranch[i] = make([]byte, 32) - } - - // TODO: can this be based on the current epoch? - var m proto.Message - if currentEpoch < params.BeaconConfig().CapellaForkEpoch { - m = &pb.LightClientBootstrapAltair{ - Header: &pb.LightClientHeaderAltair{ - Beacon: &pb.BeaconBlockHeader{}, - }, - CurrentSyncCommittee: currentSyncCommittee, - CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, - } - } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { - m = &pb.LightClientBootstrapCapella{ - Header: &pb.LightClientHeaderCapella{ - Beacon: &pb.BeaconBlockHeader{}, - Execution: &enginev1.ExecutionPayloadHeaderCapella{}, - ExecutionBranch: executionBranch, - }, - CurrentSyncCommittee: currentSyncCommittee, - CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, - } - } else if currentEpoch < params.BeaconConfig().ElectraForkEpoch { - m = &pb.LightClientBootstrapDeneb{ - Header: &pb.LightClientHeaderDeneb{ - Beacon: &pb.BeaconBlockHeader{}, - Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, - ExecutionBranch: executionBranch, - }, - CurrentSyncCommittee: currentSyncCommittee, - CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, - } - } else { - m = &pb.LightClientBootstrapElectra{ - Header: &pb.LightClientHeaderDeneb{ - Beacon: &pb.BeaconBlockHeader{}, - Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, - ExecutionBranch: executionBranch, - }, - CurrentSyncCommittee: currentSyncCommittee, - CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, - } - } - - return light_client.NewWrappedBootstrap(m) -} - func UpdateHasSupermajority(syncAggregate *pb.SyncAggregate) bool { maxActiveParticipants := syncAggregate.SyncCommitteeBits.Len() numActiveParticipants := syncAggregate.SyncCommitteeBits.Count() diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go index de09af2e77..a4ec6e5c49 100644 --- a/beacon-chain/core/light-client/lightclient_test.go +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -7,7 +7,6 @@ import ( "github.com/OffchainLabs/prysm/v6/config/params" light_client "github.com/OffchainLabs/prysm/v6/consensus-types/light-client" - "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" "github.com/OffchainLabs/prysm/v6/runtime/version" lightClient "github.com/OffchainLabs/prysm/v6/beacon-chain/core/light-client" @@ -547,7 +546,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().AltairForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Altair, l.Block, ) require.NoError(t, err) @@ -570,7 +569,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().BellatrixForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Bellatrix, l.Block, ) require.NoError(t, err) @@ -594,7 +593,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().CapellaForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Capella, l.Block, ) require.NoError(t, err) @@ -655,7 +654,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().CapellaForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Capella, l.Block, ) require.NoError(t, err) @@ -718,7 +717,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Deneb, l.Block, ) require.NoError(t, err) @@ -787,7 +786,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Deneb, l.Block, ) require.NoError(t, err) @@ -856,7 +855,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { t.Run("Non-Blinded Beacon Block", func(t *testing.T) { l := util.NewTestLightClient(t, version.Electra) - header, err := lightClient.BlockToLightClientHeader(l.Ctx, l.State.Slot(), l.Block) + header, err := lightClient.BlockToLightClientHeader(l.Ctx, version.Electra, l.Block) require.NoError(t, err) require.NotNil(t, header, "header is nil") @@ -921,7 +920,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { t.Run("Blinded Beacon Block", func(t *testing.T) { l := util.NewTestLightClient(t, version.Electra, util.WithBlinded()) - header, err := lightClient.BlockToLightClientHeader(l.Ctx, l.State.Slot(), l.Block) + header, err := lightClient.BlockToLightClientHeader(l.Ctx, version.Electra, l.Block) require.NoError(t, err) require.NotNil(t, header, "header is nil") @@ -989,7 +988,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().CapellaForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Capella, l.Block) require.NoError(t, err) require.NotNil(t, header, "header is nil") @@ -1011,7 +1010,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Deneb, l.Block) require.NoError(t, err) require.NotNil(t, header, "header is nil") @@ -1034,7 +1033,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Deneb, l.Block) require.NoError(t, err) require.NotNil(t, header, "header is nil") @@ -1094,7 +1093,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { header, err := lightClient.BlockToLightClientHeader( l.Ctx, - primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + version.Deneb, l.Block) require.NoError(t, err) require.NotNil(t, header, "header is nil") @@ -1180,14 +1179,13 @@ func createNonEmptyFinalityBranch() [][]byte { } func TestIsBetterUpdate(t *testing.T) { - config := params.BeaconConfig() - st, err := util.NewBeaconStateAltair() + blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockAltair()) require.NoError(t, err) t.Run("new has supermajority but old doesn't", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1203,9 +1201,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("old has supermajority but new doesn't", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1221,9 +1219,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new doesn't have supermajority and newNumActiveParticipants is greater than oldNumActiveParticipants", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1239,9 +1237,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new doesn't have supermajority and newNumActiveParticipants is lesser than oldNumActiveParticipants", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1257,9 +1255,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new has relevant sync committee but old doesn't", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1296,9 +1294,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("old has relevant sync committee but new doesn't", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1335,9 +1333,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new has finality but old doesn't", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1378,9 +1376,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("old has finality but new doesn't", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1421,9 +1419,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new has finality and sync committee finality both but old doesn't have sync committee finality", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1482,9 +1480,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new has finality but doesn't have sync committee finality and old has sync committee finality", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1543,9 +1541,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new has more active participants than old", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1561,9 +1559,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new has less active participants than old", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1579,9 +1577,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new's attested header's slot is lesser than old's attested header's slot", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1640,9 +1638,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("new's attested header's slot is greater than old's attested header's slot", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1701,9 +1699,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("none of the above conditions are met and new signature's slot is less than old signature's slot", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ @@ -1762,9 +1760,9 @@ func TestIsBetterUpdate(t *testing.T) { }) t.Run("none of the above conditions are met and new signature's slot is greater than old signature's slot", func(t *testing.T) { - oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) - newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ diff --git a/beacon-chain/db/kv/lightclient.go b/beacon-chain/db/kv/lightclient.go index 6b008578c3..33eb6bb237 100644 --- a/beacon-chain/db/kv/lightclient.go +++ b/beacon-chain/db/kv/lightclient.go @@ -153,6 +153,13 @@ func decodeLightClientBootstrap(enc []byte) (interfaces.LightClientBootstrap, [] } m = bootstrap syncCommitteeHash = enc[len(altairKey) : len(altairKey)+32] + case hasBellatrixKey(enc): + bootstrap := ðpb.LightClientBootstrapAltair{} + if err := bootstrap.UnmarshalSSZ(enc[len(bellatrixKey)+32:]); err != nil { + return nil, nil, errors.Wrap(err, "could not unmarshal Bellatrix light client bootstrap") + } + m = bootstrap + syncCommitteeHash = enc[len(bellatrixKey) : len(bellatrixKey)+32] case hasCapellaKey(enc): bootstrap := ðpb.LightClientBootstrapCapella{} if err := bootstrap.UnmarshalSSZ(enc[len(capellaKey)+32:]); err != nil { @@ -265,6 +272,12 @@ func decodeLightClientUpdate(enc []byte) (interfaces.LightClientUpdate, error) { return nil, errors.Wrap(err, "could not unmarshal Altair light client update") } m = update + case hasBellatrixKey(enc): + update := ðpb.LightClientUpdateAltair{} + if err := update.UnmarshalSSZ(enc[len(bellatrixKey):]); err != nil { + return nil, errors.Wrap(err, "could not unmarshal Bellatrix light client update") + } + m = update case hasCapellaKey(enc): update := ðpb.LightClientUpdateCapella{} if err := update.UnmarshalSSZ(enc[len(capellaKey):]); err != nil { @@ -297,6 +310,8 @@ func keyForLightClientUpdate(v int) ([]byte, error) { return denebKey, nil case version.Capella: return capellaKey, nil + case version.Bellatrix: + return bellatrixKey, nil case version.Altair: return altairKey, nil default: diff --git a/beacon-chain/db/kv/lightclient_test.go b/beacon-chain/db/kv/lightclient_test.go index 4c194d1b3c..1592b81bc9 100644 --- a/beacon-chain/db/kv/lightclient_test.go +++ b/beacon-chain/db/kv/lightclient_test.go @@ -46,7 +46,21 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { slot = primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + }) + require.NoError(t, err) + st, err = util.NewBeaconState() + require.NoError(t, err) + case version.Bellatrix: + slot = primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -60,7 +74,7 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { slot = primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderCapella{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -88,7 +102,7 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { slot = primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -116,7 +130,7 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { slot = primitives.Slot(config.ElectraForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -144,7 +158,7 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { slot = primitives.Slot(config.FuluForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -192,10 +206,11 @@ func TestStore_LightClientUpdate_CanSaveRetrieve(t *testing.T) { params.SetupTestConfigCleanup(t) cfg := params.BeaconConfig() cfg.AltairForkEpoch = 0 - cfg.CapellaForkEpoch = 1 - cfg.DenebForkEpoch = 2 - cfg.ElectraForkEpoch = 3 - cfg.FuluForkEpoch = 3 + cfg.BellatrixForkEpoch = 1 + cfg.CapellaForkEpoch = 2 + cfg.DenebForkEpoch = 3 + cfg.ElectraForkEpoch = 4 + cfg.FuluForkEpoch = 5 params.OverrideBeaconConfig(cfg) db := setupDB(t) @@ -213,6 +228,18 @@ func TestStore_LightClientUpdate_CanSaveRetrieve(t *testing.T) { require.NoError(t, err) require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") }) + t.Run("Bellatrix", func(t *testing.T) { + update, err := createUpdate(t, version.Bellatrix) + require.NoError(t, err) + period := uint64(1) + + err = db.SaveLightClientUpdate(ctx, period, update) + require.NoError(t, err) + + retrievedUpdate, err := db.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") + }) t.Run("Capella", func(t *testing.T) { update, err := createUpdate(t, version.Capella) require.NoError(t, err) @@ -242,17 +269,6 @@ func TestStore_LightClientUpdate_CanSaveRetrieve(t *testing.T) { err = db.SaveLightClientUpdate(ctx, period, update) require.NoError(t, err) - retrievedUpdate, err := db.LightClientUpdate(ctx, period) - require.NoError(t, err) - require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") - }) - t.Run("Fulu", func(t *testing.T) { - update, err := createUpdate(t, version.Fulu) - require.NoError(t, err) - period := uint64(1) - err = db.SaveLightClientUpdate(ctx, period, update) - require.NoError(t, err) - retrievedUpdate, err := db.LightClientUpdate(ctx, period) require.NoError(t, err) require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") @@ -584,9 +600,10 @@ func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) { params.SetupTestConfigCleanup(t) cfg := params.BeaconConfig() cfg.AltairForkEpoch = 0 - cfg.CapellaForkEpoch = 1 - cfg.DenebForkEpoch = 2 - cfg.ElectraForkEpoch = 3 + cfg.BellatrixForkEpoch = 1 + cfg.CapellaForkEpoch = 2 + cfg.DenebForkEpoch = 3 + cfg.ElectraForkEpoch = 4 cfg.EpochsPerSyncCommitteePeriod = 1 params.OverrideBeaconConfig(cfg) @@ -839,6 +856,7 @@ func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces. m = &pb.LightClientBootstrapAltair{ Header: &pb.LightClientHeaderAltair{ Beacon: &pb.BeaconBlockHeader{ + Slot: currentSlot, ParentRoot: make([]byte, 32), StateRoot: make([]byte, 32), BodyRoot: make([]byte, 32), @@ -851,6 +869,7 @@ func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces. m = &pb.LightClientBootstrapCapella{ Header: &pb.LightClientHeaderCapella{ Beacon: &pb.BeaconBlockHeader{ + Slot: currentSlot, ParentRoot: make([]byte, 32), StateRoot: make([]byte, 32), BodyRoot: make([]byte, 32), @@ -877,6 +896,7 @@ func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces. m = &pb.LightClientBootstrapDeneb{ Header: &pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ + Slot: currentSlot, ParentRoot: make([]byte, 32), StateRoot: make([]byte, 32), BodyRoot: make([]byte, 32), @@ -905,6 +925,7 @@ func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces. m = &pb.LightClientBootstrapElectra{ Header: &pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ + Slot: currentSlot, ParentRoot: make([]byte, 32), StateRoot: make([]byte, 32), BodyRoot: make([]byte, 32), diff --git a/beacon-chain/rpc/eth/light-client/BUILD.bazel b/beacon-chain/rpc/eth/light-client/BUILD.bazel index 643abd1bf0..b3a9ccac93 100644 --- a/beacon-chain/rpc/eth/light-client/BUILD.bazel +++ b/beacon-chain/rpc/eth/light-client/BUILD.bazel @@ -42,9 +42,9 @@ go_test( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/light-client:go_default_library", "//beacon-chain/db/testing:go_default_library", - "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/light-client:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/beacon-chain/rpc/eth/light-client/handlers_test.go b/beacon-chain/rpc/eth/light-client/handlers_test.go index 0bd382cb66..7001e3e919 100644 --- a/beacon-chain/rpc/eth/light-client/handlers_test.go +++ b/beacon-chain/rpc/eth/light-client/handlers_test.go @@ -15,9 +15,9 @@ import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers" lightclient "github.com/OffchainLabs/prysm/v6/beacon-chain/core/light-client" dbtesting "github.com/OffchainLabs/prysm/v6/beacon-chain/db/testing" - "github.com/OffchainLabs/prysm/v6/beacon-chain/state" fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" "github.com/OffchainLabs/prysm/v6/config/params" + "github.com/OffchainLabs/prysm/v6/consensus-types/blocks" "github.com/OffchainLabs/prysm/v6/consensus-types/interfaces" light_client "github.com/OffchainLabs/prysm/v6/consensus-types/light-client" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" @@ -175,7 +175,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { var respHeader structs.LightClientHeader err = json.Unmarshal(resp.Data.Header, &respHeader) require.NoError(t, err) - require.Equal(t, "altair", resp.Version) + require.Equal(t, "bellatrix", resp.Version) blockHeader, err := l.Block.Header() require.NoError(t, err) @@ -454,8 +454,9 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { config := params.BeaconConfig() config.EpochsPerSyncCommitteePeriod = 1 config.AltairForkEpoch = 0 - config.CapellaForkEpoch = 1 - config.DenebForkEpoch = 2 + config.BellatrixForkEpoch = 1 + config.CapellaForkEpoch = 2 + config.DenebForkEpoch = 3 params.OverrideBeaconConfig(config) t.Run("altair", func(t *testing.T) { @@ -537,6 +538,85 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { require.DeepEqual(t, resp.AttestedHeader, update.AttestedHeader().Proto()) }) + t.Run("bellatrix", func(t *testing.T) { + slot := primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateBellatrix() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := uint64(slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch))) + + update, err := createUpdate(t, version.Bellatrix) + require.NoError(t, err) + err = db.SaveLightClientUpdate(ctx, updatePeriod, update) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=1&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 1, len(resp.Updates)) + require.Equal(t, "bellatrix", resp.Updates[0].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[0].Data) + }) + + t.Run("bellatrix ssz", func(t *testing.T) { + slot := primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateBellatrix() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := uint64(slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch))) + + update, err := createUpdate(t, version.Bellatrix) + require.NoError(t, err) + err = db.SaveLightClientUpdate(ctx, updatePeriod, update) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=1&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp pb.LightClientUpdateAltair + err = resp.UnmarshalSSZ(writer.Body.Bytes()[12:]) // skip the length and fork digest prefixes + require.NoError(t, err) + require.DeepEqual(t, resp.AttestedHeader, update.AttestedHeader().Proto()) + }) + t.Run("capella", func(t *testing.T) { slot := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) @@ -1013,13 +1093,13 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { } }) - t.Run("multiple forks - altair, capella", func(t *testing.T) { - slotCapella := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + t.Run("multiple forks - altair, bellatrix", func(t *testing.T) { + slotBellatrix := primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) slotAltair := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - st, err := util.NewBeaconStateAltair() + st, err := util.NewBeaconStateBellatrix() require.NoError(t, err) - headSlot := slotCapella.Add(1) + headSlot := slotBellatrix.Add(1) err = st.SetSlot(headSlot) require.NoError(t, err) @@ -1035,9 +1115,9 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[0]) require.NoError(t, err) - updatePeriod = slotCapella.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + updatePeriod = slotBellatrix.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) - updates[1], err = createUpdate(t, version.Capella) + updates[1], err = createUpdate(t, version.Bellatrix) require.NoError(t, err) err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[1]) @@ -1065,7 +1145,7 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { if i < 1 { require.Equal(t, "altair", resp.Updates[i].Version) } else { - require.Equal(t, "capella", resp.Updates[i].Version) + require.Equal(t, "bellatrix", resp.Updates[i].Version) } updateJson, err := structs.LightClientUpdateFromConsensus(update) require.NoError(t, err) @@ -1073,13 +1153,13 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { } }) - t.Run("multiple forks - altair, capella - ssz", func(t *testing.T) { - slotCapella := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + t.Run("multiple forks - altair, bellatrix - ssz", func(t *testing.T) { + slotBellatrix := primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) slotAltair := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - st, err := util.NewBeaconStateAltair() + st, err := util.NewBeaconStateBellatrix() require.NoError(t, err) - headSlot := slotCapella.Add(1) + headSlot := slotBellatrix.Add(1) err = st.SetSlot(headSlot) require.NoError(t, err) @@ -1095,6 +1175,68 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[0]) require.NoError(t, err) + updatePeriod = slotBellatrix.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[1], err = createUpdate(t, version.Bellatrix) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[1]) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := 0 + url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + + offset := 0 + updateLen := int(ssz.UnmarshallUint64(writer.Body.Bytes()[offset:offset+8]) - 4) + offset += 12 + var resp pb.LightClientUpdateAltair + err = resp.UnmarshalSSZ(writer.Body.Bytes()[offset : offset+updateLen]) + require.NoError(t, err) + require.DeepEqual(t, resp.AttestedHeader, updates[0].AttestedHeader().Proto()) + offset += updateLen + updateLen = int(ssz.UnmarshallUint64(writer.Body.Bytes()[offset:offset+8]) - 4) + offset += 12 + var resp1 pb.LightClientUpdateAltair + err = resp1.UnmarshalSSZ(writer.Body.Bytes()[offset : offset+updateLen]) + require.NoError(t, err) + require.DeepEqual(t, resp1.AttestedHeader, updates[1].AttestedHeader().Proto()) + }) + + t.Run("multiple forks - bellatrix, capella", func(t *testing.T) { + slotCapella := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + slotBellatrix := primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateCapella() + require.NoError(t, err) + headSlot := slotCapella.Add(1) + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 2) + + updatePeriod := slotBellatrix.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[0], err = createUpdate(t, version.Bellatrix) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[0]) + require.NoError(t, err) + updatePeriod = slotCapella.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) updates[1], err = createUpdate(t, version.Capella) @@ -1108,7 +1250,67 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { HeadFetcher: mockChainService, BeaconDB: db, } - startPeriod := 0 + startPeriod := slotBellatrix.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + if i < 1 { + require.Equal(t, "bellatrix", resp.Updates[i].Version) + } else { + require.Equal(t, "capella", resp.Updates[i].Version) + } + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + }) + + t.Run("multiple forks - bellatrix, capella - ssz", func(t *testing.T) { + slotCapella := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + slotBellatrix := primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateCapella() + require.NoError(t, err) + headSlot := slotCapella.Add(1) + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 2) + + updatePeriod := slotBellatrix.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[0], err = createUpdate(t, version.Bellatrix) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[0]) + require.NoError(t, err) + + updatePeriod = slotCapella.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[1], err = createUpdate(t, version.Capella) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[1]) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slotBellatrix.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) request := httptest.NewRequest("GET", url, nil) request.Header.Add("Accept", "application/octet-stream") @@ -1170,7 +1372,7 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { HeadFetcher: mockChainService, BeaconDB: db, } - startPeriod := 1 + startPeriod := slotCapella.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) request := httptest.NewRequest("GET", url, nil) writer := httptest.NewRecorder() @@ -1230,7 +1432,7 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) { HeadFetcher: mockChainService, BeaconDB: db, } - startPeriod := 1 + startPeriod := slotCapella.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) request := httptest.NewRequest("GET", url, nil) request.Header.Add("Accept", "application/octet-stream") @@ -1522,11 +1724,7 @@ func TestLightClientHandler_GetLightClientFinalityUpdate(t *testing.T) { var resp structs.LightClientFinalityUpdateResponse err = json.Unmarshal(writer.Body.Bytes(), &resp) require.NoError(t, err) - if testVersion == version.Bellatrix { - require.Equal(t, version.String(version.Altair), resp.Version) - } else { - require.Equal(t, version.String(testVersion), resp.Version) - } + require.Equal(t, version.String(testVersion), resp.Version) require.DeepEqual(t, data, resp.Data) }) @@ -1606,13 +1804,7 @@ func TestLightClientHandler_GetLightClientOptimisticUpdate(t *testing.T) { var resp structs.LightClientOptimisticUpdateResponse err = json.Unmarshal(writer.Body.Bytes(), &resp) require.NoError(t, err) - if testVersion == version.Bellatrix { - require.Equal(t, version.String(version.Altair), resp.Version) - } else if testVersion == version.Electra { - require.Equal(t, version.String(version.Deneb), resp.Version) - } else { - require.Equal(t, version.String(testVersion), resp.Version) - } + require.Equal(t, version.String(testVersion), resp.Version) require.DeepEqual(t, data, resp.Data) }) @@ -1661,7 +1853,7 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { config := params.BeaconConfig() var slot primitives.Slot var header interfaces.LightClientHeader - var st state.BeaconState + var blk interfaces.ReadOnlySignedBeaconBlock var err error sampleRoot := make([]byte, 32) @@ -1682,7 +1874,7 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { slot = primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -1690,13 +1882,27 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { }, }) require.NoError(t, err) - st, err = util.NewBeaconStateAltair() + blk, err = blocks.NewSignedBeaconBlock(util.NewBeaconBlockAltair()) + require.NoError(t, err) + case version.Bellatrix: + slot = primitives.Slot(config.BellatrixForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: slot, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + }) + require.NoError(t, err) + blk, err = blocks.NewSignedBeaconBlock(util.NewBeaconBlockBellatrix()) require.NoError(t, err) case version.Capella: slot = primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderCapella{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -1718,13 +1924,13 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { ExecutionBranch: sampleExecutionBranch, }) require.NoError(t, err) - st, err = util.NewBeaconStateCapella() + blk, err = blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella()) require.NoError(t, err) case version.Deneb: slot = primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -1746,13 +1952,13 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { ExecutionBranch: sampleExecutionBranch, }) require.NoError(t, err) - st, err = util.NewBeaconStateDeneb() + blk, err = blocks.NewSignedBeaconBlock(util.NewBeaconBlockDeneb()) require.NoError(t, err) case version.Electra: slot = primitives.Slot(config.ElectraForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -1774,13 +1980,13 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { ExecutionBranch: sampleExecutionBranch, }) require.NoError(t, err) - st, err = util.NewBeaconStateElectra() + blk, err = blocks.NewSignedBeaconBlock(util.NewBeaconBlockElectra()) require.NoError(t, err) case version.Fulu: slot = primitives.Slot(config.FuluForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ Beacon: &pb.BeaconBlockHeader{ - Slot: 1, + Slot: slot, ProposerIndex: primitives.ValidatorIndex(rand.Int()), ParentRoot: sampleRoot, StateRoot: sampleRoot, @@ -1802,13 +2008,13 @@ func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { ExecutionBranch: sampleExecutionBranch, }) require.NoError(t, err) - st, err = util.NewBeaconStateFulu() + blk, err = blocks.NewSignedBeaconBlock(util.NewBeaconBlockFulu()) require.NoError(t, err) default: return nil, fmt.Errorf("unsupported version %s", version.String(v)) } - update, err := lightclient.CreateDefaultLightClientUpdate(slot, st) + update, err := lightclient.CreateDefaultLightClientUpdate(blk) require.NoError(t, err) update.SetSignatureSlot(slot - 1) syncCommitteeBits := make([]byte, 64) diff --git a/changelog/bastin_fix-lc-versioning.md b/changelog/bastin_fix-lc-versioning.md new file mode 100644 index 0000000000..51579b6936 --- /dev/null +++ b/changelog/bastin_fix-lc-versioning.md @@ -0,0 +1,3 @@ +### Fixed + +- Fixed the versioning bug for light client data types in the Beacon API. \ No newline at end of file diff --git a/consensus-types/light-client/bootstrap.go b/consensus-types/light-client/bootstrap.go index deab9c50ed..a477b89dca 100644 --- a/consensus-types/light-client/bootstrap.go +++ b/consensus-types/light-client/bootstrap.go @@ -8,6 +8,7 @@ import ( "github.com/OffchainLabs/prysm/v6/consensus-types/interfaces" pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v6/runtime/version" + "github.com/OffchainLabs/prysm/v6/time/slots" "google.golang.org/protobuf/proto" ) @@ -83,7 +84,7 @@ func (h *bootstrapAltair) SizeSSZ() int { } func (h *bootstrapAltair) Version() int { - return version.Altair + return slots.ToForkVersion(h.header.Beacon().Slot) } func (h *bootstrapAltair) Proto() proto.Message { @@ -188,7 +189,7 @@ func (h *bootstrapCapella) SizeSSZ() int { } func (h *bootstrapCapella) Version() int { - return version.Capella + return slots.ToForkVersion(h.header.Beacon().Slot) } func (h *bootstrapCapella) Proto() proto.Message { @@ -293,7 +294,7 @@ func (h *bootstrapDeneb) SizeSSZ() int { } func (h *bootstrapDeneb) Version() int { - return version.Deneb + return slots.ToForkVersion(h.header.Beacon().Slot) } func (h *bootstrapDeneb) Proto() proto.Message { @@ -398,7 +399,7 @@ func (h *bootstrapElectra) SizeSSZ() int { } func (h *bootstrapElectra) Version() int { - return version.Electra + return slots.ToForkVersion(h.header.Beacon().Slot) } func (h *bootstrapElectra) Proto() proto.Message { diff --git a/consensus-types/light-client/finality_update.go b/consensus-types/light-client/finality_update.go index 77c876940e..b6445cacc9 100644 --- a/consensus-types/light-client/finality_update.go +++ b/consensus-types/light-client/finality_update.go @@ -8,7 +8,7 @@ import ( "github.com/OffchainLabs/prysm/v6/consensus-types/interfaces" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" - "github.com/OffchainLabs/prysm/v6/runtime/version" + "github.com/OffchainLabs/prysm/v6/time/slots" "google.golang.org/protobuf/proto" ) @@ -174,7 +174,7 @@ func (u *finalityUpdateAltair) Proto() proto.Message { } func (u *finalityUpdateAltair) Version() int { - return version.Altair + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *finalityUpdateAltair) AttestedHeader() interfaces.LightClientHeader { @@ -286,7 +286,7 @@ func (u *finalityUpdateCapella) Proto() proto.Message { } func (u *finalityUpdateCapella) Version() int { - return version.Capella + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *finalityUpdateCapella) AttestedHeader() interfaces.LightClientHeader { @@ -398,7 +398,7 @@ func (u *finalityUpdateDeneb) Proto() proto.Message { } func (u *finalityUpdateDeneb) Version() int { - return version.Deneb + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *finalityUpdateDeneb) AttestedHeader() interfaces.LightClientHeader { @@ -511,7 +511,7 @@ func (u *finalityUpdateElectra) Proto() proto.Message { } func (u *finalityUpdateElectra) Version() int { - return version.Electra + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *finalityUpdateElectra) AttestedHeader() interfaces.LightClientHeader { diff --git a/consensus-types/light-client/optimistic_update.go b/consensus-types/light-client/optimistic_update.go index 56e6b85353..5c723588cc 100644 --- a/consensus-types/light-client/optimistic_update.go +++ b/consensus-types/light-client/optimistic_update.go @@ -7,7 +7,7 @@ import ( "github.com/OffchainLabs/prysm/v6/consensus-types/interfaces" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" - "github.com/OffchainLabs/prysm/v6/runtime/version" + "github.com/OffchainLabs/prysm/v6/time/slots" "google.golang.org/protobuf/proto" ) @@ -139,7 +139,7 @@ func (u *optimisticUpdateAltair) Proto() proto.Message { } func (u *optimisticUpdateAltair) Version() int { - return version.Altair + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *optimisticUpdateAltair) AttestedHeader() interfaces.LightClientHeader { @@ -223,7 +223,7 @@ func (u *optimisticUpdateCapella) Proto() proto.Message { } func (u *optimisticUpdateCapella) Version() int { - return version.Capella + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *optimisticUpdateCapella) AttestedHeader() interfaces.LightClientHeader { @@ -307,7 +307,7 @@ func (u *optimisticUpdateDeneb) Proto() proto.Message { } func (u *optimisticUpdateDeneb) Version() int { - return version.Deneb + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *optimisticUpdateDeneb) AttestedHeader() interfaces.LightClientHeader { diff --git a/consensus-types/light-client/update.go b/consensus-types/light-client/update.go index fffce1e56f..f66ac0270f 100644 --- a/consensus-types/light-client/update.go +++ b/consensus-types/light-client/update.go @@ -9,6 +9,7 @@ import ( "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v6/runtime/version" + "github.com/OffchainLabs/prysm/v6/time/slots" "google.golang.org/protobuf/proto" ) @@ -105,7 +106,7 @@ func (u *updateAltair) Proto() proto.Message { } func (u *updateAltair) Version() int { - return version.Altair + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *updateAltair) AttestedHeader() interfaces.LightClientHeader { @@ -272,7 +273,7 @@ func (u *updateCapella) Proto() proto.Message { } func (u *updateCapella) Version() int { - return version.Capella + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *updateCapella) AttestedHeader() interfaces.LightClientHeader { @@ -439,7 +440,7 @@ func (u *updateDeneb) Proto() proto.Message { } func (u *updateDeneb) Version() int { - return version.Deneb + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *updateDeneb) AttestedHeader() interfaces.LightClientHeader { @@ -607,7 +608,7 @@ func (u *updateElectra) Proto() proto.Message { } func (u *updateElectra) Version() int { - return version.Electra + return slots.ToForkVersion(u.attestedHeader.Beacon().Slot) } func (u *updateElectra) AttestedHeader() interfaces.LightClientHeader { diff --git a/testing/spectest/minimal/electra__light_client__single_merkle_proof_test.go b/testing/spectest/minimal/electra__light_client__single_merkle_proof_test.go index 3a9f775e1f..78a6701f86 100644 --- a/testing/spectest/minimal/electra__light_client__single_merkle_proof_test.go +++ b/testing/spectest/minimal/electra__light_client__single_merkle_proof_test.go @@ -7,6 +7,6 @@ import ( "github.com/OffchainLabs/prysm/v6/testing/spectest/shared/common/light_client" ) -func TestMainnet_Electra_LightClient_SingleMerkleProof(t *testing.T) { +func TestMinimal_Electra_LightClient_SingleMerkleProof(t *testing.T) { light_client.RunLightClientSingleMerkleProofTests(t, "minimal", version.Electra) } diff --git a/testing/spectest/minimal/electra__light_client__update_ranking_test.go b/testing/spectest/minimal/electra__light_client__update_ranking_test.go index 6a38411999..8903e774aa 100644 --- a/testing/spectest/minimal/electra__light_client__update_ranking_test.go +++ b/testing/spectest/minimal/electra__light_client__update_ranking_test.go @@ -7,6 +7,6 @@ import ( "github.com/OffchainLabs/prysm/v6/testing/spectest/shared/common/light_client" ) -func TestMainnet_Electra_LightClient_UpdateRanking(t *testing.T) { +func TestMinimal_Electra_LightClient_UpdateRanking(t *testing.T) { light_client.RunLightClientUpdateRankingTests(t, "minimal", version.Electra) } diff --git a/testing/spectest/shared/common/light_client/BUILD.bazel b/testing/spectest/shared/common/light_client/BUILD.bazel index 8fe775bda4..b4b9bf6c96 100644 --- a/testing/spectest/shared/common/light_client/BUILD.bazel +++ b/testing/spectest/shared/common/light_client/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//beacon-chain/core/light-client:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", + "//config/params:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/light-client:go_default_library", "//container/trie:go_default_library", diff --git a/testing/spectest/shared/common/light_client/update_ranking.go b/testing/spectest/shared/common/light_client/update_ranking.go index e1eae1efff..1b911d6175 100644 --- a/testing/spectest/shared/common/light_client/update_ranking.go +++ b/testing/spectest/shared/common/light_client/update_ranking.go @@ -7,6 +7,7 @@ import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers" lightclient "github.com/OffchainLabs/prysm/v6/beacon-chain/core/light-client" + "github.com/OffchainLabs/prysm/v6/config/params" "github.com/OffchainLabs/prysm/v6/consensus-types/interfaces" lightclienttypes "github.com/OffchainLabs/prysm/v6/consensus-types/light-client" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" @@ -20,6 +21,24 @@ import ( // RunLightClientUpdateRankingTests executes "light_client/update_ranking/pyspec_tests/update_ranking" tests. func RunLightClientUpdateRankingTests(t *testing.T, config string, v int) { require.NoError(t, utils.SetConfig(t, config)) + if v >= version.Altair { + params.BeaconConfig().AltairForkEpoch = 0 + } + if v >= version.Bellatrix { + params.BeaconConfig().BellatrixForkEpoch = 0 + } + if v >= version.Capella { + params.BeaconConfig().CapellaForkEpoch = 0 + } + if v >= version.Deneb { + params.BeaconConfig().DenebForkEpoch = 0 + } + if v >= version.Electra { + params.BeaconConfig().ElectraForkEpoch = 0 + } + if v >= version.Fulu { + params.BeaconConfig().FuluForkEpoch = 0 + } _, testsFolderPath := utils.TestFolders(t, config, version.String(v), "light_client/update_ranking/pyspec_tests/") testTypes, err := util.BazelListDirectories(testsFolderPath)