diff --git a/core/chain_makers.go b/core/chain_makers.go index 29306c5222..8c0b6491a9 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -20,6 +20,8 @@ import ( "fmt" "math/big" + "github.com/holiman/uint256" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" @@ -33,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/triedb" - "github.com/holiman/uint256" ) // BlockGen creates blocks for testing. @@ -120,7 +121,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti b.SetCoinbase(common.Address{}) } b.statedb.SetTxContext(tx.Hash(), len(b.txs)) - receipt, err := ApplyTransaction(b.cm.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig, NewReceiptBloomGenerator()) + receipt, err := ApplyTransaction(b.cm.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig, false, NewReceiptBloomGenerator()) if err != nil { panic(err) } diff --git a/core/state_processor.go b/core/state_processor.go index 9ef227ccc2..3a3e346c27 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -127,7 +127,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } statedb.SetTxContext(tx.Hash(), i) - receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, bloomProcessors) + receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, false, bloomProcessors) if err != nil { bloomProcessors.Close() return statedb, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) @@ -155,7 +155,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return statedb, receipts, allLogs, *usedGas, nil } -func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, receiptProcessors ...ReceiptProcessor) (*types.Receipt, error) { +func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, droppable bool, receiptProcessors ...ReceiptProcessor) (*types.Receipt, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -166,6 +166,10 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta return nil, err } + if result.Failed() && droppable { + return nil, errors.New("droppable transaction receipt failed") + } + // Update the state with pending changes. var root []byte if config.IsByzantium(blockNumber) { @@ -211,7 +215,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, receiptProcessors ...ReceiptProcessor) (*types.Receipt, error) { +func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, droppable bool, receiptProcessors ...ReceiptProcessor) (*types.Receipt, error) { msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee) if err != nil { return nil, err @@ -225,7 +229,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo vm.EVMInterpreterPool.Put(ite) vm.EvmPool.Put(vmenv) }() - return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, receiptProcessors...) + return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, droppable, receiptProcessors...) } // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index 498f1ec2b2..92cf7a5a51 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -846,7 +846,7 @@ func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *para } receipt, err := core.ApplyTransaction(chainConfig, chain, &env.coinbase, env.gasPool, env.state, env.header, tx, - &env.header.GasUsed, *chain.GetVMConfig(), core.NewReceiptBloomGenerator()) + &env.header.GasUsed, *chain.GetVMConfig(), false, core.NewReceiptBloomGenerator()) if err != nil { return err } else if unRevertible && receipt.Status == types.ReceiptStatusFailed { diff --git a/miner/worker.go b/miner/worker.go index e1f6c3c47c..1b4bc26b3c 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -810,7 +810,7 @@ func (w *worker) applyTransaction(env *environment, tx *types.Transaction, recei gp = env.gasPool.Gas() ) - receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig(), receiptProcessors...) + receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig(), false, receiptProcessors...) if err != nil { env.state.RevertToSnapshot(snap) env.gasPool.SetGas(gp) diff --git a/miner/worker_builder.go b/miner/worker_builder.go index c4043089b9..bd81771765 100644 --- a/miner/worker_builder.go +++ b/miner/worker_builder.go @@ -431,12 +431,15 @@ func (w *worker) simulateBundle( snap := state.Snapshot() gp := gasPool.Gas() + droppable := containsHash(bundle.DroppingTxHashes, tx.Hash()) + revertible := containsHash(bundle.RevertingTxHashes, tx.Hash()) + receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &w.coinbase, gasPool, state, env.header, tx, - &tempGasUsed, *w.chain.GetVMConfig()) + &tempGasUsed, *w.chain.GetVMConfig(), droppable) if err != nil { log.Warn("fail to simulate bundle", "hash", bundle.Hash().String(), "err", err) - if containsHash(bundle.DroppingTxHashes, tx.Hash()) { + if droppable { log.Warn("drop tx in bundle", "hash", tx.Hash().String()) state.RevertToSnapshot(snap) gasPool.SetGas(gp) @@ -458,12 +461,13 @@ func (w *worker) simulateBundle( return nil, err } - if receipt.Status == types.ReceiptStatusFailed && !containsHash(bundle.RevertingTxHashes, receipt.TxHash) { + if receipt.Status == types.ReceiptStatusFailed && !revertible { // for unRevertible tx but itself can be dropped, we drop it and revert the state and gas pool - if containsHash(bundle.DroppingTxHashes, receipt.TxHash) { + if droppable { log.Warn("drop tx in bundle", "hash", receipt.TxHash.String()) // NOTE: here should not revert state, when no err returned by ApplyTransaction, state.clearJournalAndRefund() // must had been called to avoid reverting across transactions, so we can directly remove the tx from bundle + state.RevertToSnapshot(snap) gasPool.SetGas(gp) bundle.Txs = bundle.Txs.Remove(i) txsLen = len(bundle.Txs) @@ -559,7 +563,7 @@ func (w *worker) simulateGaslessBundle(env *environment, bundle *types.Bundle) ( ) receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &w.coinbase, env.gasPool, env.state, env.header, tx, - &env.header.GasUsed, *w.chain.GetVMConfig()) + &env.header.GasUsed, *w.chain.GetVMConfig(), false) if err != nil { env.state.RevertToSnapshot(snap) env.gasPool.SetGas(gp)