deneb - validator beacon rest apis (#12871)

* wip

* adding tests for deneb

* adding deneb to get block

* Update validator/client/beacon-api/get_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/beacon-api/propose_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/beacon-api/propose_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/beacon-api/propose_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/beacon-api/propose_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
james-prysm 2023-09-11 11:50:55 -05:00 committed by GitHub
parent c0a01bb859
commit 6c16e90fe9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 446 additions and 1 deletions

View File

@ -2405,6 +2405,28 @@ func BlindedBeaconBlockContentsDenebFromConsensus(b *eth.BlindedBeaconBlockAndBl
}, nil
}
func SignedBlindedBeaconBlockContentsDenebFromConsensus(b *eth.SignedBlindedBeaconBlockAndBlobsDeneb) (*SignedBlindedBeaconBlockContentsDeneb, error) {
var blindedBlobSidecars []*SignedBlindedBlobSidecar
if len(b.Blobs) != 0 {
blindedBlobSidecars = make([]*SignedBlindedBlobSidecar, len(b.Blobs))
for i, s := range b.Blobs {
signedBlob, err := SignedBlindedBlobSidecarFromConsensus(s)
if err != nil {
return nil, err
}
blindedBlobSidecars[i] = signedBlob
}
}
blindedBlock, err := SignedBlindedBeaconBlockDenebFromConsensus(b.Block)
if err != nil {
return nil, err
}
return &SignedBlindedBeaconBlockContentsDeneb{
SignedBlindedBlock: blindedBlock,
SignedBlindedBlobSidecars: blindedBlobSidecars,
}, nil
}
func BeaconBlockContentsDenebFromConsensus(b *eth.BeaconBlockAndBlobsDeneb) (*BeaconBlockContentsDeneb, error) {
var blobSidecars []*BlobSidecar
if len(b.Blobs) != 0 {
@ -2427,6 +2449,28 @@ func BeaconBlockContentsDenebFromConsensus(b *eth.BeaconBlockAndBlobsDeneb) (*Be
}, nil
}
func SignedBeaconBlockContentsDenebFromConsensus(b *eth.SignedBeaconBlockAndBlobsDeneb) (*SignedBeaconBlockContentsDeneb, error) {
var blobSidecars []*SignedBlobSidecar
if len(b.Blobs) != 0 {
blobSidecars = make([]*SignedBlobSidecar, len(b.Blobs))
for i, s := range b.Blobs {
blob, err := SignedBlobSidecarFromConsensus(s)
if err != nil {
return nil, err
}
blobSidecars[i] = blob
}
}
block, err := SignedBeaconBlockDenebFromConsensus(b.Block)
if err != nil {
return nil, err
}
return &SignedBeaconBlockContentsDeneb{
SignedBlock: block,
SignedBlobSidecars: blobSidecars,
}, nil
}
func BlindedBeaconBlockDenebFromConsensus(b *eth.BlindedBeaconBlockDeneb) (*BlindedBeaconBlockDeneb, error) {
proposerSlashings, err := ProposerSlashingsFromConsensus(b.Body.ProposerSlashings)
if err != nil {
@ -2509,6 +2553,17 @@ func BlindedBeaconBlockDenebFromConsensus(b *eth.BlindedBeaconBlockDeneb) (*Blin
}, nil
}
func SignedBlindedBeaconBlockDenebFromConsensus(b *eth.SignedBlindedBeaconBlockDeneb) (*SignedBlindedBeaconBlockDeneb, error) {
block, err := BlindedBeaconBlockDenebFromConsensus(b.Block)
if err != nil {
return nil, err
}
return &SignedBlindedBeaconBlockDeneb{
Message: block,
Signature: hexutil.Encode(b.Signature),
}, nil
}
func BeaconBlockDenebFromConsensus(b *eth.BeaconBlockDeneb) (*BeaconBlockDeneb, error) {
proposerSlashings, err := ProposerSlashingsFromConsensus(b.Body.ProposerSlashings)
if err != nil {
@ -2603,6 +2658,17 @@ func BeaconBlockDenebFromConsensus(b *eth.BeaconBlockDeneb) (*BeaconBlockDeneb,
}, nil
}
func SignedBeaconBlockDenebFromConsensus(b *eth.SignedBeaconBlockDeneb) (*SignedBeaconBlockDeneb, error) {
beaconBlock, err := BeaconBlockDenebFromConsensus(b.Block)
if err != nil {
return nil, err
}
return &SignedBeaconBlockDeneb{
Message: beaconBlock,
Signature: hexutil.Encode(b.Signature),
}, nil
}
func BlindedBlobSidecarFromConsensus(b *eth.BlindedBlobSidecar) (*BlindedBlobSidecar, error) {
return &BlindedBlobSidecar{
BlockRoot: hexutil.Encode(b.BlockRoot),
@ -2616,6 +2682,17 @@ func BlindedBlobSidecarFromConsensus(b *eth.BlindedBlobSidecar) (*BlindedBlobSid
}, nil
}
func SignedBlindedBlobSidecarFromConsensus(b *eth.SignedBlindedBlobSidecar) (*SignedBlindedBlobSidecar, error) {
blobSidecar, err := BlindedBlobSidecarFromConsensus(b.Message)
if err != nil {
return nil, err
}
return &SignedBlindedBlobSidecar{
Message: blobSidecar,
Signature: hexutil.Encode(b.Signature),
}, nil
}
func BlobSidecarFromConsensus(b *eth.BlobSidecar) (*BlobSidecar, error) {
return &BlobSidecar{
BlockRoot: hexutil.Encode(b.BlockRoot),
@ -2629,6 +2706,17 @@ func BlobSidecarFromConsensus(b *eth.BlobSidecar) (*BlobSidecar, error) {
}, nil
}
func SignedBlobSidecarFromConsensus(b *eth.SignedBlobSidecar) (*SignedBlobSidecar, error) {
blobSidecar, err := BlobSidecarFromConsensus(b.Message)
if err != nil {
return nil, err
}
return &SignedBlobSidecar{
Message: blobSidecar,
Signature: hexutil.Encode(b.Signature),
}, nil
}
func ProposerSlashingsToConsensus(src []*ProposerSlashing) ([]*eth.ProposerSlashing, error) {
if src == nil {
return nil, errNilValue

View File

@ -89,7 +89,9 @@ go_test(
"propose_beacon_block_bellatrix_test.go",
"propose_beacon_block_blinded_bellatrix_test.go",
"propose_beacon_block_blinded_capella_test.go",
"propose_beacon_block_blinded_deneb_test.go",
"propose_beacon_block_capella_test.go",
"propose_beacon_block_deneb_test.go",
"propose_beacon_block_phase0_test.go",
"propose_beacon_block_test.go",
"propose_exit_test.go",
@ -109,6 +111,7 @@ go_test(
"//api/gateway/apimiddleware:go_default_library",
"//beacon-chain/rpc/apimiddleware:go_default_library",
"//beacon-chain/rpc/eth/shared:go_default_library",
"//beacon-chain/rpc/eth/shared/testing:go_default_library",
"//beacon-chain/rpc/eth/validator:go_default_library",
"//beacon-chain/rpc/prysm/validator:go_default_library",
"//config/params:go_default_library",

View File

@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)
@ -98,7 +99,16 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
response.Block = &ethpb.GenericBeaconBlock_Capella{
Capella: capellaBlock,
}
case "deneb":
jsonDenebBlockContents := shared.BeaconBlockContentsDeneb{}
if err := decoder.Decode(&jsonDenebBlockContents); err != nil {
return nil, errors.Wrap(err, "failed to decode deneb block response json")
}
genericBlock, err := jsonDenebBlockContents.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "could not convert deneb block contents to generic block")
}
response = genericBlock
default:
return nil, errors.Errorf("unsupported consensus version `%s`", produceBlockResponseJson.Version)
}

View File

@ -10,6 +10,8 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/golang/mock/gomock"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
rpctesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared/testing"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
@ -379,3 +381,47 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) {
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
}
func TestGetBeaconBlock_DenebValid(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
var blockContents shared.SignedBeaconBlockContentsDeneb
err := json.Unmarshal([]byte(rpctesting.DenebBlockContents), &blockContents)
require.NoError(t, err)
denebBeaconBlockBytes, err := json.Marshal(blockContents.ToUnsigned())
require.NoError(t, err)
ctx := context.Background()
const slot = primitives.Slot(1)
randaoReveal, err := hexutil.Decode("0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505")
require.NoError(t, err)
graffiti, err := hexutil.Decode("0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2")
require.NoError(t, err)
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetRestJsonResponse(
ctx,
fmt.Sprintf("/eth/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&abstractProduceBlockResponseJson{},
).SetArg(
2,
abstractProduceBlockResponseJson{
Version: "deneb",
Data: denebBeaconBlockBytes,
},
).Return(
nil,
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
expectedBeaconBlock, err := blockContents.ToUnsigned().ToGeneric()
require.NoError(t, err)
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
}

View File

@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)
@ -90,6 +91,35 @@ func (c beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *et
if err != nil {
return nil, errors.Wrap(err, "failed to marshall blinded capella beacon block")
}
case *ethpb.GenericSignedBeaconBlock_Deneb:
consensusVersion = "deneb"
beaconBlockRoot, err = blockType.Deneb.Block.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to compute block root for deneb beacon block")
}
signedBlock, err := shared.SignedBeaconBlockContentsDenebFromConsensus(blockType.Deneb)
if err != nil {
return nil, errors.Wrap(err, "failed to convert deneb beacon block contents")
}
marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal deneb beacon block contents")
}
case *ethpb.GenericSignedBeaconBlock_BlindedDeneb:
blinded = true
consensusVersion = "deneb"
beaconBlockRoot, err = blockType.BlindedDeneb.Block.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to compute block root for blinded deneb beacon block")
}
signedBlock, err := shared.SignedBlindedBeaconBlockContentsDenebFromConsensus(blockType.BlindedDeneb)
if err != nil {
return nil, errors.Wrap(err, "failed to convert blinded deneb beacon block contents")
}
marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal blinded deneb beacon block contents")
}
default:
return nil, errors.Errorf("unsupported block type %T", in.Block)
}

View File

@ -0,0 +1,50 @@
package beacon_api
import (
"bytes"
"context"
"encoding/json"
"testing"
"github.com/golang/mock/gomock"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
rpctesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared/testing"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/validator/client/beacon-api/mock"
)
func TestProposeBeaconBlock_BlindedDeneb(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
var blockContents shared.SignedBlindedBeaconBlockContentsDeneb
err := json.Unmarshal([]byte(rpctesting.BlindedDenebBlockContents), &blockContents)
require.NoError(t, err)
genericSignedBlock, err := blockContents.ToGeneric()
require.NoError(t, err)
denebBytes, err := json.Marshal(blockContents)
require.NoError(t, err)
// Make sure that what we send in the POST body is the marshalled version of the protobuf block
headers := map[string]string{"Eth-Consensus-Version": "deneb"}
jsonRestHandler.EXPECT().PostRestJson(
context.Background(),
"/eth/v1/beacon/blinded_blocks",
headers,
bytes.NewBuffer(denebBytes),
nil,
)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock)
assert.NoError(t, err)
require.NotNil(t, proposeResponse)
expectedBlockRoot, err := genericSignedBlock.GetBlindedDeneb().Block.HashTreeRoot()
require.NoError(t, err)
// Make sure that the block root is set
assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot)
}

View File

@ -0,0 +1,50 @@
package beacon_api
import (
"bytes"
"context"
"encoding/json"
"testing"
"github.com/golang/mock/gomock"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
rpctesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared/testing"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/validator/client/beacon-api/mock"
)
func TestProposeBeaconBlock_Deneb(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
var blockContents shared.SignedBeaconBlockContentsDeneb
err := json.Unmarshal([]byte(rpctesting.DenebBlockContents), &blockContents)
require.NoError(t, err)
genericSignedBlock, err := blockContents.ToGeneric()
require.NoError(t, err)
denebBytes, err := json.Marshal(blockContents)
require.NoError(t, err)
// Make sure that what we send in the POST body is the marshalled version of the protobuf block
headers := map[string]string{"Eth-Consensus-Version": "deneb"}
jsonRestHandler.EXPECT().PostRestJson(
context.Background(),
"/eth/v1/beacon/blocks",
headers,
bytes.NewBuffer(denebBytes),
nil,
)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock)
assert.NoError(t, err)
require.NotNil(t, proposeResponse)
expectedBlockRoot, err := genericSignedBlock.GetDeneb().Block.HashTreeRoot()
require.NoError(t, err)
// Make sure that the block root is set
assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot)
}

View File

@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"google.golang.org/grpc"
@ -183,6 +184,25 @@ func (c beaconApiValidatorClient) getHeadSignedBeaconBlock(ctx context.Context)
}
slot = capellaBlock.Slot
case "deneb":
jsonDenebBlock := shared.SignedBeaconBlockDeneb{}
if err := decoder.Decode(&jsonDenebBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode signed deneb block response json")
}
denebBlock, err := jsonDenebBlock.ToConsensus()
if err != nil {
return nil, errors.Wrap(err, "failed to get signed deneb block")
}
response.Block = &ethpb.StreamBlocksResponse_DenebBlock{
DenebBlock: &ethpb.SignedBeaconBlockDeneb{
Signature: denebBlock.Signature,
Block: denebBlock.Block,
},
}
slot = denebBlock.Block.Slot
default:
return nil, errors.Errorf("unsupported consensus version `%s`", signedBlockResponseJson.Version)

View File

@ -7,9 +7,12 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
rpctesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared/testing"
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
@ -830,3 +833,148 @@ func TestStreamBlocks_CapellaValid(t *testing.T) {
})
}
}
func TestStreamBlocks_DenebValid(t *testing.T) {
testCases := []struct {
name string
verifiedOnly bool
}{
{
name: "verified optional",
verifiedOnly: false,
},
{
name: "verified only",
verifiedOnly: true,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
signedBlockResponseJson := abstractSignedBlockResponseJson{}
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl)
// For the first call, return a block that satisfies the verifiedOnly condition. This block should be returned by the first Recv().
// For the second call, return the same block as the previous one. This block shouldn't be returned by the second Recv().
var blockContents shared.SignedBeaconBlockContentsDeneb
err := json.Unmarshal([]byte(rpctesting.DenebBlockContents), &blockContents)
require.NoError(t, err)
sig := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
denebBlock := blockContents.SignedBlock
denebBlock.Message.Slot = "1"
denebBlock.Signature = sig
marshalledSignedBeaconBlockContainer1, err := json.Marshal(denebBlock)
require.NoError(t, err)
jsonRestHandler.EXPECT().GetRestJsonResponse(
ctx,
"/eth/v2/beacon/blocks/head",
&signedBlockResponseJson,
).Return(
nil,
nil,
).SetArg(
2,
abstractSignedBlockResponseJson{
Version: "deneb",
ExecutionOptimistic: false,
Data: marshalledSignedBeaconBlockContainer1,
},
).Times(2)
// For the third call, return a block with a different slot than the previous one, but with the verifiedOnly condition not satisfied.
// If verifiedOnly == false, this block will be returned by the second Recv(); otherwise, another block will be requested.
var blockContents2 shared.SignedBeaconBlockContentsDeneb
err = json.Unmarshal([]byte(rpctesting.DenebBlockContents), &blockContents2)
require.NoError(t, err)
sig2 := "0x2b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
denebBlock2 := blockContents.SignedBlock
denebBlock2.Message.Slot = "2"
denebBlock2.Signature = sig2
marshalledSignedBeaconBlockContainer2, err := json.Marshal(denebBlock2)
require.NoError(t, err)
jsonRestHandler.EXPECT().GetRestJsonResponse(
ctx,
"/eth/v2/beacon/blocks/head",
&signedBlockResponseJson,
).Return(
nil,
nil,
).SetArg(
2,
abstractSignedBlockResponseJson{
Version: "deneb",
ExecutionOptimistic: true,
Data: marshalledSignedBeaconBlockContainer2,
},
).Times(1)
// The fourth call is only necessary when verifiedOnly == true since the previous block was optimistic
if testCase.verifiedOnly {
jsonRestHandler.EXPECT().GetRestJsonResponse(
ctx,
"/eth/v2/beacon/blocks/head",
&signedBlockResponseJson,
).Return(
nil,
nil,
).SetArg(
2,
abstractSignedBlockResponseJson{
Version: "deneb",
ExecutionOptimistic: false,
Data: marshalledSignedBeaconBlockContainer2,
},
).Times(1)
}
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter}
streamBlocksClient := validatorClient.streamBlocks(ctx, &eth.StreamBlocksRequest{VerifiedOnly: testCase.verifiedOnly}, time.Millisecond*100)
// Get the first block
streamBlocksResponse1, err := streamBlocksClient.Recv()
require.NoError(t, err)
consensusBlock, err := denebBlock.Message.ToConsensus()
consensusBlock.Slot = 1
require.NoError(t, err)
sigBytes, err := hexutil.Decode(sig)
require.NoError(t, err)
expectedStreamBlocksResponse1 := &eth.StreamBlocksResponse{
Block: &eth.StreamBlocksResponse_DenebBlock{
DenebBlock: &eth.SignedBeaconBlockDeneb{
Block: consensusBlock,
Signature: sigBytes,
},
},
}
assert.DeepEqual(t, expectedStreamBlocksResponse1, streamBlocksResponse1)
// Get the second block
streamBlocksResponse2, err := streamBlocksClient.Recv()
require.NoError(t, err)
consensusBlock.Slot = 2
sig2Bytes, err := hexutil.Decode(sig2)
require.NoError(t, err)
expectedStreamBlocksResponse2 := &eth.StreamBlocksResponse{
Block: &eth.StreamBlocksResponse_DenebBlock{
DenebBlock: &eth.SignedBeaconBlockDeneb{
Block: consensusBlock,
Signature: sig2Bytes,
},
},
}
assert.DeepEqual(t, expectedStreamBlocksResponse2, streamBlocksResponse2)
})
}
}