mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Engine api (#7)
This commit is contained in:
parent
0e4999d59f
commit
7285ddd28b
8 changed files with 157 additions and 2 deletions
|
|
@ -21,6 +21,10 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
// <specular modification>
|
||||||
|
Transactions []hexutil.Bytes `json:"transactions,omitempty" gencodec:"optional"`
|
||||||
|
NoTxPool bool `json:"noTxPool,omitempty" gencodec:"optional"`
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
var enc PayloadAttributes
|
var enc PayloadAttributes
|
||||||
enc.Timestamp = hexutil.Uint64(p.Timestamp)
|
enc.Timestamp = hexutil.Uint64(p.Timestamp)
|
||||||
|
|
@ -28,6 +32,15 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||||
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
||||||
enc.Withdrawals = p.Withdrawals
|
enc.Withdrawals = p.Withdrawals
|
||||||
enc.BeaconRoot = p.BeaconRoot
|
enc.BeaconRoot = p.BeaconRoot
|
||||||
|
// <specular modification>
|
||||||
|
if p.Transactions != nil {
|
||||||
|
enc.Transactions = make([]hexutil.Bytes, len(p.Transactions))
|
||||||
|
for k, v := range p.Transactions {
|
||||||
|
enc.Transactions[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc.NoTxPool = p.NoTxPool
|
||||||
|
// <specular modification/>
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,6 +52,10 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
||||||
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
// <specular modification>
|
||||||
|
Transactions []hexutil.Bytes `json:"transactions,omitempty" gencodec:"optional"`
|
||||||
|
NoTxPool *bool `json:"noTxPool,omitempty" gencodec:"optional"`
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
var dec PayloadAttributes
|
var dec PayloadAttributes
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -62,5 +79,16 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
||||||
if dec.BeaconRoot != nil {
|
if dec.BeaconRoot != nil {
|
||||||
p.BeaconRoot = dec.BeaconRoot
|
p.BeaconRoot = dec.BeaconRoot
|
||||||
}
|
}
|
||||||
|
// <specular modification>
|
||||||
|
if dec.Transactions != nil {
|
||||||
|
p.Transactions = make([][]byte, len(dec.Transactions))
|
||||||
|
for k, v := range dec.Transactions {
|
||||||
|
p.Transactions[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dec.NoTxPool != nil {
|
||||||
|
p.NoTxPool = *dec.NoTxPool
|
||||||
|
}
|
||||||
|
// <specular modification/>
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,21 @@ type PayloadAttributes struct {
|
||||||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
// <specular modification>
|
||||||
|
// Transactions is a field for L2s: the transactions list is forced into the block
|
||||||
|
Transactions [][]byte `json:"transactions,omitempty" gencodec:"optional"`
|
||||||
|
// NoTxPool is a field for L2s: if true, the no transactions are taken out of the tx-pool,
|
||||||
|
// only transactions from the above Transactions list will be included.
|
||||||
|
NoTxPool bool `json:"noTxPool,omitempty" gencodec:"optional"`
|
||||||
|
// <specular modification//>
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON type overrides for PayloadAttributes.
|
// JSON type overrides for PayloadAttributes.
|
||||||
type payloadAttributesMarshaling struct {
|
type payloadAttributesMarshaling struct {
|
||||||
Timestamp hexutil.Uint64
|
Timestamp hexutil.Uint64
|
||||||
|
// <specular modification>
|
||||||
|
Transactions []hexutil.Bytes
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go
|
//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,9 @@ var (
|
||||||
utils.GpoPercentileFlag,
|
utils.GpoPercentileFlag,
|
||||||
utils.GpoMaxGasPriceFlag,
|
utils.GpoMaxGasPriceFlag,
|
||||||
utils.GpoIgnoreGasPriceFlag,
|
utils.GpoIgnoreGasPriceFlag,
|
||||||
|
// <specular modification>
|
||||||
|
utils.EnableL2EngineApiFlag,
|
||||||
|
// <specular modification/>
|
||||||
configFileFlag,
|
configFileFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags)
|
}, utils.NetworkFlags, utils.DatabasePathFlags)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -949,6 +949,14 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||||
Value: metrics.DefaultConfig.InfluxDBOrganization,
|
Value: metrics.DefaultConfig.InfluxDBOrganization,
|
||||||
Category: flags.MetricsCategory,
|
Category: flags.MetricsCategory,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <specular modification/>
|
||||||
|
EnableL2EngineApiFlag = &cli.BoolFlag{
|
||||||
|
Name: "enableL2EngineApi",
|
||||||
|
Usage: "Enable L2 Engine API",
|
||||||
|
Category: flags.EthCategory,
|
||||||
|
}
|
||||||
|
// </specular modification/>
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -1574,6 +1582,12 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
||||||
if ctx.IsSet(MinerNewPayloadTimeout.Name) {
|
if ctx.IsSet(MinerNewPayloadTimeout.Name) {
|
||||||
cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name)
|
cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name)
|
||||||
}
|
}
|
||||||
|
// <specular modification>
|
||||||
|
cfg.EnableL2EngineApi = ctx.Bool(EnableL2EngineApiFlag.Name)
|
||||||
|
if cfg.EnableL2EngineApi {
|
||||||
|
log.Info("L2 Engine API enabled")
|
||||||
|
}
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
|
|
||||||
func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,9 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
// If the specified head matches with our local head, do nothing and keep
|
// If the specified head matches with our local head, do nothing and keep
|
||||||
// generating the payload. It's a special corner case that a few slots are
|
// generating the payload. It's a special corner case that a few slots are
|
||||||
// missing and we are requested to generate the payload in slot.
|
// missing and we are requested to generate the payload in slot.
|
||||||
} else {
|
// <specular modification>
|
||||||
|
} else if !api.eth.Miner().IsL2EngineApiEnabled() { // minor Engine API divergence: allow proposers to reorg their own chain
|
||||||
|
// <specular modification/>
|
||||||
// If the head block is already in our canonical chain, the beacon client is
|
// If the head block is already in our canonical chain, the beacon client is
|
||||||
// probably resyncing. Ignore the update.
|
// probably resyncing. Ignore the update.
|
||||||
log.Info("Ignoring beacon update to old head", "number", block.NumberU64(), "hash", update.HeadBlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)), "have", api.eth.BlockChain().CurrentBlock().Number)
|
log.Info("Ignoring beacon update to old head", "number", block.NumberU64(), "hash", update.HeadBlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)), "have", api.eth.BlockChain().CurrentBlock().Number)
|
||||||
|
|
@ -364,6 +366,17 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
// sealed by the beacon client. The payload will be requested later, and we
|
// sealed by the beacon client. The payload will be requested later, and we
|
||||||
// will replace it arbitrarily many times in between.
|
// will replace it arbitrarily many times in between.
|
||||||
if payloadAttributes != nil {
|
if payloadAttributes != nil {
|
||||||
|
// <specular modification>
|
||||||
|
transactions := make(types.Transactions, 0, len(payloadAttributes.Transactions))
|
||||||
|
for i, otx := range payloadAttributes.Transactions {
|
||||||
|
var tx types.Transaction
|
||||||
|
if err := tx.UnmarshalBinary(otx); err != nil {
|
||||||
|
return engine.STATUS_INVALID, fmt.Errorf("transaction %d is not valid: %v", i, err)
|
||||||
|
}
|
||||||
|
transactions = append(transactions, &tx)
|
||||||
|
}
|
||||||
|
// <specular modification/>
|
||||||
|
|
||||||
args := &miner.BuildPayloadArgs{
|
args := &miner.BuildPayloadArgs{
|
||||||
Parent: update.HeadBlockHash,
|
Parent: update.HeadBlockHash,
|
||||||
Timestamp: payloadAttributes.Timestamp,
|
Timestamp: payloadAttributes.Timestamp,
|
||||||
|
|
@ -371,6 +384,10 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
Random: payloadAttributes.Random,
|
Random: payloadAttributes.Random,
|
||||||
Withdrawals: payloadAttributes.Withdrawals,
|
Withdrawals: payloadAttributes.Withdrawals,
|
||||||
BeaconRoot: payloadAttributes.BeaconRoot,
|
BeaconRoot: payloadAttributes.BeaconRoot,
|
||||||
|
// <specular modification>
|
||||||
|
NoTxPool: payloadAttributes.NoTxPool,
|
||||||
|
Transactions: transactions,
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
id := args.Id()
|
id := args.Id()
|
||||||
// If we already are busy generating this work, then we do not need
|
// If we already are busy generating this work, then we do not need
|
||||||
|
|
@ -716,6 +733,12 @@ func (api *ConsensusAPI) invalid(err error, latestValid *types.Header) engine.Pa
|
||||||
//
|
//
|
||||||
// TODO(karalabe): Spin this goroutine down somehow
|
// TODO(karalabe): Spin this goroutine down somehow
|
||||||
func (api *ConsensusAPI) heartbeat() {
|
func (api *ConsensusAPI) heartbeat() {
|
||||||
|
// <specular modification>
|
||||||
|
if api.eth.Miner().IsL2EngineApiEnabled() { // don't start the api heartbeat, there is no transition
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// <specular modification/>
|
||||||
|
|
||||||
// Sleep a bit on startup since there's obviously no beacon client yet
|
// Sleep a bit on startup since there's obviously no beacon client yet
|
||||||
// attached, so no need to print scary warnings to the user.
|
// attached, so no need to print scary warnings to the user.
|
||||||
time.Sleep(beaconUpdateStartupTimeout)
|
time.Sleep(beaconUpdateStartupTimeout)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
package miner
|
package miner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -31,6 +32,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -43,6 +45,13 @@ type Backend interface {
|
||||||
TxPool() *txpool.TxPool
|
TxPool() *txpool.TxPool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <specular modification>
|
||||||
|
type BackendWithHistoricalState interface {
|
||||||
|
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// <specular modification/>
|
||||||
|
|
||||||
// Config is the configuration parameters of mining.
|
// Config is the configuration parameters of mining.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards
|
Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards
|
||||||
|
|
@ -53,6 +62,10 @@ type Config struct {
|
||||||
Recommit time.Duration // The time interval for miner to re-create mining work.
|
Recommit time.Duration // The time interval for miner to re-create mining work.
|
||||||
|
|
||||||
NewPayloadTimeout time.Duration // The maximum time allowance for creating a new payload
|
NewPayloadTimeout time.Duration // The maximum time allowance for creating a new payload
|
||||||
|
|
||||||
|
// <specular modification>
|
||||||
|
EnableL2EngineApi bool `toml:",omitempty"`
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultConfig contains default settings for miner.
|
// DefaultConfig contains default settings for miner.
|
||||||
|
|
@ -244,3 +257,10 @@ func (miner *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscript
|
||||||
func (miner *Miner) BuildPayload(args *BuildPayloadArgs) (*Payload, error) {
|
func (miner *Miner) BuildPayload(args *BuildPayloadArgs) (*Payload, error) {
|
||||||
return miner.worker.buildPayload(args)
|
return miner.worker.buildPayload(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <specular modification>
|
||||||
|
func (miner *Miner) IsL2EngineApiEnabled() bool {
|
||||||
|
return miner.worker.config.EnableL2EngineApi
|
||||||
|
}
|
||||||
|
|
||||||
|
// <specular modification/>
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,10 @@ type BuildPayloadArgs struct {
|
||||||
Random common.Hash // The provided randomness value
|
Random common.Hash // The provided randomness value
|
||||||
Withdrawals types.Withdrawals // The provided withdrawals
|
Withdrawals types.Withdrawals // The provided withdrawals
|
||||||
BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
|
BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
|
||||||
|
// <specular modification>
|
||||||
|
NoTxPool bool // Specular addition: option to disable tx pool contents from being included
|
||||||
|
Transactions []*types.Transaction // Specular addition: txs forced into the block via engine API
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
|
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
|
||||||
|
|
@ -55,6 +59,16 @@ func (args *BuildPayloadArgs) Id() engine.PayloadID {
|
||||||
if args.BeaconRoot != nil {
|
if args.BeaconRoot != nil {
|
||||||
hasher.Write(args.BeaconRoot[:])
|
hasher.Write(args.BeaconRoot[:])
|
||||||
}
|
}
|
||||||
|
// <specular modification>
|
||||||
|
if args.NoTxPool || len(args.Transactions) > 0 { // extend if extra payload attributes are used
|
||||||
|
binary.Write(hasher, binary.BigEndian, args.NoTxPool)
|
||||||
|
binary.Write(hasher, binary.BigEndian, uint64(len(args.Transactions)))
|
||||||
|
for _, tx := range args.Transactions {
|
||||||
|
h := tx.Hash()
|
||||||
|
hasher.Write(h[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// <specular modification/>
|
||||||
var out engine.PayloadID
|
var out engine.PayloadID
|
||||||
copy(out[:], hasher.Sum(nil)[:8])
|
copy(out[:], hasher.Sum(nil)[:8])
|
||||||
return out
|
return out
|
||||||
|
|
@ -188,6 +202,9 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
|
||||||
withdrawals: args.Withdrawals,
|
withdrawals: args.Withdrawals,
|
||||||
beaconRoot: args.BeaconRoot,
|
beaconRoot: args.BeaconRoot,
|
||||||
noTxs: true,
|
noTxs: true,
|
||||||
|
// <specular modification>
|
||||||
|
txs: args.Transactions,
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
empty := w.getSealingBlock(emptyParams)
|
empty := w.getSealingBlock(emptyParams)
|
||||||
if empty.err != nil {
|
if empty.err != nil {
|
||||||
|
|
@ -196,6 +213,14 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
|
||||||
|
|
||||||
// Construct a payload object for return.
|
// Construct a payload object for return.
|
||||||
payload := newPayload(empty.block, args.Id())
|
payload := newPayload(empty.block, args.Id())
|
||||||
|
// <specular modification>
|
||||||
|
if args.NoTxPool { // don't start the background payload updating job if there is no tx pool to pull from
|
||||||
|
// make sure to make it appear as full, otherwise it will wait indefinitely for payload building to complete.
|
||||||
|
payload.full = empty.block
|
||||||
|
payload.fullFees = empty.fees
|
||||||
|
return payload, nil
|
||||||
|
}
|
||||||
|
// <specular modification/>
|
||||||
|
|
||||||
// Spin up a routine for updating the payload in background. This strategy
|
// Spin up a routine for updating the payload in background. This strategy
|
||||||
// can maximum the revenue for including transactions with highest fee.
|
// can maximum the revenue for including transactions with highest fee.
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package miner
|
package miner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -33,6 +34,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -705,6 +707,18 @@ func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase co
|
||||||
// Retrieve the parent state to execute on top and start a prefetcher for
|
// Retrieve the parent state to execute on top and start a prefetcher for
|
||||||
// the miner to speed block sealing up a bit.
|
// the miner to speed block sealing up a bit.
|
||||||
state, err := w.chain.StateAt(parent.Root)
|
state, err := w.chain.StateAt(parent.Root)
|
||||||
|
// <specular modification>
|
||||||
|
if w.config.EnableL2EngineApi { // Allow the miner to reorg its own chain arbitrarily deep
|
||||||
|
if historicalBackend, ok := w.eth.(BackendWithHistoricalState); ok {
|
||||||
|
var release tracers.StateReleaseFunc
|
||||||
|
parentBlock := w.eth.BlockChain().GetBlockByHash(parent.Hash())
|
||||||
|
state, release, err = historicalBackend.StateAtBlock(context.Background(), parentBlock, ^uint64(0), nil, false, false)
|
||||||
|
state = state.Copy()
|
||||||
|
release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// <specular modification/>
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -885,6 +899,9 @@ type generateParams struct {
|
||||||
withdrawals types.Withdrawals // List of withdrawals to include in block.
|
withdrawals types.Withdrawals // List of withdrawals to include in block.
|
||||||
beaconRoot *common.Hash // The beacon root (cancun field).
|
beaconRoot *common.Hash // The beacon root (cancun field).
|
||||||
noTxs bool // Flag whether an empty block without any transaction is expected
|
noTxs bool // Flag whether an empty block without any transaction is expected
|
||||||
|
// <specular modification>
|
||||||
|
txs types.Transactions // Transactions to include at the start of the block
|
||||||
|
// <specular modification/>
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepareWork constructs the sealing task according to the given parameters,
|
// prepareWork constructs the sealing task according to the given parameters,
|
||||||
|
|
@ -921,9 +938,12 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
|
||||||
Coinbase: genParams.coinbase,
|
Coinbase: genParams.coinbase,
|
||||||
}
|
}
|
||||||
// Set the extra field.
|
// Set the extra field.
|
||||||
if len(w.extra) != 0 {
|
// <specular modification>
|
||||||
|
if len(w.extra) != 0 && !w.config.EnableL2EngineApi { // L2 chains must not set any extra data.
|
||||||
header.Extra = w.extra
|
header.Extra = w.extra
|
||||||
}
|
}
|
||||||
|
// <specular modification/>
|
||||||
|
|
||||||
// Set the randomness field from the beacon chain if it's available.
|
// Set the randomness field from the beacon chain if it's available.
|
||||||
if genParams.random != (common.Hash{}) {
|
if genParams.random != (common.Hash{}) {
|
||||||
header.MixDigest = genParams.random
|
header.MixDigest = genParams.random
|
||||||
|
|
@ -1008,6 +1028,18 @@ func (w *worker) generateWork(params *generateParams) *newPayloadResult {
|
||||||
return &newPayloadResult{err: err}
|
return &newPayloadResult{err: err}
|
||||||
}
|
}
|
||||||
defer work.discard()
|
defer work.discard()
|
||||||
|
// <specular modification>
|
||||||
|
for _, tx := range params.txs {
|
||||||
|
from, _ := types.Sender(work.signer, tx)
|
||||||
|
work.state.SetTxContext(tx.Hash(), work.tcount)
|
||||||
|
_, err := w.commitTransaction(work, tx)
|
||||||
|
if err != nil {
|
||||||
|
return &newPayloadResult{err: fmt.Errorf("failed to force-include tx: %s type: %d sender: %s nonce: %d, err: %w", tx.Hash(), tx.Type(), from, tx.Nonce(), err)}
|
||||||
|
}
|
||||||
|
work.tcount++
|
||||||
|
}
|
||||||
|
// forced transactions done, fill rest of block with transactions
|
||||||
|
// <specular modification/>
|
||||||
|
|
||||||
if !params.noTxs {
|
if !params.noTxs {
|
||||||
interrupt := new(atomic.Int32)
|
interrupt := new(atomic.Int32)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue