diff --git a/miner/worker.go b/miner/worker.go index 4f6943c02e..815fbf16ec 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -121,17 +121,20 @@ type environment struct { blobs int UnRevertible mapset.Set[common.Hash] + + gasForTxDAG uint64 // gas reserved for the txdag } // copy creates a deep copy of environment. func (env *environment) copy() *environment { cpy := &environment{ - signer: env.signer, - state: env.state.CopyWithMvStates(), - tcount: env.tcount, - coinbase: env.coinbase, - header: types.CopyHeader(env.header), - receipts: copyReceipts(env.receipts), + signer: env.signer, + state: env.state.CopyWithMvStates(), + tcount: env.tcount, + coinbase: env.coinbase, + header: types.CopyHeader(env.header), + receipts: copyReceipts(env.receipts), + gasForTxDAG: env.gasForTxDAG, } if env.gasPool != nil { gasPool := *env.gasPool @@ -908,7 +911,7 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn } } // If we don't have enough gas for any further transactions then we're done. - if env.gasPool.Gas() < params.TxGas { + if env.gasPool.Gas()-env.gasForTxDAG < params.TxGas { log.Trace("Not enough gas for further transactions", "have", env.gasPool, "want", params.TxGas) break } @@ -919,7 +922,7 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn } txTotalMeter.Mark(1) // If we don't have enough space for the next transaction, skip the account. - if env.gasPool.Gas() < ltx.Gas { + if env.gasPool.Gas()-env.gasForTxDAG < ltx.Gas { log.Trace("Not enough gas left for transaction", "hash", ltx.Hash, "left", env.gasPool.Gas(), "needed", ltx.Gas) txs.Pop() txErrNotenoughgasMeter.Mark(1) @@ -1002,7 +1005,7 @@ func (w *worker) appendTxDAG(env *environment) { return } // TODO this is a placeholder for the tx DAG data that will be generated by the stateDB - txForDAG, err := w.generateDAGTx(env.state, env.signer, env.tcount, env.coinbase) + txForDAG, err := w.generateDAGTx(env.state, env.signer, env.tcount, env.coinbase, env.gasForTxDAG) if err != nil { log.Warn("failed to generate DAG tx", "err", err) return @@ -1016,7 +1019,7 @@ func (w *worker) appendTxDAG(env *environment) { } // generateDAGTx generates a DAG transaction for the block -func (w *worker) generateDAGTx(statedb *state.StateDB, signer types.Signer, txIndex int, coinbase common.Address) (*types.Transaction, error) { +func (w *worker) generateDAGTx(statedb *state.StateDB, signer types.Signer, txIndex int, coinbase common.Address, gasLimitForDag uint64) (*types.Transaction, error) { if statedb == nil { return nil, fmt.Errorf("failed to get state db, env.state=nil") } @@ -1027,7 +1030,6 @@ func (w *worker) generateDAGTx(statedb *state.StateDB, signer types.Signer, txIn //privateKey, err := crypto.HexToECDSA(privateKeyHex) sender := w.config.ParallelTxDAGSenderPriv - receiver := DefaultTxDAGAddress if sender == nil { return nil, fmt.Errorf("missing sender private key") } @@ -1056,7 +1058,14 @@ func (w *worker) generateDAGTx(statedb *state.StateDB, signer types.Signer, txIn } // Create the transaction - tx := types.NewTransaction(nonce, receiver, big.NewInt(0), 21100, big.NewInt(0), data) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + To: &DefaultTxDAGAddress, + Value: big.NewInt(0), + Gas: gasLimitForDag, + GasPrice: big.NewInt(0), + Data: data, + }) // Sign the transaction with the private key signedTx, err := types.SignTx(tx, signer, sender) @@ -1295,6 +1304,16 @@ func (w *worker) generateWork(genParams *generateParams) *newPayloadResult { // forced transactions done, fill rest of block with transactions if !genParams.noTxs { + // reserve gas for TxDAG + work.gasForTxDAG = 0 + if w.chain.TxDAGEnabledWhenMine() { + // We reserved n% of the header.GasLimit for TxDAG data, because: + // 1. a 10k-transactions block will need at most 64k bytes for its txdag data. a 10k-transactions block usually cost 500M gas; + // 2. before EIP-2028, it cost 68 gas per non-zero byte, and after EIP-2028, it cost 16 gas; + // 3. the gas for a n-bytes txdag transaction is calculated by: 64*68 = 4352, rate: 4352/500000000 = 0.0000087; + // for just in case, we finally reserved 0.00002% gas for TxDAG data. + work.gasForTxDAG = work.header.GasLimit/50000 + 21000 + } // use shared interrupt if present interrupt := genParams.interrupt if interrupt == nil { @@ -1336,15 +1355,15 @@ func (w *worker) generateWork(genParams *generateParams) *newPayloadResult { isBuildBlockInterruptCounter.Inc(1) } } + if w.chain.TxDAGEnabledWhenMine() { + // append a DAG tx at the end of the block + w.appendTxDAG(work) + } } if intr := genParams.interrupt; intr != nil && genParams.isUpdate && intr.Load() != commitInterruptNone { return &newPayloadResult{err: errInterruptedUpdate} } - if w.chain.TxDAGEnabledWhenMine() { - // append a DAG tx at the end of the block - w.appendTxDAG(work) - } start = time.Now() block, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, nil, work.receipts, genParams.withdrawals)