Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add new engine_opSealPayload API #248

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion op-e2e/actions/l2_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ type safeDB interface {

func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, plasmaSrc driver.PlasmaIface, eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB) *L2Verifier {
metrics := &testutils.TestDerivationMetrics{}
engine := derive.NewEngineController(eng, log, metrics, cfg, syncCfg)
engine := derive.NewEngineController(eng, log, metrics, cfg, syncCfg, false)

clSync := clsync.NewCLSync(log, cfg, metrics, engine)

Expand Down
7 changes: 7 additions & 0 deletions op-node/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ var (
EnvVars: prefixEnvVars("SEQUENCER_PRIORITY"),
Category: SequencerCategory,
}
SequencerCombinedEngineFlag = &cli.BoolFlag{
Name: "sequencer.combined-engine",
Usage: "Enable sequencer select combined engine api when sealing payload.",
EnvVars: prefixEnvVars("SEQUENCER_COMBINED_ENGINE"),
Category: SequencerCategory,
}
SequencerL1Confs = &cli.Uint64Flag{
Name: "sequencer.l1-confs",
Usage: "Number of L1 blocks to keep distance from the L1 head as a sequencer for picking an L1 origin.",
Expand Down Expand Up @@ -437,6 +443,7 @@ var optionalFlags = []cli.Flag{
SequencerStoppedFlag,
SequencerMaxSafeLagFlag,
SequencerPriorityFlag,
SequencerCombinedEngineFlag,
SequencerL1Confs,
L1EpochPollIntervalFlag,
RuntimeConfigReloadIntervalFlag,
Expand Down
14 changes: 7 additions & 7 deletions op-node/rollup/attributes/attributes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func TestAttributesHandler(t *testing.T) {
t.Run("drop stale attributes", func(t *testing.T) {
logger := testlog.Logger(t, log.LevelInfo)
eng := &testutils.MockEngine{}
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync})
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync}, false)
ah := NewAttributesHandler(logger, cfg, ec, eng)
defer eng.AssertExpectations(t)

Expand All @@ -195,7 +195,7 @@ func TestAttributesHandler(t *testing.T) {
t.Run("pending gets reorged", func(t *testing.T) {
logger := testlog.Logger(t, log.LevelInfo)
eng := &testutils.MockEngine{}
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync})
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync}, false)
ah := NewAttributesHandler(logger, cfg, ec, eng)
defer eng.AssertExpectations(t)

Expand All @@ -210,7 +210,7 @@ func TestAttributesHandler(t *testing.T) {
t.Run("consolidation fails", func(t *testing.T) {
logger := testlog.Logger(t, log.LevelInfo)
eng := &testutils.MockEngine{}
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync})
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync}, false)
ah := NewAttributesHandler(logger, cfg, ec, eng)

ec.SetUnsafeHead(refA1)
Expand Down Expand Up @@ -264,7 +264,7 @@ func TestAttributesHandler(t *testing.T) {
fn := func(t *testing.T, lastInSpan bool) {
logger := testlog.Logger(t, log.LevelInfo)
eng := &testutils.MockEngine{}
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync})
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync}, false)
ah := NewAttributesHandler(logger, cfg, ec, eng)

ec.SetUnsafeHead(refA1)
Expand Down Expand Up @@ -323,7 +323,7 @@ func TestAttributesHandler(t *testing.T) {

logger := testlog.Logger(t, log.LevelInfo)
eng := &testutils.MockEngine{}
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync})
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync}, false)
ah := NewAttributesHandler(logger, cfg, ec, eng)

ec.SetUnsafeHead(refA0)
Expand Down Expand Up @@ -374,7 +374,7 @@ func TestAttributesHandler(t *testing.T) {

logger := testlog.Logger(t, log.LevelInfo)
eng := &testutils.MockEngine{}
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync})
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync}, false)
ah := NewAttributesHandler(logger, cfg, ec, eng)

ec.SetUnsafeHead(refA0)
Expand All @@ -398,7 +398,7 @@ func TestAttributesHandler(t *testing.T) {
t.Run("no attributes", func(t *testing.T) {
logger := testlog.Logger(t, log.LevelInfo)
eng := &testutils.MockEngine{}
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync})
ec := derive.NewEngineController(eng, logger, metrics.NoopMetrics, cfg, &sync.Config{SyncMode: sync.CLSync}, false)
ah := NewAttributesHandler(logger, cfg, ec, eng)
defer eng.AssertExpectations(t)

Expand Down
14 changes: 12 additions & 2 deletions op-node/rollup/derive/engine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type ExecEngine interface {
GetPayload(ctx context.Context, payloadInfo eth.PayloadInfo) (*eth.ExecutionPayloadEnvelope, error)
ForkchoiceUpdate(ctx context.Context, state *eth.ForkchoiceState, attr *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error)
NewPayload(ctx context.Context, payload *eth.ExecutionPayload, parentBeaconBlockRoot *common.Hash) (*eth.PayloadStatusV1, error)
SealPayload(ctx context.Context, payloadInfo eth.PayloadInfo, fc *eth.ForkchoiceState, needPayload bool) (*eth.SealPayloadResponse, string, error)
L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L2BlockRef, error)
}

Expand Down Expand Up @@ -84,9 +85,11 @@ type EngineController struct {
buildingInfo eth.PayloadInfo
buildingSafe bool
safeAttrs *AttributesWithParent

combinedAPI bool
}

func NewEngineController(engine ExecEngine, log log.Logger, metrics Metrics, rollupCfg *rollup.Config, syncConfig *sync.Config) *EngineController {
func NewEngineController(engine ExecEngine, log log.Logger, metrics Metrics, rollupCfg *rollup.Config, syncConfig *sync.Config, combinedAPI bool) *EngineController {
syncStatus := syncStatusCL
if syncConfig.SyncMode == sync.ELSync {
syncStatus = syncStatusWillStartEL
Expand All @@ -102,6 +105,7 @@ func NewEngineController(engine ExecEngine, log log.Logger, metrics Metrics, rol
elTriggerGap: syncConfig.ELTriggerGap,
syncStatus: syncStatus,
clock: clock.SystemClock,
combinedAPI: combinedAPI,
}
}

Expand Down Expand Up @@ -267,7 +271,13 @@ func (e *EngineController) ConfirmPayload(ctx context.Context, agossip async.Asy
}
// Update the safe head if the payload is built with the last attributes in the batch.
updateSafe := e.buildingSafe && e.safeAttrs != nil && e.safeAttrs.IsLastInSpan
envelope, errTyp, err := confirmPayload(ctx, e.log, e.engine, fc, e.buildingInfo, updateSafe, agossip, sequencerConductor, e.metrics)

var envelope *eth.ExecutionPayloadEnvelope
if e.combinedAPI && !e.buildingSafe {
envelope, errTyp, err = confirmPayloadCombined(ctx, e.log, e.engine, fc, e.buildingInfo, updateSafe, agossip, sequencerConductor, e.metrics)
} else {
envelope, errTyp, err = confirmPayload(ctx, e.log, e.engine, fc, e.buildingInfo, updateSafe, agossip, sequencerConductor, e.metrics)
}
if err != nil {
return nil, errTyp, fmt.Errorf("failed to complete building on top of L2 chain %s, id: %s, error (%d): %w", e.buildingOnto, e.buildingInfo.ID, errTyp, err)
}
Expand Down
8 changes: 4 additions & 4 deletions op-node/rollup/derive/engine_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func TestEngineQueue_ResetWhenUnsafeOriginNotCanonical(t *testing.T) {
SyncMode: sync.CLSync,
SkipSyncStartCheck: false,
ELTriggerGap: 0,
})
}, false)
eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled, noopFinality{}, &fakeAttributesHandler{})
require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF)

Expand Down Expand Up @@ -634,7 +634,7 @@ func TestVerifyNewL1Origin(t *testing.T) {
SyncMode: sync.CLSync,
SkipSyncStartCheck: false,
ELTriggerGap: 0,
})
}, false)
eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled, noopFinality{}, &fakeAttributesHandler{})
require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF)

Expand Down Expand Up @@ -738,7 +738,7 @@ func TestBlockBuildingRace(t *testing.T) {
SyncMode: sync.CLSync,
SkipSyncStartCheck: false,
ELTriggerGap: 0,
})
}, false)
attribHandler := &fakeAttributesHandler{}
eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled, noopFinality{}, attribHandler)
require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF)
Expand Down Expand Up @@ -858,7 +858,7 @@ func TestResetLoop(t *testing.T) {
SyncMode: sync.CLSync,
SkipSyncStartCheck: false,
ELTriggerGap: 0,
})
}, false)
eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}, safedb.Disabled, noopFinality{}, &fakeAttributesHandler{})
eq.ec.SetUnsafeHead(refA2)
eq.ec.SetSafeHead(refA1)
Expand Down
114 changes: 114 additions & 0 deletions op-node/rollup/derive/engine_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,117 @@ func confirmPayload(
"txs", len(payload.Transactions), "update_safe", updateSafe)
return envelope, BlockInsertOK, nil
}

// confirmPayloadCombined is equal to confirmPayload but using engine_opSealPayload API to combine GetPayload, NewPayload, ForckchoiceUpdated calls
func confirmPayloadCombined(
ctx context.Context,
log log.Logger,
eng ExecEngine,
fc eth.ForkchoiceState,
payloadInfo eth.PayloadInfo,
updateSafe bool,
agossip async.AsyncGossiper,
sequencerConductor conductor.SequencerConductor,
metrics Metrics,
) (out *eth.ExecutionPayloadEnvelope, errTyp BlockInsertionErrType, err error) {
start := time.Now()
type SealPayloadRet struct {
res *eth.SealPayloadResponse
errStage string
err error
}
sealPayloadRetCh := make(chan SealPayloadRet, 1)
go func() {
res, errStage, err := eng.SealPayload(ctx, payloadInfo, &fc, false)
sealPayloadRetCh <- SealPayloadRet{res, errStage, err}
}()

type GetPayloadRet struct {
res *eth.ExecutionPayloadEnvelope
err error
}
getPayloadRetCh := make(chan GetPayloadRet, 1)
go func() {
res, err := eng.GetPayload(ctx, payloadInfo)
getPayloadRetCh <- GetPayloadRet{res, err}
}()

getPayloadRet := <-getPayloadRetCh
envelope := getPayloadRet.res
getPayloadErr := getPayloadRet.err
validatePayloadErr := error(nil)
if getPayloadErr == nil {
payload := envelope.ExecutionPayload
validatePayloadErr = sanityCheckPayload(payload)
if validatePayloadErr == nil {
// TODO handle sequencerConductor component
if err := sequencerConductor.CommitUnsafePayload(ctx, envelope); err != nil {
log.Error("failed to commit unsafe payload to conductor", "payloadID", payloadInfo.ID, "err", err)
}
agossip.Gossip(envelope)
}
}

sealPayloadRet := <-sealPayloadRetCh
sealRes := sealPayloadRet.res
errStage := sealPayloadRet.errStage
sealPayloadErr := sealPayloadRet.err
switch errStage {
case eth.GetPayloadStage:
return nil, BlockInsertTemporaryErr, fmt.Errorf("failed to get execution payload: %w", sealPayloadErr)
case eth.NewPayloadStage:
if sealPayloadErr != nil {
return nil, BlockInsertTemporaryErr, fmt.Errorf("failed to insert execution payload: %w", sealPayloadErr)
}
if sealRes.PayloadStatus.Status == eth.ExecutionInvalid || sealRes.PayloadStatus.Status == eth.ExecutionInvalidBlockHash {
agossip.Clear()
log.Error("Seal payload failed to new payload", "payloadID", payloadInfo.ID, "status", sealRes.PayloadStatus)
return nil, BlockInsertPayloadErr, fmt.Errorf("failed to new payload, status: %s, validationError: %v", sealRes.PayloadStatus.Status, sealRes.PayloadStatus.ValidationError)
}
if sealRes.PayloadStatus.Status != eth.ExecutionValid {
return nil, BlockInsertTemporaryErr, fmt.Errorf("failed to new payload, status: %s, validationError: %v", sealRes.PayloadStatus.Status, sealRes.PayloadStatus.ValidationError)
}
case eth.ForkchoiceUpdatedStage:
if sealPayloadErr != nil {
var inputErr eth.InputError
if errors.As(sealPayloadErr, &inputErr) {
switch inputErr.Code {
case eth.InvalidForkchoiceState:
// if we succeed to update the forkchoice pre-payload, but fail post-payload, then it is a payload error
agossip.Clear()
return nil, BlockInsertPayloadErr, fmt.Errorf("post-block-creation forkchoice update was inconsistent with engine, need reset to resolve: %w", inputErr.Unwrap())
default:
agossip.Clear()
return nil, BlockInsertPrestateErr, fmt.Errorf("unexpected error code in forkchoice-updated response: %w", sealPayloadErr)
}
} else {
agossip.Clear()
return nil, BlockInsertTemporaryErr, NewTemporaryError(fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", sealPayloadErr))
}
}
if sealRes.PayloadStatus.Status != eth.ExecutionValid {
agossip.Clear()
return nil, BlockInsertPayloadErr, fmt.Errorf("failed to forkchoice update, status: %s, validationError: %v", sealRes.PayloadStatus.Status, sealRes.PayloadStatus.ValidationError)
}
default:
if sealPayloadErr != nil || sealRes.PayloadStatus.Status != eth.ExecutionValid {
return nil, BlockInsertTemporaryErr, NewTemporaryError(fmt.Errorf("failed to seal payload, status: %s, err: %w", sealRes.PayloadStatus.Status, sealPayloadErr))
}
}

if getPayloadErr != nil {
return nil, BlockInsertTemporaryErr, NewTemporaryError(fmt.Errorf("failed to get payload: %w", getPayloadErr))
}
if validatePayloadErr != nil {
return nil, BlockInsertPayloadErr, NewCriticalError(fmt.Errorf("failed to validate payload but seal succeed: %w", validatePayloadErr))
}

agossip.Clear()
payload := envelope.ExecutionPayload
metrics.RecordSequencerStepTime("sealPayload", time.Since(start))
log.Info("Sealed block succeed", "hash", payload.BlockHash, "number", uint64(payload.BlockNumber),
"state_root", payload.StateRoot, "timestamp", uint64(payload.Timestamp), "parent", payload.ParentHash,
"prev_randao", payload.PrevRandao, "fee_recipient", payload.FeeRecipient,
"txs", len(payload.Transactions), "update_safe", updateSafe)
return envelope, BlockInsertOK, nil
}
2 changes: 2 additions & 0 deletions op-node/rollup/driver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ type Config struct {

// SequencerPriority is true when sequencer step takes precedence over other steps.
SequencerPriority bool `json:"sequencer_priority"`

SequencerCombinedEngine bool `json:"sequencer_combined_engine"`
}
2 changes: 1 addition & 1 deletion op-node/rollup/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func NewDriver(
sequencerConfDepth := NewConfDepth(driverCfg.SequencerConfDepth, l1State.L1Head, l1)
findL1Origin := NewL1OriginSelector(log, cfg, sequencerConfDepth)
verifConfDepth := NewConfDepth(driverCfg.VerifierConfDepth, l1State.L1Head, l1)
engine := derive.NewEngineController(l2, log, metrics, cfg, syncCfg)
engine := derive.NewEngineController(l2, log, metrics, cfg, syncCfg, driverCfg.SequencerCombinedEngine)
clSync := clsync.NewCLSync(log, cfg, metrics, engine)

var finalizer Finalizer
Expand Down
10 changes: 10 additions & 0 deletions op-node/rollup/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,16 @@ func (c *Config) GetPayloadVersion(timestamp uint64) eth.EngineAPIMethod {
}
}

// SealPayloadVersion returns the EngineAPIMethod suitable for the chain hard fork version.
func (c *Config) SealPayloadVersion(timestamp uint64) eth.EngineAPIMethod {
if c.IsEcotone(timestamp) {
// Cancun
return eth.SealPayloadV3
} else {
return eth.SealPayloadV2
}
}

// GetOPPlasmaConfig validates and returns the plasma config from the rollup config.
func (c *Config) GetOPPlasmaConfig() (plasma.Config, error) {
if c.PlasmaConfig == nil {
Expand Down
13 changes: 7 additions & 6 deletions op-node/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,13 @@ func NewConfigPersistence(ctx *cli.Context) node.ConfigPersistence {

func NewDriverConfig(ctx *cli.Context) *driver.Config {
return &driver.Config{
VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name),
SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name),
SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name),
SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name),
SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name),
SequencerPriority: ctx.Bool(flags.SequencerPriorityFlag.Name),
VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name),
SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name),
SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name),
SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name),
SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name),
SequencerPriority: ctx.Bool(flags.SequencerPriorityFlag.Name),
SequencerCombinedEngine: ctx.Bool(flags.SequencerCombinedEngineFlag.Name),
}
}

Expand Down
2 changes: 1 addition & 1 deletion op-program/client/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func NewDriver(logger log.Logger, cfg *rollup.Config, l1Source derive.L1Fetcher,
SyncMode: sync.CLSync,
SkipSyncStartCheck: false,
ELTriggerGap: 0,
})
}, false)
attributesHandler := attributes.NewAttributesHandler(logger, cfg, engine, l2Source)
pipeline := derive.NewDerivationPipeline(logger, cfg, l1Source, l1BlobsSource, plasma.Disabled, l2Source, engine, metrics.NoopMetrics, &sync.Config{}, safedb.Disabled, NoopFinalizer{}, attributesHandler)
pipeline.Reset()
Expand Down
4 changes: 4 additions & 0 deletions op-program/client/l2/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ func (o *OracleEngine) NewPayload(ctx context.Context, payload *eth.ExecutionPay
}
}

func (o *OracleEngine) SealPayload(ctx context.Context, payloadInfo eth.PayloadInfo, fc *eth.ForkchoiceState, needPayload bool) (*eth.SealPayloadResponse, string, error) {
return nil, "", nil
}

func (o *OracleEngine) PayloadByHash(ctx context.Context, hash common.Hash) (*eth.ExecutionPayloadEnvelope, error) {
block := o.backend.GetBlockByHash(hash)
if block == nil {
Expand Down
15 changes: 15 additions & 0 deletions op-service/eth/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ const (
InvalidPayloadAttributes ErrorCode = -38003 // Payload attributes are invalid / inconsistent.
)

const (
GetPayloadStage = "getPayload"
NewPayloadStage = "newPayload"
ForkchoiceUpdatedStage = "forkchoiceUpdated"
)

var ErrBedrockScalarPaddingNotEmpty = errors.New("version 0 scalar value has non-empty padding")

// InputError distinguishes an user-input error from regular rpc errors,
Expand Down Expand Up @@ -367,6 +373,12 @@ type ForkchoiceUpdatedResult struct {
PayloadID *PayloadID `json:"payloadId"`
}

type SealPayloadResponse struct {
ErrStage string `json:"errStage"`
PayloadStatus PayloadStatusV1 `json:"payloadStatus"`
Payload *ExecutionPayloadEnvelope `json:"payload"`
}

// SystemConfig represents the rollup system configuration that carries over in every L2 block,
// and may be changed through L1 system config events.
// The initial SystemConfig at rollup genesis is embedded in the rollup configuration.
Expand Down Expand Up @@ -512,4 +524,7 @@ const (

GetPayloadV2 EngineAPIMethod = "engine_getPayloadV2"
GetPayloadV3 EngineAPIMethod = "engine_getPayloadV3"

SealPayloadV2 EngineAPIMethod = "engine_opSealPayloadV2"
SealPayloadV3 EngineAPIMethod = "engine_opSealPayloadV3"
)
Loading
Loading