Skip to content

Commit 042b851

Browse files
committed
Deneb: implements engine API end points (#12384)
1 parent c02ccdc commit 042b851

File tree

10 files changed

+1238
-474
lines changed

10 files changed

+1238
-474
lines changed

beacon-chain/blockchain/execution_engine.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,18 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
207207
if err != nil {
208208
return false, errors.Wrap(invalidBlock{error: err}, "could not get execution payload")
209209
}
210-
lastValidHash, err := s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload)
210+
211+
var lastValidHash []byte
212+
if blk.Version() >= version.Deneb {
213+
_, err = blk.Block().Body().BlobKzgCommitments()
214+
if err != nil {
215+
return false, errors.Wrap(invalidBlock{error: err}, "could not get blob kzg commitments")
216+
}
217+
// TODO: Convert kzg commitment to version hashes and feed to below
218+
lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, [][32]byte{})
219+
} else {
220+
lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, [][32]byte{} /*empty version hashes before Deneb*/)
221+
}
211222
switch err {
212223
case nil:
213224
newPayloadValidNodeCount.Inc()

beacon-chain/execution/engine_client.go

+89-28
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const (
5050
NewPayloadMethod = "engine_newPayloadV1"
5151
// NewPayloadMethodV2 v2 request string for JSON-RPC.
5252
NewPayloadMethodV2 = "engine_newPayloadV2"
53+
NewPayloadMethodV3 = "engine_newPayloadV3"
5354
// ForkchoiceUpdatedMethod v1 request string for JSON-RPC.
5455
ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1"
5556
// ForkchoiceUpdatedMethodV2 v2 request string for JSON-RPC.
@@ -58,6 +59,7 @@ const (
5859
GetPayloadMethod = "engine_getPayloadV1"
5960
// GetPayloadMethodV2 v2 request string for JSON-RPC.
6061
GetPayloadMethodV2 = "engine_getPayloadV2"
62+
GetPayloadMethodV3 = "engine_getPayloadV3"
6163
// ExchangeTransitionConfigurationMethod v1 request string for JSON-RPC.
6264
ExchangeTransitionConfigurationMethod = "engine_exchangeTransitionConfigurationV1"
6365
// ExecutionBlockByHashMethod request string for JSON-RPC.
@@ -96,11 +98,11 @@ type ExecutionPayloadReconstructor interface {
9698
// EngineCaller defines a client that can interact with an Ethereum
9799
// execution node's engine service via JSON-RPC.
98100
type EngineCaller interface {
99-
NewPayload(ctx context.Context, payload interfaces.ExecutionData) ([]byte, error)
101+
NewPayload(ctx context.Context, payload interfaces.ExecutionData, versionedHashes [][32]byte) ([]byte, error)
100102
ForkchoiceUpdated(
101103
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
102104
) (*pb.PayloadIDBytes, []byte, error)
103-
GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (interfaces.ExecutionData, error)
105+
GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (interfaces.ExecutionData, *pb.BlobsBundle, error)
104106
ExchangeTransitionConfiguration(
105107
ctx context.Context, cfg *pb.TransitionConfiguration,
106108
) error
@@ -111,7 +113,7 @@ type EngineCaller interface {
111113
var EmptyBlockHash = errors.New("Block hash is empty 0x0000...")
112114

113115
// NewPayload calls the engine_newPayloadVX method via JSON-RPC.
114-
func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionData) ([]byte, error) {
116+
func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionData, versionedHashes [][32]byte) ([]byte, error) {
115117
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.NewPayload")
116118
defer span.End()
117119
start := time.Now()
@@ -143,6 +145,15 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
143145
if err != nil {
144146
return nil, handleRPCError(err)
145147
}
148+
case *pb.ExecutionPayloadDeneb:
149+
payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadDeneb)
150+
if !ok {
151+
return nil, errors.New("execution data must be a Deneb execution payload")
152+
}
153+
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV3, payloadPb, versionedHashes)
154+
if err != nil {
155+
return nil, handleRPCError(err)
156+
}
146157
default:
147158
return nil, errors.New("unknown execution data type")
148159
}
@@ -190,7 +201,7 @@ func (s *Service) ForkchoiceUpdated(
190201
if err != nil {
191202
return nil, nil, handleRPCError(err)
192203
}
193-
case version.Capella:
204+
case version.Capella, version.Deneb:
194205
a, err := attrs.PbV2()
195206
if err != nil {
196207
return nil, nil, err
@@ -220,7 +231,8 @@ func (s *Service) ForkchoiceUpdated(
220231
}
221232

222233
// GetPayload calls the engine_getPayloadVX method via JSON-RPC.
223-
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (interfaces.ExecutionData, error) {
234+
// It returns the execution data as well as the blobs bundle.
235+
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (interfaces.ExecutionData, *pb.BlobsBundle, error) {
224236
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetPayload")
225237
defer span.End()
226238
start := time.Now()
@@ -232,23 +244,44 @@ func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot primit
232244
ctx, cancel := context.WithDeadline(ctx, d)
233245
defer cancel()
234246

247+
if slots.ToEpoch(slot) >= params.BeaconConfig().DenebForkEpoch {
248+
result := &pb.ExecutionPayloadDenebWithValueAndBlobsBundle{}
249+
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV3, pb.PayloadIDBytes(payloadId))
250+
if err != nil {
251+
return nil, nil, handleRPCError(err)
252+
}
253+
v := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(result.Value))
254+
ed, err := blocks.WrappedExecutionPayloadDeneb(result.Payload, math.WeiToGwei(v))
255+
if err != nil {
256+
return nil, nil, err
257+
}
258+
return ed, result.BlobsBundle, nil
259+
}
260+
235261
if slots.ToEpoch(slot) >= params.BeaconConfig().CapellaForkEpoch {
236262
result := &pb.ExecutionPayloadCapellaWithValue{}
237263
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV2, pb.PayloadIDBytes(payloadId))
238264
if err != nil {
239-
return nil, handleRPCError(err)
265+
return nil, nil, handleRPCError(err)
240266
}
241-
242267
v := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(result.Value))
243-
return blocks.WrappedExecutionPayloadCapella(result.Payload, math.WeiToGwei(v))
268+
ed, err := blocks.WrappedExecutionPayloadCapella(result.Payload, math.WeiToGwei(v))
269+
if err != nil {
270+
return nil, nil, err
271+
}
272+
return ed, nil, nil
244273
}
245274

246275
result := &pb.ExecutionPayload{}
247276
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethod, pb.PayloadIDBytes(payloadId))
248277
if err != nil {
249-
return nil, handleRPCError(err)
278+
return nil, nil, handleRPCError(err)
250279
}
251-
return blocks.WrappedExecutionPayload(result)
280+
ed, err := blocks.WrappedExecutionPayload(result)
281+
if err != nil {
282+
return nil, nil, err
283+
}
284+
return ed, nil, nil
252285
}
253286

254287
// ExchangeTransitionConfiguration calls the engine_exchangeTransitionConfigurationV1 method via JSON-RPC.
@@ -684,7 +717,8 @@ func fullPayloadFromExecutionBlock(
684717
txs[i] = txBin
685718
}
686719

687-
if block.Version == version.Bellatrix {
720+
switch block.Version {
721+
case version.Bellatrix:
688722
return blocks.WrappedExecutionPayload(&pb.ExecutionPayload{
689723
ParentHash: header.ParentHash(),
690724
FeeRecipient: header.FeeRecipient(),
@@ -701,24 +735,51 @@ func fullPayloadFromExecutionBlock(
701735
BlockHash: blockHash[:],
702736
Transactions: txs,
703737
})
738+
case version.Capella:
739+
return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{
740+
ParentHash: header.ParentHash(),
741+
FeeRecipient: header.FeeRecipient(),
742+
StateRoot: header.StateRoot(),
743+
ReceiptsRoot: header.ReceiptsRoot(),
744+
LogsBloom: header.LogsBloom(),
745+
PrevRandao: header.PrevRandao(),
746+
BlockNumber: header.BlockNumber(),
747+
GasLimit: header.GasLimit(),
748+
GasUsed: header.GasUsed(),
749+
Timestamp: header.Timestamp(),
750+
ExtraData: header.ExtraData(),
751+
BaseFeePerGas: header.BaseFeePerGas(),
752+
BlockHash: blockHash[:],
753+
Transactions: txs,
754+
Withdrawals: block.Withdrawals,
755+
}, 0) // We can't get the block value and don't care about the block value for this instance
756+
case version.Deneb:
757+
edg, err := header.ExcessDataGas()
758+
if err != nil {
759+
return nil, errors.Wrap(err, "unable to extract ExcessDataGas attribute from excution payload header")
760+
}
761+
return blocks.WrappedExecutionPayloadDeneb(
762+
&pb.ExecutionPayloadDeneb{
763+
ParentHash: header.ParentHash(),
764+
FeeRecipient: header.FeeRecipient(),
765+
StateRoot: header.StateRoot(),
766+
ReceiptsRoot: header.ReceiptsRoot(),
767+
LogsBloom: header.LogsBloom(),
768+
PrevRandao: header.PrevRandao(),
769+
BlockNumber: header.BlockNumber(),
770+
GasLimit: header.GasLimit(),
771+
GasUsed: header.GasUsed(),
772+
Timestamp: header.Timestamp(),
773+
ExtraData: header.ExtraData(),
774+
BaseFeePerGas: header.BaseFeePerGas(),
775+
BlockHash: blockHash[:],
776+
Transactions: txs,
777+
Withdrawals: block.Withdrawals,
778+
ExcessDataGas: edg,
779+
}, 0) // We can't get the block value and don't care about the block value for this instance
780+
default:
781+
return nil, fmt.Errorf("unknown execution block version %d", block.Version)
704782
}
705-
return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{
706-
ParentHash: header.ParentHash(),
707-
FeeRecipient: header.FeeRecipient(),
708-
StateRoot: header.StateRoot(),
709-
ReceiptsRoot: header.ReceiptsRoot(),
710-
LogsBloom: header.LogsBloom(),
711-
PrevRandao: header.PrevRandao(),
712-
BlockNumber: header.BlockNumber(),
713-
GasLimit: header.GasLimit(),
714-
GasUsed: header.GasUsed(),
715-
Timestamp: header.Timestamp(),
716-
ExtraData: header.ExtraData(),
717-
BaseFeePerGas: header.BaseFeePerGas(),
718-
BlockHash: blockHash[:],
719-
Transactions: txs,
720-
Withdrawals: block.Withdrawals,
721-
}, 0) // We can't get the block value and don't care about the block value for this instance
722783
}
723784

724785
// Handles errors received from the RPC server according to the specification.

0 commit comments

Comments
 (0)