mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
[Feature] - Store Only Blinded Beacon Blocks Post-Merge (#11010)
* add in flags * add sync and db items * bring over all other changes * enable on * use feature flag * powchain * builds * fix up tests * pass iface * gaz * enable bellatrix blind in unmarshal only behind flag * poolside * pass rpc tests * rebuilds * naming * cleaner func * check needs resync * idiomatic * gaz * rem * build * nicer * build * cleaner * surface error * wrapping * unmarshal logs * fix up * cleaner * log * builds * Update beacon-chain/blockchain/execution_engine.go Co-authored-by: terencechain <terence@prysmaticlabs.com> * terence feedback * test added for resync * nil check * fmt Co-authored-by: terencechain <terence@prysmaticlabs.com>
This commit is contained in:
@@ -84,7 +84,7 @@ func (s *Service) validateMergeBlock(ctx context.Context, b interfaces.SignedBea
|
|||||||
|
|
||||||
// getBlkParentHashAndTD retrieves the parent hash and total difficulty of the given block.
|
// getBlkParentHashAndTD retrieves the parent hash and total difficulty of the given block.
|
||||||
func (s *Service) getBlkParentHashAndTD(ctx context.Context, blkHash []byte) ([]byte, *uint256.Int, error) {
|
func (s *Service) getBlkParentHashAndTD(ctx context.Context, blkHash []byte) ([]byte, *uint256.Int, error) {
|
||||||
blk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(blkHash))
|
blk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(blkHash), false /* no txs */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "could not get pow block")
|
return nil, nil, errors.Wrap(err, "could not get pow block")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ go_library(
|
|||||||
"log.go",
|
"log.go",
|
||||||
"migration.go",
|
"migration.go",
|
||||||
"migration_archived_index.go",
|
"migration_archived_index.go",
|
||||||
|
"migration_blinded_beacon_blocks.go",
|
||||||
"migration_block_slot_index.go",
|
"migration_block_slot_index.go",
|
||||||
"migration_state_validators.go",
|
"migration_state_validators.go",
|
||||||
"powchain.go",
|
"powchain.go",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
ssz "github.com/prysmaticlabs/fastssz"
|
ssz "github.com/prysmaticlabs/fastssz"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||||
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
@@ -130,7 +131,7 @@ func (s *Store) Blocks(ctx context.Context, f *filters.QueryFilter) ([]interface
|
|||||||
encoded := bkt.Get(keys[i])
|
encoded := bkt.Get(keys[i])
|
||||||
blk, err := unmarshalBlock(ctx, encoded)
|
blk, err := unmarshalBlock(ctx, encoded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrapf(err, "could not unmarshal block with key %#x", keys[i])
|
||||||
}
|
}
|
||||||
blocks = append(blocks, blk)
|
blocks = append(blocks, blk)
|
||||||
blockRoots = append(blockRoots, bytesutil.ToBytes32(keys[i]))
|
blockRoots = append(blockRoots, bytesutil.ToBytes32(keys[i]))
|
||||||
@@ -304,6 +305,16 @@ func (s *Store) SaveBlocks(ctx context.Context, blocks []interfaces.SignedBeacon
|
|||||||
if err := updateValueForIndices(ctx, indicesForBlocks[i], blockRoots[i], tx); err != nil {
|
if err := updateValueForIndices(ctx, indicesForBlocks[i], blockRoots[i], tx); err != nil {
|
||||||
return errors.Wrap(err, "could not update DB indices")
|
return errors.Wrap(err, "could not update DB indices")
|
||||||
}
|
}
|
||||||
|
if features.Get().EnableOnlyBlindedBeaconBlocks {
|
||||||
|
blindedBlock, err := blk.ToBlinded()
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, wrapper.ErrUnsupportedVersion) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
blk = blindedBlock
|
||||||
|
}
|
||||||
|
}
|
||||||
s.blockCache.Set(string(blockRoots[i]), blk, int64(len(encodedBlocks[i])))
|
s.blockCache.Set(string(blockRoots[i]), blk, int64(len(encodedBlocks[i])))
|
||||||
if err := bkt.Put(blockRoots[i], encodedBlocks[i]); err != nil {
|
if err := bkt.Put(blockRoots[i], encodedBlocks[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -758,7 +769,7 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.SignedBeaconBlock
|
|||||||
var err error
|
var err error
|
||||||
enc, err = snappy.Decode(nil, enc)
|
enc, err = snappy.Decode(nil, enc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "could not snappy decode block")
|
||||||
}
|
}
|
||||||
var rawBlock ssz.Unmarshaler
|
var rawBlock ssz.Unmarshaler
|
||||||
switch {
|
switch {
|
||||||
@@ -766,23 +777,23 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.SignedBeaconBlock
|
|||||||
// Marshal block bytes to altair beacon block.
|
// Marshal block bytes to altair beacon block.
|
||||||
rawBlock = ðpb.SignedBeaconBlockAltair{}
|
rawBlock = ðpb.SignedBeaconBlockAltair{}
|
||||||
if err := rawBlock.UnmarshalSSZ(enc[len(altairKey):]); err != nil {
|
if err := rawBlock.UnmarshalSSZ(enc[len(altairKey):]); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "could not unmarshal Altair block")
|
||||||
}
|
}
|
||||||
case hasBellatrixKey(enc):
|
case hasBellatrixKey(enc):
|
||||||
rawBlock = ðpb.SignedBeaconBlockBellatrix{}
|
rawBlock = ðpb.SignedBeaconBlockBellatrix{}
|
||||||
if err := rawBlock.UnmarshalSSZ(enc[len(bellatrixKey):]); err != nil {
|
if err := rawBlock.UnmarshalSSZ(enc[len(bellatrixKey):]); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "could not unmarshal Bellatrix block")
|
||||||
}
|
}
|
||||||
case hasBellatrixBlindKey(enc):
|
case hasBellatrixBlindKey(enc):
|
||||||
rawBlock = ðpb.SignedBlindedBeaconBlockBellatrix{}
|
rawBlock = ðpb.SignedBlindedBeaconBlockBellatrix{}
|
||||||
if err := rawBlock.UnmarshalSSZ(enc[len(bellatrixBlindKey):]); err != nil {
|
if err := rawBlock.UnmarshalSSZ(enc[len(bellatrixBlindKey):]); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "could not unmarshal blinded Bellatrix block")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// Marshal block bytes to phase 0 beacon block.
|
// Marshal block bytes to phase 0 beacon block.
|
||||||
rawBlock = ðpb.SignedBeaconBlock{}
|
rawBlock = ðpb.SignedBeaconBlock{}
|
||||||
if err := rawBlock.UnmarshalSSZ(enc); err != nil {
|
if err := rawBlock.UnmarshalSSZ(enc); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "could not unmarshal Phase0 block")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wrapper.WrappedSignedBeaconBlock(rawBlock)
|
return wrapper.WrappedSignedBeaconBlock(rawBlock)
|
||||||
@@ -790,19 +801,41 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.SignedBeaconBlock
|
|||||||
|
|
||||||
// marshal versioned beacon block from struct type down to bytes.
|
// marshal versioned beacon block from struct type down to bytes.
|
||||||
func marshalBlock(_ context.Context, blk interfaces.SignedBeaconBlock) ([]byte, error) {
|
func marshalBlock(_ context.Context, blk interfaces.SignedBeaconBlock) ([]byte, error) {
|
||||||
obj, err := blk.MarshalSSZ()
|
var encodedBlock []byte
|
||||||
if err != nil {
|
var err error
|
||||||
return nil, err
|
blockToSave := blk
|
||||||
|
if features.Get().EnableOnlyBlindedBeaconBlocks {
|
||||||
|
blindedBlock, err := blk.ToBlinded()
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, wrapper.ErrUnsupportedVersion):
|
||||||
|
encodedBlock, err = blk.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not marshal non-blinded block")
|
||||||
|
}
|
||||||
|
case err != nil:
|
||||||
|
return nil, errors.Wrap(err, "could not convert block to blinded format")
|
||||||
|
default:
|
||||||
|
encodedBlock, err = blindedBlock.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not marshal blinded block")
|
||||||
|
}
|
||||||
|
blockToSave = blindedBlock
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
encodedBlock, err = blk.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch blk.Version() {
|
switch blockToSave.Version() {
|
||||||
case version.BellatrixBlind:
|
case version.BellatrixBlind:
|
||||||
return snappy.Encode(nil, append(bellatrixBlindKey, obj...)), nil
|
return snappy.Encode(nil, append(bellatrixBlindKey, encodedBlock...)), nil
|
||||||
case version.Bellatrix:
|
case version.Bellatrix:
|
||||||
return snappy.Encode(nil, append(bellatrixKey, obj...)), nil
|
return snappy.Encode(nil, append(bellatrixKey, encodedBlock...)), nil
|
||||||
case version.Altair:
|
case version.Altair:
|
||||||
return snappy.Encode(nil, append(altairKey, obj...)), nil
|
return snappy.Encode(nil, append(altairKey, encodedBlock...)), nil
|
||||||
case version.Phase0:
|
case version.Phase0:
|
||||||
return snappy.Encode(nil, obj), nil
|
return snappy.Encode(nil, encodedBlock), nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("Unknown block version")
|
return nil, errors.New("Unknown block version")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,11 +134,17 @@ func TestStore_BlocksCRUD(t *testing.T) {
|
|||||||
retrievedBlock, err := db.Block(ctx, blockRoot)
|
retrievedBlock, err := db.Block(ctx, blockRoot)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
|
assert.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
|
||||||
|
|
||||||
require.NoError(t, db.SaveBlock(ctx, blk))
|
require.NoError(t, db.SaveBlock(ctx, blk))
|
||||||
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
|
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
|
||||||
retrievedBlock, err = db.Block(ctx, blockRoot)
|
retrievedBlock, err = db.Block(ctx, blockRoot)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(blk.Proto(), retrievedBlock.Proto()), "Wanted: %v, received: %v", blk, retrievedBlock)
|
wanted := retrievedBlock
|
||||||
|
if _, err := retrievedBlock.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = retrievedBlock.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), retrievedBlock.Proto()), "Wanted: %v, received: %v", wanted, retrievedBlock)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +320,13 @@ func TestStore_BlocksCRUD_NoCache(t *testing.T) {
|
|||||||
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
|
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
|
||||||
retrievedBlock, err = db.Block(ctx, blockRoot)
|
retrievedBlock, err = db.Block(ctx, blockRoot)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(blk.Proto(), retrievedBlock.Proto()), "Wanted: %v, received: %v", blk, retrievedBlock)
|
|
||||||
|
wanted := blk
|
||||||
|
if _, err := blk.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = blk.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), retrievedBlock.Proto()), "Wanted: %v, received: %v", wanted, retrievedBlock)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,7 +536,12 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
root := roots[0]
|
root := roots[0]
|
||||||
b, err := db.Block(ctx, root)
|
b, err := db.Block(ctx, root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(block1.Proto(), b.Proto()), "Wanted: %v, received: %v", block1, b)
|
wanted := block1
|
||||||
|
if _, err := block1.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = wanted.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), b.Proto()), "Wanted: %v, received: %v", wanted, b)
|
||||||
|
|
||||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 11)
|
_, roots, err = db.HighestRootsBelowSlot(ctx, 11)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -533,7 +550,12 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
root = roots[0]
|
root = roots[0]
|
||||||
b, err = db.Block(ctx, root)
|
b, err = db.Block(ctx, root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(block2.Proto(), b.Proto()), "Wanted: %v, received: %v", block2, b)
|
wanted2 := block2
|
||||||
|
if _, err := block2.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted2, err = block2.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted2.Proto(), b.Proto()), "Wanted: %v, received: %v", wanted2, b)
|
||||||
|
|
||||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 101)
|
_, roots, err = db.HighestRootsBelowSlot(ctx, 101)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -542,7 +564,12 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
root = roots[0]
|
root = roots[0]
|
||||||
b, err = db.Block(ctx, root)
|
b, err = db.Block(ctx, root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(block3.Proto(), b.Proto()), "Wanted: %v, received: %v", block3, b)
|
wanted = block3
|
||||||
|
if _, err := block3.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = wanted.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), b.Proto()), "Wanted: %v, received: %v", wanted, b)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -569,7 +596,12 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
root := roots[0]
|
root := roots[0]
|
||||||
b, err := db.Block(ctx, root)
|
b, err := db.Block(ctx, root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(block1.Proto(), b.Proto()), "Wanted: %v, received: %v", block1, b)
|
wanted := block1
|
||||||
|
if _, err := block1.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = block1.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), b.Proto()), "Wanted: %v, received: %v", wanted, b)
|
||||||
|
|
||||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 1)
|
_, roots, err = db.HighestRootsBelowSlot(ctx, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -577,7 +609,12 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
root = roots[0]
|
root = roots[0]
|
||||||
b, err = db.Block(ctx, root)
|
b, err = db.Block(ctx, root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), b.Proto()), "Wanted: %v, received: %v", genesisBlock, b)
|
wanted = genesisBlock
|
||||||
|
if _, err := genesisBlock.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = genesisBlock.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), b.Proto()), "Wanted: %v, received: %v", wanted, b)
|
||||||
|
|
||||||
_, roots, err = db.HighestRootsBelowSlot(ctx, 0)
|
_, roots, err = db.HighestRootsBelowSlot(ctx, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -585,7 +622,12 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
root = roots[0]
|
root = roots[0]
|
||||||
b, err = db.Block(ctx, root)
|
b, err = db.Block(ctx, root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), b.Proto()), "Wanted: %v, received: %v", genesisBlock, b)
|
wanted = genesisBlock
|
||||||
|
if _, err := genesisBlock.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = genesisBlock.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), b.Proto()), "Wanted: %v, received: %v", wanted, b)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -671,15 +713,31 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) {
|
|||||||
assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none")
|
assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none")
|
||||||
retrievedBlocks, err = db.BlocksBySlot(ctx, 20)
|
retrievedBlocks, err = db.BlocksBySlot(ctx, 20)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, proto.Equal(b1.Proto(), retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b1, retrievedBlocks[0])
|
|
||||||
|
wanted := b1
|
||||||
|
if _, err := b1.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = b1.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(retrievedBlocks[0].Proto(), wanted.Proto()), "Wanted: %v, received: %v", retrievedBlocks[0], wanted)
|
||||||
assert.Equal(t, true, len(retrievedBlocks) > 0, "Expected to have blocks")
|
assert.Equal(t, true, len(retrievedBlocks) > 0, "Expected to have blocks")
|
||||||
retrievedBlocks, err = db.BlocksBySlot(ctx, 100)
|
retrievedBlocks, err = db.BlocksBySlot(ctx, 100)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if len(retrievedBlocks) != 2 {
|
if len(retrievedBlocks) != 2 {
|
||||||
t.Fatalf("Expected 2 blocks, received %d blocks", len(retrievedBlocks))
|
t.Fatalf("Expected 2 blocks, received %d blocks", len(retrievedBlocks))
|
||||||
}
|
}
|
||||||
assert.Equal(t, true, proto.Equal(b2.Proto(), retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b2, retrievedBlocks[0])
|
wanted = b2
|
||||||
assert.Equal(t, true, proto.Equal(b3.Proto(), retrievedBlocks[1].Proto()), "Wanted: %v, received: %v", b3, retrievedBlocks[1])
|
if _, err := b2.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = b2.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(wanted.Proto(), retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", retrievedBlocks[0], wanted)
|
||||||
|
wanted = b3
|
||||||
|
if _, err := b3.PbBellatrixBlock(); err == nil {
|
||||||
|
wanted, err = b3.ToBlinded()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, true, proto.Equal(retrievedBlocks[1].Proto(), wanted.Proto()), "Wanted: %v, received: %v", retrievedBlocks[1], wanted)
|
||||||
assert.Equal(t, true, len(retrievedBlocks) > 0, "Expected to have blocks")
|
assert.Equal(t, true, len(retrievedBlocks) > 0, "Expected to have blocks")
|
||||||
|
|
||||||
hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1)
|
hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package kv
|
package kv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -9,4 +10,7 @@ func init() {
|
|||||||
if err := params.SetActive(params.MainnetTestConfig()); err != nil {
|
if err := params.SetActive(params.MainnetTestConfig()); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
features.Init(&features.Flags{
|
||||||
|
EnableOnlyBlindedBeaconBlocks: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package kv
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,6 +15,7 @@ import (
|
|||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
prombolt "github.com/prysmaticlabs/prombbolt"
|
prombolt "github.com/prysmaticlabs/prombbolt"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/iface"
|
"github.com/prysmaticlabs/prysm/beacon-chain/db/iface"
|
||||||
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/io/file"
|
"github.com/prysmaticlabs/prysm/io/file"
|
||||||
bolt "go.etcd.io/bbolt"
|
bolt "go.etcd.io/bbolt"
|
||||||
@@ -183,8 +185,13 @@ func NewKVStore(ctx context.Context, dirPath string, config *Config) (*Store, er
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = prometheus.Register(createBoltCollector(kv.db))
|
if err = prometheus.Register(createBoltCollector(kv.db)); err != nil {
|
||||||
return kv, err
|
return nil, err
|
||||||
|
}
|
||||||
|
if err = kv.checkNeedsResync(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return kv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearDB removes the previously stored database in the data directory.
|
// ClearDB removes the previously stored database in the data directory.
|
||||||
@@ -216,6 +223,23 @@ func (s *Store) DatabasePath() string {
|
|||||||
return s.databasePath
|
return s.databasePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Store) checkNeedsResync() error {
|
||||||
|
return s.db.View(func(tx *bolt.Tx) error {
|
||||||
|
bkt := tx.Bucket(migrationsBucket)
|
||||||
|
hasDisabledFeature := !features.Get().EnableOnlyBlindedBeaconBlocks
|
||||||
|
if hasDisabledFeature && bkt.Get(migrationBlindedBeaconBlocksKey) != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"you have disabled the flag %s, and your node must resync to ensure your "+
|
||||||
|
"database is compatible. If you do not want to resync, please re-enable the %s flag",
|
||||||
|
features.EnableOnlyBlindedBeaconBlocks.Name,
|
||||||
|
features.EnableOnlyBlindedBeaconBlocks.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func createBuckets(tx *bolt.Tx, buckets ...[]byte) error {
|
func createBuckets(tx *bolt.Tx, buckets ...[]byte) error {
|
||||||
for _, bucket := range buckets {
|
for _, bucket := range buckets {
|
||||||
if _, err := tx.CreateBucketIfNotExists(bucket); err != nil {
|
if _, err := tx.CreateBucketIfNotExists(bucket); err != nil {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// setupDB instantiates and returns a Store instance.
|
// setupDB instantiates and returns a Store instance.
|
||||||
@@ -16,3 +18,17 @@ func setupDB(t testing.TB) *Store {
|
|||||||
})
|
})
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_checkNeedsResync(t *testing.T) {
|
||||||
|
store := setupDB(t)
|
||||||
|
resetFn := features.InitWithReset(&features.Flags{
|
||||||
|
EnableOnlyBlindedBeaconBlocks: false,
|
||||||
|
})
|
||||||
|
defer resetFn()
|
||||||
|
require.NoError(t, store.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
bkt := tx.Bucket(migrationsBucket)
|
||||||
|
return bkt.Put(migrationBlindedBeaconBlocksKey, migrationCompleted)
|
||||||
|
}))
|
||||||
|
err := store.checkNeedsResync()
|
||||||
|
require.ErrorContains(t, "your node must resync", err)
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ var migrations = []migration{
|
|||||||
migrateArchivedIndex,
|
migrateArchivedIndex,
|
||||||
migrateBlockSlotIndex,
|
migrateBlockSlotIndex,
|
||||||
migrateStateValidators,
|
migrateStateValidators,
|
||||||
|
migrateBlindedBeaconBlocksEnabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunMigrations defined in the migrations array.
|
// RunMigrations defined in the migrations array.
|
||||||
|
|||||||
27
beacon-chain/db/kv/migration_blinded_beacon_blocks.go
Normal file
27
beacon-chain/db/kv/migration_blinded_beacon_blocks.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package kv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var migrationBlindedBeaconBlocksKey = []byte("blinded-beacon-blocks-enabled")
|
||||||
|
|
||||||
|
func migrateBlindedBeaconBlocksEnabled(ctx context.Context, db *bolt.DB) error {
|
||||||
|
if !features.Get().EnableOnlyBlindedBeaconBlocks {
|
||||||
|
return nil // Only write to the migrations bucket if the feature is enabled.
|
||||||
|
}
|
||||||
|
if updateErr := db.Update(func(tx *bolt.Tx) error {
|
||||||
|
mb := tx.Bucket(migrationsBucket)
|
||||||
|
if b := mb.Get(migrationBlindedBeaconBlocksKey); bytes.Equal(b, migrationCompleted) {
|
||||||
|
return nil // Migration already completed.
|
||||||
|
}
|
||||||
|
return mb.Put(migrationBlindedBeaconBlocksKey, migrationCompleted)
|
||||||
|
}); updateErr != nil {
|
||||||
|
return updateErr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -694,6 +694,7 @@ func (b *BeaconNode) registerSyncService() error {
|
|||||||
regularsync.WithStateGen(b.stateGen),
|
regularsync.WithStateGen(b.stateGen),
|
||||||
regularsync.WithSlasherAttestationsFeed(b.slasherAttestationsFeed),
|
regularsync.WithSlasherAttestationsFeed(b.slasherAttestationsFeed),
|
||||||
regularsync.WithSlasherBlockHeadersFeed(b.slasherBlockHeadersFeed),
|
regularsync.WithSlasherBlockHeadersFeed(b.slasherBlockHeadersFeed),
|
||||||
|
regularsync.WithExecutionPayloadReconstructor(web3Service),
|
||||||
)
|
)
|
||||||
return b.services.RegisterService(rs)
|
return b.services.RegisterService(rs)
|
||||||
}
|
}
|
||||||
@@ -799,49 +800,50 @@ func (b *BeaconNode) registerRPCService() error {
|
|||||||
|
|
||||||
p2pService := b.fetchP2P()
|
p2pService := b.fetchP2P()
|
||||||
rpcService := rpc.NewService(b.ctx, &rpc.Config{
|
rpcService := rpc.NewService(b.ctx, &rpc.Config{
|
||||||
Host: host,
|
ExecutionEngineCaller: web3Service,
|
||||||
Port: port,
|
ExecutionPayloadReconstructor: web3Service,
|
||||||
BeaconMonitoringHost: beaconMonitoringHost,
|
Host: host,
|
||||||
BeaconMonitoringPort: beaconMonitoringPort,
|
Port: port,
|
||||||
CertFlag: cert,
|
BeaconMonitoringHost: beaconMonitoringHost,
|
||||||
KeyFlag: key,
|
BeaconMonitoringPort: beaconMonitoringPort,
|
||||||
BeaconDB: b.db,
|
CertFlag: cert,
|
||||||
Broadcaster: p2pService,
|
KeyFlag: key,
|
||||||
PeersFetcher: p2pService,
|
BeaconDB: b.db,
|
||||||
PeerManager: p2pService,
|
Broadcaster: p2pService,
|
||||||
MetadataProvider: p2pService,
|
PeersFetcher: p2pService,
|
||||||
ChainInfoFetcher: chainService,
|
PeerManager: p2pService,
|
||||||
HeadUpdater: chainService,
|
MetadataProvider: p2pService,
|
||||||
HeadFetcher: chainService,
|
ChainInfoFetcher: chainService,
|
||||||
CanonicalFetcher: chainService,
|
HeadUpdater: chainService,
|
||||||
ForkFetcher: chainService,
|
HeadFetcher: chainService,
|
||||||
FinalizationFetcher: chainService,
|
CanonicalFetcher: chainService,
|
||||||
BlockReceiver: chainService,
|
ForkFetcher: chainService,
|
||||||
AttestationReceiver: chainService,
|
FinalizationFetcher: chainService,
|
||||||
GenesisTimeFetcher: chainService,
|
BlockReceiver: chainService,
|
||||||
GenesisFetcher: chainService,
|
AttestationReceiver: chainService,
|
||||||
OptimisticModeFetcher: chainService,
|
GenesisTimeFetcher: chainService,
|
||||||
AttestationsPool: b.attestationPool,
|
GenesisFetcher: chainService,
|
||||||
ExitPool: b.exitPool,
|
OptimisticModeFetcher: chainService,
|
||||||
SlashingsPool: b.slashingsPool,
|
AttestationsPool: b.attestationPool,
|
||||||
SlashingChecker: slasherService,
|
ExitPool: b.exitPool,
|
||||||
SyncCommitteeObjectPool: b.syncCommitteePool,
|
SlashingsPool: b.slashingsPool,
|
||||||
POWChainService: web3Service,
|
SlashingChecker: slasherService,
|
||||||
POWChainInfoFetcher: web3Service,
|
SyncCommitteeObjectPool: b.syncCommitteePool,
|
||||||
ChainStartFetcher: chainStartFetcher,
|
POWChainService: web3Service,
|
||||||
MockEth1Votes: mockEth1DataVotes,
|
POWChainInfoFetcher: web3Service,
|
||||||
SyncService: syncService,
|
ChainStartFetcher: chainStartFetcher,
|
||||||
DepositFetcher: depositFetcher,
|
MockEth1Votes: mockEth1DataVotes,
|
||||||
PendingDepositFetcher: b.depositCache,
|
SyncService: syncService,
|
||||||
BlockNotifier: b,
|
DepositFetcher: depositFetcher,
|
||||||
StateNotifier: b,
|
PendingDepositFetcher: b.depositCache,
|
||||||
OperationNotifier: b,
|
BlockNotifier: b,
|
||||||
StateGen: b.stateGen,
|
StateNotifier: b,
|
||||||
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
|
OperationNotifier: b,
|
||||||
MaxMsgSize: maxMsgSize,
|
StateGen: b.stateGen,
|
||||||
ProposerIdsCache: b.proposerIdsCache,
|
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
|
||||||
ExecutionEngineCaller: web3Service,
|
MaxMsgSize: maxMsgSize,
|
||||||
BlockBuilder: b.fetchBuilderService(),
|
ProposerIdsCache: b.proposerIdsCache,
|
||||||
|
BlockBuilder: b.fetchBuilderService(),
|
||||||
})
|
})
|
||||||
|
|
||||||
return b.services.RegisterService(rpcService)
|
return b.services.RegisterService(rpcService)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ type EngineCaller interface {
|
|||||||
ExchangeTransitionConfiguration(
|
ExchangeTransitionConfiguration(
|
||||||
ctx context.Context, cfg *pb.TransitionConfiguration,
|
ctx context.Context, cfg *pb.TransitionConfiguration,
|
||||||
) error
|
) error
|
||||||
ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error)
|
ExecutionBlockByHash(ctx context.Context, hash common.Hash, withTxs bool) (*pb.ExecutionBlock, error)
|
||||||
GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error)
|
GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ func (s *Service) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error
|
|||||||
if parentHash == params.BeaconConfig().ZeroHash {
|
if parentHash == params.BeaconConfig().ZeroHash {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
parentBlk, err := s.ExecutionBlockByHash(ctx, parentHash)
|
parentBlk, err := s.ExecutionBlockByHash(ctx, parentHash, false /* no txs */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||||
}
|
}
|
||||||
@@ -296,12 +296,11 @@ func (s *Service) LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock,
|
|||||||
|
|
||||||
// ExecutionBlockByHash fetches an execution engine block by hash by calling
|
// ExecutionBlockByHash fetches an execution engine block by hash by calling
|
||||||
// eth_blockByHash via JSON-RPC.
|
// eth_blockByHash via JSON-RPC.
|
||||||
func (s *Service) ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error) {
|
func (s *Service) ExecutionBlockByHash(ctx context.Context, hash common.Hash, withTxs bool) (*pb.ExecutionBlock, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExecutionBlockByHash")
|
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExecutionBlockByHash")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
result := &pb.ExecutionBlock{}
|
result := &pb.ExecutionBlock{}
|
||||||
err := s.rpcClient.CallContext(ctx, result, ExecutionBlockByHashMethod, hash, false /* no full transaction objects */)
|
err := s.rpcClient.CallContext(ctx, result, ExecutionBlockByHashMethod, hash, withTxs)
|
||||||
return result, handleRPCError(err)
|
return result, handleRPCError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +320,7 @@ func (s *Service) ReconstructFullBellatrixBlock(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
executionBlockHash := common.BytesToHash(header.BlockHash())
|
executionBlockHash := common.BytesToHash(header.BlockHash())
|
||||||
executionBlock, err := s.ExecutionBlockByHash(ctx, executionBlockHash)
|
executionBlock, err := s.ExecutionBlockByHash(ctx, executionBlockHash, true /* with txs */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not fetch execution block with txs by hash %#x: %v", executionBlockHash, err)
|
return nil, fmt.Errorf("could not fetch execution block with txs by hash %#x: %v", executionBlockHash, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
_ = ExecutionPayloadReconstructor(&Service{})
|
_ = ExecutionPayloadReconstructor(&Service{})
|
||||||
_ = EngineCaller(&Service{})
|
_ = EngineCaller(&Service{})
|
||||||
|
_ = ExecutionPayloadReconstructor(&Service{})
|
||||||
_ = EngineCaller(&mocks.EngineClient{})
|
_ = EngineCaller(&mocks.EngineClient{})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ func TestClient_IPC(t *testing.T) {
|
|||||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
arg := common.BytesToHash([]byte("foo"))
|
arg := common.BytesToHash([]byte("foo"))
|
||||||
resp, err := srv.ExecutionBlockByHash(ctx, arg)
|
resp, err := srv.ExecutionBlockByHash(ctx, arg, true /* with txs */)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.DeepEqual(t, want, resp)
|
require.DeepEqual(t, want, resp)
|
||||||
})
|
})
|
||||||
@@ -396,7 +397,7 @@ func TestClient_HTTP(t *testing.T) {
|
|||||||
service.rpcClient = rpcClient
|
service.rpcClient = rpcClient
|
||||||
|
|
||||||
// We call the RPC method via HTTP and expect a proper result.
|
// We call the RPC method via HTTP and expect a proper result.
|
||||||
resp, err := service.ExecutionBlockByHash(ctx, arg)
|
resp, err := service.ExecutionBlockByHash(ctx, arg, true /* with txs */)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.DeepEqual(t, want, resp)
|
require.DeepEqual(t, want, resp)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ go_library(
|
|||||||
"//beacon-chain/state/v1:go_default_library",
|
"//beacon-chain/state/v1:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
"//consensus-types/interfaces:go_default_library",
|
"//consensus-types/interfaces:go_default_library",
|
||||||
|
"//consensus-types/wrapper:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//proto/engine/v1:go_default_library",
|
"//proto/engine/v1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
|
|||||||
@@ -10,26 +10,29 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EngineClient --
|
// EngineClient --
|
||||||
type EngineClient struct {
|
type EngineClient struct {
|
||||||
NewPayloadResp []byte
|
NewPayloadResp []byte
|
||||||
PayloadIDBytes *pb.PayloadIDBytes
|
PayloadIDBytes *pb.PayloadIDBytes
|
||||||
ForkChoiceUpdatedResp []byte
|
ForkChoiceUpdatedResp []byte
|
||||||
ExecutionPayload *pb.ExecutionPayload
|
ExecutionPayload *pb.ExecutionPayload
|
||||||
ExecutionBlock *pb.ExecutionBlock
|
ExecutionBlock *pb.ExecutionBlock
|
||||||
Err error
|
Err error
|
||||||
ErrLatestExecBlock error
|
ErrLatestExecBlock error
|
||||||
ErrExecBlockByHash error
|
ErrExecBlockByHash error
|
||||||
ErrForkchoiceUpdated error
|
ErrForkchoiceUpdated error
|
||||||
ErrNewPayload error
|
ErrNewPayload error
|
||||||
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
ExecutionPayloadByBlockHash map[[32]byte]*pb.ExecutionPayload
|
||||||
TerminalBlockHash []byte
|
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
||||||
TerminalBlockHashExists bool
|
NumReconstructedPayloads uint64
|
||||||
OverrideValidHash [32]byte
|
TerminalBlockHash []byte
|
||||||
|
TerminalBlockHashExists bool
|
||||||
|
OverrideValidHash [32]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPayload --
|
// NewPayload --
|
||||||
@@ -63,7 +66,7 @@ func (e *EngineClient) LatestExecutionBlock(_ context.Context) (*pb.ExecutionBlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionBlockByHash --
|
// ExecutionBlockByHash --
|
||||||
func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash) (*pb.ExecutionBlock, error) {
|
func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash, _ bool) (*pb.ExecutionBlock, error) {
|
||||||
b, ok := e.BlockByHashMap[h]
|
b, ok := e.BlockByHashMap[h]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("block not found")
|
return nil, errors.New("block not found")
|
||||||
@@ -71,6 +74,24 @@ func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash) (*
|
|||||||
return b, e.ErrExecBlockByHash
|
return b, e.ErrExecBlockByHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *EngineClient) ReconstructFullBellatrixBlock(
|
||||||
|
_ context.Context, blindedBlock interfaces.SignedBeaconBlock,
|
||||||
|
) (interfaces.SignedBeaconBlock, error) {
|
||||||
|
if !blindedBlock.Block().IsBlinded() {
|
||||||
|
return nil, errors.New("block must be blinded")
|
||||||
|
}
|
||||||
|
header, err := blindedBlock.Block().Body().Execution()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload, ok := e.ExecutionPayloadByBlockHash[bytesutil.ToBytes32(header.BlockHash())]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("block not found")
|
||||||
|
}
|
||||||
|
e.NumReconstructedPayloads++
|
||||||
|
return wrapper.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload)
|
||||||
|
}
|
||||||
|
|
||||||
// GetTerminalBlockHash --
|
// GetTerminalBlockHash --
|
||||||
func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
|
func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
|
||||||
ttd := new(big.Int)
|
ttd := new(big.Int)
|
||||||
@@ -99,7 +120,7 @@ func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool,
|
|||||||
if parentHash == params.BeaconConfig().ZeroHash {
|
if parentHash == params.BeaconConfig().ZeroHash {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
parentBlk, err := e.ExecutionBlockByHash(ctx, parentHash)
|
parentBlk, err := e.ExecutionBlockByHash(ctx, parentHash, false /* with txs */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ go_library(
|
|||||||
"//beacon-chain/operations/slashings:go_default_library",
|
"//beacon-chain/operations/slashings:go_default_library",
|
||||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||||
"//beacon-chain/p2p:go_default_library",
|
"//beacon-chain/p2p:go_default_library",
|
||||||
|
"//beacon-chain/powchain:go_default_library",
|
||||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||||
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
|
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
|
||||||
"//beacon-chain/rpc/statefetcher:go_default_library",
|
"//beacon-chain/rpc/statefetcher:go_default_library",
|
||||||
@@ -88,6 +89,7 @@ go_test(
|
|||||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||||
"//beacon-chain/operations/voluntaryexits/mock:go_default_library",
|
"//beacon-chain/operations/voluntaryexits/mock:go_default_library",
|
||||||
"//beacon-chain/p2p/testing:go_default_library",
|
"//beacon-chain/p2p/testing:go_default_library",
|
||||||
|
"//beacon-chain/powchain/testing:go_default_library",
|
||||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||||
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
|
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
|
||||||
"//beacon-chain/rpc/statefetcher:go_default_library",
|
"//beacon-chain/rpc/statefetcher:go_default_library",
|
||||||
@@ -101,6 +103,7 @@ go_test(
|
|||||||
"//crypto/bls:go_default_library",
|
"//crypto/bls:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//encoding/ssz:go_default_library",
|
"//encoding/ssz:go_default_library",
|
||||||
|
"//proto/engine/v1:go_default_library",
|
||||||
"//proto/eth/service:go_default_library",
|
"//proto/eth/service:go_default_library",
|
||||||
"//proto/eth/v1:go_default_library",
|
"//proto/eth/v1:go_default_library",
|
||||||
"//proto/eth/v2:go_default_library",
|
"//proto/eth/v2:go_default_library",
|
||||||
|
|||||||
@@ -474,8 +474,42 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
|
|||||||
ExecutionOptimistic: isOptimistic,
|
ExecutionOptimistic: isOptimistic,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
if _, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||||
|
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBellatrixBlock(ctx, blk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(
|
||||||
|
codes.Internal,
|
||||||
|
"Could not reconstruct full execution payload to create signed beacon block: %v",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
bellatrixBlk, err = signedFullBlock.PbBellatrixBlock()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||||
|
}
|
||||||
|
v2Blk, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlk.Block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||||
|
}
|
||||||
|
root, err := blk.Block().HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get block root: %v", err)
|
||||||
|
}
|
||||||
|
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not check if block is optimistic: %v", err)
|
||||||
|
}
|
||||||
|
return ðpbv2.BlockResponseV2{
|
||||||
|
Version: ethpbv2.Version_BELLATRIX,
|
||||||
|
Data: ðpbv2.SignedBeaconBlockContainerV2{
|
||||||
|
Message: ðpbv2.SignedBeaconBlockContainerV2_BellatrixBlock{BellatrixBlock: v2Blk},
|
||||||
|
Signature: blk.Signature(),
|
||||||
|
},
|
||||||
|
ExecutionOptimistic: isOptimistic,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
// ErrUnsupportedBellatrixBlock means that we have another block type
|
// ErrUnsupportedBellatrixBlock means that we have another block type
|
||||||
if !errors.Is(err, wrapper.ErrUnsupportedBellatrixBlock) {
|
if !errors.Is(err, wrapper.ErrUnsupportedBlindedBellatrixBlock) {
|
||||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||||
dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||||
|
powchaintesting "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||||
|
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||||
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
|
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
|
||||||
"github.com/prysmaticlabs/prysm/proto/migration"
|
"github.com/prysmaticlabs/prysm/proto/migration"
|
||||||
@@ -1290,6 +1292,9 @@ func TestServer_GetBlockV2(t *testing.T) {
|
|||||||
ChainInfoFetcher: mockChainService,
|
ChainInfoFetcher: mockChainService,
|
||||||
HeadFetcher: mockChainService,
|
HeadFetcher: mockChainService,
|
||||||
OptimisticModeFetcher: mockChainService,
|
OptimisticModeFetcher: mockChainService,
|
||||||
|
ExecutionPayloadReconstructor: &powchaintesting.EngineClient{
|
||||||
|
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
genBlk, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
|
genBlk, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||||
v1alpha1validator "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator"
|
v1alpha1validator "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher"
|
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||||
@@ -21,22 +22,23 @@ import (
|
|||||||
// Server defines a server implementation of the gRPC Beacon Chain service,
|
// Server defines a server implementation of the gRPC Beacon Chain service,
|
||||||
// providing RPC endpoints to access data relevant to the Ethereum Beacon Chain.
|
// providing RPC endpoints to access data relevant to the Ethereum Beacon Chain.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
BeaconDB db.ReadOnlyDatabase
|
BeaconDB db.ReadOnlyDatabase
|
||||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||||
GenesisTimeFetcher blockchain.TimeFetcher
|
GenesisTimeFetcher blockchain.TimeFetcher
|
||||||
BlockReceiver blockchain.BlockReceiver
|
BlockReceiver blockchain.BlockReceiver
|
||||||
BlockNotifier blockfeed.Notifier
|
BlockNotifier blockfeed.Notifier
|
||||||
OperationNotifier operation.Notifier
|
OperationNotifier operation.Notifier
|
||||||
Broadcaster p2p.Broadcaster
|
Broadcaster p2p.Broadcaster
|
||||||
AttestationsPool attestations.Pool
|
AttestationsPool attestations.Pool
|
||||||
SlashingsPool slashings.PoolManager
|
SlashingsPool slashings.PoolManager
|
||||||
VoluntaryExitsPool voluntaryexits.PoolManager
|
VoluntaryExitsPool voluntaryexits.PoolManager
|
||||||
StateGenService stategen.StateManager
|
StateGenService stategen.StateManager
|
||||||
StateFetcher statefetcher.Fetcher
|
StateFetcher statefetcher.Fetcher
|
||||||
HeadFetcher blockchain.HeadFetcher
|
HeadFetcher blockchain.HeadFetcher
|
||||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||||
V1Alpha1ValidatorServer *v1alpha1validator.Server
|
V1Alpha1ValidatorServer *v1alpha1validator.Server
|
||||||
SyncChecker sync.Checker
|
SyncChecker sync.Checker
|
||||||
CanonicalHistory *stategen.CanonicalHistory
|
CanonicalHistory *stategen.CanonicalHistory
|
||||||
HeadUpdater blockchain.HeadUpdater
|
HeadUpdater blockchain.HeadUpdater
|
||||||
|
ExecutionPayloadReconstructor powchain.ExecutionPayloadReconstructor
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,12 @@ func convertToBlockContainer(blk interfaces.SignedBeaconBlock, root [32]byte, is
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctr.Block = ðpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: rBlk}
|
ctr.Block = ðpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: rBlk}
|
||||||
|
case version.BellatrixBlind:
|
||||||
|
rBlk, err := blk.PbBlindedBellatrixBlock()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctr.Block = ðpb.BeaconBlockContainer_BlindedBellatrixBlock{BlindedBellatrixBlock: rBlk}
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("block type is not recognized: %d", blk.Version())
|
return nil, errors.Errorf("block type is not recognized: %d", blk.Version())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||||
"github.com/prysmaticlabs/prysm/cmd"
|
"github.com/prysmaticlabs/prysm/cmd"
|
||||||
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
@@ -871,13 +872,21 @@ func TestServer_ListBeaconBlocks_Genesis(t *testing.T) {
|
|||||||
blk.Block.ParentRoot = parentRoot[:]
|
blk.Block.ParentRoot = parentRoot[:]
|
||||||
wrapped, err := wrapper.WrappedSignedBeaconBlock(blk)
|
wrapped, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
blinded, err := wrapped.ToBlinded()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
blindedProto, err := blinded.PbBlindedBellatrixBlock()
|
||||||
|
assert.NoError(t, err)
|
||||||
blkContainer := ðpb.BeaconBlockContainer{
|
blkContainer := ðpb.BeaconBlockContainer{
|
||||||
Block: ðpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: blk}}
|
Block: ðpb.BeaconBlockContainer_BlindedBellatrixBlock{BlindedBellatrixBlock: blindedProto}}
|
||||||
runListBlocksGenesis(t, wrapped, blkContainer)
|
runListBlocksGenesis(t, wrapped, blkContainer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func runListBlocksGenesis(t *testing.T, blk interfaces.SignedBeaconBlock, blkContainer *ethpb.BeaconBlockContainer) {
|
func runListBlocksGenesis(t *testing.T, blk interfaces.SignedBeaconBlock, blkContainer *ethpb.BeaconBlockContainer) {
|
||||||
|
resetFn := features.InitWithReset(&features.Flags{
|
||||||
|
EnableOnlyBlindedBeaconBlocks: true,
|
||||||
|
})
|
||||||
|
defer resetFn()
|
||||||
db := dbTest.SetupDB(t)
|
db := dbTest.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
|||||||
@@ -71,49 +71,50 @@ type Service struct {
|
|||||||
|
|
||||||
// Config options for the beacon node RPC server.
|
// Config options for the beacon node RPC server.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Host string
|
ExecutionPayloadReconstructor powchain.ExecutionPayloadReconstructor
|
||||||
Port string
|
Host string
|
||||||
CertFlag string
|
Port string
|
||||||
KeyFlag string
|
CertFlag string
|
||||||
BeaconMonitoringHost string
|
KeyFlag string
|
||||||
BeaconMonitoringPort int
|
BeaconMonitoringHost string
|
||||||
BeaconDB db.HeadAccessDatabase
|
BeaconMonitoringPort int
|
||||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
BeaconDB db.HeadAccessDatabase
|
||||||
HeadUpdater blockchain.HeadUpdater
|
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||||
HeadFetcher blockchain.HeadFetcher
|
HeadUpdater blockchain.HeadUpdater
|
||||||
CanonicalFetcher blockchain.CanonicalFetcher
|
HeadFetcher blockchain.HeadFetcher
|
||||||
ForkFetcher blockchain.ForkFetcher
|
CanonicalFetcher blockchain.CanonicalFetcher
|
||||||
FinalizationFetcher blockchain.FinalizationFetcher
|
ForkFetcher blockchain.ForkFetcher
|
||||||
AttestationReceiver blockchain.AttestationReceiver
|
FinalizationFetcher blockchain.FinalizationFetcher
|
||||||
BlockReceiver blockchain.BlockReceiver
|
AttestationReceiver blockchain.AttestationReceiver
|
||||||
POWChainService powchain.Chain
|
BlockReceiver blockchain.BlockReceiver
|
||||||
ChainStartFetcher powchain.ChainStartFetcher
|
POWChainService powchain.Chain
|
||||||
POWChainInfoFetcher powchain.ChainInfoFetcher
|
ChainStartFetcher powchain.ChainStartFetcher
|
||||||
GenesisTimeFetcher blockchain.TimeFetcher
|
POWChainInfoFetcher powchain.ChainInfoFetcher
|
||||||
GenesisFetcher blockchain.GenesisFetcher
|
GenesisTimeFetcher blockchain.TimeFetcher
|
||||||
EnableDebugRPCEndpoints bool
|
GenesisFetcher blockchain.GenesisFetcher
|
||||||
MockEth1Votes bool
|
EnableDebugRPCEndpoints bool
|
||||||
AttestationsPool attestations.Pool
|
MockEth1Votes bool
|
||||||
ExitPool voluntaryexits.PoolManager
|
AttestationsPool attestations.Pool
|
||||||
SlashingsPool slashings.PoolManager
|
ExitPool voluntaryexits.PoolManager
|
||||||
SlashingChecker slasherservice.SlashingChecker
|
SlashingsPool slashings.PoolManager
|
||||||
SyncCommitteeObjectPool synccommittee.Pool
|
SlashingChecker slasherservice.SlashingChecker
|
||||||
SyncService chainSync.Checker
|
SyncCommitteeObjectPool synccommittee.Pool
|
||||||
Broadcaster p2p.Broadcaster
|
SyncService chainSync.Checker
|
||||||
PeersFetcher p2p.PeersProvider
|
Broadcaster p2p.Broadcaster
|
||||||
PeerManager p2p.PeerManager
|
PeersFetcher p2p.PeersProvider
|
||||||
MetadataProvider p2p.MetadataProvider
|
PeerManager p2p.PeerManager
|
||||||
DepositFetcher depositcache.DepositFetcher
|
MetadataProvider p2p.MetadataProvider
|
||||||
PendingDepositFetcher depositcache.PendingDepositsFetcher
|
DepositFetcher depositcache.DepositFetcher
|
||||||
StateNotifier statefeed.Notifier
|
PendingDepositFetcher depositcache.PendingDepositsFetcher
|
||||||
BlockNotifier blockfeed.Notifier
|
StateNotifier statefeed.Notifier
|
||||||
OperationNotifier opfeed.Notifier
|
BlockNotifier blockfeed.Notifier
|
||||||
StateGen *stategen.State
|
OperationNotifier opfeed.Notifier
|
||||||
MaxMsgSize int
|
StateGen *stategen.State
|
||||||
ExecutionEngineCaller powchain.EngineCaller
|
MaxMsgSize int
|
||||||
ProposerIdsCache *cache.ProposerPayloadIDsCache
|
ExecutionEngineCaller powchain.EngineCaller
|
||||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
ProposerIdsCache *cache.ProposerPayloadIDsCache
|
||||||
BlockBuilder builder.BlockBuilder
|
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||||
|
BlockBuilder builder.BlockBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService instantiates a new RPC service instance that will
|
// NewService instantiates a new RPC service instance that will
|
||||||
@@ -309,11 +310,12 @@ func (s *Service) Start() {
|
|||||||
StateGenService: s.cfg.StateGen,
|
StateGenService: s.cfg.StateGen,
|
||||||
ReplayerBuilder: ch,
|
ReplayerBuilder: ch,
|
||||||
},
|
},
|
||||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||||
HeadFetcher: s.cfg.HeadFetcher,
|
HeadFetcher: s.cfg.HeadFetcher,
|
||||||
VoluntaryExitsPool: s.cfg.ExitPool,
|
VoluntaryExitsPool: s.cfg.ExitPool,
|
||||||
V1Alpha1ValidatorServer: validatorServer,
|
V1Alpha1ValidatorServer: validatorServer,
|
||||||
SyncChecker: s.cfg.SyncService,
|
SyncChecker: s.cfg.SyncService,
|
||||||
|
ExecutionPayloadReconstructor: s.cfg.ExecutionPayloadReconstructor,
|
||||||
}
|
}
|
||||||
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
||||||
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ go_library(
|
|||||||
"//beacon-chain/p2p/encoder:go_default_library",
|
"//beacon-chain/p2p/encoder:go_default_library",
|
||||||
"//beacon-chain/p2p/peers:go_default_library",
|
"//beacon-chain/p2p/peers:go_default_library",
|
||||||
"//beacon-chain/p2p/types:go_default_library",
|
"//beacon-chain/p2p/types:go_default_library",
|
||||||
|
"//beacon-chain/powchain:go_default_library",
|
||||||
"//beacon-chain/state:go_default_library",
|
"//beacon-chain/state:go_default_library",
|
||||||
"//beacon-chain/state/stategen:go_default_library",
|
"//beacon-chain/state/stategen:go_default_library",
|
||||||
"//cache/lru:go_default_library",
|
"//cache/lru:go_default_library",
|
||||||
@@ -185,12 +186,14 @@ go_test(
|
|||||||
"//beacon-chain/p2p/testing:go_default_library",
|
"//beacon-chain/p2p/testing:go_default_library",
|
||||||
"//beacon-chain/p2p/types:go_default_library",
|
"//beacon-chain/p2p/types:go_default_library",
|
||||||
"//beacon-chain/powchain:go_default_library",
|
"//beacon-chain/powchain:go_default_library",
|
||||||
|
"//beacon-chain/powchain/testing:go_default_library",
|
||||||
"//beacon-chain/state:go_default_library",
|
"//beacon-chain/state:go_default_library",
|
||||||
"//beacon-chain/state/stategen:go_default_library",
|
"//beacon-chain/state/stategen:go_default_library",
|
||||||
"//beacon-chain/state/v1:go_default_library",
|
"//beacon-chain/state/v1:go_default_library",
|
||||||
"//beacon-chain/sync/initial-sync/testing:go_default_library",
|
"//beacon-chain/sync/initial-sync/testing:go_default_library",
|
||||||
"//cache/lru:go_default_library",
|
"//cache/lru:go_default_library",
|
||||||
"//cmd/beacon-chain/flags:go_default_library",
|
"//cmd/beacon-chain/flags:go_default_library",
|
||||||
|
"//config/features:go_default_library",
|
||||||
"//config/fieldparams:go_default_library",
|
"//config/fieldparams:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
"//consensus-types/interfaces:go_default_library",
|
"//consensus-types/interfaces:go_default_library",
|
||||||
@@ -201,6 +204,7 @@ go_test(
|
|||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//encoding/ssz/equality:go_default_library",
|
"//encoding/ssz/equality:go_default_library",
|
||||||
"//network/forks:go_default_library",
|
"//network/forks:go_default_library",
|
||||||
|
"//proto/engine/v1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||||
"//proto/prysm/v1alpha1/metadata:go_default_library",
|
"//proto/prysm/v1alpha1/metadata:go_default_library",
|
||||||
@@ -210,6 +214,8 @@ go_test(
|
|||||||
"//time:go_default_library",
|
"//time:go_default_library",
|
||||||
"//time/slots:go_default_library",
|
"//time/slots:go_default_library",
|
||||||
"@com_github_d4l3k_messagediff//:go_default_library",
|
"@com_github_d4l3k_messagediff//:go_default_library",
|
||||||
|
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||||
|
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||||
"@com_github_ethereum_go_ethereum//p2p/enr:go_default_library",
|
"@com_github_ethereum_go_ethereum//p2p/enr:go_default_library",
|
||||||
"@com_github_golang_snappy//:go_default_library",
|
"@com_github_golang_snappy//:go_default_library",
|
||||||
"@com_github_kevinms_leakybucket_go//:go_default_library",
|
"@com_github_kevinms_leakybucket_go//:go_default_library",
|
||||||
|
|||||||
@@ -75,7 +75,13 @@ var (
|
|||||||
Buckets: []float64{10, 50, 100, 200, 400, 800, 1600, 3200},
|
Buckets: []float64{10, 50, 100, 200, 400, 800, 1600, 3200},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
rpcBlocksByRangeResponseLatency = promauto.NewHistogram(
|
||||||
|
prometheus.HistogramOpts{
|
||||||
|
Name: "rpc_blocks_by_range_response_latency_milliseconds",
|
||||||
|
Help: "Captures total time to respond to rpc blocks by range requests in a milliseconds distribution",
|
||||||
|
Buckets: []float64{250, 500, 1000, 1500, 2000, 3000, 4000, 10000},
|
||||||
|
},
|
||||||
|
)
|
||||||
arrivalBlockPropagationHistogram = promauto.NewHistogram(
|
arrivalBlockPropagationHistogram = promauto.NewHistogram(
|
||||||
prometheus.HistogramOpts{
|
prometheus.HistogramOpts{
|
||||||
Name: "block_arrival_latency_milliseconds",
|
Name: "block_arrival_latency_milliseconds",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -120,3 +121,10 @@ func WithSlasherBlockHeadersFeed(slasherBlockHeadersFeed *event.Feed) Option {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithExecutionPayloadReconstructor(r powchain.ExecutionPayloadReconstructor) Option {
|
||||||
|
return func(s *Service) error {
|
||||||
|
s.cfg.executionPayloadReconstructor = r
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
pb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
@@ -161,18 +162,29 @@ func (s *Service) writeBlockRangeToStream(ctx context.Context, startSlot, endSlo
|
|||||||
tracing.AnnotateError(span, err)
|
tracing.AnnotateError(span, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
start := time.Now()
|
||||||
for _, b := range blks {
|
for _, b := range blks {
|
||||||
if b == nil || b.IsNil() || b.Block().IsNil() {
|
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if chunkErr := s.chunkBlockWriter(stream, b); chunkErr != nil {
|
blockToWrite := b
|
||||||
log.WithError(chunkErr).Debug("Could not send a chunked response")
|
if blockToWrite.Block().IsBlinded() {
|
||||||
|
fullBlock, err := s.cfg.executionPayloadReconstructor.ReconstructFullBellatrixBlock(ctx, blockToWrite)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Could not get reconstruct full bellatrix block from blinded body")
|
||||||
|
s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
blockToWrite = fullBlock
|
||||||
|
}
|
||||||
|
if chunkErr := s.chunkBlockWriter(stream, blockToWrite); chunkErr != nil {
|
||||||
|
log.WithError(chunkErr).Error("Could not send a chunked response")
|
||||||
s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream)
|
s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream)
|
||||||
tracing.AnnotateError(span, chunkErr)
|
tracing.AnnotateError(span, chunkErr)
|
||||||
return chunkErr
|
return chunkErr
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
rpcBlocksByRangeResponseLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||||
// Return error in the event we have an invalid parent.
|
// Return error in the event we have an invalid parent.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ package sync
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/kevinms/leakybucket-go"
|
"github.com/kevinms/leakybucket-go"
|
||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/protocol"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
@@ -17,13 +20,16 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||||
p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||||
|
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||||
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
|
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
@@ -157,6 +163,124 @@ func TestRPCBeaconBlocksByRange_ReturnCorrectNumberBack(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRPCBeaconBlocksByRange_ReconstructsPayloads(t *testing.T) {
|
||||||
|
features.Init(&features.Flags{EnableOnlyBlindedBeaconBlocks: true})
|
||||||
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
p1.Connect(p2)
|
||||||
|
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
|
||||||
|
d := db.SetupDB(t)
|
||||||
|
|
||||||
|
req := ðpb.BeaconBlocksByRangeRequest{
|
||||||
|
StartSlot: 0,
|
||||||
|
Step: 1,
|
||||||
|
Count: 200,
|
||||||
|
}
|
||||||
|
|
||||||
|
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
|
||||||
|
stateRoot := bytesutil.PadTo([]byte("stateRoot"), fieldparams.RootLength)
|
||||||
|
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
|
||||||
|
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
|
||||||
|
tx := gethTypes.NewTransaction(
|
||||||
|
0,
|
||||||
|
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
|
||||||
|
big.NewInt(0), 0, big.NewInt(0),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
txs := []*gethTypes.Transaction{tx}
|
||||||
|
encodedBinaryTxs := make([][]byte, 1)
|
||||||
|
var err error
|
||||||
|
encodedBinaryTxs[0], err = txs[0].MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
blockHash := bytesutil.ToBytes32([]byte("foo"))
|
||||||
|
payload := &enginev1.ExecutionPayload{
|
||||||
|
ParentHash: parent,
|
||||||
|
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
||||||
|
StateRoot: stateRoot,
|
||||||
|
ReceiptsRoot: receiptsRoot,
|
||||||
|
LogsBloom: logsBloom,
|
||||||
|
PrevRandao: blockHash[:],
|
||||||
|
BlockNumber: 0,
|
||||||
|
GasLimit: 0,
|
||||||
|
GasUsed: 0,
|
||||||
|
Timestamp: 0,
|
||||||
|
ExtraData: make([]byte, 0),
|
||||||
|
BlockHash: blockHash[:],
|
||||||
|
BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength),
|
||||||
|
Transactions: encodedBinaryTxs,
|
||||||
|
}
|
||||||
|
mockEngine := &mockPOW.EngineClient{
|
||||||
|
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{
|
||||||
|
blockHash: payload,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
wrappedPayload, err := wrapper.WrappedExecutionPayload(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
header, err := wrapper.PayloadToHeader(wrappedPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
genRoot := [32]byte{}
|
||||||
|
// Populate the database with blocks that would match the request.
|
||||||
|
for i := req.StartSlot; i < req.StartSlot.Add(req.Step*req.Count); i += types.Slot(req.Step) {
|
||||||
|
blk := util.NewBlindedBeaconBlockBellatrix()
|
||||||
|
blk.Block.Slot = i
|
||||||
|
blk.Block.Body.ExecutionPayloadHeader = header
|
||||||
|
if i == 0 {
|
||||||
|
rt, err := blk.Block.HashTreeRoot()
|
||||||
|
require.NoError(t, err)
|
||||||
|
genRoot = rt
|
||||||
|
}
|
||||||
|
util.SaveBlock(t, context.Background(), d, blk)
|
||||||
|
}
|
||||||
|
require.NoError(t, d.SaveGenesisBlockRoot(context.Background(), genRoot))
|
||||||
|
|
||||||
|
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
|
||||||
|
r := &Service{
|
||||||
|
cfg: &config{
|
||||||
|
p2p: p1,
|
||||||
|
beaconDB: d,
|
||||||
|
chain: &chainMock.ChainService{},
|
||||||
|
executionPayloadReconstructor: mockEngine,
|
||||||
|
},
|
||||||
|
rateLimiter: newRateLimiter(p1),
|
||||||
|
}
|
||||||
|
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
|
||||||
|
topic := string(pcl)
|
||||||
|
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(0.000001, int64(req.Count*10), false)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
// Use a new request to test this out
|
||||||
|
newReq := ðpb.BeaconBlocksByRangeRequest{StartSlot: 0, Step: 1, Count: 1}
|
||||||
|
|
||||||
|
p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) {
|
||||||
|
defer wg.Done()
|
||||||
|
for i := newReq.StartSlot; i < newReq.StartSlot.Add(newReq.Count*newReq.Step); i += types.Slot(newReq.Step) {
|
||||||
|
expectSuccess(t, stream)
|
||||||
|
res := util.NewBeaconBlockBellatrix()
|
||||||
|
assert.NoError(t, r.cfg.p2p.Encoding().DecodeWithMaxLength(stream, res))
|
||||||
|
if res.Block.Slot.SubSlot(newReq.StartSlot).Mod(newReq.Step) != 0 {
|
||||||
|
t.Errorf("Received unexpected block slot %d", res.Block.Slot)
|
||||||
|
}
|
||||||
|
// Expect EOF
|
||||||
|
b := make([]byte, 1)
|
||||||
|
_, err := stream.Read(b)
|
||||||
|
require.ErrorContains(t, io.EOF.Error(), err)
|
||||||
|
}
|
||||||
|
require.Equal(t, uint64(1), mockEngine.NumReconstructedPayloads)
|
||||||
|
})
|
||||||
|
|
||||||
|
stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = r.beaconBlocksByRangeRPCHandler(context.Background(), newReq, stream1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if util.WaitTimeout(&wg, 1*time.Second) {
|
||||||
|
t.Fatal("Did not receive stream within 1 sec")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRPCBeaconBlocksByRange_RPCHandlerReturnsSortedBlocks(t *testing.T) {
|
func TestRPCBeaconBlocksByRange_RPCHandlerReturnsSortedBlocks(t *testing.T) {
|
||||||
p1 := p2ptest.NewTestP2P(t)
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
p2 := p2ptest.NewTestP2P(t)
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sendRecentBeaconBlocksRequest sends a recent beacon blocks request to a peer to get
|
// sendRecentBeaconBlocksRequest sends a recent beacon blocks request to a peer to get
|
||||||
@@ -68,13 +69,24 @@ func (s *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
|||||||
s.writeErrorResponseToStream(responseCodeServerError, types.ErrGeneric.Error(), stream)
|
s.writeErrorResponseToStream(responseCodeServerError, types.ErrGeneric.Error(), stream)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if blk == nil || blk.IsNil() {
|
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if blk.Block().IsBlinded() {
|
||||||
|
blk, err = s.cfg.executionPayloadReconstructor.ReconstructFullBellatrixBlock(ctx, blk)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Could not get reconstruct full bellatrix block from blinded body")
|
||||||
|
s.writeErrorResponseToStream(responseCodeServerError, types.ErrGeneric.Error(), stream)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.chunkBlockWriter(stream, blk); err != nil {
|
if err := s.chunkBlockWriter(stream, blk); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closeStream(stream, log)
|
closeStream(stream, log)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package sync
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/kevinms/leakybucket-go"
|
"github.com/kevinms/leakybucket-go"
|
||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/protocol"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
@@ -16,8 +19,13 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||||
p2pTypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
p2pTypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||||
|
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
|
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
@@ -72,6 +80,105 @@ func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks_ReconstructsPayload(t *testing.T) {
|
||||||
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
p1.Connect(p2)
|
||||||
|
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
|
||||||
|
d := db.SetupDB(t)
|
||||||
|
|
||||||
|
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
|
||||||
|
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
|
||||||
|
stateRoot := bytesutil.PadTo([]byte("stateRoot"), fieldparams.RootLength)
|
||||||
|
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
|
||||||
|
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
|
||||||
|
tx := gethTypes.NewTransaction(
|
||||||
|
0,
|
||||||
|
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
|
||||||
|
big.NewInt(0), 0, big.NewInt(0),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
txs := []*gethTypes.Transaction{tx}
|
||||||
|
encodedBinaryTxs := make([][]byte, 1)
|
||||||
|
var err error
|
||||||
|
encodedBinaryTxs[0], err = txs[0].MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
blockHash := bytesutil.ToBytes32([]byte("foo"))
|
||||||
|
payload := &enginev1.ExecutionPayload{
|
||||||
|
ParentHash: parent,
|
||||||
|
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
||||||
|
StateRoot: stateRoot,
|
||||||
|
ReceiptsRoot: receiptsRoot,
|
||||||
|
LogsBloom: logsBloom,
|
||||||
|
PrevRandao: blockHash[:],
|
||||||
|
BlockNumber: 0,
|
||||||
|
GasLimit: 0,
|
||||||
|
GasUsed: 0,
|
||||||
|
Timestamp: 0,
|
||||||
|
ExtraData: make([]byte, 0),
|
||||||
|
BlockHash: blockHash[:],
|
||||||
|
BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength),
|
||||||
|
Transactions: encodedBinaryTxs,
|
||||||
|
}
|
||||||
|
wrappedPayload, err := wrapper.WrappedExecutionPayload(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
header, err := wrapper.PayloadToHeader(wrappedPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var blkRoots p2pTypes.BeaconBlockByRootsReq
|
||||||
|
// Populate the database with blocks that would match the request.
|
||||||
|
for i := types.Slot(1); i < 11; i++ {
|
||||||
|
blk := util.NewBlindedBeaconBlockBellatrix()
|
||||||
|
blk.Block.Body.ExecutionPayloadHeader = header
|
||||||
|
blk.Block.Slot = i
|
||||||
|
root, err := blk.Block.HashTreeRoot()
|
||||||
|
require.NoError(t, err)
|
||||||
|
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, d.SaveBlock(context.Background(), wsb))
|
||||||
|
blkRoots = append(blkRoots, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
mockEngine := &mockPOW.EngineClient{
|
||||||
|
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{
|
||||||
|
blockHash: payload,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
r := &Service{cfg: &config{
|
||||||
|
p2p: p1,
|
||||||
|
beaconDB: d,
|
||||||
|
executionPayloadReconstructor: mockEngine,
|
||||||
|
}, rateLimiter: newRateLimiter(p1)}
|
||||||
|
r.cfg.chain = &mock.ChainService{ValidatorsRoot: [32]byte{}}
|
||||||
|
pcl := protocol.ID(p2p.RPCBlocksByRootTopicV1)
|
||||||
|
topic := string(pcl)
|
||||||
|
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, false)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) {
|
||||||
|
defer wg.Done()
|
||||||
|
for i := range blkRoots {
|
||||||
|
expectSuccess(t, stream)
|
||||||
|
res := util.NewBeaconBlockBellatrix()
|
||||||
|
assert.NoError(t, r.cfg.p2p.Encoding().DecodeWithMaxLength(stream, res))
|
||||||
|
if uint64(res.Block.Slot) != uint64(i+1) {
|
||||||
|
t.Errorf("Received unexpected block slot %d but wanted %d", res.Block.Slot, i+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.Equal(t, uint64(10), mockEngine.NumReconstructedPayloads)
|
||||||
|
})
|
||||||
|
|
||||||
|
stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = r.beaconBlocksRootRPCHandler(context.Background(), &blkRoots, stream1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
if util.WaitTimeout(&wg, 1*time.Second) {
|
||||||
|
t.Fatal("Did not receive stream within 1 sec")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
||||||
p1 := p2ptest.NewTestP2P(t)
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
p2 := p2ptest.NewTestP2P(t)
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ func WriteBlockChunk(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var obtainedCtx []byte
|
var obtainedCtx []byte
|
||||||
|
|
||||||
switch blk.Version() {
|
switch blk.Version() {
|
||||||
case version.Phase0:
|
case version.Phase0:
|
||||||
valRoot := chain.GenesisValidatorsRoot()
|
valRoot := chain.GenesisValidatorsRoot()
|
||||||
@@ -45,7 +46,7 @@ func WriteBlockChunk(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
obtainedCtx = digest[:]
|
obtainedCtx = digest[:]
|
||||||
case version.Bellatrix:
|
case version.Bellatrix, version.BellatrixBlind:
|
||||||
valRoot := chain.GenesisValidatorsRoot()
|
valRoot := chain.GenesisValidatorsRoot()
|
||||||
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, valRoot[:])
|
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, valRoot[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||||
lruwrpr "github.com/prysmaticlabs/prysm/cache/lru"
|
lruwrpr "github.com/prysmaticlabs/prysm/cache/lru"
|
||||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||||
@@ -68,21 +69,22 @@ type validationFn func(ctx context.Context) (pubsub.ValidationResult, error)
|
|||||||
|
|
||||||
// config to hold dependencies for the sync service.
|
// config to hold dependencies for the sync service.
|
||||||
type config struct {
|
type config struct {
|
||||||
attestationNotifier operation.Notifier
|
attestationNotifier operation.Notifier
|
||||||
p2p p2p.P2P
|
p2p p2p.P2P
|
||||||
beaconDB db.NoHeadAccessDatabase
|
beaconDB db.NoHeadAccessDatabase
|
||||||
attPool attestations.Pool
|
attPool attestations.Pool
|
||||||
exitPool voluntaryexits.PoolManager
|
exitPool voluntaryexits.PoolManager
|
||||||
slashingPool slashings.PoolManager
|
slashingPool slashings.PoolManager
|
||||||
syncCommsPool synccommittee.Pool
|
syncCommsPool synccommittee.Pool
|
||||||
chain blockchainService
|
chain blockchainService
|
||||||
initialSync Checker
|
initialSync Checker
|
||||||
stateNotifier statefeed.Notifier
|
stateNotifier statefeed.Notifier
|
||||||
blockNotifier blockfeed.Notifier
|
blockNotifier blockfeed.Notifier
|
||||||
operationNotifier operation.Notifier
|
operationNotifier operation.Notifier
|
||||||
stateGen *stategen.State
|
executionPayloadReconstructor powchain.ExecutionPayloadReconstructor
|
||||||
slasherAttestationsFeed *event.Feed
|
stateGen *stategen.State
|
||||||
slasherBlockHeadersFeed *event.Feed
|
slasherAttestationsFeed *event.Feed
|
||||||
|
slasherBlockHeadersFeed *event.Feed
|
||||||
}
|
}
|
||||||
|
|
||||||
// This defines the interface for interacting with block chain service
|
// This defines the interface for interacting with block chain service
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ type Flags struct {
|
|||||||
EnableVectorizedHTR bool // EnableVectorizedHTR specifies whether the beacon state will use the optimized sha256 routines.
|
EnableVectorizedHTR bool // EnableVectorizedHTR specifies whether the beacon state will use the optimized sha256 routines.
|
||||||
EnableForkChoiceDoublyLinkedTree bool // EnableForkChoiceDoublyLinkedTree specifies whether fork choice store will use a doubly linked tree.
|
EnableForkChoiceDoublyLinkedTree bool // EnableForkChoiceDoublyLinkedTree specifies whether fork choice store will use a doubly linked tree.
|
||||||
EnableBatchGossipAggregation bool // EnableBatchGossipAggregation specifies whether to further aggregate our gossip batches before verifying them.
|
EnableBatchGossipAggregation bool // EnableBatchGossipAggregation specifies whether to further aggregate our gossip batches before verifying them.
|
||||||
|
EnableOnlyBlindedBeaconBlocks bool // EnableOnlyBlindedBeaconBlocks enables only storing blinded beacon blocks in the DB post-Bellatrix fork.
|
||||||
|
|
||||||
// KeystoreImportDebounceInterval specifies the time duration the validator waits to reload new keys if they have
|
// KeystoreImportDebounceInterval specifies the time duration the validator waits to reload new keys if they have
|
||||||
// changed on disk. This feature is for advanced use cases only.
|
// changed on disk. This feature is for advanced use cases only.
|
||||||
@@ -228,6 +229,10 @@ func ConfigureBeaconChain(ctx *cli.Context) error {
|
|||||||
logEnabled(enableGossipBatchAggregation)
|
logEnabled(enableGossipBatchAggregation)
|
||||||
cfg.EnableBatchGossipAggregation = true
|
cfg.EnableBatchGossipAggregation = true
|
||||||
}
|
}
|
||||||
|
if ctx.Bool(EnableOnlyBlindedBeaconBlocks.Name) {
|
||||||
|
logEnabled(EnableOnlyBlindedBeaconBlocks)
|
||||||
|
cfg.EnableOnlyBlindedBeaconBlocks = true
|
||||||
|
}
|
||||||
Init(cfg)
|
Init(cfg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,12 +105,10 @@ var (
|
|||||||
Name: "disable-native-state",
|
Name: "disable-native-state",
|
||||||
Usage: "Disables representing the beacon state as a pure Go struct.",
|
Usage: "Disables representing the beacon state as a pure Go struct.",
|
||||||
}
|
}
|
||||||
|
|
||||||
enablePullTips = &cli.BoolFlag{
|
enablePullTips = &cli.BoolFlag{
|
||||||
Name: "experimental-disable-boundary-checks",
|
Name: "experimental-disable-boundary-checks",
|
||||||
Usage: "Experimental disable of boundary checks, useful for debugging, may cause bad votes.",
|
Usage: "Experimental disable of boundary checks, useful for debugging, may cause bad votes.",
|
||||||
}
|
}
|
||||||
|
|
||||||
enableVecHTR = &cli.BoolFlag{
|
enableVecHTR = &cli.BoolFlag{
|
||||||
Name: "enable-vectorized-htr",
|
Name: "enable-vectorized-htr",
|
||||||
Usage: "Enables new go sha256 library which utilizes optimized routines for merkle trees",
|
Usage: "Enables new go sha256 library which utilizes optimized routines for merkle trees",
|
||||||
@@ -123,6 +121,10 @@ var (
|
|||||||
Name: "enable-gossip-batch-aggregation",
|
Name: "enable-gossip-batch-aggregation",
|
||||||
Usage: "Enables new methods to further aggregate our gossip batches before verifying them.",
|
Usage: "Enables new methods to further aggregate our gossip batches before verifying them.",
|
||||||
}
|
}
|
||||||
|
EnableOnlyBlindedBeaconBlocks = &cli.BoolFlag{
|
||||||
|
Name: "enable-only-blinded-beacon-blocks",
|
||||||
|
Usage: "Enables storing only blinded beacon blocks in the database without full execution layer transactions",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// devModeFlags holds list of flags that are set when development mode is on.
|
// devModeFlags holds list of flags that are set when development mode is on.
|
||||||
@@ -173,6 +175,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{
|
|||||||
enableVecHTR,
|
enableVecHTR,
|
||||||
enableForkChoiceDoublyLinkedTree,
|
enableForkChoiceDoublyLinkedTree,
|
||||||
enableGossipBatchAggregation,
|
enableGossipBatchAggregation,
|
||||||
|
EnableOnlyBlindedBeaconBlocks,
|
||||||
}...)
|
}...)
|
||||||
|
|
||||||
// E2EBeaconChainFlags contains a list of the beacon chain feature flags to be tested in E2E.
|
// E2EBeaconChainFlags contains a list of the beacon chain feature flags to be tested in E2E.
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type SignedBeaconBlock interface {
|
|||||||
PbGenericBlock() (*ethpb.GenericSignedBeaconBlock, error)
|
PbGenericBlock() (*ethpb.GenericSignedBeaconBlock, error)
|
||||||
PbPhase0Block() (*ethpb.SignedBeaconBlock, error)
|
PbPhase0Block() (*ethpb.SignedBeaconBlock, error)
|
||||||
PbAltairBlock() (*ethpb.SignedBeaconBlockAltair, error)
|
PbAltairBlock() (*ethpb.SignedBeaconBlockAltair, error)
|
||||||
|
ToBlinded() (SignedBeaconBlock, error)
|
||||||
PbBellatrixBlock() (*ethpb.SignedBeaconBlockBellatrix, error)
|
PbBellatrixBlock() (*ethpb.SignedBeaconBlockBellatrix, error)
|
||||||
PbBlindedBellatrixBlock() (*ethpb.SignedBlindedBeaconBlockBellatrix, error)
|
PbBlindedBellatrixBlock() (*ethpb.SignedBlindedBeaconBlockBellatrix, error)
|
||||||
ssz.Marshaler
|
ssz.Marshaler
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ func (SignedBeaconBlock) Version() int {
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (SignedBeaconBlock) ToBlinded() (interfaces.SignedBeaconBlock, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
func (SignedBeaconBlock) Header() (*eth.SignedBeaconBlockHeader, error) {
|
func (SignedBeaconBlock) Header() (*eth.SignedBeaconBlockHeader, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ var (
|
|||||||
// This allows us to create a generic beacon block interface that is implemented by different
|
// This allows us to create a generic beacon block interface that is implemented by different
|
||||||
// fork versions of beacon blocks.
|
// fork versions of beacon blocks.
|
||||||
ErrUnsupportedField = errors.New("unsupported field for block type")
|
ErrUnsupportedField = errors.New("unsupported field for block type")
|
||||||
|
// ErrUnsupportedVersion for beacon block methods.
|
||||||
|
ErrUnsupportedVersion = errors.New("unsupported beacon block version")
|
||||||
// ErrUnsupportedSignedBeaconBlock is returned when the struct type is not a supported signed
|
// ErrUnsupportedSignedBeaconBlock is returned when the struct type is not a supported signed
|
||||||
// beacon block type.
|
// beacon block type.
|
||||||
ErrUnsupportedSignedBeaconBlock = errors.New("unsupported signed beacon block")
|
ErrUnsupportedSignedBeaconBlock = errors.New("unsupported signed beacon block")
|
||||||
@@ -208,55 +210,6 @@ func BuildSignedBeaconBlockFromExecutionPayload(
|
|||||||
return wrappedBellatrixSignedBeaconBlock(bellatrixFullBlock)
|
return wrappedBellatrixSignedBeaconBlock(bellatrixFullBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WrapSignedBlindedBeaconBlock converts a signed beacon block into a blinded format.
|
|
||||||
func WrapSignedBlindedBeaconBlock(blk interfaces.SignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
|
|
||||||
if err := BeaconBlockIsNil(blk); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if blk.Block().IsBlinded() {
|
|
||||||
return blk, nil
|
|
||||||
}
|
|
||||||
b := blk.Block()
|
|
||||||
payload, err := b.Body().Execution()
|
|
||||||
switch {
|
|
||||||
case errors.Is(err, ErrUnsupportedField):
|
|
||||||
return nil, ErrUnsupportedSignedBeaconBlock
|
|
||||||
case err != nil:
|
|
||||||
return nil, errors.Wrap(err, "could not get execution payload")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
syncAgg, err := b.Body().SyncAggregate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
header, err := PayloadToHeader(payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blindedBlock := ð.SignedBlindedBeaconBlockBellatrix{
|
|
||||||
Block: ð.BlindedBeaconBlockBellatrix{
|
|
||||||
Slot: b.Slot(),
|
|
||||||
ProposerIndex: b.ProposerIndex(),
|
|
||||||
ParentRoot: b.ParentRoot(),
|
|
||||||
StateRoot: b.StateRoot(),
|
|
||||||
Body: ð.BlindedBeaconBlockBodyBellatrix{
|
|
||||||
RandaoReveal: b.Body().RandaoReveal(),
|
|
||||||
Eth1Data: b.Body().Eth1Data(),
|
|
||||||
Graffiti: b.Body().Graffiti(),
|
|
||||||
ProposerSlashings: b.Body().ProposerSlashings(),
|
|
||||||
AttesterSlashings: b.Body().AttesterSlashings(),
|
|
||||||
Attestations: b.Body().Attestations(),
|
|
||||||
Deposits: b.Body().Deposits(),
|
|
||||||
VoluntaryExits: b.Body().VoluntaryExits(),
|
|
||||||
SyncAggregate: syncAgg,
|
|
||||||
ExecutionPayloadHeader: header,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Signature: blk.Signature(),
|
|
||||||
}
|
|
||||||
return wrappedBellatrixSignedBlindedBeaconBlock(blindedBlock)
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnwrapGenericSignedBeaconBlock(gb *eth.GenericSignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
|
func UnwrapGenericSignedBeaconBlock(gb *eth.GenericSignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
|
||||||
if gb == nil {
|
if gb == nil {
|
||||||
return nil, ErrNilObjectWrapped
|
return nil, ErrNilObjectWrapped
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ func (altairSignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeac
|
|||||||
return nil, ErrUnsupportedBlindedBellatrixBlock
|
return nil, ErrUnsupportedBlindedBellatrixBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (altairSignedBeaconBlock) ToBlinded() (interfaces.SignedBeaconBlock, error) {
|
||||||
|
return nil, ErrUnsupportedVersion
|
||||||
|
}
|
||||||
|
|
||||||
// Version of the underlying protobuf object.
|
// Version of the underlying protobuf object.
|
||||||
func (altairSignedBeaconBlock) Version() int {
|
func (altairSignedBeaconBlock) Version() int {
|
||||||
return version.Altair
|
return version.Altair
|
||||||
|
|||||||
@@ -107,6 +107,44 @@ func (bellatrixSignedBeaconBlock) PbAltairBlock() (*eth.SignedBeaconBlockAltair,
|
|||||||
return nil, ErrUnsupportedAltairBlock
|
return nil, ErrUnsupportedAltairBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w bellatrixSignedBeaconBlock) ToBlinded() (interfaces.SignedBeaconBlock, error) {
|
||||||
|
if w.Block().IsNil() {
|
||||||
|
return nil, errors.New("cannot convert nil block to blinded format")
|
||||||
|
}
|
||||||
|
payload := w.b.Block.Body.ExecutionPayload
|
||||||
|
wrappedPayload, err := WrappedExecutionPayload(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
header, err := PayloadToHeader(wrappedPayload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return signedBlindedBeaconBlockBellatrix{
|
||||||
|
b: ð.SignedBlindedBeaconBlockBellatrix{
|
||||||
|
Block: ð.BlindedBeaconBlockBellatrix{
|
||||||
|
Slot: w.b.Block.Slot,
|
||||||
|
ProposerIndex: w.b.Block.ProposerIndex,
|
||||||
|
ParentRoot: w.b.Block.ParentRoot,
|
||||||
|
StateRoot: w.b.Block.StateRoot,
|
||||||
|
Body: ð.BlindedBeaconBlockBodyBellatrix{
|
||||||
|
RandaoReveal: w.b.Block.Body.RandaoReveal,
|
||||||
|
Eth1Data: w.b.Block.Body.Eth1Data,
|
||||||
|
Graffiti: w.b.Block.Body.Graffiti,
|
||||||
|
ProposerSlashings: w.b.Block.Body.ProposerSlashings,
|
||||||
|
AttesterSlashings: w.b.Block.Body.AttesterSlashings,
|
||||||
|
Attestations: w.b.Block.Body.Attestations,
|
||||||
|
Deposits: w.b.Block.Body.Deposits,
|
||||||
|
VoluntaryExits: w.b.Block.Body.VoluntaryExits,
|
||||||
|
SyncAggregate: w.b.Block.Body.SyncAggregate,
|
||||||
|
ExecutionPayloadHeader: header,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Signature: w.b.Signature,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Version of the underlying protobuf object.
|
// Version of the underlying protobuf object.
|
||||||
func (bellatrixSignedBeaconBlock) Version() int {
|
func (bellatrixSignedBeaconBlock) Version() int {
|
||||||
return version.Bellatrix
|
return version.Bellatrix
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ func (Phase0SignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeac
|
|||||||
return nil, ErrUnsupportedBlindedBellatrixBlock
|
return nil, ErrUnsupportedBlindedBellatrixBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Phase0SignedBeaconBlock) ToBlinded() (interfaces.SignedBeaconBlock, error) {
|
||||||
|
return nil, ErrUnsupportedVersion
|
||||||
|
}
|
||||||
|
|
||||||
// Version of the underlying protobuf object.
|
// Version of the underlying protobuf object.
|
||||||
func (Phase0SignedBeaconBlock) Version() int {
|
func (Phase0SignedBeaconBlock) Version() int {
|
||||||
return version.Phase0
|
return version.Phase0
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ func TestWrapSignedBlindedBeaconBlock(t *testing.T) {
|
|||||||
|
|
||||||
blk, err := wrapper.WrappedSignedBeaconBlock(bellatrixBlk)
|
blk, err := wrapper.WrappedSignedBeaconBlock(bellatrixBlk)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
builtBlock, err := wrapper.WrapSignedBlindedBeaconBlock(blk)
|
builtBlock, err := blk.ToBlinded()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
got, err := builtBlock.Block().Body().Execution()
|
got, err := builtBlock.Block().Body().Execution()
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ func (signedBlindedBeaconBlockBellatrix) PbAltairBlock() (*eth.SignedBeaconBlock
|
|||||||
return nil, ErrUnsupportedAltairBlock
|
return nil, ErrUnsupportedAltairBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (signedBlindedBeaconBlockBellatrix) ToBlinded() (interfaces.SignedBeaconBlock, error) {
|
||||||
|
return nil, ErrUnsupportedVersion
|
||||||
|
}
|
||||||
|
|
||||||
// Version of the underlying protobuf object.
|
// Version of the underlying protobuf object.
|
||||||
func (signedBlindedBeaconBlockBellatrix) Version() int {
|
func (signedBlindedBeaconBlockBellatrix) Version() int {
|
||||||
return version.BellatrixBlind
|
return version.BellatrixBlind
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ func (m *engineMock) NewPayload(context.Context, interfaces.ExecutionData) ([]by
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *engineMock) LatestExecutionBlock() (*pb.ExecutionBlock, error) {
|
func (m *engineMock) LatestExecutionBlock(context.Context) (*pb.ExecutionBlock, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ func (m *engineMock) ExchangeTransitionConfiguration(context.Context, *pb.Transi
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *engineMock) ExecutionBlockByHash(_ context.Context, hash common.Hash) (*pb.ExecutionBlock, error) {
|
func (m *engineMock) ExecutionBlockByHash(_ context.Context, hash common.Hash, _ bool) (*pb.ExecutionBlock, error) {
|
||||||
b, ok := m.powBlocks[bytesutil.ToBytes32(hash.Bytes())]
|
b, ok := m.powBlocks[bytesutil.ToBytes32(hash.Bytes())]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user