mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
Support engine_forkchoiceUpdatedV3 with ParentBeaconBlockRoot (EIP-4788) (#7969)
Prerequisites: https://github.com/ledgerwatch/interfaces/pull/187 & https://github.com/ledgerwatch/erigon-lib/pull/1069. Also implement https://github.com/ethereum/execution-apis/pull/426.
This commit is contained in:
parent
b4057da8e6
commit
d69b20bc4e
@ -290,7 +290,7 @@ Erigon can be used as an Execution Layer (EL) for Consensus Layer clients (CL).
|
||||
If your CL client is on a different device, add `--authrpc.addr 0.0.0.0` ([Engine API] listens on localhost by default)
|
||||
as well as `--authrpc.vhosts <CL host>` where `<CL host>` is your source host or `any`.
|
||||
|
||||
[Engine API]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md
|
||||
[Engine API]: https://github.com/ethereum/execution-apis/blob/main/src/engine
|
||||
|
||||
In order to establish a secure connection between the Consensus Layer and the Execution Layer, a JWT secret key is
|
||||
automatically generated.
|
||||
|
@ -6,3 +6,4 @@ const EngineNewPayloadV3 = "engine_newPayloadV3"
|
||||
|
||||
const ForkChoiceUpdatedV1 = "engine_forkchoiceUpdatedV1"
|
||||
const ForkChoiceUpdatedV2 = "engine_forkchoiceUpdatedV2"
|
||||
const ForkChoiceUpdatedV3 = "engine_forkchoiceUpdatedV3"
|
||||
|
@ -276,6 +276,7 @@ The following table shows the current implementation status of Erigon's RPC daem
|
||||
| engine_newPayloadV3 | Yes | |
|
||||
| engine_forkchoiceUpdatedV1 | Yes | |
|
||||
| engine_forkchoiceUpdatedV2 | Yes | |
|
||||
| engine_forkchoiceUpdatedV3 | Yes | |
|
||||
| engine_getPayloadV1 | Yes | |
|
||||
| engine_getPayloadV2 | Yes | |
|
||||
| engine_getPayloadV3 | Yes | |
|
||||
|
@ -7,12 +7,13 @@ import (
|
||||
)
|
||||
|
||||
// Parameters for PoS block building
|
||||
// See also https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv2
|
||||
// See also https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
|
||||
type BlockBuilderParameters struct {
|
||||
PayloadId uint64
|
||||
ParentHash libcommon.Hash
|
||||
Timestamp uint64
|
||||
PrevRandao libcommon.Hash
|
||||
SuggestedFeeRecipient libcommon.Address
|
||||
Withdrawals []*types.Withdrawal
|
||||
PayloadId uint64
|
||||
Withdrawals []*types.Withdrawal // added in Shapella (EIP-4895)
|
||||
ParentBeaconBlockRoot *libcommon.Hash // added in Dencun (EIP-4788)
|
||||
}
|
||||
|
@ -193,6 +193,7 @@ func SpawnMiningCreateBlockStage(s *StageState, tx kv.RwTx, cfg MiningCreateBloc
|
||||
|
||||
if cfg.blockBuilderParameters != nil {
|
||||
header.MixDigest = cfg.blockBuilderParameters.PrevRandao
|
||||
header.ParentBeaconBlockRoot = cfg.blockBuilderParameters.ParentBeaconBlockRoot
|
||||
|
||||
current.Header = header
|
||||
current.Uncles = nil
|
||||
|
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230806000623-e9a42e443c30
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230806094003-563a68124b44
|
||||
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2
|
||||
github.com/ledgerwatch/log/v3 v3.8.0
|
||||
github.com/ledgerwatch/secp256k1 v1.0.0
|
||||
|
4
go.sum
4
go.sum
@ -497,8 +497,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0=
|
||||
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
|
||||
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230806000623-e9a42e443c30 h1:FdZJ/lz6Uv936nQe/n7tTVc/VXcdXgipC5oPi31TEXk=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230806000623-e9a42e443c30/go.mod h1:g8v1BUhWTrK1mDMLLzFYMmLfqmfrqQmXyCPxRiBJ7iA=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230806094003-563a68124b44 h1:5tmiUuLlj94snkO1Ljq12dmqBDG+ncO2IQNPe9fU0HA=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230806094003-563a68124b44/go.mod h1:vMETmlckriMRtrg81+YGcmA4/V3XFmjScMqjCojPr3g=
|
||||
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2 h1:Ls2itRGHMOr2PbHRDA4g1HH8HQdwfJhRVfMPEaLQe94=
|
||||
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo=
|
||||
github.com/ledgerwatch/log/v3 v3.8.0 h1:gCpp7uGtIerEz1jKVPeDnbIopFPud9ZnCpBLlLBGqPU=
|
||||
|
@ -74,6 +74,13 @@ func (e *InvalidParamsError) ErrorCode() int { return -32602 }
|
||||
|
||||
func (e *InvalidParamsError) Error() string { return e.Message }
|
||||
|
||||
// mismatch between the Engine API method version and the fork
|
||||
type UnsupportedForkError struct{ Message string }
|
||||
|
||||
func (e *UnsupportedForkError) ErrorCode() int { return -38005 }
|
||||
|
||||
func (e *UnsupportedForkError) Error() string { return e.Message }
|
||||
|
||||
type CustomError struct {
|
||||
Code int
|
||||
Message string
|
||||
|
@ -115,7 +115,7 @@ func (s *EngineServer) checkWithdrawalsPresence(time uint64, withdrawals []*type
|
||||
|
||||
// EngineNewPayload validates and possibly executes payload
|
||||
func (s *EngineServer) newPayload(ctx context.Context, req *engine_types.ExecutionPayload,
|
||||
expectedBlobHashes []libcommon.Hash, version clparams.StateVersion,
|
||||
expectedBlobHashes []libcommon.Hash, parentBeaconBlockRoot *libcommon.Hash, version clparams.StateVersion,
|
||||
) (*engine_types.PayloadStatus, error) {
|
||||
var bloom types.Bloom
|
||||
copy(bloom[:], req.LogsBloom)
|
||||
@ -160,16 +160,22 @@ func (s *EngineServer) newPayload(ctx context.Context, req *engine_types.Executi
|
||||
if version >= clparams.DenebVersion {
|
||||
header.BlobGasUsed = (*uint64)(req.BlobGasUsed)
|
||||
header.ExcessBlobGas = (*uint64)(req.ExcessBlobGas)
|
||||
header.ParentBeaconBlockRoot = parentBeaconBlockRoot
|
||||
}
|
||||
|
||||
if !s.config.IsCancun(header.Time) && (header.BlobGasUsed != nil || header.ExcessBlobGas != nil) {
|
||||
return nil, &rpc.InvalidParamsError{Message: "blobGasUsed/excessBlobGas present before Cancun"}
|
||||
if (!s.config.IsCancun(header.Time) && version >= clparams.DenebVersion) ||
|
||||
(s.config.IsCancun(header.Time) && version < clparams.DenebVersion) {
|
||||
return nil, &rpc.UnsupportedForkError{Message: "Unsupported fork"}
|
||||
}
|
||||
|
||||
if s.config.IsCancun(header.Time) && (header.BlobGasUsed == nil || header.ExcessBlobGas == nil) {
|
||||
return nil, &rpc.InvalidParamsError{Message: "blobGasUsed/excessBlobGas missing"}
|
||||
}
|
||||
|
||||
if s.config.IsCancun(header.Time) && header.ParentBeaconBlockRoot == nil {
|
||||
return nil, &rpc.InvalidParamsError{Message: "parentBeaconBlockRoot missing"}
|
||||
}
|
||||
|
||||
blockHash := req.BlockHash
|
||||
if header.Hash() != blockHash {
|
||||
s.logger.Error("[NewPayload] invalid block hash", "stated", blockHash, "actual", header.Hash())
|
||||
@ -428,6 +434,12 @@ func (s *EngineServer) forkchoiceUpdated(ctx context.Context, forkchoiceState *e
|
||||
return nil, fmt.Errorf("execution layer not running as a proposer. enable proposer by taking out the --proposer.disable flag on startup")
|
||||
}
|
||||
|
||||
timestamp := uint64(payloadAttributes.Timestamp)
|
||||
if (!s.config.IsCancun(timestamp) && version >= clparams.DenebVersion) ||
|
||||
(s.config.IsCancun(timestamp) && version < clparams.DenebVersion) {
|
||||
return nil, &rpc.UnsupportedForkError{Message: "Unsupported fork"}
|
||||
}
|
||||
|
||||
headHeader := s.chainRW.GetHeaderByHash(forkchoiceState.HeadHash)
|
||||
|
||||
if headHeader.Hash() != forkchoiceState.HeadHash {
|
||||
@ -443,21 +455,25 @@ func (s *EngineServer) forkchoiceUpdated(ctx context.Context, forkchoiceState *e
|
||||
return &engine_types.ForkChoiceUpdatedResponse{PayloadStatus: status}, nil
|
||||
}
|
||||
|
||||
if headHeader.Time >= uint64(payloadAttributes.Timestamp) {
|
||||
if headHeader.Time >= timestamp {
|
||||
return nil, &engine_helpers.InvalidPayloadAttributesErr
|
||||
}
|
||||
|
||||
req := &execution.AssembleBlockRequest{
|
||||
ParentHash: gointerfaces.ConvertHashToH256(forkchoiceState.HeadHash),
|
||||
Timestamp: uint64(payloadAttributes.Timestamp),
|
||||
MixDigest: gointerfaces.ConvertHashToH256(payloadAttributes.PrevRandao),
|
||||
SuggestedFeeRecipent: gointerfaces.ConvertAddressToH160(payloadAttributes.SuggestedFeeRecipient),
|
||||
Timestamp: timestamp,
|
||||
PrevRandao: gointerfaces.ConvertHashToH256(payloadAttributes.PrevRandao),
|
||||
SuggestedFeeRecipient: gointerfaces.ConvertAddressToH160(payloadAttributes.SuggestedFeeRecipient),
|
||||
}
|
||||
|
||||
if version >= clparams.CapellaVersion {
|
||||
req.Withdrawals = engine_types.ConvertWithdrawalsToRpc(payloadAttributes.Withdrawals)
|
||||
}
|
||||
|
||||
if version >= clparams.DenebVersion {
|
||||
req.ParentBeaconBlockRoot = gointerfaces.ConvertHashToH256(payloadAttributes.ParentBeaconBlockRoot)
|
||||
}
|
||||
|
||||
resp, err := s.executionService.AssembleBlock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -564,26 +580,26 @@ func (e *EngineServer) ForkchoiceUpdatedV2(ctx context.Context, forkChoiceState
|
||||
}
|
||||
|
||||
func (e *EngineServer) ForkchoiceUpdatedV3(ctx context.Context, forkChoiceState *engine_types.ForkChoiceState, payloadAttributes *engine_types.PayloadAttributes) (*engine_types.ForkChoiceUpdatedResponse, error) {
|
||||
return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.CapellaVersion)
|
||||
return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.DenebVersion)
|
||||
}
|
||||
|
||||
// NewPayloadV1 processes new payloads (blocks) from the beacon chain without withdrawals.
|
||||
// See https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_newpayloadv1
|
||||
func (e *EngineServer) NewPayloadV1(ctx context.Context, payload *engine_types.ExecutionPayload) (*engine_types.PayloadStatus, error) {
|
||||
return e.newPayload(ctx, payload, nil, clparams.BellatrixVersion)
|
||||
return e.newPayload(ctx, payload, nil, nil, clparams.BellatrixVersion)
|
||||
}
|
||||
|
||||
// NewPayloadV2 processes new payloads (blocks) from the beacon chain with withdrawals.
|
||||
// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_newpayloadv2
|
||||
func (e *EngineServer) NewPayloadV2(ctx context.Context, payload *engine_types.ExecutionPayload) (*engine_types.PayloadStatus, error) {
|
||||
return e.newPayload(ctx, payload, nil, clparams.CapellaVersion)
|
||||
return e.newPayload(ctx, payload, nil, nil, clparams.CapellaVersion)
|
||||
}
|
||||
|
||||
// NewPayloadV3 processes new payloads (blocks) from the beacon chain with withdrawals & blob gas.
|
||||
// See https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_newpayloadv3
|
||||
func (e *EngineServer) NewPayloadV3(ctx context.Context, payload *engine_types.ExecutionPayload,
|
||||
expectedBlobHashes []libcommon.Hash, parentBeaconBlockRoot *libcommon.Hash) (*engine_types.PayloadStatus, error) {
|
||||
return e.newPayload(ctx, payload, expectedBlobHashes, clparams.DenebVersion)
|
||||
return e.newPayload(ctx, payload, expectedBlobHashes, parentBeaconBlockRoot, clparams.DenebVersion)
|
||||
}
|
||||
|
||||
// Receives consensus layer's transition configuration and checks if the execution layer has the correct configuration.
|
||||
|
@ -6,9 +6,12 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
"github.com/ledgerwatch/erigon-lib/gointerfaces"
|
||||
"github.com/ledgerwatch/erigon-lib/gointerfaces/execution"
|
||||
types2 "github.com/ledgerwatch/erigon-lib/gointerfaces/types"
|
||||
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
"github.com/ledgerwatch/erigon/core"
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
@ -49,8 +52,8 @@ func (e *EthereumExecutionModule) AssembleBlock(ctx context.Context, req *execut
|
||||
param := core.BlockBuilderParameters{
|
||||
ParentHash: gointerfaces.ConvertH256ToHash(req.ParentHash),
|
||||
Timestamp: req.Timestamp,
|
||||
PrevRandao: gointerfaces.ConvertH256ToHash(req.MixDigest),
|
||||
SuggestedFeeRecipient: gointerfaces.ConvertH160toAddress(req.SuggestedFeeRecipent),
|
||||
PrevRandao: gointerfaces.ConvertH256ToHash(req.PrevRandao),
|
||||
SuggestedFeeRecipient: gointerfaces.ConvertH160toAddress(req.SuggestedFeeRecipient),
|
||||
Withdrawals: eth1_utils.ConvertWithdrawalsFromRpc(req.Withdrawals),
|
||||
}
|
||||
|
||||
@ -58,6 +61,11 @@ func (e *EthereumExecutionModule) AssembleBlock(ctx context.Context, req *execut
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.ParentBeaconBlockRoot != nil {
|
||||
pbbr := libcommon.Hash(gointerfaces.ConvertH256ToHash(req.ParentBeaconBlockRoot))
|
||||
param.ParentBeaconBlockRoot = &pbbr
|
||||
}
|
||||
|
||||
// First check if we're already building a block with the requested parameters
|
||||
if reflect.DeepEqual(e.lastParameters, ¶m) {
|
||||
e.logger.Info("[ForkChoiceUpdated] duplicate build request")
|
||||
|
Loading…
Reference in New Issue
Block a user