miner: build block with mandatory inclusion list

This commit is contained in:
Marius van der Wijden 2024-03-21 05:26:12 +01:00
parent 4cce9f9970
commit 226fe5c203
3 changed files with 74 additions and 38 deletions

View file

@ -136,6 +136,8 @@ type ConsensusAPI struct {
forkchoiceLock sync.Mutex // Lock for the forkChoiceUpdated 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.
@ -341,6 +343,8 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
}
// Set the finalized block
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
if update.SafeBlockHash != (common.Hash{}) {
@ -368,6 +372,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
Withdrawals: payloadAttributes.Withdrawals,
BeaconRoot: payloadAttributes.BeaconRoot,
Version: payloadVersion,
InclusionList: api.coolMapThatIsNotAMemLeak[update.HeadBlockHash],
}
id := args.Id()
// 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 {
return inclusionListError(err.Error()), nil
}
api.coolMapThatIsNotAMemLeak[parentBlockHash] = txs
return &engine.InclusionListStatusV1{Status: engine.VALID}, nil
}

View file

@ -42,6 +42,7 @@ type BuildPayloadArgs struct {
Withdrawals types.Withdrawals // The provided withdrawals
BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
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.
@ -189,6 +190,7 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
withdrawals: args.Withdrawals,
beaconRoot: args.BeaconRoot,
noTxs: true,
inclusionList: args.InclusionList,
}
empty := miner.generateWork(emptyParams)
if empty.err != nil {
@ -220,6 +222,7 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
withdrawals: args.Withdrawals,
beaconRoot: args.BeaconRoot,
noTxs: false,
inclusionList: args.InclusionList,
}
for {

View file

@ -85,6 +85,7 @@ type generateParams struct {
withdrawals types.Withdrawals // List of withdrawals to include in block (shanghai field)
beaconRoot *common.Hash // The beacon root (cancun field).
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.
@ -93,6 +94,19 @@ func (miner *Miner) generateWork(params *generateParams) *newPayloadResult {
if err != nil {
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 {
interrupt := new(atomic.Int32)
timer := time.AfterFunc(miner.config.Recommit, func() {
@ -431,6 +445,19 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
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.
func totalFees(block *types.Block, receipts []*types.Receipt) *big.Int {
feesWei := new(big.Int)