mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-02-01 16:45:04 -05:00
Compare commits
68 Commits
e2e-debugg
...
only-heade
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f754e98727 | ||
|
|
2269e6aac8 | ||
|
|
f5b2dd986a | ||
|
|
9203d63f90 | ||
|
|
b9b24afb69 | ||
|
|
28c44fca75 | ||
|
|
182abac1c1 | ||
|
|
60d839b8e9 | ||
|
|
bedefd5ead | ||
|
|
8103095cc0 | ||
|
|
9f02b541dd | ||
|
|
76f201ee8f | ||
|
|
31c39aac96 | ||
|
|
51109f61b4 | ||
|
|
dc94612272 | ||
|
|
eb150622ed | ||
|
|
27e210f6b8 | ||
|
|
bbcbb8dc26 | ||
|
|
04a96da75d | ||
|
|
1acb3b6346 | ||
|
|
ff69994b7b | ||
|
|
7ad27324fd | ||
|
|
1cba6c306e | ||
|
|
247c2da608 | ||
|
|
f749702ed7 | ||
|
|
dbd6232e6f | ||
|
|
d8b6b6d17c | ||
|
|
e2a06625cf | ||
|
|
92f9aff295 | ||
|
|
ab734442a3 | ||
|
|
36b1efb12f | ||
|
|
5a4a4c2016 | ||
|
|
ba6c28c48d | ||
|
|
01ae8d58d5 | ||
|
|
574b03d2ed | ||
|
|
0c6feb60b1 | ||
|
|
70143cff56 | ||
|
|
49aedf8459 | ||
|
|
ea5e8b99b7 | ||
|
|
3611afb448 | ||
|
|
d3a1cff406 | ||
|
|
e3c07ac84f | ||
|
|
57d52089bc | ||
|
|
d0b92aa42b | ||
|
|
35a7cc43e3 | ||
|
|
c214525e70 | ||
|
|
fcd9f0830e | ||
|
|
8c8380f28c | ||
|
|
5885e44670 | ||
|
|
11e0f4025a | ||
|
|
05ed96dc25 | ||
|
|
c57baa00f7 | ||
|
|
76b2e23232 | ||
|
|
68e67c3023 | ||
|
|
eaa3d756e7 | ||
|
|
cdf4c8d3fe | ||
|
|
ada07f5358 | ||
|
|
114277d0b0 | ||
|
|
0b6bf2c316 | ||
|
|
2299b00cd8 | ||
|
|
4ba8c98acd | ||
|
|
63f858d2da | ||
|
|
e7d9b33904 | ||
|
|
77657dca93 | ||
|
|
c755751410 | ||
|
|
571edeaf43 | ||
|
|
e2e8528f97 | ||
|
|
2cfbc92c17 |
@@ -142,14 +142,7 @@ func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return [32]byte{}, err
|
return [32]byte{}, err
|
||||||
}
|
}
|
||||||
if blocks.IsPreBellatrixVersion(blk.Block().Version()) {
|
return getBlockPayloadHash(blk.Block())
|
||||||
return params.BeaconConfig().ZeroHash, nil
|
|
||||||
}
|
|
||||||
payload, err := blk.Block().Body().ExecutionPayload()
|
|
||||||
if err != nil {
|
|
||||||
return [32]byte{}, errors.Wrap(err, "could not get execution payload")
|
|
||||||
}
|
|
||||||
return bytesutil.ToBytes32(payload.BlockHash), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// notifyForkchoiceUpdate signals execution engine on a new payload.
|
// notifyForkchoiceUpdate signals execution engine on a new payload.
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
|||||||
}
|
}
|
||||||
isValidPayload, err := s.notifyNewPayload(ctx, postStateVersion, postStateHeader, signed)
|
isValidPayload, err := s.notifyNewPayload(ctx, postStateVersion, postStateHeader, signed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not verify new payload")
|
return fmt.Errorf("could not verify new payload: %v", err)
|
||||||
}
|
}
|
||||||
if isValidPayload {
|
if isValidPayload {
|
||||||
if err := s.validateMergeTransitionBlock(ctx, preStateVersion, preStateHeader, signed); err != nil {
|
if err := s.validateMergeTransitionBlock(ctx, preStateVersion, preStateHeader, signed); err != nil {
|
||||||
@@ -622,15 +622,24 @@ func (s *Service) InsertSlashingsToForkChoiceStore(ctx context.Context, slashing
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getBlockPayloadHash(blk interfaces.BeaconBlock) ([32]byte, error) {
|
func getBlockPayloadHash(blk interfaces.BeaconBlock) ([32]byte, error) {
|
||||||
payloadHash := [32]byte{}
|
var blockHashFromPayload [32]byte
|
||||||
if blocks.IsPreBellatrixVersion(blk.Version()) {
|
if blocks.IsPreBellatrixVersion(blk.Version()) {
|
||||||
return payloadHash, nil
|
return blockHashFromPayload, nil
|
||||||
}
|
}
|
||||||
payload, err := blk.Body().ExecutionPayload()
|
payload, err := blk.Body().ExecutionPayload()
|
||||||
if err != nil {
|
switch {
|
||||||
return payloadHash, err
|
case errors.Is(err, wrapper.ErrUnsupportedField):
|
||||||
|
payloadHeader, err := blk.Body().ExecutionPayloadHeader()
|
||||||
|
if err != nil {
|
||||||
|
return blockHashFromPayload, err
|
||||||
|
}
|
||||||
|
blockHashFromPayload = bytesutil.ToBytes32(payloadHeader.BlockHash)
|
||||||
|
case err != nil:
|
||||||
|
return blockHashFromPayload, err
|
||||||
|
default:
|
||||||
|
blockHashFromPayload = bytesutil.ToBytes32(payload.BlockHash)
|
||||||
}
|
}
|
||||||
return bytesutil.ToBytes32(payload.BlockHash), nil
|
return blockHashFromPayload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This saves post state info to DB or cache. This also saves post state info to fork choice store.
|
// This saves post state info to DB or cache. This also saves post state info to fork choice store.
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ func ProcessOperationsNoVerifyAttsSigs(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case version.Altair, version.Bellatrix:
|
case version.Altair, version.Bellatrix, version.BellatrixBlind:
|
||||||
state, err = altairOperations(ctx, state, signedBeaconBlock)
|
state, err = altairOperations(ctx, state, signedBeaconBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -700,11 +700,6 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.SignedBeaconBlock
|
|||||||
if err := rawBlock.UnmarshalSSZ(enc[len(altairKey):]); err != nil {
|
if err := rawBlock.UnmarshalSSZ(enc[len(altairKey):]); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case hasBellatrixKey(enc):
|
|
||||||
rawBlock = ðpb.SignedBeaconBlockBellatrix{}
|
|
||||||
if err := rawBlock.UnmarshalSSZ(enc[len(bellatrixKey):]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
case hasBellatrixBlindKey(enc):
|
case hasBellatrixBlindKey(enc):
|
||||||
rawBlock = ðpb.SignedBlindedBeaconBlockBellatrix{}
|
rawBlock = ðpb.SignedBlindedBeaconBlockBellatrix{}
|
||||||
if err := rawBlock.UnmarshalSSZ(enc[len(bellatrixBlindKey):]); err != nil {
|
if err := rawBlock.UnmarshalSSZ(enc[len(bellatrixBlindKey):]); err != nil {
|
||||||
@@ -722,19 +717,34 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.SignedBeaconBlock
|
|||||||
|
|
||||||
// marshal versioned beacon block from struct type down to bytes.
|
// marshal versioned beacon block from struct type down to bytes.
|
||||||
func marshalBlock(_ context.Context, blk interfaces.SignedBeaconBlock) ([]byte, error) {
|
func marshalBlock(_ context.Context, blk interfaces.SignedBeaconBlock) ([]byte, error) {
|
||||||
obj, err := blk.MarshalSSZ()
|
var encodedBlock []byte
|
||||||
if err != nil {
|
var blindedBlock interfaces.SignedBeaconBlock
|
||||||
|
var err error
|
||||||
|
// If the block supports blinding of execution payloads, we wrap as
|
||||||
|
// a signed, blinded beacon block and then marshal to bytes. Otherwise,
|
||||||
|
// We just marshal the block as it is.
|
||||||
|
blindedBlock, err = wrapper.WrapSignedBlindedBeaconBlock(blk)
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, wrapper.ErrUnsupportedSignedBeaconBlock):
|
||||||
|
encodedBlock, err = blk.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case err != nil:
|
||||||
return nil, err
|
return nil, err
|
||||||
|
default:
|
||||||
|
encodedBlock, err = blindedBlock.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch blk.Version() {
|
switch blk.Version() {
|
||||||
case version.BellatrixBlind:
|
case version.Bellatrix, version.BellatrixBlind:
|
||||||
return snappy.Encode(nil, append(bellatrixBlindKey, obj...)), nil
|
return snappy.Encode(nil, append(bellatrixBlindKey, encodedBlock...)), nil
|
||||||
case version.Bellatrix:
|
|
||||||
return snappy.Encode(nil, append(bellatrixKey, obj...)), nil
|
|
||||||
case version.Altair:
|
case version.Altair:
|
||||||
return snappy.Encode(nil, append(altairKey, obj...)), nil
|
return snappy.Encode(nil, append(altairKey, encodedBlock...)), nil
|
||||||
case version.Phase0:
|
case version.Phase0:
|
||||||
return snappy.Encode(nil, obj), nil
|
return snappy.Encode(nil, encodedBlock), nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("Unknown block version")
|
return nil, errors.New("Unknown block version")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -678,6 +678,7 @@ func (b *BeaconNode) registerSyncService() error {
|
|||||||
regularsync.WithStateGen(b.stateGen),
|
regularsync.WithStateGen(b.stateGen),
|
||||||
regularsync.WithSlasherAttestationsFeed(b.slasherAttestationsFeed),
|
regularsync.WithSlasherAttestationsFeed(b.slasherAttestationsFeed),
|
||||||
regularsync.WithSlasherBlockHeadersFeed(b.slasherBlockHeadersFeed),
|
regularsync.WithSlasherBlockHeadersFeed(b.slasherBlockHeadersFeed),
|
||||||
|
regularsync.WithExecutionPayloadReconstructor(web3Service),
|
||||||
)
|
)
|
||||||
return b.services.RegisterService(rs)
|
return b.services.RegisterService(rs)
|
||||||
}
|
}
|
||||||
@@ -783,48 +784,49 @@ func (b *BeaconNode) registerRPCService() error {
|
|||||||
|
|
||||||
p2pService := b.fetchP2P()
|
p2pService := b.fetchP2P()
|
||||||
rpcService := rpc.NewService(b.ctx, &rpc.Config{
|
rpcService := rpc.NewService(b.ctx, &rpc.Config{
|
||||||
Host: host,
|
Host: host,
|
||||||
Port: port,
|
Port: port,
|
||||||
BeaconMonitoringHost: beaconMonitoringHost,
|
BeaconMonitoringHost: beaconMonitoringHost,
|
||||||
BeaconMonitoringPort: beaconMonitoringPort,
|
BeaconMonitoringPort: beaconMonitoringPort,
|
||||||
CertFlag: cert,
|
CertFlag: cert,
|
||||||
KeyFlag: key,
|
KeyFlag: key,
|
||||||
BeaconDB: b.db,
|
BeaconDB: b.db,
|
||||||
Broadcaster: p2pService,
|
Broadcaster: p2pService,
|
||||||
PeersFetcher: p2pService,
|
PeersFetcher: p2pService,
|
||||||
PeerManager: p2pService,
|
PeerManager: p2pService,
|
||||||
MetadataProvider: p2pService,
|
MetadataProvider: p2pService,
|
||||||
ChainInfoFetcher: chainService,
|
ChainInfoFetcher: chainService,
|
||||||
HeadUpdater: chainService,
|
HeadUpdater: chainService,
|
||||||
HeadFetcher: chainService,
|
HeadFetcher: chainService,
|
||||||
CanonicalFetcher: chainService,
|
CanonicalFetcher: chainService,
|
||||||
ForkFetcher: chainService,
|
ForkFetcher: chainService,
|
||||||
FinalizationFetcher: chainService,
|
FinalizationFetcher: chainService,
|
||||||
BlockReceiver: chainService,
|
BlockReceiver: chainService,
|
||||||
AttestationReceiver: chainService,
|
AttestationReceiver: chainService,
|
||||||
GenesisTimeFetcher: chainService,
|
GenesisTimeFetcher: chainService,
|
||||||
GenesisFetcher: chainService,
|
GenesisFetcher: chainService,
|
||||||
OptimisticModeFetcher: chainService,
|
OptimisticModeFetcher: chainService,
|
||||||
AttestationsPool: b.attestationPool,
|
AttestationsPool: b.attestationPool,
|
||||||
ExitPool: b.exitPool,
|
ExitPool: b.exitPool,
|
||||||
SlashingsPool: b.slashingsPool,
|
SlashingsPool: b.slashingsPool,
|
||||||
SlashingChecker: slasherService,
|
SlashingChecker: slasherService,
|
||||||
SyncCommitteeObjectPool: b.syncCommitteePool,
|
SyncCommitteeObjectPool: b.syncCommitteePool,
|
||||||
POWChainService: web3Service,
|
POWChainService: web3Service,
|
||||||
POWChainInfoFetcher: web3Service,
|
POWChainInfoFetcher: web3Service,
|
||||||
ChainStartFetcher: chainStartFetcher,
|
ChainStartFetcher: chainStartFetcher,
|
||||||
MockEth1Votes: mockEth1DataVotes,
|
MockEth1Votes: mockEth1DataVotes,
|
||||||
SyncService: syncService,
|
SyncService: syncService,
|
||||||
DepositFetcher: depositFetcher,
|
DepositFetcher: depositFetcher,
|
||||||
PendingDepositFetcher: b.depositCache,
|
PendingDepositFetcher: b.depositCache,
|
||||||
BlockNotifier: b,
|
BlockNotifier: b,
|
||||||
StateNotifier: b,
|
StateNotifier: b,
|
||||||
OperationNotifier: b,
|
OperationNotifier: b,
|
||||||
StateGen: b.stateGen,
|
StateGen: b.stateGen,
|
||||||
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
|
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
|
||||||
MaxMsgSize: maxMsgSize,
|
MaxMsgSize: maxMsgSize,
|
||||||
ProposerIdsCache: b.proposerIdsCache,
|
ProposerIdsCache: b.proposerIdsCache,
|
||||||
ExecutionEngineCaller: web3Service,
|
ExecutionEngineCaller: web3Service,
|
||||||
|
ExecutionPayloadReconstructor: web3Service,
|
||||||
})
|
})
|
||||||
|
|
||||||
return b.services.RegisterService(rpcService)
|
return b.services.RegisterService(rpcService)
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ go_library(
|
|||||||
"//beacon-chain/state/v1:go_default_library",
|
"//beacon-chain/state/v1:go_default_library",
|
||||||
"//config/features:go_default_library",
|
"//config/features:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
|
"//consensus-types/interfaces:go_default_library",
|
||||||
|
"//consensus-types/wrapper:go_default_library",
|
||||||
"//container/trie:go_default_library",
|
"//container/trie:go_default_library",
|
||||||
"//contracts/deposit:go_default_library",
|
"//contracts/deposit:go_default_library",
|
||||||
"//crypto/hash:go_default_library",
|
"//crypto/hash:go_default_library",
|
||||||
@@ -101,6 +103,7 @@ go_test(
|
|||||||
"//beacon-chain/state/stategen:go_default_library",
|
"//beacon-chain/state/stategen:go_default_library",
|
||||||
"//config/fieldparams:go_default_library",
|
"//config/fieldparams:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
|
"//consensus-types/forks/bellatrix:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
"//consensus-types/wrapper:go_default_library",
|
"//consensus-types/wrapper:go_default_library",
|
||||||
"//container/trie:go_default_library",
|
"//container/trie:go_default_library",
|
||||||
|
|||||||
@@ -14,8 +14,11 @@ import (
|
|||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
)
|
)
|
||||||
@@ -46,6 +49,15 @@ type ForkchoiceUpdatedResponse struct {
|
|||||||
PayloadId *pb.PayloadIDBytes `json:"payloadId"`
|
PayloadId *pb.PayloadIDBytes `json:"payloadId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecutionPayloadReconstructor defines a service that can reconstruct a full beacon
|
||||||
|
// block with an execution payload from a signed beacon block and a connection
|
||||||
|
// to an execution client's engine API.
|
||||||
|
type ExecutionPayloadReconstructor interface {
|
||||||
|
ReconstructFullBellatrixBlock(
|
||||||
|
ctx context.Context, blindedBlock interfaces.SignedBeaconBlock,
|
||||||
|
) (interfaces.SignedBeaconBlock, error)
|
||||||
|
}
|
||||||
|
|
||||||
// EngineCaller defines a client that can interact with an Ethereum
|
// EngineCaller defines a client that can interact with an Ethereum
|
||||||
// execution node's engine service via JSON-RPC.
|
// execution node's engine service via JSON-RPC.
|
||||||
type EngineCaller interface {
|
type EngineCaller interface {
|
||||||
@@ -58,6 +70,7 @@ type EngineCaller interface {
|
|||||||
ctx context.Context, cfg *pb.TransitionConfiguration,
|
ctx context.Context, cfg *pb.TransitionConfiguration,
|
||||||
) error
|
) error
|
||||||
ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error)
|
ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error)
|
||||||
|
ExecutionBlockByHashWithTxs(ctx context.Context, hash common.Hash) (*pb.ExecutionBlockWithTxs, error)
|
||||||
GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error)
|
GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,19 +297,81 @@ func (s *Service) LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock,
|
|||||||
func (s *Service) ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error) {
|
func (s *Service) ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExecutionBlockByHash")
|
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExecutionBlockByHash")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
result := &pb.ExecutionBlock{}
|
result := &pb.ExecutionBlock{}
|
||||||
err := s.rpcClient.CallContext(ctx, result, ExecutionBlockByHashMethod, hash, false /* no full transaction objects */)
|
err := s.rpcClient.CallContext(ctx, result, ExecutionBlockByHashMethod, hash, false /* no full transaction objects */)
|
||||||
return result, handleRPCError(err)
|
return result, handleRPCError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecutionBlockByHashWithTxs fetches an execution engine block by hash by calling
|
||||||
|
// eth_blockByHash via JSON-RPC and asks for full transactions in the response.
|
||||||
|
func (s *Service) ExecutionBlockByHashWithTxs(ctx context.Context, hash common.Hash) (*pb.ExecutionBlockWithTxs, error) {
|
||||||
|
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExecutionBlockByHash")
|
||||||
|
defer span.End()
|
||||||
|
start := time.Now()
|
||||||
|
defer func() {
|
||||||
|
executionBlockByHashWithTxsLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||||
|
}()
|
||||||
|
|
||||||
|
result := &pb.ExecutionBlockWithTxs{}
|
||||||
|
err := s.rpcClient.CallContext(ctx, result, ExecutionBlockByHashMethod, hash, true /* full transaction objects */)
|
||||||
|
return result, handleRPCError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReconstructFullBellatrixBlock takes in a blinded beacon block and reconstructs
|
||||||
|
// a beacon block with a full execution payload via the engine API.
|
||||||
|
func (s *Service) ReconstructFullBellatrixBlock(
|
||||||
|
ctx context.Context, blindedBlock interfaces.SignedBeaconBlock,
|
||||||
|
) (interfaces.SignedBeaconBlock, error) {
|
||||||
|
if err := wrapper.BeaconBlockIsNil(blindedBlock); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot reconstruct bellatrix block from nil data")
|
||||||
|
}
|
||||||
|
if !blindedBlock.Block().IsBlinded() {
|
||||||
|
return nil, errors.New("can only reconstruct block from blinded block format")
|
||||||
|
}
|
||||||
|
start := time.Now()
|
||||||
|
defer func() {
|
||||||
|
executionPayloadReconstructionLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||||
|
reconstructedExecutionPayloadCount.Add(1)
|
||||||
|
}()
|
||||||
|
header, err := blindedBlock.Block().Body().ExecutionPayloadHeader()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
executionBlockHash := common.BytesToHash(header.BlockHash)
|
||||||
|
executionBlock, err := s.ExecutionBlockByHashWithTxs(ctx, executionBlockHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not fetch execution block with txs by hash %#x: %v", executionBlockHash, err)
|
||||||
|
}
|
||||||
|
payload := fullPayloadFromExecutionBlock(header, executionBlock)
|
||||||
|
return wrapper.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fullPayloadFromExecutionBlock(header *ethpb.ExecutionPayloadHeader, block *pb.ExecutionBlockWithTxs) *pb.ExecutionPayload {
|
||||||
|
return &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: block.Hash,
|
||||||
|
Transactions: block.Transactions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handles errors received from the RPC server according to the specification.
|
// Handles errors received from the RPC server according to the specification.
|
||||||
func handleRPCError(err error) error {
|
func handleRPCError(err error) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if isTimeout(err) {
|
if isTimeout(err) {
|
||||||
return errors.Wrapf(ErrHTTPTimeout, "%s", err)
|
return ErrHTTPTimeout
|
||||||
}
|
}
|
||||||
e, ok := err.(rpc.Error)
|
e, ok := err.(rpc.Error)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -307,7 +382,7 @@ func handleRPCError(err error) error {
|
|||||||
"here https://docs.prylabs.network/docs/execution-node/authentication")
|
"here https://docs.prylabs.network/docs/execution-node/authentication")
|
||||||
return fmt.Errorf("could not authenticate connection to execution client: %v", err)
|
return fmt.Errorf("could not authenticate connection to execution client: %v", err)
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "got an unexpected error")
|
return fmt.Errorf("got an unexpected error in JSON-RPC response: %v", err)
|
||||||
}
|
}
|
||||||
switch e.ErrorCode() {
|
switch e.ErrorCode() {
|
||||||
case -32700:
|
case -32700:
|
||||||
@@ -330,7 +405,7 @@ func handleRPCError(err error) error {
|
|||||||
// Only -32000 status codes are data errors in the RPC specification.
|
// Only -32000 status codes are data errors in the RPC specification.
|
||||||
errWithData, ok := err.(rpc.DataError)
|
errWithData, ok := err.(rpc.DataError)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Wrap(err, "got an unexpected error")
|
return fmt.Errorf("got an unexpected error in JSON-RPC response: %v", err)
|
||||||
}
|
}
|
||||||
return errors.Wrapf(ErrServer, "%v", errWithData.ErrorData())
|
return errors.Wrapf(ErrServer, "%v", errWithData.ErrorData())
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -12,20 +12,26 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
mocks "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
mocks "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/forks/bellatrix"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
|
"github.com/prysmaticlabs/prysm/testing/util"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ = EngineCaller(&Service{})
|
_ = EngineCaller(&Service{})
|
||||||
|
_ = ExecutionPayloadReconstructor(&Service{})
|
||||||
_ = EngineCaller(&mocks.EngineClient{})
|
_ = EngineCaller(&mocks.EngineClient{})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -534,6 +540,87 @@ func Test_tDStringToUint256(t *testing.T) {
|
|||||||
require.ErrorContains(t, "hex number > 256 bits", err)
|
require.ErrorContains(t, "hex number > 256 bits", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReconstructFullBellatrixBlock(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
t.Run("nil block", func(t *testing.T) {
|
||||||
|
service := &Service{}
|
||||||
|
|
||||||
|
_, err := service.ReconstructFullBellatrixBlock(ctx, nil)
|
||||||
|
require.ErrorContains(t, "nil data", err)
|
||||||
|
})
|
||||||
|
t.Run("only blinded block", func(t *testing.T) {
|
||||||
|
want := "can only reconstruct block from blinded block format"
|
||||||
|
service := &Service{}
|
||||||
|
bellatrixBlock := util.NewBeaconBlockBellatrix()
|
||||||
|
wrapped, err := wrapper.WrappedSignedBeaconBlock(bellatrixBlock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = service.ReconstructFullBellatrixBlock(ctx, wrapped)
|
||||||
|
require.ErrorContains(t, want, err)
|
||||||
|
})
|
||||||
|
t.Run("properly reconstructs block with correct payload", func(t *testing.T) {
|
||||||
|
fix := fixtures()
|
||||||
|
payload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
|
||||||
|
require.Equal(t, true, ok)
|
||||||
|
|
||||||
|
jsonPayload := make(map[string]interface{})
|
||||||
|
tx := types.NewTransaction(
|
||||||
|
0,
|
||||||
|
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
|
||||||
|
big.NewInt(0), 0, big.NewInt(0),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
txs := []*types.Transaction{tx}
|
||||||
|
encodedBinaryTxs := make([][]byte, 1)
|
||||||
|
var err error
|
||||||
|
encodedBinaryTxs[0], err = txs[0].MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
payload.Transactions = encodedBinaryTxs
|
||||||
|
jsonPayload["transactions"] = txs
|
||||||
|
num := big.NewInt(1)
|
||||||
|
encodedNum := hexutil.EncodeBig(num)
|
||||||
|
jsonPayload["hash"] = hexutil.Encode(payload.BlockHash)
|
||||||
|
jsonPayload["number"] = encodedNum
|
||||||
|
jsonPayload["difficulty"] = encodedNum
|
||||||
|
jsonPayload["size"] = encodedNum
|
||||||
|
jsonPayload["baseFeePerGas"] = encodedNum
|
||||||
|
|
||||||
|
header, err := bellatrix.PayloadToHeader(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
defer func() {
|
||||||
|
require.NoError(t, r.Body.Close())
|
||||||
|
}()
|
||||||
|
respJSON := map[string]interface{}{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 1,
|
||||||
|
"result": jsonPayload,
|
||||||
|
}
|
||||||
|
require.NoError(t, json.NewEncoder(w).Encode(respJSON))
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
rpcClient, err := rpc.DialHTTP(srv.URL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer rpcClient.Close()
|
||||||
|
|
||||||
|
service := &Service{}
|
||||||
|
service.rpcClient = rpcClient
|
||||||
|
blindedBlock := util.NewBlindedBeaconBlockBellatrix()
|
||||||
|
|
||||||
|
blindedBlock.Block.Body.ExecutionPayloadHeader = header
|
||||||
|
wrapped, err := wrapper.WrappedSignedBeaconBlock(blindedBlock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
reconstructed, err := service.ReconstructFullBellatrixBlock(ctx, wrapped)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
got, err := reconstructed.Block().Body().ExecutionPayload()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, payload, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestExchangeTransitionConfiguration(t *testing.T) {
|
func TestExchangeTransitionConfiguration(t *testing.T) {
|
||||||
fix := fixtures()
|
fix := fixtures()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|||||||
@@ -27,4 +27,22 @@ var (
|
|||||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
executionBlockByHashWithTxsLatency = promauto.NewHistogram(
|
||||||
|
prometheus.HistogramOpts{
|
||||||
|
Name: "execution_block_by_hash_with_txs_latency_milliseconds",
|
||||||
|
Help: "Captures RPC latency for retrieving in milliseconds",
|
||||||
|
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
executionPayloadReconstructionLatency = promauto.NewHistogram(
|
||||||
|
prometheus.HistogramOpts{
|
||||||
|
Name: "execution_payload_reconstruction_latency_milliseconds",
|
||||||
|
Help: "Captures RPC latency for retrieving in milliseconds",
|
||||||
|
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
reconstructedExecutionPayloadCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||||
|
Name: "reconstructed_execution_payload_count",
|
||||||
|
Help: "Count the number of execution payloads that are reconstructed using JSON-RPC from payload headers",
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ go_library(
|
|||||||
"//beacon-chain/state:go_default_library",
|
"//beacon-chain/state:go_default_library",
|
||||||
"//beacon-chain/state/v1:go_default_library",
|
"//beacon-chain/state/v1:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
|
"//consensus-types/interfaces:go_default_library",
|
||||||
|
"//consensus-types/wrapper:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//proto/engine/v1:go_default_library",
|
"//proto/engine/v1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
|
|||||||
@@ -9,26 +9,31 @@ import (
|
|||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EngineClient --
|
// EngineClient --
|
||||||
type EngineClient struct {
|
type EngineClient struct {
|
||||||
NewPayloadResp []byte
|
NewPayloadResp []byte
|
||||||
PayloadIDBytes *pb.PayloadIDBytes
|
PayloadIDBytes *pb.PayloadIDBytes
|
||||||
ForkChoiceUpdatedResp []byte
|
ForkChoiceUpdatedResp []byte
|
||||||
ExecutionPayload *pb.ExecutionPayload
|
ExecutionPayload *pb.ExecutionPayload
|
||||||
ExecutionBlock *pb.ExecutionBlock
|
ExecutionBlock *pb.ExecutionBlock
|
||||||
Err error
|
Err error
|
||||||
ErrLatestExecBlock error
|
ErrLatestExecBlock error
|
||||||
ErrExecBlockByHash error
|
ErrExecBlockByHash error
|
||||||
ErrForkchoiceUpdated error
|
ErrForkchoiceUpdated error
|
||||||
ErrNewPayload error
|
ErrNewPayload error
|
||||||
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
ExecutionPayloadByBlockHash map[[32]byte]*pb.ExecutionPayload
|
||||||
TerminalBlockHash []byte
|
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
||||||
TerminalBlockHashExists bool
|
BlockWithTxsByHashMap map[[32]byte]*pb.ExecutionBlockWithTxs
|
||||||
OverrideValidHash [32]byte
|
NumReconstructedPayloads uint64
|
||||||
|
TerminalBlockHash []byte
|
||||||
|
TerminalBlockHashExists bool
|
||||||
|
OverrideValidHash [32]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPayload --
|
// NewPayload --
|
||||||
@@ -70,6 +75,33 @@ func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash) (*
|
|||||||
return b, e.ErrExecBlockByHash
|
return b, e.ErrExecBlockByHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *EngineClient) ReconstructFullBellatrixBlock(
|
||||||
|
_ context.Context, blindedBlock interfaces.SignedBeaconBlock,
|
||||||
|
) (interfaces.SignedBeaconBlock, error) {
|
||||||
|
if !blindedBlock.Block().IsBlinded() {
|
||||||
|
return nil, errors.New("block must be blinded")
|
||||||
|
}
|
||||||
|
header, err := blindedBlock.Block().Body().ExecutionPayloadHeader()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload, ok := e.ExecutionPayloadByBlockHash[bytesutil.ToBytes32(header.BlockHash)]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("block not found")
|
||||||
|
}
|
||||||
|
e.NumReconstructedPayloads++
|
||||||
|
return wrapper.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecutionBlockByHashWithTxs --
|
||||||
|
func (e *EngineClient) ExecutionBlockByHashWithTxs(_ context.Context, h common.Hash) (*pb.ExecutionBlockWithTxs, error) {
|
||||||
|
b, ok := e.BlockWithTxsByHashMap[h]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("block not found")
|
||||||
|
}
|
||||||
|
return b, e.ErrExecBlockByHash
|
||||||
|
}
|
||||||
|
|
||||||
// GetTerminalBlockHash --
|
// GetTerminalBlockHash --
|
||||||
func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
|
func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
|
||||||
ttd := new(big.Int)
|
ttd := new(big.Int)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ go_library(
|
|||||||
"//beacon-chain/operations/slashings:go_default_library",
|
"//beacon-chain/operations/slashings:go_default_library",
|
||||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||||
"//beacon-chain/p2p:go_default_library",
|
"//beacon-chain/p2p:go_default_library",
|
||||||
|
"//beacon-chain/powchain:go_default_library",
|
||||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||||
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
|
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
|
||||||
"//beacon-chain/rpc/statefetcher:go_default_library",
|
"//beacon-chain/rpc/statefetcher:go_default_library",
|
||||||
|
|||||||
@@ -470,8 +470,42 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
|
|||||||
ExecutionOptimistic: isOptimistic,
|
ExecutionOptimistic: isOptimistic,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
if _, err := blk.PbBlindedBellatrixBlock(); err == nil {
|
||||||
|
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBellatrixBlock(ctx, blk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(
|
||||||
|
codes.Internal,
|
||||||
|
"Could not reconstruct full execution payload to create signed beacon block: %v",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
bellatrixBlk, err = signedFullBlock.PbBellatrixBlock()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||||
|
}
|
||||||
|
v2Blk, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlk.Block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||||
|
}
|
||||||
|
root, err := blk.Block().HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get block root: %v", err)
|
||||||
|
}
|
||||||
|
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not check if block is optimistic: %v", err)
|
||||||
|
}
|
||||||
|
return ðpbv2.BlockResponseV2{
|
||||||
|
Version: ethpbv2.Version_BELLATRIX,
|
||||||
|
Data: ðpbv2.SignedBeaconBlockContainerV2{
|
||||||
|
Message: ðpbv2.SignedBeaconBlockContainerV2_BellatrixBlock{BellatrixBlock: v2Blk},
|
||||||
|
Signature: blk.Signature(),
|
||||||
|
},
|
||||||
|
ExecutionOptimistic: isOptimistic,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
// ErrUnsupportedBellatrixBlock means that we have another block type
|
// ErrUnsupportedBellatrixBlock means that we have another block type
|
||||||
if !errors.Is(err, wrapper.ErrUnsupportedBellatrixBlock) {
|
if !errors.Is(err, wrapper.ErrUnsupportedBlindedBellatrixBlock) {
|
||||||
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||||
v1alpha1validator "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator"
|
v1alpha1validator "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher"
|
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||||
@@ -21,22 +22,23 @@ import (
|
|||||||
// Server defines a server implementation of the gRPC Beacon Chain service,
|
// Server defines a server implementation of the gRPC Beacon Chain service,
|
||||||
// providing RPC endpoints to access data relevant to the Ethereum Beacon Chain.
|
// providing RPC endpoints to access data relevant to the Ethereum Beacon Chain.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
BeaconDB db.ReadOnlyDatabase
|
BeaconDB db.ReadOnlyDatabase
|
||||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||||
GenesisTimeFetcher blockchain.TimeFetcher
|
GenesisTimeFetcher blockchain.TimeFetcher
|
||||||
BlockReceiver blockchain.BlockReceiver
|
BlockReceiver blockchain.BlockReceiver
|
||||||
BlockNotifier blockfeed.Notifier
|
BlockNotifier blockfeed.Notifier
|
||||||
OperationNotifier operation.Notifier
|
OperationNotifier operation.Notifier
|
||||||
Broadcaster p2p.Broadcaster
|
Broadcaster p2p.Broadcaster
|
||||||
AttestationsPool attestations.Pool
|
AttestationsPool attestations.Pool
|
||||||
SlashingsPool slashings.PoolManager
|
SlashingsPool slashings.PoolManager
|
||||||
VoluntaryExitsPool voluntaryexits.PoolManager
|
VoluntaryExitsPool voluntaryexits.PoolManager
|
||||||
StateGenService stategen.StateManager
|
StateGenService stategen.StateManager
|
||||||
StateFetcher statefetcher.Fetcher
|
StateFetcher statefetcher.Fetcher
|
||||||
HeadFetcher blockchain.HeadFetcher
|
HeadFetcher blockchain.HeadFetcher
|
||||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||||
V1Alpha1ValidatorServer *v1alpha1validator.Server
|
V1Alpha1ValidatorServer *v1alpha1validator.Server
|
||||||
SyncChecker sync.Checker
|
SyncChecker sync.Checker
|
||||||
CanonicalHistory *stategen.CanonicalHistory
|
CanonicalHistory *stategen.CanonicalHistory
|
||||||
HeadUpdater blockchain.HeadUpdater
|
HeadUpdater blockchain.HeadUpdater
|
||||||
|
ExecutionPayloadReconstructor powchain.ExecutionPayloadReconstructor
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,48 +70,49 @@ type Service struct {
|
|||||||
|
|
||||||
// Config options for the beacon node RPC server.
|
// Config options for the beacon node RPC server.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port string
|
||||||
CertFlag string
|
CertFlag string
|
||||||
KeyFlag string
|
KeyFlag string
|
||||||
BeaconMonitoringHost string
|
BeaconMonitoringHost string
|
||||||
BeaconMonitoringPort int
|
BeaconMonitoringPort int
|
||||||
BeaconDB db.HeadAccessDatabase
|
BeaconDB db.HeadAccessDatabase
|
||||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||||
HeadUpdater blockchain.HeadUpdater
|
HeadUpdater blockchain.HeadUpdater
|
||||||
HeadFetcher blockchain.HeadFetcher
|
HeadFetcher blockchain.HeadFetcher
|
||||||
CanonicalFetcher blockchain.CanonicalFetcher
|
CanonicalFetcher blockchain.CanonicalFetcher
|
||||||
ForkFetcher blockchain.ForkFetcher
|
ForkFetcher blockchain.ForkFetcher
|
||||||
FinalizationFetcher blockchain.FinalizationFetcher
|
FinalizationFetcher blockchain.FinalizationFetcher
|
||||||
AttestationReceiver blockchain.AttestationReceiver
|
AttestationReceiver blockchain.AttestationReceiver
|
||||||
BlockReceiver blockchain.BlockReceiver
|
BlockReceiver blockchain.BlockReceiver
|
||||||
POWChainService powchain.Chain
|
POWChainService powchain.Chain
|
||||||
ChainStartFetcher powchain.ChainStartFetcher
|
ChainStartFetcher powchain.ChainStartFetcher
|
||||||
POWChainInfoFetcher powchain.ChainInfoFetcher
|
POWChainInfoFetcher powchain.ChainInfoFetcher
|
||||||
GenesisTimeFetcher blockchain.TimeFetcher
|
GenesisTimeFetcher blockchain.TimeFetcher
|
||||||
GenesisFetcher blockchain.GenesisFetcher
|
GenesisFetcher blockchain.GenesisFetcher
|
||||||
EnableDebugRPCEndpoints bool
|
EnableDebugRPCEndpoints bool
|
||||||
MockEth1Votes bool
|
MockEth1Votes bool
|
||||||
AttestationsPool attestations.Pool
|
AttestationsPool attestations.Pool
|
||||||
ExitPool voluntaryexits.PoolManager
|
ExitPool voluntaryexits.PoolManager
|
||||||
SlashingsPool slashings.PoolManager
|
SlashingsPool slashings.PoolManager
|
||||||
SlashingChecker slasherservice.SlashingChecker
|
SlashingChecker slasherservice.SlashingChecker
|
||||||
SyncCommitteeObjectPool synccommittee.Pool
|
SyncCommitteeObjectPool synccommittee.Pool
|
||||||
SyncService chainSync.Checker
|
SyncService chainSync.Checker
|
||||||
Broadcaster p2p.Broadcaster
|
Broadcaster p2p.Broadcaster
|
||||||
PeersFetcher p2p.PeersProvider
|
PeersFetcher p2p.PeersProvider
|
||||||
PeerManager p2p.PeerManager
|
PeerManager p2p.PeerManager
|
||||||
MetadataProvider p2p.MetadataProvider
|
MetadataProvider p2p.MetadataProvider
|
||||||
DepositFetcher depositcache.DepositFetcher
|
DepositFetcher depositcache.DepositFetcher
|
||||||
PendingDepositFetcher depositcache.PendingDepositsFetcher
|
PendingDepositFetcher depositcache.PendingDepositsFetcher
|
||||||
StateNotifier statefeed.Notifier
|
StateNotifier statefeed.Notifier
|
||||||
BlockNotifier blockfeed.Notifier
|
BlockNotifier blockfeed.Notifier
|
||||||
OperationNotifier opfeed.Notifier
|
OperationNotifier opfeed.Notifier
|
||||||
StateGen *stategen.State
|
StateGen *stategen.State
|
||||||
MaxMsgSize int
|
MaxMsgSize int
|
||||||
ExecutionEngineCaller powchain.EngineCaller
|
ExecutionEngineCaller powchain.EngineCaller
|
||||||
ProposerIdsCache *cache.ProposerPayloadIDsCache
|
ProposerIdsCache *cache.ProposerPayloadIDsCache
|
||||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||||
|
ExecutionPayloadReconstructor powchain.ExecutionPayloadReconstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService instantiates a new RPC service instance that will
|
// NewService instantiates a new RPC service instance that will
|
||||||
@@ -304,11 +305,12 @@ func (s *Service) Start() {
|
|||||||
StateGenService: s.cfg.StateGen,
|
StateGenService: s.cfg.StateGen,
|
||||||
ReplayerBuilder: ch,
|
ReplayerBuilder: ch,
|
||||||
},
|
},
|
||||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||||
HeadFetcher: s.cfg.HeadFetcher,
|
HeadFetcher: s.cfg.HeadFetcher,
|
||||||
VoluntaryExitsPool: s.cfg.ExitPool,
|
VoluntaryExitsPool: s.cfg.ExitPool,
|
||||||
V1Alpha1ValidatorServer: validatorServer,
|
V1Alpha1ValidatorServer: validatorServer,
|
||||||
SyncChecker: s.cfg.SyncService,
|
SyncChecker: s.cfg.SyncService,
|
||||||
|
ExecutionPayloadReconstructor: s.cfg.ExecutionPayloadReconstructor,
|
||||||
}
|
}
|
||||||
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
||||||
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ go_library(
|
|||||||
"//beacon-chain/p2p/encoder:go_default_library",
|
"//beacon-chain/p2p/encoder:go_default_library",
|
||||||
"//beacon-chain/p2p/peers:go_default_library",
|
"//beacon-chain/p2p/peers:go_default_library",
|
||||||
"//beacon-chain/p2p/types:go_default_library",
|
"//beacon-chain/p2p/types:go_default_library",
|
||||||
|
"//beacon-chain/powchain:go_default_library",
|
||||||
"//beacon-chain/state:go_default_library",
|
"//beacon-chain/state:go_default_library",
|
||||||
"//beacon-chain/state/stategen:go_default_library",
|
"//beacon-chain/state/stategen:go_default_library",
|
||||||
"//cache/lru:go_default_library",
|
"//cache/lru:go_default_library",
|
||||||
@@ -186,6 +187,7 @@ go_test(
|
|||||||
"//beacon-chain/p2p/testing:go_default_library",
|
"//beacon-chain/p2p/testing:go_default_library",
|
||||||
"//beacon-chain/p2p/types:go_default_library",
|
"//beacon-chain/p2p/types:go_default_library",
|
||||||
"//beacon-chain/powchain:go_default_library",
|
"//beacon-chain/powchain:go_default_library",
|
||||||
|
"//beacon-chain/powchain/testing:go_default_library",
|
||||||
"//beacon-chain/state:go_default_library",
|
"//beacon-chain/state:go_default_library",
|
||||||
"//beacon-chain/state/stategen:go_default_library",
|
"//beacon-chain/state/stategen:go_default_library",
|
||||||
"//beacon-chain/state/v1:go_default_library",
|
"//beacon-chain/state/v1:go_default_library",
|
||||||
@@ -194,6 +196,7 @@ go_test(
|
|||||||
"//cmd/beacon-chain/flags:go_default_library",
|
"//cmd/beacon-chain/flags:go_default_library",
|
||||||
"//config/fieldparams:go_default_library",
|
"//config/fieldparams:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
|
"//consensus-types/forks/bellatrix:go_default_library",
|
||||||
"//consensus-types/interfaces:go_default_library",
|
"//consensus-types/interfaces:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
"//consensus-types/wrapper:go_default_library",
|
"//consensus-types/wrapper:go_default_library",
|
||||||
@@ -202,6 +205,7 @@ go_test(
|
|||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//encoding/ssz/equality:go_default_library",
|
"//encoding/ssz/equality:go_default_library",
|
||||||
"//network/forks:go_default_library",
|
"//network/forks:go_default_library",
|
||||||
|
"//proto/engine/v1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||||
"//proto/prysm/v1alpha1/metadata:go_default_library",
|
"//proto/prysm/v1alpha1/metadata:go_default_library",
|
||||||
@@ -211,6 +215,8 @@ go_test(
|
|||||||
"//time:go_default_library",
|
"//time:go_default_library",
|
||||||
"//time/slots:go_default_library",
|
"//time/slots:go_default_library",
|
||||||
"@com_github_d4l3k_messagediff//:go_default_library",
|
"@com_github_d4l3k_messagediff//:go_default_library",
|
||||||
|
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||||
|
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||||
"@com_github_ethereum_go_ethereum//p2p/enr:go_default_library",
|
"@com_github_ethereum_go_ethereum//p2p/enr:go_default_library",
|
||||||
"@com_github_golang_snappy//:go_default_library",
|
"@com_github_golang_snappy//:go_default_library",
|
||||||
"@com_github_kevinms_leakybucket_go//:go_default_library",
|
"@com_github_kevinms_leakybucket_go//:go_default_library",
|
||||||
|
|||||||
@@ -75,7 +75,13 @@ var (
|
|||||||
Buckets: []float64{10, 50, 100, 200, 400, 800, 1600, 3200},
|
Buckets: []float64{10, 50, 100, 200, 400, 800, 1600, 3200},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
rpcBlocksByRangeResponseLatency = promauto.NewHistogram(
|
||||||
|
prometheus.HistogramOpts{
|
||||||
|
Name: "rpc_blocks_by_range_response_latency_milliseconds",
|
||||||
|
Help: "Captures total time to respond to rpc blocks by range requests in a milliseconds distribution",
|
||||||
|
Buckets: []float64{250, 500, 1000, 1500, 2000, 3000, 4000, 10000},
|
||||||
|
},
|
||||||
|
)
|
||||||
arrivalBlockPropagationHistogram = promauto.NewHistogram(
|
arrivalBlockPropagationHistogram = promauto.NewHistogram(
|
||||||
prometheus.HistogramOpts{
|
prometheus.HistogramOpts{
|
||||||
Name: "block_arrival_latency_milliseconds",
|
Name: "block_arrival_latency_milliseconds",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -120,3 +121,10 @@ func WithSlasherBlockHeadersFeed(slasherBlockHeadersFeed *event.Feed) Option {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithExecutionPayloadReconstructor(r powchain.ExecutionPayloadReconstructor) Option {
|
||||||
|
return func(s *Service) error {
|
||||||
|
s.cfg.executionPayloadReconstructor = r
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
pb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
@@ -158,18 +159,29 @@ func (s *Service) writeBlockRangeToStream(ctx context.Context, startSlot, endSlo
|
|||||||
tracing.AnnotateError(span, err)
|
tracing.AnnotateError(span, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
start := time.Now()
|
||||||
for _, b := range blks {
|
for _, b := range blks {
|
||||||
if b == nil || b.IsNil() || b.Block().IsNil() {
|
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if chunkErr := s.chunkBlockWriter(stream, b); chunkErr != nil {
|
blockToWrite := b
|
||||||
log.WithError(chunkErr).Debug("Could not send a chunked response")
|
if blockToWrite.Block().IsBlinded() {
|
||||||
|
fullBlock, err := s.cfg.executionPayloadReconstructor.ReconstructFullBellatrixBlock(ctx, blockToWrite)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Could not get reconstruct full bellatrix block from blinded body")
|
||||||
|
s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
blockToWrite = fullBlock
|
||||||
|
}
|
||||||
|
if chunkErr := s.chunkBlockWriter(stream, blockToWrite); chunkErr != nil {
|
||||||
|
log.WithError(chunkErr).Error("Could not send a chunked response")
|
||||||
s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream)
|
s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream)
|
||||||
tracing.AnnotateError(span, chunkErr)
|
tracing.AnnotateError(span, chunkErr)
|
||||||
return chunkErr
|
return chunkErr
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
rpcBlocksByRangeResponseLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||||
// Return error in the event we have an invalid parent.
|
// Return error in the event we have an invalid parent.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ package sync
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/kevinms/leakybucket-go"
|
"github.com/kevinms/leakybucket-go"
|
||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/protocol"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
@@ -17,12 +20,15 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||||
p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||||
|
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/forks/bellatrix"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
|
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
@@ -155,6 +161,121 @@ func TestRPCBeaconBlocksByRange_ReturnCorrectNumberBack(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRPCBeaconBlocksByRange_CanReconstructFullPayloadBlocks(t *testing.T) {
|
||||||
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
p1.Connect(p2)
|
||||||
|
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
|
||||||
|
d := db.SetupDB(t)
|
||||||
|
|
||||||
|
req := ðpb.BeaconBlocksByRangeRequest{
|
||||||
|
StartSlot: 200,
|
||||||
|
Step: 21,
|
||||||
|
Count: 33,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
|
||||||
|
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
|
||||||
|
stateRoot := bytesutil.PadTo([]byte("stateRoot"), fieldparams.RootLength)
|
||||||
|
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
|
||||||
|
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
|
||||||
|
tx := gethTypes.NewTransaction(
|
||||||
|
0,
|
||||||
|
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
|
||||||
|
big.NewInt(0), 0, big.NewInt(0),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
txs := []*gethTypes.Transaction{tx}
|
||||||
|
encodedBinaryTxs := make([][]byte, 1)
|
||||||
|
var err error
|
||||||
|
encodedBinaryTxs[0], err = txs[0].MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
blockHash := bytesutil.ToBytes32([]byte("foo"))
|
||||||
|
payload := &enginev1.ExecutionPayload{
|
||||||
|
ParentHash: parent,
|
||||||
|
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
||||||
|
StateRoot: stateRoot,
|
||||||
|
ReceiptsRoot: receiptsRoot,
|
||||||
|
LogsBloom: logsBloom,
|
||||||
|
PrevRandao: blockHash[:],
|
||||||
|
BlockNumber: 0,
|
||||||
|
GasLimit: 0,
|
||||||
|
GasUsed: 0,
|
||||||
|
Timestamp: 0,
|
||||||
|
ExtraData: make([]byte, 0),
|
||||||
|
BlockHash: blockHash[:],
|
||||||
|
BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength),
|
||||||
|
Transactions: encodedBinaryTxs,
|
||||||
|
}
|
||||||
|
header, err := bellatrix.PayloadToHeader(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
endSlot := req.StartSlot.Add(req.Step * (req.Count - 1))
|
||||||
|
expectedRoots := make([][32]byte, req.Count)
|
||||||
|
|
||||||
|
// Populate the database with blocks that would match the request.
|
||||||
|
for i, j := endSlot, req.Count-1; i >= req.StartSlot; i -= types.Slot(req.Step) {
|
||||||
|
blk := util.NewBlindedBeaconBlockBellatrix()
|
||||||
|
blk.Block.Body.ExecutionPayloadHeader = header
|
||||||
|
blk.Block.Slot = i
|
||||||
|
rt, err := blk.Block.HashTreeRoot()
|
||||||
|
require.NoError(t, err)
|
||||||
|
expectedRoots[j] = rt
|
||||||
|
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, d.SaveBlock(context.Background(), wsb))
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
|
||||||
|
mockEngine := &mockPOW.EngineClient{
|
||||||
|
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{
|
||||||
|
blockHash: payload,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
r := &Service{cfg: &config{
|
||||||
|
p2p: p1,
|
||||||
|
beaconDB: d,
|
||||||
|
chain: &chainMock.ChainService{},
|
||||||
|
executionPayloadReconstructor: mockEngine,
|
||||||
|
},
|
||||||
|
rateLimiter: newRateLimiter(p1),
|
||||||
|
}
|
||||||
|
|
||||||
|
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
|
||||||
|
topic := string(pcl)
|
||||||
|
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(0.000001, int64(req.Count*10), false)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) {
|
||||||
|
defer wg.Done()
|
||||||
|
prevSlot := types.Slot(0)
|
||||||
|
require.Equal(t, uint64(len(expectedRoots)), req.Count, "Number of roots not expected")
|
||||||
|
for i, j := req.StartSlot, 0; i < req.StartSlot.Add(req.Count*req.Step); i += types.Slot(req.Step) {
|
||||||
|
expectSuccess(t, stream)
|
||||||
|
res := ðpb.SignedBeaconBlockBellatrix{}
|
||||||
|
assert.NoError(t, r.cfg.p2p.Encoding().DecodeWithMaxLength(stream, res))
|
||||||
|
if res.Block.Slot < prevSlot {
|
||||||
|
t.Errorf("Received block is unsorted with slot %d lower than previous slot %d", res.Block.Slot, prevSlot)
|
||||||
|
}
|
||||||
|
rt, err := res.Block.HashTreeRoot()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedRoots[j], rt, "roots not equal")
|
||||||
|
prevSlot = res.Block.Slot
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
require.Equal(t, uint64(33), mockEngine.NumReconstructedPayloads, "wrong number of reconstructed payloads")
|
||||||
|
})
|
||||||
|
|
||||||
|
stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, r.beaconBlocksByRangeRPCHandler(context.Background(), req, stream1))
|
||||||
|
|
||||||
|
if util.WaitTimeout(&wg, 1*time.Second) {
|
||||||
|
t.Fatal("Did not receive stream within 1 sec")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRPCBeaconBlocksByRange_RPCHandlerReturnsSortedBlocks(t *testing.T) {
|
func TestRPCBeaconBlocksByRange_RPCHandlerReturnsSortedBlocks(t *testing.T) {
|
||||||
p1 := p2ptest.NewTestP2P(t)
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
p2 := p2ptest.NewTestP2P(t)
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sendRecentBeaconBlocksRequest sends a recent beacon blocks request to a peer to get
|
// sendRecentBeaconBlocksRequest sends a recent beacon blocks request to a peer to get
|
||||||
@@ -68,13 +69,24 @@ func (s *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
|||||||
s.writeErrorResponseToStream(responseCodeServerError, types.ErrGeneric.Error(), stream)
|
s.writeErrorResponseToStream(responseCodeServerError, types.ErrGeneric.Error(), stream)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if blk == nil || blk.IsNil() {
|
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if blk.Block().IsBlinded() {
|
||||||
|
blk, err = s.cfg.executionPayloadReconstructor.ReconstructFullBellatrixBlock(ctx, blk)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Could not get reconstruct full bellatrix block from blinded body")
|
||||||
|
s.writeErrorResponseToStream(responseCodeServerError, types.ErrGeneric.Error(), stream)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.chunkBlockWriter(stream, blk); err != nil {
|
if err := s.chunkBlockWriter(stream, blk); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closeStream(stream, log)
|
closeStream(stream, log)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package sync
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/kevinms/leakybucket-go"
|
"github.com/kevinms/leakybucket-go"
|
||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/protocol"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
@@ -16,9 +19,14 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||||
p2pTypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
p2pTypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||||
|
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/forks/bellatrix"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
|
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
@@ -75,6 +83,103 @@ func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks_ReconstructsExecutionPayloads(t *testing.T) {
|
||||||
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
p1.Connect(p2)
|
||||||
|
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
|
||||||
|
d := db.SetupDB(t)
|
||||||
|
|
||||||
|
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
|
||||||
|
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
|
||||||
|
stateRoot := bytesutil.PadTo([]byte("stateRoot"), fieldparams.RootLength)
|
||||||
|
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
|
||||||
|
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
|
||||||
|
tx := gethTypes.NewTransaction(
|
||||||
|
0,
|
||||||
|
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
|
||||||
|
big.NewInt(0), 0, big.NewInt(0),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
txs := []*gethTypes.Transaction{tx}
|
||||||
|
encodedBinaryTxs := make([][]byte, 1)
|
||||||
|
var err error
|
||||||
|
encodedBinaryTxs[0], err = txs[0].MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
blockHash := bytesutil.ToBytes32([]byte("foo"))
|
||||||
|
payload := &enginev1.ExecutionPayload{
|
||||||
|
ParentHash: parent,
|
||||||
|
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
||||||
|
StateRoot: stateRoot,
|
||||||
|
ReceiptsRoot: receiptsRoot,
|
||||||
|
LogsBloom: logsBloom,
|
||||||
|
PrevRandao: blockHash[:],
|
||||||
|
BlockNumber: 0,
|
||||||
|
GasLimit: 0,
|
||||||
|
GasUsed: 0,
|
||||||
|
Timestamp: 0,
|
||||||
|
ExtraData: make([]byte, 0),
|
||||||
|
BlockHash: blockHash[:],
|
||||||
|
BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength),
|
||||||
|
Transactions: encodedBinaryTxs,
|
||||||
|
}
|
||||||
|
header, err := bellatrix.PayloadToHeader(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var blkRoots p2pTypes.BeaconBlockByRootsReq
|
||||||
|
// Populate the database with blocks that would match the request.
|
||||||
|
for i := types.Slot(1); i < 11; i++ {
|
||||||
|
blk := util.NewBlindedBeaconBlockBellatrix()
|
||||||
|
blk.Block.Body.ExecutionPayloadHeader = header
|
||||||
|
blk.Block.Slot = i
|
||||||
|
root, err := blk.Block.HashTreeRoot()
|
||||||
|
require.NoError(t, err)
|
||||||
|
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, d.SaveBlock(context.Background(), wsb))
|
||||||
|
blkRoots = append(blkRoots, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
mockEngine := &mockPOW.EngineClient{
|
||||||
|
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{
|
||||||
|
blockHash: payload,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
r := &Service{cfg: &config{
|
||||||
|
p2p: p1,
|
||||||
|
beaconDB: d,
|
||||||
|
executionPayloadReconstructor: mockEngine,
|
||||||
|
}, rateLimiter: newRateLimiter(p1)}
|
||||||
|
r.cfg.chain = &mock.ChainService{ValidatorsRoot: [32]byte{}}
|
||||||
|
pcl := protocol.ID(p2p.RPCBlocksByRootTopicV1)
|
||||||
|
topic := string(pcl)
|
||||||
|
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, false)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) {
|
||||||
|
defer wg.Done()
|
||||||
|
for i := range blkRoots {
|
||||||
|
expectSuccess(t, stream)
|
||||||
|
res := util.NewBeaconBlockBellatrix()
|
||||||
|
assert.NoError(t, r.cfg.p2p.Encoding().DecodeWithMaxLength(stream, res))
|
||||||
|
if uint64(res.Block.Slot) != uint64(i+1) {
|
||||||
|
t.Errorf("Received unexpected block slot %d but wanted %d", res.Block.Slot, i+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.Equal(t, uint64(10), mockEngine.NumReconstructedPayloads)
|
||||||
|
})
|
||||||
|
|
||||||
|
stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = r.beaconBlocksRootRPCHandler(context.Background(), &blkRoots, stream1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
if util.WaitTimeout(&wg, 1*time.Second) {
|
||||||
|
t.Fatal("Did not receive stream within 1 sec")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
||||||
p1 := p2ptest.NewTestP2P(t)
|
p1 := p2ptest.NewTestP2P(t)
|
||||||
p2 := p2ptest.NewTestP2P(t)
|
p2 := p2ptest.NewTestP2P(t)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ func WriteBlockChunk(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var obtainedCtx []byte
|
var obtainedCtx []byte
|
||||||
|
|
||||||
switch blk.Version() {
|
switch blk.Version() {
|
||||||
case version.Phase0:
|
case version.Phase0:
|
||||||
valRoot := chain.GenesisValidatorsRoot()
|
valRoot := chain.GenesisValidatorsRoot()
|
||||||
@@ -45,7 +46,7 @@ func WriteBlockChunk(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
obtainedCtx = digest[:]
|
obtainedCtx = digest[:]
|
||||||
case version.Bellatrix:
|
case version.Bellatrix, version.BellatrixBlind:
|
||||||
valRoot := chain.GenesisValidatorsRoot()
|
valRoot := chain.GenesisValidatorsRoot()
|
||||||
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, valRoot[:])
|
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, valRoot[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||||
lruwrpr "github.com/prysmaticlabs/prysm/cache/lru"
|
lruwrpr "github.com/prysmaticlabs/prysm/cache/lru"
|
||||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||||
@@ -68,21 +69,22 @@ type validationFn func(ctx context.Context) (pubsub.ValidationResult, error)
|
|||||||
|
|
||||||
// config to hold dependencies for the sync service.
|
// config to hold dependencies for the sync service.
|
||||||
type config struct {
|
type config struct {
|
||||||
attestationNotifier operation.Notifier
|
attestationNotifier operation.Notifier
|
||||||
p2p p2p.P2P
|
p2p p2p.P2P
|
||||||
beaconDB db.NoHeadAccessDatabase
|
beaconDB db.NoHeadAccessDatabase
|
||||||
attPool attestations.Pool
|
attPool attestations.Pool
|
||||||
exitPool voluntaryexits.PoolManager
|
exitPool voluntaryexits.PoolManager
|
||||||
slashingPool slashings.PoolManager
|
slashingPool slashings.PoolManager
|
||||||
syncCommsPool synccommittee.Pool
|
syncCommsPool synccommittee.Pool
|
||||||
chain blockchainService
|
chain blockchainService
|
||||||
initialSync Checker
|
initialSync Checker
|
||||||
stateNotifier statefeed.Notifier
|
stateNotifier statefeed.Notifier
|
||||||
blockNotifier blockfeed.Notifier
|
blockNotifier blockfeed.Notifier
|
||||||
operationNotifier operation.Notifier
|
operationNotifier operation.Notifier
|
||||||
stateGen *stategen.State
|
executionPayloadReconstructor powchain.ExecutionPayloadReconstructor
|
||||||
slasherAttestationsFeed *event.Feed
|
stateGen *stategen.State
|
||||||
slasherBlockHeadersFeed *event.Feed
|
slasherAttestationsFeed *event.Feed
|
||||||
|
slasherBlockHeadersFeed *event.Feed
|
||||||
}
|
}
|
||||||
|
|
||||||
// This defines the interface for interacting with block chain service
|
// This defines the interface for interacting with block chain service
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ go_library(
|
|||||||
importpath = "github.com/prysmaticlabs/prysm/consensus-types/wrapper",
|
importpath = "github.com/prysmaticlabs/prysm/consensus-types/wrapper",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//consensus-types/forks/bellatrix:go_default_library",
|
||||||
"//consensus-types/interfaces:go_default_library",
|
"//consensus-types/interfaces:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
"//proto/engine/v1:go_default_library",
|
"//proto/engine/v1:go_default_library",
|
||||||
@@ -39,6 +40,8 @@ go_test(
|
|||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
":go_default_library",
|
":go_default_library",
|
||||||
|
"//config/fieldparams:go_default_library",
|
||||||
|
"//consensus-types/forks/bellatrix:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//proto/engine/v1:go_default_library",
|
"//proto/engine/v1:go_default_library",
|
||||||
@@ -48,5 +51,6 @@ go_test(
|
|||||||
"//testing/assert:go_default_library",
|
"//testing/assert:go_default_library",
|
||||||
"//testing/require:go_default_library",
|
"//testing/require:go_default_library",
|
||||||
"//testing/util:go_default_library",
|
"//testing/util:go_default_library",
|
||||||
|
"@com_github_pkg_errors//:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package wrapper
|
package wrapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/forks/bellatrix"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
|
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -145,6 +149,115 @@ func BuildSignedBeaconBlock(blk interfaces.BeaconBlock, signature []byte) (inter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildSignedBeaconBlockFromExecutionPayload takes a signed, blinded beacon block and converts into
|
||||||
|
// a full, signed beacon block by specifying an execution payload.
|
||||||
|
func BuildSignedBeaconBlockFromExecutionPayload(
|
||||||
|
blk interfaces.SignedBeaconBlock, payload *enginev1.ExecutionPayload,
|
||||||
|
) (interfaces.SignedBeaconBlock, error) {
|
||||||
|
if err := BeaconBlockIsNil(blk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b := blk.Block()
|
||||||
|
payloadHeader, err := b.Body().ExecutionPayloadHeader()
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, ErrUnsupportedField):
|
||||||
|
return nil, errors.Wrap(err, "can only build signed beacon block from blinded format")
|
||||||
|
case err != nil:
|
||||||
|
return nil, errors.Wrap(err, "could not get execution payload header")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
payloadRoot, err := payload.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not hash tree root execution payload")
|
||||||
|
}
|
||||||
|
payloadHeaderRoot, err := payloadHeader.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not hash tree root payload header")
|
||||||
|
}
|
||||||
|
if payloadRoot != payloadHeaderRoot {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"payload %#x and header %#x roots do not match",
|
||||||
|
payloadRoot,
|
||||||
|
payloadHeaderRoot,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
syncAgg, err := b.Body().SyncAggregate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get sync aggregate from block body")
|
||||||
|
}
|
||||||
|
bellatrixFullBlock := ð.SignedBeaconBlockBellatrix{
|
||||||
|
Block: ð.BeaconBlockBellatrix{
|
||||||
|
Slot: b.Slot(),
|
||||||
|
ProposerIndex: b.ProposerIndex(),
|
||||||
|
ParentRoot: b.ParentRoot(),
|
||||||
|
StateRoot: b.StateRoot(),
|
||||||
|
Body: ð.BeaconBlockBodyBellatrix{
|
||||||
|
RandaoReveal: b.Body().RandaoReveal(),
|
||||||
|
Eth1Data: b.Body().Eth1Data(),
|
||||||
|
Graffiti: b.Body().Graffiti(),
|
||||||
|
ProposerSlashings: b.Body().ProposerSlashings(),
|
||||||
|
AttesterSlashings: b.Body().AttesterSlashings(),
|
||||||
|
Attestations: b.Body().Attestations(),
|
||||||
|
Deposits: b.Body().Deposits(),
|
||||||
|
VoluntaryExits: b.Body().VoluntaryExits(),
|
||||||
|
SyncAggregate: syncAgg,
|
||||||
|
ExecutionPayload: payload,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Signature: blk.Signature(),
|
||||||
|
}
|
||||||
|
return wrappedBellatrixSignedBeaconBlock(bellatrixFullBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapSignedBlindedBeaconBlock converts a signed beacon block into a blinded format.
|
||||||
|
func WrapSignedBlindedBeaconBlock(blk interfaces.SignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
|
||||||
|
if err := BeaconBlockIsNil(blk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if blk.Block().IsBlinded() {
|
||||||
|
return blk, nil
|
||||||
|
}
|
||||||
|
b := blk.Block()
|
||||||
|
payload, err := b.Body().ExecutionPayload()
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, ErrUnsupportedField):
|
||||||
|
return nil, ErrUnsupportedSignedBeaconBlock
|
||||||
|
case err != nil:
|
||||||
|
return nil, errors.Wrap(err, "could not get execution payload")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
syncAgg, err := b.Body().SyncAggregate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
header, err := bellatrix.PayloadToHeader(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blindedBlock := ð.SignedBlindedBeaconBlockBellatrix{
|
||||||
|
Block: ð.BlindedBeaconBlockBellatrix{
|
||||||
|
Slot: b.Slot(),
|
||||||
|
ProposerIndex: b.ProposerIndex(),
|
||||||
|
ParentRoot: b.ParentRoot(),
|
||||||
|
StateRoot: b.StateRoot(),
|
||||||
|
Body: ð.BlindedBeaconBlockBodyBellatrix{
|
||||||
|
RandaoReveal: b.Body().RandaoReveal(),
|
||||||
|
Eth1Data: b.Body().Eth1Data(),
|
||||||
|
Graffiti: b.Body().Graffiti(),
|
||||||
|
ProposerSlashings: b.Body().ProposerSlashings(),
|
||||||
|
AttesterSlashings: b.Body().AttesterSlashings(),
|
||||||
|
Attestations: b.Body().Attestations(),
|
||||||
|
Deposits: b.Body().Deposits(),
|
||||||
|
VoluntaryExits: b.Body().VoluntaryExits(),
|
||||||
|
SyncAggregate: syncAgg,
|
||||||
|
ExecutionPayloadHeader: header,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Signature: blk.Signature(),
|
||||||
|
}
|
||||||
|
return wrappedBellatrixSignedBlindedBeaconBlock(blindedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
func UnwrapGenericSignedBeaconBlock(gb *eth.GenericSignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
|
func UnwrapGenericSignedBeaconBlock(gb *eth.GenericSignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
|
||||||
if gb == nil {
|
if gb == nil {
|
||||||
return nil, ErrNilObjectWrapped
|
return nil, ErrNilObjectWrapped
|
||||||
|
|||||||
@@ -3,11 +3,121 @@ package wrapper_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
|
"github.com/prysmaticlabs/prysm/consensus-types/forks/bellatrix"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||||
|
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
"github.com/prysmaticlabs/prysm/testing/util"
|
"github.com/prysmaticlabs/prysm/testing/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestBuildSignedBeaconBlockFromExecutionPayload(t *testing.T) {
|
||||||
|
t.Run("nil block check", func(t *testing.T) {
|
||||||
|
_, err := wrapper.BuildSignedBeaconBlockFromExecutionPayload(nil, nil)
|
||||||
|
require.ErrorIs(t, wrapper.ErrNilSignedBeaconBlock, err)
|
||||||
|
})
|
||||||
|
t.Run("unsupported field payload header", func(t *testing.T) {
|
||||||
|
altairBlock := util.NewBeaconBlockAltair()
|
||||||
|
blk, err := wrapper.WrappedSignedBeaconBlock(altairBlock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = wrapper.BuildSignedBeaconBlockFromExecutionPayload(blk, nil)
|
||||||
|
require.Equal(t, true, errors.Is(err, wrapper.ErrUnsupportedField))
|
||||||
|
})
|
||||||
|
t.Run("payload header root and payload root mismatch", func(t *testing.T) {
|
||||||
|
payload := &enginev1.ExecutionPayload{
|
||||||
|
ParentHash: make([]byte, fieldparams.RootLength),
|
||||||
|
FeeRecipient: make([]byte, 20),
|
||||||
|
StateRoot: make([]byte, fieldparams.RootLength),
|
||||||
|
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||||
|
LogsBloom: make([]byte, 256),
|
||||||
|
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||||
|
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||||
|
BlockHash: make([]byte, fieldparams.RootLength),
|
||||||
|
Transactions: make([][]byte, 0),
|
||||||
|
}
|
||||||
|
header, err := bellatrix.PayloadToHeader(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
blindedBlock := util.NewBlindedBeaconBlockBellatrix()
|
||||||
|
|
||||||
|
// Modify the header.
|
||||||
|
header.GasUsed += 1
|
||||||
|
blindedBlock.Block.Body.ExecutionPayloadHeader = header
|
||||||
|
|
||||||
|
blk, err := wrapper.WrappedSignedBeaconBlock(blindedBlock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = wrapper.BuildSignedBeaconBlockFromExecutionPayload(blk, payload)
|
||||||
|
require.ErrorContains(t, "roots do not match", err)
|
||||||
|
})
|
||||||
|
t.Run("ok", func(t *testing.T) {
|
||||||
|
payload := &enginev1.ExecutionPayload{
|
||||||
|
ParentHash: make([]byte, fieldparams.RootLength),
|
||||||
|
FeeRecipient: make([]byte, 20),
|
||||||
|
StateRoot: make([]byte, fieldparams.RootLength),
|
||||||
|
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||||
|
LogsBloom: make([]byte, 256),
|
||||||
|
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||||
|
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||||
|
BlockHash: make([]byte, fieldparams.RootLength),
|
||||||
|
Transactions: make([][]byte, 0),
|
||||||
|
}
|
||||||
|
header, err := bellatrix.PayloadToHeader(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
blindedBlock := util.NewBlindedBeaconBlockBellatrix()
|
||||||
|
blindedBlock.Block.Body.ExecutionPayloadHeader = header
|
||||||
|
|
||||||
|
blk, err := wrapper.WrappedSignedBeaconBlock(blindedBlock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
builtBlock, err := wrapper.BuildSignedBeaconBlockFromExecutionPayload(blk, payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
got, err := builtBlock.Block().Body().ExecutionPayload()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, payload, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapSignedBlindedBeaconBlock(t *testing.T) {
|
||||||
|
t.Run("nil block check", func(t *testing.T) {
|
||||||
|
_, err := wrapper.BuildSignedBeaconBlockFromExecutionPayload(nil, nil)
|
||||||
|
require.ErrorIs(t, wrapper.ErrNilSignedBeaconBlock, err)
|
||||||
|
})
|
||||||
|
t.Run("unsupported field execution payload", func(t *testing.T) {
|
||||||
|
altairBlock := util.NewBeaconBlockAltair()
|
||||||
|
blk, err := wrapper.WrappedSignedBeaconBlock(altairBlock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = wrapper.BuildSignedBeaconBlockFromExecutionPayload(blk, nil)
|
||||||
|
require.Equal(t, true, errors.Is(err, wrapper.ErrUnsupportedField))
|
||||||
|
})
|
||||||
|
t.Run("ok", func(t *testing.T) {
|
||||||
|
payload := &enginev1.ExecutionPayload{
|
||||||
|
ParentHash: make([]byte, fieldparams.RootLength),
|
||||||
|
FeeRecipient: make([]byte, 20),
|
||||||
|
StateRoot: make([]byte, fieldparams.RootLength),
|
||||||
|
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||||
|
LogsBloom: make([]byte, 256),
|
||||||
|
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||||
|
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||||
|
BlockHash: make([]byte, fieldparams.RootLength),
|
||||||
|
Transactions: make([][]byte, 0),
|
||||||
|
}
|
||||||
|
bellatrixBlk := util.NewBeaconBlockBellatrix()
|
||||||
|
bellatrixBlk.Block.Body.ExecutionPayload = payload
|
||||||
|
|
||||||
|
want, err := bellatrix.PayloadToHeader(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
blk, err := wrapper.WrappedSignedBeaconBlock(bellatrixBlk)
|
||||||
|
require.NoError(t, err)
|
||||||
|
builtBlock, err := wrapper.WrapSignedBlindedBeaconBlock(blk)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
got, err := builtBlock.Block().Body().ExecutionPayloadHeader()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestWrappedSignedBeaconBlock(t *testing.T) {
|
func TestWrappedSignedBeaconBlock(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ go_library(
|
|||||||
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
||||||
"@com_github_golang_protobuf//proto:go_default_library",
|
"@com_github_golang_protobuf//proto:go_default_library",
|
||||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||||
|
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||||
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
|
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
|
||||||
"@go_googleapis//google/api:annotations_go_proto",
|
"@go_googleapis//google/api:annotations_go_proto",
|
||||||
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
|
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
)
|
)
|
||||||
@@ -157,6 +158,141 @@ func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExecutionBlockWithTxs struct {
|
||||||
|
ExecutionBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
type executionBlockWithTxsJSON struct {
|
||||||
|
Number string `json:"number"`
|
||||||
|
Hash hexutil.Bytes `json:"hash"`
|
||||||
|
ParentHash hexutil.Bytes `json:"parentHash"`
|
||||||
|
Sha3Uncles hexutil.Bytes `json:"sha3Uncles"`
|
||||||
|
Miner hexutil.Bytes `json:"miner"`
|
||||||
|
StateRoot hexutil.Bytes `json:"stateRoot"`
|
||||||
|
TransactionsRoot hexutil.Bytes `json:"transactionsRoot"`
|
||||||
|
ReceiptsRoot hexutil.Bytes `json:"receiptsRoot"`
|
||||||
|
LogsBloom hexutil.Bytes `json:"logsBloom"`
|
||||||
|
Difficulty string `json:"difficulty"`
|
||||||
|
TotalDifficulty string `json:"totalDifficulty"`
|
||||||
|
GasLimit hexutil.Uint64 `json:"gasLimit"`
|
||||||
|
GasUsed hexutil.Uint64 `json:"gasUsed"`
|
||||||
|
Timestamp hexutil.Uint64 `json:"timestamp"`
|
||||||
|
BaseFeePerGas string `json:"baseFeePerGas"`
|
||||||
|
ExtraData hexutil.Bytes `json:"extraData"`
|
||||||
|
MixHash hexutil.Bytes `json:"mixHash"`
|
||||||
|
Nonce hexutil.Bytes `json:"nonce"`
|
||||||
|
Size string `json:"size"`
|
||||||
|
Transactions []*types.Transaction `json:"transactions"`
|
||||||
|
Uncles []hexutil.Bytes `json:"uncles"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON defines a custom json.Marshaler interface implementation
|
||||||
|
// that uses custom json.Marshalers for the hexutil.Bytes and hexutil.Uint64 types.
|
||||||
|
func (e *ExecutionBlockWithTxs) MarshalJSON() ([]byte, error) {
|
||||||
|
transactions := make([]hexutil.Bytes, len(e.Transactions))
|
||||||
|
for i, tx := range e.Transactions {
|
||||||
|
transactions[i] = tx
|
||||||
|
}
|
||||||
|
uncles := make([]hexutil.Bytes, len(e.Uncles))
|
||||||
|
for i, ucl := range e.Uncles {
|
||||||
|
uncles[i] = ucl
|
||||||
|
}
|
||||||
|
num := new(big.Int).SetBytes(e.Number)
|
||||||
|
numHex := hexutil.EncodeBig(num)
|
||||||
|
|
||||||
|
diff := new(big.Int).SetBytes(e.Difficulty)
|
||||||
|
diffHex := hexutil.EncodeBig(diff)
|
||||||
|
|
||||||
|
size := new(big.Int).SetBytes(e.Size)
|
||||||
|
sizeHex := hexutil.EncodeBig(size)
|
||||||
|
|
||||||
|
baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas))
|
||||||
|
baseFeeHex := hexutil.EncodeBig(baseFee)
|
||||||
|
return json.Marshal(executionBlockJSON{
|
||||||
|
Number: numHex,
|
||||||
|
Hash: e.Hash,
|
||||||
|
ParentHash: e.ParentHash,
|
||||||
|
Sha3Uncles: e.Sha3Uncles,
|
||||||
|
Miner: e.Miner,
|
||||||
|
StateRoot: e.StateRoot,
|
||||||
|
TransactionsRoot: e.TransactionsRoot,
|
||||||
|
ReceiptsRoot: e.ReceiptsRoot,
|
||||||
|
LogsBloom: e.LogsBloom,
|
||||||
|
Difficulty: diffHex,
|
||||||
|
TotalDifficulty: e.TotalDifficulty,
|
||||||
|
GasLimit: hexutil.Uint64(e.GasLimit),
|
||||||
|
GasUsed: hexutil.Uint64(e.GasUsed),
|
||||||
|
Timestamp: hexutil.Uint64(e.Timestamp),
|
||||||
|
ExtraData: e.ExtraData,
|
||||||
|
MixHash: e.MixHash,
|
||||||
|
Nonce: e.Nonce,
|
||||||
|
Size: sizeHex,
|
||||||
|
BaseFeePerGas: baseFeeHex,
|
||||||
|
Transactions: transactions,
|
||||||
|
Uncles: uncles,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON defines a custom json.Unmarshaler interface implementation
|
||||||
|
// that uses custom json.Unmarshalers for the hexutil.Bytes and hexutil.Uint64 types.
|
||||||
|
func (e *ExecutionBlockWithTxs) UnmarshalJSON(enc []byte) error {
|
||||||
|
dec := executionBlockWithTxsJSON{}
|
||||||
|
if err := json.Unmarshal(enc, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*e = ExecutionBlockWithTxs{}
|
||||||
|
num, err := hexutil.DecodeBig(dec.Number)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.Number = num.Bytes()
|
||||||
|
e.Hash = dec.Hash
|
||||||
|
e.ParentHash = dec.ParentHash
|
||||||
|
e.Sha3Uncles = dec.Sha3Uncles
|
||||||
|
e.Miner = dec.Miner
|
||||||
|
e.StateRoot = dec.StateRoot
|
||||||
|
e.TransactionsRoot = dec.TransactionsRoot
|
||||||
|
e.ReceiptsRoot = dec.ReceiptsRoot
|
||||||
|
e.LogsBloom = dec.LogsBloom
|
||||||
|
diff, err := hexutil.DecodeBig(dec.Difficulty)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.Difficulty = diff.Bytes()
|
||||||
|
e.TotalDifficulty = dec.TotalDifficulty
|
||||||
|
e.GasLimit = uint64(dec.GasLimit)
|
||||||
|
e.GasUsed = uint64(dec.GasUsed)
|
||||||
|
e.Timestamp = uint64(dec.Timestamp)
|
||||||
|
e.ExtraData = dec.ExtraData
|
||||||
|
e.MixHash = dec.MixHash
|
||||||
|
e.Nonce = dec.Nonce
|
||||||
|
size, err := hexutil.DecodeBig(dec.Size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.Size = size.Bytes()
|
||||||
|
baseFee, err := hexutil.DecodeBig(dec.BaseFeePerGas)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
|
||||||
|
transactions := make([][]byte, len(dec.Transactions))
|
||||||
|
for i, tx := range dec.Transactions {
|
||||||
|
enc, err := tx.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
transactions[i] = enc
|
||||||
|
}
|
||||||
|
e.Transactions = transactions
|
||||||
|
uncles := make([][]byte, len(dec.Uncles))
|
||||||
|
for i, ucl := range dec.Uncles {
|
||||||
|
uncles[i] = ucl
|
||||||
|
}
|
||||||
|
e.Uncles = uncles
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type executionPayloadJSON struct {
|
type executionPayloadJSON struct {
|
||||||
ParentHash hexutil.Bytes `json:"parentHash"`
|
ParentHash hexutil.Bytes `json:"parentHash"`
|
||||||
FeeRecipient hexutil.Bytes `json:"feeRecipient"`
|
FeeRecipient hexutil.Bytes `json:"feeRecipient"`
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ func (m *engineMock) NewPayload(context.Context, *pb.ExecutionPayload) ([]byte,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *engineMock) ExecutionBlockByHashWithTxs(_ context.Context, _ common.Hash) (*pb.ExecutionBlockWithTxs, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *engineMock) LatestExecutionBlock(context.Context) (*pb.ExecutionBlock, error) {
|
func (m *engineMock) LatestExecutionBlock(context.Context) (*pb.ExecutionBlock, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user