Eth2api: GetBlockSSZ supports bellatrix block (#10077)

* add rpc and tests

* rename
This commit is contained in:
terence tsao 2022-01-16 18:30:09 -08:00 committed by GitHub
parent 182bd615ac
commit 33d1ae0792
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2329 additions and 900 deletions

View File

@ -289,6 +289,11 @@ type altairBlockResponseJson struct {
Data *signedBeaconBlockAltairContainerJson `json:"data"`
}
type bellatrixBlockResponseJson struct {
Version string `json:"version"`
Data *signedBeaconBlockBellatrixContainerJson `json:"data"`
}
func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) {
respContainer, ok := response.(*blockV2ResponseJson)
if !ok {
@ -312,6 +317,14 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a
Signature: respContainer.Data.Signature,
},
}
} else if strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_MERGE.String())) {
actualRespContainer = &bellatrixBlockResponseJson{
Version: respContainer.Version,
Data: &signedBeaconBlockBellatrixContainerJson{
Message: respContainer.Data.BellatrixBlock,
Signature: respContainer.Data.Signature,
},
}
} else {
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
}

View File

@ -323,14 +323,16 @@ type beaconBlockBodyJson struct {
}
type signedBeaconBlockContainerV2Json struct {
Phase0Block *beaconBlockJson `json:"phase0_block"`
AltairBlock *beaconBlockAltairJson `json:"altair_block"`
Signature string `json:"signature" hex:"true"`
Phase0Block *beaconBlockJson `json:"phase0_block"`
AltairBlock *beaconBlockAltairJson `json:"altair_block"`
BellatrixBlock *beaconBlockBellatrixJson `json:"bellatrix_block"`
Signature string `json:"signature" hex:"true"`
}
type beaconBlockContainerV2Json struct {
Phase0Block *beaconBlockJson `json:"phase0_block"`
AltairBlock *beaconBlockAltairJson `json:"altair_block"`
Phase0Block *beaconBlockJson `json:"phase0_block"`
AltairBlock *beaconBlockAltairJson `json:"altair_block"`
BellatrixBlock *beaconBlockBellatrixJson `json:"bellatrix_block"`
}
type signedBeaconBlockAltairContainerJson struct {
@ -338,6 +340,11 @@ type signedBeaconBlockAltairContainerJson struct {
Signature string `json:"signature" hex:"true"`
}
type signedBeaconBlockBellatrixContainerJson struct {
Message *beaconBlockBellatrixJson `json:"message"`
Signature string `json:"signature" hex:"true"`
}
type beaconBlockAltairJson struct {
Slot string `json:"slot"`
ProposerIndex string `json:"proposer_index"`
@ -346,6 +353,14 @@ type beaconBlockAltairJson struct {
Body *beaconBlockBodyAltairJson `json:"body"`
}
type beaconBlockBellatrixJson struct {
Slot string `json:"slot"`
ProposerIndex string `json:"proposer_index"`
ParentRoot string `json:"parent_root" hex:"true"`
StateRoot string `json:"state_root" hex:"true"`
Body *beaconBlockBodyBellatrixJson `json:"body"`
}
type beaconBlockBodyAltairJson struct {
RandaoReveal string `json:"randao_reveal" hex:"true"`
Eth1Data *eth1DataJson `json:"eth1_data"`
@ -358,6 +373,36 @@ type beaconBlockBodyAltairJson struct {
SyncAggregate *syncAggregateJson `json:"sync_aggregate"`
}
type beaconBlockBodyBellatrixJson struct {
RandaoReveal string `json:"randao_reveal" hex:"true"`
Eth1Data *eth1DataJson `json:"eth1_data"`
Graffiti string `json:"graffiti" hex:"true"`
ProposerSlashings []*proposerSlashingJson `json:"proposer_slashings"`
AttesterSlashings []*attesterSlashingJson `json:"attester_slashings"`
Attestations []*attestationJson `json:"attestations"`
Deposits []*depositJson `json:"deposits"`
VoluntaryExits []*signedVoluntaryExitJson `json:"voluntary_exits"`
SyncAggregate *syncAggregateJson `json:"sync_aggregate"`
ExecutionPayload *executionPayloadJson `json:"execution_payload"`
}
type executionPayloadJson struct {
ParentHash string `json:"parent_hash" hex:"true"`
CoinBase string `json:"coinbase" hex:"true"`
StateRoot string `json:"state_root" hex:"true"`
ReceiptRoot string `json:"receipt_root" hex:"true"`
LogsBloom string `json:"logs_bloom" hex:"true"`
Random string `json:"random" hex:"true"`
BlockNumber string `json:"block_number"`
GasLimit string `json:"gas_limit"`
GasUsed string `json:"gas_used"`
TimeStamp string `json:"timestamp"`
ExtraData string `json:"extra_data" hex:"true"`
BaseFeePerGas string `json:"base_fee_per_gas" hex:"true"`
BlockHash string `json:"block_hash" hex:"true"`
Transactions []string `json:"transactions" hex:"true"`
}
type syncAggregateJson struct {
SyncCommitteeBits string `json:"sync_committee_bits" hex:"true"`
SyncCommitteeSignature string `json:"sync_committee_signature" hex:"true"`

View File

@ -271,7 +271,7 @@ func (bs *Server) GetBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequest) (*
// GetBlockV2 retrieves block details for given block ID.
func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (*ethpbv2.BlockResponseV2, error) {
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockAltair")
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockV2")
defer span.End()
blk, phase0Blk, err := bs.blocksFromId(ctx, req.BlockId)
@ -292,21 +292,43 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
},
}, nil
}
altairBlk, err := blk.PbAltairBlock()
bellatrixBlk, err := blk.PbMergeBlock()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check for Altair block")
altairBlk, err := blk.PbAltairBlock()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check for block")
}
if altairBlk != nil {
v2Blk, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlk.Block)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
}
return &ethpbv2.BlockResponseV2{
Version: ethpbv2.Version_ALTAIR,
Data: &ethpbv2.SignedBeaconBlockContainerV2{
Message: &ethpbv2.SignedBeaconBlockContainerV2_AltairBlock{AltairBlock: v2Blk},
Signature: blk.Signature(),
},
}, nil
}
return nil, status.Errorf(codes.Internal, "Could not check for block")
}
v2Blk, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlk.Block)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
if bellatrixBlk != nil {
v2Blk, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlk.Block)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
}
return &ethpbv2.BlockResponseV2{
Version: ethpbv2.Version_MERGE,
Data: &ethpbv2.SignedBeaconBlockContainerV2{
Message: &ethpbv2.SignedBeaconBlockContainerV2_MergeBlock{MergeBlock: v2Blk},
Signature: blk.Signature(),
},
}, nil
}
return &ethpbv2.BlockResponseV2{
Version: ethpbv2.Version_ALTAIR,
Data: &ethpbv2.SignedBeaconBlockContainerV2{
Message: &ethpbv2.SignedBeaconBlockContainerV2_AltairBlock{AltairBlock: v2Blk},
Signature: blk.Signature(),
},
}, nil
return nil, nil
}
// GetBlockSSZV2 returns the SSZ-serialized version of the beacon block for given block ID.

View File

@ -108,6 +108,50 @@ func fillDBTestBlocksAltair(ctx context.Context, t *testing.T, beaconDB db.Datab
return genBlk, blkContainers
}
func fillDBTestBlocksBellatrix(ctx context.Context, t *testing.T, beaconDB db.Database) (*ethpbalpha.SignedBeaconBlockMerge, []*ethpbalpha.BeaconBlockContainer) {
parentRoot := [32]byte{1, 2, 3}
genBlk := util.NewBeaconBlockMerge()
genBlk.Block.ParentRoot = parentRoot[:]
root, err := genBlk.Block.HashTreeRoot()
require.NoError(t, err)
signedBlk, err := wrapper.WrappedMergeSignedBeaconBlock(genBlk)
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, signedBlk))
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, root))
count := types.Slot(100)
blks := make([]block.SignedBeaconBlock, count)
blkContainers := make([]*ethpbalpha.BeaconBlockContainer, count)
for i := types.Slot(0); i < count; i++ {
b := util.NewBeaconBlockMerge()
b.Block.Slot = i
b.Block.ParentRoot = bytesutil.PadTo([]byte{uint8(i)}, 32)
att1 := util.NewAttestation()
att1.Data.Slot = i
att1.Data.CommitteeIndex = types.CommitteeIndex(i)
att2 := util.NewAttestation()
att2.Data.Slot = i
att2.Data.CommitteeIndex = types.CommitteeIndex(i + 1)
b.Block.Body.Attestations = []*ethpbalpha.Attestation{att1, att2}
root, err := b.Block.HashTreeRoot()
require.NoError(t, err)
signedB, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
blks[i] = signedB
blkContainers[i] = &ethpbalpha.BeaconBlockContainer{
Block: &ethpbalpha.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: b}, BlockRoot: root[:]}
}
require.NoError(t, beaconDB.SaveBlocks(ctx, blks))
headRoot := bytesutil.ToBytes32(blkContainers[len(blks)-1].BlockRoot)
summary := &ethpbalpha.StateSummary{
Root: headRoot[:],
Slot: blkContainers[len(blks)-1].Block.(*ethpbalpha.BeaconBlockContainer_BellatrixBlock).BellatrixBlock.Block.Slot,
}
require.NoError(t, beaconDB.SaveStateSummary(ctx, summary))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, headRoot))
return genBlk, blkContainers
}
func TestServer_GetBlockHeader(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
@ -704,6 +748,123 @@ func TestServer_GetBlockV2(t *testing.T) {
})
}
})
t.Run("Bellatrix", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
b2 := util.NewBeaconBlockMerge()
b2.Block.Slot = 30
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
signedBlk, err := wrapper.WrappedMergeSignedBeaconBlock(b2)
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, signedBlk))
b3 := util.NewBeaconBlockMerge()
b3.Block.Slot = 30
b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32)
signedBlk, err = wrapper.WrappedMergeSignedBeaconBlock(b2)
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, signedBlk))
chainBlk, err := wrapper.WrappedMergeSignedBeaconBlock(headBlock.GetBellatrixBlock())
require.NoError(t, err)
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
},
}
genBlk, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
root, err := genBlk.Block.HashTreeRoot()
require.NoError(t, err)
tests := []struct {
name string
blockID []byte
want *ethpbalpha.SignedBeaconBlockMerge
wantErr bool
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].GetBellatrixBlock(),
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].GetBellatrixBlock(),
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.GetBellatrixBlock(),
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].GetBellatrixBlock(),
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].GetBellatrixBlock(),
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlockV2(ctx, &ethpbv2.BlockRequestV2{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v2Block, err := migration.V1Alpha1BeaconBlockBellatrixToV2(tt.want.Block)
require.NoError(t, err)
b, ok := blk.Data.Message.(*ethpbv2.SignedBeaconBlockContainerV2_MergeBlock)
require.Equal(t, true, ok)
if !reflect.DeepEqual(b.MergeBlock, v2Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_MERGE, blk.Version)
})
}
})
}
func TestServer_GetBlockSSZ(t *testing.T) {

View File

@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: a4b9bf0c477f52b0980da66582aa23b181985388419d9551e8e256729d71f1d0
// Hash: 576c78a070992220bef5cd02fa884e5a2a6fc25d851788655c4520a41c1fedee
package v1
import (

View File

@ -36,6 +36,7 @@ ssz_gen_marshal(
],
objs = [
"SignedBeaconBlockAltair",
"SignedBeaconBlockMerge",
],
)

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,20 @@ func AltairToV1Alpha1SignedBlock(altairBlk *ethpbv2.SignedBeaconBlockAltair) (*e
return v1alpha1Block, nil
}
// V1Alpha1BeaconBlockBellatrixToV2 converts a v1alpha1 Bellatrix beacon block to a v2
// Bellatrix block.
func V1Alpha1BeaconBlockBellatrixToV2(v1alpha1Block *ethpbalpha.BeaconBlockMerge) (*ethpbv2.BeaconBlockMerge, error) {
marshaledBlk, err := proto.Marshal(v1alpha1Block)
if err != nil {
return nil, errors.Wrap(err, "could not marshal block")
}
v2Block := &ethpbv2.BeaconBlockMerge{}
if err := proto.Unmarshal(marshaledBlk, v2Block); err != nil {
return nil, errors.Wrap(err, "could not unmarshal block")
}
return v2Block, nil
}
func BeaconStateAltairToV2(altairState *statev2.BeaconState) (*ethpbv2.BeaconStateV2, error) {
sourceFork := altairState.Fork()
sourceLatestBlockHeader := altairState.LatestBlockHeader()

View File

@ -98,3 +98,31 @@ func Test_AltairToV1Alpha1SignedBlock(t *testing.T) {
require.NoError(t, err)
assert.DeepEqual(t, v2Root, alphaRoot)
}
func Test_V1Alpha1BeaconBlockBellatrixToV2(t *testing.T) {
alphaBlock := util.HydrateBeaconBlockMerge(&ethpbalpha.BeaconBlockMerge{})
alphaBlock.Slot = slot
alphaBlock.ProposerIndex = validatorIndex
alphaBlock.ParentRoot = parentRoot
alphaBlock.StateRoot = stateRoot
alphaBlock.Body.RandaoReveal = randaoReveal
alphaBlock.Body.Eth1Data = &ethpbalpha.Eth1Data{
DepositRoot: depositRoot,
DepositCount: depositCount,
BlockHash: blockHash,
}
syncCommitteeBits := bitfield.NewBitvector512()
syncCommitteeBits.SetBitAt(100, true)
alphaBlock.Body.SyncAggregate = &ethpbalpha.SyncAggregate{
SyncCommitteeBits: syncCommitteeBits,
SyncCommitteeSignature: signature,
}
v2Block, err := V1Alpha1BeaconBlockBellatrixToV2(alphaBlock)
require.NoError(t, err)
alphaRoot, err := alphaBlock.HashTreeRoot()
require.NoError(t, err)
v2Root, err := v2Block.HashTreeRoot()
require.NoError(t, err)
assert.DeepEqual(t, alphaRoot, v2Root)
}

File diff suppressed because it is too large Load Diff

View File

@ -441,6 +441,9 @@ message BeaconBlockContainer {
// Representing an altair block.
SignedBeaconBlockAltair altair_block = 4;
// Representing an bellatrix block.
SignedBeaconBlockMerge bellatrix_block = 5;
}
}

View File

@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 036fa88e7ecacbc13431c0b240e9aca847ce683c0568236674aebfd928cb3a63
// Hash: d5d13cacd9733f9ea5f73d4c7a819c1f3fdd3c675b6fe7c5014da3558a93395b
package eth
import (