Skip to content

Commit a495968

Browse files
eth/catalyst: move witness methods from engine api (#31867)
No functional changes, just moves the witness methods into its own file
1 parent 63740b7 commit a495968

File tree

2 files changed

+295
-265
lines changed

2 files changed

+295
-265
lines changed

eth/catalyst/api.go

Lines changed: 0 additions & 265 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@ import (
2727
"github.com/ethereum/go-ethereum/beacon/engine"
2828
"github.com/ethereum/go-ethereum/common"
2929
"github.com/ethereum/go-ethereum/common/hexutil"
30-
"github.com/ethereum/go-ethereum/core"
3130
"github.com/ethereum/go-ethereum/core/rawdb"
32-
"github.com/ethereum/go-ethereum/core/stateless"
3331
"github.com/ethereum/go-ethereum/core/types"
34-
"github.com/ethereum/go-ethereum/core/vm"
3532
"github.com/ethereum/go-ethereum/eth"
3633
"github.com/ethereum/go-ethereum/eth/ethconfig"
3734
"github.com/ethereum/go-ethereum/internal/version"
@@ -245,58 +242,6 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
245242
return api.forkchoiceUpdated(update, params, engine.PayloadV3, false)
246243
}
247244

248-
// ForkchoiceUpdatedWithWitnessV1 is analogous to ForkchoiceUpdatedV1, only it
249-
// generates an execution witness too if block building was requested.
250-
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
251-
if payloadAttributes != nil {
252-
switch {
253-
case payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil:
254-
return engine.STATUS_INVALID, paramsErr("withdrawals and beacon root not supported in V1")
255-
case !api.checkFork(payloadAttributes.Timestamp, forks.Paris, forks.Shanghai):
256-
return engine.STATUS_INVALID, paramsErr("fcuV1 called post-shanghai")
257-
}
258-
}
259-
return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, true)
260-
}
261-
262-
// ForkchoiceUpdatedWithWitnessV2 is analogous to ForkchoiceUpdatedV2, only it
263-
// generates an execution witness too if block building was requested.
264-
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
265-
if params != nil {
266-
switch {
267-
case params.BeaconRoot != nil:
268-
return engine.STATUS_INVALID, attributesErr("unexpected beacon root")
269-
case api.checkFork(params.Timestamp, forks.Paris) && params.Withdrawals != nil:
270-
return engine.STATUS_INVALID, attributesErr("withdrawals before shanghai")
271-
case api.checkFork(params.Timestamp, forks.Shanghai) && params.Withdrawals == nil:
272-
return engine.STATUS_INVALID, attributesErr("missing withdrawals")
273-
case !api.checkFork(params.Timestamp, forks.Paris, forks.Shanghai):
274-
return engine.STATUS_INVALID, unsupportedForkErr("fcuV2 must only be called with paris or shanghai payloads")
275-
}
276-
}
277-
return api.forkchoiceUpdated(update, params, engine.PayloadV2, true)
278-
}
279-
280-
// ForkchoiceUpdatedWithWitnessV3 is analogous to ForkchoiceUpdatedV3, only it
281-
// generates an execution witness too if block building was requested.
282-
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
283-
if params != nil {
284-
switch {
285-
case params.Withdrawals == nil:
286-
return engine.STATUS_INVALID, attributesErr("missing withdrawals")
287-
case params.BeaconRoot == nil:
288-
return engine.STATUS_INVALID, attributesErr("missing beacon root")
289-
case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague):
290-
return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads")
291-
}
292-
}
293-
// TODO(matt): the spec requires that fcu is applied when called on a valid
294-
// hash, even if params are wrong. To do this we need to split up
295-
// forkchoiceUpdate into a function that only updates the head and then a
296-
// function that kicks off block construction.
297-
return api.forkchoiceUpdated(update, params, engine.PayloadV3, true)
298-
}
299-
300245
func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, payloadWitness bool) (engine.ForkChoiceResponse, error) {
301246
api.forkchoiceLock.Lock()
302247
defer api.forkchoiceLock.Unlock()
@@ -615,160 +560,6 @@ func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHas
615560
return api.newPayload(params, versionedHashes, beaconRoot, requests, false)
616561
}
617562

618-
// NewPayloadWithWitnessV1 is analogous to NewPayloadV1, only it also generates
619-
// and returns a stateless witness after running the payload.
620-
func (api *ConsensusAPI) NewPayloadWithWitnessV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) {
621-
if params.Withdrawals != nil {
622-
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
623-
}
624-
return api.newPayload(params, nil, nil, nil, true)
625-
}
626-
627-
// NewPayloadWithWitnessV2 is analogous to NewPayloadV2, only it also generates
628-
// and returns a stateless witness after running the payload.
629-
func (api *ConsensusAPI) NewPayloadWithWitnessV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) {
630-
var (
631-
cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp)
632-
shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp)
633-
)
634-
switch {
635-
case cancun:
636-
return invalidStatus, paramsErr("can't use newPayloadV2 post-cancun")
637-
case shanghai && params.Withdrawals == nil:
638-
return invalidStatus, paramsErr("nil withdrawals post-shanghai")
639-
case !shanghai && params.Withdrawals != nil:
640-
return invalidStatus, paramsErr("non-nil withdrawals pre-shanghai")
641-
case params.ExcessBlobGas != nil:
642-
return invalidStatus, paramsErr("non-nil excessBlobGas pre-cancun")
643-
case params.BlobGasUsed != nil:
644-
return invalidStatus, paramsErr("non-nil blobGasUsed pre-cancun")
645-
}
646-
return api.newPayload(params, nil, nil, nil, true)
647-
}
648-
649-
// NewPayloadWithWitnessV3 is analogous to NewPayloadV3, only it also generates
650-
// and returns a stateless witness after running the payload.
651-
func (api *ConsensusAPI) NewPayloadWithWitnessV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
652-
switch {
653-
case params.Withdrawals == nil:
654-
return invalidStatus, paramsErr("nil withdrawals post-shanghai")
655-
case params.ExcessBlobGas == nil:
656-
return invalidStatus, paramsErr("nil excessBlobGas post-cancun")
657-
case params.BlobGasUsed == nil:
658-
return invalidStatus, paramsErr("nil blobGasUsed post-cancun")
659-
case versionedHashes == nil:
660-
return invalidStatus, paramsErr("nil versionedHashes post-cancun")
661-
case beaconRoot == nil:
662-
return invalidStatus, paramsErr("nil beaconRoot post-cancun")
663-
case !api.checkFork(params.Timestamp, forks.Cancun):
664-
return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads")
665-
}
666-
return api.newPayload(params, versionedHashes, beaconRoot, nil, true)
667-
}
668-
669-
// NewPayloadWithWitnessV4 is analogous to NewPayloadV4, only it also generates
670-
// and returns a stateless witness after running the payload.
671-
func (api *ConsensusAPI) NewPayloadWithWitnessV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) {
672-
switch {
673-
case params.Withdrawals == nil:
674-
return invalidStatus, paramsErr("nil withdrawals post-shanghai")
675-
case params.ExcessBlobGas == nil:
676-
return invalidStatus, paramsErr("nil excessBlobGas post-cancun")
677-
case params.BlobGasUsed == nil:
678-
return invalidStatus, paramsErr("nil blobGasUsed post-cancun")
679-
case versionedHashes == nil:
680-
return invalidStatus, paramsErr("nil versionedHashes post-cancun")
681-
case beaconRoot == nil:
682-
return invalidStatus, paramsErr("nil beaconRoot post-cancun")
683-
case executionRequests == nil:
684-
return invalidStatus, paramsErr("nil executionRequests post-prague")
685-
case !api.checkFork(params.Timestamp, forks.Prague):
686-
return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads")
687-
}
688-
requests := convertRequests(executionRequests)
689-
if err := validateRequests(requests); err != nil {
690-
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err)
691-
}
692-
return api.newPayload(params, versionedHashes, beaconRoot, requests, true)
693-
}
694-
695-
// ExecuteStatelessPayloadV1 is analogous to NewPayloadV1, only it operates in
696-
// a stateless mode on top of a provided witness instead of the local database.
697-
func (api *ConsensusAPI) ExecuteStatelessPayloadV1(params engine.ExecutableData, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) {
698-
if params.Withdrawals != nil {
699-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
700-
}
701-
return api.executeStatelessPayload(params, nil, nil, nil, opaqueWitness)
702-
}
703-
704-
// ExecuteStatelessPayloadV2 is analogous to NewPayloadV2, only it operates in
705-
// a stateless mode on top of a provided witness instead of the local database.
706-
func (api *ConsensusAPI) ExecuteStatelessPayloadV2(params engine.ExecutableData, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) {
707-
var (
708-
cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp)
709-
shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp)
710-
)
711-
switch {
712-
case cancun:
713-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("can't use newPayloadV2 post-cancun")
714-
case shanghai && params.Withdrawals == nil:
715-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai")
716-
case !shanghai && params.Withdrawals != nil:
717-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil withdrawals pre-shanghai")
718-
case params.ExcessBlobGas != nil:
719-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil excessBlobGas pre-cancun")
720-
case params.BlobGasUsed != nil:
721-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil blobGasUsed pre-cancun")
722-
}
723-
return api.executeStatelessPayload(params, nil, nil, nil, opaqueWitness)
724-
}
725-
726-
// ExecuteStatelessPayloadV3 is analogous to NewPayloadV3, only it operates in
727-
// a stateless mode on top of a provided witness instead of the local database.
728-
func (api *ConsensusAPI) ExecuteStatelessPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) {
729-
switch {
730-
case params.Withdrawals == nil:
731-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai")
732-
case params.ExcessBlobGas == nil:
733-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun")
734-
case params.BlobGasUsed == nil:
735-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun")
736-
case versionedHashes == nil:
737-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun")
738-
case beaconRoot == nil:
739-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun")
740-
case !api.checkFork(params.Timestamp, forks.Cancun):
741-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads")
742-
}
743-
return api.executeStatelessPayload(params, versionedHashes, beaconRoot, nil, opaqueWitness)
744-
}
745-
746-
// ExecuteStatelessPayloadV4 is analogous to NewPayloadV4, only it operates in
747-
// a stateless mode on top of a provided witness instead of the local database.
748-
func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) {
749-
switch {
750-
case params.Withdrawals == nil:
751-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai")
752-
case params.ExcessBlobGas == nil:
753-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun")
754-
case params.BlobGasUsed == nil:
755-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun")
756-
case versionedHashes == nil:
757-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun")
758-
case beaconRoot == nil:
759-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun")
760-
case executionRequests == nil:
761-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague")
762-
case !api.checkFork(params.Timestamp, forks.Prague):
763-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads")
764-
}
765-
requests := convertRequests(executionRequests)
766-
if err := validateRequests(requests); err != nil {
767-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err)
768-
}
769-
return api.executeStatelessPayload(params, versionedHashes, beaconRoot, requests, opaqueWitness)
770-
}
771-
772563
func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, witness bool) (engine.PayloadStatusV1, error) {
773564
// The locking here is, strictly, not required. Without these locks, this can happen:
774565
//
@@ -884,62 +675,6 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
884675
return engine.PayloadStatusV1{Status: engine.VALID, Witness: ow, LatestValidHash: &hash}, nil
885676
}
886677

887-
func (api *ConsensusAPI) executeStatelessPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) {
888-
log.Trace("Engine API request received", "method", "ExecuteStatelessPayload", "number", params.Number, "hash", params.BlockHash)
889-
block, err := engine.ExecutableDataToBlockNoHash(params, versionedHashes, beaconRoot, requests)
890-
if err != nil {
891-
bgu := "nil"
892-
if params.BlobGasUsed != nil {
893-
bgu = strconv.Itoa(int(*params.BlobGasUsed))
894-
}
895-
ebg := "nil"
896-
if params.ExcessBlobGas != nil {
897-
ebg = strconv.Itoa(int(*params.ExcessBlobGas))
898-
}
899-
log.Warn("Invalid ExecuteStatelessPayload params",
900-
"params.Number", params.Number,
901-
"params.ParentHash", params.ParentHash,
902-
"params.BlockHash", params.BlockHash,
903-
"params.StateRoot", params.StateRoot,
904-
"params.FeeRecipient", params.FeeRecipient,
905-
"params.LogsBloom", common.PrettyBytes(params.LogsBloom),
906-
"params.Random", params.Random,
907-
"params.GasLimit", params.GasLimit,
908-
"params.GasUsed", params.GasUsed,
909-
"params.Timestamp", params.Timestamp,
910-
"params.ExtraData", common.PrettyBytes(params.ExtraData),
911-
"params.BaseFeePerGas", params.BaseFeePerGas,
912-
"params.BlobGasUsed", bgu,
913-
"params.ExcessBlobGas", ebg,
914-
"len(params.Transactions)", len(params.Transactions),
915-
"len(params.Withdrawals)", len(params.Withdrawals),
916-
"beaconRoot", beaconRoot,
917-
"len(requests)", len(requests),
918-
"error", err)
919-
errorMsg := err.Error()
920-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil
921-
}
922-
witness := new(stateless.Witness)
923-
if err := rlp.DecodeBytes(opaqueWitness, witness); err != nil {
924-
log.Warn("Invalid ExecuteStatelessPayload witness", "err", err)
925-
errorMsg := err.Error()
926-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil
927-
}
928-
// Stash away the last update to warn the user if the beacon client goes offline
929-
api.lastNewPayloadLock.Lock()
930-
api.lastNewPayloadUpdate = time.Now()
931-
api.lastNewPayloadLock.Unlock()
932-
933-
log.Trace("Executing block statelessly", "number", block.Number(), "hash", params.BlockHash)
934-
stateRoot, receiptRoot, err := core.ExecuteStateless(api.config(), vm.Config{}, block, witness)
935-
if err != nil {
936-
log.Warn("ExecuteStatelessPayload: execution failed", "err", err)
937-
errorMsg := err.Error()
938-
return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil
939-
}
940-
return engine.StatelessPayloadStatusV1{Status: engine.VALID, StateRoot: stateRoot, ReceiptsRoot: receiptRoot}, nil
941-
}
942-
943678
// delayPayloadImport stashes the given block away for import at a later time,
944679
// either via a forkchoice update or a sync extension. This method is meant to
945680
// be called by the newpayload command when the block seems to be ok, but some

0 commit comments

Comments
 (0)