mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Compare commits
145 Commits
d929e1dcaa
...
capella-po
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4903a809f2 | ||
|
|
e1a2267f86 | ||
|
|
3c9e4ee7f7 | ||
|
|
9ba32c9acd | ||
|
|
d23008452e | ||
|
|
f397cba1e0 | ||
|
|
aa2bbb676f | ||
|
|
1f87322ddf | ||
|
|
837fac628a | ||
|
|
7d3e627d2d | ||
|
|
016a027c48 | ||
|
|
3040f3ae4d | ||
|
|
c8f1d51280 | ||
|
|
1583e93b48 | ||
|
|
849457df81 | ||
|
|
903cab75ee | ||
|
|
ee108d4aff | ||
|
|
49bcc58762 | ||
|
|
a08baf4a14 | ||
|
|
8c56dfdd46 | ||
|
|
dcdd9af9db | ||
|
|
a464cf5c60 | ||
|
|
5cb5ce7e14 | ||
|
|
6e26a6f128 | ||
|
|
b512b92a8a | ||
|
|
b0601580ef | ||
|
|
c1f29ea651 | ||
|
|
910822400f | ||
|
|
881d1d435a | ||
|
|
d1aae0c941 | ||
|
|
57bdb907cc | ||
|
|
15d683c78f | ||
|
|
bf6c8ced7d | ||
|
|
78fb685027 | ||
|
|
c0297ca0c2 | ||
|
|
d51fb3a648 | ||
|
|
98c0b23350 | ||
|
|
3ab486e140 | ||
|
|
039a0fffba | ||
|
|
90ec640e7a | ||
|
|
10acd31d25 | ||
|
|
f52dbe3c8f | ||
|
|
df1e8b33d8 | ||
|
|
cdb4ee42cc | ||
|
|
d29baec77e | ||
|
|
166c284ca4 | ||
|
|
2654e3f080 | ||
|
|
0adc54b7ff | ||
|
|
1cbd7e9888 | ||
|
|
ed65688252 | ||
|
|
0a9e1658dd | ||
|
|
31d4a4cd11 | ||
|
|
fbc4e73d31 | ||
|
|
c1d4eaa79d | ||
|
|
760af6428e | ||
|
|
4bae07fdbb | ||
|
|
dfa0ccf626 | ||
|
|
1a51fdbd58 | ||
|
|
368a99ec8d | ||
|
|
1c7e734918 | ||
|
|
42808a0c29 | ||
|
|
11cbe8fcb9 | ||
|
|
764d1325bf | ||
|
|
0cf30e9022 | ||
|
|
227b20f368 | ||
|
|
d7d70bc25b | ||
|
|
82f6ddb693 | ||
|
|
9e4e82d2c5 | ||
|
|
9838369fe9 | ||
|
|
6085ad1bfa | ||
|
|
d3851b27df | ||
|
|
d6100dfdcb | ||
|
|
c2144dac86 | ||
|
|
a47ff569a8 | ||
|
|
f8be022ef2 | ||
|
|
4f39e6b685 | ||
|
|
c67b000633 | ||
|
|
02f7443586 | ||
|
|
6275e7df4e | ||
|
|
1b6b52fda1 | ||
|
|
5fa1fd84b9 | ||
|
|
bd0c9f9e8d | ||
|
|
2532bb370c | ||
|
|
12efc6c2c1 | ||
|
|
a6cc9ac9c5 | ||
|
|
031f5845a2 | ||
|
|
b88559726c | ||
|
|
938fca1933 | ||
|
|
604688a00e | ||
|
|
62f6b07cba | ||
|
|
f956f1ed6e | ||
|
|
16b0820193 | ||
|
|
4b02267e96 | ||
|
|
746584c453 | ||
|
|
b56daaaca2 | ||
|
|
931e5e10c3 | ||
|
|
c172f838b1 | ||
|
|
c07ae29cd9 | ||
|
|
214c9bfd8b | ||
|
|
716140d64d | ||
|
|
088cb4ef59 | ||
|
|
d1472fc351 | ||
|
|
5c8c0c31d8 | ||
|
|
7f3c00c7a2 | ||
|
|
c180dab791 | ||
|
|
f24acc21c7 | ||
|
|
40b637849d | ||
|
|
e7db1685df | ||
|
|
eccbfd1011 | ||
|
|
90211f6769 | ||
|
|
edc32ac18e | ||
|
|
fe68e020e3 | ||
|
|
81e1e3544d | ||
|
|
09372d5c35 | ||
|
|
078a89e4ca | ||
|
|
dbc6ae26a6 | ||
|
|
b6f429867a | ||
|
|
09f50660ce | ||
|
|
189825b495 | ||
|
|
764b7ff610 | ||
|
|
d499db7f0e | ||
|
|
ed2d1c7bf9 | ||
|
|
14b73cbd47 | ||
|
|
3124785a08 | ||
|
|
60e6306107 | ||
|
|
42ccb7830a | ||
|
|
0bb03b9292 | ||
|
|
ed6fbf1480 | ||
|
|
477cec6021 | ||
|
|
924500d111 | ||
|
|
0677504ef1 | ||
|
|
ca2a7c4d9c | ||
|
|
28606629ad | ||
|
|
c817279464 | ||
|
|
009d6ed8ed | ||
|
|
5cec1282a9 | ||
|
|
340170fd29 | ||
|
|
7ed0cc139a | ||
|
|
2c822213eb | ||
|
|
c08bb39ffe | ||
|
|
5083d8ab34 | ||
|
|
7552a5dd07 | ||
|
|
c93d68f853 | ||
|
|
3e8aa4023d | ||
|
|
b443875e66 |
@@ -64,6 +64,7 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/payload-attribute:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
@@ -15,9 +16,11 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -38,6 +41,7 @@ type notifyForkchoiceUpdateArg struct {
|
||||
func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkchoiceUpdateArg) (*enginev1.PayloadIDBytes, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.notifyForkchoiceUpdate")
|
||||
defer span.End()
|
||||
log.Infof("notifyForkchoiceUpdate, fork version=%#x, headRoot=%#x, headState.latest_block_header=%#x", arg.headState.Fork().CurrentVersion, arg.headRoot, arg.headState.LatestBlockHeader().BodyRoot)
|
||||
|
||||
headBlk := arg.headBlock
|
||||
if headBlk == nil || headBlk.IsNil() || headBlk.Body().IsNil() {
|
||||
@@ -50,7 +54,25 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
log.WithError(err).Error("Could not determine if head block is execution block")
|
||||
return nil, nil
|
||||
}
|
||||
var eth1BlockHash []byte
|
||||
if !isExecutionBlk {
|
||||
br, err := headBlk.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: this is a hack
|
||||
// try to grab the payload header from the state in case the block doesn't have it but the state does
|
||||
sp, err := arg.headState.LatestExecutionPayloadHeader()
|
||||
if err != nil {
|
||||
log.WithError(err).Infof("notifyForkchoiceUpdate, skipping non-execution block with root=%#x", br)
|
||||
return nil, nil
|
||||
}
|
||||
eth1BlockHash = sp.BlockHash()
|
||||
if len(sp.BlockHash()) != 32 || bytes.Equal(eth1BlockHash, params.BeaconConfig().ZeroHash[:]) {
|
||||
log.Infof("notifyForkchoiceUpdate, skipping non-execution block with root=%#x and empty payload header block hash", br)
|
||||
return nil, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
headPayload, err := headBlk.Body().Execution()
|
||||
@@ -58,10 +80,11 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
log.WithError(err).Error("Could not get execution payload for head block")
|
||||
return nil, nil
|
||||
}
|
||||
eth1BlockHash = headPayload.BlockHash()
|
||||
finalizedHash := s.ForkChoicer().FinalizedPayloadBlockHash()
|
||||
justifiedHash := s.ForkChoicer().JustifiedPayloadBlockHash()
|
||||
fcs := &enginev1.ForkchoiceState{
|
||||
HeadBlockHash: headPayload.BlockHash(),
|
||||
HeadBlockHash: eth1BlockHash,
|
||||
SafeBlockHash: justifiedHash[:],
|
||||
FinalizedBlockHash: finalizedHash[:],
|
||||
}
|
||||
@@ -71,7 +94,6 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get head payload attribute")
|
||||
}
|
||||
|
||||
payloadID, lastValidHash, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, attr)
|
||||
if err != nil {
|
||||
switch err {
|
||||
@@ -79,7 +101,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
forkchoiceUpdatedOptimisticNodeCount.Inc()
|
||||
log.WithFields(logrus.Fields{
|
||||
"headSlot": headBlk.Slot(),
|
||||
"headPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(headPayload.BlockHash())),
|
||||
"headPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(eth1BlockHash)),
|
||||
"finalizedPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash[:])),
|
||||
}).Info("Called fork choice updated with optimistic block")
|
||||
return payloadID, nil
|
||||
@@ -144,18 +166,21 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
log.WithField("payloadID", fmt.Sprintf("%#x", payloadID)).WithField("lastValidHash", fmt.Sprintf("%#x", lastValidHash)).Infof("notifyForkchoiceUpdate, no error from ee call")
|
||||
forkchoiceUpdatedValidNodeCount.Inc()
|
||||
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, arg.headRoot); err != nil {
|
||||
log.WithError(err).Error("Could not set head root to valid")
|
||||
log.WithField("headRoot", fmt.Sprintf("%#x", arg.headRoot)).WithField("payloadID", fmt.Sprintf("%#x", payloadID)).WithField("lastValidHash", fmt.Sprintf("%#x", lastValidHash)).WithError(err).Error("Could not set head root to valid")
|
||||
return nil, nil
|
||||
}
|
||||
if hasAttr && payloadID != nil { // If the forkchoice update call has an attribute, update the proposer payload ID cache.
|
||||
// If the forkchoice update call has an attribute, update the proposer payload ID cache.
|
||||
if hasAttr && payloadID != nil {
|
||||
var pId [8]byte
|
||||
copy(pId[:], payloadID[:])
|
||||
s.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nextSlot, proposerId, pId, arg.headRoot)
|
||||
log.Infof("notifyForkchoiceUpdate, SetProposerAndPayloadIDs(nextSlot=%d, proposerId=%d, pId=%#x, arg.headRoot=%#x)", nextSlot, proposerId, pId, arg.headRoot)
|
||||
} else if hasAttr && payloadID == nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"blockHash": fmt.Sprintf("%#x", headPayload.BlockHash()),
|
||||
"blockHash": fmt.Sprintf("%#x", eth1BlockHash),
|
||||
"slot": headBlk.Slot(),
|
||||
}).Error("Received nil payload ID on VALID engine response")
|
||||
}
|
||||
@@ -250,22 +275,24 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
|
||||
|
||||
// getPayloadAttributes returns the payload attributes for the given state and slot.
|
||||
// The attribute is required to initiate a payload build process in the context of an `engine_forkchoiceUpdated` call.
|
||||
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot types.Slot) (bool, *enginev1.PayloadAttributes, types.ValidatorIndex, error) {
|
||||
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot types.Slot) (bool, payloadattribute.Attributer, types.ValidatorIndex, error) {
|
||||
emptyAttri := payloadattribute.EmptyWithVersion(st.Version())
|
||||
// Root is `[32]byte{}` since we are retrieving proposer ID of a given slot. During insertion at assignment the root was not known.
|
||||
proposerID, _, ok := s.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, [32]byte{} /* root */)
|
||||
if !ok { // There's no need to build attribute if there is no proposer for slot.
|
||||
return false, nil, 0, nil
|
||||
return false, emptyAttri, 0, nil
|
||||
}
|
||||
log.Infof("getPayloadAttribute, GetProposerPayloadIDs(nextSlot=%d, arg.headRoot=%#x,idx=%v)", slot, [32]byte{}, proposerID)
|
||||
|
||||
// Get previous randao.
|
||||
st = st.Copy()
|
||||
st, err := transition.ProcessSlotsIfPossible(ctx, st, slot)
|
||||
if err != nil {
|
||||
return false, nil, 0, err
|
||||
return false, emptyAttri, 0, err
|
||||
}
|
||||
prevRando, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
|
||||
if err != nil {
|
||||
return false, nil, 0, nil
|
||||
return false, emptyAttri, 0, err
|
||||
}
|
||||
|
||||
// Get fee recipient.
|
||||
@@ -283,7 +310,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
||||
"Please refer to our documentation for instructions")
|
||||
}
|
||||
case err != nil:
|
||||
return false, nil, 0, errors.Wrap(err, "could not get fee recipient in db")
|
||||
return false, emptyAttri, 0, errors.Wrap(err, "could not get fee recipient in db")
|
||||
default:
|
||||
feeRecipient = recipient
|
||||
}
|
||||
@@ -291,13 +318,38 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
||||
// Get timestamp.
|
||||
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
|
||||
if err != nil {
|
||||
return false, nil, 0, err
|
||||
return false, emptyAttri, 0, err
|
||||
}
|
||||
attr := &enginev1.PayloadAttributes{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
PrevRandao: prevRando,
|
||||
SuggestedFeeRecipient: feeRecipient.Bytes(),
|
||||
|
||||
var attr payloadattribute.Attributer
|
||||
switch st.Version() {
|
||||
case version.Capella:
|
||||
withdrawals, err := st.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
return false, emptyAttri, 0, errors.Wrap(err, "could not get expected withdrawals")
|
||||
}
|
||||
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
PrevRandao: prevRando,
|
||||
SuggestedFeeRecipient: feeRecipient.Bytes(),
|
||||
Withdrawals: withdrawals,
|
||||
})
|
||||
if err != nil {
|
||||
return false, emptyAttri, 0, err
|
||||
}
|
||||
case version.Bellatrix:
|
||||
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
PrevRandao: prevRando,
|
||||
SuggestedFeeRecipient: feeRecipient.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
return false, emptyAttri, 0, err
|
||||
}
|
||||
default:
|
||||
return false, emptyAttri, 0, errors.New("unknown state version")
|
||||
}
|
||||
|
||||
return true, attr, proposerID, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -698,14 +698,14 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := &mockExecution.EngineClient{ErrNewPayload: tt.newPayloadErr, BlockByHashMap: map[[32]byte]*v1.ExecutionBlock{}}
|
||||
e.BlockByHashMap[[32]byte{'a'}] = &v1.ExecutionBlock{
|
||||
e := &mockExecution.EngineClient{ErrNewPayload: tt.newPayloadErr, BlockByHashMap: map[[32]byte]*v1.ExecutionBlockBellatrix{}}
|
||||
e.BlockByHashMap[[32]byte{'a'}] = &v1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
},
|
||||
TotalDifficulty: "0x2",
|
||||
}
|
||||
e.BlockByHashMap[[32]byte{'b'}] = &v1.ExecutionBlock{
|
||||
e.BlockByHashMap[[32]byte{'b'}] = &v1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("3")),
|
||||
},
|
||||
@@ -759,14 +759,14 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
e := &mockExecution.EngineClient{BlockByHashMap: map[[32]byte]*v1.ExecutionBlock{}}
|
||||
e.BlockByHashMap[[32]byte{'a'}] = &v1.ExecutionBlock{
|
||||
e := &mockExecution.EngineClient{BlockByHashMap: map[[32]byte]*v1.ExecutionBlockBellatrix{}}
|
||||
e.BlockByHashMap[[32]byte{'a'}] = &v1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
},
|
||||
TotalDifficulty: "0x2",
|
||||
}
|
||||
e.BlockByHashMap[[32]byte{'b'}] = &v1.ExecutionBlock{
|
||||
e.BlockByHashMap[[32]byte{'b'}] = &v1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("3")),
|
||||
},
|
||||
@@ -807,7 +807,7 @@ func Test_GetPayloadAttribute(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, hasPayload)
|
||||
require.Equal(t, suggestedVid, vId)
|
||||
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient).String())
|
||||
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
||||
require.LogsContain(t, hook, "Fee recipient is currently using the burn address")
|
||||
|
||||
// Cache hit, advance state, has fee recipient
|
||||
@@ -818,7 +818,7 @@ func Test_GetPayloadAttribute(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, hasPayload)
|
||||
require.Equal(t, suggestedVid, vId)
|
||||
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient))
|
||||
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
|
||||
}
|
||||
|
||||
func Test_UpdateLastValidatedCheckpoint(t *testing.T) {
|
||||
|
||||
@@ -207,7 +207,7 @@ func (s *Service) setHead(root [32]byte, block interfaces.SignedBeaconBlock, sta
|
||||
block: bCp,
|
||||
state: state.Copy(),
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// This sets head view object which is used to track the head slot, root, block and state. The method
|
||||
|
||||
@@ -87,6 +87,7 @@ func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, justif
|
||||
"version": version.String(block.Version()),
|
||||
"sinceSlotStartTime": prysmTime.Now().Sub(startTime),
|
||||
"chainServiceProcessedTime": prysmTime.Now().Sub(receivedTime),
|
||||
"deposits": fmt.Sprintf("%d/%d", len(block.Body().Deposits()), block.Body().Eth1Data().DepositCount),
|
||||
}).Debug("Synced new block")
|
||||
} else {
|
||||
log.WithFields(logrus.Fields{
|
||||
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -85,14 +87,19 @@ func (s *Service) validateMergeBlock(ctx context.Context, b interfaces.SignedBea
|
||||
|
||||
// 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) {
|
||||
blk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(blkHash), false /* no txs */)
|
||||
blk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, version.Bellatrix, common.BytesToHash(blkHash), false /* no txs */)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not get pow block")
|
||||
}
|
||||
|
||||
if blk == nil {
|
||||
return nil, nil, errors.New("pow block is nil")
|
||||
}
|
||||
blkTDBig, err := hexutil.DecodeBig(blk.TotalDifficulty)
|
||||
blkBellatrix, ok := blk.(*pb.ExecutionBlockBellatrix)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("wrong execution block type %T", blk)
|
||||
}
|
||||
blkTDBig, err := hexutil.DecodeBig(blkBellatrix.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not decode merge block total difficulty")
|
||||
}
|
||||
@@ -100,7 +107,7 @@ func (s *Service) getBlkParentHashAndTD(ctx context.Context, blkHash []byte) ([]
|
||||
if overflows {
|
||||
return nil, nil, errors.New("total difficulty overflows")
|
||||
}
|
||||
return blk.ParentHash[:], blkTDUint256, nil
|
||||
return blkBellatrix.ParentHash[:], blkTDUint256, nil
|
||||
}
|
||||
|
||||
// validateTerminalBlockHash validates if the merge block is a valid terminal PoW block.
|
||||
|
||||
@@ -118,18 +118,18 @@ func Test_validateMergeBlock(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
engine := &mocks.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlock{}}
|
||||
engine := &mocks.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlockBellatrix{}}
|
||||
service.cfg.ExecutionEngineCaller = engine
|
||||
a := [32]byte{'a'}
|
||||
b := [32]byte{'b'}
|
||||
mergeBlockParentHash := [32]byte{'3'}
|
||||
engine.BlockByHashMap[a] = &enginev1.ExecutionBlock{
|
||||
engine.BlockByHashMap[a] = &enginev1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: b,
|
||||
},
|
||||
TotalDifficulty: "0x2",
|
||||
}
|
||||
engine.BlockByHashMap[b] = &enginev1.ExecutionBlock{
|
||||
engine.BlockByHashMap[b] = &enginev1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: mergeBlockParentHash,
|
||||
},
|
||||
@@ -168,12 +168,12 @@ func Test_getBlkParentHashAndTD(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
engine := &mocks.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlock{}}
|
||||
engine := &mocks.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlockBellatrix{}}
|
||||
service.cfg.ExecutionEngineCaller = engine
|
||||
h := [32]byte{'a'}
|
||||
p := [32]byte{'b'}
|
||||
td := "0x1"
|
||||
engine.BlockByHashMap[h] = &enginev1.ExecutionBlock{
|
||||
engine.BlockByHashMap[h] = &enginev1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: p,
|
||||
},
|
||||
@@ -191,7 +191,7 @@ func Test_getBlkParentHashAndTD(t *testing.T) {
|
||||
_, _, err = service.getBlkParentHashAndTD(ctx, h[:])
|
||||
require.ErrorContains(t, "pow block is nil", err)
|
||||
|
||||
engine.BlockByHashMap[h] = &enginev1.ExecutionBlock{
|
||||
engine.BlockByHashMap[h] = &enginev1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: p,
|
||||
},
|
||||
@@ -200,7 +200,7 @@ func Test_getBlkParentHashAndTD(t *testing.T) {
|
||||
_, _, err = service.getBlkParentHashAndTD(ctx, h[:])
|
||||
require.ErrorContains(t, "could not decode merge block total difficulty: hex string without 0x prefix", err)
|
||||
|
||||
engine.BlockByHashMap[h] = &enginev1.ExecutionBlock{
|
||||
engine.BlockByHashMap[h] = &enginev1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: p,
|
||||
},
|
||||
|
||||
@@ -712,6 +712,8 @@ func (s *Service) fillMissingBlockPayloadId(ctx context.Context, ti time.Time) e
|
||||
// Head root should be empty when retrieving proposer index for the next slot.
|
||||
_, id, has := s.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(s.CurrentSlot()+1, [32]byte{} /* head root */)
|
||||
// There exists proposer for next slot, but we haven't called fcu w/ payload attribute yet.
|
||||
log.Infof("missingPayloadID, GetProposerPayloadIDs(nextSlot=%d, arg.headRoot=%#x,has=%v,pid=%#x)", s.CurrentSlot()+1, [32]byte{}, has, id)
|
||||
|
||||
if has && id == [8]byte{} {
|
||||
missedPayloadIDFilledCount.Inc()
|
||||
headBlock, err := s.headBlock()
|
||||
|
||||
@@ -69,6 +69,7 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b interfaces.BeaconBloc
|
||||
// during initial syncing. There's no risk given a state summary object is just a
|
||||
// a subset of the block object.
|
||||
if !s.cfg.BeaconDB.HasStateSummary(ctx, parentRoot) && !s.cfg.BeaconDB.HasBlock(ctx, parentRoot) {
|
||||
log.Errorf("requesting blockroot %#x", bytesutil.Trunc(parentRoot[:]))
|
||||
return errors.New("could not reconstruct parent state")
|
||||
}
|
||||
|
||||
|
||||
@@ -1285,14 +1285,14 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := &mockExecution.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlock{}}
|
||||
e.BlockByHashMap[aHash] = &enginev1.ExecutionBlock{
|
||||
e := &mockExecution.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlockBellatrix{}}
|
||||
e.BlockByHashMap[aHash] = &enginev1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: bHash,
|
||||
},
|
||||
TotalDifficulty: "0x2",
|
||||
}
|
||||
e.BlockByHashMap[bHash] = &enginev1.ExecutionBlock{
|
||||
e.BlockByHashMap[bHash] = &enginev1.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("3")),
|
||||
},
|
||||
|
||||
@@ -311,7 +311,10 @@ func (s *Service) initializeHeadFromDB(ctx context.Context) error {
|
||||
if err := s.setHead(finalizedRoot, finalizedBlock, finalizedState); err != nil {
|
||||
return errors.Wrap(err, "could not set head")
|
||||
}
|
||||
|
||||
_, err = s.notifyForkchoiceUpdate(s.ctx, ¬ifyForkchoiceUpdateArg{headState: finalizedState, headRoot: finalizedRoot, headBlock: finalizedBlock.Block()})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error calling FCU with finalized state at startup")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -446,6 +449,10 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState state.Beacon
|
||||
if err := s.setHead(genesisBlkRoot, genesisBlk, genesisState); err != nil {
|
||||
log.WithError(err).Fatal("Could not set head")
|
||||
}
|
||||
_, err = s.notifyForkchoiceUpdate(s.ctx, ¬ifyForkchoiceUpdateArg{headState: genesisState, headRoot: genesisBlkRoot, headBlock: genesisBlk.Block()})
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("Could not call FCU with genesis")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ func (c *SyncCommitteeHeadStateCache) Get(slot types.Slot) (state.BeaconState, e
|
||||
return nil, ErrIncorrectType
|
||||
}
|
||||
switch st.Version() {
|
||||
case version.Altair, version.Bellatrix:
|
||||
case version.Altair, version.Bellatrix, version.Capella:
|
||||
default:
|
||||
return nil, ErrIncorrectType
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package altair
|
||||
import (
|
||||
"context"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||
@@ -29,6 +31,7 @@ func InitializePrecomputeValidators(ctx context.Context, beaconState state.Beaco
|
||||
// This shouldn't happen with a correct beacon state,
|
||||
// but rather be safe to defend against index out of bound panics.
|
||||
if beaconState.NumValidators() != len(inactivityScores) {
|
||||
log.Errorf("NumValidators=%d inactivityScores=%d", beaconState.NumValidators(), len(inactivityScores))
|
||||
return nil, nil, errors.New("num of validators is different than num of inactivity scores")
|
||||
}
|
||||
if err := beaconState.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
|
||||
|
||||
@@ -19,12 +19,7 @@ go_library(
|
||||
"withdrawals.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
"//testing/util:__pkg__",
|
||||
"//validator:__subpackages__",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
@@ -46,6 +41,7 @@ go_library(
|
||||
"//math:go_default_library",
|
||||
"//network/forks:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v2:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||
"//proto/prysm/v1alpha1/slashings:go_default_library",
|
||||
|
||||
@@ -3,9 +3,14 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -29,3 +34,60 @@ func NewGenesisBlock(stateRoot []byte) *ethpb.SignedBeaconBlock {
|
||||
}
|
||||
return block
|
||||
}
|
||||
|
||||
var ErrUnrecognizedState = errors.New("uknonwn underlying type for state.BeaconState value")
|
||||
|
||||
func NewGenesisBlockForState(root [32]byte, st state.BeaconState) (interfaces.SignedBeaconBlock, error) {
|
||||
ps := st.ToProto()
|
||||
switch ps.(type) {
|
||||
case *ethpb.BeaconState:
|
||||
return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: params.BeaconConfig().ZeroHash[:],
|
||||
StateRoot: root[:],
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, fieldparams.BLSSignatureLength),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
},
|
||||
Graffiti: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
Signature: params.BeaconConfig().EmptySignature[:],
|
||||
})
|
||||
case *ethpb.BeaconStateBellatrix:
|
||||
return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
ParentRoot: params.BeaconConfig().ZeroHash[:],
|
||||
StateRoot: root[:],
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
},
|
||||
Graffiti: make([]byte, 32),
|
||||
SyncAggregate: ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8),
|
||||
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
},
|
||||
ExecutionPayload: &enginev1.ExecutionPayload{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, 32),
|
||||
ReceiptsRoot: make([]byte, 32),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
Transactions: make([][]byte, 0),
|
||||
},
|
||||
},
|
||||
},
|
||||
Signature: params.BeaconConfig().EmptySignature[:],
|
||||
})
|
||||
default:
|
||||
return nil, ErrUnrecognizedState
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload interfaces.
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(payload.ParentHash(), header.BlockHash()) {
|
||||
log.Errorf("parent Hash %#x, header Hash: %#x", bytesutil.Trunc(payload.ParentHash()), bytesutil.Trunc(header.BlockHash()))
|
||||
return ErrInvalidPayloadBlockHash
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -2,7 +2,6 @@ package blocks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||
@@ -15,6 +14,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
||||
@@ -22,6 +22,10 @@ import (
|
||||
|
||||
const executionToBLSPadding = 12
|
||||
|
||||
var ErrInvalidBLSChangeBeforeCapella = errors.New("cannot process BLSToExecutionChange before Capella fork")
|
||||
|
||||
// ProcessBLSToExecutionChanges process all signed BLS_TO_EXECUTION_MESSAGE found in the block.
|
||||
// It does not verify their signature.
|
||||
func ProcessBLSToExecutionChanges(
|
||||
st state.BeaconState,
|
||||
signed interfaces.SignedBeaconBlock) (state.BeaconState, error) {
|
||||
@@ -84,6 +88,9 @@ func processBLSToExecutionChange(st state.BeaconState, signed *ethpb.SignedBLSTo
|
||||
// ValidateBLSToExecutionChange validates the execution change message against the state and returns the
|
||||
// validator referenced by the message.
|
||||
func ValidateBLSToExecutionChange(st state.ReadOnlyBeaconState, signed *ethpb.SignedBLSToExecutionChange) (*ethpb.Validator, error) {
|
||||
if st.Version() < version.Capella {
|
||||
return nil, ErrInvalidBLSChangeBeforeCapella
|
||||
}
|
||||
if signed == nil {
|
||||
return nil, errNilSignedWithdrawalMessage
|
||||
}
|
||||
@@ -120,13 +127,14 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
|
||||
return nil, errInvalidWithdrawalNumber
|
||||
}
|
||||
for i, withdrawal := range withdrawals {
|
||||
if withdrawal.WithdrawalIndex != expected[i].WithdrawalIndex {
|
||||
if withdrawal.Index != expected[i].Index {
|
||||
return nil, errInvalidWithdrawalIndex
|
||||
}
|
||||
if withdrawal.ValidatorIndex != expected[i].ValidatorIndex {
|
||||
log.Errorf("Expected %v, got %v", expected[i], withdrawal)
|
||||
return nil, errInvalidValidatorIndex
|
||||
}
|
||||
if !bytes.Equal(withdrawal.ExecutionAddress, expected[i].ExecutionAddress) {
|
||||
if !bytes.Equal(withdrawal.Address, expected[i].Address) {
|
||||
return nil, errInvalidExecutionAddress
|
||||
}
|
||||
if withdrawal.Amount != expected[i].Amount {
|
||||
@@ -138,7 +146,7 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
|
||||
}
|
||||
}
|
||||
if len(withdrawals) > 0 {
|
||||
if err := st.SetNextWithdrawalIndex(withdrawals[len(withdrawals)-1].WithdrawalIndex + 1); err != nil {
|
||||
if err := st.SetNextWithdrawalIndex(withdrawals[len(withdrawals)-1].Index + 1); err != nil {
|
||||
return nil, errors.Wrap(err, "could not set next withdrawal index")
|
||||
}
|
||||
nextValidatorIndex := withdrawals[len(withdrawals)-1].ValidatorIndex + 1
|
||||
@@ -146,14 +154,13 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
|
||||
nextValidatorIndex = 0
|
||||
}
|
||||
if err := st.SetNextWithdrawalValidatorIndex(nextValidatorIndex); err != nil {
|
||||
return nil, errors.Wrap(err, "could not set latest withdrawal validator index")
|
||||
return nil, errors.Wrap(err, "could not set next withdrawal validator index")
|
||||
}
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
func BLSChangesSignatureBatch(
|
||||
ctx context.Context,
|
||||
st state.ReadOnlyBeaconState,
|
||||
changes []*ethpb.SignedBLSToExecutionChange,
|
||||
) (*bls.SignatureBatch, error) {
|
||||
@@ -172,9 +179,6 @@ func BLSChangesSignatureBatch(
|
||||
return nil, err
|
||||
}
|
||||
for i, change := range changes {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
batch.Signatures[i] = change.Signature
|
||||
publicKey, err := bls.PublicKeyFromBytes(change.Message.FromBlsPubkey)
|
||||
if err != nil {
|
||||
@@ -189,3 +193,17 @@ func BLSChangesSignatureBatch(
|
||||
}
|
||||
return batch, nil
|
||||
}
|
||||
|
||||
// VerifyBLSChangeSignature checks the signature in the SignedBLSToExecutionChange message.
|
||||
func VerifyBLSChangeSignature(
|
||||
st state.BeaconState,
|
||||
change *ethpbv2.SignedBLSToExecutionChange,
|
||||
) error {
|
||||
epoch := slots.ToEpoch(st.Slot())
|
||||
domain, err := signing.Domain(st.Fork(), epoch, params.BeaconConfig().DomainBLSToExecutionChange, st.GenesisValidatorsRoot())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not compute signing domain")
|
||||
}
|
||||
publicKey := change.Message.FromBlsPubkey
|
||||
return signing.VerifySigningRoot(change.Message, publicKey, change.Signature, domain)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package blocks_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
@@ -746,7 +745,7 @@ func TestBLSChangesSignatureBatch(t *testing.T) {
|
||||
}
|
||||
signedChanges[i] = signed
|
||||
}
|
||||
batch, err := blocks.BLSChangesSignatureBatch(context.Background(), st, signedChanges)
|
||||
batch, err := blocks.BLSChangesSignatureBatch(st, signedChanges)
|
||||
require.NoError(t, err)
|
||||
verify, err := batch.Verify()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -6,6 +6,7 @@ go_library(
|
||||
"log.go",
|
||||
"skip_slot_cache.go",
|
||||
"state.go",
|
||||
"state-bellatrix.go",
|
||||
"trailing_slot_state_cache.go",
|
||||
"transition.go",
|
||||
"transition_no_verify_sig.go",
|
||||
@@ -36,6 +37,7 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
@@ -45,6 +47,7 @@ go_library(
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//monitoring/tracing:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
|
||||
283
beacon-chain/core/transition/state-bellatrix.go
Normal file
283
beacon-chain/core/transition/state-bellatrix.go
Normal file
@@ -0,0 +1,283 @@
|
||||
package transition
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/altair"
|
||||
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
b "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// GenesisBeaconStateBellatrix gets called when MinGenesisActiveValidatorCount count of
|
||||
// full deposits were made to the deposit contract and the ChainStart log gets emitted.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
//
|
||||
// def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32,
|
||||
// eth1_timestamp: uint64,
|
||||
// deposits: Sequence[Deposit]) -> BeaconState:
|
||||
// fork = Fork(
|
||||
// previous_version=GENESIS_FORK_VERSION,
|
||||
// current_version=GENESIS_FORK_VERSION,
|
||||
// epoch=GENESIS_EPOCH,
|
||||
// )
|
||||
// state = BeaconState(
|
||||
// genesis_time=eth1_timestamp + GENESIS_DELAY,
|
||||
// fork=fork,
|
||||
// eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
|
||||
// latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
|
||||
// randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
|
||||
// )
|
||||
//
|
||||
// # Process deposits
|
||||
// leaves = list(map(lambda deposit: deposit.data, deposits))
|
||||
// for index, deposit in enumerate(deposits):
|
||||
// deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
|
||||
// state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
|
||||
// process_deposit(state, deposit)
|
||||
//
|
||||
// # Process activations
|
||||
// for index, validator in enumerate(state.validators):
|
||||
// balance = state.balances[index]
|
||||
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
||||
// if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
|
||||
// validator.activation_eligibility_epoch = GENESIS_EPOCH
|
||||
// validator.activation_epoch = GENESIS_EPOCH
|
||||
//
|
||||
// # Set genesis validators root for domain separation and chain versioning
|
||||
// state.genesis_validators_root = hash_tree_root(state.validators)
|
||||
//
|
||||
// return state
|
||||
//
|
||||
// This method differs from the spec so as to process deposits beforehand instead of the end of the function.
|
||||
func GenesisBeaconStateBellatrix(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data, ep *enginev1.ExecutionPayload) (state.BeaconState, error) {
|
||||
st, err := EmptyGenesisStateBellatrix()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Process initial deposits.
|
||||
st, err = helpers.UpdateGenesisEth1Data(st, deposits, eth1Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st, err = b.ProcessPreGenesisDeposits(ctx, st, deposits)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process validator deposits")
|
||||
}
|
||||
|
||||
// After deposits have been processed, overwrite eth1data to what is passed in. This allows us to "pre-mine" validators
|
||||
// without the deposit root and count mismatching the real deposit contract.
|
||||
if err := st.SetEth1Data(eth1Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := st.SetEth1DepositIndex(eth1Data.DepositCount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return OptimizedGenesisBeaconStateBellatrix(genesisTime, st, st.Eth1Data(), ep)
|
||||
}
|
||||
|
||||
// OptimizedGenesisBeaconState is used to create a state that has already processed deposits. This is to efficiently
|
||||
// create a mainnet state at chainstart.
|
||||
func OptimizedGenesisBeaconStateBellatrix(genesisTime uint64, preState state.BeaconState, eth1Data *ethpb.Eth1Data, ep *enginev1.ExecutionPayload) (state.BeaconState, error) {
|
||||
if eth1Data == nil {
|
||||
return nil, errors.New("no eth1data provided for genesis state")
|
||||
}
|
||||
|
||||
randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
|
||||
for i := 0; i < len(randaoMixes); i++ {
|
||||
h := make([]byte, 32)
|
||||
copy(h, eth1Data.BlockHash)
|
||||
randaoMixes[i] = h
|
||||
}
|
||||
|
||||
zeroHash := params.BeaconConfig().ZeroHash[:]
|
||||
|
||||
activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
|
||||
for i := 0; i < len(activeIndexRoots); i++ {
|
||||
activeIndexRoots[i] = zeroHash
|
||||
}
|
||||
|
||||
blockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
|
||||
for i := 0; i < len(blockRoots); i++ {
|
||||
blockRoots[i] = zeroHash
|
||||
}
|
||||
|
||||
stateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
|
||||
for i := 0; i < len(stateRoots); i++ {
|
||||
stateRoots[i] = zeroHash
|
||||
}
|
||||
|
||||
slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
|
||||
|
||||
genesisValidatorsRoot, err := stateutil.ValidatorRegistryRoot(preState.Validators())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not hash tree root genesis validators %v", err)
|
||||
}
|
||||
|
||||
scores, err := preState.InactivityScores()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scoresMissing := len(preState.Validators()) - len(scores)
|
||||
if scoresMissing > 0 {
|
||||
for i := 0; i < scoresMissing; i++ {
|
||||
scores = append(scores, 0)
|
||||
}
|
||||
}
|
||||
wep, err := blocks.WrappedExecutionPayload(ep)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eph, err := blocks.PayloadToHeader(wep)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st := ðpb.BeaconStateBellatrix{
|
||||
// Misc fields.
|
||||
Slot: 0,
|
||||
GenesisTime: genesisTime,
|
||||
GenesisValidatorsRoot: genesisValidatorsRoot[:],
|
||||
|
||||
Fork: ðpb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().AltairForkVersion,
|
||||
CurrentVersion: params.BeaconConfig().BellatrixForkVersion,
|
||||
Epoch: 0,
|
||||
},
|
||||
|
||||
// Validator registry fields.
|
||||
Validators: preState.Validators(),
|
||||
Balances: preState.Balances(),
|
||||
|
||||
// Randomness and committees.
|
||||
RandaoMixes: randaoMixes,
|
||||
|
||||
// Finality.
|
||||
PreviousJustifiedCheckpoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
CurrentJustifiedCheckpoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
JustificationBits: []byte{0},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
|
||||
HistoricalRoots: [][]byte{},
|
||||
BlockRoots: blockRoots,
|
||||
StateRoots: stateRoots,
|
||||
Slashings: slashings,
|
||||
|
||||
// Eth1 data.
|
||||
Eth1Data: eth1Data,
|
||||
Eth1DataVotes: []*ethpb.Eth1Data{},
|
||||
Eth1DepositIndex: preState.Eth1DepositIndex(),
|
||||
LatestExecutionPayloadHeader: eph,
|
||||
InactivityScores: scores,
|
||||
}
|
||||
|
||||
bodyRoot, err := (ðpb.BeaconBlockBodyBellatrix{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
},
|
||||
Graffiti: make([]byte, 32),
|
||||
SyncAggregate: ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8),
|
||||
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
},
|
||||
ExecutionPayload: &enginev1.ExecutionPayload{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, 32),
|
||||
ReceiptsRoot: make([]byte, 32),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
Transactions: make([][]byte, 0),
|
||||
},
|
||||
}).HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not hash tree root empty block body")
|
||||
}
|
||||
|
||||
st.LatestBlockHeader = ðpb.BeaconBlockHeader{
|
||||
ParentRoot: zeroHash,
|
||||
StateRoot: zeroHash,
|
||||
BodyRoot: bodyRoot[:],
|
||||
}
|
||||
|
||||
ist, err := state_native.InitializeFromProtoBellatrix(st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sc, err := altair.NextSyncCommittee(context.Background(), ist)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ist.SetNextSyncCommittee(sc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ist.SetCurrentSyncCommittee(sc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ist, nil
|
||||
}
|
||||
|
||||
// EmptyGenesisState returns an empty beacon state object.
|
||||
func EmptyGenesisStateBellatrix() (state.BeaconState, error) {
|
||||
st := ðpb.BeaconStateBellatrix{
|
||||
// Misc fields.
|
||||
Slot: 0,
|
||||
Fork: ðpb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().AltairForkVersion,
|
||||
CurrentVersion: params.BeaconConfig().BellatrixForkVersion,
|
||||
Epoch: 0,
|
||||
},
|
||||
// Validator registry fields.
|
||||
Validators: []*ethpb.Validator{},
|
||||
Balances: []uint64{},
|
||||
|
||||
JustificationBits: []byte{0},
|
||||
HistoricalRoots: [][]byte{},
|
||||
|
||||
// Eth1 data.
|
||||
Eth1Data: ðpb.Eth1Data{},
|
||||
Eth1DataVotes: []*ethpb.Eth1Data{},
|
||||
Eth1DepositIndex: 0,
|
||||
LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, 32),
|
||||
ReceiptsRoot: make([]byte, 32),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
TransactionsRoot: make([]byte, 32),
|
||||
},
|
||||
}
|
||||
|
||||
return state_native.InitializeFromProtoBellatrix(st)
|
||||
}
|
||||
@@ -205,7 +205,7 @@ func ProcessBlockNoVerifyAnySig(
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not get BLSToExecutionChanges")
|
||||
}
|
||||
cSet, err := b.BLSChangesSignatureBatch(ctx, st, changes)
|
||||
cSet, err := b.BLSChangesSignatureBatch(st, changes)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not get BLSToExecutionChanges signatures")
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz/detect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
dbIface "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/iface"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -19,17 +16,25 @@ import (
|
||||
func (s *Store) SaveGenesisData(ctx context.Context, genesisState state.BeaconState) error {
|
||||
stateRoot, err := genesisState.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "HashTreeRoot")
|
||||
}
|
||||
genesisBlk := blocks.NewGenesisBlock(stateRoot[:])
|
||||
genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot()
|
||||
wsb, err := blocks.NewGenesisBlockForState(stateRoot, genesisState)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewGenesisBlockForState")
|
||||
}
|
||||
genesisBlkRoot, err := wsb.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get genesis block root")
|
||||
}
|
||||
wsb, err := consensusblocks.NewSignedBeaconBlock(genesisBlk)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not wrap genesis block")
|
||||
}
|
||||
/*
|
||||
lbhr, err := genesisState.LatestBlockHeader().HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to compute HTR of latest block header from genesis state")
|
||||
}
|
||||
if genesisBlkRoot != lbhr {
|
||||
return fmt.Errorf("state.latest_block_header=%#x does not match derived genessis block root=%#x", genesisBlkRoot, lbhr)
|
||||
}
|
||||
*/
|
||||
if err := s.SaveBlock(ctx, wsb); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis block")
|
||||
}
|
||||
@@ -54,11 +59,11 @@ func (s *Store) SaveGenesisData(ctx context.Context, genesisState state.BeaconSt
|
||||
|
||||
// LoadGenesis loads a genesis state from a ssz-serialized byte slice, if no genesis exists already.
|
||||
func (s *Store) LoadGenesis(ctx context.Context, sb []byte) error {
|
||||
st := ðpb.BeaconState{}
|
||||
if err := st.UnmarshalSSZ(sb); err != nil {
|
||||
vu, err := detect.FromState(sb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gs, err := state_native.InitializeFromProtoUnsafePhase0(st)
|
||||
gs, err := vu.UnmarshalBeaconState(sb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -83,10 +88,6 @@ func (s *Store) LoadGenesis(ctx context.Context, sb []byte) error {
|
||||
return dbIface.ErrExistingGenesisState
|
||||
}
|
||||
|
||||
if !bytes.Equal(gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion) {
|
||||
return fmt.Errorf("loaded genesis fork version (%#x) does not match config genesis "+
|
||||
"fork version (%#x)", gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion)
|
||||
}
|
||||
return s.SaveGenesisData(ctx, gs)
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/payload-attribute:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
"//contracts/deposit:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
@@ -52,6 +54,7 @@ go_library(
|
||||
"//network/authorization:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//:go_default_library",
|
||||
@@ -108,6 +111,7 @@ go_test(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/payload-attribute:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
"//contracts/deposit:go_default_library",
|
||||
@@ -118,6 +122,7 @@ go_test(
|
||||
"//network/authorization:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
|
||||
@@ -106,7 +106,11 @@ func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.Hea
|
||||
latestBlkTime := s.latestEth1Data.BlockTime
|
||||
s.latestEth1DataLock.RUnlock()
|
||||
|
||||
log.WithField("time (req val)", time).WithField("latestBlockTime", latestBlkTime).WithField("latestBlockHeight", s.latestEth1Data.BlockHeight).Info("BlockByTimestamp")
|
||||
if time > latestBlkTime {
|
||||
if latestBlkHeight < params.BeaconConfig().Eth1FollowDistance {
|
||||
|
||||
}
|
||||
return nil, errors.Wrap(errBlockTimeTooLate, fmt.Sprintf("(%d > %d)", time, latestBlkTime))
|
||||
}
|
||||
// Initialize a pointer to eth1 chain's history to start our search from.
|
||||
|
||||
@@ -163,7 +163,7 @@ func TestService_logTtdStatus(t *testing.T) {
|
||||
require.NoError(t, r.Body.Close())
|
||||
}()
|
||||
|
||||
resp := &pb.ExecutionBlock{
|
||||
resp := &pb.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.Hash{},
|
||||
UncleHash: common.Hash{},
|
||||
@@ -219,7 +219,7 @@ func TestService_logTtdStatus_NotSyncedClient(t *testing.T) {
|
||||
require.NoError(t, r.Body.Close())
|
||||
}()
|
||||
|
||||
resp := (*pb.ExecutionBlock)(nil) // Nil response when a client is not synced
|
||||
resp := (*pb.ExecutionBlockBellatrix)(nil) // Nil response when a client is not synced
|
||||
respJSON := map[string]interface{}{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
|
||||
@@ -19,8 +19,12 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
|
||||
types2 "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -28,10 +32,16 @@ import (
|
||||
const (
|
||||
// NewPayloadMethod v1 request string for JSON-RPC.
|
||||
NewPayloadMethod = "engine_newPayloadV1"
|
||||
// NewPayloadMethod v2 request string for JSON-RPC.
|
||||
NewPayloadMethodV2 = "engine_newPayloadV2"
|
||||
// ForkchoiceUpdatedMethod v1 request string for JSON-RPC.
|
||||
ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1"
|
||||
// ForkchoiceUpdatedMethod v2 request string for JSON-RPC.
|
||||
ForkchoiceUpdatedMethodV2 = "engine_forkchoiceUpdatedV2"
|
||||
// GetPayloadMethod v1 request string for JSON-RPC.
|
||||
GetPayloadMethod = "engine_getPayloadV1"
|
||||
// GetPayloadMethod v2 request string for JSON-RPC.
|
||||
GetPayloadMethodV2 = "engine_getPayloadV2"
|
||||
// ExchangeTransitionConfigurationMethod v1 request string for JSON-RPC.
|
||||
ExchangeTransitionConfigurationMethod = "engine_exchangeTransitionConfigurationV1"
|
||||
// ExecutionBlockByHashMethod request string for JSON-RPC.
|
||||
@@ -53,7 +63,7 @@ type ForkchoiceUpdatedResponse struct {
|
||||
// block with an execution payload from a signed beacon block and a connection
|
||||
// to an execution client's engine API.
|
||||
type ExecutionPayloadReconstructor interface {
|
||||
ReconstructFullBellatrixBlock(
|
||||
ReconstructFullBlock(
|
||||
ctx context.Context, blindedBlock interfaces.SignedBeaconBlock,
|
||||
) (interfaces.SignedBeaconBlock, error)
|
||||
ReconstructFullBellatrixBlockBatch(
|
||||
@@ -66,13 +76,13 @@ type ExecutionPayloadReconstructor interface {
|
||||
type EngineCaller interface {
|
||||
NewPayload(ctx context.Context, payload interfaces.ExecutionData) ([]byte, error)
|
||||
ForkchoiceUpdated(
|
||||
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
|
||||
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
|
||||
) (*pb.PayloadIDBytes, []byte, error)
|
||||
GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error)
|
||||
GetPayload(ctx context.Context, payloadId [8]byte, slot types2.Slot) (interfaces.ExecutionData, error)
|
||||
ExchangeTransitionConfiguration(
|
||||
ctx context.Context, cfg *pb.TransitionConfiguration,
|
||||
) error
|
||||
ExecutionBlockByHash(ctx context.Context, hash common.Hash, withTxs bool) (*pb.ExecutionBlock, error)
|
||||
ExecutionBlockByHash(ctx context.Context, forkVersion int, hash common.Hash, withTxs bool) (interface{}, error)
|
||||
GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error)
|
||||
}
|
||||
|
||||
@@ -89,13 +99,21 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &pb.PayloadStatus{}
|
||||
payloadPb, ok := payload.Proto().(*pb.ExecutionPayload)
|
||||
payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadCapella)
|
||||
if !ok {
|
||||
return nil, errors.New("execution data must be an execution payload")
|
||||
}
|
||||
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payloadPb)
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
payloadPb, ok := payload.Proto().(*pb.ExecutionPayload)
|
||||
if !ok {
|
||||
return nil, errors.New("execution data must be a Bellatrix or Capella execution payload")
|
||||
}
|
||||
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payloadPb)
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
}
|
||||
} else {
|
||||
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV2, payloadPb)
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
}
|
||||
}
|
||||
|
||||
switch result.Status {
|
||||
@@ -114,7 +132,7 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
|
||||
|
||||
// ForkchoiceUpdated calls the engine_forkchoiceUpdatedV1 method via JSON-RPC.
|
||||
func (s *Service) ForkchoiceUpdated(
|
||||
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
|
||||
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
|
||||
) (*pb.PayloadIDBytes, []byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ForkchoiceUpdated")
|
||||
defer span.End()
|
||||
@@ -127,9 +145,29 @@ func (s *Service) ForkchoiceUpdated(
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &ForkchoiceUpdatedResponse{}
|
||||
err := s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, attrs)
|
||||
if err != nil {
|
||||
return nil, nil, handleRPCError(err)
|
||||
|
||||
if attrs == nil {
|
||||
return nil, nil, errors.New("nil payload attribute")
|
||||
}
|
||||
switch attrs.Version() {
|
||||
case version.Bellatrix:
|
||||
a, err := attrs.PbV1()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, a)
|
||||
if err != nil {
|
||||
return nil, nil, handleRPCError(err)
|
||||
}
|
||||
case version.Capella:
|
||||
a, err := attrs.PbV2()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethodV2, state, a)
|
||||
if err != nil {
|
||||
return nil, nil, handleRPCError(err)
|
||||
}
|
||||
}
|
||||
|
||||
if result.Status == nil {
|
||||
@@ -149,7 +187,7 @@ func (s *Service) ForkchoiceUpdated(
|
||||
}
|
||||
|
||||
// GetPayload calls the engine_getPayloadV1 method via JSON-RPC.
|
||||
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error) {
|
||||
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot types2.Slot) (interfaces.ExecutionData, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetPayload")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
@@ -160,9 +198,22 @@ func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.Execut
|
||||
d := time.Now().Add(defaultEngineTimeout)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
|
||||
if slots.ToEpoch(slot) >= params.BeaconConfig().CapellaForkEpoch {
|
||||
result := &pb.ExecutionPayloadCapella{}
|
||||
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV2, pb.PayloadIDBytes(payloadId))
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
}
|
||||
return blocks.WrappedExecutionPayloadCapella(result)
|
||||
}
|
||||
|
||||
result := &pb.ExecutionPayload{}
|
||||
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethod, pb.PayloadIDBytes(payloadId))
|
||||
return result, handleRPCError(err)
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
}
|
||||
return blocks.WrappedExecutionPayload(result)
|
||||
}
|
||||
|
||||
// ExchangeTransitionConfiguration calls the engine_exchangeTransitionConfigurationV1 method via JSON-RPC.
|
||||
@@ -253,16 +304,20 @@ func (s *Service) GetTerminalBlockHash(ctx context.Context, transitionTime uint6
|
||||
if parentHash == params.BeaconConfig().ZeroHash {
|
||||
return nil, false, nil
|
||||
}
|
||||
parentBlk, err := s.ExecutionBlockByHash(ctx, parentHash, false /* no txs */)
|
||||
parentBlk, err := s.ExecutionBlockByHash(ctx, version.Bellatrix, parentHash, false /* no txs */)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||
}
|
||||
if parentBlk == nil {
|
||||
return nil, false, errors.New("parent execution block is nil")
|
||||
}
|
||||
bellatrixParentBlk, ok := parentBlk.(*pb.ExecutionBlockBellatrix)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("wrong execution block type %T", parentBlk)
|
||||
}
|
||||
|
||||
if blockReachedTTD {
|
||||
parentTotalDifficulty, err := tDStringToUint256(parentBlk.TotalDifficulty)
|
||||
parentTotalDifficulty, err := tDStringToUint256(bellatrixParentBlk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
@@ -281,7 +336,7 @@ func (s *Service) GetTerminalBlockHash(ctx context.Context, transitionTime uint6
|
||||
"number": blk.Number,
|
||||
"hash": fmt.Sprintf("%#x", bytesutil.Trunc(blk.Hash[:])),
|
||||
"td": blk.TotalDifficulty,
|
||||
"parentTd": parentBlk.TotalDifficulty,
|
||||
"parentTd": bellatrixParentBlk.TotalDifficulty,
|
||||
"ttd": terminalTotalDifficulty,
|
||||
}).Info("Retrieved terminal block hash")
|
||||
return blk.Hash[:], true, nil
|
||||
@@ -289,17 +344,17 @@ func (s *Service) GetTerminalBlockHash(ctx context.Context, transitionTime uint6
|
||||
} else {
|
||||
return nil, false, nil
|
||||
}
|
||||
blk = parentBlk
|
||||
blk = bellatrixParentBlk
|
||||
}
|
||||
}
|
||||
|
||||
// LatestExecutionBlock fetches the latest execution engine block by calling
|
||||
// eth_blockByNumber via JSON-RPC.
|
||||
func (s *Service) LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock, error) {
|
||||
func (s *Service) LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlockBellatrix, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.LatestExecutionBlock")
|
||||
defer span.End()
|
||||
|
||||
result := &pb.ExecutionBlock{}
|
||||
result := &pb.ExecutionBlockBellatrix{}
|
||||
err := s.rpcClient.CallContext(
|
||||
ctx,
|
||||
result,
|
||||
@@ -311,29 +366,38 @@ func (s *Service) LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock,
|
||||
}
|
||||
|
||||
// ExecutionBlockByHash fetches an execution engine block by hash by calling
|
||||
// eth_blockByHash via JSON-RPC.
|
||||
func (s *Service) ExecutionBlockByHash(ctx context.Context, hash common.Hash, withTxs bool) (*pb.ExecutionBlock, error) {
|
||||
// eth_blockByHash via JSON-RPC. The forkVersion parameter determines which fork's
|
||||
// execution block will be returned.
|
||||
func (s *Service) ExecutionBlockByHash(ctx context.Context, forkVersion int, hash common.Hash, withTxs bool) (interface{}, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExecutionBlockByHash")
|
||||
defer span.End()
|
||||
result := &pb.ExecutionBlock{}
|
||||
var result interface{}
|
||||
switch forkVersion {
|
||||
case version.Capella:
|
||||
result = &pb.ExecutionBlockCapella{}
|
||||
case version.Bellatrix:
|
||||
result = &pb.ExecutionBlockBellatrix{}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported execution block version %s", version.String(forkVersion))
|
||||
}
|
||||
err := s.rpcClient.CallContext(ctx, result, ExecutionBlockByHashMethod, hash, withTxs)
|
||||
return result, handleRPCError(err)
|
||||
}
|
||||
|
||||
// ExecutionBlocksByHashes fetches a batch of execution engine blocks by hash by calling
|
||||
// eth_blockByHash via JSON-RPC.
|
||||
func (s *Service) ExecutionBlocksByHashes(ctx context.Context, hashes []common.Hash, withTxs bool) ([]*pb.ExecutionBlock, error) {
|
||||
func (s *Service) ExecutionBlocksByHashes(ctx context.Context, hashes []common.Hash, withTxs bool) ([]*pb.ExecutionBlockBellatrix, error) {
|
||||
_, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExecutionBlocksByHashes")
|
||||
defer span.End()
|
||||
numOfHashes := len(hashes)
|
||||
elems := make([]gethRPC.BatchElem, 0, numOfHashes)
|
||||
execBlks := make([]*pb.ExecutionBlock, 0, numOfHashes)
|
||||
execBlks := make([]*pb.ExecutionBlockBellatrix, 0, numOfHashes)
|
||||
errs := make([]error, 0, numOfHashes)
|
||||
if numOfHashes == 0 {
|
||||
return execBlks, nil
|
||||
}
|
||||
for _, h := range hashes {
|
||||
blk := &pb.ExecutionBlock{}
|
||||
blk := &pb.ExecutionBlockBellatrix{}
|
||||
err := error(nil)
|
||||
newH := h
|
||||
elems = append(elems, gethRPC.BatchElem{
|
||||
@@ -377,9 +441,9 @@ func (s *Service) HeaderByNumber(ctx context.Context, number *big.Int) (*types.H
|
||||
return hdr, err
|
||||
}
|
||||
|
||||
// ReconstructFullBellatrixBlock takes in a blinded beacon block and reconstructs
|
||||
// ReconstructFullBlock takes in a blinded beacon block and reconstructs
|
||||
// a beacon block with a full execution payload via the engine API.
|
||||
func (s *Service) ReconstructFullBellatrixBlock(
|
||||
func (s *Service) ReconstructFullBlock(
|
||||
ctx context.Context, blindedBlock interfaces.SignedBeaconBlock,
|
||||
) (interfaces.SignedBeaconBlock, error) {
|
||||
if err := blocks.BeaconBlockIsNil(blindedBlock); err != nil {
|
||||
@@ -404,10 +468,19 @@ func (s *Service) ReconstructFullBellatrixBlock(
|
||||
}
|
||||
|
||||
executionBlockHash := common.BytesToHash(header.BlockHash())
|
||||
executionBlock, err := s.ExecutionBlockByHash(ctx, executionBlockHash, true /* with txs */)
|
||||
var executionBlockIface interface{}
|
||||
if blindedBlock.Version() == version.Bellatrix {
|
||||
executionBlockIface, err = s.ExecutionBlockByHash(ctx, version.Bellatrix, executionBlockHash, true /* with txs */)
|
||||
} else {
|
||||
executionBlockIface, err = s.ExecutionBlockByHash(ctx, version.Capella, executionBlockHash, true /* with txs */)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not fetch execution block with txs by hash %#x: %v", executionBlockHash, err)
|
||||
}
|
||||
executionBlock, ok := executionBlockIface.(pb.ExecutionBlock)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("block type %T does not implement ExecutionBlock", executionBlockIface)
|
||||
}
|
||||
if executionBlock == nil {
|
||||
return nil, fmt.Errorf("received nil execution block for request by hash %#x", executionBlockHash)
|
||||
}
|
||||
@@ -415,7 +488,7 @@ func (s *Service) ReconstructFullBellatrixBlock(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload)
|
||||
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload.Proto())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -478,7 +551,7 @@ func (s *Service) ReconstructFullBellatrixBlockBatch(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlocks[realIdx], payload)
|
||||
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlocks[realIdx], payload.Proto())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -499,27 +572,52 @@ func (s *Service) ReconstructFullBellatrixBlockBatch(
|
||||
}
|
||||
|
||||
func fullPayloadFromExecutionBlock(
|
||||
header interfaces.ExecutionData, block *pb.ExecutionBlock,
|
||||
) (*pb.ExecutionPayload, error) {
|
||||
header interfaces.ExecutionData, block pb.ExecutionBlock,
|
||||
) (interfaces.ExecutionData, error) {
|
||||
if header.IsNil() || block == nil {
|
||||
return nil, errors.New("execution block and header cannot be nil")
|
||||
}
|
||||
if !bytes.Equal(header.BlockHash(), block.Hash[:]) {
|
||||
blockHash := block.GetHash()
|
||||
if !bytes.Equal(header.BlockHash(), blockHash[:]) {
|
||||
return nil, fmt.Errorf(
|
||||
"block hash field in execution header %#x does not match execution block hash %#x",
|
||||
header.BlockHash(),
|
||||
block.Hash,
|
||||
blockHash,
|
||||
)
|
||||
}
|
||||
txs := make([][]byte, len(block.Transactions))
|
||||
for i, tx := range block.Transactions {
|
||||
blockTransactions := block.GetTransactions()
|
||||
txs := make([][]byte, len(blockTransactions))
|
||||
for i, tx := range blockTransactions {
|
||||
txBin, err := tx.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txs[i] = txBin
|
||||
}
|
||||
return &pb.ExecutionPayload{
|
||||
|
||||
if block.Version() == version.Bellatrix {
|
||||
return blocks.WrappedExecutionPayload(&pb.ExecutionPayload{
|
||||
ParentHash: header.ParentHash(),
|
||||
FeeRecipient: header.FeeRecipient(),
|
||||
StateRoot: header.StateRoot(),
|
||||
ReceiptsRoot: header.ReceiptsRoot(),
|
||||
LogsBloom: header.LogsBloom(),
|
||||
PrevRandao: header.PrevRandao(),
|
||||
BlockNumber: header.BlockNumber(),
|
||||
GasLimit: header.GasLimit(),
|
||||
GasUsed: header.GasUsed(),
|
||||
Timestamp: header.Timestamp(),
|
||||
ExtraData: header.ExtraData(),
|
||||
BaseFeePerGas: header.BaseFeePerGas(),
|
||||
BlockHash: blockHash[:],
|
||||
Transactions: txs,
|
||||
})
|
||||
}
|
||||
withdrawals, err := block.GetWithdrawals()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{
|
||||
ParentHash: header.ParentHash(),
|
||||
FeeRecipient: header.FeeRecipient(),
|
||||
StateRoot: header.StateRoot(),
|
||||
@@ -532,9 +630,10 @@ func fullPayloadFromExecutionBlock(
|
||||
Timestamp: header.Timestamp(),
|
||||
ExtraData: header.ExtraData(),
|
||||
BaseFeePerGas: header.BaseFeePerGas(),
|
||||
BlockHash: block.Hash[:],
|
||||
BlockHash: blockHash[:],
|
||||
Transactions: txs,
|
||||
}, nil
|
||||
Withdrawals: withdrawals,
|
||||
})
|
||||
}
|
||||
|
||||
// Handles errors received from the RPC server according to the specification.
|
||||
|
||||
@@ -178,7 +178,7 @@ func FuzzExecutionBlock(f *testing.F) {
|
||||
S: big.NewInt(math.MaxInt),
|
||||
}
|
||||
tx := types.NewTx(innerData)
|
||||
execBlock := &pb.ExecutionBlock{
|
||||
execBlock := &pb.ExecutionBlockBellatrix{
|
||||
Header: types.Header{
|
||||
ParentHash: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
|
||||
Root: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
|
||||
@@ -203,7 +203,7 @@ func FuzzExecutionBlock(f *testing.F) {
|
||||
|
||||
f.Fuzz(func(t *testing.T, jsonBlob []byte) {
|
||||
gethResp := make(map[string]interface{})
|
||||
prysmResp := &pb.ExecutionBlock{}
|
||||
prysmResp := &pb.ExecutionBlockBellatrix{}
|
||||
gethErr := json.Unmarshal(jsonBlob, &gethResp)
|
||||
prysmErr := json.Unmarshal(jsonBlob, prysmResp)
|
||||
// Nothing to marshal if we have an error.
|
||||
@@ -237,7 +237,7 @@ func FuzzExecutionBlock(f *testing.F) {
|
||||
})
|
||||
}
|
||||
|
||||
func isBogusTransactionHash(blk *pb.ExecutionBlock, jsonMap map[string]interface{}) bool {
|
||||
func isBogusTransactionHash(blk *pb.ExecutionBlockBellatrix, jsonMap map[string]interface{}) bool {
|
||||
if blk.Transactions == nil {
|
||||
return false
|
||||
}
|
||||
@@ -260,7 +260,7 @@ func isBogusTransactionHash(blk *pb.ExecutionBlock, jsonMap map[string]interface
|
||||
|
||||
func compareHeaders(t *testing.T, jsonBlob []byte) {
|
||||
gethResp := &types.Header{}
|
||||
prysmResp := &pb.ExecutionBlock{}
|
||||
prysmResp := &pb.ExecutionBlockBellatrix{}
|
||||
gethErr := json.Unmarshal(jsonBlob, gethResp)
|
||||
prysmErr := json.Unmarshal(jsonBlob, prysmResp)
|
||||
assert.Equal(t, gethErr != nil, prysmErr != nil, fmt.Sprintf("geth and prysm unmarshaller return inconsistent errors. %v and %v", gethErr, prysmErr))
|
||||
@@ -282,7 +282,7 @@ func compareHeaders(t *testing.T, jsonBlob []byte) {
|
||||
assert.DeepEqual(t, newGethResp, newGethResp2)
|
||||
}
|
||||
|
||||
func validateBlockConsistency(execBlock *pb.ExecutionBlock, jsonMap map[string]interface{}) error {
|
||||
func validateBlockConsistency(execBlock *pb.ExecutionBlockBellatrix, jsonMap map[string]interface{}) error {
|
||||
blockVal := reflect.ValueOf(execBlock).Elem()
|
||||
bType := reflect.TypeOf(execBlock).Elem()
|
||||
|
||||
@@ -316,7 +316,7 @@ func validateBlockConsistency(execBlock *pb.ExecutionBlock, jsonMap map[string]i
|
||||
return nil
|
||||
}
|
||||
|
||||
func jsonFieldsAreValid(execBlock *pb.ExecutionBlock, jsonMap map[string]interface{}) (bool, error) {
|
||||
func jsonFieldsAreValid(execBlock *pb.ExecutionBlockBellatrix, jsonMap map[string]interface{}) (bool, error) {
|
||||
bType := reflect.TypeOf(execBlock).Elem()
|
||||
|
||||
fieldnum := bType.NumField()
|
||||
|
||||
@@ -24,8 +24,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/util"
|
||||
@@ -72,7 +74,9 @@ func TestClient_IPC(t *testing.T) {
|
||||
t.Run(ForkchoiceUpdatedMethod, func(t *testing.T) {
|
||||
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
|
||||
require.Equal(t, true, ok)
|
||||
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, &pb.PayloadAttributes{})
|
||||
attr, err := payloadattribute.New(&pb.PayloadAttributes{})
|
||||
require.NoError(t, err)
|
||||
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, attr)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
|
||||
require.DeepEqual(t, want.PayloadId, payloadID)
|
||||
@@ -95,17 +99,17 @@ func TestClient_IPC(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run(ExecutionBlockByNumberMethod, func(t *testing.T) {
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlockBellatrix)
|
||||
require.Equal(t, true, ok)
|
||||
resp, err := srv.LatestExecutionBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want, resp)
|
||||
})
|
||||
t.Run(ExecutionBlockByHashMethod, func(t *testing.T) {
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlockBellatrix)
|
||||
require.Equal(t, true, ok)
|
||||
arg := common.BytesToHash([]byte("foo"))
|
||||
resp, err := srv.ExecutionBlockByHash(ctx, arg, true /* with txs */)
|
||||
resp, err := srv.ExecutionBlockByHash(ctx, version.Bellatrix, arg, true /* with txs */)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want, resp)
|
||||
})
|
||||
@@ -173,7 +177,9 @@ func TestClient_HTTP(t *testing.T) {
|
||||
srv := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
|
||||
|
||||
// We call the RPC method via HTTP and expect a proper result.
|
||||
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
|
||||
attr, err := payloadattribute.New(payloadAttributes)
|
||||
require.NoError(t, err)
|
||||
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, attr)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
|
||||
require.DeepEqual(t, want.PayloadId, payloadID)
|
||||
@@ -194,7 +200,9 @@ func TestClient_HTTP(t *testing.T) {
|
||||
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
|
||||
|
||||
// We call the RPC method via HTTP and expect a proper result.
|
||||
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
|
||||
attr, err := payloadattribute.New(&payloadAttributes)
|
||||
require.NoError(t, err)
|
||||
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, attr)
|
||||
require.ErrorIs(t, err, ErrAcceptedSyncingPayloadStatus)
|
||||
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
|
||||
require.DeepEqual(t, []byte(nil), validHash)
|
||||
@@ -215,7 +223,9 @@ func TestClient_HTTP(t *testing.T) {
|
||||
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
|
||||
|
||||
// We call the RPC method via HTTP and expect a proper result.
|
||||
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
|
||||
attr, err := payloadattribute.New(&payloadAttributes)
|
||||
require.NoError(t, err)
|
||||
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, attr)
|
||||
require.ErrorIs(t, err, ErrInvalidPayloadStatus)
|
||||
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
|
||||
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
|
||||
@@ -236,7 +246,9 @@ func TestClient_HTTP(t *testing.T) {
|
||||
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
|
||||
|
||||
// We call the RPC method via HTTP and expect a proper result.
|
||||
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
|
||||
attr, err := payloadattribute.New(&payloadAttributes)
|
||||
require.NoError(t, err)
|
||||
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, attr)
|
||||
require.ErrorIs(t, err, ErrUnknownPayloadStatus)
|
||||
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
|
||||
require.DeepEqual(t, []byte(nil), validHash)
|
||||
@@ -312,7 +324,7 @@ func TestClient_HTTP(t *testing.T) {
|
||||
require.DeepEqual(t, []uint8(nil), resp)
|
||||
})
|
||||
t.Run(ExecutionBlockByNumberMethod, func(t *testing.T) {
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlockBellatrix)
|
||||
require.Equal(t, true, ok)
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -381,7 +393,7 @@ func TestClient_HTTP(t *testing.T) {
|
||||
})
|
||||
t.Run(ExecutionBlockByHashMethod, func(t *testing.T) {
|
||||
arg := common.BytesToHash([]byte("foo"))
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
||||
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlockBellatrix)
|
||||
require.Equal(t, true, ok)
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -413,7 +425,7 @@ func TestClient_HTTP(t *testing.T) {
|
||||
service.rpcClient = rpcClient
|
||||
|
||||
// We call the RPC method via HTTP and expect a proper result.
|
||||
resp, err := service.ExecutionBlockByHash(ctx, arg, true /* with txs */)
|
||||
resp, err := service.ExecutionBlockByHash(ctx, version.Bellatrix, arg, true /* with txs */)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want, resp)
|
||||
})
|
||||
@@ -424,7 +436,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
|
||||
t.Run("nil block", func(t *testing.T) {
|
||||
service := &Service{}
|
||||
|
||||
_, err := service.ReconstructFullBellatrixBlock(ctx, nil)
|
||||
_, err := service.ReconstructFullBlock(ctx, nil)
|
||||
require.ErrorContains(t, "nil data", err)
|
||||
})
|
||||
t.Run("only blinded block", func(t *testing.T) {
|
||||
@@ -433,7 +445,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
|
||||
bellatrixBlock := util.NewBeaconBlockBellatrix()
|
||||
wrapped, err := blocks.NewSignedBeaconBlock(bellatrixBlock)
|
||||
require.NoError(t, err)
|
||||
_, err = service.ReconstructFullBellatrixBlock(ctx, wrapped)
|
||||
_, err = service.ReconstructFullBlock(ctx, wrapped)
|
||||
require.ErrorContains(t, want, err)
|
||||
})
|
||||
t.Run("pre-merge execution payload", func(t *testing.T) {
|
||||
@@ -448,7 +460,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
wantedWrapped, err := blocks.NewSignedBeaconBlock(wanted)
|
||||
require.NoError(t, err)
|
||||
reconstructed, err := service.ReconstructFullBellatrixBlock(ctx, wrapped)
|
||||
reconstructed, err := service.ReconstructFullBlock(ctx, wrapped)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, wantedWrapped, reconstructed)
|
||||
})
|
||||
@@ -521,7 +533,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
|
||||
blindedBlock.Block.Body.ExecutionPayloadHeader = header
|
||||
wrapped, err := blocks.NewSignedBeaconBlock(blindedBlock)
|
||||
require.NoError(t, err)
|
||||
reconstructed, err := service.ReconstructFullBellatrixBlock(ctx, wrapped)
|
||||
reconstructed, err := service.ReconstructFullBlock(ctx, wrapped)
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := reconstructed.Block().Body().Execution()
|
||||
@@ -677,8 +689,8 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
paramsTd string
|
||||
currentPowBlock *pb.ExecutionBlock
|
||||
parentPowBlock *pb.ExecutionBlock
|
||||
currentPowBlock *pb.ExecutionBlockBellatrix
|
||||
parentPowBlock *pb.ExecutionBlockBellatrix
|
||||
errLatestExecutionBlk error
|
||||
wantTerminalBlockHash []byte
|
||||
wantExists bool
|
||||
@@ -703,7 +715,7 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
{
|
||||
name: "current execution block invalid TD",
|
||||
paramsTd: "1",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
TotalDifficulty: "1115792089237316195423570985008687907853269984665640564039457584007913129638912",
|
||||
},
|
||||
@@ -712,7 +724,7 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
{
|
||||
name: "current execution block has zero hash parent",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash(params.BeaconConfig().ZeroHash[:]),
|
||||
@@ -723,7 +735,7 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
{
|
||||
name: "could not get parent block",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
@@ -735,14 +747,14 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
{
|
||||
name: "parent execution block invalid TD",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
parentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("b")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("c")),
|
||||
@@ -754,14 +766,14 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
{
|
||||
name: "happy case",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
parentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("b")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("c")),
|
||||
@@ -774,7 +786,7 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
{
|
||||
name: "happy case, but invalid timestamp",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
@@ -782,7 +794,7 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
parentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("b")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("c")),
|
||||
@@ -793,14 +805,14 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
{
|
||||
name: "ttd not reached",
|
||||
paramsTd: "3",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
},
|
||||
TotalDifficulty: "0x2",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
parentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("b")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("c")),
|
||||
@@ -814,9 +826,9 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
cfg := params.BeaconConfig().Copy()
|
||||
cfg.TerminalTotalDifficulty = tt.paramsTd
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
var m map[[32]byte]*pb.ExecutionBlock
|
||||
var m map[[32]byte]*pb.ExecutionBlockBellatrix
|
||||
if tt.parentPowBlock != nil {
|
||||
m = map[[32]byte]*pb.ExecutionBlock{
|
||||
m = map[[32]byte]*pb.ExecutionBlockBellatrix{
|
||||
tt.parentPowBlock.Hash: tt.parentPowBlock,
|
||||
}
|
||||
}
|
||||
@@ -1079,7 +1091,7 @@ func fixtures() map[string]interface{} {
|
||||
transactionsRoot := bytesutil.PadTo([]byte("transactionsRoot"), fieldparams.RootLength)
|
||||
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
|
||||
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
|
||||
executionBlock := &pb.ExecutionBlock{
|
||||
executionBlock := &pb.ExecutionBlockBellatrix{
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash(parent),
|
||||
UncleHash: common.BytesToHash(sha3Uncles),
|
||||
@@ -1182,13 +1194,13 @@ func fixtures() map[string]interface{} {
|
||||
func Test_fullPayloadFromExecutionBlock(t *testing.T) {
|
||||
type args struct {
|
||||
header *pb.ExecutionPayloadHeader
|
||||
block *pb.ExecutionBlock
|
||||
block *pb.ExecutionBlockBellatrix
|
||||
}
|
||||
wantedHash := common.BytesToHash([]byte("foo"))
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *pb.ExecutionPayload
|
||||
want func() interfaces.ExecutionData
|
||||
err string
|
||||
}{
|
||||
{
|
||||
@@ -1197,7 +1209,7 @@ func Test_fullPayloadFromExecutionBlock(t *testing.T) {
|
||||
header: &pb.ExecutionPayloadHeader{
|
||||
BlockHash: []byte("foo"),
|
||||
},
|
||||
block: &pb.ExecutionBlock{
|
||||
block: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("bar")),
|
||||
},
|
||||
},
|
||||
@@ -1209,23 +1221,30 @@ func Test_fullPayloadFromExecutionBlock(t *testing.T) {
|
||||
header: &pb.ExecutionPayloadHeader{
|
||||
BlockHash: wantedHash[:],
|
||||
},
|
||||
block: &pb.ExecutionBlock{
|
||||
block: &pb.ExecutionBlockBellatrix{
|
||||
Hash: wantedHash,
|
||||
},
|
||||
},
|
||||
want: &pb.ExecutionPayload{
|
||||
BlockHash: wantedHash[:],
|
||||
want: func() interfaces.ExecutionData {
|
||||
p, err := blocks.WrappedExecutionPayload(&pb.ExecutionPayload{
|
||||
BlockHash: wantedHash[:],
|
||||
Transactions: [][]byte{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return p
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
wrapped, err := blocks.WrappedExecutionPayloadHeader(tt.args.header)
|
||||
require.NoError(t, err)
|
||||
got, err := fullPayloadFromExecutionBlock(wrapped, tt.args.block)
|
||||
if (err != nil) && !strings.Contains(err.Error(), tt.err) {
|
||||
t.Fatalf("Wanted err %s got %v", tt.err, err)
|
||||
if err != nil {
|
||||
assert.ErrorContains(t, tt.err, err)
|
||||
} else {
|
||||
assert.DeepEqual(t, tt.want(), got)
|
||||
}
|
||||
require.DeepEqual(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1308,9 +1327,9 @@ func (*testEngineService) NoArgsRets() {}
|
||||
|
||||
func (*testEngineService) GetBlockByHash(
|
||||
_ context.Context, _ common.Hash, _ bool,
|
||||
) *pb.ExecutionBlock {
|
||||
) *pb.ExecutionBlockBellatrix {
|
||||
fix := fixtures()
|
||||
item, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
||||
item, ok := fix["ExecutionBlock"].(*pb.ExecutionBlockBellatrix)
|
||||
if !ok {
|
||||
panic("not found")
|
||||
}
|
||||
@@ -1319,9 +1338,9 @@ func (*testEngineService) GetBlockByHash(
|
||||
|
||||
func (*testEngineService) GetBlockByNumber(
|
||||
_ context.Context, _ string, _ bool,
|
||||
) *pb.ExecutionBlock {
|
||||
) *pb.ExecutionBlockBellatrix {
|
||||
fix := fixtures()
|
||||
item, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
|
||||
item, ok := fix["ExecutionBlock"].(*pb.ExecutionBlockBellatrix)
|
||||
if !ok {
|
||||
panic("not found")
|
||||
}
|
||||
|
||||
@@ -288,13 +288,13 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
headersMap := make(map[uint64]*types.HeaderInfo)
|
||||
rawLogCount, err := s.depositContractCaller.GetDepositCount(&bind.CallOpts{})
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "GetDepositCount")
|
||||
}
|
||||
logCount := binary.LittleEndian.Uint64(rawLogCount)
|
||||
|
||||
latestFollowHeight, err := s.followedBlockHeight(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "followedBlockHeight")
|
||||
}
|
||||
|
||||
batchSize := s.cfg.eth1HeaderReqLimit
|
||||
@@ -303,7 +303,7 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
for currentBlockNum < latestFollowHeight {
|
||||
currentBlockNum, batchSize, err = s.processBlockInBatch(ctx, currentBlockNum, latestFollowHeight, batchSize, additiveFactor, logCount, headersMap)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "processBlockInBatch, num=%d, height=%d", currentBlockNum, latestFollowHeight)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
|
||||
c, err := s.cfg.beaconDB.FinalizedCheckpoint(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "FinalizedCheckpoint")
|
||||
}
|
||||
fRoot := bytesutil.ToBytes32(c.Root)
|
||||
// Return if no checkpoint exists yet.
|
||||
@@ -333,7 +333,7 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
if isNil || slots.ToEpoch(fState.Slot()) != c.Epoch {
|
||||
fState, err = s.cfg.stateGen.StateByRoot(ctx, fRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "StateByRoot=%#x", fRoot)
|
||||
}
|
||||
}
|
||||
if fState != nil && !fState.IsNil() && fState.Eth1DepositIndex() > 0 {
|
||||
|
||||
@@ -45,7 +45,7 @@ func (s *Service) setupExecutionClientConnections(ctx context.Context, currEndpo
|
||||
}
|
||||
return errors.Wrap(err, errStr)
|
||||
}
|
||||
s.updateConnectedETH1(true)
|
||||
s.updateConnectedETH1(true, "execution chain connection established")
|
||||
s.runError = nil
|
||||
return nil
|
||||
}
|
||||
@@ -88,13 +88,14 @@ func (s *Service) pollConnectionStatus(ctx context.Context) {
|
||||
|
||||
// Forces to retry an execution client connection.
|
||||
func (s *Service) retryExecutionClientConnection(ctx context.Context, err error) {
|
||||
s.runError = err
|
||||
s.updateConnectedETH1(false)
|
||||
log.Debugf("retryExecutionClientConnection, err=%s", err.Error())
|
||||
s.runError = errors.Wrap(err, "retryExecutionClientConnection")
|
||||
s.updateConnectedETH1(false, "retryExecutionClientConnection")
|
||||
// Back off for a while before redialing.
|
||||
time.Sleep(backOffPeriod)
|
||||
currClient := s.rpcClient
|
||||
if err := s.setupExecutionClientConnections(ctx, s.cfg.currHttpEndpoint); err != nil {
|
||||
s.runError = err
|
||||
s.runError = errors.Wrap(err, "setupExecutionClientConnections")
|
||||
return
|
||||
}
|
||||
// Close previous client, if connection was successful.
|
||||
|
||||
@@ -307,7 +307,8 @@ func (s *Service) updateBeaconNodeStats() {
|
||||
s.cfg.beaconNodeStatsUpdater.Update(bs)
|
||||
}
|
||||
|
||||
func (s *Service) updateConnectedETH1(state bool) {
|
||||
func (s *Service) updateConnectedETH1(state bool, reason string) {
|
||||
log.Infof("updateConnectedETH1 - %s", reason)
|
||||
s.connectedETH1 = state
|
||||
s.updateBeaconNodeStats()
|
||||
}
|
||||
@@ -319,10 +320,14 @@ func (s *Service) followedBlockHeight(ctx context.Context) (uint64, error) {
|
||||
latestBlockTime := uint64(0)
|
||||
if s.latestEth1Data.BlockTime > followTime {
|
||||
latestBlockTime = s.latestEth1Data.BlockTime - followTime
|
||||
if s.latestEth1Data.BlockHeight < params.BeaconConfig().Eth1FollowDistance {
|
||||
latestBlockTime = s.latestEth1Data.BlockTime
|
||||
}
|
||||
}
|
||||
log.WithField("distance", params.BeaconConfig().Eth1FollowDistance).WithField("followTime", followTime).WithField("BlockTime", s.latestEth1Data.BlockTime).WithField("BlockHeight", s.latestEth1Data.BlockHeight).WithField("latestBlockTime", latestBlockTime).Info("followedBlockHeight")
|
||||
blk, err := s.BlockByTimestamp(ctx, latestBlockTime)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrapf(err, "BlockByTimestamp=%d", latestBlockTime)
|
||||
}
|
||||
return blk.Number.Uint64(), nil
|
||||
}
|
||||
@@ -467,21 +472,23 @@ func (s *Service) handleETH1FollowDistance() {
|
||||
}
|
||||
if !s.chainStartData.Chainstarted {
|
||||
if err := s.processChainStartFromBlockNum(ctx, big.NewInt(int64(s.latestEth1Data.LastRequestedBlock))); err != nil {
|
||||
s.runError = err
|
||||
s.runError = errors.Wrap(err, "processChainStartFromBlockNum")
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If the last requested block has not changed,
|
||||
// we do not request batched logs as this means there are no new
|
||||
// logs for the powchain service to process. Also it is a potential
|
||||
// failure condition as would mean we have not respected the protocol threshold.
|
||||
if s.latestEth1Data.LastRequestedBlock == s.latestEth1Data.BlockHeight {
|
||||
log.Error("Beacon node is not respecting the follow distance")
|
||||
// TODO this is usually an error but temporarily setting it to warn because its noisy when starting from genesis
|
||||
log.Warn("Beacon node is not respecting the follow distance")
|
||||
return
|
||||
}
|
||||
if err := s.requestBatchedHeadersAndLogs(ctx); err != nil {
|
||||
s.runError = err
|
||||
s.runError = errors.Wrap(err, "requestBatchedHeadersAndLogs")
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
@@ -511,6 +518,7 @@ func (s *Service) initPOWService() {
|
||||
ctx := s.ctx
|
||||
header, err := s.HeaderByNumber(ctx, nil)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "HeaderByNumber")
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to retrieve latest execution client header")
|
||||
continue
|
||||
@@ -523,6 +531,7 @@ func (s *Service) initPOWService() {
|
||||
s.latestEth1DataLock.Unlock()
|
||||
|
||||
if err := s.processPastLogs(ctx); err != nil {
|
||||
err = errors.Wrap(err, "processPastLogs")
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(
|
||||
err,
|
||||
@@ -532,6 +541,7 @@ func (s *Service) initPOWService() {
|
||||
}
|
||||
// Cache eth1 headers from our voting period.
|
||||
if err := s.cacheHeadersForEth1DataVote(ctx); err != nil {
|
||||
err = errors.Wrap(err, "cacheHeadersForEth1DataVote")
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
if errors.Is(err, errBlockTimeTooLate) {
|
||||
log.WithError(err).Debug("Unable to cache headers for execution client votes")
|
||||
@@ -550,6 +560,7 @@ func (s *Service) initPOWService() {
|
||||
if genHash != [32]byte{} {
|
||||
genHeader, err := s.HeaderByHash(ctx, genHash)
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "HeaderByHash, hash=%#x", genHash)
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to retrieve proof-of-stake genesis block data")
|
||||
continue
|
||||
@@ -558,6 +569,7 @@ func (s *Service) initPOWService() {
|
||||
}
|
||||
s.chainStartData.GenesisBlock = genBlock
|
||||
if err := s.savePowchainData(ctx); err != nil {
|
||||
err = errors.Wrap(err, "savePowchainData")
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to save execution client data")
|
||||
continue
|
||||
@@ -583,7 +595,7 @@ func (s *Service) run(done <-chan struct{}) {
|
||||
s.isRunning = false
|
||||
s.runError = nil
|
||||
s.rpcClient.Close()
|
||||
s.updateConnectedETH1(false)
|
||||
s.updateConnectedETH1(false, "context canceled in run()")
|
||||
log.Debug("Context closed, exiting goroutine")
|
||||
return
|
||||
case <-s.eth1HeadTicker.C:
|
||||
@@ -641,11 +653,11 @@ func (s *Service) cacheHeadersForEth1DataVote(ctx context.Context) error {
|
||||
// Find the end block to request from.
|
||||
end, err := s.followedBlockHeight(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "followedBlockHeight")
|
||||
}
|
||||
start, err := s.determineEarliestVotingBlock(ctx, end)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "determineEarliestVotingBlock=%d", end)
|
||||
}
|
||||
return s.cacheBlockHeaders(start, end)
|
||||
}
|
||||
@@ -677,7 +689,7 @@ func (s *Service) cacheBlockHeaders(start, end uint64) error {
|
||||
}
|
||||
continue
|
||||
}
|
||||
return err
|
||||
return errors.Wrapf(err, "cacheBlockHeaders, start=%d, end=%d", startReq, endReq)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -696,12 +708,22 @@ func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock
|
||||
}
|
||||
return earliestBlk, nil
|
||||
}
|
||||
if s.latestEth1Data.BlockHeight < params.BeaconConfig().Eth1FollowDistance {
|
||||
return 0, nil
|
||||
}
|
||||
votingTime := slots.VotingPeriodStartTime(genesisTime, currSlot)
|
||||
followBackDist := 2 * params.BeaconConfig().SecondsPerETH1Block * params.BeaconConfig().Eth1FollowDistance
|
||||
if followBackDist > votingTime {
|
||||
return 0, errors.Errorf("invalid genesis time provided. %d > %d", followBackDist, votingTime)
|
||||
}
|
||||
earliestValidTime := votingTime - followBackDist
|
||||
/*
|
||||
if earliestValidTime > s.latestEth1Data.BlockTime {
|
||||
return 0, nil
|
||||
}
|
||||
log.WithField("earliestValidTime", earliestValidTime).Info("calling BlockByTimestamp")
|
||||
*/
|
||||
log.WithField("distance", params.BeaconConfig().Eth1FollowDistance).WithField("earliestValidTime", earliestValidTime).WithField("BlockTime", s.latestEth1Data.BlockTime).WithField("BlockHeight", s.latestEth1Data.BlockHeight).WithField("followBlock", followBlock).Info("determineEarliestVotingBlock")
|
||||
hdr, err := s.BlockByTimestamp(ctx, earliestValidTime)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
||||
@@ -4,13 +4,14 @@ go_library(
|
||||
name = "go_default_library",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"genesis.go",
|
||||
"mock_engine_client.go",
|
||||
"mock_execution_chain.go",
|
||||
"mock_faulty_powchain.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
@@ -20,13 +21,17 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/payload-attribute:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//core:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//params:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
|
||||
202
beacon-chain/execution/testing/genesis.go
Normal file
202
beacon-chain/execution/testing/genesis.go
Normal file
File diff suppressed because one or more lines are too long
@@ -2,6 +2,7 @@ package testing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@@ -11,6 +12,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
)
|
||||
@@ -21,7 +24,7 @@ type EngineClient struct {
|
||||
PayloadIDBytes *pb.PayloadIDBytes
|
||||
ForkChoiceUpdatedResp []byte
|
||||
ExecutionPayload *pb.ExecutionPayload
|
||||
ExecutionBlock *pb.ExecutionBlock
|
||||
ExecutionBlock *pb.ExecutionBlockBellatrix
|
||||
Err error
|
||||
ErrLatestExecBlock error
|
||||
ErrExecBlockByHash error
|
||||
@@ -29,7 +32,7 @@ type EngineClient struct {
|
||||
ErrNewPayload error
|
||||
ErrGetPayload error
|
||||
ExecutionPayloadByBlockHash map[[32]byte]*pb.ExecutionPayload
|
||||
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
||||
BlockByHashMap map[[32]byte]*pb.ExecutionBlockBellatrix
|
||||
NumReconstructedPayloads uint64
|
||||
TerminalBlockHash []byte
|
||||
TerminalBlockHashExists bool
|
||||
@@ -43,7 +46,7 @@ func (e *EngineClient) NewPayload(_ context.Context, _ interfaces.ExecutionData)
|
||||
|
||||
// ForkchoiceUpdated --
|
||||
func (e *EngineClient) ForkchoiceUpdated(
|
||||
_ context.Context, fcs *pb.ForkchoiceState, _ *pb.PayloadAttributes,
|
||||
_ context.Context, fcs *pb.ForkchoiceState, _ payloadattribute.Attributer,
|
||||
) (*pb.PayloadIDBytes, []byte, error) {
|
||||
if e.OverrideValidHash != [32]byte{} && bytesutil.ToBytes32(fcs.HeadBlockHash) == e.OverrideValidHash {
|
||||
return e.PayloadIDBytes, e.ForkChoiceUpdatedResp, nil
|
||||
@@ -52,8 +55,17 @@ func (e *EngineClient) ForkchoiceUpdated(
|
||||
}
|
||||
|
||||
// GetPayload --
|
||||
func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte) (*pb.ExecutionPayload, error) {
|
||||
return e.ExecutionPayload, e.ErrGetPayload
|
||||
func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, slot types.Slot) (interfaces.ExecutionData, error) {
|
||||
p, err := blocks.WrappedExecutionPayload(e.ExecutionPayload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, e.ErrGetPayload
|
||||
}
|
||||
|
||||
// GetPayloadV2 --
|
||||
func (e *EngineClient) GetPayloadV2(_ context.Context, _ [8]byte) (*pb.ExecutionPayloadCapella, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// ExchangeTransitionConfiguration --
|
||||
@@ -62,12 +74,12 @@ func (e *EngineClient) ExchangeTransitionConfiguration(_ context.Context, _ *pb.
|
||||
}
|
||||
|
||||
// LatestExecutionBlock --
|
||||
func (e *EngineClient) LatestExecutionBlock(_ context.Context) (*pb.ExecutionBlock, error) {
|
||||
func (e *EngineClient) LatestExecutionBlock(_ context.Context) (*pb.ExecutionBlockBellatrix, error) {
|
||||
return e.ExecutionBlock, e.ErrLatestExecBlock
|
||||
}
|
||||
|
||||
// ExecutionBlockByHash --
|
||||
func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash, _ bool) (*pb.ExecutionBlock, error) {
|
||||
func (e *EngineClient) ExecutionBlockByHash(_ context.Context, _ int, h common.Hash, _ bool) (interface{}, error) {
|
||||
b, ok := e.BlockByHashMap[h]
|
||||
if !ok {
|
||||
return nil, errors.New("block not found")
|
||||
@@ -75,7 +87,8 @@ func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash, _
|
||||
return b, e.ErrExecBlockByHash
|
||||
}
|
||||
|
||||
func (e *EngineClient) ReconstructFullBellatrixBlock(
|
||||
// ReconstructFullBlock --
|
||||
func (e *EngineClient) ReconstructFullBlock(
|
||||
_ context.Context, blindedBlock interfaces.SignedBeaconBlock,
|
||||
) (interfaces.SignedBeaconBlock, error) {
|
||||
if !blindedBlock.Block().IsBlinded() {
|
||||
@@ -93,12 +106,13 @@ func (e *EngineClient) ReconstructFullBellatrixBlock(
|
||||
return blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload)
|
||||
}
|
||||
|
||||
// ReconstructFullBellatrixBlockBatch --
|
||||
func (e *EngineClient) ReconstructFullBellatrixBlockBatch(
|
||||
ctx context.Context, blindedBlocks []interfaces.SignedBeaconBlock,
|
||||
) ([]interfaces.SignedBeaconBlock, error) {
|
||||
fullBlocks := make([]interfaces.SignedBeaconBlock, 0, len(blindedBlocks))
|
||||
for _, b := range blindedBlocks {
|
||||
newBlock, err := e.ReconstructFullBellatrixBlock(ctx, b)
|
||||
newBlock, err := e.ReconstructFullBlock(ctx, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -135,12 +149,16 @@ func (e *EngineClient) GetTerminalBlockHash(ctx context.Context, transitionTime
|
||||
if parentHash == params.BeaconConfig().ZeroHash {
|
||||
return nil, false, nil
|
||||
}
|
||||
parentBlk, err := e.ExecutionBlockByHash(ctx, parentHash, false /* with txs */)
|
||||
parentBlk, err := e.ExecutionBlockByHash(ctx, 0, parentHash, false /* with txs */)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||
}
|
||||
parentBlkBellatrix, ok := parentBlk.(*pb.ExecutionBlockBellatrix)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("wrong execution block type %T", parentBlk)
|
||||
}
|
||||
if blockReachedTTD {
|
||||
b, err := hexutil.DecodeBig(parentBlk.TotalDifficulty)
|
||||
b, err := hexutil.DecodeBig(parentBlkBellatrix.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
@@ -155,6 +173,6 @@ func (e *EngineClient) GetTerminalBlockHash(ctx context.Context, transitionTime
|
||||
} else {
|
||||
return nil, false, nil
|
||||
}
|
||||
blk = parentBlk
|
||||
blk = parentBlkBellatrix
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,6 +815,7 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
AttestationsPool: b.attestationPool,
|
||||
ExitPool: b.exitPool,
|
||||
SlashingsPool: b.slashingsPool,
|
||||
BLSChangesPool: b.blsToExecPool,
|
||||
SlashingChecker: slasherService,
|
||||
SyncCommitteeObjectPool: b.syncCommitteePool,
|
||||
ExecutionChainService: web3Service,
|
||||
|
||||
@@ -11,10 +11,15 @@ go_library(
|
||||
"//beacon-chain:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//container/doubly-linked-list:go_default_library",
|
||||
"//crypto/bls/blst:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -24,8 +29,15 @@ go_test(
|
||||
srcs = ["pool_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/bls/common:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
|
||||
@@ -4,17 +4,22 @@ import (
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
doublylinkedlist "github.com/prysmaticlabs/prysm/v3/container/doubly-linked-list"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/bls/blst"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// PoolManager maintains pending and seen BLS-to-execution-change objects.
|
||||
// This pool is used by proposers to insert BLS-to-execution-change objects into new blocks.
|
||||
type PoolManager interface {
|
||||
PendingBLSToExecChanges() ([]*ethpb.SignedBLSToExecutionChange, error)
|
||||
BLSToExecChangesForInclusion() ([]*ethpb.SignedBLSToExecutionChange, error)
|
||||
BLSToExecChangesForInclusion(state.BeaconState) ([]*ethpb.SignedBLSToExecutionChange, error)
|
||||
InsertBLSToExecChange(change *ethpb.SignedBLSToExecutionChange)
|
||||
MarkIncluded(change *ethpb.SignedBLSToExecutionChange) error
|
||||
ValidatorExists(idx types.ValidatorIndex) bool
|
||||
@@ -58,25 +63,69 @@ func (p *Pool) PendingBLSToExecChanges() ([]*ethpb.SignedBLSToExecutionChange, e
|
||||
|
||||
// BLSToExecChangesForInclusion returns objects that are ready for inclusion at the given slot.
|
||||
// This method will not return more than the block enforced MaxBlsToExecutionChanges.
|
||||
func (p *Pool) BLSToExecChangesForInclusion() ([]*ethpb.SignedBLSToExecutionChange, error) {
|
||||
func (p *Pool) BLSToExecChangesForInclusion(st state.BeaconState) ([]*ethpb.SignedBLSToExecutionChange, error) {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
length := int(math.Min(float64(params.BeaconConfig().MaxBlsToExecutionChanges), float64(p.pending.Len())))
|
||||
result := make([]*ethpb.SignedBLSToExecutionChange, length)
|
||||
result := make([]*ethpb.SignedBLSToExecutionChange, 0, length)
|
||||
node := p.pending.First()
|
||||
var err error
|
||||
for i := 0; node != nil && i < length; i++ {
|
||||
result[i], err = node.Value()
|
||||
for node != nil && len(result) < length {
|
||||
change, err := node.Value()
|
||||
if err != nil {
|
||||
p.lock.RUnlock()
|
||||
return nil, err
|
||||
}
|
||||
_, err = blocks.ValidateBLSToExecutionChange(st, change)
|
||||
if err != nil {
|
||||
logrus.Warning("removing invalid BLSToExecutionChange from pool")
|
||||
// MarkIncluded removes the invalid change from the pool
|
||||
p.lock.RUnlock()
|
||||
if err := p.MarkIncluded(change); err != nil {
|
||||
return nil, errors.Wrap(err, "could not mark BLSToExecutionChange as included")
|
||||
}
|
||||
p.lock.RLock()
|
||||
} else {
|
||||
result = append(result, change)
|
||||
}
|
||||
node, err = node.Next()
|
||||
if err != nil {
|
||||
p.lock.RUnlock()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
p.lock.RUnlock()
|
||||
if len(result) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
// We now verify the signatures in batches
|
||||
cSet, err := blocks.BLSChangesSignatureBatch(st, result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get BLSToExecutionChanges signatures")
|
||||
}
|
||||
ok, err := cSet.Verify()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not batch verify BLSToExecutionChanges signatures")
|
||||
}
|
||||
if ok {
|
||||
return result, nil
|
||||
|
||||
}
|
||||
// Batch signature failed, check signatures individually
|
||||
verified := make([]*ethpb.SignedBLSToExecutionChange, 0, length)
|
||||
for i, sig := range cSet.Signatures {
|
||||
signature, err := blst.SignatureFromBytes(sig)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get signature from bytes")
|
||||
}
|
||||
if !signature.Verify(cSet.PublicKeys[i], cSet.Messages[i][:]) {
|
||||
logrus.Warning("removing BLSToExecutionChange with invalid signature from pool")
|
||||
if err := p.MarkIncluded(result[i]); err != nil {
|
||||
return nil, errors.Wrap(err, "could not mark BLSToExecutionChange as included")
|
||||
}
|
||||
} else {
|
||||
verified = append(verified, result[i])
|
||||
}
|
||||
}
|
||||
return verified, nil
|
||||
}
|
||||
|
||||
// InsertBLSToExecChange inserts an object into the pool.
|
||||
|
||||
@@ -3,8 +3,15 @@ package blstoexec
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
|
||||
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/bls/common"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
||||
eth "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
@@ -36,42 +43,89 @@ func TestPendingBLSToExecChanges(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBLSToExecChangesForInclusion(t *testing.T) {
|
||||
spb := ð.BeaconStateCapella{
|
||||
Fork: ð.Fork{
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
}
|
||||
numValidators := 2 * params.BeaconConfig().MaxBlsToExecutionChanges
|
||||
validators := make([]*eth.Validator, numValidators)
|
||||
blsChanges := make([]*eth.BLSToExecutionChange, numValidators)
|
||||
spb.Balances = make([]uint64, numValidators)
|
||||
privKeys := make([]common.SecretKey, numValidators)
|
||||
maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance
|
||||
executionAddress := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13}
|
||||
|
||||
for i := range validators {
|
||||
v := ð.Validator{}
|
||||
v.EffectiveBalance = maxEffectiveBalance
|
||||
v.WithdrawableEpoch = params.BeaconConfig().FarFutureEpoch
|
||||
v.WithdrawalCredentials = make([]byte, 32)
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
privKeys[i] = priv
|
||||
pubkey := priv.PublicKey().Marshal()
|
||||
|
||||
message := ð.BLSToExecutionChange{
|
||||
ToExecutionAddress: executionAddress,
|
||||
ValidatorIndex: types.ValidatorIndex(i),
|
||||
FromBlsPubkey: pubkey,
|
||||
}
|
||||
|
||||
hashFn := ssz.NewHasherFunc(hash.CustomSHA256Hasher())
|
||||
digest := hashFn.Hash(pubkey)
|
||||
digest[0] = params.BeaconConfig().BLSWithdrawalPrefixByte
|
||||
copy(v.WithdrawalCredentials, digest[:])
|
||||
validators[i] = v
|
||||
blsChanges[i] = message
|
||||
}
|
||||
spb.Validators = validators
|
||||
st, err := state_native.InitializeFromProtoCapella(spb)
|
||||
require.NoError(t, err)
|
||||
|
||||
signedChanges := make([]*eth.SignedBLSToExecutionChange, numValidators)
|
||||
for i, message := range blsChanges {
|
||||
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, privKeys[i])
|
||||
require.NoError(t, err)
|
||||
|
||||
signed := ð.SignedBLSToExecutionChange{
|
||||
Message: message,
|
||||
Signature: signature,
|
||||
}
|
||||
signedChanges[i] = signed
|
||||
}
|
||||
|
||||
t.Run("empty pool", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges-1; i++ {
|
||||
pool.InsertBLSToExecChange(ð.SignedBLSToExecutionChange{
|
||||
Message: ð.BLSToExecutionChange{
|
||||
ValidatorIndex: types.ValidatorIndex(i),
|
||||
},
|
||||
})
|
||||
}
|
||||
changes, err := pool.BLSToExecChangesForInclusion()
|
||||
changes, err := pool.BLSToExecChangesForInclusion(st)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges-1), len(changes))
|
||||
assert.Equal(t, 0, len(changes))
|
||||
})
|
||||
t.Run("Less than MaxBlsToExecutionChanges in pool", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges-1; i++ {
|
||||
pool.InsertBLSToExecChange(signedChanges[i])
|
||||
}
|
||||
changes, err := pool.BLSToExecChangesForInclusion(st)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges)-1, len(changes))
|
||||
})
|
||||
t.Run("MaxBlsToExecutionChanges in pool", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges; i++ {
|
||||
pool.InsertBLSToExecChange(ð.SignedBLSToExecutionChange{
|
||||
Message: ð.BLSToExecutionChange{
|
||||
ValidatorIndex: types.ValidatorIndex(i),
|
||||
},
|
||||
})
|
||||
pool.InsertBLSToExecChange(signedChanges[i])
|
||||
}
|
||||
changes, err := pool.BLSToExecChangesForInclusion()
|
||||
changes, err := pool.BLSToExecChangesForInclusion(st)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
|
||||
})
|
||||
t.Run("more than MaxBlsToExecutionChanges in pool", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges+1; i++ {
|
||||
pool.InsertBLSToExecChange(ð.SignedBLSToExecutionChange{
|
||||
Message: ð.BLSToExecutionChange{
|
||||
ValidatorIndex: types.ValidatorIndex(i),
|
||||
},
|
||||
})
|
||||
for i := uint64(0); i < numValidators; i++ {
|
||||
pool.InsertBLSToExecChange(signedChanges[i])
|
||||
}
|
||||
changes, err := pool.BLSToExecChangesForInclusion()
|
||||
changes, err := pool.BLSToExecChangesForInclusion(st)
|
||||
require.NoError(t, err)
|
||||
// We want FIFO semantics, which means validator with index 16 shouldn't be returned
|
||||
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
|
||||
@@ -79,6 +133,28 @@ func TestBLSToExecChangesForInclusion(t *testing.T) {
|
||||
assert.NotEqual(t, types.ValidatorIndex(16), ch.Message.ValidatorIndex)
|
||||
}
|
||||
})
|
||||
t.Run("One Bad change", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
signedChanges[1].Message.FromBlsPubkey[5] = 0xff
|
||||
for i := uint64(0); i < numValidators; i++ {
|
||||
pool.InsertBLSToExecChange(signedChanges[i])
|
||||
}
|
||||
changes, err := pool.BLSToExecChangesForInclusion(st)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
|
||||
assert.Equal(t, types.ValidatorIndex(2), changes[1].Message.ValidatorIndex)
|
||||
})
|
||||
t.Run("One Bad Signature", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
copy(signedChanges[1].Signature, signedChanges[2].Signature)
|
||||
for i := uint64(0); i < numValidators; i++ {
|
||||
pool.InsertBLSToExecChange(signedChanges[i])
|
||||
}
|
||||
changes, err := pool.BLSToExecChangesForInclusion(st)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges)-1, len(changes))
|
||||
assert.Equal(t, types.ValidatorIndex(2), changes[1].Message.ValidatorIndex)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInsertBLSToExecChange(t *testing.T) {
|
||||
|
||||
@@ -19,6 +19,7 @@ go_library(
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/execution:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
|
||||
@@ -64,6 +64,19 @@ func handleGetBeaconBlockSSZV2(m *apimiddleware.ApiProxyMiddleware, endpoint api
|
||||
return handleGetSSZ(m, endpoint, w, req, config)
|
||||
}
|
||||
|
||||
func handleGetBlindedBeaconBlockSSZ(
|
||||
m *apimiddleware.ApiProxyMiddleware,
|
||||
endpoint apimiddleware.Endpoint,
|
||||
w http.ResponseWriter,
|
||||
req *http.Request,
|
||||
) (handled bool) {
|
||||
config := sszConfig{
|
||||
fileName: "beacon_block.ssz",
|
||||
responseJson: &VersionedSSZResponseJson{},
|
||||
}
|
||||
return handleGetSSZ(m, endpoint, w, req, config)
|
||||
}
|
||||
|
||||
func handleSubmitBlockSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
return handlePostSSZ(m, endpoint, w, req)
|
||||
}
|
||||
|
||||
@@ -233,11 +233,21 @@ type bellatrixPublishBlockRequestJson struct {
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type capellaPublishBlockRequestJson struct {
|
||||
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type bellatrixPublishBlindedBlockRequestJson struct {
|
||||
BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type capellaPublishBlindedBlockRequestJson struct {
|
||||
CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
// setInitialPublishBlockPostRequest is triggered before we deserialize the request JSON into a struct.
|
||||
// We don't know which version of the block got posted, but we can determine it from the slot.
|
||||
// We know that blocks of all versions have a Message field with a Slot field,
|
||||
@@ -269,8 +279,10 @@ func setInitialPublishBlockPostRequest(endpoint *apimiddleware.Endpoint,
|
||||
endpoint.PostRequest = &SignedBeaconBlockContainerJson{}
|
||||
} else if currentEpoch < params.BeaconConfig().BellatrixForkEpoch {
|
||||
endpoint.PostRequest = &SignedBeaconBlockAltairContainerJson{}
|
||||
} else {
|
||||
} else if currentEpoch < params.BeaconConfig().CapellaForkEpoch {
|
||||
endpoint.PostRequest = &SignedBeaconBlockBellatrixContainerJson{}
|
||||
} else {
|
||||
endpoint.PostRequest = &SignedBeaconBlockCapellaContainerJson{}
|
||||
}
|
||||
req.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||
return true, nil
|
||||
@@ -308,6 +320,15 @@ func preparePublishedBlock(endpoint *apimiddleware.Endpoint, _ http.ResponseWrit
|
||||
endpoint.PostRequest = actualPostReq
|
||||
return nil
|
||||
}
|
||||
if block, ok := endpoint.PostRequest.(*SignedBeaconBlockCapellaContainerJson); ok {
|
||||
// Prepare post request that can be properly decoded on gRPC side.
|
||||
actualPostReq := &capellaPublishBlockRequestJson{
|
||||
CapellaBlock: block.Message,
|
||||
Signature: block.Signature,
|
||||
}
|
||||
endpoint.PostRequest = actualPostReq
|
||||
return nil
|
||||
}
|
||||
return apimiddleware.InternalServerError(errors.New("unsupported block type"))
|
||||
}
|
||||
|
||||
@@ -342,8 +363,10 @@ func setInitialPublishBlindedBlockPostRequest(endpoint *apimiddleware.Endpoint,
|
||||
endpoint.PostRequest = &SignedBeaconBlockContainerJson{}
|
||||
} else if currentEpoch < params.BeaconConfig().BellatrixForkEpoch {
|
||||
endpoint.PostRequest = &SignedBeaconBlockAltairContainerJson{}
|
||||
} else {
|
||||
} else if currentEpoch < params.BeaconConfig().CapellaForkEpoch {
|
||||
endpoint.PostRequest = &SignedBlindedBeaconBlockBellatrixContainerJson{}
|
||||
} else {
|
||||
endpoint.PostRequest = &SignedBlindedBeaconBlockCapellaContainerJson{}
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
|
||||
return true, nil
|
||||
@@ -381,6 +404,15 @@ func preparePublishedBlindedBlock(endpoint *apimiddleware.Endpoint, _ http.Respo
|
||||
endpoint.PostRequest = actualPostReq
|
||||
return nil
|
||||
}
|
||||
if block, ok := endpoint.PostRequest.(*SignedBlindedBeaconBlockCapellaContainerJson); ok {
|
||||
// Prepare post request that can be properly decoded on gRPC side.
|
||||
actualPostReq := &capellaPublishBlindedBlockRequestJson{
|
||||
CapellaBlock: block.Message,
|
||||
Signature: block.Signature,
|
||||
}
|
||||
endpoint.PostRequest = actualPostReq
|
||||
return nil
|
||||
}
|
||||
return apimiddleware.InternalServerError(errors.New("unsupported block type"))
|
||||
}
|
||||
|
||||
@@ -439,6 +471,12 @@ type bellatrixBlockResponseJson struct {
|
||||
ExecutionOptimistic bool `json:"execution_optimistic"`
|
||||
}
|
||||
|
||||
type capellaBlockResponseJson struct {
|
||||
Version string `json:"version"`
|
||||
Data *SignedBeaconBlockCapellaContainerJson `json:"data"`
|
||||
ExecutionOptimistic bool `json:"execution_optimistic"`
|
||||
}
|
||||
|
||||
type bellatrixBlindedBlockResponseJson struct {
|
||||
Version string `json:"version"`
|
||||
Data *SignedBlindedBeaconBlockBellatrixContainerJson `json:"data"`
|
||||
@@ -486,6 +524,15 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a
|
||||
},
|
||||
ExecutionOptimistic: respContainer.ExecutionOptimistic,
|
||||
}
|
||||
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_CAPELLA.String())):
|
||||
actualRespContainer = &capellaBlockResponseJson{
|
||||
Version: respContainer.Version,
|
||||
Data: &SignedBeaconBlockCapellaContainerJson{
|
||||
Message: respContainer.Data.CapellaBlock,
|
||||
Signature: respContainer.Data.Signature,
|
||||
},
|
||||
ExecutionOptimistic: respContainer.ExecutionOptimistic,
|
||||
}
|
||||
default:
|
||||
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ func (_ *BeaconEndpointFactory) Paths() []string {
|
||||
"/eth/v1/beacon/pool/attester_slashings",
|
||||
"/eth/v1/beacon/pool/proposer_slashings",
|
||||
"/eth/v1/beacon/pool/voluntary_exits",
|
||||
"/eth/v1/beacon/pool/bls_to_execution_changes",
|
||||
"/eth/v1/beacon/pool/sync_committees",
|
||||
"/eth/v1/beacon/weak_subjectivity",
|
||||
"/eth/v1/node/identity",
|
||||
@@ -143,6 +144,7 @@ func (_ *BeaconEndpointFactory) Create(path string) (*apimiddleware.Endpoint, er
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreSerializeMiddlewareResponseIntoJson: serializeBlindedBlock,
|
||||
}
|
||||
endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleGetBlindedBeaconBlockSSZ}
|
||||
case "/eth/v1/beacon/pool/attestations":
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "slot"}, {Name: "committee_index"}}
|
||||
endpoint.GetResponse = &AttestationsPoolResponseJson{}
|
||||
@@ -160,6 +162,8 @@ func (_ *BeaconEndpointFactory) Create(path string) (*apimiddleware.Endpoint, er
|
||||
case "/eth/v1/beacon/pool/voluntary_exits":
|
||||
endpoint.PostRequest = &SignedVoluntaryExitJson{}
|
||||
endpoint.GetResponse = &VoluntaryExitsPoolResponseJson{}
|
||||
case "/eth/v1/beacon/pool/bls_to_execution_changes":
|
||||
endpoint.PostRequest = &SignedBLSToExecutionChangeJson{}
|
||||
case "/eth/v1/beacon/pool/sync_committees":
|
||||
endpoint.PostRequest = &SubmitSyncCommitteeSignaturesRequestJson{}
|
||||
endpoint.Err = &IndexedVerificationFailureErrorJson{}
|
||||
|
||||
@@ -374,6 +374,7 @@ type SignedBeaconBlockContainerV2Json struct {
|
||||
Phase0Block *BeaconBlockJson `json:"phase0_block"`
|
||||
AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
|
||||
BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
@@ -389,12 +390,14 @@ type BeaconBlockContainerV2Json struct {
|
||||
Phase0Block *BeaconBlockJson `json:"phase0_block"`
|
||||
AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
|
||||
BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockContainerJson struct {
|
||||
Phase0Block *BeaconBlockJson `json:"phase0_block"`
|
||||
AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
|
||||
BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"`
|
||||
}
|
||||
|
||||
type SignedBeaconBlockAltairContainerJson struct {
|
||||
@@ -407,6 +410,11 @@ type SignedBeaconBlockBellatrixContainerJson struct {
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type SignedBeaconBlockCapellaContainerJson struct {
|
||||
Message *BeaconBlockCapellaJson `json:"message"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type SignedBlindedBeaconBlockBellatrixContainerJson struct {
|
||||
Message *BlindedBeaconBlockBellatrixJson `json:"message"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
@@ -433,6 +441,14 @@ type BeaconBlockBellatrixJson struct {
|
||||
Body *BeaconBlockBodyBellatrixJson `json:"body"`
|
||||
}
|
||||
|
||||
type BeaconBlockCapellaJson struct {
|
||||
Slot string `json:"slot"`
|
||||
ProposerIndex string `json:"proposer_index"`
|
||||
ParentRoot string `json:"parent_root" hex:"true"`
|
||||
StateRoot string `json:"state_root" hex:"true"`
|
||||
Body *BeaconBlockBodyCapellaJson `json:"body"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockBellatrixJson struct {
|
||||
Slot string `json:"slot"`
|
||||
ProposerIndex string `json:"proposer_index"`
|
||||
@@ -474,6 +490,20 @@ type BeaconBlockBodyBellatrixJson struct {
|
||||
ExecutionPayload *ExecutionPayloadJson `json:"execution_payload"`
|
||||
}
|
||||
|
||||
type BeaconBlockBodyCapellaJson struct {
|
||||
RandaoReveal string `json:"randao_reveal" hex:"true"`
|
||||
Eth1Data *Eth1DataJson `json:"eth1_data"`
|
||||
Graffiti string `json:"graffiti" hex:"true"`
|
||||
ProposerSlashings []*ProposerSlashingJson `json:"proposer_slashings"`
|
||||
AttesterSlashings []*AttesterSlashingJson `json:"attester_slashings"`
|
||||
Attestations []*AttestationJson `json:"attestations"`
|
||||
Deposits []*DepositJson `json:"deposits"`
|
||||
VoluntaryExits []*SignedVoluntaryExitJson `json:"voluntary_exits"`
|
||||
SyncAggregate *SyncAggregateJson `json:"sync_aggregate"`
|
||||
ExecutionPayload *ExecutionPayloadCapellaJson `json:"execution_payload"`
|
||||
BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockBodyBellatrixJson struct {
|
||||
RandaoReveal string `json:"randao_reveal" hex:"true"`
|
||||
Eth1Data *Eth1DataJson `json:"eth1_data"`
|
||||
@@ -498,7 +528,7 @@ type BlindedBeaconBlockBodyCapellaJson struct {
|
||||
VoluntaryExits []*SignedVoluntaryExitJson `json:"voluntary_exits"`
|
||||
SyncAggregate *SyncAggregateJson `json:"sync_aggregate"`
|
||||
ExecutionPayloadHeader *ExecutionPayloadHeaderCapellaJson `json:"execution_payload_header"`
|
||||
BLSToExecutionChanges []*BLSToExecutionChangeJson `json:"bls_to_execution_changes"`
|
||||
BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"`
|
||||
}
|
||||
|
||||
type ExecutionPayloadJson struct {
|
||||
@@ -518,6 +548,24 @@ type ExecutionPayloadJson struct {
|
||||
Transactions []string `json:"transactions" hex:"true"`
|
||||
}
|
||||
|
||||
type ExecutionPayloadCapellaJson struct {
|
||||
ParentHash string `json:"parent_hash" hex:"true"`
|
||||
FeeRecipient string `json:"fee_recipient" hex:"true"`
|
||||
StateRoot string `json:"state_root" hex:"true"`
|
||||
ReceiptsRoot string `json:"receipts_root" hex:"true"`
|
||||
LogsBloom string `json:"logs_bloom" hex:"true"`
|
||||
PrevRandao string `json:"prev_randao" hex:"true"`
|
||||
BlockNumber string `json:"block_number"`
|
||||
GasLimit string `json:"gas_limit"`
|
||||
GasUsed string `json:"gas_used"`
|
||||
TimeStamp string `json:"timestamp"`
|
||||
ExtraData string `json:"extra_data" hex:"true"`
|
||||
BaseFeePerGas string `json:"base_fee_per_gas" uint256:"true"`
|
||||
BlockHash string `json:"block_hash" hex:"true"`
|
||||
Transactions []string `json:"transactions" hex:"true"`
|
||||
Withdrawals []*WithdrawalJson `json:"withdrawals"`
|
||||
}
|
||||
|
||||
type ExecutionPayloadHeaderJson struct {
|
||||
ParentHash string `json:"parent_hash" hex:"true"`
|
||||
FeeRecipient string `json:"fee_recipient" hex:"true"`
|
||||
@@ -629,6 +677,11 @@ type BLSToExecutionChangeJson struct {
|
||||
ToExecutionAddress string `json:"to_execution_address" hex:"true"`
|
||||
}
|
||||
|
||||
type SignedBLSToExecutionChangeJson struct {
|
||||
BLSToExecutionChange *BLSToExecutionChangeJson `json:"message"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type DepositJson struct {
|
||||
Proof []string `json:"proof" hex:"true"`
|
||||
Data *Deposit_DataJson `json:"data"`
|
||||
@@ -683,6 +736,13 @@ type VersionJson struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type WithdrawalJson struct {
|
||||
WithdrawalIndex string `json:"index"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
ExecutionAddress string `json:"address" hex:"true"`
|
||||
Amount string `json:"amount"`
|
||||
}
|
||||
|
||||
type BeaconStateJson struct {
|
||||
GenesisTime string `json:"genesis_time"`
|
||||
GenesisValidatorsRoot string `json:"genesis_validators_root" hex:"true"`
|
||||
|
||||
@@ -29,6 +29,7 @@ go_library(
|
||||
"//beacon-chain/db/filters:go_default_library",
|
||||
"//beacon-chain/execution:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
@@ -106,6 +107,7 @@ go_test(
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
|
||||
@@ -4,14 +4,20 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz/detect"
|
||||
"github.com/prysmaticlabs/prysm/v3/network/forks"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/v3/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/v3/proto/migration"
|
||||
eth "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// GetBlindedBlock retrieves blinded block for given block id.
|
||||
@@ -61,6 +67,159 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest
|
||||
return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk)
|
||||
}
|
||||
|
||||
// GetBlindedBlockSSZ returns the SSZ-serialized version of the blinded beacon block for given block id.
|
||||
func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequest) (*ethpbv2.SSZContainer, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlockSSZ")
|
||||
defer span.End()
|
||||
|
||||
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
|
||||
err = handleGetBlockError(blk, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := getSSZBlockPhase0(blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
result, err = getSSZBlockAltair(blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
result, err = bs.getBlindedSSZBlockBellatrix(ctx, blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
result, err = bs.getBlindedSSZBlockCapella(ctx, blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk)
|
||||
}
|
||||
|
||||
// SubmitBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct
|
||||
// and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`.
|
||||
// The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network,
|
||||
// to be included in the beacon chain. The beacon node is not required to validate the signed
|
||||
// `BeaconBlock`, and a successful response (20X) only indicates that the broadcast has been
|
||||
// successful. The beacon node is expected to integrate the new block into its state, and
|
||||
// therefore validate the block internally, however blocks which fail the validation are still
|
||||
// broadcast but a different status code is returned (202).
|
||||
func (bs *Server) SubmitBlindedBlock(ctx context.Context, req *ethpbv2.SignedBlindedBeaconBlockContainer) (*emptypb.Empty, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.SubmitBlindedBlock")
|
||||
defer span.End()
|
||||
|
||||
capellaBlkContainer, ok := req.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_CapellaBlock)
|
||||
if ok {
|
||||
if err := bs.submitBlindedCapellaBlock(ctx, capellaBlkContainer.CapellaBlock, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
bellatrixBlkContainer, ok := req.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock)
|
||||
if ok {
|
||||
if err := bs.submitBlindedBellatrixBlock(ctx, bellatrixBlkContainer.BellatrixBlock, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// At the end we check forks that don't have blinded blocks.
|
||||
phase0BlkContainer, ok := req.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_Phase0Block)
|
||||
if ok {
|
||||
if err := bs.submitPhase0Block(ctx, phase0BlkContainer.Phase0Block, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
altairBlkContainer, ok := req.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_AltairBlock)
|
||||
if ok {
|
||||
if err := bs.submitAltairBlock(ctx, altairBlkContainer.AltairBlock, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// SubmitBlindedBlockSSZ instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct
|
||||
// and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`.
|
||||
// The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network,
|
||||
// to be included in the beacon chain. The beacon node is not required to validate the signed
|
||||
// `BeaconBlock`, and a successful response (20X) only indicates that the broadcast has been
|
||||
// successful. The beacon node is expected to integrate the new block into its state, and
|
||||
// therefore validate the block internally, however blocks which fail the validation are still
|
||||
// broadcast but a different status code is returned (202).
|
||||
//
|
||||
// The provided block must be SSZ-serialized.
|
||||
func (bs *Server) SubmitBlindedBlockSSZ(ctx context.Context, req *ethpbv2.SSZContainer) (*emptypb.Empty, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.SubmitBlindedBlockSSZ")
|
||||
defer span.End()
|
||||
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read"+versionHeader+" header")
|
||||
}
|
||||
ver := md.Get(versionHeader)
|
||||
if len(ver) == 0 {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read"+versionHeader+" header")
|
||||
}
|
||||
schedule := forks.NewOrderedSchedule(params.BeaconConfig())
|
||||
forkVer, err := schedule.VersionForName(ver[0])
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not determine fork version: %v", err)
|
||||
}
|
||||
unmarshaler, err := detect.FromForkVersion(forkVer)
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not create unmarshaler: %v", err)
|
||||
}
|
||||
block, err := unmarshaler.UnmarshalBlindedBeaconBlock(req.Data)
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not unmarshal request data into block: %v", err)
|
||||
}
|
||||
|
||||
if block.IsBlinded() {
|
||||
b, err := block.PbBlindedBellatrixBlock()
|
||||
if err != nil {
|
||||
b, err := block.PbBlindedCapellaBlock()
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not get blinded block: %v", err)
|
||||
}
|
||||
bb, err := migration.V1Alpha1BeaconBlockBlindedCapellaToV2Blinded(b.Block)
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not migrate block: %v", err)
|
||||
}
|
||||
return &emptypb.Empty{}, bs.submitBlindedCapellaBlock(ctx, bb, b.Signature)
|
||||
}
|
||||
bb, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(b.Block)
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not migrate block: %v", err)
|
||||
}
|
||||
return &emptypb.Empty{}, bs.submitBlindedBellatrixBlock(ctx, bb, b.Signature)
|
||||
}
|
||||
|
||||
root, err := block.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not compute block's hash tree root: %v", err)
|
||||
}
|
||||
return &emptypb.Empty{}, bs.submitBlock(ctx, root, block)
|
||||
}
|
||||
|
||||
func getBlindedBlockPhase0(blk interfaces.SignedBeaconBlock) (*ethpbv2.BlindedBlockResponse, error) {
|
||||
phase0Blk, err := blk.PbPhase0Block()
|
||||
if err != nil {
|
||||
@@ -209,6 +368,7 @@ func (bs *Server) getBlindedBlockCapella(ctx context.Context, blk interfaces.Sig
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if capellaBlk == nil {
|
||||
@@ -244,3 +404,191 @@ func (bs *Server) getBlindedBlockCapella(ctx context.Context, blk interfaces.Sig
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) getBlindedSSZBlockBellatrix(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
|
||||
bellatrixBlk, err := blk.PbBellatrixBlock()
|
||||
if err != nil {
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
if blindedBellatrixBlk, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||
if blindedBellatrixBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(blindedBellatrixBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBlindedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Data: sszData,
|
||||
}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if bellatrixBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
blindedBlkInterface, err := blk.ToBlinded()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert block to blinded block")
|
||||
}
|
||||
blindedBellatrixBlock, err := blindedBlkInterface.PbBlindedBellatrixBlock()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(blindedBellatrixBlock.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBlindedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_BELLATRIX, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) getBlindedSSZBlockCapella(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
|
||||
capellaBlk, err := blk.PbCapellaBlock()
|
||||
if err != nil {
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
if blindedCapellaBlk, err := blk.PbBlindedCapellaBlock(); err == nil {
|
||||
if blindedCapellaBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBlindedCapellaToV2Blinded(blindedCapellaBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBlindedBeaconBlockCapella{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{
|
||||
Version: ethpbv2.Version_CAPELLA,
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Data: sszData,
|
||||
}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if capellaBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
blindedBlkInterface, err := blk.ToBlinded()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert block to blinded block")
|
||||
}
|
||||
blindedCapellaBlock, err := blindedBlkInterface.PbBlindedCapellaBlock()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBlindedCapellaToV2Blinded(blindedCapellaBlock.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBlindedBeaconBlockCapella{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_CAPELLA, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) submitBlindedBellatrixBlock(ctx context.Context, blindedBellatrixBlk *ethpbv2.BlindedBeaconBlockBellatrix, sig []byte) error {
|
||||
b, err := migration.BlindedBellatrixToV1Alpha1SignedBlock(ðpbv2.SignedBlindedBeaconBlockBellatrix{
|
||||
Message: blindedBellatrixBlk,
|
||||
Signature: sig,
|
||||
})
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get blinded block: %v", err)
|
||||
}
|
||||
_, err = bs.V1Alpha1ValidatorServer.ProposeBeaconBlock(ctx, ð.GenericSignedBeaconBlock{
|
||||
Block: ð.GenericSignedBeaconBlock_BlindedBellatrix{
|
||||
BlindedBellatrix: b,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not propose blinded block: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs *Server) submitBlindedCapellaBlock(ctx context.Context, blindedCapellaBlk *ethpbv2.BlindedBeaconBlockCapella, sig []byte) error {
|
||||
b, err := migration.BlindedCapellaToV1Alpha1SignedBlock(ðpbv2.SignedBlindedBeaconBlockCapella{
|
||||
Message: blindedCapellaBlk,
|
||||
Signature: sig,
|
||||
})
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get blinded block: %v", err)
|
||||
}
|
||||
_, err = bs.V1Alpha1ValidatorServer.ProposeBeaconBlock(ctx, ð.GenericSignedBeaconBlock{
|
||||
Block: ð.GenericSignedBeaconBlock_BlindedCapella{
|
||||
BlindedCapella: b,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not propose blinded block: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,10 +7,17 @@ import (
|
||||
"testing"
|
||||
|
||||
mock "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing"
|
||||
builderTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder/testing"
|
||||
dbTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/testing"
|
||||
executionTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
mockp2p "github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p/testing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/prysm/v1alpha1/validator"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/v3/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
||||
@@ -19,6 +26,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/util"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
func TestServer_GetBlindedBlock(t *testing.T) {
|
||||
@@ -592,3 +600,555 @@ func TestServer_GetBlindedBlock(t *testing.T) {
|
||||
assert.Equal(t, true, blk.ExecutionOptimistic)
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_GetBlindedBlockSSZ(t *testing.T) {
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
|
||||
b2 := util.NewBeaconBlock()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
|
||||
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
|
||||
require.NoError(t, err)
|
||||
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
ChainInfoFetcher: &mock.ChainService{
|
||||
DB: beaconDB,
|
||||
Block: wsb,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
},
|
||||
}
|
||||
|
||||
blks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{BlockId: []byte("30")})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version)
|
||||
})
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB)
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
|
||||
b2 := util.NewBeaconBlockAltair()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
|
||||
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock())
|
||||
require.NoError(t, err)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
ChainInfoFetcher: &mock.ChainService{
|
||||
DB: beaconDB,
|
||||
Block: chainBlk,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
},
|
||||
}
|
||||
|
||||
blks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{BlockId: []byte("30")})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version)
|
||||
})
|
||||
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB)
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
|
||||
b2 := util.NewBlindedBeaconBlockBellatrix()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
|
||||
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock())
|
||||
require.NoError(t, err)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
ChainInfoFetcher: &mock.ChainService{
|
||||
DB: beaconDB,
|
||||
Block: chainBlk,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
},
|
||||
OptimisticModeFetcher: &mock.ChainService{},
|
||||
}
|
||||
|
||||
blks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{BlockId: []byte("30")})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version)
|
||||
})
|
||||
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, blkContainers := fillDBTestBlocksCapellaBlinded(ctx, t, beaconDB)
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
|
||||
b2 := util.NewBlindedBeaconBlockCapella()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
|
||||
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedCapellaBlock())
|
||||
require.NoError(t, err)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
ChainInfoFetcher: &mock.ChainService{
|
||||
DB: beaconDB,
|
||||
Block: chainBlk,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
},
|
||||
OptimisticModeFetcher: &mock.ChainService{},
|
||||
}
|
||||
|
||||
blks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{BlockId: []byte("30")})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version)
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlock()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
}
|
||||
req := util.NewBeaconBlock()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockSsz, err := req.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
blockReq := ðpbv2.SSZContainer{
|
||||
Data: blockSsz,
|
||||
}
|
||||
md := metadata.MD{}
|
||||
md.Set(versionHeader, "phase0")
|
||||
sszCtx := metadata.NewIncomingContext(ctx, md)
|
||||
_, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockAltair()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
}
|
||||
req := util.NewBeaconBlockAltair()
|
||||
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().AltairForkEpoch))
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockSsz, err := req.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
blockReq := ðpbv2.SSZContainer{
|
||||
Data: blockSsz,
|
||||
}
|
||||
md := metadata.MD{}
|
||||
md.Set(versionHeader, "altair")
|
||||
sszCtx := metadata.NewIncomingContext(ctx, md)
|
||||
_, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
// INFO: This code block can be removed once Bellatrix
|
||||
// fork epoch is set to a value other than math.MaxUint64
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.BellatrixForkEpoch = cfg.AltairForkEpoch + 1000
|
||||
cfg.ForkVersionSchedule[bytesutil.ToBytes4(cfg.BellatrixForkVersion)] = cfg.AltairForkEpoch + 1000
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockBellatrix()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
alphaServer := &validator.Server{
|
||||
SyncCommitteePool: synccommittee.NewStore(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BlockBuilder: &builderTest.MockBuilderService{},
|
||||
BlockReceiver: c,
|
||||
BlockNotifier: &mock.MockBlockNotifier{},
|
||||
}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
V1Alpha1ValidatorServer: alphaServer,
|
||||
}
|
||||
req := util.NewBlindedBeaconBlockBellatrix()
|
||||
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().BellatrixForkEpoch))
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockSsz, err := req.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
blockReq := ðpbv2.SSZContainer{
|
||||
Data: blockSsz,
|
||||
}
|
||||
md := metadata.MD{}
|
||||
md.Set(versionHeader, "bellatrix")
|
||||
sszCtx := metadata.NewIncomingContext(ctx, md)
|
||||
_, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
t.Skip("This test needs Capella fork version configured properly")
|
||||
|
||||
// INFO: This code block can be removed once Capella
|
||||
// fork epoch is set to a value other than math.MaxUint64
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.CapellaForkEpoch = cfg.BellatrixForkEpoch + 1000
|
||||
cfg.ForkVersionSchedule[bytesutil.ToBytes4(cfg.CapellaForkVersion)] = cfg.BellatrixForkEpoch + 1000
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockCapella()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
alphaServer := &validator.Server{
|
||||
SyncCommitteePool: synccommittee.NewStore(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BlockBuilder: &builderTest.MockBuilderService{},
|
||||
BlockReceiver: c,
|
||||
BlockNotifier: &mock.MockBlockNotifier{},
|
||||
}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
V1Alpha1ValidatorServer: alphaServer,
|
||||
}
|
||||
req := util.NewBlindedBeaconBlockCapella()
|
||||
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().CapellaForkEpoch))
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockSsz, err := req.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
blockReq := ðpbv2.SSZContainer{
|
||||
Data: blockSsz,
|
||||
}
|
||||
md := metadata.MD{}
|
||||
md.Set(versionHeader, "capella")
|
||||
sszCtx := metadata.NewIncomingContext(ctx, md)
|
||||
_, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
}
|
||||
|
||||
func TestSubmitBlindedBlock(t *testing.T) {
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlock()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
}
|
||||
req := util.NewBeaconBlock()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
v1Block, err := migration.V1Alpha1ToV1SignedBlock(req)
|
||||
require.NoError(t, err)
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockReq := ðpbv2.SignedBlindedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBlindedBeaconBlockContainer_Phase0Block{Phase0Block: v1Block.Block},
|
||||
Signature: v1Block.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlindedBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockAltair()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
}
|
||||
req := util.NewBeaconBlockAltair()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
v2Block, err := migration.V1Alpha1BeaconBlockAltairToV2(req.Block)
|
||||
require.NoError(t, err)
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockReq := ðpbv2.SignedBlindedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBlindedBeaconBlockContainer_AltairBlock{AltairBlock: v2Block},
|
||||
Signature: req.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlindedBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
transactions := [][]byte{[]byte("transaction1"), []byte("transaction2")}
|
||||
transactionsRoot, err := ssz.TransactionsRoot(transactions)
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockBellatrix()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
alphaServer := &validator.Server{
|
||||
SyncCommitteePool: synccommittee.NewStore(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BlockBuilder: &builderTest.MockBuilderService{},
|
||||
BlockReceiver: c,
|
||||
BlockNotifier: &mock.MockBlockNotifier{},
|
||||
}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
V1Alpha1ValidatorServer: alphaServer,
|
||||
}
|
||||
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Slot = 5
|
||||
blk.Block.ParentRoot = bsRoot[:]
|
||||
blk.Block.Body.ExecutionPayload.Transactions = transactions
|
||||
blindedBlk := util.NewBlindedBeaconBlockBellatrixV2()
|
||||
blindedBlk.Message.Slot = 5
|
||||
blindedBlk.Message.ParentRoot = bsRoot[:]
|
||||
blindedBlk.Message.Body.ExecutionPayloadHeader.TransactionsRoot = transactionsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, blk)
|
||||
|
||||
blockReq := ðpbv2.SignedBlindedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock{BellatrixBlock: blindedBlk.Message},
|
||||
Signature: blindedBlk.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlindedBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
transactions := [][]byte{[]byte("transaction1"), []byte("transaction2")}
|
||||
transactionsRoot, err := ssz.TransactionsRoot(transactions)
|
||||
require.NoError(t, err)
|
||||
|
||||
withdrawals := []*enginev1.Withdrawal{
|
||||
{
|
||||
Index: 1,
|
||||
ValidatorIndex: 1,
|
||||
Address: bytesutil.PadTo([]byte("address1"), 20),
|
||||
Amount: 1,
|
||||
},
|
||||
{
|
||||
Index: 2,
|
||||
ValidatorIndex: 2,
|
||||
Address: bytesutil.PadTo([]byte("address2"), 20),
|
||||
Amount: 2,
|
||||
},
|
||||
}
|
||||
withdrawalsRoot, err := ssz.WithdrawalSliceRoot(hash.CustomSHA256Hasher(), withdrawals, 16)
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockCapella()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
alphaServer := &validator.Server{
|
||||
SyncCommitteePool: synccommittee.NewStore(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BlockBuilder: &builderTest.MockBuilderService{},
|
||||
BlockReceiver: c,
|
||||
BlockNotifier: &mock.MockBlockNotifier{},
|
||||
}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
V1Alpha1ValidatorServer: alphaServer,
|
||||
}
|
||||
|
||||
blk := util.NewBeaconBlockCapella()
|
||||
blk.Block.Slot = 5
|
||||
blk.Block.ParentRoot = bsRoot[:]
|
||||
blk.Block.Body.ExecutionPayload.Transactions = transactions
|
||||
blk.Block.Body.ExecutionPayload.Withdrawals = withdrawals
|
||||
blindedBlk := util.NewBlindedBeaconBlockCapellaV2()
|
||||
blindedBlk.Message.Slot = 5
|
||||
blindedBlk.Message.ParentRoot = bsRoot[:]
|
||||
blindedBlk.Message.Body.ExecutionPayloadHeader.TransactionsRoot = transactionsRoot[:]
|
||||
blindedBlk.Message.Body.ExecutionPayloadHeader.WithdrawalsRoot = withdrawalsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, blk)
|
||||
|
||||
blockReq := ðpbv2.SignedBlindedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBlindedBeaconBlockContainer_CapellaBlock{CapellaBlock: blindedBlk.Message},
|
||||
Signature: blindedBlk.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlindedBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/v3/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/v3/proto/migration"
|
||||
eth "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -234,6 +233,12 @@ func (bs *Server) SubmitBlock(ctx context.Context, req *ethpbv2.SignedBeaconBloc
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
capellaBlkContainer, ok := req.Message.(*ethpbv2.SignedBeaconBlockContainer_CapellaBlock)
|
||||
if ok {
|
||||
if err := bs.submitCapellaBlock(ctx, capellaBlkContainer.CapellaBlock, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
@@ -276,97 +281,6 @@ func (bs *Server) SubmitBlockSSZ(ctx context.Context, req *ethpbv2.SSZContainer)
|
||||
return &emptypb.Empty{}, bs.submitBlock(ctx, root, block)
|
||||
}
|
||||
|
||||
// SubmitBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct
|
||||
// and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`.
|
||||
// The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network,
|
||||
// to be included in the beacon chain. The beacon node is not required to validate the signed
|
||||
// `BeaconBlock`, and a successful response (20X) only indicates that the broadcast has been
|
||||
// successful. The beacon node is expected to integrate the new block into its state, and
|
||||
// therefore validate the block internally, however blocks which fail the validation are still
|
||||
// broadcast but a different status code is returned (202).
|
||||
func (bs *Server) SubmitBlindedBlock(ctx context.Context, req *ethpbv2.SignedBlindedBeaconBlockContainer) (*emptypb.Empty, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.SubmitBlindedBlock")
|
||||
defer span.End()
|
||||
|
||||
bellatrixBlkContainer, ok := req.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock)
|
||||
if ok {
|
||||
if err := bs.submitBlindedBellatrixBlock(ctx, bellatrixBlkContainer.BellatrixBlock, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// At the end we check forks that don't have blinded blocks.
|
||||
phase0BlkContainer, ok := req.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_Phase0Block)
|
||||
if ok {
|
||||
if err := bs.submitPhase0Block(ctx, phase0BlkContainer.Phase0Block, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
altairBlkContainer, ok := req.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_AltairBlock)
|
||||
if ok {
|
||||
if err := bs.submitAltairBlock(ctx, altairBlkContainer.AltairBlock, req.Signature); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// SubmitBlindedBlockSSZ instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct
|
||||
// and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`.
|
||||
// The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network,
|
||||
// to be included in the beacon chain. The beacon node is not required to validate the signed
|
||||
// `BeaconBlock`, and a successful response (20X) only indicates that the broadcast has been
|
||||
// successful. The beacon node is expected to integrate the new block into its state, and
|
||||
// therefore validate the block internally, however blocks which fail the validation are still
|
||||
// broadcast but a different status code is returned (202).
|
||||
//
|
||||
// The provided block must be SSZ-serialized.
|
||||
func (bs *Server) SubmitBlindedBlockSSZ(ctx context.Context, req *ethpbv2.SSZContainer) (*emptypb.Empty, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.SubmitBlindedBlockSSZ")
|
||||
defer span.End()
|
||||
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read"+versionHeader+" header")
|
||||
}
|
||||
ver := md.Get(versionHeader)
|
||||
if len(ver) == 0 {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read"+versionHeader+" header")
|
||||
}
|
||||
schedule := forks.NewOrderedSchedule(params.BeaconConfig())
|
||||
forkVer, err := schedule.VersionForName(ver[0])
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not determine fork version: %v", err)
|
||||
}
|
||||
unmarshaler, err := detect.FromForkVersion(forkVer)
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not create unmarshaler: %v", err)
|
||||
}
|
||||
block, err := unmarshaler.UnmarshalBlindedBeaconBlock(req.Data)
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not unmarshal request data into block: %v", err)
|
||||
}
|
||||
|
||||
if block.IsBlinded() {
|
||||
b, err := block.PbBlindedBellatrixBlock()
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not get blinded block: %v", err)
|
||||
}
|
||||
bb, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(b.Block)
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not migrate block: %v", err)
|
||||
}
|
||||
return &emptypb.Empty{}, bs.submitBlindedBellatrixBlock(ctx, bb, b.Signature)
|
||||
}
|
||||
|
||||
root, err := block.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not compute block's hash tree root: %v", err)
|
||||
}
|
||||
return &emptypb.Empty{}, bs.submitBlock(ctx, root, block)
|
||||
}
|
||||
|
||||
// GetBlock retrieves block details for given block ID.
|
||||
func (bs *Server) GetBlock(ctx context.Context, req *ethpbv1.BlockRequest) (*ethpbv1.BlockResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.GetBlock")
|
||||
@@ -423,128 +337,38 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
phase0Blk, err := blk.PbPhase0Block()
|
||||
if err == nil {
|
||||
if phase0Blk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
v1Blk, err := migration.SignedBeaconBlock(blk)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_PHASE0,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_Phase0Block{Phase0Block: v1Blk.Block},
|
||||
Signature: v1Blk.Signature,
|
||||
},
|
||||
ExecutionOptimistic: false,
|
||||
}, nil
|
||||
result, err := getBlockPhase0(blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
altairBlk, err := blk.PbAltairBlock()
|
||||
if err == nil {
|
||||
if altairBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlk.Block)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_ALTAIR,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_AltairBlock{AltairBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: false,
|
||||
}, nil
|
||||
result, err = getBlockAltair(blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
bellatrixBlk, err := blk.PbBellatrixBlock()
|
||||
if err == nil {
|
||||
if bellatrixBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
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)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_BellatrixBlock{BellatrixBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
result, err = bs.getBlockBellatrix(ctx, blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
if blindedBellatrixBlk, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||
if blindedBellatrixBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
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)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_BellatrixBlock{BellatrixBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
result, err = bs.getBlockCapella(ctx, blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk)
|
||||
}
|
||||
|
||||
@@ -559,262 +383,33 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2
|
||||
return nil, err
|
||||
}
|
||||
|
||||
phase0Blk, err := blk.PbPhase0Block()
|
||||
if err == nil {
|
||||
if phase0Blk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
signedBeaconBlock, err := migration.SignedBeaconBlock(blk)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
sszBlock, err := signedBeaconBlock.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_PHASE0, ExecutionOptimistic: false, Data: sszBlock}, nil
|
||||
result, err := getSSZBlockPhase0(blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
altairBlk, err := blk.PbAltairBlock()
|
||||
if err == nil {
|
||||
if altairBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlk.Block)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockAltair{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_ALTAIR, ExecutionOptimistic: false, Data: sszData}, nil
|
||||
result, err = getSSZBlockAltair(blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
bellatrixBlk, err := blk.PbBellatrixBlock()
|
||||
if err == nil {
|
||||
if bellatrixBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
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)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_BELLATRIX, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
|
||||
result, err = bs.getSSZBlockBellatrix(ctx, blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
if blindedBellatrixBlk, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||
if blindedBellatrixBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
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)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Data: sszData,
|
||||
}, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk)
|
||||
}
|
||||
|
||||
// GetBlindedBlockSSZ returns the SSZ-serialized version of the blinded beacon block for given block id.
|
||||
func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequest) (*ethpbv2.SSZContainer, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlockSSZ")
|
||||
defer span.End()
|
||||
|
||||
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
|
||||
err = handleGetBlockError(blk, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
phase0Blk, err := blk.PbPhase0Block()
|
||||
if err == nil {
|
||||
if phase0Blk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
signedBeaconBlock, err := migration.SignedBeaconBlock(blk)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
sszBlock, err := signedBeaconBlock.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_PHASE0, ExecutionOptimistic: false, Data: sszBlock}, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
altairBlk, err := blk.PbAltairBlock()
|
||||
if err == nil {
|
||||
if altairBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlk.Block)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockAltair{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_ALTAIR, ExecutionOptimistic: false, Data: sszData}, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
bellatrixBlk, err := blk.PbBellatrixBlock()
|
||||
if err == nil {
|
||||
if bellatrixBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
blindedBlkInterface, err := blk.ToBlinded()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert block to blinded block: %v", err)
|
||||
}
|
||||
blindedBellatrixBlock, err := blindedBlkInterface.PbBlindedBellatrixBlock()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(blindedBellatrixBlock.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)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBlindedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_BELLATRIX, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||
}
|
||||
|
||||
if blindedBellatrixBlk, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||
if blindedBellatrixBlk == nil {
|
||||
return nil, status.Error(codes.Internal, "Nil block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(blindedBellatrixBlk.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)
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBlindedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
||||
}
|
||||
return ðpbv2.SSZContainer{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Data: sszData,
|
||||
}, nil
|
||||
result, err = bs.getSSZBlockCapella(ctx, blk)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
@@ -1013,6 +608,386 @@ func handleGetBlockError(blk interfaces.SignedBeaconBlock, err error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getBlockPhase0(blk interfaces.SignedBeaconBlock) (*ethpbv2.BlockResponseV2, error) {
|
||||
phase0Blk, err := blk.PbPhase0Block()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if phase0Blk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v1Blk, err := migration.SignedBeaconBlock(blk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_PHASE0,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_Phase0Block{Phase0Block: v1Blk.Block},
|
||||
Signature: v1Blk.Signature,
|
||||
},
|
||||
ExecutionOptimistic: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getBlockAltair(blk interfaces.SignedBeaconBlock) (*ethpbv2.BlockResponseV2, error) {
|
||||
altairBlk, err := blk.PbAltairBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if altairBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_ALTAIR,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_AltairBlock{AltairBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) getBlockBellatrix(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpbv2.BlockResponseV2, error) {
|
||||
bellatrixBlk, err := blk.PbBellatrixBlock()
|
||||
if err != nil {
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
if blindedBellatrixBlk, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||
if blindedBellatrixBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block")
|
||||
}
|
||||
bellatrixBlk, err = signedFullBlock.PbBellatrixBlock()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_BellatrixBlock{BellatrixBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if bellatrixBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_BellatrixBlock{BellatrixBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) getBlockCapella(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpbv2.BlockResponseV2, error) {
|
||||
capellaBlk, err := blk.PbCapellaBlock()
|
||||
if err != nil {
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
if blindedCapellaBlk, err := blk.PbBlindedCapellaBlock(); err == nil {
|
||||
if blindedCapellaBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block")
|
||||
}
|
||||
capellaBlk, err = signedFullBlock.PbCapellaBlock()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockCapellaToV2(capellaBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_CAPELLA,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_CapellaBlock{CapellaBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if capellaBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockCapellaToV2(capellaBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
return ðpbv2.BlockResponseV2{
|
||||
Version: ethpbv2.Version_CAPELLA,
|
||||
Data: ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_CapellaBlock{CapellaBlock: v2Blk},
|
||||
Signature: sig[:],
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getSSZBlockPhase0(blk interfaces.SignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
|
||||
phase0Blk, err := blk.PbPhase0Block()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if phase0Blk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
signedBeaconBlock, err := migration.SignedBeaconBlock(blk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
sszBlock, err := signedBeaconBlock.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_PHASE0, ExecutionOptimistic: false, Data: sszBlock}, nil
|
||||
}
|
||||
|
||||
func getSSZBlockAltair(blk interfaces.SignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
|
||||
altairBlk, err := blk.PbAltairBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if altairBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockAltair{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_ALTAIR, ExecutionOptimistic: false, Data: sszData}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) getSSZBlockBellatrix(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
|
||||
bellatrixBlk, err := blk.PbBellatrixBlock()
|
||||
if err != nil {
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
if blindedBellatrixBlk, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||
if blindedBellatrixBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block")
|
||||
}
|
||||
bellatrixBlk, err = signedFullBlock.PbBellatrixBlock()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{
|
||||
Version: ethpbv2.Version_BELLATRIX,
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Data: sszData,
|
||||
}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if bellatrixBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockBellatrix{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_BELLATRIX, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) getSSZBlockCapella(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
|
||||
capellaBlk, err := blk.PbCapellaBlock()
|
||||
if err != nil {
|
||||
// ErrUnsupportedGetter means that we have another block type
|
||||
if errors.Is(err, blocks.ErrUnsupportedGetter) {
|
||||
if blindedCapellaBlk, err := blk.PbBlindedCapellaBlock(); err == nil {
|
||||
if blindedCapellaBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block")
|
||||
}
|
||||
capellaBlk, err = signedFullBlock.PbCapellaBlock()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signed beacon block")
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockCapellaToV2(capellaBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockCapella{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{
|
||||
Version: ethpbv2.Version_CAPELLA,
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Data: sszData,
|
||||
}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if capellaBlk == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
v2Blk, err := migration.V1Alpha1BeaconBlockCapellaToV2(capellaBlk.Block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not convert signed beacon block")
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root")
|
||||
}
|
||||
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not check if block is optimistic")
|
||||
}
|
||||
sig := blk.Signature()
|
||||
data := ðpbv2.SignedBeaconBlockCapella{
|
||||
Message: v2Blk,
|
||||
Signature: sig[:],
|
||||
}
|
||||
sszData, err := data.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
|
||||
}
|
||||
return ðpbv2.SSZContainer{Version: ethpbv2.Version_CAPELLA, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) submitPhase0Block(ctx context.Context, phase0Blk *ethpbv1.BeaconBlock, sig []byte) error {
|
||||
v1alpha1Blk, err := migration.V1ToV1Alpha1SignedBlock(ðpbv1.SignedBeaconBlock{Block: phase0Blk, Signature: sig})
|
||||
if err != nil {
|
||||
@@ -1066,23 +1041,22 @@ func (bs *Server) submitBellatrixBlock(ctx context.Context, bellatrixBlk *ethpbv
|
||||
return bs.submitBlock(ctx, root, wrappedBellatrixBlk)
|
||||
}
|
||||
|
||||
func (bs *Server) submitBlindedBellatrixBlock(ctx context.Context, blindedBellatrixBlk *ethpbv2.BlindedBeaconBlockBellatrix, sig []byte) error {
|
||||
b, err := migration.BlindedBellatrixToV1Alpha1SignedBlock(ðpbv2.SignedBlindedBeaconBlockBellatrix{
|
||||
Message: blindedBellatrixBlk,
|
||||
Signature: sig,
|
||||
})
|
||||
func (bs *Server) submitCapellaBlock(ctx context.Context, capellaBlk *ethpbv2.BeaconBlockCapella, sig []byte) error {
|
||||
v1alpha1Blk, err := migration.CapellaToV1Alpha1SignedBlock(ðpbv2.SignedBeaconBlockCapella{Message: capellaBlk, Signature: sig})
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get blinded block: %v", err)
|
||||
return status.Errorf(codes.InvalidArgument, "Could not convert block to v1 block")
|
||||
}
|
||||
_, err = bs.V1Alpha1ValidatorServer.ProposeBeaconBlock(ctx, ð.GenericSignedBeaconBlock{
|
||||
Block: ð.GenericSignedBeaconBlock_BlindedBellatrix{
|
||||
BlindedBellatrix: b,
|
||||
},
|
||||
})
|
||||
wrappedCapellaBlk, err := blocks.NewSignedBeaconBlock(v1alpha1Blk)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not propose blinded block: %v", err)
|
||||
return status.Errorf(codes.InvalidArgument, "Could not prepare block")
|
||||
}
|
||||
return nil
|
||||
|
||||
root, err := capellaBlk.HashTreeRoot()
|
||||
if err != nil {
|
||||
return status.Errorf(codes.InvalidArgument, "Could not tree hash block: %v", err)
|
||||
}
|
||||
|
||||
return bs.submitBlock(ctx, root, wrappedCapellaBlk)
|
||||
}
|
||||
|
||||
func (bs *Server) submitBlock(ctx context.Context, blockRoot [fieldparams.RootLength]byte, block interfaces.SignedBeaconBlock) error {
|
||||
|
||||
@@ -7,19 +7,15 @@ import (
|
||||
"testing"
|
||||
|
||||
mock "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing"
|
||||
builderTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder/testing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db"
|
||||
dbTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/testing"
|
||||
executionTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
mockp2p "github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p/testing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/prysm/v1alpha1/validator"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/v3/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
||||
@@ -158,6 +154,48 @@ func fillDBTestBlocksBellatrix(ctx context.Context, t *testing.T, beaconDB db.Da
|
||||
return genBlk, blkContainers
|
||||
}
|
||||
|
||||
func fillDBTestBlocksCapella(ctx context.Context, t *testing.T, beaconDB db.Database) (*ethpbalpha.SignedBeaconBlockCapella, []*ethpbalpha.BeaconBlockContainer) {
|
||||
parentRoot := [32]byte{1, 2, 3}
|
||||
genBlk := util.NewBeaconBlockCapella()
|
||||
genBlk.Block.ParentRoot = parentRoot[:]
|
||||
root, err := genBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
util.SaveBlock(t, ctx, beaconDB, genBlk)
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, root))
|
||||
|
||||
count := types.Slot(100)
|
||||
blks := make([]interfaces.SignedBeaconBlock, count)
|
||||
blkContainers := make([]*ethpbalpha.BeaconBlockContainer, count)
|
||||
for i := types.Slot(0); i < count; i++ {
|
||||
b := util.NewBeaconBlockCapella()
|
||||
b.Block.Slot = i
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte{uint8(i)}, 32)
|
||||
att1 := util.NewAttestation()
|
||||
att1.Data.Slot = i
|
||||
att1.Data.CommitteeIndex = types.CommitteeIndex(i)
|
||||
att2 := util.NewAttestation()
|
||||
att2.Data.Slot = i
|
||||
att2.Data.CommitteeIndex = types.CommitteeIndex(i + 1)
|
||||
b.Block.Body.Attestations = []*ethpbalpha.Attestation{att1, att2}
|
||||
root, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
signedB, err := blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
blks[i] = signedB
|
||||
blkContainers[i] = ðpbalpha.BeaconBlockContainer{
|
||||
Block: ðpbalpha.BeaconBlockContainer_CapellaBlock{CapellaBlock: b}, BlockRoot: root[:]}
|
||||
}
|
||||
require.NoError(t, beaconDB.SaveBlocks(ctx, blks))
|
||||
headRoot := bytesutil.ToBytes32(blkContainers[len(blks)-1].BlockRoot)
|
||||
summary := ðpbalpha.StateSummary{
|
||||
Root: headRoot[:],
|
||||
Slot: blkContainers[len(blks)-1].Block.(*ethpbalpha.BeaconBlockContainer_CapellaBlock).CapellaBlock.Block.Slot,
|
||||
}
|
||||
require.NoError(t, beaconDB.SaveStateSummary(ctx, summary))
|
||||
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, headRoot))
|
||||
return genBlk, blkContainers
|
||||
}
|
||||
|
||||
func fillDBTestBlocksBellatrixBlinded(ctx context.Context, t *testing.T, beaconDB db.Database) (*ethpbalpha.SignedBlindedBeaconBlockBellatrix, []*ethpbalpha.BeaconBlockContainer) {
|
||||
parentRoot := [32]byte{1, 2, 3}
|
||||
genBlk := util.NewBlindedBeaconBlockBellatrix()
|
||||
@@ -621,6 +659,44 @@ func TestServer_SubmitBlock_OK(t *testing.T) {
|
||||
_, err = beaconChainServer.SubmitBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockCapella()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
}
|
||||
req := util.NewBeaconBlockCapella()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
v2Block, err := migration.V1Alpha1BeaconBlockCapellaToV2(req.Block)
|
||||
require.NoError(t, err)
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockReq := ðpbv2.SignedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBeaconBlockContainer_CapellaBlock{CapellaBlock: v2Block},
|
||||
Signature: req.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_SubmitBlockSSZ_OK(t *testing.T) {
|
||||
@@ -705,13 +781,6 @@ func TestServer_SubmitBlockSSZ_OK(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
// INFO: This code block can be removed once Bellatrix
|
||||
// fork epoch is set to a value other than math.MaxUint64
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.BellatrixForkEpoch = cfg.AltairForkEpoch + 1000
|
||||
cfg.ForkVersionSchedule[bytesutil.ToBytes4(cfg.BellatrixForkVersion)] = cfg.AltairForkEpoch + 1000
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -750,102 +819,21 @@ func TestServer_SubmitBlockSSZ_OK(t *testing.T) {
|
||||
_, err = beaconChainServer.SubmitBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
t.Skip("This test needs Capella fork version configured properly")
|
||||
|
||||
genesis := util.NewBeaconBlock()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
}
|
||||
req := util.NewBeaconBlock()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockSsz, err := req.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
blockReq := ðpbv2.SSZContainer{
|
||||
Data: blockSsz,
|
||||
}
|
||||
md := metadata.MD{}
|
||||
md.Set(versionHeader, "phase0")
|
||||
sszCtx := metadata.NewIncomingContext(ctx, md)
|
||||
_, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockAltair()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
}
|
||||
req := util.NewBeaconBlockAltair()
|
||||
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().AltairForkEpoch))
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockSsz, err := req.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
blockReq := ðpbv2.SSZContainer{
|
||||
Data: blockSsz,
|
||||
}
|
||||
md := metadata.MD{}
|
||||
md.Set(versionHeader, "altair")
|
||||
sszCtx := metadata.NewIncomingContext(ctx, md)
|
||||
_, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
// INFO: This code block can be removed once Bellatrix
|
||||
// INFO: This code block can be removed once Capella
|
||||
// fork epoch is set to a value other than math.MaxUint64
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.BellatrixForkEpoch = cfg.AltairForkEpoch + 1000
|
||||
cfg.ForkVersionSchedule[bytesutil.ToBytes4(cfg.BellatrixForkVersion)] = cfg.AltairForkEpoch + 1000
|
||||
cfg.CapellaForkEpoch = cfg.BellatrixForkEpoch + 1000
|
||||
cfg.ForkVersionSchedule[bytesutil.ToBytes4(cfg.CapellaForkVersion)] = cfg.BellatrixForkEpoch + 1000
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockBellatrix()
|
||||
genesis := util.NewBeaconBlockCapella()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
@@ -857,24 +845,16 @@ func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
alphaServer := &validator.Server{
|
||||
SyncCommitteePool: synccommittee.NewStore(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BlockBuilder: &builderTest.MockBuilderService{},
|
||||
BlockReceiver: c,
|
||||
BlockNotifier: &mock.MockBlockNotifier{},
|
||||
}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
V1Alpha1ValidatorServer: alphaServer,
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
HeadFetcher: c,
|
||||
}
|
||||
req := util.NewBlindedBeaconBlockBellatrix()
|
||||
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().BellatrixForkEpoch))
|
||||
req := util.NewBeaconBlockCapella()
|
||||
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().CapellaForkEpoch))
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockSsz, err := req.MarshalSSZ()
|
||||
@@ -883,143 +863,13 @@ func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
|
||||
Data: blockSsz,
|
||||
}
|
||||
md := metadata.MD{}
|
||||
md.Set(versionHeader, "bellatrix")
|
||||
md.Set(versionHeader, "capella")
|
||||
sszCtx := metadata.NewIncomingContext(ctx, md)
|
||||
_, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq)
|
||||
_, err = beaconChainServer.SubmitBlockSSZ(sszCtx, blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
}
|
||||
|
||||
func TestSubmitBlindedBlock(t *testing.T) {
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlock()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
}
|
||||
req := util.NewBeaconBlock()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
v1Block, err := migration.V1Alpha1ToV1SignedBlock(req)
|
||||
require.NoError(t, err)
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockReq := ðpbv2.SignedBlindedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBlindedBeaconBlockContainer_Phase0Block{Phase0Block: v1Block.Block},
|
||||
Signature: v1Block.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlindedBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockAltair()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
}
|
||||
req := util.NewBeaconBlockAltair()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
v2Block, err := migration.V1Alpha1BeaconBlockAltairToV2(req.Block)
|
||||
require.NoError(t, err)
|
||||
util.SaveBlock(t, ctx, beaconDB, req)
|
||||
blockReq := ðpbv2.SignedBlindedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBlindedBeaconBlockContainer_AltairBlock{AltairBlock: v2Block},
|
||||
Signature: req.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlindedBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
})
|
||||
|
||||
t.Run("Bellatrix - OK", func(t *testing.T) {
|
||||
transactions := [][]byte{[]byte("transaction1"), []byte("transaction2")}
|
||||
transactionsRoot, err := ssz.TransactionsRoot(transactions)
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := util.NewBeaconBlockBellatrix()
|
||||
util.SaveBlock(t, context.Background(), beaconDB, genesis)
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
alphaServer := &validator.Server{
|
||||
SyncCommitteePool: synccommittee.NewStore(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BlockBuilder: &builderTest.MockBuilderService{},
|
||||
BlockReceiver: c,
|
||||
BlockNotifier: &mock.MockBlockNotifier{},
|
||||
}
|
||||
beaconChainServer := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
BlockReceiver: c,
|
||||
ChainInfoFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
Broadcaster: mockp2p.NewTestP2P(t),
|
||||
V1Alpha1ValidatorServer: alphaServer,
|
||||
}
|
||||
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Slot = 5
|
||||
blk.Block.ParentRoot = bsRoot[:]
|
||||
blk.Block.Body.ExecutionPayload.Transactions = transactions
|
||||
blindedBlk := util.NewBlindedBeaconBlockBellatrixV2()
|
||||
blindedBlk.Message.Slot = 5
|
||||
blindedBlk.Message.ParentRoot = bsRoot[:]
|
||||
blindedBlk.Message.Body.ExecutionPayloadHeader.TransactionsRoot = transactionsRoot[:]
|
||||
util.SaveBlock(t, ctx, beaconDB, blk)
|
||||
|
||||
blockReq := ðpbv2.SignedBlindedBeaconBlockContainer{
|
||||
Message: ðpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock{BellatrixBlock: blindedBlk.Message},
|
||||
Signature: blindedBlk.Signature,
|
||||
}
|
||||
_, err = beaconChainServer.SubmitBlindedBlock(context.Background(), blockReq)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_GetBlock(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
@@ -1544,6 +1394,140 @@ func TestServer_GetBlockV2(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genBlk, blkContainers := fillDBTestBlocksCapella(ctx, t, beaconDB)
|
||||
canonicalRoots := make(map[[32]byte]bool)
|
||||
|
||||
for _, bContr := range blkContainers {
|
||||
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
|
||||
}
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
nextSlot := headBlock.GetCapellaBlock().Block.Slot + 1
|
||||
|
||||
b2 := util.NewBeaconBlockCapella()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
b3 := util.NewBeaconBlockCapella()
|
||||
b3.Block.Slot = 30
|
||||
b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b3)
|
||||
b4 := util.NewBeaconBlockCapella()
|
||||
b4.Block.Slot = nextSlot
|
||||
b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b4)
|
||||
|
||||
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetCapellaBlock())
|
||||
require.NoError(t, err)
|
||||
mockChainService := &mock.ChainService{
|
||||
DB: beaconDB,
|
||||
Block: chainBlk,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
CanonicalRoots: canonicalRoots,
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
ChainInfoFetcher: mockChainService,
|
||||
HeadFetcher: mockChainService,
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
ExecutionPayloadReconstructor: &executionTest.EngineClient{
|
||||
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{},
|
||||
},
|
||||
}
|
||||
|
||||
root, err := genBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
blockID []byte
|
||||
want *ethpbalpha.SignedBeaconBlockCapella
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "slot",
|
||||
blockID: []byte("30"),
|
||||
want: blkContainers[30].GetCapellaBlock(),
|
||||
},
|
||||
{
|
||||
name: "bad formatting",
|
||||
blockID: []byte("3bad0"),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "canonical",
|
||||
blockID: []byte("30"),
|
||||
want: blkContainers[30].GetCapellaBlock(),
|
||||
},
|
||||
{
|
||||
name: "non canonical",
|
||||
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "head",
|
||||
blockID: []byte("head"),
|
||||
want: headBlock.GetCapellaBlock(),
|
||||
},
|
||||
{
|
||||
name: "finalized",
|
||||
blockID: []byte("finalized"),
|
||||
want: blkContainers[64].GetCapellaBlock(),
|
||||
},
|
||||
{
|
||||
name: "genesis",
|
||||
blockID: []byte("genesis"),
|
||||
want: genBlk,
|
||||
},
|
||||
{
|
||||
name: "genesis root",
|
||||
blockID: root[:],
|
||||
want: genBlk,
|
||||
},
|
||||
{
|
||||
name: "root",
|
||||
blockID: blkContainers[20].BlockRoot,
|
||||
want: blkContainers[20].GetCapellaBlock(),
|
||||
},
|
||||
{
|
||||
name: "non-existent root",
|
||||
blockID: bytesutil.PadTo([]byte("hi there"), 32),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "no block",
|
||||
blockID: []byte("105"),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
blk, err := bs.GetBlockV2(ctx, ðpbv2.BlockRequestV2{
|
||||
BlockId: tt.blockID,
|
||||
})
|
||||
if tt.wantErr {
|
||||
require.NotEqual(t, err, nil)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
v2Block, err := migration.V1Alpha1BeaconBlockCapellaToV2(tt.want.Block)
|
||||
require.NoError(t, err)
|
||||
|
||||
b, ok := blk.Data.Message.(*ethpbv2.SignedBeaconBlockContainer_CapellaBlock)
|
||||
require.Equal(t, true, ok)
|
||||
if !reflect.DeepEqual(b.CapellaBlock, v2Block) {
|
||||
t.Error("Expected blocks to equal")
|
||||
}
|
||||
assert.Equal(t, ethpbv2.Version_CAPELLA, blk.Version)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("execution optimistic", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
@@ -1734,97 +1718,20 @@ func TestServer_GetBlockSSZV2(t *testing.T) {
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version)
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_GetBlindedBlockSSZ(t *testing.T) {
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
|
||||
_, blkContainers := fillDBTestBlocksCapella(ctx, t, beaconDB)
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
|
||||
b2 := util.NewBeaconBlock()
|
||||
b2 := util.NewBeaconBlockCapella()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
|
||||
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
|
||||
require.NoError(t, err)
|
||||
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
ChainInfoFetcher: &mock.ChainService{
|
||||
DB: beaconDB,
|
||||
Block: wsb,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
},
|
||||
}
|
||||
|
||||
blks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{BlockId: []byte("30")})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version)
|
||||
})
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB)
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
|
||||
b2 := util.NewBeaconBlockAltair()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
|
||||
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock())
|
||||
require.NoError(t, err)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
ChainInfoFetcher: &mock.ChainService{
|
||||
DB: beaconDB,
|
||||
Block: chainBlk,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
},
|
||||
}
|
||||
|
||||
blks, err := beaconDB.BlocksBySlot(ctx, 30)
|
||||
require.Equal(t, true, len(blks) > 0)
|
||||
require.NoError(t, err)
|
||||
sszBlock, err := blks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{BlockId: []byte("30")})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version)
|
||||
})
|
||||
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB)
|
||||
headBlock := blkContainers[len(blkContainers)-1]
|
||||
|
||||
b2 := util.NewBlindedBeaconBlockBellatrix()
|
||||
b2.Block.Slot = 30
|
||||
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
|
||||
util.SaveBlock(t, ctx, beaconDB, b2)
|
||||
|
||||
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock())
|
||||
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetCapellaBlock())
|
||||
require.NoError(t, err)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
@@ -1843,11 +1750,11 @@ func TestServer_GetBlindedBlockSSZ(t *testing.T) {
|
||||
sszBlock, err := blks[0].MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{BlockId: []byte("30")})
|
||||
resp, err := bs.GetBlockSSZV2(ctx, ðpbv2.BlockRequestV2{BlockId: []byte("30")})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.DeepEqual(t, sszBlock, resp.Data)
|
||||
assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version)
|
||||
assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/config/features"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/v3/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/v3/proto/migration"
|
||||
ethpbalpha "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
||||
@@ -304,3 +305,28 @@ func (bs *Server) SubmitVoluntaryExit(ctx context.Context, req *ethpbv1.SignedVo
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// SubmitSignedBLSToExecutionChange submits said object to the node's pool
|
||||
// if it passes validation the node must broadcast it to the network.
|
||||
func (bs *Server) SubmitSignedBLSToExecutionChange(ctx context.Context, req *ethpbv2.SignedBLSToExecutionChange) (*emptypb.Empty, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.SubmitVoluntaryExit")
|
||||
defer span.End()
|
||||
alphaChange := migration.V2SignedBLSToExecutionChangeToV1Alpha1(req)
|
||||
st, err := bs.ChainInfoFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
|
||||
}
|
||||
_, err = blocks.ValidateBLSToExecutionChange(st, alphaChange)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Could not validate SignedBLSToExecutionChange: %v", err)
|
||||
}
|
||||
if err := blocks.VerifyBLSChangeSignature(st, req); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Could not validate signature: %v", err)
|
||||
}
|
||||
bs.BLSChangesPool.InsertBLSToExecChange(alphaChange)
|
||||
if err := bs.Broadcaster.Broadcast(ctx, alphaChange); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not broadcast BLSToExecutionChange: %v", err)
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/execution"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p"
|
||||
@@ -41,4 +42,5 @@ type Server struct {
|
||||
CanonicalHistory *stategen.CanonicalHistory
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
ExecutionPayloadReconstructor execution.ExecutionPayloadReconstructor
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ go_library(
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p"
|
||||
v1alpha1validator "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/prysm/v1alpha1/validator"
|
||||
@@ -24,6 +25,7 @@ type Server struct {
|
||||
StateFetcher statefetcher.Fetcher
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
SyncCommitteePool synccommittee.Pool
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
V1Alpha1Server *v1alpha1validator.Server
|
||||
ProposerSlotIndexCache *cache.ProposerPayloadIDsCache
|
||||
}
|
||||
|
||||
@@ -488,16 +488,9 @@ func (vs *Server) ProduceBlindedBlock(ctx context.Context, req *ethpbv1.ProduceB
|
||||
if optimistic {
|
||||
return nil, status.Errorf(codes.Unavailable, "The node is currently optimistic and cannot serve validators")
|
||||
}
|
||||
altairBlk, err := vs.V1Alpha1Server.BuildAltairBeaconBlock(ctx, v1alpha1req)
|
||||
b, err := vs.V1Alpha1Server.GetBeaconBlock(ctx, v1alpha1req)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err)
|
||||
}
|
||||
ok, b, err := vs.V1Alpha1Server.GetAndBuildBlindBlock(ctx, altairBlk)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not prepare blind beacon block: %v", err)
|
||||
}
|
||||
if !ok {
|
||||
return nil, status.Error(codes.Unavailable, "Builder is not available due to miss-config or circuit breaker")
|
||||
return nil, err
|
||||
}
|
||||
blk, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(b.GetBlindedBellatrix())
|
||||
if err != nil {
|
||||
|
||||
@@ -943,7 +943,7 @@ func TestProduceBlockV2(t *testing.T) {
|
||||
|
||||
v1Alpha1Server := &v1alpha1validator.Server{
|
||||
ExecutionEngineCaller: &mockExecution.EngineClient{
|
||||
ExecutionBlock: &enginev1.ExecutionBlock{
|
||||
ExecutionBlock: &enginev1.ExecutionBlockBellatrix{
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
@@ -1438,7 +1438,7 @@ func TestProduceBlockV2SSZ(t *testing.T) {
|
||||
|
||||
v1Alpha1Server := &v1alpha1validator.Server{
|
||||
ExecutionEngineCaller: &mockExecution.EngineClient{
|
||||
ExecutionBlock: &enginev1.ExecutionBlock{
|
||||
ExecutionBlock: &enginev1.ExecutionBlockBellatrix{
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
@@ -2460,7 +2460,7 @@ func TestProduceBlindedBlockSSZ(t *testing.T) {
|
||||
|
||||
v1Alpha1Server := &v1alpha1validator.Server{
|
||||
ExecutionEngineCaller: &mockExecution.EngineClient{
|
||||
ExecutionBlock: &enginev1.ExecutionBlock{
|
||||
ExecutionBlock: &enginev1.ExecutionBlockBellatrix{
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ go_library(
|
||||
"assignments.go",
|
||||
"attestations.go",
|
||||
"blocks.go",
|
||||
"blstoexec.go",
|
||||
"committees.go",
|
||||
"config.go",
|
||||
"log.go",
|
||||
@@ -36,6 +37,7 @@ go_library(
|
||||
"//beacon-chain/db/filters:go_default_library",
|
||||
"//beacon-chain/execution:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
|
||||
@@ -122,6 +122,20 @@ func convertToBlockContainer(blk interfaces.SignedBeaconBlock, root [32]byte, is
|
||||
}
|
||||
ctr.Block = ðpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: rBlk}
|
||||
}
|
||||
case version.Capella:
|
||||
if blk.IsBlinded() {
|
||||
rBlk, err := blk.PbBlindedCapellaBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr.Block = ðpb.BeaconBlockContainer_BlindedCapellaBlock{BlindedCapellaBlock: rBlk}
|
||||
} else {
|
||||
rBlk, err := blk.PbCapellaBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr.Block = ðpb.BeaconBlockContainer_CapellaBlock{CapellaBlock: rBlk}
|
||||
}
|
||||
default:
|
||||
return nil, errors.Errorf("block type is not recognized: %d", blk.Version())
|
||||
}
|
||||
|
||||
24
beacon-chain/rpc/prysm/v1alpha1/beacon/blstoexec.go
Normal file
24
beacon-chain/rpc/prysm/v1alpha1/beacon/blstoexec.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// SubmitBLSToExecutionChange receives a withdrawal credential change object via
|
||||
// RPC and injects it into the beacon node's operations pool.
|
||||
// Submission into this pool does not guarantee inclusion into a beacon block. If the object passes validation
|
||||
// the node MUST broadcast it
|
||||
func (bs *Server) SubmitBLSToExecutionChange(
|
||||
ctx context.Context,
|
||||
req *ethpb.SignedBLSToExecutionChange,
|
||||
) (*ethpb.BLSToExecutionChangeResponse, error) {
|
||||
bs.BLSChangesPool.InsertBLSToExecChange(req)
|
||||
if err := bs.Broadcaster.Broadcast(ctx, req); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not broadcast SigledBLSToExecutionChange object: %v", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/execution"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stategen"
|
||||
@@ -40,6 +41,7 @@ type Server struct {
|
||||
Broadcaster p2p.Broadcaster
|
||||
AttestationsPool attestations.Pool
|
||||
SlashingsPool slashings.PoolManager
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
ChainStartChan chan time.Time
|
||||
ReceivedAttestationsBuffer chan *ethpb.Attestation
|
||||
CollectedAttestationsBuffer chan []*ethpb.Attestation
|
||||
|
||||
@@ -16,7 +16,6 @@ go_library(
|
||||
"proposer_deposits.go",
|
||||
"proposer_eth1data.go",
|
||||
"proposer_execution_payload.go",
|
||||
"proposer_phase0.go",
|
||||
"proposer_sync_aggregate.go",
|
||||
"server.go",
|
||||
"status.go",
|
||||
@@ -47,6 +46,7 @@ go_library(
|
||||
"//beacon-chain/execution:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
@@ -58,6 +58,7 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/payload-attribute:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
"//contracts/deposit:go_default_library",
|
||||
|
||||
@@ -89,6 +89,17 @@ func sendVerifiedBlocks(stream ethpb.BeaconNodeValidator_StreamBlocksAltairServe
|
||||
return nil
|
||||
}
|
||||
b.Block = ðpb.StreamBlocksResponse_BellatrixBlock{BellatrixBlock: phBlk}
|
||||
case version.Capella:
|
||||
pb, err := data.SignedBlock.Proto()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get protobuf block")
|
||||
}
|
||||
phBlk, ok := pb.(*ethpb.SignedBeaconBlockCapella)
|
||||
if !ok {
|
||||
log.Warn("Mismatch between version and block type, was expecting SignedBeaconBlockCapella")
|
||||
return nil
|
||||
}
|
||||
b.Block = ðpb.StreamBlocksResponse_CapellaBlock{CapellaBlock: phBlk}
|
||||
}
|
||||
|
||||
if err := stream.Send(b); err != nil {
|
||||
@@ -136,6 +147,8 @@ func (vs *Server) sendBlocks(stream ethpb.BeaconNodeValidator_StreamBlocksAltair
|
||||
b.Block = ðpb.StreamBlocksResponse_AltairBlock{AltairBlock: p}
|
||||
case *ethpb.SignedBeaconBlockBellatrix:
|
||||
b.Block = ðpb.StreamBlocksResponse_BellatrixBlock{BellatrixBlock: p}
|
||||
case *ethpb.SignedBeaconBlockCapella:
|
||||
b.Block = ðpb.StreamBlocksResponse_CapellaBlock{CapellaBlock: p}
|
||||
default:
|
||||
log.Errorf("Unknown block type %T", p)
|
||||
}
|
||||
|
||||
@@ -12,10 +12,15 @@ import (
|
||||
emptypb "github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/builder"
|
||||
blocks2 "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/feed"
|
||||
blockfeed "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/feed/block"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition"
|
||||
v "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
@@ -35,32 +40,247 @@ var eth1DataNotification bool
|
||||
const eth1dataTimeout = 2 * time.Second
|
||||
|
||||
// GetBeaconBlock is called by a proposer during its assigned slot to request a block to sign
|
||||
// by passing in the slot and the signed randao reveal of the slot. Returns phase0 beacon blocks
|
||||
// before the Altair fork epoch and Altair blocks post-fork epoch.
|
||||
// by passing in the slot and the signed randao reveal of the slot. Returns a full block
|
||||
// corresponding to the fork epoch
|
||||
func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBeaconBlock")
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot)))
|
||||
if slots.ToEpoch(req.Slot) < params.BeaconConfig().AltairForkEpoch {
|
||||
blk, err := vs.getPhase0BeaconBlock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch phase0 beacon block: %v", err)
|
||||
}
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: blk}}, nil
|
||||
} else if slots.ToEpoch(req.Slot) < params.BeaconConfig().BellatrixForkEpoch {
|
||||
blk, err := vs.getAltairBeaconBlock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch Altair beacon block: %v", err)
|
||||
}
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: blk}}, nil
|
||||
|
||||
// A syncing validator should not produce a block.
|
||||
if vs.SyncChecker.Syncing() {
|
||||
return nil, status.Error(codes.Unavailable, "Syncing to latest head, not ready to respond")
|
||||
}
|
||||
|
||||
// An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain).
|
||||
if err := vs.optimisticStatus(ctx); err != nil {
|
||||
return nil, err
|
||||
return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err)
|
||||
}
|
||||
|
||||
return vs.getBellatrixBeaconBlock(ctx, req)
|
||||
blk, sBlk, err := emptyBlockToSign(req.Slot)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not prepare block: %v", err)
|
||||
}
|
||||
|
||||
parentRoot, err := vs.HeadFetcher.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head root: %v", err)
|
||||
}
|
||||
head, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
|
||||
}
|
||||
head, err = transition.ProcessSlotsUsingNextSlotCache(ctx, head, parentRoot, req.Slot)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not process slots up to %d: %v", req.Slot, err)
|
||||
}
|
||||
|
||||
// Set slot, graffiti, randao reveal, and parent root.
|
||||
blk.SetSlot(req.Slot)
|
||||
blk.Body().SetGraffiti(req.Graffiti)
|
||||
blk.Body().SetRandaoReveal(req.RandaoReveal)
|
||||
blk.SetParentRoot(parentRoot)
|
||||
|
||||
// Set eth1 data.
|
||||
eth1Data, err := vs.eth1DataMajorityVote(ctx, head)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get eth1data")
|
||||
} else {
|
||||
blk.Body().SetEth1Data(eth1Data)
|
||||
|
||||
// Set deposit and attestation.
|
||||
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not pack deposits and attestations")
|
||||
} else {
|
||||
blk.Body().SetDeposits(deposits)
|
||||
blk.Body().SetAttestations(atts)
|
||||
}
|
||||
}
|
||||
|
||||
// Set proposer index
|
||||
idx, err := helpers.BeaconProposerIndex(ctx, head)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not calculate proposer index %v", err)
|
||||
}
|
||||
blk.SetProposerIndex(idx)
|
||||
|
||||
// Set slashings
|
||||
validProposerSlashings, validAttSlashings := vs.getSlashings(ctx, head)
|
||||
blk.Body().SetProposerSlashings(validProposerSlashings)
|
||||
blk.Body().SetAttesterSlashings(validAttSlashings)
|
||||
|
||||
// Set exits
|
||||
blk.Body().SetVoluntaryExits(vs.getExits(head, req))
|
||||
|
||||
// Set sync aggregate. New in Altair.
|
||||
if req.Slot > 0 && slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch {
|
||||
syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(parentRoot))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get sync aggregate")
|
||||
} else {
|
||||
if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil {
|
||||
log.WithError(err).Error("Could not set sync aggregate")
|
||||
if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize),
|
||||
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
}); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not set default sync aggregate: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set execution data. New in Bellatrix
|
||||
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch {
|
||||
fallBackToLocal := true
|
||||
canUseBuilder, err := vs.canUseBuilder(ctx, req.Slot, idx)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: failed to check if builder can be used")
|
||||
} else if canUseBuilder {
|
||||
h, err := vs.getPayloadHeaderFromBuilder(ctx, req.Slot, idx)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: failed to get payload header from builder")
|
||||
} else {
|
||||
blk.SetBlinded(true)
|
||||
if err := blk.Body().SetExecution(h); err != nil {
|
||||
log.WithError(err).Warn("Proposer: failed to set execution payload")
|
||||
} else {
|
||||
fallBackToLocal = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if fallBackToLocal {
|
||||
executionData, err := vs.getExecutionPayload(ctx, req.Slot, idx, bytesutil.ToBytes32(parentRoot), head)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get execution payload: %v", err)
|
||||
}
|
||||
if err := blk.Body().SetExecution(executionData); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not set execution payload: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set bls to execution change. New in Capella
|
||||
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch {
|
||||
changes, err := vs.BLSChangesPool.BLSToExecChangesForInclusion(head)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get bls to execution changes")
|
||||
} else {
|
||||
if err := blk.Body().SetBLSToExecutionChanges(changes); err != nil {
|
||||
log.WithError(err).Error("Could not set bls to execution changes")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := sBlk.SetBlock(blk); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not set block: %v", err)
|
||||
}
|
||||
sr, err := vs.computeStateRoot(ctx, sBlk)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err)
|
||||
}
|
||||
blk.SetStateRoot(sr)
|
||||
|
||||
pb, err := blk.Proto()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert block to proto: %v", err)
|
||||
}
|
||||
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch {
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}}, nil
|
||||
} else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch {
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}}, nil
|
||||
} else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch {
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: pb.(*ethpb.BeaconBlockAltair)}}, nil
|
||||
}
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: pb.(*ethpb.BeaconBlock)}}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) getExits(head state.BeaconState, req *ethpb.BlockRequest) []*ethpb.SignedVoluntaryExit {
|
||||
exits := vs.ExitPool.PendingExits(head, req.Slot, false /*noLimit*/)
|
||||
validExits := make([]*ethpb.SignedVoluntaryExit, 0, len(exits))
|
||||
for _, exit := range exits {
|
||||
val, err := head.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid exit")
|
||||
continue
|
||||
}
|
||||
if err := blocks2.VerifyExitAndSignature(val, head.Slot(), head.Fork(), exit, head.GenesisValidatorsRoot()); err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid exit")
|
||||
continue
|
||||
}
|
||||
validExits = append(validExits, exit)
|
||||
}
|
||||
return validExits
|
||||
}
|
||||
|
||||
func (vs *Server) getSlashings(ctx context.Context, head state.BeaconState) ([]*ethpb.ProposerSlashing, []*ethpb.AttesterSlashing) {
|
||||
proposerSlashings := vs.SlashingsPool.PendingProposerSlashings(ctx, head, false /*noLimit*/)
|
||||
validProposerSlashings := make([]*ethpb.ProposerSlashing, 0, len(proposerSlashings))
|
||||
for _, slashing := range proposerSlashings {
|
||||
_, err := blocks2.ProcessProposerSlashing(ctx, head, slashing, v.SlashValidator)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid proposer slashing")
|
||||
continue
|
||||
}
|
||||
validProposerSlashings = append(validProposerSlashings, slashing)
|
||||
}
|
||||
attSlashings := vs.SlashingsPool.PendingAttesterSlashings(ctx, head, false /*noLimit*/)
|
||||
validAttSlashings := make([]*ethpb.AttesterSlashing, 0, len(attSlashings))
|
||||
for _, slashing := range attSlashings {
|
||||
_, err := blocks2.ProcessAttesterSlashing(ctx, head, slashing, v.SlashValidator)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid attester slashing")
|
||||
continue
|
||||
}
|
||||
validAttSlashings = append(validAttSlashings, slashing)
|
||||
}
|
||||
return validProposerSlashings, validAttSlashings
|
||||
}
|
||||
|
||||
func emptyBlockToSign(slot types.Slot) (interfaces.BeaconBlock, interfaces.SignedBeaconBlock, error) {
|
||||
var blk interfaces.BeaconBlock
|
||||
var sBlk interfaces.SignedBeaconBlock
|
||||
var err error
|
||||
switch {
|
||||
case slots.ToEpoch(slot) < params.BeaconConfig().AltairForkEpoch:
|
||||
blk, err = blocks.NewBeaconBlock(ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
sBlk, err = blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
case slots.ToEpoch(slot) < params.BeaconConfig().BellatrixForkEpoch:
|
||||
blk, err = blocks.NewBeaconBlock(ðpb.BeaconBlockAltair{Body: ðpb.BeaconBlockBodyAltair{}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
sBlk, err = blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockAltair{Block: ðpb.BeaconBlockAltair{Body: ðpb.BeaconBlockBodyAltair{}}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
case slots.ToEpoch(slot) < params.BeaconConfig().CapellaForkEpoch:
|
||||
blk, err = blocks.NewBeaconBlock(ðpb.BeaconBlockBellatrix{Body: ðpb.BeaconBlockBodyBellatrix{}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
sBlk, err = blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: ðpb.BeaconBlockBellatrix{Body: ðpb.BeaconBlockBodyBellatrix{}}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
default:
|
||||
blk, err = blocks.NewBeaconBlock(ðpb.BeaconBlockCapella{Body: ðpb.BeaconBlockBodyCapella{}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
sBlk, err = blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockCapella{Block: ðpb.BeaconBlockCapella{Body: ðpb.BeaconBlockBodyCapella{}}})
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
|
||||
}
|
||||
}
|
||||
return blk, sBlk, err
|
||||
}
|
||||
|
||||
// ProposeBeaconBlock is called by a proposer during its assigned slot to create a block in an attempt
|
||||
|
||||
@@ -2,11 +2,8 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
@@ -15,66 +12,6 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
func (vs *Server) BuildAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.BuildAltairBeaconBlock")
|
||||
defer span.End()
|
||||
blkData, err := vs.buildPhase0BlockData(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not build block data: %v", err)
|
||||
}
|
||||
|
||||
// Use zero hash as stub for state root to compute later.
|
||||
stateRoot := params.BeaconConfig().ZeroHash[:]
|
||||
|
||||
// No need for safe sub as req.Slot cannot be 0 if requesting Altair blocks. If 0, we will be throwing
|
||||
// an error in the first validity check of this endpoint.
|
||||
syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(blkData.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ðpb.BeaconBlockAltair{
|
||||
Slot: req.Slot,
|
||||
ParentRoot: blkData.ParentRoot,
|
||||
StateRoot: stateRoot,
|
||||
ProposerIndex: blkData.ProposerIdx,
|
||||
Body: ðpb.BeaconBlockBodyAltair{
|
||||
Eth1Data: blkData.Eth1Data,
|
||||
Deposits: blkData.Deposits,
|
||||
Attestations: blkData.Attestations,
|
||||
RandaoReveal: req.RandaoReveal,
|
||||
ProposerSlashings: blkData.ProposerSlashings,
|
||||
AttesterSlashings: blkData.AttesterSlashings,
|
||||
VoluntaryExits: blkData.VoluntaryExits,
|
||||
Graffiti: blkData.Graffiti[:],
|
||||
SyncAggregate: syncAggregate,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.getAltairBeaconBlock")
|
||||
defer span.End()
|
||||
blk, err := vs.BuildAltairBeaconBlock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not build block data: %v", err)
|
||||
}
|
||||
// Compute state root with the newly constructed block.
|
||||
wsb, err := blocks.NewSignedBeaconBlock(
|
||||
ðpb.SignedBeaconBlockAltair{Block: blk, Signature: make([]byte, 96)},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stateRoot, err := vs.computeStateRoot(ctx, wsb)
|
||||
if err != nil {
|
||||
interop.WriteBlockToDisk(wsb, true /*failed*/)
|
||||
return nil, fmt.Errorf("could not compute state root: %v", err)
|
||||
}
|
||||
blk.StateRoot = stateRoot
|
||||
return blk, nil
|
||||
}
|
||||
|
||||
// getSyncAggregate retrieves the sync contributions from the pool to construct the sync aggregate object.
|
||||
// The contributions are filtered based on matching of the input root and slot then profitability.
|
||||
func (vs *Server) getSyncAggregate(ctx context.Context, slot types.Slot, root [32]byte) (*ethpb.SyncAggregate, error) {
|
||||
|
||||
@@ -80,7 +80,7 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon
|
||||
// filter separates attestation list into two groups: valid and invalid attestations.
|
||||
// The first group passes the all the required checks for attestation to be considered for proposing.
|
||||
// And attestations from the second group should be deleted.
|
||||
func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (proposerAtts, proposerAtts) {
|
||||
func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (proposerAtts, proposerAtts, error) {
|
||||
validAtts := make([]*ethpb.Attestation, 0, len(a))
|
||||
invalidAtts := make([]*ethpb.Attestation, 0, len(a))
|
||||
var attestationProcessor func(context.Context, state.BeaconState, *ethpb.Attestation) (state.BeaconState, error)
|
||||
@@ -88,7 +88,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
switch st.Version() {
|
||||
case version.Phase0:
|
||||
attestationProcessor = blocks.ProcessAttestationNoVerifySignature
|
||||
case version.Altair, version.Bellatrix:
|
||||
case version.Altair, version.Bellatrix, version.Capella:
|
||||
// Use a wrapper here, as go needs strong typing for the function signature.
|
||||
attestationProcessor = func(ctx context.Context, st state.BeaconState, attestation *ethpb.Attestation) (state.BeaconState, error) {
|
||||
totalBalance, err := helpers.TotalActiveBalance(st)
|
||||
@@ -99,7 +99,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
}
|
||||
default:
|
||||
// Exit early if there is an unknown state type.
|
||||
return validAtts, invalidAtts
|
||||
return validAtts, invalidAtts, errors.Errorf("unknown state type: %v", st.Version())
|
||||
}
|
||||
for _, att := range a {
|
||||
if _, err := attestationProcessor(ctx, st, att); err == nil {
|
||||
@@ -108,7 +108,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
}
|
||||
invalidAtts = append(invalidAtts, att)
|
||||
}
|
||||
return validAtts, invalidAtts
|
||||
return validAtts, invalidAtts, nil
|
||||
}
|
||||
|
||||
// sortByProfitability orders attestations by highest slot and by highest aggregation bit count.
|
||||
@@ -247,7 +247,10 @@ func (vs *Server) validateAndDeleteAttsInPool(ctx context.Context, st state.Beac
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.validateAndDeleteAttsInPool")
|
||||
defer span.End()
|
||||
|
||||
validAtts, invalidAtts := proposerAtts(atts).filter(ctx, st)
|
||||
validAtts, invalidAtts, err := proposerAtts(atts).filter(ctx, st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := vs.deleteAttsInPool(ctx, invalidAtts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
@@ -38,73 +37,20 @@ var builderGetPayloadMissCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||
// block request. This value is known as `BUILDER_PROPOSAL_DELAY_TOLERANCE` in builder spec.
|
||||
const blockBuilderTimeout = 1 * time.Second
|
||||
|
||||
func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
||||
altairBlk, err := vs.BuildAltairBeaconBlock(ctx, req)
|
||||
func (vs *Server) canUseBuilder(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (bool, error) {
|
||||
registered, err := vs.validatorRegistered(ctx, idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !req.SkipMevBoost {
|
||||
registered, err := vs.validatorRegistered(ctx, altairBlk.ProposerIndex)
|
||||
if registered && err == nil {
|
||||
builderReady, b, err := vs.GetAndBuildBlindBlock(ctx, altairBlk)
|
||||
if err != nil {
|
||||
// In the event of an error, the node should fall back to default execution engine for building block.
|
||||
log.WithError(err).Error("Failed to build a block from external builder, falling " +
|
||||
"back to local execution client")
|
||||
builderGetPayloadMissCount.Inc()
|
||||
} else if builderReady {
|
||||
return b, nil
|
||||
}
|
||||
} else if err != nil {
|
||||
log.WithError(err).WithFields(logrus.Fields{
|
||||
"slot": req.Slot,
|
||||
"validatorIndex": altairBlk.ProposerIndex,
|
||||
}).Error("Could not determine validator has registered. Defaulting to local execution client")
|
||||
}
|
||||
if !registered {
|
||||
return false, nil
|
||||
}
|
||||
payload, err := vs.getExecutionPayload(ctx, req.Slot, altairBlk.ProposerIndex, bytesutil.ToBytes32(altairBlk.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blk := ðpb.BeaconBlockBellatrix{
|
||||
Slot: altairBlk.Slot,
|
||||
ProposerIndex: altairBlk.ProposerIndex,
|
||||
ParentRoot: altairBlk.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
RandaoReveal: altairBlk.Body.RandaoReveal,
|
||||
Eth1Data: altairBlk.Body.Eth1Data,
|
||||
Graffiti: altairBlk.Body.Graffiti,
|
||||
ProposerSlashings: altairBlk.Body.ProposerSlashings,
|
||||
AttesterSlashings: altairBlk.Body.AttesterSlashings,
|
||||
Attestations: altairBlk.Body.Attestations,
|
||||
Deposits: altairBlk.Body.Deposits,
|
||||
VoluntaryExits: altairBlk.Body.VoluntaryExits,
|
||||
SyncAggregate: altairBlk.Body.SyncAggregate,
|
||||
ExecutionPayload: payload,
|
||||
},
|
||||
}
|
||||
// Compute state root with the newly constructed block.
|
||||
wsb, err := consensusblocks.NewSignedBeaconBlock(
|
||||
ðpb.SignedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stateRoot, err := vs.computeStateRoot(ctx, wsb)
|
||||
if err != nil {
|
||||
interop.WriteBlockToDisk(wsb, true /*failed*/)
|
||||
return nil, fmt.Errorf("could not compute state root: %v", err)
|
||||
}
|
||||
blk.StateRoot = stateRoot
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: blk}}, nil
|
||||
return vs.circuitBreakBuilder(slot)
|
||||
}
|
||||
|
||||
// This function retrieves the payload header given the slot number and the validator index.
|
||||
// It's a no-op if the latest head block is not versioned bellatrix.
|
||||
func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (*enginev1.ExecutionPayloadHeader, error) {
|
||||
func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (interfaces.ExecutionData, error) {
|
||||
b, err := vs.HeadFetcher.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -164,48 +110,8 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Sl
|
||||
"builderPubKey": fmt.Sprintf("%#x", bid.Message.Pubkey),
|
||||
"blockHash": fmt.Sprintf("%#x", bid.Message.Header.BlockHash),
|
||||
}).Info("Received header with bid")
|
||||
return bid.Message.Header, nil
|
||||
}
|
||||
|
||||
// This function constructs the builder block given the input altair block and the header. It returns a generic beacon block for signing
|
||||
func (vs *Server) buildBlindBlock(ctx context.Context, b *ethpb.BeaconBlockAltair, h *enginev1.ExecutionPayloadHeader) (*ethpb.GenericBeaconBlock, error) {
|
||||
if b == nil || b.Body == nil {
|
||||
return nil, errors.New("nil block")
|
||||
}
|
||||
if h == nil {
|
||||
return nil, errors.New("nil header")
|
||||
}
|
||||
|
||||
blk := ðpb.BlindedBeaconBlockBellatrix{
|
||||
Slot: b.Slot,
|
||||
ProposerIndex: b.ProposerIndex,
|
||||
ParentRoot: b.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Body: ðpb.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: b.Body.SyncAggregate,
|
||||
ExecutionPayloadHeader: h,
|
||||
},
|
||||
}
|
||||
wsb, err := consensusblocks.NewSignedBeaconBlock(
|
||||
ðpb.SignedBlindedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stateRoot, err := vs.computeStateRoot(ctx, wsb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute state root")
|
||||
}
|
||||
blk.StateRoot = stateRoot
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: blk}}, nil
|
||||
return coreBlock.WrappedExecutionPayloadHeader(bid.Message.Header)
|
||||
}
|
||||
|
||||
// This function retrieves the full payload block using the input blind block. This input must be versioned as
|
||||
@@ -319,24 +225,6 @@ func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.SignedBe
|
||||
return wb, nil
|
||||
}
|
||||
|
||||
// readyForBuilder returns true if builder is allowed to be used. Builder is only allowed to be use after the
|
||||
// first finalized checkpt has been execution-enabled.
|
||||
func (vs *Server) readyForBuilder(ctx context.Context) (bool, error) {
|
||||
cp := vs.FinalizationFetcher.FinalizedCheckpt()
|
||||
// Checkpoint root is zero means we are still at genesis epoch.
|
||||
if bytesutil.ToBytes32(cp.Root) == params.BeaconConfig().ZeroHash {
|
||||
return false, nil
|
||||
}
|
||||
b, err := vs.BeaconDB.Block(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err = coreBlock.BeaconBlockIsNil(b); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return blocks.IsExecutionBlock(b.Block().Body())
|
||||
}
|
||||
|
||||
// circuitBreakBuilder returns true if the builder is not allowed to be used due to circuit breaker conditions.
|
||||
func (vs *Server) circuitBreakBuilder(s types.Slot) (bool, error) {
|
||||
if vs.ForkFetcher == nil || vs.ForkFetcher.ForkChoicer() == nil {
|
||||
@@ -385,50 +273,6 @@ func (vs *Server) circuitBreakBuilder(s types.Slot) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// GetAndBuildBlindBlock builds blind block from builder network. Returns a boolean status, built block and error.
|
||||
// If the status is false that means builder the header block is disallowed.
|
||||
// This routine is time limited by `blockBuilderTimeout`.
|
||||
func (vs *Server) GetAndBuildBlindBlock(ctx context.Context, b *ethpb.BeaconBlockAltair) (bool, *ethpb.GenericBeaconBlock, error) {
|
||||
// No op. Builder is not defined. User did not specify a user URL. We should use local EE.
|
||||
if vs.BlockBuilder == nil || !vs.BlockBuilder.Configured() {
|
||||
return false, nil, nil
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, blockBuilderTimeout)
|
||||
defer cancel()
|
||||
// Does the protocol allow for builder at this current moment. Builder is only allowed post merge after finalization.
|
||||
ready, err := vs.readyForBuilder(ctx)
|
||||
if err != nil {
|
||||
return false, nil, errors.Wrap(err, "could not determine if builder is ready")
|
||||
}
|
||||
if !ready {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
circuitBreak, err := vs.circuitBreakBuilder(b.Slot)
|
||||
if err != nil {
|
||||
return false, nil, errors.Wrap(err, "could not determine if builder circuit breaker condition")
|
||||
}
|
||||
if circuitBreak {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
h, err := vs.getPayloadHeaderFromBuilder(ctx, b.Slot, b.ProposerIndex)
|
||||
if err != nil {
|
||||
return false, nil, errors.Wrap(err, "could not get payload header")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"blockHash": fmt.Sprintf("%#x", h.BlockHash),
|
||||
"feeRecipient": fmt.Sprintf("%#x", h.FeeRecipient),
|
||||
"gasUsed": h.GasUsed,
|
||||
"slot": b.Slot,
|
||||
}).Info("Retrieved header from builder")
|
||||
gb, err := vs.buildBlindBlock(ctx, b, h)
|
||||
if err != nil {
|
||||
return false, nil, errors.Wrap(err, "could not combine altair block with payload header")
|
||||
}
|
||||
return true, gb, nil
|
||||
}
|
||||
|
||||
// validatorRegistered returns true if validator with index `id` was previously registered in the database.
|
||||
func (vs *Server) validatorRegistered(ctx context.Context, id types.ValidatorIndex) (bool, error) {
|
||||
if vs.BeaconDB == nil {
|
||||
@@ -448,7 +292,7 @@ func (vs *Server) validatorRegistered(ctx context.Context, id types.ValidatorInd
|
||||
func (vs *Server) validateBuilderSignature(bid *ethpb.SignedBuilderBid) error {
|
||||
d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder,
|
||||
nil, /* fork version */
|
||||
nil /* genesis val root */)
|
||||
nil /* genesis val root */)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -41,25 +42,38 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.Be
|
||||
return vs.mockETH1DataVote(ctx, slot)
|
||||
}
|
||||
if !vs.Eth1InfoFetcher.ExecutionClientConnected() {
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
return vs.randomETH1DataVote(ctx, "ExecutionClientConnected == false")
|
||||
}
|
||||
eth1DataNotification = false
|
||||
|
||||
eth1FollowDistance := params.BeaconConfig().Eth1FollowDistance
|
||||
earliestValidTime := votingPeriodStartTime - 2*params.BeaconConfig().SecondsPerETH1Block*eth1FollowDistance
|
||||
latestValidTime := votingPeriodStartTime - params.BeaconConfig().SecondsPerETH1Block*eth1FollowDistance
|
||||
genesisTime, _ := vs.Eth1InfoFetcher.GenesisExecutionChainInfo()
|
||||
followDistanceSeconds := params.BeaconConfig().Eth1FollowDistance * params.BeaconConfig().SecondsPerETH1Block
|
||||
latestValidTime := votingPeriodStartTime - followDistanceSeconds
|
||||
earliestValidTime := votingPeriodStartTime - 2*followDistanceSeconds
|
||||
|
||||
// Special case for starting from a pre-mined genesis: the eth1 vote should be genesis until the chain has advanced
|
||||
// by ETH1_FOLLOW_DISTANCE. The head state should maintain the same ETH1Data until this condition has passed, so
|
||||
// trust the existing head for the right eth1 vote until we can get a meaningful value from the deposit contract.
|
||||
log.WithField("votingPeriodStartTime", votingPeriodStartTime-genesisTime).WithField("latestValidTime", latestValidTime-genesisTime).WithField("earliestValidTime", earliestValidTime-genesisTime).Info("eth1DataMajorityVote")
|
||||
if latestValidTime < genesisTime+followDistanceSeconds {
|
||||
log.WithField("genesisTime", genesisTime).WithField("latestValidTime", latestValidTime).Info("voting period before genesis + follow distance, return head eth1data")
|
||||
return vs.HeadFetcher.HeadETH1Data(), nil
|
||||
}
|
||||
|
||||
lastBlockByLatestValidTime, err := vs.Eth1BlockFetcher.BlockByTimestamp(ctx, latestValidTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get last block by latest valid time")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
return vs.randomETH1DataVote(ctx, "error from BlockByTimestamp")
|
||||
}
|
||||
if lastBlockByLatestValidTime.Time < earliestValidTime {
|
||||
return vs.HeadFetcher.HeadETH1Data(), nil
|
||||
ed := vs.HeadFetcher.HeadETH1Data()
|
||||
log.WithField("latestBlock.Time", lastBlockByLatestValidTime.Time).WithField("latestBlock.Height", lastBlockByLatestValidTime.Number).WithFields(logFields(ed)).WithField("condition", "lastBlockByLatestValidTime.Time < earliestValidTime").Info("eth1DataMajorityVote")
|
||||
return ed, nil
|
||||
}
|
||||
|
||||
lastBlockDepositCount, lastBlockDepositRoot := vs.DepositFetcher.DepositsNumberAndRootAtHeight(ctx, lastBlockByLatestValidTime.Number)
|
||||
if lastBlockDepositCount == 0 {
|
||||
log.WithFields(logFields(vs.ChainStartFetcher.ChainStartEth1Data())).WithField("condition", "ChainStartEth1Data").Info("eth1DataMajorityVote")
|
||||
return vs.ChainStartFetcher.ChainStartEth1Data(), nil
|
||||
}
|
||||
|
||||
@@ -67,17 +81,27 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.Be
|
||||
h, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, lastBlockByLatestValidTime.Number)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get hash of last block by latest valid time")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
return vs.randomETH1DataVote(ctx, "deposit count too high")
|
||||
}
|
||||
return ðpb.Eth1Data{
|
||||
ed := ðpb.Eth1Data{
|
||||
BlockHash: h.Bytes(),
|
||||
DepositCount: lastBlockDepositCount,
|
||||
DepositRoot: lastBlockDepositRoot[:],
|
||||
}, nil
|
||||
}
|
||||
log.WithFields(logFields(ed)).WithField("condition", "lastBlockDepositCount >= vs.HeadFetcher.HeadETH1Data().DepositCount").Info("eth1DataMajorityVote")
|
||||
return ed, nil
|
||||
}
|
||||
return vs.HeadFetcher.HeadETH1Data(), nil
|
||||
}
|
||||
|
||||
func logFields(ed *ethpb.Eth1Data) map[string]interface{} {
|
||||
fields := make(map[string]interface{})
|
||||
fields["deposit_root"] = fmt.Sprintf("%#x", ed.DepositRoot)
|
||||
fields["deposit_count"] = ed.DepositCount
|
||||
fields["block_hash"] = fmt.Sprintf("%#x", ed.BlockHash)
|
||||
return fields
|
||||
}
|
||||
|
||||
func (vs *Server) slotStartTime(slot types.Slot) uint64 {
|
||||
startTime, _ := vs.Eth1InfoFetcher.GenesisExecutionChainInfo()
|
||||
return slots.VotingPeriodStartTime(startTime, slot)
|
||||
@@ -147,7 +171,8 @@ func (vs *Server) mockETH1DataVote(ctx context.Context, slot types.Slot) (*ethpb
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) randomETH1DataVote(ctx context.Context) (*ethpb.Eth1Data, error) {
|
||||
func (vs *Server) randomETH1DataVote(ctx context.Context, reason string) (*ethpb.Eth1Data, error) {
|
||||
log.WithField("reason", reason).Warn("randomETH1DataVote")
|
||||
if !eth1DataNotification {
|
||||
log.Warn("Beacon Node is no longer connected to an ETH1 chain, so ETH1 data votes are now random.")
|
||||
eth1DataNotification = true
|
||||
|
||||
@@ -12,11 +12,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
@@ -38,10 +40,17 @@ var (
|
||||
})
|
||||
)
|
||||
|
||||
// This returns the execution payload of a given slot. The function has full awareness of pre and post merge.
|
||||
// This returns the execution payload of a given slot.
|
||||
// The function has full awareness of pre and post merge.
|
||||
// The payload is computed given the respected time of merge.
|
||||
func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx types.ValidatorIndex, headRoot [32]byte) (*enginev1.ExecutionPayload, error) {
|
||||
func (vs *Server) getExecutionPayload(ctx context.Context,
|
||||
slot types.Slot,
|
||||
vIdx types.ValidatorIndex,
|
||||
headRoot [32]byte,
|
||||
st state.BeaconState) (interfaces.ExecutionData, error) {
|
||||
proposerID, payloadId, ok := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, headRoot)
|
||||
log.Infof("getExecutionPayload, GetProposerPayloadIDs(slot=%d, arg.headRoot=%#x,has=%v,pid=%#x,proposerIdx=%d)", slot, headRoot, ok, payloadId, proposerID)
|
||||
|
||||
feeRecipient := params.BeaconConfig().DefaultFeeRecipient
|
||||
recipient, err := vs.BeaconDB.FeeRecipientByValidatorID(ctx, vIdx)
|
||||
switch err == nil {
|
||||
@@ -67,10 +76,10 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
var pid [8]byte
|
||||
copy(pid[:], payloadId[:])
|
||||
payloadIDCacheHit.Inc()
|
||||
payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, pid)
|
||||
payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, pid, slot)
|
||||
switch {
|
||||
case err == nil:
|
||||
warnIfFeeRecipientDiffers(payload, feeRecipient)
|
||||
warnIfFeeRecipientDiffers(payload.FeeRecipient(), feeRecipient)
|
||||
return payload, nil
|
||||
case errors.Is(err, context.DeadlineExceeded):
|
||||
default:
|
||||
@@ -78,15 +87,6 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
}
|
||||
}
|
||||
|
||||
st, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, err = transition.ProcessSlotsIfPossible(ctx, st, slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var parentHash []byte
|
||||
var hasTerminalBlock bool
|
||||
mergeComplete, err := blocks.IsMergeTransitionComplete(st)
|
||||
@@ -106,14 +106,14 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
parentHash = header.BlockHash()
|
||||
} else {
|
||||
if activationEpochNotReached(slot) {
|
||||
return emptyPayload(), nil
|
||||
return emptyPayload()
|
||||
}
|
||||
parentHash, hasTerminalBlock, err = vs.getTerminalBlockHashIfExists(ctx, uint64(t.Unix()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasTerminalBlock {
|
||||
return emptyPayload(), nil
|
||||
return emptyPayload()
|
||||
}
|
||||
}
|
||||
payloadIDCacheMiss.Inc()
|
||||
@@ -149,10 +149,13 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
FinalizedBlockHash: finalizedBlockHash,
|
||||
}
|
||||
|
||||
p := &enginev1.PayloadAttributes{
|
||||
p, err := payloadattribute.New(&enginev1.PayloadAttributes{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
PrevRandao: random,
|
||||
SuggestedFeeRecipient: feeRecipient.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, p)
|
||||
if err != nil {
|
||||
@@ -161,22 +164,22 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
if payloadID == nil {
|
||||
return nil, fmt.Errorf("nil payload with block hash: %#x", parentHash)
|
||||
}
|
||||
payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, *payloadID)
|
||||
payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, *payloadID, slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
warnIfFeeRecipientDiffers(payload, feeRecipient)
|
||||
warnIfFeeRecipientDiffers(payload.FeeRecipient(), feeRecipient)
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// warnIfFeeRecipientDiffers logs a warning if the fee recipient in the included payload does not
|
||||
// match the requested one.
|
||||
func warnIfFeeRecipientDiffers(payload *enginev1.ExecutionPayload, feeRecipient common.Address) {
|
||||
func warnIfFeeRecipientDiffers(payloadRecipient []byte, feeRecipient common.Address) {
|
||||
// Warn if the fee recipient is not the value we expect.
|
||||
if payload != nil && !bytes.Equal(payload.FeeRecipient, feeRecipient[:]) {
|
||||
if !bytes.Equal(payloadRecipient, feeRecipient[:]) {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"wantedFeeRecipient": fmt.Sprintf("%#x", feeRecipient),
|
||||
"received": fmt.Sprintf("%#x", payload.FeeRecipient),
|
||||
"received": fmt.Sprintf("%#x", payloadRecipient),
|
||||
}).Warn("Fee recipient address from execution client is not what was expected. " +
|
||||
"It is possible someone has compromised your client to try and take your transaction fees")
|
||||
}
|
||||
@@ -228,8 +231,8 @@ func activationEpochNotReached(slot types.Slot) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func emptyPayload() *enginev1.ExecutionPayload {
|
||||
return &enginev1.ExecutionPayload{
|
||||
func emptyPayload() (interfaces.ExecutionData, error) {
|
||||
return consensusblocks.WrappedExecutionPayload(&enginev1.ExecutionPayload{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
@@ -238,5 +241,5 @@ func emptyPayload() *enginev1.ExecutionPayload {
|
||||
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -231,8 +231,8 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
|
||||
name string
|
||||
paramsTerminalHash []byte
|
||||
paramsTd string
|
||||
currentPowBlock *pb.ExecutionBlock
|
||||
parentPowBlock *pb.ExecutionBlock
|
||||
currentPowBlock *pb.ExecutionBlockBellatrix
|
||||
parentPowBlock *pb.ExecutionBlockBellatrix
|
||||
wantTerminalBlockHash []byte
|
||||
wantExists bool
|
||||
errString string
|
||||
@@ -253,14 +253,14 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
|
||||
{
|
||||
name: "use terminal total difficulty",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
parentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("b")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("c")),
|
||||
@@ -273,7 +273,7 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
|
||||
{
|
||||
name: "use terminal total difficulty but fails timestamp",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
currentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("a")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("b")),
|
||||
@@ -281,7 +281,7 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
|
||||
},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
parentPowBlock: &pb.ExecutionBlockBellatrix{
|
||||
Hash: common.BytesToHash([]byte("b")),
|
||||
Header: gethtypes.Header{
|
||||
ParentHash: common.BytesToHash([]byte("c")),
|
||||
@@ -296,9 +296,9 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
|
||||
cfg.TerminalTotalDifficulty = tt.paramsTd
|
||||
cfg.TerminalBlockHash = common.BytesToHash(tt.paramsTerminalHash)
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
var m map[[32]byte]*pb.ExecutionBlock
|
||||
var m map[[32]byte]*pb.ExecutionBlockBellatrix
|
||||
if tt.parentPowBlock != nil {
|
||||
m = map[[32]byte]*pb.ExecutionBlock{
|
||||
m = map[[32]byte]*pb.ExecutionBlockBellatrix{
|
||||
tt.parentPowBlock.Hash: tt.parentPowBlock,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop"
|
||||
v "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// blockData required to create a beacon block.
|
||||
type blockData struct {
|
||||
ParentRoot []byte
|
||||
Graffiti [32]byte
|
||||
ProposerIdx types.ValidatorIndex
|
||||
Eth1Data *ethpb.Eth1Data
|
||||
Deposits []*ethpb.Deposit
|
||||
Attestations []*ethpb.Attestation
|
||||
ProposerSlashings []*ethpb.ProposerSlashing
|
||||
AttesterSlashings []*ethpb.AttesterSlashing
|
||||
VoluntaryExits []*ethpb.SignedVoluntaryExit
|
||||
}
|
||||
|
||||
func (vs *Server) getPhase0BeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlock, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.getPhase0BeaconBlock")
|
||||
defer span.End()
|
||||
blkData, err := vs.buildPhase0BlockData(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not build block data: %v", err)
|
||||
}
|
||||
|
||||
// Use zero hash as stub for state root to compute later.
|
||||
stateRoot := params.BeaconConfig().ZeroHash[:]
|
||||
|
||||
blk := ðpb.BeaconBlock{
|
||||
Slot: req.Slot,
|
||||
ParentRoot: blkData.ParentRoot,
|
||||
StateRoot: stateRoot,
|
||||
ProposerIndex: blkData.ProposerIdx,
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
Eth1Data: blkData.Eth1Data,
|
||||
Deposits: blkData.Deposits,
|
||||
Attestations: blkData.Attestations,
|
||||
RandaoReveal: req.RandaoReveal,
|
||||
ProposerSlashings: blkData.ProposerSlashings,
|
||||
AttesterSlashings: blkData.AttesterSlashings,
|
||||
VoluntaryExits: blkData.VoluntaryExits,
|
||||
Graffiti: blkData.Graffiti[:],
|
||||
},
|
||||
}
|
||||
|
||||
// Compute state root with the newly constructed block.
|
||||
wsb, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: blk, Signature: make([]byte, 96)})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stateRoot, err = vs.computeStateRoot(ctx, wsb)
|
||||
if err != nil {
|
||||
interop.WriteBlockToDisk(wsb, true /*failed*/)
|
||||
return nil, errors.Wrap(err, "could not compute state root")
|
||||
}
|
||||
blk.StateRoot = stateRoot
|
||||
return blk, nil
|
||||
}
|
||||
|
||||
// Build data required for creating a new beacon block, so this method can be shared across forks.
|
||||
func (vs *Server) buildPhase0BlockData(ctx context.Context, req *ethpb.BlockRequest) (*blockData, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.buildPhase0BlockData")
|
||||
defer span.End()
|
||||
|
||||
if vs.SyncChecker.Syncing() {
|
||||
return nil, fmt.Errorf("syncing to latest head, not ready to respond")
|
||||
}
|
||||
|
||||
if err := vs.HeadUpdater.UpdateHead(ctx); err != nil {
|
||||
log.WithError(err).Error("Could not process attestations and update head")
|
||||
}
|
||||
|
||||
// Retrieve the parent block as the current head of the canonical chain.
|
||||
parentRoot, err := vs.HeadFetcher.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retrieve head root: %v", err)
|
||||
}
|
||||
|
||||
head, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get head state %v", err)
|
||||
}
|
||||
|
||||
head, err = transition.ProcessSlotsUsingNextSlotCache(ctx, head, parentRoot, req.Slot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not advance slots to calculate proposer index: %v", err)
|
||||
}
|
||||
|
||||
eth1Data, err := vs.eth1DataMajorityVote(ctx, head)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get ETH1 data: %v", err)
|
||||
}
|
||||
|
||||
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
graffiti := bytesutil.ToBytes32(req.Graffiti)
|
||||
|
||||
// Calculate new proposer index.
|
||||
idx, err := helpers.BeaconProposerIndex(ctx, head)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not calculate proposer index %v", err)
|
||||
}
|
||||
|
||||
proposerSlashings := vs.SlashingsPool.PendingProposerSlashings(ctx, head, false /*noLimit*/)
|
||||
validProposerSlashings := make([]*ethpb.ProposerSlashing, 0, len(proposerSlashings))
|
||||
for _, slashing := range proposerSlashings {
|
||||
_, err := blocks.ProcessProposerSlashing(ctx, head, slashing, v.SlashValidator)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid proposer slashing")
|
||||
continue
|
||||
}
|
||||
validProposerSlashings = append(validProposerSlashings, slashing)
|
||||
}
|
||||
|
||||
attSlashings := vs.SlashingsPool.PendingAttesterSlashings(ctx, head, false /*noLimit*/)
|
||||
validAttSlashings := make([]*ethpb.AttesterSlashing, 0, len(attSlashings))
|
||||
for _, slashing := range attSlashings {
|
||||
_, err := blocks.ProcessAttesterSlashing(ctx, head, slashing, v.SlashValidator)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid attester slashing")
|
||||
continue
|
||||
}
|
||||
validAttSlashings = append(validAttSlashings, slashing)
|
||||
}
|
||||
exits := vs.ExitPool.PendingExits(head, req.Slot, false /*noLimit*/)
|
||||
validExits := make([]*ethpb.SignedVoluntaryExit, 0, len(exits))
|
||||
for _, exit := range exits {
|
||||
val, err := head.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid exit")
|
||||
continue
|
||||
}
|
||||
if err := blocks.VerifyExitAndSignature(val, head.Slot(), head.Fork(), exit, head.GenesisValidatorsRoot()); err != nil {
|
||||
log.WithError(err).Warn("Proposer: invalid exit")
|
||||
continue
|
||||
}
|
||||
validExits = append(validExits, exit)
|
||||
}
|
||||
|
||||
return &blockData{
|
||||
ParentRoot: parentRoot,
|
||||
Graffiti: graffiti,
|
||||
ProposerIdx: idx,
|
||||
Eth1Data: eth1Data,
|
||||
Deposits: deposits,
|
||||
Attestations: atts,
|
||||
ProposerSlashings: validProposerSlashings,
|
||||
AttesterSlashings: validAttSlashings,
|
||||
VoluntaryExits: validExits,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/execution"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits"
|
||||
@@ -62,6 +63,7 @@ type Server struct {
|
||||
SlashingsPool slashings.PoolManager
|
||||
ExitPool voluntaryexits.PoolManager
|
||||
SyncCommitteePool synccommittee.Pool
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
BlockReceiver blockchain.BlockReceiver
|
||||
MockEth1Votes bool
|
||||
Eth1BlockFetcher execution.POWBlockFetcher
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/execution"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits"
|
||||
@@ -99,6 +100,7 @@ type Config struct {
|
||||
SlashingsPool slashings.PoolManager
|
||||
SlashingChecker slasherservice.SlashingChecker
|
||||
SyncCommitteeObjectPool synccommittee.Pool
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
SyncService chainSync.Checker
|
||||
Broadcaster p2p.Broadcaster
|
||||
PeersFetcher p2p.PeersProvider
|
||||
@@ -216,6 +218,7 @@ func (s *Service) Start() {
|
||||
SlashingsPool: s.cfg.SlashingsPool,
|
||||
StateGen: s.cfg.StateGen,
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
BLSChangesPool: s.cfg.BLSChangesPool,
|
||||
ReplayerBuilder: ch,
|
||||
ExecutionEngineCaller: s.cfg.ExecutionEngineCaller,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
@@ -240,6 +243,7 @@ func (s *Service) Start() {
|
||||
ReplayerBuilder: ch,
|
||||
},
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
BLSChangesPool: s.cfg.BLSChangesPool,
|
||||
ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
|
||||
}
|
||||
|
||||
@@ -292,6 +296,7 @@ func (s *Service) Start() {
|
||||
ReceivedAttestationsBuffer: make(chan *ethpbv1alpha1.Attestation, attestationBufferSize),
|
||||
CollectedAttestationsBuffer: make(chan []*ethpbv1alpha1.Attestation, attestationBufferSize),
|
||||
ReplayerBuilder: ch,
|
||||
BLSChangesPool: s.cfg.BLSChangesPool,
|
||||
}
|
||||
beaconChainServerV1 := &beacon.Server{
|
||||
CanonicalHistory: ch,
|
||||
@@ -318,6 +323,7 @@ func (s *Service) Start() {
|
||||
V1Alpha1ValidatorServer: validatorServer,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
ExecutionPayloadReconstructor: s.cfg.ExecutionPayloadReconstructor,
|
||||
BLSChangesPool: s.cfg.BLSChangesPool,
|
||||
}
|
||||
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
||||
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
@@ -48,7 +49,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, params.BeaconConfig().MaxWithdrawalsPerPayload)
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, fieldparams.MaxWithdrawalsPerPayload)
|
||||
validatorIndex := b.nextWithdrawalValidatorIndex
|
||||
withdrawalIndex := b.nextWithdrawalIndex
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
@@ -57,22 +58,22 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
balance := b.balances[validatorIndex]
|
||||
if balance > 0 && isFullyWithdrawableValidator(val, epoch) {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
WithdrawalIndex: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
ExecutionAddress: bytesutil.SafeCopyBytes(val.WithdrawalCredentials[ETH1AddressOffset:]),
|
||||
Amount: balance,
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
Address: bytesutil.SafeCopyBytes(val.WithdrawalCredentials[ETH1AddressOffset:]),
|
||||
Amount: balance,
|
||||
})
|
||||
withdrawalIndex++
|
||||
} else if isPartiallyWithdrawableValidator(val, balance) {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
WithdrawalIndex: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
ExecutionAddress: bytesutil.SafeCopyBytes(val.WithdrawalCredentials[ETH1AddressOffset:]),
|
||||
Amount: balance - params.BeaconConfig().MaxEffectiveBalance,
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
Address: bytesutil.SafeCopyBytes(val.WithdrawalCredentials[ETH1AddressOffset:]),
|
||||
Amount: balance - params.BeaconConfig().MaxEffectiveBalance,
|
||||
})
|
||||
withdrawalIndex++
|
||||
}
|
||||
if uint64(len(withdrawals)) == params.BeaconConfig().MaxWithdrawalsPerPayload {
|
||||
if uint64(len(withdrawals)) == fieldparams.MaxWithdrawalsPerPayload {
|
||||
break
|
||||
}
|
||||
validatorIndex += 1
|
||||
|
||||
@@ -26,7 +26,7 @@ func TestNextWithdrawalIndex(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestLastWithdrawalValidatorIndex(t *testing.T) {
|
||||
func TestNextWithdrawalValidatorIndex(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
s := BeaconState{version: version.Capella, nextWithdrawalValidatorIndex: 123}
|
||||
i, err := s.NextWithdrawalValidatorIndex()
|
||||
@@ -153,10 +153,10 @@ func TestExpectedWithdrawals(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
WithdrawalIndex: 0,
|
||||
ValidatorIndex: 3,
|
||||
ExecutionAddress: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[3],
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[3],
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
@@ -181,10 +181,10 @@ func TestExpectedWithdrawals(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
WithdrawalIndex: 0,
|
||||
ValidatorIndex: 3,
|
||||
ExecutionAddress: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
@@ -212,16 +212,16 @@ func TestExpectedWithdrawals(t *testing.T) {
|
||||
require.Equal(t, 2, len(expected))
|
||||
|
||||
withdrawalFull := &enginev1.Withdrawal{
|
||||
WithdrawalIndex: 1,
|
||||
ValidatorIndex: 7,
|
||||
ExecutionAddress: s.validators[7].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[7],
|
||||
Index: 1,
|
||||
ValidatorIndex: 7,
|
||||
Address: s.validators[7].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[7],
|
||||
}
|
||||
withdrawalPartial := &enginev1.Withdrawal{
|
||||
WithdrawalIndex: 0,
|
||||
ValidatorIndex: 3,
|
||||
ExecutionAddress: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawalPartial, expected[0])
|
||||
require.DeepEqual(t, withdrawalFull, expected[1])
|
||||
@@ -246,10 +246,10 @@ func TestExpectedWithdrawals(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
WithdrawalIndex: 0,
|
||||
ValidatorIndex: 0,
|
||||
ExecutionAddress: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: 1,
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
@@ -273,10 +273,10 @@ func TestExpectedWithdrawals(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
WithdrawalIndex: 0,
|
||||
ValidatorIndex: 0,
|
||||
ExecutionAddress: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance,
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
@@ -300,10 +300,10 @@ func TestExpectedWithdrawals(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
WithdrawalIndex: 0,
|
||||
ValidatorIndex: 0,
|
||||
ExecutionAddress: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance + 1,
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance + 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
|
||||
@@ -20,7 +20,7 @@ func (b *BeaconState) SetNextWithdrawalIndex(i uint64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLastWithdrawalValidatorIndex sets the index of the validator which is
|
||||
// SetNexWithdrawalValidatorIndex sets the index of the validator which is
|
||||
// next in line for a partial withdrawal.
|
||||
func (b *BeaconState) SetNextWithdrawalValidatorIndex(i types.ValidatorIndex) error {
|
||||
if b.version < version.Capella {
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestSetNextWithdrawalIndex(t *testing.T) {
|
||||
require.Equal(t, true, s.dirtyFields[nativetypes.NextWithdrawalIndex])
|
||||
}
|
||||
|
||||
func TestSetLastWithdrawalValidatorIndex(t *testing.T) {
|
||||
func TestSetNextWithdrawalValidatorIndex(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
nextWithdrawalValidatorIndex: 3,
|
||||
|
||||
@@ -75,7 +75,7 @@ func (s *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
||||
}
|
||||
|
||||
if blk.Block().IsBlinded() {
|
||||
blk, err = s.cfg.executionPayloadReconstructor.ReconstructFullBellatrixBlock(ctx, blk)
|
||||
blk, err = s.cfg.executionPayloadReconstructor.ReconstructFullBlock(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)
|
||||
|
||||
@@ -54,7 +54,7 @@ func (s *Service) goodbyeRPCHandler(_ context.Context, msg interface{}, stream l
|
||||
|
||||
// disconnectBadPeer checks whether peer is considered bad by some scorer, and tries to disconnect
|
||||
// the peer, if that is the case. Additionally, disconnection reason is obtained from scorer.
|
||||
func (s *Service) disconnectBadPeer(ctx context.Context, id peer.ID) {
|
||||
func (s *Service) disconnectBadPeer(ctx context.Context, id peer.ID, from string) {
|
||||
if !s.cfg.p2p.Peers().IsBad(id) {
|
||||
return
|
||||
}
|
||||
@@ -63,6 +63,7 @@ func (s *Service) disconnectBadPeer(ctx context.Context, id peer.ID) {
|
||||
if err == nil {
|
||||
goodbyeCode = p2ptypes.GoodbyeCodeBanned
|
||||
}
|
||||
log.Infof("disconnectBadPeer from %s", from)
|
||||
if err := s.sendGoodByeAndDisconnect(ctx, goodbyeCode, id); err != nil {
|
||||
log.WithError(err).Debug("Error when disconnecting with bad peer")
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (s *Service) maintainPeerStatuses() {
|
||||
}
|
||||
// Disconnect from peers that are considered bad by any of the registered scorers.
|
||||
if s.cfg.p2p.Peers().IsBad(id) {
|
||||
s.disconnectBadPeer(s.ctx, id)
|
||||
s.disconnectBadPeer(s.ctx, id, "maintainPeerStatuses")
|
||||
return
|
||||
}
|
||||
// If the status hasn't been updated in the recent interval time.
|
||||
@@ -170,7 +170,7 @@ func (s *Service) sendRPCStatusRequest(ctx context.Context, id peer.ID) error {
|
||||
err = s.validateStatusMessage(ctx, msg)
|
||||
s.cfg.p2p.Peers().Scorers().PeerStatusScorer().SetPeerStatus(id, msg, err)
|
||||
if s.cfg.p2p.Peers().IsBad(id) {
|
||||
s.disconnectBadPeer(s.ctx, id)
|
||||
s.disconnectBadPeer(s.ctx, id, "sendRPCStatusRequest")
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -222,6 +222,11 @@ func (s *Service) statusRPCHandler(ctx context.Context, msg interface{}, stream
|
||||
}
|
||||
// Close before disconnecting, and wait for the other end to ack our response.
|
||||
closeStreamAndWait(stream, log)
|
||||
forkDigest, err := s.currentForkDigest()
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to compute fork digest")
|
||||
}
|
||||
log.Errorf("fork digest mismatch, expected=%#x, saw=%#x", forkDigest, m.ForkDigest)
|
||||
if err := s.sendGoodByeAndDisconnect(ctx, p2ptypes.GoodbyeCodeWrongNetwork, remotePeer); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -326,6 +326,7 @@ func (s *Service) subscribeStaticWithSubnets(topic string, validator wrappedVal,
|
||||
return
|
||||
case <-ticker.C():
|
||||
if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() {
|
||||
log.Debug("(subscribeStaticWithSubnets) chain started set, but in initial sync")
|
||||
continue
|
||||
}
|
||||
valid, err := isDigestValid(digest, genesis, genRoot)
|
||||
@@ -396,6 +397,7 @@ func (s *Service) subscribeDynamicWithSubnets(
|
||||
return
|
||||
case currentSlot := <-ticker.C():
|
||||
if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() {
|
||||
log.Debug("(subscribeDynamicWithSubnets) chain started set, but in initial sync")
|
||||
continue
|
||||
}
|
||||
valid, err := isDigestValid(digest, genesis, genRoot)
|
||||
@@ -526,6 +528,7 @@ func (s *Service) subscribeStaticWithSyncSubnets(topic string, validator wrapped
|
||||
return
|
||||
case <-ticker.C():
|
||||
if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() {
|
||||
log.Debug("(subscribeStaticWithSyncSubnets) chain started set, but in initial sync")
|
||||
continue
|
||||
}
|
||||
valid, err := isDigestValid(digest, genesis, genRoot)
|
||||
@@ -595,6 +598,7 @@ func (s *Service) subscribeDynamicWithSyncSubnets(
|
||||
return
|
||||
case currentSlot := <-ticker.C():
|
||||
if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() {
|
||||
log.Debug("(subscribeDynamicWithSyncSubnets) chain started set, but in initial sync")
|
||||
continue
|
||||
}
|
||||
valid, err := isDigestValid(digest, genesis, genRoot)
|
||||
|
||||
@@ -57,7 +57,7 @@ func (s *Service) validateBlsToExecutionChange(ctx context.Context, pid peer.ID,
|
||||
return pubsub.ValidationReject, err
|
||||
}
|
||||
// Validate the signature of the message using our batch gossip verifier.
|
||||
sigBatch, err := blocks.BLSChangesSignatureBatch(ctx, st, []*ethpb.SignedBLSToExecutionChange{blsChange})
|
||||
sigBatch, err := blocks.BLSChangesSignatureBatch(st, []*ethpb.SignedBLSToExecutionChange{blsChange})
|
||||
if err != nil {
|
||||
return pubsub.ValidationReject, err
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c
|
||||
disableBroadcastSlashingFlag,
|
||||
enableSlasherFlag,
|
||||
enableHistoricalSpaceRepresentation,
|
||||
disableStakinContractCheck,
|
||||
disablePullTips,
|
||||
disableVecHTR,
|
||||
disableForkChoiceDoublyLinkedTree,
|
||||
|
||||
@@ -226,6 +226,8 @@ func configForkSchedule(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt
|
||||
fvs[bytesutil.ToBytes4(b.AltairForkVersion)] = b.AltairForkEpoch
|
||||
// Set Bellatrix fork data.
|
||||
fvs[bytesutil.ToBytes4(b.BellatrixForkVersion)] = b.BellatrixForkEpoch
|
||||
// Set Capella fork data.
|
||||
fvs[bytesutil.ToBytes4(b.CapellaForkVersion)] = b.CapellaForkEpoch
|
||||
return fvs
|
||||
}
|
||||
|
||||
@@ -237,5 +239,7 @@ func configForkNames(b *BeaconChainConfig) map[[fieldparams.VersionLength]byte]s
|
||||
fvn[bytesutil.ToBytes4(b.AltairForkVersion)] = "altair"
|
||||
// Set Bellatrix fork data.
|
||||
fvn[bytesutil.ToBytes4(b.BellatrixForkVersion)] = "bellatrix"
|
||||
// Set Capella fork data.
|
||||
fvn[bytesutil.ToBytes4(b.CapellaForkVersion)] = "capella"
|
||||
return fvn
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ func InteropConfig() *BeaconChainConfig {
|
||||
c.GenesisForkVersion = []byte{0, 0, 0, 235}
|
||||
c.AltairForkVersion = []byte{1, 0, 0, 235}
|
||||
c.BellatrixForkVersion = []byte{2, 0, 0, 235}
|
||||
c.ShardingForkVersion = []byte{3, 0, 0, 235}
|
||||
c.CapellaForkVersion = []byte{3, 0, 0, 235}
|
||||
c.ShardingForkVersion = []byte{4, 0, 0, 235}
|
||||
|
||||
c.InitializeForkSchedule()
|
||||
return c
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package params
|
||||
|
||||
const (
|
||||
altairE2EForkEpoch = 6
|
||||
bellatrixE2EForkEpoch = 8
|
||||
altairE2EForkEpoch = 0
|
||||
bellatrixE2EForkEpoch = 0
|
||||
)
|
||||
|
||||
// E2ETestConfig retrieves the configurations made specifically for E2E testing.
|
||||
@@ -10,6 +10,8 @@ const (
|
||||
// WARNING: This config is only for testing, it is not meant for use outside of E2E.
|
||||
func E2ETestConfig() *BeaconChainConfig {
|
||||
e2eConfig := MinimalSpecConfig()
|
||||
e2eConfig.DepositContractAddress = "0x4242424242424242424242424242424242424242"
|
||||
e2eConfig.Eth1FollowDistance = 8
|
||||
|
||||
// Misc.
|
||||
e2eConfig.MinGenesisActiveValidatorCount = 256
|
||||
@@ -21,7 +23,6 @@ func E2ETestConfig() *BeaconChainConfig {
|
||||
e2eConfig.SlotsPerEpoch = 6
|
||||
e2eConfig.SqrRootSlotsPerEpoch = 2
|
||||
e2eConfig.SecondsPerETH1Block = 2
|
||||
e2eConfig.Eth1FollowDistance = 8
|
||||
e2eConfig.EpochsPerEth1VotingPeriod = 2
|
||||
e2eConfig.ShardCommitteePeriod = 4
|
||||
e2eConfig.MaxSeedLookahead = 1
|
||||
@@ -35,14 +36,15 @@ func E2ETestConfig() *BeaconChainConfig {
|
||||
e2eConfig.BellatrixForkEpoch = bellatrixE2EForkEpoch
|
||||
|
||||
// Terminal Total Difficulty.
|
||||
e2eConfig.TerminalTotalDifficulty = "616"
|
||||
e2eConfig.TerminalTotalDifficulty = "0"
|
||||
|
||||
// Prysm constants.
|
||||
e2eConfig.ConfigName = EndToEndName
|
||||
e2eConfig.GenesisForkVersion = []byte{0, 0, 0, 253}
|
||||
e2eConfig.AltairForkVersion = []byte{1, 0, 0, 253}
|
||||
e2eConfig.BellatrixForkVersion = []byte{2, 0, 0, 253}
|
||||
e2eConfig.ShardingForkVersion = []byte{3, 0, 0, 253}
|
||||
e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 253}
|
||||
e2eConfig.ShardingForkVersion = []byte{4, 0, 0, 253}
|
||||
|
||||
e2eConfig.InitializeForkSchedule()
|
||||
return e2eConfig
|
||||
@@ -50,6 +52,8 @@ func E2ETestConfig() *BeaconChainConfig {
|
||||
|
||||
func E2EMainnetTestConfig() *BeaconChainConfig {
|
||||
e2eConfig := MainnetConfig().Copy()
|
||||
e2eConfig.DepositContractAddress = "0x4242424242424242424242424242424242424242"
|
||||
e2eConfig.Eth1FollowDistance = 8
|
||||
|
||||
// Misc.
|
||||
e2eConfig.MinGenesisActiveValidatorCount = 256
|
||||
@@ -60,7 +64,6 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
|
||||
e2eConfig.SecondsPerSlot = 6
|
||||
e2eConfig.SqrRootSlotsPerEpoch = 5
|
||||
e2eConfig.SecondsPerETH1Block = 2
|
||||
e2eConfig.Eth1FollowDistance = 8
|
||||
e2eConfig.ShardCommitteePeriod = 4
|
||||
|
||||
// PoW parameters.
|
||||
@@ -72,14 +75,15 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
|
||||
e2eConfig.BellatrixForkEpoch = bellatrixE2EForkEpoch
|
||||
|
||||
// Terminal Total Difficulty.
|
||||
e2eConfig.TerminalTotalDifficulty = "616"
|
||||
e2eConfig.TerminalTotalDifficulty = "0"
|
||||
|
||||
// Prysm constants.
|
||||
e2eConfig.ConfigName = EndToEndMainnetName
|
||||
e2eConfig.GenesisForkVersion = []byte{0, 0, 0, 254}
|
||||
e2eConfig.AltairForkVersion = []byte{1, 0, 0, 254}
|
||||
e2eConfig.BellatrixForkVersion = []byte{2, 0, 0, 254}
|
||||
e2eConfig.ShardingForkVersion = []byte{3, 0, 0, 254}
|
||||
e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 254}
|
||||
e2eConfig.ShardingForkVersion = []byte{4, 0, 0, 254}
|
||||
|
||||
e2eConfig.InitializeForkSchedule()
|
||||
return e2eConfig
|
||||
|
||||
@@ -32,6 +32,7 @@ func RopstenConfig() *BeaconChainConfig {
|
||||
cfg.AltairForkVersion = []byte{0x80, 0x00, 0x00, 0x70}
|
||||
cfg.BellatrixForkEpoch = 750
|
||||
cfg.BellatrixForkVersion = []byte{0x80, 0x00, 0x00, 0x71}
|
||||
cfg.CapellaForkVersion = []byte{0x80, 0x00, 0x00, 0x72}
|
||||
cfg.TerminalTotalDifficulty = "50000000000000000"
|
||||
cfg.DepositContractAddress = "0x6f22fFbC56eFF051aECF839396DD1eD9aD6BBA9D"
|
||||
cfg.InitializeForkSchedule()
|
||||
|
||||
@@ -155,6 +155,16 @@ func (e executionPayload) WithdrawalsRoot() ([]byte, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// PbV1 --
|
||||
func (e executionPayload) PbV1() (*enginev1.ExecutionPayload, error) {
|
||||
return e.p, nil
|
||||
}
|
||||
|
||||
// PbV2 --
|
||||
func (e executionPayload) PbV2() (*enginev1.ExecutionPayloadCapella, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// executionPayloadHeader is a convenience wrapper around a blinded beacon block body's execution header data structure
|
||||
// This wrapper allows us to conform to a common interface so that beacon
|
||||
// blocks for future forks can also be applied across Prysm without issues.
|
||||
@@ -296,6 +306,16 @@ func (e executionPayloadHeader) WithdrawalsRoot() ([]byte, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// PbV2 --
|
||||
func (e executionPayloadHeader) PbV2() (*enginev1.ExecutionPayloadCapella, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// PbV1 --
|
||||
func (e executionPayloadHeader) PbV1() (*enginev1.ExecutionPayload, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// PayloadToHeader converts `payload` into execution payload header format.
|
||||
func PayloadToHeader(payload interfaces.ExecutionData) (*enginev1.ExecutionPayloadHeader, error) {
|
||||
txs, err := payload.Transactions()
|
||||
@@ -465,6 +485,16 @@ func (e executionPayloadCapella) WithdrawalsRoot() ([]byte, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// PbV2 --
|
||||
func (e executionPayloadCapella) PbV2() (*enginev1.ExecutionPayloadCapella, error) {
|
||||
return e.p, nil
|
||||
}
|
||||
|
||||
// PbV1 --
|
||||
func (e executionPayloadCapella) PbV1() (*enginev1.ExecutionPayload, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// executionPayloadHeaderCapella is a convenience wrapper around a blinded beacon block body's execution header data structure
|
||||
// This wrapper allows us to conform to a common interface so that beacon
|
||||
// blocks for future forks can also be applied across Prysm without issues.
|
||||
@@ -606,6 +636,16 @@ func (e executionPayloadHeaderCapella) WithdrawalsRoot() ([]byte, error) {
|
||||
return e.p.WithdrawalsRoot, nil
|
||||
}
|
||||
|
||||
// PbV2 --
|
||||
func (e executionPayloadHeaderCapella) PbV2() (*enginev1.ExecutionPayloadCapella, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// PbV1 --
|
||||
func (e executionPayloadHeaderCapella) PbV1() (*enginev1.ExecutionPayload, error) {
|
||||
return nil, ErrUnsupportedGetter
|
||||
}
|
||||
|
||||
// PayloadToHeaderCapella converts `payload` into execution payload header format.
|
||||
func PayloadToHeaderCapella(payload interfaces.ExecutionData) (*enginev1.ExecutionPayloadHeaderCapella, error) {
|
||||
txs, err := payload.Transactions()
|
||||
|
||||
@@ -23,7 +23,8 @@ var (
|
||||
// ErrNilObject is returned in a constructor when the underlying object is nil.
|
||||
ErrNilObject = errors.New("received nil object")
|
||||
// ErrNilSignedBeaconBlock is returned when a nil signed beacon block is received.
|
||||
ErrNilSignedBeaconBlock = errors.New("signed beacon block can't be nil")
|
||||
ErrNilSignedBeaconBlock = errors.New("signed beacon block can't be nil")
|
||||
errNonBlindedSignedBeaconBlock = errors.New("can only build signed beacon block from blinded format")
|
||||
)
|
||||
|
||||
// NewSignedBeaconBlock creates a signed beacon block from a protobuf signed beacon block.
|
||||
@@ -177,14 +178,13 @@ func BuildSignedBeaconBlockFromExecutionPayload(
|
||||
if err := BeaconBlockIsNil(blk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !blk.IsBlinded() {
|
||||
return nil, errNonBlindedSignedBeaconBlock
|
||||
}
|
||||
b := blk.Block()
|
||||
payloadHeader, err := b.Body().Execution()
|
||||
switch {
|
||||
case errors.Is(err, ErrUnsupportedGetter):
|
||||
return nil, errors.Wrap(err, "can only build signed beacon block from blinded format")
|
||||
case err != nil:
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload header")
|
||||
default:
|
||||
}
|
||||
|
||||
var wrappedPayload interfaces.ExecutionData
|
||||
|
||||
@@ -332,14 +332,14 @@ func TestBuildSignedBeaconBlockFromExecutionPayload(t *testing.T) {
|
||||
_, err := BuildSignedBeaconBlockFromExecutionPayload(nil, nil)
|
||||
require.ErrorIs(t, ErrNilSignedBeaconBlock, err)
|
||||
})
|
||||
t.Run("unsupported field payload header", func(t *testing.T) {
|
||||
t.Run("not blinded payload", func(t *testing.T) {
|
||||
altairBlock := ð.SignedBeaconBlockAltair{
|
||||
Block: ð.BeaconBlockAltair{
|
||||
Body: ð.BeaconBlockBodyAltair{}}}
|
||||
blk, err := NewSignedBeaconBlock(altairBlock)
|
||||
require.NoError(t, err)
|
||||
_, err = BuildSignedBeaconBlockFromExecutionPayload(blk, nil)
|
||||
require.Equal(t, true, errors.Is(err, ErrUnsupportedGetter))
|
||||
require.Equal(t, true, errors.Is(err, errNonBlindedSignedBeaconBlock))
|
||||
})
|
||||
t.Run("payload header root and payload root mismatch", func(t *testing.T) {
|
||||
blockHash := bytesutil.Bytes32(1)
|
||||
|
||||
@@ -29,11 +29,63 @@ func (b *SignedBeaconBlock) Signature() [field_params.BLSSignatureLength]byte {
|
||||
return b.signature
|
||||
}
|
||||
|
||||
// SetSignature sets the signature of the signed beacon block.
|
||||
func (b *SignedBeaconBlock) SetSignature(sig []byte) {
|
||||
copy(b.signature[:], sig)
|
||||
}
|
||||
|
||||
// Block returns the underlying beacon block object.
|
||||
func (b *SignedBeaconBlock) Block() interfaces.BeaconBlock {
|
||||
return b.block
|
||||
}
|
||||
|
||||
// SetBlock sets the underlying beacon block object.
|
||||
func (b *SignedBeaconBlock) SetBlock(blk interfaces.BeaconBlock) error {
|
||||
copied, err := blk.Copy()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.block.slot = copied.Slot()
|
||||
b.block.parentRoot = copied.ParentRoot()
|
||||
b.block.stateRoot = copied.StateRoot()
|
||||
b.block.stateRoot = copied.StateRoot()
|
||||
b.block.proposerIndex = copied.ProposerIndex()
|
||||
b.block.body.randaoReveal = copied.Body().RandaoReveal()
|
||||
b.block.body.eth1Data = copied.Body().Eth1Data()
|
||||
b.block.body.graffiti = copied.Body().Graffiti()
|
||||
b.block.body.proposerSlashings = copied.Body().ProposerSlashings()
|
||||
b.block.body.attesterSlashings = copied.Body().AttesterSlashings()
|
||||
b.block.body.attestations = copied.Body().Attestations()
|
||||
b.block.body.deposits = copied.Body().Deposits()
|
||||
b.block.body.voluntaryExits = copied.Body().VoluntaryExits()
|
||||
if b.version >= version.Altair {
|
||||
syncAggregate, err := copied.Body().SyncAggregate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.block.body.syncAggregate = syncAggregate
|
||||
}
|
||||
if b.version >= version.Bellatrix {
|
||||
executionData, err := copied.Body().Execution()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b.block.body.isBlinded {
|
||||
b.block.body.executionPayloadHeader = executionData
|
||||
} else {
|
||||
b.block.body.executionPayload = executionData
|
||||
}
|
||||
}
|
||||
if b.version >= version.Capella {
|
||||
changes, err := copied.Body().BLSToExecutionChanges()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.block.body.blsToExecutionChanges = changes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsNil checks if the underlying beacon block is nil.
|
||||
func (b *SignedBeaconBlock) IsNil() bool {
|
||||
return b == nil || b.block.IsNil()
|
||||
@@ -458,21 +510,46 @@ func (b *BeaconBlock) Slot() types.Slot {
|
||||
return b.slot
|
||||
}
|
||||
|
||||
// SetSlot sets the respective slot of the block.
|
||||
// This function is not thread safe, it is only used during block creation.
|
||||
func (b *BeaconBlock) SetSlot(slot types.Slot) {
|
||||
b.slot = slot
|
||||
}
|
||||
|
||||
// ProposerIndex returns the proposer index of the beacon block.
|
||||
func (b *BeaconBlock) ProposerIndex() types.ValidatorIndex {
|
||||
return b.proposerIndex
|
||||
}
|
||||
|
||||
// SetProposerIndex sets the proposer index of the beacon block.
|
||||
// This function is not thread safe, it is only used during block creation.
|
||||
func (b *BeaconBlock) SetProposerIndex(proposerIndex types.ValidatorIndex) {
|
||||
b.proposerIndex = proposerIndex
|
||||
}
|
||||
|
||||
// ParentRoot returns the parent root of beacon block.
|
||||
func (b *BeaconBlock) ParentRoot() [field_params.RootLength]byte {
|
||||
return b.parentRoot
|
||||
}
|
||||
|
||||
// SetParentRoot sets the parent root of beacon block.
|
||||
// This function is not thread safe, it is only used during block creation.
|
||||
func (b *BeaconBlock) SetParentRoot(parentRoot []byte) {
|
||||
copy(b.parentRoot[:], parentRoot)
|
||||
}
|
||||
|
||||
// StateRoot returns the state root of the beacon block.
|
||||
func (b *BeaconBlock) StateRoot() [field_params.RootLength]byte {
|
||||
return b.stateRoot
|
||||
}
|
||||
|
||||
// SetStateRoot sets the state root of the underlying beacon block
|
||||
// This function is not thread safe, it is only used during block
|
||||
// proposal to set the state root of a new block
|
||||
func (b *BeaconBlock) SetStateRoot(root []byte) {
|
||||
copy(b.stateRoot[:], root)
|
||||
}
|
||||
|
||||
// Body returns the underlying block body.
|
||||
func (b *BeaconBlock) Body() interfaces.BeaconBlockBody {
|
||||
return b.body
|
||||
@@ -488,6 +565,11 @@ func (b *BeaconBlock) IsBlinded() bool {
|
||||
return b.body.isBlinded
|
||||
}
|
||||
|
||||
// SetBlinded sets the blinded flag of the beacon block.
|
||||
func (b *BeaconBlock) SetBlinded(blinded bool) {
|
||||
b.body.isBlinded = blinded
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (b *BeaconBlock) Version() int {
|
||||
return b.version
|
||||
@@ -731,6 +813,41 @@ func (b *BeaconBlock) AsSignRequestObject() (validatorpb.SignRequestObject, erro
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BeaconBlock) Copy() (interfaces.BeaconBlock, error) {
|
||||
if b == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pb, err := b.Proto()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch b.version {
|
||||
case version.Phase0:
|
||||
cp := eth.CopyBeaconBlock(pb.(*eth.BeaconBlock))
|
||||
return initBlockFromProtoPhase0(cp)
|
||||
case version.Altair:
|
||||
cp := eth.CopyBeaconBlockAltair(pb.(*eth.BeaconBlockAltair))
|
||||
return initBlockFromProtoAltair(cp)
|
||||
case version.Bellatrix:
|
||||
if b.IsBlinded() {
|
||||
cp := eth.CopyBlindedBeaconBlockBellatrix(pb.(*eth.BlindedBeaconBlockBellatrix))
|
||||
return initBlindedBlockFromProtoBellatrix(cp)
|
||||
}
|
||||
cp := eth.CopyBeaconBlockBellatrix(pb.(*eth.BeaconBlockBellatrix))
|
||||
return initBlockFromProtoBellatrix(cp)
|
||||
case version.Capella:
|
||||
if b.IsBlinded() {
|
||||
cp := eth.CopyBlindedBeaconBlockCapella(pb.(*eth.BlindedBeaconBlockCapella))
|
||||
return initBlindedBlockFromProtoCapella(cp)
|
||||
}
|
||||
cp := eth.CopyBeaconBlockCapella(pb.(*eth.BeaconBlockCapella))
|
||||
return initBlockFromProtoCapella(cp)
|
||||
default:
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil checks if the block body is nil.
|
||||
func (b *BeaconBlockBody) IsNil() bool {
|
||||
return b == nil
|
||||
@@ -741,41 +858,81 @@ func (b *BeaconBlockBody) RandaoReveal() [field_params.BLSSignatureLength]byte {
|
||||
return b.randaoReveal
|
||||
}
|
||||
|
||||
// SetRandaoReveal sets the randao reveal in the block body.
|
||||
func (b *BeaconBlockBody) SetRandaoReveal(r []byte) {
|
||||
copy(b.randaoReveal[:], r)
|
||||
}
|
||||
|
||||
// Eth1Data returns the eth1 data in the block.
|
||||
func (b *BeaconBlockBody) Eth1Data() *eth.Eth1Data {
|
||||
return b.eth1Data
|
||||
}
|
||||
|
||||
// SetEth1Data sets the eth1 data in the block.
|
||||
func (b *BeaconBlockBody) SetEth1Data(e *eth.Eth1Data) {
|
||||
b.eth1Data = eth.CopyETH1Data(e)
|
||||
}
|
||||
|
||||
// Graffiti returns the graffiti in the block.
|
||||
func (b *BeaconBlockBody) Graffiti() [field_params.RootLength]byte {
|
||||
return b.graffiti
|
||||
}
|
||||
|
||||
// SetGraffiti sets the graffiti in the block.
|
||||
func (b *BeaconBlockBody) SetGraffiti(g []byte) {
|
||||
copy(b.graffiti[:], g)
|
||||
}
|
||||
|
||||
// ProposerSlashings returns the proposer slashings in the block.
|
||||
func (b *BeaconBlockBody) ProposerSlashings() []*eth.ProposerSlashing {
|
||||
return b.proposerSlashings
|
||||
}
|
||||
|
||||
// SetProposerSlashings sets the proposer slashings in the block.
|
||||
func (b *BeaconBlockBody) SetProposerSlashings(p []*eth.ProposerSlashing) {
|
||||
b.proposerSlashings = eth.CopyProposerSlashings(p)
|
||||
}
|
||||
|
||||
// AttesterSlashings returns the attester slashings in the block.
|
||||
func (b *BeaconBlockBody) AttesterSlashings() []*eth.AttesterSlashing {
|
||||
return b.attesterSlashings
|
||||
}
|
||||
|
||||
// SetAttesterSlashings sets the attester slashings in the block.
|
||||
func (b *BeaconBlockBody) SetAttesterSlashings(a []*eth.AttesterSlashing) {
|
||||
b.attesterSlashings = eth.CopyAttesterSlashings(a)
|
||||
}
|
||||
|
||||
// Attestations returns the stored attestations in the block.
|
||||
func (b *BeaconBlockBody) Attestations() []*eth.Attestation {
|
||||
return b.attestations
|
||||
}
|
||||
|
||||
// SetAttestations sets the attestations in the block.
|
||||
func (b *BeaconBlockBody) SetAttestations(a []*eth.Attestation) {
|
||||
b.attestations = eth.CopyAttestations(a)
|
||||
}
|
||||
|
||||
// Deposits returns the stored deposits in the block.
|
||||
func (b *BeaconBlockBody) Deposits() []*eth.Deposit {
|
||||
return b.deposits
|
||||
}
|
||||
|
||||
// SetDeposits sets the deposits in the block.
|
||||
func (b *BeaconBlockBody) SetDeposits(d []*eth.Deposit) {
|
||||
b.deposits = eth.CopyDeposits(d)
|
||||
}
|
||||
|
||||
// VoluntaryExits returns the voluntary exits in the block.
|
||||
func (b *BeaconBlockBody) VoluntaryExits() []*eth.SignedVoluntaryExit {
|
||||
return b.voluntaryExits
|
||||
}
|
||||
|
||||
// SetVoluntaryExits sets the voluntary exits in the block.
|
||||
func (b *BeaconBlockBody) SetVoluntaryExits(v []*eth.SignedVoluntaryExit) {
|
||||
b.voluntaryExits = eth.CopySignedVoluntaryExits(v)
|
||||
}
|
||||
|
||||
// SyncAggregate returns the sync aggregate in the block.
|
||||
func (b *BeaconBlockBody) SyncAggregate() (*eth.SyncAggregate, error) {
|
||||
if b.version == version.Phase0 {
|
||||
@@ -784,6 +941,15 @@ func (b *BeaconBlockBody) SyncAggregate() (*eth.SyncAggregate, error) {
|
||||
return b.syncAggregate, nil
|
||||
}
|
||||
|
||||
// SetSyncAggregate sets the sync aggregate in the block.
|
||||
func (b *BeaconBlockBody) SetSyncAggregate(s *eth.SyncAggregate) error {
|
||||
if b.version == version.Phase0 {
|
||||
return ErrNotSupported("SyncAggregate", b.version)
|
||||
}
|
||||
b.syncAggregate = eth.CopySyncAggregate(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execution returns the execution payload of the block body.
|
||||
func (b *BeaconBlockBody) Execution() (interfaces.ExecutionData, error) {
|
||||
switch b.version {
|
||||
@@ -836,6 +1002,19 @@ func (b *BeaconBlockBody) Execution() (interfaces.ExecutionData, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetExecution sets the execution payload of the block body.
|
||||
func (b *BeaconBlockBody) SetExecution(e interfaces.ExecutionData) error {
|
||||
if b.version == version.Phase0 || b.version == version.Altair {
|
||||
return ErrNotSupported("Execution", b.version)
|
||||
}
|
||||
if b.isBlinded {
|
||||
b.executionPayloadHeader = e // TODO: Copy?
|
||||
return nil
|
||||
}
|
||||
b.executionPayload = e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) BLSToExecutionChanges() ([]*eth.SignedBLSToExecutionChange, error) {
|
||||
if b.version < version.Capella {
|
||||
return nil, ErrNotSupported("BLSToExecutionChanges", b.version)
|
||||
@@ -843,6 +1022,15 @@ func (b *BeaconBlockBody) BLSToExecutionChanges() ([]*eth.SignedBLSToExecutionCh
|
||||
return b.blsToExecutionChanges, nil
|
||||
}
|
||||
|
||||
// SetBLSToExecutionChanges sets the BLS to execution changes in the block.
|
||||
func (b *BeaconBlockBody) SetBLSToExecutionChanges(blsToExecutionChanges []*eth.SignedBLSToExecutionChange) error {
|
||||
if b.version < version.Capella {
|
||||
return ErrNotSupported("BLSToExecutionChanges", b.version)
|
||||
}
|
||||
b.blsToExecutionChanges = eth.CopyBLSToExecutionChanges(blsToExecutionChanges)
|
||||
return nil
|
||||
}
|
||||
|
||||
// HashTreeRoot returns the ssz root of the block body.
|
||||
func (b *BeaconBlockBody) HashTreeRoot() ([field_params.RootLength]byte, error) {
|
||||
pb, err := b.Proto()
|
||||
|
||||
@@ -14,7 +14,9 @@ import (
|
||||
// a signed beacon block.
|
||||
type SignedBeaconBlock interface {
|
||||
Block() BeaconBlock
|
||||
SetBlock(BeaconBlock) error
|
||||
Signature() [field_params.BLSSignatureLength]byte
|
||||
SetSignature(sig []byte)
|
||||
IsNil() bool
|
||||
Copy() (SignedBeaconBlock, error)
|
||||
Proto() (proto.Message, error)
|
||||
@@ -37,12 +39,17 @@ type SignedBeaconBlock interface {
|
||||
// employed by an object that is a beacon block.
|
||||
type BeaconBlock interface {
|
||||
Slot() types.Slot
|
||||
SetSlot(slot types.Slot)
|
||||
ProposerIndex() types.ValidatorIndex
|
||||
SetProposerIndex(idx types.ValidatorIndex)
|
||||
ParentRoot() [field_params.RootLength]byte
|
||||
SetParentRoot([]byte)
|
||||
StateRoot() [field_params.RootLength]byte
|
||||
SetStateRoot([]byte)
|
||||
Body() BeaconBlockBody
|
||||
IsNil() bool
|
||||
IsBlinded() bool
|
||||
SetBlinded(bool)
|
||||
HashTreeRoot() ([field_params.RootLength]byte, error)
|
||||
Proto() (proto.Message, error)
|
||||
ssz.Marshaler
|
||||
@@ -50,25 +57,37 @@ type BeaconBlock interface {
|
||||
ssz.HashRoot
|
||||
Version() int
|
||||
AsSignRequestObject() (validatorpb.SignRequestObject, error)
|
||||
Copy() (BeaconBlock, error)
|
||||
}
|
||||
|
||||
// BeaconBlockBody describes the method set employed by an object
|
||||
// that is a beacon block body.
|
||||
type BeaconBlockBody interface {
|
||||
RandaoReveal() [field_params.BLSSignatureLength]byte
|
||||
SetRandaoReveal([]byte)
|
||||
Eth1Data() *ethpb.Eth1Data
|
||||
SetEth1Data(*ethpb.Eth1Data)
|
||||
Graffiti() [field_params.RootLength]byte
|
||||
SetGraffiti([]byte)
|
||||
ProposerSlashings() []*ethpb.ProposerSlashing
|
||||
SetProposerSlashings([]*ethpb.ProposerSlashing)
|
||||
AttesterSlashings() []*ethpb.AttesterSlashing
|
||||
SetAttesterSlashings([]*ethpb.AttesterSlashing)
|
||||
Attestations() []*ethpb.Attestation
|
||||
SetAttestations([]*ethpb.Attestation)
|
||||
Deposits() []*ethpb.Deposit
|
||||
SetDeposits([]*ethpb.Deposit)
|
||||
VoluntaryExits() []*ethpb.SignedVoluntaryExit
|
||||
SetVoluntaryExits([]*ethpb.SignedVoluntaryExit)
|
||||
SyncAggregate() (*ethpb.SyncAggregate, error)
|
||||
SetSyncAggregate(*ethpb.SyncAggregate) error
|
||||
IsNil() bool
|
||||
HashTreeRoot() ([field_params.RootLength]byte, error)
|
||||
Proto() (proto.Message, error)
|
||||
Execution() (ExecutionData, error)
|
||||
SetExecution(ExecutionData) error
|
||||
BLSToExecutionChanges() ([]*ethpb.SignedBLSToExecutionChange, error)
|
||||
SetBLSToExecutionChanges([]*ethpb.SignedBLSToExecutionChange) error
|
||||
}
|
||||
|
||||
// ExecutionData represents execution layer information that is contained
|
||||
@@ -96,4 +115,6 @@ type ExecutionData interface {
|
||||
TransactionsRoot() ([]byte, error)
|
||||
Withdrawals() ([]*enginev1.Withdrawal, error)
|
||||
WithdrawalsRoot() ([]byte, error)
|
||||
PbV2() (*enginev1.ExecutionPayloadCapella, error)
|
||||
PbV1() (*enginev1.ExecutionPayload, error)
|
||||
}
|
||||
|
||||
@@ -94,6 +94,14 @@ func (SignedBeaconBlock) Header() (*eth.SignedBeaconBlockHeader, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (SignedBeaconBlock) SetBlock(_ interfaces.BeaconBlock) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (SignedBeaconBlock) SetSignature(_ []byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
type BeaconBlock struct {
|
||||
Htr [field_params.RootLength]byte
|
||||
HtrErr error
|
||||
@@ -165,6 +173,30 @@ func (BeaconBlock) Version() int {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (BeaconBlock) ToBlinded() (interfaces.BeaconBlock, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (BeaconBlock) SetSlot(_ types.Slot) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (BeaconBlock) SetProposerIndex(_ types.ValidatorIndex) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (BeaconBlock) SetParentRoot(_ []byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (BeaconBlock) SetBlinded(_ bool) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (BeaconBlock) Copy() (interfaces.BeaconBlock, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
type BeaconBlockBody struct{}
|
||||
|
||||
func (BeaconBlockBody) RandaoReveal() [field_params.BLSSignatureLength]byte {
|
||||
@@ -227,6 +259,50 @@ func (b *BeaconBlock) SetStateRoot(root []byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetRandaoReveal([]byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetEth1Data(*eth.Eth1Data) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetGraffiti([]byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetProposerSlashings([]*eth.ProposerSlashing) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetAttesterSlashings([]*eth.AttesterSlashing) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetAttestations([]*eth.Attestation) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetDeposits([]*eth.Deposit) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetVoluntaryExits([]*eth.SignedVoluntaryExit) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetSyncAggregate(*eth.SyncAggregate) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetExecution(interfaces.ExecutionData) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SetBLSToExecutionChanges([]*eth.SignedBLSToExecutionChange) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
var _ interfaces.SignedBeaconBlock = &SignedBeaconBlock{}
|
||||
var _ interfaces.BeaconBlock = &BeaconBlock{}
|
||||
var _ interfaces.BeaconBlockBody = &BeaconBlockBody{}
|
||||
|
||||
@@ -16,6 +16,7 @@ go_library(
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v3/crypto/bls/blst",
|
||||
visibility = [
|
||||
"//beacon-chain/operations/blstoexec:__pkg__",
|
||||
"//crypto/bls:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
|
||||
@@ -10,6 +10,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/v3/crypto/bls/common",
|
||||
visibility = [
|
||||
"//beacon-chain/core/blocks:__subpackages__",
|
||||
"//beacon-chain/operations/blstoexec:__pkg__",
|
||||
"//crypto/bls:__subpackages__",
|
||||
"//testing:__subpackages__",
|
||||
],
|
||||
|
||||
@@ -99,6 +99,15 @@ func ToBytes4(x []byte) [4]byte {
|
||||
return y
|
||||
}
|
||||
|
||||
// ToBytes20 is a convenience method for converting a byte slice to a fix
|
||||
// sized 20 byte array. This method will truncate the input if it is larger
|
||||
// than 20 bytes.
|
||||
func ToBytes20(x []byte) [20]byte {
|
||||
var y [20]byte
|
||||
copy(y[:], x)
|
||||
return y
|
||||
}
|
||||
|
||||
// ToBytes32 is a convenience method for converting a byte slice to a fix
|
||||
// sized 32 byte array. This method will truncate the input if it is larger
|
||||
// than 32 bytes.
|
||||
|
||||
@@ -41,7 +41,6 @@ go_test(
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
|
||||
@@ -167,11 +167,11 @@ func transactionRoot(tx []byte) ([32]byte, error) {
|
||||
func withdrawalRoot(hasher HashFn, w *enginev1.Withdrawal) ([32]byte, error) {
|
||||
fieldRoots := make([][32]byte, 4)
|
||||
if w != nil {
|
||||
binary.LittleEndian.PutUint64(fieldRoots[0][:], w.WithdrawalIndex)
|
||||
binary.LittleEndian.PutUint64(fieldRoots[0][:], w.Index)
|
||||
|
||||
binary.LittleEndian.PutUint64(fieldRoots[1][:], uint64(w.ValidatorIndex))
|
||||
|
||||
fieldRoots[2] = bytesutil.ToBytes32(w.ExecutionAddress)
|
||||
fieldRoots[2] = bytesutil.ToBytes32(w.Address)
|
||||
binary.LittleEndian.PutUint64(fieldRoots[3][:], w.Amount)
|
||||
}
|
||||
return BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package forks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"sort"
|
||||
"time"
|
||||
@@ -165,7 +166,19 @@ func SortedForkVersions(forkSchedule map[[4]byte]types.Epoch) [][4]byte {
|
||||
i++
|
||||
}
|
||||
sort.Slice(sortedVersions, func(a, b int) bool {
|
||||
return forkSchedule[sortedVersions[a]] < forkSchedule[sortedVersions[b]]
|
||||
// va == "version" a, ie the [4]byte version id
|
||||
va, vb := sortedVersions[a], sortedVersions[b]
|
||||
// ea == "epoch" a, ie the types.Epoch corresponding to va
|
||||
ea, eb := forkSchedule[va], forkSchedule[vb]
|
||||
// Try to sort by epochs first, which works fine when epochs are all distinct.
|
||||
// in the case of testnets starting from a given fork, all epochs leading to the fork will be zero.
|
||||
if ea != eb {
|
||||
return ea < eb
|
||||
}
|
||||
// If the epochs are equal, break the tie with a lexicographic comparison of the fork version bytes.
|
||||
// eg 2 versions both with a fork epoch of 0, 0x00000000 would come before 0x01000000.
|
||||
// sort.Slice takes a 'less' func, ie `return a < b`, and when va < vb, bytes.Compare will return -1
|
||||
return bytes.Compare(va[:], vb[:]) < 0
|
||||
})
|
||||
return sortedVersions
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -28,7 +29,12 @@ func (o OrderedSchedule) Len() int { return len(o) }
|
||||
func (o OrderedSchedule) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
||||
|
||||
// Less implements the Less method of sort.Interface
|
||||
func (o OrderedSchedule) Less(i, j int) bool { return o[i].Epoch < o[j].Epoch }
|
||||
func (o OrderedSchedule) Less(i, j int) bool {
|
||||
if o[i].Epoch == o[j].Epoch {
|
||||
return bytes.Compare(o[i].Version[:], o[j].Version[:]) < 0
|
||||
}
|
||||
return o[i].Epoch < o[j].Epoch
|
||||
}
|
||||
|
||||
// VersionForEpoch finds the Version with the highest epoch <= the given epoch
|
||||
func (o OrderedSchedule) VersionForEpoch(epoch types.Epoch) ([fieldparams.VersionLength]byte, error) {
|
||||
|
||||
@@ -76,14 +76,17 @@ go_library(
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/eth/ext:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_golang_protobuf//proto:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@go_googleapis//google/api:annotations_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
|
||||
@@ -114,6 +117,7 @@ go_test(
|
||||
":go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
|
||||
100
proto/engine/v1/execution_engine.pb.go
generated
100
proto/engine/v1/execution_engine.pb.go
generated
@@ -1029,10 +1029,10 @@ type Withdrawal struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
WithdrawalIndex uint64 `protobuf:"varint,1,opt,name=withdrawal_index,json=withdrawalIndex,proto3" json:"withdrawal_index,omitempty"`
|
||||
ValidatorIndex github_com_prysmaticlabs_prysm_v3_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives.ValidatorIndex"`
|
||||
ExecutionAddress []byte `protobuf:"bytes,3,opt,name=execution_address,json=executionAddress,proto3" json:"execution_address,omitempty" ssz-size:"20"`
|
||||
Amount uint64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"`
|
||||
Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
|
||||
ValidatorIndex github_com_prysmaticlabs_prysm_v3_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives.ValidatorIndex"`
|
||||
Address []byte `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty" ssz-size:"20"`
|
||||
Amount uint64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Withdrawal) Reset() {
|
||||
@@ -1067,9 +1067,9 @@ func (*Withdrawal) Descriptor() ([]byte, []int) {
|
||||
return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *Withdrawal) GetWithdrawalIndex() uint64 {
|
||||
func (x *Withdrawal) GetIndex() uint64 {
|
||||
if x != nil {
|
||||
return x.WithdrawalIndex
|
||||
return x.Index
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -1081,9 +1081,9 @@ func (x *Withdrawal) GetValidatorIndex() github_com_prysmaticlabs_prysm_v3_conse
|
||||
return github_com_prysmaticlabs_prysm_v3_consensus_types_primitives.ValidatorIndex(0)
|
||||
}
|
||||
|
||||
func (x *Withdrawal) GetExecutionAddress() []byte {
|
||||
func (x *Withdrawal) GetAddress() []byte {
|
||||
if x != nil {
|
||||
return x.ExecutionAddress
|
||||
return x.Address
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1440,49 +1440,47 @@ var file_proto_engine_v1_execution_engine_proto_rawDesc = []byte{
|
||||
0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68,
|
||||
0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33,
|
||||
0x32, 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0xfe, 0x01, 0x0a, 0x0a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72,
|
||||
0x61, 0x77, 0x61, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77,
|
||||
0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f,
|
||||
0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12,
|
||||
0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74,
|
||||
0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x33, 0x2f,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f,
|
||||
0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x33, 0x0a, 0x11, 0x65, 0x78, 0x65,
|
||||
0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x10, 0x65, 0x78,
|
||||
0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06,
|
||||
0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xd8, 0x01, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x62, 0x73,
|
||||
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
|
||||
0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02,
|
||||
0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x37, 0x0a,
|
||||
0x0f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0e, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38,
|
||||
0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69,
|
||||
0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18,
|
||||
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
|
||||
0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x42,
|
||||
0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x31,
|
||||
0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f,
|
||||
0x6f, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38,
|
||||
0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f,
|
||||
0x66, 0x22, 0x26, 0x0a, 0x04, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x1e, 0x0a, 0x04, 0x64, 0x61, 0x74,
|
||||
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x31, 0x33, 0x31,
|
||||
0x30, 0x37, 0x32, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x96, 0x01, 0x0a, 0x16, 0x6f, 0x72,
|
||||
0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e,
|
||||
0x65, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45,
|
||||
0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74,
|
||||
0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x33, 0x2f,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b,
|
||||
0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x76, 0x31, 0xaa, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12,
|
||||
0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5c,
|
||||
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0xd6, 0x01, 0x0a, 0x0a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72,
|
||||
0x61, 0x77, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61,
|
||||
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62,
|
||||
0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x33, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69,
|
||||
0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49,
|
||||
0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49,
|
||||
0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x07, 0x61,
|
||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xd8,
|
||||
0x01, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x25,
|
||||
0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x37, 0x0a, 0x0f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0e,
|
||||
0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e,
|
||||
0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x36,
|
||||
0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e,
|
||||
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52,
|
||||
0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x31, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67,
|
||||
0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67,
|
||||
0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x26, 0x0a, 0x04, 0x42, 0x6c, 0x6f,
|
||||
0x62, 0x12, 0x1e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42,
|
||||
0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x04, 0x64, 0x61, 0x74,
|
||||
0x61, 0x42, 0x96, 0x01, 0x0a, 0x16, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
|
||||
0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x45, 0x78,
|
||||
0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70,
|
||||
0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e,
|
||||
0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x76, 0x31,
|
||||
0xaa, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, 0x67, 0x69,
|
||||
0x6e, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
|
||||
0x5c, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user