mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
miner: build block with mandatory inclusion list
This commit is contained in:
parent
4cce9f9970
commit
226fe5c203
3 changed files with 74 additions and 38 deletions
|
|
@ -136,6 +136,8 @@ type ConsensusAPI struct {
|
||||||
|
|
||||||
forkchoiceLock sync.Mutex // Lock for the forkChoiceUpdated method
|
forkchoiceLock sync.Mutex // Lock for the forkChoiceUpdated method
|
||||||
newPayloadLock sync.Mutex // Lock for the NewPayload method
|
newPayloadLock sync.Mutex // Lock for the NewPayload method
|
||||||
|
|
||||||
|
coolMapThatIsNotAMemLeak map[common.Hash][]*types.Transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConsensusAPI creates a new consensus api for the given backend.
|
// NewConsensusAPI creates a new consensus api for the given backend.
|
||||||
|
|
@ -341,6 +343,8 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
}
|
}
|
||||||
// Set the finalized block
|
// Set the finalized block
|
||||||
api.eth.BlockChain().SetFinalized(finalBlock.Header())
|
api.eth.BlockChain().SetFinalized(finalBlock.Header())
|
||||||
|
// Clear the inclusionList for that block
|
||||||
|
delete(api.coolMapThatIsNotAMemLeak, update.FinalizedBlockHash)
|
||||||
}
|
}
|
||||||
// Check if the safe block hash is in our canonical tree, if not something is wrong
|
// Check if the safe block hash is in our canonical tree, if not something is wrong
|
||||||
if update.SafeBlockHash != (common.Hash{}) {
|
if update.SafeBlockHash != (common.Hash{}) {
|
||||||
|
|
@ -361,13 +365,14 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
// will replace it arbitrarily many times in between.
|
// will replace it arbitrarily many times in between.
|
||||||
if payloadAttributes != nil {
|
if payloadAttributes != nil {
|
||||||
args := &miner.BuildPayloadArgs{
|
args := &miner.BuildPayloadArgs{
|
||||||
Parent: update.HeadBlockHash,
|
Parent: update.HeadBlockHash,
|
||||||
Timestamp: payloadAttributes.Timestamp,
|
Timestamp: payloadAttributes.Timestamp,
|
||||||
FeeRecipient: payloadAttributes.SuggestedFeeRecipient,
|
FeeRecipient: payloadAttributes.SuggestedFeeRecipient,
|
||||||
Random: payloadAttributes.Random,
|
Random: payloadAttributes.Random,
|
||||||
Withdrawals: payloadAttributes.Withdrawals,
|
Withdrawals: payloadAttributes.Withdrawals,
|
||||||
BeaconRoot: payloadAttributes.BeaconRoot,
|
BeaconRoot: payloadAttributes.BeaconRoot,
|
||||||
Version: payloadVersion,
|
Version: payloadVersion,
|
||||||
|
InclusionList: api.coolMapThatIsNotAMemLeak[update.HeadBlockHash],
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
@ -928,6 +933,7 @@ func (api *ConsensusAPI) NewInclusionListV1(addresses []common.Address, transact
|
||||||
if err := eip7547.VerifyInclusionList(api.eth.BlockChain(), block, signer, txs); err != nil {
|
if err := eip7547.VerifyInclusionList(api.eth.BlockChain(), block, signer, txs); err != nil {
|
||||||
return inclusionListError(err.Error()), nil
|
return inclusionListError(err.Error()), nil
|
||||||
}
|
}
|
||||||
|
api.coolMapThatIsNotAMemLeak[parentBlockHash] = txs
|
||||||
return &engine.InclusionListStatusV1{Status: engine.VALID}, nil
|
return &engine.InclusionListStatusV1{Status: engine.VALID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,14 @@ import (
|
||||||
// Check engine-api specification for more details.
|
// Check engine-api specification for more details.
|
||||||
// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
|
// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
|
||||||
type BuildPayloadArgs struct {
|
type BuildPayloadArgs struct {
|
||||||
Parent common.Hash // The parent block to build payload on top
|
Parent common.Hash // The parent block to build payload on top
|
||||||
Timestamp uint64 // The provided timestamp of generated payload
|
Timestamp uint64 // The provided timestamp of generated payload
|
||||||
FeeRecipient common.Address // The provided recipient address for collecting transaction fee
|
FeeRecipient common.Address // The provided recipient address for collecting transaction fee
|
||||||
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)
|
||||||
Version engine.PayloadVersion // Versioning byte for payload id calculation.
|
Version engine.PayloadVersion // Versioning byte for payload id calculation.
|
||||||
|
InclusionList []*types.Transaction // Mandatory Inclusion List
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
@ -181,14 +182,15 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
|
||||||
// enough to run. The empty payload can at least make sure there is something
|
// enough to run. The empty payload can at least make sure there is something
|
||||||
// to deliver for not missing slot.
|
// to deliver for not missing slot.
|
||||||
emptyParams := &generateParams{
|
emptyParams := &generateParams{
|
||||||
timestamp: args.Timestamp,
|
timestamp: args.Timestamp,
|
||||||
forceTime: true,
|
forceTime: true,
|
||||||
parentHash: args.Parent,
|
parentHash: args.Parent,
|
||||||
coinbase: args.FeeRecipient,
|
coinbase: args.FeeRecipient,
|
||||||
random: args.Random,
|
random: args.Random,
|
||||||
withdrawals: args.Withdrawals,
|
withdrawals: args.Withdrawals,
|
||||||
beaconRoot: args.BeaconRoot,
|
beaconRoot: args.BeaconRoot,
|
||||||
noTxs: true,
|
noTxs: true,
|
||||||
|
inclusionList: args.InclusionList,
|
||||||
}
|
}
|
||||||
empty := miner.generateWork(emptyParams)
|
empty := miner.generateWork(emptyParams)
|
||||||
if empty.err != nil {
|
if empty.err != nil {
|
||||||
|
|
@ -212,14 +214,15 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
|
||||||
endTimer := time.NewTimer(time.Second * 12)
|
endTimer := time.NewTimer(time.Second * 12)
|
||||||
|
|
||||||
fullParams := &generateParams{
|
fullParams := &generateParams{
|
||||||
timestamp: args.Timestamp,
|
timestamp: args.Timestamp,
|
||||||
forceTime: true,
|
forceTime: true,
|
||||||
parentHash: args.Parent,
|
parentHash: args.Parent,
|
||||||
coinbase: args.FeeRecipient,
|
coinbase: args.FeeRecipient,
|
||||||
random: args.Random,
|
random: args.Random,
|
||||||
withdrawals: args.Withdrawals,
|
withdrawals: args.Withdrawals,
|
||||||
beaconRoot: args.BeaconRoot,
|
beaconRoot: args.BeaconRoot,
|
||||||
noTxs: false,
|
noTxs: false,
|
||||||
|
inclusionList: args.InclusionList,
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -77,14 +77,15 @@ type newPayloadResult struct {
|
||||||
|
|
||||||
// generateParams wraps various of settings for generating sealing task.
|
// generateParams wraps various of settings for generating sealing task.
|
||||||
type generateParams struct {
|
type generateParams struct {
|
||||||
timestamp uint64 // The timestamp for sealing task
|
timestamp uint64 // The timestamp for sealing task
|
||||||
forceTime bool // Flag whether the given timestamp is immutable or not
|
forceTime bool // Flag whether the given timestamp is immutable or not
|
||||||
parentHash common.Hash // Parent block hash, empty means the latest chain head
|
parentHash common.Hash // Parent block hash, empty means the latest chain head
|
||||||
coinbase common.Address // The fee recipient address for including transaction
|
coinbase common.Address // The fee recipient address for including transaction
|
||||||
random common.Hash // The randomness generated by beacon chain, empty before the merge
|
random common.Hash // The randomness generated by beacon chain, empty before the merge
|
||||||
withdrawals types.Withdrawals // List of withdrawals to include in block (shanghai field)
|
withdrawals types.Withdrawals // List of withdrawals to include in block (shanghai field)
|
||||||
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
|
||||||
|
inclusionList []*types.Transaction // Mandatory transactions to include
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateWork generates a sealing block based on the given parameters.
|
// generateWork generates a sealing block based on the given parameters.
|
||||||
|
|
@ -93,6 +94,19 @@ func (miner *Miner) generateWork(params *generateParams) *newPayloadResult {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &newPayloadResult{err: err}
|
return &newPayloadResult{err: err}
|
||||||
}
|
}
|
||||||
|
// apply inclusion list
|
||||||
|
if len(params.inclusionList) != 0 {
|
||||||
|
interrupt := new(atomic.Int32)
|
||||||
|
timer := time.AfterFunc(miner.config.Recommit, func() {
|
||||||
|
interrupt.Store(commitInterruptTimeout)
|
||||||
|
})
|
||||||
|
defer timer.Stop()
|
||||||
|
|
||||||
|
err := miner.applyInclusionList(interrupt, work, params.inclusionList)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unexpected error while applying inclusion list: %v, noTxs: %v", err, params.noTxs)
|
||||||
|
}
|
||||||
|
}
|
||||||
if !params.noTxs {
|
if !params.noTxs {
|
||||||
interrupt := new(atomic.Int32)
|
interrupt := new(atomic.Int32)
|
||||||
timer := time.AfterFunc(miner.config.Recommit, func() {
|
timer := time.AfterFunc(miner.config.Recommit, func() {
|
||||||
|
|
@ -431,6 +445,19 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (miner *Miner) applyInclusionList(interrupt *atomic.Int32, env *environment, inclusionList []*types.Transaction) error {
|
||||||
|
txs := make(map[common.Address][]*txpool.LazyTransaction)
|
||||||
|
for _, tx := range inclusionList {
|
||||||
|
signer, _ := env.signer.Sender(tx)
|
||||||
|
txs[signer] = append(txs[signer], &txpool.LazyTransaction{Tx: tx})
|
||||||
|
}
|
||||||
|
plainTxs := newTransactionsByPriceAndNonce(env.signer, txs, env.header.BaseFee)
|
||||||
|
if err := miner.commitTransactions(env, plainTxs, new(transactionsByPriceAndNonce), interrupt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// totalFees computes total consumed miner fees in Wei. Block transactions and receipts have to have the same order.
|
// totalFees computes total consumed miner fees in Wei. Block transactions and receipts have to have the same order.
|
||||||
func totalFees(block *types.Block, receipts []*types.Receipt) *big.Int {
|
func totalFees(block *types.Block, receipts []*types.Receipt) *big.Int {
|
||||||
feesWei := new(big.Int)
|
feesWei := new(big.Int)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue