From 0ea12a8c78d0cf396058398658b7c34749fe41e6 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 24 Oct 2024 20:24:53 -0400 Subject: [PATCH] feat(node-api): proof of proposer index in beacon block (#2099) --- mod/consensus-types/pkg/types/genesis.go | 4 +- mod/consensus/pkg/cometbft/service/abci.go | 24 ++++-- mod/consensus/pkg/cometbft/service/service.go | 17 ++-- mod/da/pkg/types/sidecar_test.go | 10 ++- mod/node-api/handlers/proof/block_proposer.go | 18 +++- .../handlers/proof/merkle/beacon_state.go | 4 +- .../proof/merkle/block_proposer_index.go | 82 ++++++++++++++++++ .../proof/merkle/block_proposer_index_test.go | 84 +++++++++++++++++++ ...k_proposer.go => block_proposer_pubkey.go} | 4 +- ..._test.go => block_proposer_pubkey_test.go} | 12 +-- .../handlers/proof/merkle/constants.go | 4 + .../handlers/proof/merkle/constants_test.go | 15 ++++ .../many_validators_proposer_index_proof.json | 5 ++ ...any_validators_proposer_pubkey_proof.json} | 0 .../one_validator_proposer_index_proof.json | 5 ++ ... one_validator_proposer_pubkey_proof.json} | 0 mod/node-api/handlers/proof/types/response.go | 4 + mod/primitives/pkg/common/execution_test.go | 7 +- mod/primitives/pkg/math/u64_test.go | 4 +- 19 files changed, 265 insertions(+), 38 deletions(-) create mode 100644 mod/node-api/handlers/proof/merkle/block_proposer_index.go create mode 100644 mod/node-api/handlers/proof/merkle/block_proposer_index_test.go rename mod/node-api/handlers/proof/merkle/{block_proposer.go => block_proposer_pubkey.go} (97%) rename mod/node-api/handlers/proof/merkle/{block_proposer_test.go => block_proposer_pubkey_test.go} (88%) create mode 100644 mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_index_proof.json rename mod/node-api/handlers/proof/merkle/testdata/{many_validators_proposer_proof.json => many_validators_proposer_pubkey_proof.json} (100%) create mode 100644 mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_index_proof.json rename mod/node-api/handlers/proof/merkle/testdata/{one_validator_proposer_proof.json => one_validator_proposer_pubkey_proof.json} (100%) diff --git a/mod/consensus-types/pkg/types/genesis.go b/mod/consensus-types/pkg/types/genesis.go index c4e93ceeaa..13db0fd9c4 100644 --- a/mod/consensus-types/pkg/types/genesis.go +++ b/mod/consensus-types/pkg/types/genesis.go @@ -155,7 +155,9 @@ func DefaultGenesisExecutionPayloadHeaderDeneb() ( return nil, fmt.Errorf("failed generating receipts root: %w", err) } - baseFeePerGas, err := math.NewU256FromBigInt(big.NewInt(defaultBaseFeePerGas)) + baseFeePerGas, err := math.NewU256FromBigInt( + big.NewInt(defaultBaseFeePerGas), + ) if err != nil { return nil, fmt.Errorf("failed setting base fee per gas: %w", err) } diff --git a/mod/consensus/pkg/cometbft/service/abci.go b/mod/consensus/pkg/cometbft/service/abci.go index 19acd798bc..cc9bfa74e6 100644 --- a/mod/consensus/pkg/cometbft/service/abci.go +++ b/mod/consensus/pkg/cometbft/service/abci.go @@ -67,14 +67,16 @@ func (s *Service[LoggerT]) InitChain( req.ChainId, ) - // Set the initial height, which will be used to determine if we are proposing + // Set the initial height, which will be used to determine if we are + // proposing // or processing the first block or not. s.initialHeight = req.InitialHeight if s.initialHeight == 0 { s.initialHeight = 1 } - // if req.InitialHeight is > 1, then we set the initial version on all stores + // if req.InitialHeight is > 1, then we set the initial version on all + // stores if req.InitialHeight > 1 { if err := s.sm.CommitMultiStore(). SetInitialVersion(req.InitialHeight); err != nil { @@ -121,7 +123,8 @@ func (s *Service[LoggerT]) InitChain( } } - // NOTE: We don't commit, but FinalizeBlock for block InitialHeight starts from + // NOTE: We don't commit, but FinalizeBlock for block InitialHeight starts + // from // this FinalizeBlockState. return &cmtabci.InitChainResponse{ ConsensusParams: req.ConsensusParams, @@ -242,10 +245,12 @@ func (s *Service[LoggerT]) ProcessProposal( ) } - // Since the application can get access to FinalizeBlock state and write to it, - // we must be sure to reset it in case ProcessProposal timeouts and is called + // Since the application can get access to FinalizeBlock state and write to + // it, we must be sure to reset it in case ProcessProposal timeouts and is + // called // again in a subsequent round. However, we only want to do this after we've - // processed the first block, as we want to avoid overwriting the finalizeState + // processed the first block, as we want to avoid overwriting the + // finalizeState // after state changes during InitChain. s.processProposalState = s.resetState() if req.Height > s.initialHeight { @@ -290,9 +295,10 @@ func (s *Service[LoggerT]) internalFinalizeBlock( return nil, err } - // finalizeBlockState should be set on InitChain or ProcessProposal. If it is - // nil, it means we are replaying this block and we need to set the state here - // given that during block replay ProcessProposal is not executed by CometBFT. + // finalizeBlockState should be set on InitChain or ProcessProposal. If it + // is nil, it means we are replaying this block and we need to set the state + // here given that during block replay ProcessProposal is not executed by + // CometBFT. if s.finalizeBlockState == nil { s.finalizeBlockState = s.resetState() } diff --git a/mod/consensus/pkg/cometbft/service/service.go b/mod/consensus/pkg/cometbft/service/service.go index f3acf90530..a506f1c648 100644 --- a/mod/consensus/pkg/cometbft/service/service.go +++ b/mod/consensus/pkg/cometbft/service/service.go @@ -57,18 +57,21 @@ type Service[ sm *statem.Manager Middleware MiddlewareI - // prepareProposalState is used for PrepareProposal, which is set based on the - // previous block's state. This state is never committed. In case of multiple - // consensus rounds, the state is always reset to the previous block's state. + // prepareProposalState is used for PrepareProposal, which is set based on + // the previous block's state. This state is never committed. In case of + // multiple consensus rounds, the state is always reset to the previous + // block's state. prepareProposalState *state - // processProposalState is used for ProcessProposal, which is set based on the - // previous block's state. This state is never committed. In case of multiple - // consensus rounds, the state is always reset to the previous block's state. + // processProposalState is used for ProcessProposal, which is set based on + // the previous block's state. This state is never committed. In case of + // multiple consensus rounds, the state is always reset to the previous + // block's state. processProposalState *state // finalizeBlockState is used for FinalizeBlock, which is set based on the - // previous block's state. This state is committed. finalizeBlockState is set + // previous block's state. This state is committed. finalizeBlockState is + // set // on InitChain and FinalizeBlock and set to nil on Commit. finalizeBlockState *state diff --git a/mod/da/pkg/types/sidecar_test.go b/mod/da/pkg/types/sidecar_test.go index 30480f4289..e1bac893e9 100644 --- a/mod/da/pkg/types/sidecar_test.go +++ b/mod/da/pkg/types/sidecar_test.go @@ -88,7 +88,10 @@ func TestHasValidInclusionProof(t *testing.T) { t.Helper() inclusionProof := make([]common.Root, 0) for i := int(1); i <= 8; i++ { - it := byteslib.ExtendToSize([]byte(strconv.Itoa(i)), byteslib.B32Size) + it := byteslib.ExtendToSize( + []byte(strconv.Itoa(i)), + byteslib.B32Size, + ) proof, err := byteslib.ToBytes32(it) require.NoError(t, err) inclusionProof = append(inclusionProof, common.Root(proof)) @@ -147,7 +150,10 @@ func TestHashTreeRoot(t *testing.T) { t.Helper() inclusionProof := make([]common.Root, 0) for i := int(1); i <= 8; i++ { - it := byteslib.ExtendToSize([]byte(strconv.Itoa(i)), byteslib.B32Size) + it := byteslib.ExtendToSize( + []byte(strconv.Itoa(i)), + byteslib.B32Size, + ) proof, err := byteslib.ToBytes32(it) require.NoError(t, err) inclusionProof = append(inclusionProof, common.Root(proof)) diff --git a/mod/node-api/handlers/proof/block_proposer.go b/mod/node-api/handlers/proof/block_proposer.go index a252ff9308..848d84b025 100644 --- a/mod/node-api/handlers/proof/block_proposer.go +++ b/mod/node-api/handlers/proof/block_proposer.go @@ -28,7 +28,7 @@ import ( // GetBlockProposer returns the block proposer pubkey for the given timestamp // id along with a merkle proof that can be verified against the beacon block -// root. +// root. It also returns the merkle proof of the proposer index. func (h *Handler[ BeaconBlockHeaderT, _, _, ContextT, _, _, ]) GetBlockProposer(c ContextT) (any, error) { @@ -45,16 +45,25 @@ func (h *Handler[ return nil, err } + h.Logger().Info("Generating block proposer proofs", "slot", slot) + // Generate the proof (along with the "correct" beacon block root to // verify against) for the proposer validator pubkey. - h.Logger().Info("Generating block proposer proof", "slot", slot) - proof, beaconBlockRoot, err := merkle.ProveProposerInBlock( + pubkeyProof, beaconBlockRoot, err := merkle.ProveProposerPubkeyInBlock( blockHeader, beaconState, ) if err != nil { return nil, err } + // Generate the proof for the proposer index. + proposerIndexProof, _, err := merkle.ProveProposerIndexInBlock( + blockHeader, + ) + if err != nil { + return nil, err + } + // Get the pubkey of the proposer validator. proposerValidator, err := beaconState.ValidatorByIndex( blockHeader.GetProposerIndex(), @@ -67,6 +76,7 @@ func (h *Handler[ BeaconBlockHeader: blockHeader, BeaconBlockRoot: beaconBlockRoot, ValidatorPubkey: proposerValidator.GetPubkey(), - ValidatorPubkeyProof: proof, + ValidatorPubkeyProof: pubkeyProof, + ProposerIndexProof: proposerIndexProof, }, nil } diff --git a/mod/node-api/handlers/proof/merkle/beacon_state.go b/mod/node-api/handlers/proof/merkle/beacon_state.go index b4d035aeee..13b9cd3c73 100644 --- a/mod/node-api/handlers/proof/merkle/beacon_state.go +++ b/mod/node-api/handlers/proof/merkle/beacon_state.go @@ -62,9 +62,7 @@ func ProveBeaconStateInBlock( // // TODO: verifying the proof is not absolutely necessary. func verifyBeaconStateInBlock( - bbh types.BeaconBlockHeader, - proof []common.Root, - leaf common.Root, + bbh types.BeaconBlockHeader, proof []common.Root, leaf common.Root, ) error { beaconRoot := bbh.HashTreeRoot() if beaconRootVerified, err := merkle.VerifyProof( diff --git a/mod/node-api/handlers/proof/merkle/block_proposer_index.go b/mod/node-api/handlers/proof/merkle/block_proposer_index.go new file mode 100644 index 0000000000..19e0a1129c --- /dev/null +++ b/mod/node-api/handlers/proof/merkle/block_proposer_index.go @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package merkle + +import ( + "github.com/berachain/beacon-kit/mod/errors" + "github.com/berachain/beacon-kit/mod/node-api/handlers/proof/types" + "github.com/berachain/beacon-kit/mod/primitives/pkg/common" + "github.com/berachain/beacon-kit/mod/primitives/pkg/encoding/ssz/merkle" +) + +// ProveProposerIndexInBlock generates a proof for the proposer index in the +// beacon block. The proof is then verified against the beacon block root as a +// sanity check. Returns the proof along with the beacon block root. It uses +// the fastssz library to generate the proof. +func ProveProposerIndexInBlock[ + BeaconBlockHeaderT types.BeaconBlockHeader, +](bbh BeaconBlockHeaderT) ([]common.Root, common.Root, error) { + blockProofTree, err := bbh.GetTree() + if err != nil { + return nil, common.Root{}, err + } + + proposerIndexProof, err := blockProofTree.Prove( + ProposerIndexGIndexDenebBlock, + ) + if err != nil { + return nil, common.Root{}, err + } + + proof := make([]common.Root, len(proposerIndexProof.Hashes)) + for i, hash := range proposerIndexProof.Hashes { + proof[i] = common.NewRootFromBytes(hash) + } + + beaconRoot, err := verifyProposerIndexInBlock( + bbh, proof, common.NewRootFromBytes(proposerIndexProof.Leaf), + ) + if err != nil { + return nil, common.Root{}, err + } + + return proof, beaconRoot, nil +} + +// verifyProposerIndexInBlock verifies the proposer index proof in the block. +// +// TODO: verifying the proof is not absolutely necessary. +func verifyProposerIndexInBlock( + bbh types.BeaconBlockHeader, proof []common.Root, leaf common.Root, +) (common.Root, error) { + beaconRoot := bbh.HashTreeRoot() + if beaconRootVerified, err := merkle.VerifyProof( + ProposerIndexGIndexDenebBlock, leaf, proof, beaconRoot, + ); err != nil { + return common.Root{}, err + } else if !beaconRootVerified { + return common.Root{}, errors.New( + "proposer index proof failed to verify against beacon root", + ) + } + + return beaconRoot, nil +} diff --git a/mod/node-api/handlers/proof/merkle/block_proposer_index_test.go b/mod/node-api/handlers/proof/merkle/block_proposer_index_test.go new file mode 100644 index 0000000000..5b8afcd159 --- /dev/null +++ b/mod/node-api/handlers/proof/merkle/block_proposer_index_test.go @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package merkle_test + +import ( + "testing" + + "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" + "github.com/berachain/beacon-kit/mod/node-api/handlers/proof/merkle" + "github.com/berachain/beacon-kit/mod/primitives/pkg/common" + "github.com/berachain/beacon-kit/mod/primitives/pkg/math" + "github.com/stretchr/testify/require" +) + +// TestBlockProposerIndexProof tests the ProveProposerIndexInBlock function +// and that the generated proof correctly verifies. +func TestBlockProposerIndexProof(t *testing.T) { + testCases := []struct { + name string + slot math.Slot + proposerIndex math.ValidatorIndex + parentBlockRoot common.Root + stateRoot common.Root + bodyRoot common.Root + expectedProofFile string + }{ + { + name: "1 Validator Set", + slot: 69, + proposerIndex: 0, + parentBlockRoot: common.Root{1, 2, 3}, + stateRoot: common.Root{4, 5, 6}, + bodyRoot: common.Root{7, 8, 9}, + expectedProofFile: "one_validator_proposer_index_proof.json", + }, + { + name: "Many Validator Set", + slot: 420, + proposerIndex: 69, + parentBlockRoot: common.Root{1, 2, 3}, + stateRoot: common.Root{4, 5, 6}, + bodyRoot: common.Root{7, 8, 9}, + expectedProofFile: "many_validators_proposer_index_proof.json", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + bbh := (&types.BeaconBlockHeader{}).New( + tc.slot, + tc.proposerIndex, + tc.parentBlockRoot, + tc.stateRoot, + tc.bodyRoot, + ) + + proof, beaconRoot, err := merkle.ProveProposerIndexInBlock(bbh) + require.NoError(t, err) + + require.Equal(t, bbh.HashTreeRoot(), beaconRoot) + + expectedProof := ReadProofFromFile(t, tc.expectedProofFile) + require.Equal(t, expectedProof, proof) + }) + } +} diff --git a/mod/node-api/handlers/proof/merkle/block_proposer.go b/mod/node-api/handlers/proof/merkle/block_proposer_pubkey.go similarity index 97% rename from mod/node-api/handlers/proof/merkle/block_proposer.go rename to mod/node-api/handlers/proof/merkle/block_proposer_pubkey.go index 75df850f45..90a641b7de 100644 --- a/mod/node-api/handlers/proof/merkle/block_proposer.go +++ b/mod/node-api/handlers/proof/merkle/block_proposer_pubkey.go @@ -28,11 +28,11 @@ import ( "github.com/berachain/beacon-kit/mod/primitives/pkg/math" ) -// ProveProposerInBlock generates a proof for the proposer pubkey in the +// ProveProposerPubkeyInBlock generates a proof for the proposer pubkey in the // beacon block. The proof is then verified against the beacon block root as a // sanity check. Returns the proof along with the beacon block root. It uses // the fastssz library to generate the proof. -func ProveProposerInBlock[ +func ProveProposerPubkeyInBlock[ BeaconBlockHeaderT types.BeaconBlockHeader, BeaconStateMarshallableT types.BeaconStateMarshallable, ExecutionPayloadHeaderT types.ExecutionPayloadHeader, diff --git a/mod/node-api/handlers/proof/merkle/block_proposer_test.go b/mod/node-api/handlers/proof/merkle/block_proposer_pubkey_test.go similarity index 88% rename from mod/node-api/handlers/proof/merkle/block_proposer_test.go rename to mod/node-api/handlers/proof/merkle/block_proposer_pubkey_test.go index fde1caf490..881398a3f3 100644 --- a/mod/node-api/handlers/proof/merkle/block_proposer_test.go +++ b/mod/node-api/handlers/proof/merkle/block_proposer_pubkey_test.go @@ -32,9 +32,9 @@ import ( "github.com/stretchr/testify/require" ) -// TestBlockProposerProof tests the ProveProposerInBlock function and -// that the generated proof correctly verifies. -func TestBlockProposerProof(t *testing.T) { +// TestBlockProposerPubkeyProof tests the ProveProposerPubkeyInBlock function +// and that the generated proof correctly verifies. +func TestBlockProposerPubkeyProof(t *testing.T) { testCases := []struct { name string numValidators int @@ -53,7 +53,7 @@ func TestBlockProposerProof(t *testing.T) { parentBlockRoot: common.Root{1, 2, 3}, bodyRoot: common.Root{3, 2, 1}, pubKey: [48]byte{9, 8, 7, 6, 5, 4, 3, 2, 1}, - expectedProofFile: "one_validator_proposer_proof.json", + expectedProofFile: "one_validator_proposer_pubkey_proof.json", }, { name: "Many Validator Set", @@ -63,7 +63,7 @@ func TestBlockProposerProof(t *testing.T) { parentBlockRoot: common.Root{1, 2, 3, 4, 5, 6}, bodyRoot: common.Root{3, 2, 1, 9, 8, 7}, pubKey: [48]byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2}, - expectedProofFile: "many_validators_proposer_proof.json", + expectedProofFile: "many_validators_proposer_pubkey_proof.json", }, } @@ -88,7 +88,7 @@ func TestBlockProposerProof(t *testing.T) { tc.bodyRoot, ) - proof, _, err := merkle.ProveProposerInBlock(bbh, bs) + proof, _, err := merkle.ProveProposerPubkeyInBlock(bbh, bs) require.NoError(t, err) expectedProof := ReadProofFromFile(t, tc.expectedProofFile) require.Equal(t, expectedProof, proof) diff --git a/mod/node-api/handlers/proof/merkle/constants.go b/mod/node-api/handlers/proof/merkle/constants.go index e2c315f2a7..f6edc48a40 100644 --- a/mod/node-api/handlers/proof/merkle/constants.go +++ b/mod/node-api/handlers/proof/merkle/constants.go @@ -21,6 +21,10 @@ package merkle const ( + // ProposerIndexGIndexDenebBlock is the generalized index of the proposer + // index in the beacon block in the Deneb fork. + ProposerIndexGIndexDenebBlock = 9 + // StateGIndexDenebBlock is the generalized index of the beacon state in // the beacon block in the Deneb fork. StateGIndexDenebBlock = 11 diff --git a/mod/node-api/handlers/proof/merkle/constants_test.go b/mod/node-api/handlers/proof/merkle/constants_test.go index 6f31fe5840..32630d08fb 100644 --- a/mod/node-api/handlers/proof/merkle/constants_test.go +++ b/mod/node-api/handlers/proof/merkle/constants_test.go @@ -109,6 +109,21 @@ var ( ) ) +// TestGIndexProposerIndexDeneb tests the generalized index of the proposer +// index in the beacon block on the Deneb fork. +func TestGIndexProposerIndexDeneb(t *testing.T) { + // GIndex of the proposer index in the beacon block. + _, proposerIndexGIndexDenebBlock, _, err := mlib.ObjectPath[ + mlib.GeneralizedIndex, [32]byte, + ]("ProposerIndex").GetGeneralizedIndex(beaconHeaderSchema) + require.NoError(t, err) + require.Equal( + t, + merkle.ProposerIndexGIndexDenebBlock, + int(proposerIndexGIndexDenebBlock), + ) +} + // TestGIndicesValidatorPubkeyDeneb tests the generalized indices used by // beacon state proofs for validator pubkeys on the Deneb fork. func TestGIndicesValidatorPubkeyDeneb(t *testing.T) { diff --git a/mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_index_proof.json b/mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_index_proof.json new file mode 100644 index 0000000000..f677acbbbf --- /dev/null +++ b/mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_index_proof.json @@ -0,0 +1,5 @@ +[ + "0xa401000000000000000000000000000000000000000000000000000000000000", + "0x5ca6b806bfaf4c5c16be71ea6ee96e4e05b172144c1e6c2eb5646535896a30ac", + "0xfbfd75335009f40216a1ca7e1e9306e76194a2cebd6f7f9e88ea5a471d86b5f9" +] diff --git a/mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_proof.json b/mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_pubkey_proof.json similarity index 100% rename from mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_proof.json rename to mod/node-api/handlers/proof/merkle/testdata/many_validators_proposer_pubkey_proof.json diff --git a/mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_index_proof.json b/mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_index_proof.json new file mode 100644 index 0000000000..c3dceb51e6 --- /dev/null +++ b/mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_index_proof.json @@ -0,0 +1,5 @@ +[ + "0x4500000000000000000000000000000000000000000000000000000000000000", + "0x5ca6b806bfaf4c5c16be71ea6ee96e4e05b172144c1e6c2eb5646535896a30ac", + "0xfbfd75335009f40216a1ca7e1e9306e76194a2cebd6f7f9e88ea5a471d86b5f9" +] diff --git a/mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_proof.json b/mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_pubkey_proof.json similarity index 100% rename from mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_proof.json rename to mod/node-api/handlers/proof/merkle/testdata/one_validator_proposer_pubkey_proof.json diff --git a/mod/node-api/handlers/proof/types/response.go b/mod/node-api/handlers/proof/types/response.go index cb73353c6d..ebe457ec0f 100644 --- a/mod/node-api/handlers/proof/types/response.go +++ b/mod/node-api/handlers/proof/types/response.go @@ -44,6 +44,10 @@ type BlockProposerResponse[BeaconBlockHeaderT any] struct { // Generalized Index of the 0 validator pubkey in the beacon block. In // the Deneb fork, z is 3254554418216960. ValidatorPubkeyProof []common.Root `json:"validator_pubkey_proof"` + + // ProposerIndexProof can be verified against the beacon block root. Use + // a Generalized Index of 9 in the Deneb fork. + ProposerIndexProof []common.Root `json:"proposer_index_proof"` } // ExecutionNumberResponse is the response for the diff --git a/mod/primitives/pkg/common/execution_test.go b/mod/primitives/pkg/common/execution_test.go index 4aaea0f138..75644d4f2b 100644 --- a/mod/primitives/pkg/common/execution_test.go +++ b/mod/primitives/pkg/common/execution_test.go @@ -30,7 +30,6 @@ import ( ) func TestExecutionAddressMarshalling(t *testing.T) { - //nolint:lll // some test data may be long tests := []struct { name string input []byte @@ -47,8 +46,10 @@ func TestExecutionAddressMarshalling(t *testing.T) { expectedErr: hex.ErrMissingPrefix, }, { - name: "address too long", - input: []byte("\"0x000102030405060708090a0b0c0d0e0f101112131415161718\""), + name: "address too long", + input: []byte( + "\"0x000102030405060708090a0b0c0d0e0f101112131415161718\"", + ), expectedErr: hex.ErrInvalidHexStringLength, }, } diff --git a/mod/primitives/pkg/math/u64_test.go b/mod/primitives/pkg/math/u64_test.go index 2d3b957937..82ddd537e2 100644 --- a/mod/primitives/pkg/math/u64_test.go +++ b/mod/primitives/pkg/math/u64_test.go @@ -348,7 +348,9 @@ func TestGweiFromWei(t *testing.T) { name: "invalid huge gwei", input: func(t *testing.T) *big.Int { t.Helper() - b, _ := new(big.Int).SetString("18446744073709551616000000000", 10) + b, _ := new( + big.Int, + ).SetString("18446744073709551616000000000", 10) return b }, expectedErr: math.ErrGweiOverflow,