From 70380660b34857a33cf5229cdfa6985dd62276c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Pernas=20Maradei?= <1394289+nicopernas@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:34:34 +0200 Subject: [PATCH] [1/5] Light client sync protocol (#12853) * generate SyncCommittee SSZ * refactor error handling * rewards: use http2.HandleError * add light client protobuf files * add light client helpers --- beacon-chain/blockchain/BUILD.bazel | 3 + beacon-chain/blockchain/lightclient.go | 246 ++++++ beacon-chain/blockchain/lightclient_test.go | 160 ++++ beacon-chain/rpc/eth/beacon/blinded_blocks.go | 5 +- beacon-chain/rpc/eth/beacon/blocks.go | 25 +- beacon-chain/rpc/eth/helpers/BUILD.bazel | 2 + .../rpc/eth/helpers/error_handling.go | 15 + beacon-chain/rpc/eth/rewards/BUILD.bazel | 4 +- beacon-chain/rpc/eth/rewards/handlers.go | 269 ++----- proto/eth/v2/BUILD.bazel | 2 + proto/eth/v2/beacon_lightclient.pb.go | 733 ++++++++++++++++++ proto/eth/v2/beacon_lightclient.pb.gw.go | 4 + proto/eth/v2/beacon_lightclient.proto | 71 ++ proto/eth/v2/custom.go | 51 ++ proto/eth/v2/generated.ssz.go | 112 ++- proto/prysm/v1alpha1/generated.ssz.go | 2 +- 16 files changed, 1452 insertions(+), 252 deletions(-) create mode 100644 beacon-chain/blockchain/lightclient.go create mode 100644 beacon-chain/blockchain/lightclient_test.go create mode 100755 proto/eth/v2/beacon_lightclient.pb.go create mode 100755 proto/eth/v2/beacon_lightclient.pb.gw.go create mode 100644 proto/eth/v2/beacon_lightclient.proto create mode 100644 proto/eth/v2/custom.go diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index f13aad2058..c6ded52197 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -12,6 +12,7 @@ go_library( "head.go", "head_sync_committee_info.go", "init_sync_process_block.go", + "lightclient.go", "log.go", "merge_ascii_art.go", "metrics.go", @@ -77,6 +78,8 @@ go_library( "//monitoring/tracing:go_default_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", diff --git a/beacon-chain/blockchain/lightclient.go b/beacon-chain/blockchain/lightclient.go new file mode 100644 index 0000000000..cac672d294 --- /dev/null +++ b/beacon-chain/blockchain/lightclient.go @@ -0,0 +1,246 @@ +package blockchain + +import ( + "bytes" + "context" + "fmt" + + "github.com/prysmaticlabs/prysm/v4/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v4/config/params" + "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" + types "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" + ethpbv1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1" + ethpbv2 "github.com/prysmaticlabs/prysm/v4/proto/eth/v2" + "github.com/prysmaticlabs/prysm/v4/proto/migration" + "github.com/prysmaticlabs/prysm/v4/time/slots" +) + +const ( + finalityBranchNumOfLeaves = 6 +) + +// CreateLightClientFinalityUpdate - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_finality_update +// def create_light_client_finality_update(update: LightClientUpdate) -> LightClientFinalityUpdate: +// +// return LightClientFinalityUpdate( +// attested_header=update.attested_header, +// finalized_header=update.finalized_header, +// finality_branch=update.finality_branch, +// sync_aggregate=update.sync_aggregate, +// signature_slot=update.signature_slot, +// ) +func CreateLightClientFinalityUpdate(update *ethpbv2.LightClientUpdate) *ethpbv2.LightClientFinalityUpdate { + return ðpbv2.LightClientFinalityUpdate{ + AttestedHeader: update.AttestedHeader, + FinalizedHeader: update.FinalizedHeader, + FinalityBranch: update.FinalityBranch, + SyncAggregate: update.SyncAggregate, + SignatureSlot: update.SignatureSlot, + } +} + +// CreateLightClientOptimisticUpdate - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_optimistic_update +// def create_light_client_optimistic_update(update: LightClientUpdate) -> LightClientOptimisticUpdate: +// +// return LightClientOptimisticUpdate( +// attested_header=update.attested_header, +// sync_aggregate=update.sync_aggregate, +// signature_slot=update.signature_slot, +// ) +func CreateLightClientOptimisticUpdate(update *ethpbv2.LightClientUpdate) *ethpbv2.LightClientOptimisticUpdate { + return ðpbv2.LightClientOptimisticUpdate{ + AttestedHeader: update.AttestedHeader, + SyncAggregate: update.SyncAggregate, + SignatureSlot: update.SignatureSlot, + } +} + +func NewLightClientOptimisticUpdateFromBeaconState( + ctx context.Context, + state state.BeaconState, + block interfaces.ReadOnlySignedBeaconBlock, + attestedState state.BeaconState) (*ethpbv2.LightClientUpdate, error) { + // assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH + attestedEpoch := slots.ToEpoch(attestedState.Slot()) + if attestedEpoch < types.Epoch(params.BeaconConfig().AltairForkEpoch) { + return nil, fmt.Errorf("invalid attested epoch %d", attestedEpoch) + } + + // assert sum(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS + syncAggregate, err := block.Block().Body().SyncAggregate() + if err != nil { + return nil, fmt.Errorf("could not get sync aggregate %v", err) + } + + if syncAggregate.SyncCommitteeBits.Count() < params.BeaconConfig().MinSyncCommitteeParticipants { + return nil, fmt.Errorf("invalid sync committee bits count %d", syncAggregate.SyncCommitteeBits.Count()) + } + + // assert state.slot == state.latest_block_header.slot + if state.Slot() != state.LatestBlockHeader().Slot { + return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), state.LatestBlockHeader().Slot) + } + + // assert hash_tree_root(header) == hash_tree_root(block.message) + header := state.LatestBlockHeader() + stateRoot, err := state.HashTreeRoot(ctx) + if err != nil { + return nil, fmt.Errorf("could not get state root %v", err) + } + header.StateRoot = stateRoot[:] + + headerRoot, err := header.HashTreeRoot() + if err != nil { + return nil, fmt.Errorf("could not get header root %v", err) + } + + blockRoot, err := block.Block().HashTreeRoot() + if err != nil { + return nil, fmt.Errorf("could not get block root %v", err) + } + + if headerRoot != blockRoot { + return nil, fmt.Errorf("header root %#x not equal to block root %#x", headerRoot, blockRoot) + } + + // assert attested_state.slot == attested_state.latest_block_header.slot + if attestedState.Slot() != attestedState.LatestBlockHeader().Slot { + return nil, fmt.Errorf("attested state slot %d not equal to attested latest block header slot %d", attestedState.Slot(), attestedState.LatestBlockHeader().Slot) + } + + // attested_header = attested_state.latest_block_header.copy() + attestedHeader := attestedState.LatestBlockHeader() + + // attested_header.state_root = hash_tree_root(attested_state) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + if err != nil { + return nil, fmt.Errorf("could not get attested state root %v", err) + } + attestedHeader.StateRoot = attestedStateRoot[:] + + // assert hash_tree_root(attested_header) == block.message.parent_root + attestedHeaderRoot, err := attestedHeader.HashTreeRoot() + if err != nil { + return nil, fmt.Errorf("could not get attested header root %v", err) + } + + if attestedHeaderRoot != block.Block().ParentRoot() { + return nil, fmt.Errorf("attested header root %#x not equal to block parent root %#x", attestedHeaderRoot, block.Block().ParentRoot()) + } + + // Return result + attestedHeaderResult := ðpbv1.BeaconBlockHeader{ + Slot: attestedHeader.Slot, + ProposerIndex: attestedHeader.ProposerIndex, + ParentRoot: attestedHeader.ParentRoot, + StateRoot: attestedHeader.StateRoot, + BodyRoot: attestedHeader.BodyRoot, + } + + syncAggregateResult := ðpbv1.SyncAggregate{ + SyncCommitteeBits: syncAggregate.SyncCommitteeBits, + SyncCommitteeSignature: syncAggregate.SyncCommitteeSignature, + } + + result := ðpbv2.LightClientUpdate{ + AttestedHeader: attestedHeaderResult, + SyncAggregate: syncAggregateResult, + SignatureSlot: block.Block().Slot(), + } + + return result, nil +} + +func NewLightClientFinalityUpdateFromBeaconState( + ctx context.Context, + state state.BeaconState, + block interfaces.ReadOnlySignedBeaconBlock, + attestedState state.BeaconState, + finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientUpdate, error) { + result, err := NewLightClientOptimisticUpdateFromBeaconState( + ctx, + state, + block, + attestedState, + ) + if err != nil { + return nil, err + } + + // Indicate finality whenever possible + var finalizedHeader *ethpbv1.BeaconBlockHeader + var finalityBranch [][]byte + + if finalizedBlock != nil && !finalizedBlock.IsNil() { + if finalizedBlock.Block().Slot() != 0 { + tempFinalizedHeader, err := finalizedBlock.Header() + if err != nil { + return nil, fmt.Errorf("could not get finalized header %v", err) + } + finalizedHeader = migration.V1Alpha1SignedHeaderToV1(tempFinalizedHeader).GetMessage() + + finalizedHeaderRoot, err := finalizedHeader.HashTreeRoot() + if err != nil { + return nil, fmt.Errorf("could not get finalized header root %v", err) + } + + if finalizedHeaderRoot != bytesutil.ToBytes32(attestedState.FinalizedCheckpoint().Root) { + return nil, fmt.Errorf("finalized header root %#x not equal to attested finalized checkpoint root %#x", finalizedHeaderRoot, bytesutil.ToBytes32(attestedState.FinalizedCheckpoint().Root)) + } + } else { + if !bytes.Equal(attestedState.FinalizedCheckpoint().Root, make([]byte, 32)) { + return nil, fmt.Errorf("invalid finalized header root %v", attestedState.FinalizedCheckpoint().Root) + } + + finalizedHeader = ðpbv1.BeaconBlockHeader{ + Slot: 0, + ProposerIndex: 0, + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + } + } + + var bErr error + finalityBranch, bErr = attestedState.FinalizedRootProof(ctx) + if bErr != nil { + return nil, fmt.Errorf("could not get finalized root proof %v", bErr) + } + } else { + finalizedHeader = ðpbv1.BeaconBlockHeader{ + Slot: 0, + ProposerIndex: 0, + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + } + + finalityBranch = make([][]byte, finalityBranchNumOfLeaves) + for i := 0; i < finalityBranchNumOfLeaves; i++ { + finalityBranch[i] = make([]byte, 32) + } + } + + result.FinalizedHeader = finalizedHeader + result.FinalityBranch = finalityBranch + return result, nil +} + +func NewLightClientUpdateFromFinalityUpdate(update *ethpbv2.LightClientFinalityUpdate) *ethpbv2.LightClientUpdate { + return ðpbv2.LightClientUpdate{ + AttestedHeader: update.AttestedHeader, + FinalizedHeader: update.FinalizedHeader, + FinalityBranch: update.FinalityBranch, + SyncAggregate: update.SyncAggregate, + SignatureSlot: update.SignatureSlot, + } +} + +func NewLightClientUpdateFromOptimisticUpdate(update *ethpbv2.LightClientOptimisticUpdate) *ethpbv2.LightClientUpdate { + return ðpbv2.LightClientUpdate{ + AttestedHeader: update.AttestedHeader, + SyncAggregate: update.SyncAggregate, + SignatureSlot: update.SignatureSlot, + } +} diff --git a/beacon-chain/blockchain/lightclient_test.go b/beacon-chain/blockchain/lightclient_test.go new file mode 100644 index 0000000000..a2a355135b --- /dev/null +++ b/beacon-chain/blockchain/lightclient_test.go @@ -0,0 +1,160 @@ +package blockchain + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/prysm/v4/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v4/config/params" + "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" + v1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1" + ethpbv2 "github.com/prysmaticlabs/prysm/v4/proto/eth/v2" + ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v4/testing/require" + "github.com/prysmaticlabs/prysm/v4/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") + } +} diff --git a/beacon-chain/rpc/eth/beacon/blinded_blocks.go b/beacon-chain/rpc/eth/beacon/blinded_blocks.go index 69dfbb54c7..bfee232ebe 100644 --- a/beacon-chain/rpc/eth/beacon/blinded_blocks.go +++ b/beacon-chain/rpc/eth/beacon/blinded_blocks.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v4/api" + rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers" consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types" "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" ethpbv1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1" @@ -24,7 +25,7 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest defer span.End() blk, err := bs.Blocker.Block(ctx, req.BlockId) - err = handleGetBlockError(blk, err) + err = rpchelpers.HandleGetBlockError(blk, err) if err != nil { return nil, err } @@ -90,7 +91,7 @@ func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequ defer span.End() blk, err := bs.Blocker.Block(ctx, req.BlockId) - err = handleGetBlockError(blk, err) + err = rpchelpers.HandleGetBlockError(blk, err) if err != nil { return nil, err } diff --git a/beacon-chain/rpc/eth/beacon/blocks.go b/beacon-chain/rpc/eth/beacon/blocks.go index 39003a29ea..0d8c58d3bc 100644 --- a/beacon-chain/rpc/eth/beacon/blocks.go +++ b/beacon-chain/rpc/eth/beacon/blocks.go @@ -9,10 +9,8 @@ import ( "github.com/prysmaticlabs/prysm/v4/api" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers" rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup" "github.com/prysmaticlabs/prysm/v4/config/params" consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types" - "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" ethpbv1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1" ethpbv2 "github.com/prysmaticlabs/prysm/v4/proto/eth/v2" @@ -79,7 +77,7 @@ func (bs *Server) GetBlock(ctx context.Context, req *ethpbv1.BlockRequest) (*eth defer span.End() blk, err := bs.Blocker.Block(ctx, req.BlockId) - err = handleGetBlockError(blk, err) + err = rpchelpers.HandleGetBlockError(blk, err) if err != nil { return nil, err } @@ -103,7 +101,7 @@ func (bs *Server) GetBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequest) (* defer span.End() blk, err := bs.Blocker.Block(ctx, req.BlockId) - err = handleGetBlockError(blk, err) + err = rpchelpers.HandleGetBlockError(blk, err) if err != nil { return nil, err } @@ -125,7 +123,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) ( defer span.End() blk, err := bs.Blocker.Block(ctx, req.BlockId) - err = handleGetBlockError(blk, err) + err = rpchelpers.HandleGetBlockError(blk, err) if err != nil { return nil, err } @@ -193,7 +191,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 defer span.End() blk, err := bs.Blocker.Block(ctx, req.BlockId) - err = handleGetBlockError(blk, err) + err = rpchelpers.HandleGetBlockError(blk, err) if err != nil { return nil, err } @@ -258,7 +256,7 @@ func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpbv1.BlockR defer span.End() blk, err := bs.Blocker.Block(ctx, req.BlockId) - err = handleGetBlockError(blk, err) + err = rpchelpers.HandleGetBlockError(blk, err) if err != nil { return nil, err } @@ -284,19 +282,6 @@ func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpbv1.BlockR }, nil } -func handleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) error { - if invalidBlockIdErr, ok := err.(*lookup.BlockIdParseError); ok { - return status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr) - } - if err != nil { - return status.Errorf(codes.Internal, "Could not get block from block ID: %v", err) - } - if err := blocks.BeaconBlockIsNil(blk); err != nil { - return status.Errorf(codes.NotFound, "Could not find requested block: %v", err) - } - return nil -} - func getBlockPhase0(blk interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.BlockResponseV2, error) { phase0Blk, err := blk.PbPhase0Block() if err != nil { diff --git a/beacon-chain/rpc/eth/helpers/BUILD.bazel b/beacon-chain/rpc/eth/helpers/BUILD.bazel index 3c695ede87..90731bcb4c 100644 --- a/beacon-chain/rpc/eth/helpers/BUILD.bazel +++ b/beacon-chain/rpc/eth/helpers/BUILD.bazel @@ -20,6 +20,8 @@ go_library( "//beacon-chain/state/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", "//encoding/bytesutil:go_default_library", diff --git a/beacon-chain/rpc/eth/helpers/error_handling.go b/beacon-chain/rpc/eth/helpers/error_handling.go index 8e2967a36b..eba1ed8a40 100644 --- a/beacon-chain/rpc/eth/helpers/error_handling.go +++ b/beacon-chain/rpc/eth/helpers/error_handling.go @@ -5,6 +5,8 @@ import ( "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -34,3 +36,16 @@ type SingleIndexedVerificationFailure struct { Index int `json:"index"` Message string `json:"message"` } + +func HandleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) error { + if invalidBlockIdErr, ok := err.(*lookup.BlockIdParseError); ok { + return status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr) + } + if err != nil { + return status.Errorf(codes.Internal, "Could not get block from block ID: %v", err) + } + if err := blocks.BeaconBlockIsNil(blk); err != nil { + return status.Errorf(codes.NotFound, "Could not find requested block: %v", err) + } + return nil +} diff --git a/beacon-chain/rpc/eth/rewards/BUILD.bazel b/beacon-chain/rpc/eth/rewards/BUILD.bazel index d929d57169..ba347f3e10 100644 --- a/beacon-chain/rpc/eth/rewards/BUILD.bazel +++ b/beacon-chain/rpc/eth/rewards/BUILD.bazel @@ -15,18 +15,16 @@ go_library( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/validators:go_default_library", + "//beacon-chain/rpc/eth/shared:go_default_library", "//beacon-chain/rpc/lookup:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/stategen:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", - "//consensus-types/blocks:go_default_library", - "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//network/http:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", - "@com_github_pkg_errors//:go_default_library", "@com_github_wealdtech_go_bytesutil//:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/rewards/handlers.go b/beacon-chain/rpc/eth/rewards/handlers.go index fd0ed66316..34a3049d4e 100644 --- a/beacon-chain/rpc/eth/rewards/handlers.go +++ b/beacon-chain/rpc/eth/rewards/handlers.go @@ -7,17 +7,14 @@ import ( "strconv" "strings" - "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair" coreblocks "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" "github.com/prysmaticlabs/prysm/v4/config/params" - "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" - "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" http2 "github.com/prysmaticlabs/prysm/v4/network/http" "github.com/prysmaticlabs/prysm/v4/runtime/version" @@ -31,16 +28,11 @@ func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) { blockId := segments[len(segments)-1] blk, err := s.Blocker.Block(r.Context(), []byte(blockId)) - if errJson := handleGetBlockError(blk, err); errJson != nil { - http2.WriteError(w, errJson) + if !shared.WriteBlockFetchError(w, blk, err) { return } if blk.Version() == version.Phase0 { - errJson := &http2.DefaultErrorJson{ - Message: "Block rewards are not supported for Phase 0 blocks", - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Block rewards are not supported for Phase 0 blocks", http.StatusBadRequest) return } @@ -49,114 +41,66 @@ func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) { // To do this, we replay the state up to the block's slot, but before processing the block. st, err := s.ReplayerBuilder.ReplayerForSlot(blk.Block().Slot()-1).ReplayToSlot(r.Context(), blk.Block().Slot()) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get state: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get state: "+err.Error(), http.StatusInternalServerError) return } proposerIndex := blk.Block().ProposerIndex() initBalance, err := st.BalanceAtIndex(proposerIndex) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get proposer's balance: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError) return } st, err = altair.ProcessAttestationsNoVerifySignature(r.Context(), st, blk) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get attestation rewards" + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get attestation rewards"+err.Error(), http.StatusInternalServerError) return } attBalance, err := st.BalanceAtIndex(proposerIndex) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get proposer's balance: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError) return } st, err = coreblocks.ProcessAttesterSlashings(r.Context(), st, blk.Block().Body().AttesterSlashings(), validators.SlashValidator) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get attester slashing rewards: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get attester slashing rewards: "+err.Error(), http.StatusInternalServerError) return } attSlashingsBalance, err := st.BalanceAtIndex(proposerIndex) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get proposer's balance: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError) return } st, err = coreblocks.ProcessProposerSlashings(r.Context(), st, blk.Block().Body().ProposerSlashings(), validators.SlashValidator) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get proposer slashing rewards" + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get proposer slashing rewards"+err.Error(), http.StatusInternalServerError) return } proposerSlashingsBalance, err := st.BalanceAtIndex(proposerIndex) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get proposer's balance: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError) return } sa, err := blk.Block().Body().SyncAggregate() if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get sync aggregate: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get sync aggregate: "+err.Error(), http.StatusInternalServerError) return } var syncCommitteeReward uint64 _, syncCommitteeReward, err = altair.ProcessSyncAggregate(r.Context(), st, sa) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get sync aggregate rewards: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get sync aggregate rewards: "+err.Error(), http.StatusInternalServerError) return } optimistic, err := s.OptimisticModeFetcher.IsOptimistic(r.Context()) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get optimistic mode info: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get optimistic mode info: "+err.Error(), http.StatusInternalServerError) return } blkRoot, err := blk.Block().HashTreeRoot() if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get block root: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError) return } @@ -198,20 +142,12 @@ func (s *Server) AttestationRewards(w http.ResponseWriter, r *http.Request) { optimistic, err := s.OptimisticModeFetcher.IsOptimistic(r.Context()) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get optimistic mode info: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get optimistic mode info: "+err.Error(), http.StatusInternalServerError) return } blkRoot, err := st.LatestBlockHeader().HashTreeRoot() if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get block root: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError) return } @@ -233,34 +169,21 @@ func (s *Server) SyncCommitteeRewards(w http.ResponseWriter, r *http.Request) { blockId := segments[len(segments)-1] blk, err := s.Blocker.Block(r.Context(), []byte(blockId)) - if errJson := handleGetBlockError(blk, err); errJson != nil { - http2.WriteError(w, errJson) + if !shared.WriteBlockFetchError(w, blk, err) { return } if blk.Version() == version.Phase0 { - errJson := &http2.DefaultErrorJson{ - Message: "Sync committee rewards are not supported for Phase 0", - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Sync committee rewards are not supported for Phase 0", http.StatusBadRequest) return } st, err := s.ReplayerBuilder.ReplayerForSlot(blk.Block().Slot()-1).ReplayToSlot(r.Context(), blk.Block().Slot()) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get state: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get state: "+err.Error(), http.StatusInternalServerError) return } sa, err := blk.Block().Body().SyncAggregate() if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get sync aggregate: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get sync aggregate: "+err.Error(), http.StatusInternalServerError) return } @@ -272,22 +195,14 @@ func (s *Server) SyncCommitteeRewards(w http.ResponseWriter, r *http.Request) { for i, valIdx := range valIndices { preProcessBals[i], err = st.BalanceAtIndex(valIdx) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get validator's balance: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get validator's balance: "+err.Error(), http.StatusInternalServerError) return } } _, proposerReward, err := altair.ProcessSyncAggregate(r.Context(), st, sa) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get sync aggregate rewards: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get sync aggregate rewards: "+err.Error(), http.StatusInternalServerError) return } @@ -296,11 +211,7 @@ func (s *Server) SyncCommitteeRewards(w http.ResponseWriter, r *http.Request) { for i, valIdx := range valIndices { bal, err := st.BalanceAtIndex(valIdx) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get validator's balance: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get validator's balance: "+err.Error(), http.StatusInternalServerError) return } rewards[i] = int(bal - preProcessBals[i]) // lint:ignore uintcast @@ -311,20 +222,12 @@ func (s *Server) SyncCommitteeRewards(w http.ResponseWriter, r *http.Request) { optimistic, err := s.OptimisticModeFetcher.IsOptimistic(r.Context()) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get optimistic mode info: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get optimistic mode info: "+err.Error(), http.StatusInternalServerError) return } blkRoot, err := blk.Block().HashTreeRoot() if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get block root: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError) return } @@ -347,46 +250,28 @@ func (s *Server) attRewardsState(w http.ResponseWriter, r *http.Request) (state. segments := strings.Split(r.URL.Path, "/") requestedEpoch, err := strconv.ParseUint(segments[len(segments)-1], 10, 64) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not decode epoch: " + err.Error(), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not decode epoch: "+err.Error(), http.StatusBadRequest) return nil, false } if primitives.Epoch(requestedEpoch) < params.BeaconConfig().AltairForkEpoch { - errJson := &http2.DefaultErrorJson{ - Message: "Attestation rewards are not supported for Phase 0", - Code: http.StatusNotFound, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Attestation rewards are not supported for Phase 0", http.StatusNotFound) return nil, false } currentEpoch := uint64(slots.ToEpoch(s.TimeFetcher.CurrentSlot())) if requestedEpoch+1 >= currentEpoch { - errJson := &http2.DefaultErrorJson{ - Code: http.StatusNotFound, - Message: "Attestation rewards are available after two epoch transitions to ensure all attestations have a chance of inclusion", - } - http2.WriteError(w, errJson) + http2.HandleError(w, + "Attestation rewards are available after two epoch transitions to ensure all attestations have a chance of inclusion", + http.StatusNotFound) return nil, false } nextEpochEnd, err := slots.EpochEnd(primitives.Epoch(requestedEpoch + 1)) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get next epoch's ending slot: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get next epoch's ending slot: "+err.Error(), http.StatusInternalServerError) return nil, false } st, err := s.Stater.StateBySlot(r.Context(), nextEpochEnd) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get state for epoch's starting slot: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get state for epoch's starting slot: "+err.Error(), http.StatusInternalServerError) return nil, false } return st, true @@ -399,20 +284,12 @@ func attRewardsBalancesAndVals( ) (*precompute.Balance, []*precompute.Validator, []primitives.ValidatorIndex, bool) { allVals, bal, err := altair.InitializePrecomputeValidators(r.Context(), st) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not initialize precompute validators: " + err.Error(), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not initialize precompute validators: "+err.Error(), http.StatusBadRequest) return nil, nil, nil, false } allVals, bal, err = altair.ProcessEpochParticipation(r.Context(), st, bal, allVals) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not process epoch participation: " + err.Error(), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not process epoch participation: "+err.Error(), http.StatusBadRequest) return nil, nil, nil, false } valIndices, ok := requestedValIndices(w, r, st, allVals) @@ -463,11 +340,7 @@ func idealAttRewards( } deltas, err := altair.AttestationsDelta(st, bal, idealVals) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get attestations delta: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get attestations delta: "+err.Error(), http.StatusInternalServerError) return nil, false } for i, d := range deltas { @@ -499,11 +372,7 @@ func totalAttRewards( } deltas, err := altair.AttestationsDelta(st, bal, vals) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get attestations delta: " + err.Error(), - Code: http.StatusInternalServerError, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get attestations delta: "+err.Error(), http.StatusInternalServerError) return nil, false } for i, d := range deltas { @@ -529,11 +398,7 @@ func syncRewardsVals( ) ([]*precompute.Validator, []primitives.ValidatorIndex, bool) { allVals, _, err := altair.InitializePrecomputeValidators(r.Context(), st) if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not initialize precompute validators: " + err.Error(), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not initialize precompute validators: "+err.Error(), http.StatusBadRequest) return nil, nil, false } valIndices, ok := requestedValIndices(w, r, st, allVals) @@ -543,22 +408,14 @@ func syncRewardsVals( sc, err := st.CurrentSyncCommittee() if err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not get current sync committee: " + err.Error(), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not get current sync committee: "+err.Error(), http.StatusBadRequest) return nil, nil, false } allScIndices := make([]primitives.ValidatorIndex, len(sc.Pubkeys)) for i, pk := range sc.Pubkeys { valIdx, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(pk)) if !ok { - errJson := &http2.DefaultErrorJson{ - Message: fmt.Sprintf("No validator index found for pubkey %#x", pk), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, fmt.Sprintf("No validator index found for pubkey %#x", pk), http.StatusBadRequest) return nil, nil, false } allScIndices[i] = valIdx @@ -583,11 +440,7 @@ func requestedValIndices(w http.ResponseWriter, r *http.Request, st state.Beacon var rawValIds []string if r.Body != http.NoBody { if err := json.NewDecoder(r.Body).Decode(&rawValIds); err != nil { - errJson := &http2.DefaultErrorJson{ - Message: "Could not decode validators: " + err.Error(), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, "Could not decode validators: "+err.Error(), http.StatusBadRequest) return nil, false } } @@ -597,30 +450,18 @@ func requestedValIndices(w http.ResponseWriter, r *http.Request, st state.Beacon if err != nil { pubkey, err := bytesutil.FromHexString(v) if err != nil || len(pubkey) != fieldparams.BLSPubkeyLength { - errJson := &http2.DefaultErrorJson{ - Message: fmt.Sprintf("%s is not a validator index or pubkey", v), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, fmt.Sprintf("%s is not a validator index or pubkey", v), http.StatusBadRequest) return nil, false } var ok bool valIndices[i], ok = st.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubkey)) if !ok { - errJson := &http2.DefaultErrorJson{ - Message: fmt.Sprintf("No validator index found for pubkey %#x", pubkey), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, fmt.Sprintf("No validator index found for pubkey %#x", pubkey), http.StatusBadRequest) return nil, false } } else { if index >= uint64(st.NumValidators()) { - errJson := &http2.DefaultErrorJson{ - Message: fmt.Sprintf("Validator index %d is too large. Maximum allowed index is %d", index, st.NumValidators()-1), - Code: http.StatusBadRequest, - } - http2.WriteError(w, errJson) + http2.HandleError(w, fmt.Sprintf("Validator index %d is too large. Maximum allowed index is %d", index, st.NumValidators()-1), http.StatusBadRequest) return nil, false } valIndices[i] = primitives.ValidatorIndex(index) @@ -635,25 +476,3 @@ func requestedValIndices(w http.ResponseWriter, r *http.Request, st state.Beacon return valIndices, true } - -func handleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) *http2.DefaultErrorJson { - if errors.Is(err, lookup.BlockIdParseError{}) { - return &http2.DefaultErrorJson{ - Message: "Invalid block ID: " + err.Error(), - Code: http.StatusBadRequest, - } - } - if err != nil { - return &http2.DefaultErrorJson{ - Message: "Could not get block from block ID: " + err.Error(), - Code: http.StatusInternalServerError, - } - } - if err := blocks.BeaconBlockIsNil(blk); err != nil { - return &http2.DefaultErrorJson{ - Message: "Could not find requested block: " + err.Error(), - Code: http.StatusNotFound, - } - } - return nil -} diff --git a/proto/eth/v2/BUILD.bazel b/proto/eth/v2/BUILD.bazel index b913bd33a3..6c12bc3394 100644 --- a/proto/eth/v2/BUILD.bazel +++ b/proto/eth/v2/BUILD.bazel @@ -56,6 +56,7 @@ ssz_gen_marshal( "SignedBlindedBeaconBlockContentsDeneb", "BeaconBlockContentsDeneb", "BlindedBeaconBlockContentsDeneb", + "SyncCommittee", ], ) @@ -103,6 +104,7 @@ ssz_proto_files( name = "ssz_proto_files", srcs = [ "beacon_block.proto", + "beacon_lightclient.proto", "beacon_state.proto", "blobs.proto", "sync_committee.proto", diff --git a/proto/eth/v2/beacon_lightclient.pb.go b/proto/eth/v2/beacon_lightclient.pb.go new file mode 100755 index 0000000000..df0bc8b18c --- /dev/null +++ b/proto/eth/v2/beacon_lightclient.pb.go @@ -0,0 +1,733 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v4.23.3 +// source: proto/eth/v2/beacon_lightclient.proto + +package eth + +import ( + reflect "reflect" + sync "sync" + + github_com_prysmaticlabs_prysm_v4_consensus_types_primitives "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" + _ "github.com/prysmaticlabs/prysm/v4/proto/eth/ext" + v1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type LightClientBootstrap struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Header *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` + CurrentSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=current_sync_committee_branch,json=currentSyncCommitteeBranch,proto3" json:"current_sync_committee_branch,omitempty" ssz-size:"current_sync_committee_branch.depth,32"` +} + +func (x *LightClientBootstrap) Reset() { + *x = LightClientBootstrap{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientBootstrap) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientBootstrap) ProtoMessage() {} + +func (x *LightClientBootstrap) ProtoReflect() protoreflect.Message { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[0] + 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 LightClientBootstrap.ProtoReflect.Descriptor instead. +func (*LightClientBootstrap) Descriptor() ([]byte, []int) { + return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{0} +} + +func (x *LightClientBootstrap) GetHeader() *v1.BeaconBlockHeader { + if x != nil { + return x.Header + } + return nil +} + +func (x *LightClientBootstrap) GetCurrentSyncCommittee() *SyncCommittee { + if x != nil { + return x.CurrentSyncCommittee + } + return nil +} + +func (x *LightClientBootstrap) GetCurrentSyncCommitteeBranch() [][]byte { + if x != nil { + return x.CurrentSyncCommitteeBranch + } + return nil +} + +type LightClientUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + NextSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` + NextSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=next_sync_committee_branch,json=nextSyncCommitteeBranch,proto3" json:"next_sync_committee_branch,omitempty" ssz-size:"next_sync_committee_branch.depth,32"` + FinalizedHeader *v1.BeaconBlockHeader `protobuf:"bytes,4,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,5,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"finality_branch.depth,32"` + SyncAggregate *v1.SyncAggregate `protobuf:"bytes,6,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot `protobuf:"varint,7,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Slot"` +} + +func (x *LightClientUpdate) Reset() { + *x = LightClientUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientUpdate) ProtoMessage() {} + +func (x *LightClientUpdate) ProtoReflect() protoreflect.Message { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[1] + 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 LightClientUpdate.ProtoReflect.Descriptor instead. +func (*LightClientUpdate) Descriptor() ([]byte, []int) { + return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{1} +} + +func (x *LightClientUpdate) GetAttestedHeader() *v1.BeaconBlockHeader { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientUpdate) GetNextSyncCommittee() *SyncCommittee { + if x != nil { + return x.NextSyncCommittee + } + return nil +} + +func (x *LightClientUpdate) GetNextSyncCommitteeBranch() [][]byte { + if x != nil { + return x.NextSyncCommitteeBranch + } + return nil +} + +func (x *LightClientUpdate) GetFinalizedHeader() *v1.BeaconBlockHeader { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientUpdate) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientUpdate) GetSyncAggregate() *v1.SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientUpdate) GetSignatureSlot() github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot(0) +} + +type LightClientFinalityUpdateWithVersion 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 *LightClientFinalityUpdate `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *LightClientFinalityUpdateWithVersion) Reset() { + *x = LightClientFinalityUpdateWithVersion{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientFinalityUpdateWithVersion) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientFinalityUpdateWithVersion) ProtoMessage() {} + +func (x *LightClientFinalityUpdateWithVersion) ProtoReflect() protoreflect.Message { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[2] + 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 LightClientFinalityUpdateWithVersion.ProtoReflect.Descriptor instead. +func (*LightClientFinalityUpdateWithVersion) Descriptor() ([]byte, []int) { + return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{2} +} + +func (x *LightClientFinalityUpdateWithVersion) GetVersion() Version { + if x != nil { + return x.Version + } + return Version_PHASE0 +} + +func (x *LightClientFinalityUpdateWithVersion) GetData() *LightClientFinalityUpdate { + if x != nil { + return x.Data + } + return nil +} + +type LightClientFinalityUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + FinalizedHeader *v1.BeaconBlockHeader `protobuf:"bytes,2,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,3,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"finality_branch.depth,32"` + SyncAggregate *v1.SyncAggregate `protobuf:"bytes,4,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot `protobuf:"varint,5,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Slot"` +} + +func (x *LightClientFinalityUpdate) Reset() { + *x = LightClientFinalityUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientFinalityUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientFinalityUpdate) ProtoMessage() {} + +func (x *LightClientFinalityUpdate) ProtoReflect() protoreflect.Message { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[3] + 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 LightClientFinalityUpdate.ProtoReflect.Descriptor instead. +func (*LightClientFinalityUpdate) Descriptor() ([]byte, []int) { + return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{3} +} + +func (x *LightClientFinalityUpdate) GetAttestedHeader() *v1.BeaconBlockHeader { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientFinalityUpdate) GetFinalizedHeader() *v1.BeaconBlockHeader { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientFinalityUpdate) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientFinalityUpdate) GetSyncAggregate() *v1.SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientFinalityUpdate) GetSignatureSlot() github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot(0) +} + +type LightClientOptimisticUpdateWithVersion 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 *LightClientOptimisticUpdate `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *LightClientOptimisticUpdateWithVersion) Reset() { + *x = LightClientOptimisticUpdateWithVersion{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientOptimisticUpdateWithVersion) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientOptimisticUpdateWithVersion) ProtoMessage() {} + +func (x *LightClientOptimisticUpdateWithVersion) ProtoReflect() protoreflect.Message { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[4] + 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 LightClientOptimisticUpdateWithVersion.ProtoReflect.Descriptor instead. +func (*LightClientOptimisticUpdateWithVersion) Descriptor() ([]byte, []int) { + return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{4} +} + +func (x *LightClientOptimisticUpdateWithVersion) GetVersion() Version { + if x != nil { + return x.Version + } + return Version_PHASE0 +} + +func (x *LightClientOptimisticUpdateWithVersion) GetData() *LightClientOptimisticUpdate { + if x != nil { + return x.Data + } + return nil +} + +type LightClientOptimisticUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + SyncAggregate *v1.SyncAggregate `protobuf:"bytes,2,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot `protobuf:"varint,3,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Slot"` +} + +func (x *LightClientOptimisticUpdate) Reset() { + *x = LightClientOptimisticUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientOptimisticUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientOptimisticUpdate) ProtoMessage() {} + +func (x *LightClientOptimisticUpdate) ProtoReflect() protoreflect.Message { + mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[5] + 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 LightClientOptimisticUpdate.ProtoReflect.Descriptor instead. +func (*LightClientOptimisticUpdate) Descriptor() ([]byte, []int) { + return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{5} +} + +func (x *LightClientOptimisticUpdate) GetAttestedHeader() *v1.BeaconBlockHeader { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientOptimisticUpdate) GetSyncAggregate() *v1.SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientOptimisticUpdate) GetSignatureSlot() github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot(0) +} + +var File_proto_eth_v2_beacon_lightclient_proto protoreflect.FileDescriptor + +var file_proto_eth_v2_beacon_lightclient_proto_rawDesc = []byte{ + 0x0a, 0x25, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, + 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x97, 0x02, 0x0a, 0x14, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x12, 0x3a, + 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x16, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, + 0x12, 0x6d, 0x0a, 0x1d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, + 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x2a, 0x8a, 0xb5, 0x18, 0x26, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x2e, 0x64, 0x65, 0x70, 0x74, 0x68, + 0x2c, 0x33, 0x32, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, + 0xe1, 0x04, 0x0a, 0x11, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x32, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, + 0x11, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x12, 0x64, 0x0a, 0x1a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x27, 0x8a, 0xb5, 0x18, 0x23, 0x6e, 0x65, 0x78, 0x74, + 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, + 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x2e, 0x64, 0x65, 0x70, 0x74, 0x68, 0x2c, 0x33, 0x32, 0x52, + 0x17, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4d, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, + 0x42, 0x1c, 0x8a, 0xb5, 0x18, 0x18, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x2e, 0x64, 0x65, 0x70, 0x74, 0x68, 0x2c, 0x33, 0x32, 0x52, 0x0e, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x45, + 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, + 0xb5, 0x18, 0x41, 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, 0x34, 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, 0x22, 0x9a, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 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, 0x3e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, + 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, 0x46, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x22, 0xb3, 0x03, 0x0a, 0x19, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x4b, + 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0e, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4d, 0x0a, 0x10, 0x66, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x0f, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0c, 0x42, 0x1c, 0x8a, 0xb5, 0x18, 0x18, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x2e, 0x64, 0x65, 0x70, 0x74, 0x68, 0x2c, 0x33, + 0x32, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x34, 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, 0x22, 0x9e, 0x01, 0x0a, 0x26, 0x4c, 0x69, 0x67, 0x68, 0x74, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, + 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, 0x40, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2c, 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, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x9f, 0x02, 0x0a, 0x1b, 0x4c, 0x69, 0x67, 0x68, + 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, + 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, + 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x34, 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, 0x34, 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 ( + file_proto_eth_v2_beacon_lightclient_proto_rawDescOnce sync.Once + file_proto_eth_v2_beacon_lightclient_proto_rawDescData = file_proto_eth_v2_beacon_lightclient_proto_rawDesc +) + +func file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP() []byte { + file_proto_eth_v2_beacon_lightclient_proto_rawDescOnce.Do(func() { + file_proto_eth_v2_beacon_lightclient_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_beacon_lightclient_proto_rawDescData) + }) + 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_goTypes = []interface{}{ + (*LightClientBootstrap)(nil), // 0: ethereum.eth.v2.LightClientBootstrap + (*LightClientUpdate)(nil), // 1: ethereum.eth.v2.LightClientUpdate + (*LightClientFinalityUpdateWithVersion)(nil), // 2: ethereum.eth.v2.LightClientFinalityUpdateWithVersion + (*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 +} +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 + 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 + 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 +} + +func init() { file_proto_eth_v2_beacon_lightclient_proto_init() } +func file_proto_eth_v2_beacon_lightclient_proto_init() { + if File_proto_eth_v2_beacon_lightclient_proto != nil { + return + } + file_proto_eth_v2_version_proto_init() + file_proto_eth_v2_sync_committee_proto_init() + if !protoimpl.UnsafeEnabled { + file_proto_eth_v2_beacon_lightclient_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientBootstrap); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_eth_v2_beacon_lightclient_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientUpdate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_eth_v2_beacon_lightclient_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientFinalityUpdateWithVersion); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_eth_v2_beacon_lightclient_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientFinalityUpdate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_eth_v2_beacon_lightclient_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientOptimisticUpdateWithVersion); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_eth_v2_beacon_lightclient_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientOptimisticUpdate); 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{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_eth_v2_beacon_lightclient_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_eth_v2_beacon_lightclient_proto_goTypes, + DependencyIndexes: file_proto_eth_v2_beacon_lightclient_proto_depIdxs, + MessageInfos: file_proto_eth_v2_beacon_lightclient_proto_msgTypes, + }.Build() + File_proto_eth_v2_beacon_lightclient_proto = out.File + file_proto_eth_v2_beacon_lightclient_proto_rawDesc = nil + file_proto_eth_v2_beacon_lightclient_proto_goTypes = nil + file_proto_eth_v2_beacon_lightclient_proto_depIdxs = nil +} diff --git a/proto/eth/v2/beacon_lightclient.pb.gw.go b/proto/eth/v2/beacon_lightclient.pb.gw.go new file mode 100755 index 0000000000..cdd03643f0 --- /dev/null +++ b/proto/eth/v2/beacon_lightclient.pb.gw.go @@ -0,0 +1,4 @@ +//go:build ignore +// +build ignore + +package ignore diff --git a/proto/eth/v2/beacon_lightclient.proto b/proto/eth/v2/beacon_lightclient.proto new file mode 100644 index 0000000000..a06873a9b0 --- /dev/null +++ b/proto/eth/v2/beacon_lightclient.proto @@ -0,0 +1,71 @@ +// Copyright 2023 Prysmatic Labs. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; + +package ethereum.eth.v2; + +import "proto/eth/ext/options.proto"; +import "proto/eth/v1/attestation.proto"; +import "proto/eth/v1/beacon_block.proto"; +import "proto/eth/v2/version.proto"; +import "proto/eth/v2/sync_committee.proto"; + +option csharp_namespace = "Ethereum.Eth.V2"; +option go_package = "github.com/prysmaticlabs/prysm/v4/proto/eth/v2;eth"; +option java_multiple_files = true; +option java_outer_classname = "SyncCommitteeProto"; +option java_package = "org.ethereum.eth.v2"; +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 [(ethereum.eth.ext.ssz_size) = "current_sync_committee_branch.depth,32"]; +} + +message LightClientUpdate { + v1.BeaconBlockHeader attested_header = 1; + SyncCommittee next_sync_committee = 2; + repeated bytes next_sync_committee_branch = 3 [(ethereum.eth.ext.ssz_size) = "next_sync_committee_branch.depth,32"]; + v1.BeaconBlockHeader finalized_header = 4; + repeated bytes finality_branch = 5 [(ethereum.eth.ext.ssz_size) = "finality_branch.depth,32"]; + v1.SyncAggregate sync_aggregate = 6; + uint64 signature_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Slot"]; +} + +message LightClientFinalityUpdateWithVersion { + v2.Version version = 1; + LightClientFinalityUpdate data = 2; +} + +message LightClientFinalityUpdate { + v1.BeaconBlockHeader attested_header = 1; + v1.BeaconBlockHeader finalized_header = 2; + repeated bytes finality_branch = 3 [(ethereum.eth.ext.ssz_size) = "finality_branch.depth,32"]; + v1.SyncAggregate sync_aggregate = 4; + uint64 signature_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Slot"]; +} + +message LightClientOptimisticUpdateWithVersion { + 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/v4/consensus-types/primitives.Slot"]; +} diff --git a/proto/eth/v2/custom.go b/proto/eth/v2/custom.go new file mode 100644 index 0000000000..86132bd84e --- /dev/null +++ b/proto/eth/v2/custom.go @@ -0,0 +1,51 @@ +package eth + +import ( + "bytes" + "math/bits" +) + +const ( + NextSyncCommitteeIndex = uint64(55) + FinalizedRootIndex = uint64(105) +) + +func (x *SyncCommittee) Equals(other *SyncCommittee) bool { + if len(x.Pubkeys) != len(other.Pubkeys) { + return false + } + for i := range x.Pubkeys { + if !bytes.Equal(x.Pubkeys[i], other.Pubkeys[i]) { + return false + } + } + return bytes.Equal(x.AggregatePubkey, other.AggregatePubkey) +} + +func FloorLog2(x uint64) int { + return bits.Len64(uint64(x - 1)) +} + +func isEmptyWithLength(bb [][]byte, length uint64) bool { + if len(bb) == 0 { + return true + } + l := FloorLog2(length) + if len(bb) != l { + return false + } + for _, b := range bb { + if !bytes.Equal(b, []byte{}) { + return false + } + } + return true +} + +func (x *LightClientUpdate) IsSyncCommiteeUpdate() bool { + return !isEmptyWithLength(x.GetNextSyncCommitteeBranch(), NextSyncCommitteeIndex) +} + +func (x *LightClientUpdate) IsFinalityUpdate() bool { + return !isEmptyWithLength(x.GetFinalityBranch(), FinalizedRootIndex) +} diff --git a/proto/eth/v2/generated.ssz.go b/proto/eth/v2/generated.ssz.go index a3be77536b..9df0f23e2b 100644 --- a/proto/eth/v2/generated.ssz.go +++ b/proto/eth/v2/generated.ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: c5b73fa04173f2f7ff57471820227c1c57ed2cf64771a033a8dd7661476b1534 +// Hash: 9f41b0f86969914896f5badce70d6303794e4bdeb09b0c2d95d11631f7863042 package eth import ( @@ -7039,6 +7039,116 @@ func (b *BlindedBlobSidecar) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } +// MarshalSSZ ssz marshals the SyncCommittee object +func (s *SyncCommittee) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SyncCommittee object to a target array +func (s *SyncCommittee) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Pubkeys' + if size := len(s.Pubkeys); size != 512 { + err = ssz.ErrVectorLengthFn("--.Pubkeys", size, 512) + return + } + for ii := 0; ii < 512; ii++ { + if size := len(s.Pubkeys[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.Pubkeys[ii]", size, 48) + return + } + dst = append(dst, s.Pubkeys[ii]...) + } + + // Field (1) 'AggregatePubkey' + if size := len(s.AggregatePubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.AggregatePubkey", size, 48) + return + } + dst = append(dst, s.AggregatePubkey...) + + return +} + +// UnmarshalSSZ ssz unmarshals the SyncCommittee object +func (s *SyncCommittee) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 24624 { + return ssz.ErrSize + } + + // Field (0) 'Pubkeys' + s.Pubkeys = make([][]byte, 512) + for ii := 0; ii < 512; ii++ { + if cap(s.Pubkeys[ii]) == 0 { + s.Pubkeys[ii] = make([]byte, 0, len(buf[0:24576][ii*48:(ii+1)*48])) + } + s.Pubkeys[ii] = append(s.Pubkeys[ii], buf[0:24576][ii*48:(ii+1)*48]...) + } + + // Field (1) 'AggregatePubkey' + if cap(s.AggregatePubkey) == 0 { + s.AggregatePubkey = make([]byte, 0, len(buf[24576:24624])) + } + s.AggregatePubkey = append(s.AggregatePubkey, buf[24576:24624]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SyncCommittee object +func (s *SyncCommittee) SizeSSZ() (size int) { + size = 24624 + return +} + +// HashTreeRoot ssz hashes the SyncCommittee object +func (s *SyncCommittee) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SyncCommittee object with a hasher +func (s *SyncCommittee) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Pubkeys' + { + if size := len(s.Pubkeys); size != 512 { + err = ssz.ErrVectorLengthFn("--.Pubkeys", size, 512) + return + } + subIndx := hh.Index() + for _, i := range s.Pubkeys { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + if ssz.EnableVectorizedHTR { + hh.MerkleizeVectorizedHTR(subIndx) + } else { + hh.Merkleize(subIndx) + } + } + + // Field (1) 'AggregatePubkey' + if size := len(s.AggregatePubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.AggregatePubkey", size, 48) + return + } + hh.PutBytes(s.AggregatePubkey) + + if ssz.EnableVectorizedHTR { + hh.MerkleizeVectorizedHTR(indx) + } else { + hh.Merkleize(indx) + } + return +} + // MarshalSSZ ssz marshals the BLSToExecutionChange object func (b *BLSToExecutionChange) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) diff --git a/proto/prysm/v1alpha1/generated.ssz.go b/proto/prysm/v1alpha1/generated.ssz.go index fbe50f8117..d1ac79770f 100644 --- a/proto/prysm/v1alpha1/generated.ssz.go +++ b/proto/prysm/v1alpha1/generated.ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 437628ba689fb27f524848c027086209535727cf259e162754f174e54b3940cc +// Hash: d926e9fab9d8f4b1333d3cb0f0efbc16e5726483c4a384317682ba3ce5565020 package eth import (