mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
core, cmd, eth, internal, miner: rework makeReceipt
This commit is contained in:
parent
b4d99e3917
commit
9482c091b6
13 changed files with 198 additions and 139 deletions
|
|
@ -151,7 +151,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre)
|
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre)
|
||||||
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
|
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
|
||||||
gaspool = new(core.GasPool)
|
gaspool = new(core.GasPool)
|
||||||
blockHash = common.Hash{0x13, 0x37}
|
|
||||||
rejectedTxs []*rejectedTx
|
rejectedTxs []*rejectedTx
|
||||||
includedTxs types.Transactions
|
includedTxs types.Transactions
|
||||||
gasUsed = uint64(0)
|
gasUsed = uint64(0)
|
||||||
|
|
@ -312,7 +311,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the receipt logs and create the bloom filter.
|
// Set the receipt logs and create the bloom filter.
|
||||||
receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash)
|
receipt.Logs = statedb.GetLogs(tx.Hash())
|
||||||
|
// TODO (rjl493456442) should we derive fields for logs? receipts?
|
||||||
|
|
||||||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
||||||
// These three are non-consensus fields:
|
// These three are non-consensus fields:
|
||||||
//receipt.BlockHash
|
//receipt.BlockHash
|
||||||
|
|
@ -367,9 +368,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
var requests [][]byte
|
var requests [][]byte
|
||||||
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
|
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
|
||||||
// EIP-6110 deposits
|
// EIP-6110 deposits
|
||||||
var allLogs []*types.Log
|
var allLogs [][]*types.Log
|
||||||
for _, receipt := range receipts {
|
for _, receipt := range receipts {
|
||||||
allLogs = append(allLogs, receipt.Logs...)
|
allLogs = append(allLogs, receipt.Logs)
|
||||||
}
|
}
|
||||||
depositRequests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
depositRequests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
"github.com/ethereum/go-ethereum/common/prque"
|
"github.com/ethereum/go-ethereum/common/prque"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
|
|
@ -1534,7 +1533,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
|
|
||||||
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
||||||
// This function expects the chain mutex to be held.
|
// This function expects the chain mutex to be held.
|
||||||
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs [][]*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||||
if err := bc.writeBlockWithState(block, receipts, state); err != nil {
|
if err := bc.writeBlockWithState(block, receipts, state); err != nil {
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
|
|
@ -1552,7 +1551,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||||
|
|
||||||
bc.chainFeed.Send(ChainEvent{Header: block.Header()})
|
bc.chainFeed.Send(ChainEvent{Header: block.Header()})
|
||||||
if len(logs) > 0 {
|
if len(logs) > 0 {
|
||||||
bc.logsFeed.Send(logs)
|
bc.logsFeed.Send(types.DeriveLogFields(block.Hash(), block.NumberU64(), logs, block.Transactions(), false))
|
||||||
}
|
}
|
||||||
// In theory, we should fire a ChainHeadEvent when we inject
|
// In theory, we should fire a ChainHeadEvent when we inject
|
||||||
// a canonical block, but sometimes we can insert a batch of
|
// a canonical block, but sometimes we can insert a batch of
|
||||||
|
|
@ -2157,25 +2156,11 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co
|
||||||
// collectLogs collects the logs that were generated or removed during the
|
// collectLogs collects the logs that were generated or removed during the
|
||||||
// processing of a block. These logs are later announced as deleted or reborn.
|
// processing of a block. These logs are later announced as deleted or reborn.
|
||||||
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
||||||
var blobGasPrice *big.Int
|
var logs [][]*types.Log
|
||||||
excessBlobGas := b.ExcessBlobGas()
|
for _, receipt := range rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64()) {
|
||||||
if excessBlobGas != nil {
|
logs = append(logs, receipt.Logs)
|
||||||
blobGasPrice = eip4844.CalcBlobFee(*excessBlobGas)
|
|
||||||
}
|
}
|
||||||
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
|
return types.DeriveLogFields(b.Hash(), b.NumberU64(), logs, b.Transactions(), removed)
|
||||||
if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), blobGasPrice, b.Transactions()); err != nil {
|
|
||||||
log.Error("Failed to derive block receipts fields", "hash", b.Hash(), "number", b.NumberU64(), "err", err)
|
|
||||||
}
|
|
||||||
var logs []*types.Log
|
|
||||||
for _, receipt := range receipts {
|
|
||||||
for _, log := range receipt.Logs {
|
|
||||||
if removed {
|
|
||||||
log.Removed = true
|
|
||||||
}
|
|
||||||
logs = append(logs, log)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return logs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reorg takes two blocks, an old chain and a new chain and will reconstruct the
|
// reorg takes two blocks, an old chain and a new chain and will reconstruct the
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ type BlockGen struct {
|
||||||
parent *types.Block
|
parent *types.Block
|
||||||
header *types.Header
|
header *types.Header
|
||||||
statedb *state.StateDB
|
statedb *state.StateDB
|
||||||
|
signer types.Signer
|
||||||
|
|
||||||
gasPool *GasPool
|
gasPool *GasPool
|
||||||
txs []*types.Transaction
|
txs []*types.Transaction
|
||||||
|
|
@ -118,14 +119,14 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
||||||
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
|
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
|
||||||
)
|
)
|
||||||
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
|
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
|
||||||
receipt, err := ApplyTransaction(evm, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed)
|
receipt, err := ApplyTransaction(b.signer, b.gasPool, b.statedb, tx, &b.header.GasUsed, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
b.txs = append(b.txs, tx)
|
b.txs = append(b.txs, tx)
|
||||||
b.receipts = append(b.receipts, receipt)
|
b.receipts = append(b.receipts, receipt)
|
||||||
if b.header.BlobGasUsed != nil {
|
if b.header.BlobGasUsed != nil {
|
||||||
*b.header.BlobGasUsed += receipt.BlobGasUsed
|
*b.header.BlobGasUsed += tx.BlobGas()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,6 +318,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
|
genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
|
||||||
b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
|
b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
|
||||||
b.header = cm.makeHeader(parent, statedb, b.engine)
|
b.header = cm.makeHeader(parent, statedb, b.engine)
|
||||||
|
b.signer = types.MakeSigner(config, b.header.Number, b.header.Time)
|
||||||
|
|
||||||
// Set the difficulty for clique block. The chain maker doesn't have access
|
// Set the difficulty for clique block. The chain maker doesn't have access
|
||||||
// to a chain, so the difficulty will be left unset (nil). Set it here to the
|
// to a chain, so the difficulty will be left unset (nil). Set it here to the
|
||||||
|
|
@ -350,9 +352,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
var requests [][]byte
|
var requests [][]byte
|
||||||
if config.IsPrague(b.header.Number, b.header.Time) {
|
if config.IsPrague(b.header.Number, b.header.Time) {
|
||||||
// EIP-6110 deposits
|
// EIP-6110 deposits
|
||||||
var blockLogs []*types.Log
|
var blockLogs [][]*types.Log
|
||||||
for _, r := range b.receipts {
|
for _, r := range b.receipts {
|
||||||
blockLogs = append(blockLogs, r.Logs...)
|
blockLogs = append(blockLogs, r.Logs)
|
||||||
}
|
}
|
||||||
depositRequests, err := ParseDepositLogs(blockLogs, config)
|
depositRequests, err := ParseDepositLogs(blockLogs, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -421,7 +423,6 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
|
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-expand to ensure all receipts are returned.
|
// Re-expand to ensure all receipts are returned.
|
||||||
receipts = receipts[:receiptsCount]
|
receipts = receipts[:receiptsCount]
|
||||||
|
|
||||||
|
|
@ -458,6 +459,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
|
genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
|
||||||
b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
|
b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
|
||||||
b.header = cm.makeHeader(parent, statedb, b.engine)
|
b.header = cm.makeHeader(parent, statedb, b.engine)
|
||||||
|
b.signer = types.MakeSigner(config, b.header.Number, b.header.Time)
|
||||||
|
|
||||||
// TODO uncomment when proof generation is merged
|
// TODO uncomment when proof generation is merged
|
||||||
// Save pre state for proof generation
|
// Save pre state for proof generation
|
||||||
|
|
|
||||||
|
|
@ -244,15 +244,12 @@ func (s *StateDB) AddLog(log *types.Log) {
|
||||||
s.logSize++
|
s.logSize++
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogs returns the logs matching the specified transaction hash, and annotates
|
// GetLogs returns the logs matching the specified transaction hash.
|
||||||
// them with the given blockNumber and blockHash.
|
//
|
||||||
func (s *StateDB) GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log {
|
// TODO (rjl493456442) these logs are partially annotated (with transaction
|
||||||
logs := s.logs[hash]
|
// information), please get rid of these annotations as well.
|
||||||
for _, l := range logs {
|
func (s *StateDB) GetLogs(hash common.Hash) []*types.Log {
|
||||||
l.BlockNumber = blockNumber
|
return s.logs[hash]
|
||||||
l.BlockHash = blockHash
|
|
||||||
}
|
|
||||||
return logs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) Logs() []*types.Log {
|
func (s *StateDB) Logs() []*types.Log {
|
||||||
|
|
@ -333,11 +330,6 @@ func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash {
|
||||||
return common.Hash{}
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxIndex returns the current transaction index set by SetTxContext.
|
|
||||||
func (s *StateDB) TxIndex() int {
|
|
||||||
return s.txIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateDB) GetCode(addr common.Address) []byte {
|
func (s *StateDB) GetCode(addr common.Address) []byte {
|
||||||
stateObject := s.getStateObject(addr)
|
stateObject := s.getStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
|
|
|
||||||
|
|
@ -673,9 +673,9 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
|
||||||
return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
|
return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
|
||||||
state.GetRefund(), checkstate.GetRefund())
|
state.GetRefund(), checkstate.GetRefund())
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(state.GetLogs(common.Hash{}, 0, common.Hash{}), checkstate.GetLogs(common.Hash{}, 0, common.Hash{})) {
|
if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) {
|
||||||
return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
|
return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
|
||||||
state.GetLogs(common.Hash{}, 0, common.Hash{}), checkstate.GetLogs(common.Hash{}, 0, common.Hash{}))
|
state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{}))
|
||||||
}
|
}
|
||||||
if !maps.Equal(state.journal.dirties, checkstate.journal.dirties) {
|
if !maps.Equal(state.journal.dirties, checkstate.journal.dirties) {
|
||||||
getKeys := func(dirty map[common.Address]int) string {
|
getKeys := func(dirty map[common.Address]int) string {
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -58,12 +58,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
usedGas = new(uint64)
|
usedGas = new(uint64)
|
||||||
header = block.Header()
|
header = block.Header()
|
||||||
blockHash = block.Hash()
|
allLogs [][]*types.Log
|
||||||
blockNumber = block.Number()
|
|
||||||
allLogs []*types.Log
|
|
||||||
gp = new(GasPool).AddGas(block.GasLimit())
|
gp = new(GasPool).AddGas(block.GasLimit())
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mutate the block and state according to any hard-fork specs
|
// Mutate the block and state according to any hard-fork specs
|
||||||
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
|
|
@ -90,18 +87,27 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
|
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
var (
|
||||||
if err != nil {
|
err error
|
||||||
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
receipt *types.Receipt
|
||||||
}
|
)
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
|
if evm.Config.Tracer != nil {
|
||||||
receipt, err := ApplyTransactionWithEVM(msg, gp, statedb, blockNumber, blockHash, tx, usedGas, evm)
|
// TODO (rjl493456442) move the message construction
|
||||||
|
// into the ApplyTransactionWithHooks.
|
||||||
|
msg, merr := TransactionToMessage(tx, signer, header.BaseFee)
|
||||||
|
if merr != nil {
|
||||||
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), merr)
|
||||||
|
}
|
||||||
|
receipt, err = ApplyTransactionWithHooks(msg, gp, statedb, tx, i, block.Hash(), usedGas, evm, evm.Config.Tracer)
|
||||||
|
} else {
|
||||||
|
receipt, err = ApplyTransaction(signer, gp, statedb, tx, usedGas, evm)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
}
|
}
|
||||||
receipts = append(receipts, receipt)
|
receipts = append(receipts, receipt)
|
||||||
allLogs = append(allLogs, receipt.Logs...)
|
allLogs = append(allLogs, receipt.Logs)
|
||||||
}
|
}
|
||||||
// Read requests if Prague is enabled.
|
// Read requests if Prague is enabled.
|
||||||
var requests [][]byte
|
var requests [][]byte
|
||||||
|
|
@ -131,19 +137,14 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyTransactionWithEVM attempts to apply a transaction to the given state database
|
// applyTransaction attempts to apply a transaction to the given state database
|
||||||
// and uses the input parameters for its environment similar to ApplyTransaction. However,
|
// and uses the input parameters for its environment. It returns the receipt
|
||||||
// this method takes an already created EVM instance as input.
|
// for the transaction, gas used and an error if the transaction failed,
|
||||||
func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) {
|
// indicating the block was invalid.
|
||||||
if hooks := evm.Config.Tracer; hooks != nil {
|
//
|
||||||
if hooks.OnTxStart != nil {
|
// Note that the generated receipt only includes the consensus fields. Any
|
||||||
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
// additional fields must be derived separately by the caller if needed.
|
||||||
}
|
func applyTransaction(msg *Message, gp *GasPool, statedb *state.StateDB, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, uint64, error) {
|
||||||
if hooks.OnTxEnd != nil {
|
|
||||||
defer func() { hooks.OnTxEnd(receipt, err) }()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new context to be used in the EVM environment.
|
// Create a new context to be used in the EVM environment.
|
||||||
txContext := NewEVMTxContext(msg)
|
txContext := NewEVMTxContext(msg)
|
||||||
evm.SetTxContext(txContext)
|
evm.SetTxContext(txContext)
|
||||||
|
|
@ -151,23 +152,84 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
|
||||||
// Apply the transaction to the current state (included in the env).
|
// Apply the transaction to the current state (included in the env).
|
||||||
result, err := ApplyMessage(evm, msg, gp)
|
result, err := ApplyMessage(evm, msg, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state with pending changes.
|
// Update the state with pending changes.
|
||||||
var root []byte
|
var root []byte
|
||||||
|
blockNumber := evm.Context.BlockNumber
|
||||||
if evm.ChainConfig().IsByzantium(blockNumber) {
|
if evm.ChainConfig().IsByzantium(blockNumber) {
|
||||||
evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
} else {
|
} else {
|
||||||
root = statedb.IntermediateRoot(evm.ChainConfig().IsEIP158(blockNumber)).Bytes()
|
root = statedb.IntermediateRoot(evm.ChainConfig().IsEIP158(blockNumber)).Bytes()
|
||||||
}
|
}
|
||||||
*usedGas += result.UsedGas
|
*usedGas += result.UsedGas
|
||||||
|
return MakeReceipt(evm, result, statedb, tx, *usedGas, root), result.UsedGas, nil
|
||||||
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeReceipt generates the receipt object for a transaction given its execution result.
|
// ApplyTransaction attempts to apply a transaction to the given state database
|
||||||
func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas uint64, root []byte) *types.Receipt {
|
// 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.
|
||||||
|
//
|
||||||
|
// Note that the generated receipt only includes the consensus fields. Any
|
||||||
|
// additional fields must be derived separately by the caller if needed.
|
||||||
|
func ApplyTransaction(signer types.Signer, gp *GasPool, statedb *state.StateDB, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
|
||||||
|
msg, err := TransactionToMessage(tx, signer, evm.Context.BaseFee)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
receipt, _, err := applyTransaction(msg, gp, statedb, tx, usedGas, evm)
|
||||||
|
return receipt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// annotateReceipt annotates receipts with chain contextual information.
|
||||||
|
func annotateReceipt(receipt *types.Receipt, tx *types.Transaction, txIndex uint, blockHash common.Hash, gasUsed uint64, evm *vm.EVM) *types.Receipt {
|
||||||
|
receipt.TxHash = tx.Hash()
|
||||||
|
receipt.GasUsed = gasUsed
|
||||||
|
|
||||||
|
if tx.Type() == types.BlobTxType {
|
||||||
|
receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
|
||||||
|
receipt.BlobGasPrice = evm.Context.BlobBaseFee
|
||||||
|
}
|
||||||
|
// If the transaction created a contract, store the creation address in the receipt.
|
||||||
|
if tx.To() == nil {
|
||||||
|
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
|
||||||
|
}
|
||||||
|
// Set the receipt logs and create the bloom filter.
|
||||||
|
blockNumber := evm.Context.BlockNumber
|
||||||
|
for _, log := range receipt.Logs {
|
||||||
|
log.BlockNumber = blockNumber.Uint64()
|
||||||
|
log.BlockHash = blockHash
|
||||||
|
}
|
||||||
|
receipt.BlockNumber = evm.Context.BlockNumber
|
||||||
|
receipt.BlockHash = blockHash
|
||||||
|
receipt.TransactionIndex = txIndex
|
||||||
|
return receipt
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyTransactionWithHooks is a wrapper of ApplyTransaction, with the additional
|
||||||
|
// hooks specified.
|
||||||
|
//
|
||||||
|
// TODO (rjl493456442) get rid of the message parameter and construct the message
|
||||||
|
// internally.
|
||||||
|
func ApplyTransactionWithHooks(msg *Message, gp *GasPool, statedb *state.StateDB, tx *types.Transaction, txIndex int, blockHash common.Hash, usedGas *uint64, evm *vm.EVM, hooks *tracing.Hooks) (*types.Receipt, error) {
|
||||||
|
if hooks.OnTxStart != nil {
|
||||||
|
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
|
}
|
||||||
|
receipt, gasUsed, err := applyTransaction(msg, gp, statedb, tx, usedGas, evm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if hooks.OnTxEnd != nil {
|
||||||
|
hooks.OnTxEnd(annotateReceipt(receipt, tx, uint(txIndex), blockHash, gasUsed, evm), err)
|
||||||
|
}
|
||||||
|
return receipt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeReceipt generates the receipt object for a transaction based on its execution
|
||||||
|
// result. Note that the generated receipt only includes the consensus fields. Any
|
||||||
|
// additional fields must be derived separately by the caller if needed.
|
||||||
|
func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, tx *types.Transaction, usedGas uint64, root []byte) *types.Receipt {
|
||||||
// Create a new receipt for the transaction, storing the intermediate root and gas used
|
// Create a new receipt for the transaction, storing the intermediate root and gas used
|
||||||
// by the tx.
|
// by the tx.
|
||||||
receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: usedGas}
|
receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: usedGas}
|
||||||
|
|
@ -176,47 +238,20 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
|
||||||
} else {
|
} else {
|
||||||
receipt.Status = types.ReceiptStatusSuccessful
|
receipt.Status = types.ReceiptStatusSuccessful
|
||||||
}
|
}
|
||||||
receipt.TxHash = tx.Hash()
|
// Set the receipt logs and create the bloom filter.
|
||||||
receipt.GasUsed = result.UsedGas
|
receipt.Logs = statedb.GetLogs(tx.Hash())
|
||||||
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
||||||
if tx.Type() == types.BlobTxType {
|
|
||||||
receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
|
|
||||||
receipt.BlobGasPrice = evm.Context.BlobBaseFee
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the transaction created a contract, store the creation address in the receipt.
|
|
||||||
if tx.To() == nil {
|
|
||||||
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge the tx-local access event into the "block-local" one, in order to collect
|
// Merge the tx-local access event into the "block-local" one, in order to collect
|
||||||
// all values, so that the witness can be built.
|
// all values, so that the witness can be built.
|
||||||
|
//
|
||||||
|
// TODO (rjl493456442) relocate it to a better place.
|
||||||
if statedb.GetTrie().IsVerkle() {
|
if statedb.GetTrie().IsVerkle() {
|
||||||
statedb.AccessEvents().Merge(evm.AccessEvents)
|
statedb.AccessEvents().Merge(evm.AccessEvents)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the receipt logs and create the bloom filter.
|
|
||||||
receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash)
|
|
||||||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
|
||||||
receipt.BlockHash = blockHash
|
|
||||||
receipt.BlockNumber = blockNumber
|
|
||||||
receipt.TransactionIndex = uint(statedb.TxIndex())
|
|
||||||
return receipt
|
return receipt
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyTransaction attempts to apply a transaction to the given state database
|
|
||||||
// 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(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, error) {
|
|
||||||
msg, err := TransactionToMessage(tx, types.MakeSigner(evm.ChainConfig(), header.Number, header.Time), header.BaseFee)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Create a new context to be used in the EVM environment
|
|
||||||
return ApplyTransactionWithEVM(msg, gp, statedb, header.Number, header.Hash(), tx, usedGas, evm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
||||||
// contract. This method is exported to be used in tests.
|
// contract. This method is exported to be used in tests.
|
||||||
func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
|
func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
|
||||||
|
|
@ -312,9 +347,10 @@ func processRequestsSystemCall(evm *vm.EVM, requestType byte, addr common.Addres
|
||||||
|
|
||||||
// ParseDepositLogs extracts the EIP-6110 deposit values from logs emitted by
|
// ParseDepositLogs extracts the EIP-6110 deposit values from logs emitted by
|
||||||
// BeaconDepositContract.
|
// BeaconDepositContract.
|
||||||
func ParseDepositLogs(logs []*types.Log, config *params.ChainConfig) ([]byte, error) {
|
func ParseDepositLogs(logs [][]*types.Log, config *params.ChainConfig) ([]byte, error) {
|
||||||
deposits := make([]byte, 1) // note: first byte is 0x00 (== deposit request type)
|
deposits := make([]byte, 1) // note: first byte is 0x00 (== deposit request type)
|
||||||
for _, log := range logs {
|
for _, subLogs := range logs {
|
||||||
|
for _, log := range subLogs {
|
||||||
if log.Address == config.DepositContractAddress {
|
if log.Address == config.DepositContractAddress {
|
||||||
request, err := types.DepositLogToRequest(log.Data)
|
request, err := types.DepositLogToRequest(log.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -323,5 +359,6 @@ func ParseDepositLogs(logs []*types.Log, config *params.ChainConfig) ([]byte, er
|
||||||
deposits = append(deposits, request...)
|
deposits = append(deposits, request...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return deposits, nil
|
return deposits, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,6 @@ type Processor interface {
|
||||||
type ProcessResult struct {
|
type ProcessResult struct {
|
||||||
Receipts types.Receipts
|
Receipts types.Receipts
|
||||||
Requests [][]byte
|
Requests [][]byte
|
||||||
Logs []*types.Log
|
Logs [][]*types.Log
|
||||||
GasUsed uint64
|
GasUsed uint64
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,3 +59,28 @@ type logMarshaling struct {
|
||||||
TxIndex hexutil.Uint
|
TxIndex hexutil.Uint
|
||||||
Index hexutil.Uint
|
Index hexutil.Uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeriveLogFields fills the logs with contextual infos like corresponding block
|
||||||
|
// and transaction info.
|
||||||
|
func DeriveLogFields(hash common.Hash, number uint64, logs [][]*Log, txs []*Transaction, removed bool) []*Log {
|
||||||
|
var (
|
||||||
|
combined []*Log
|
||||||
|
logIndex = uint(0)
|
||||||
|
)
|
||||||
|
for i := 0; i < len(txs); i++ {
|
||||||
|
for j := 0; j < len(logs[i]); j++ {
|
||||||
|
l := logs[i][j]
|
||||||
|
l.BlockNumber = number
|
||||||
|
l.BlockHash = hash
|
||||||
|
l.TxHash = txs[i].Hash()
|
||||||
|
l.TxIndex = uint(i)
|
||||||
|
l.Index = logIndex
|
||||||
|
if removed {
|
||||||
|
l.Removed = true
|
||||||
|
}
|
||||||
|
combined = append(combined, l)
|
||||||
|
logIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return combined
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -321,8 +321,8 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeriveFields fills the receipts with their computed fields based on consensus
|
// DeriveFields fills the receipts and logs with their computed fields based
|
||||||
// data and contextual infos like containing block and transactions.
|
// on consensus data and contextual infos like containing block and transactions.
|
||||||
func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, blobGasPrice *big.Int, txs []*Transaction) error {
|
func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, blobGasPrice *big.Int, txs []*Transaction) error {
|
||||||
signer := MakeSigner(config, new(big.Int).SetUint64(number), time)
|
signer := MakeSigner(config, new(big.Int).SetUint64(number), time)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -972,6 +972,12 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
msg = args.ToMessage(vmctx.BaseFee, true, true)
|
msg = args.ToMessage(vmctx.BaseFee, true, true)
|
||||||
tx = args.ToTransaction(types.LegacyTxType)
|
tx = args.ToTransaction(types.LegacyTxType)
|
||||||
traceConfig *TraceConfig
|
traceConfig *TraceConfig
|
||||||
|
txContext = &Context{
|
||||||
|
BlockNumber: new(big.Int).Add(block.Number(), common.Big1),
|
||||||
|
BlockHash: common.Hash{},
|
||||||
|
TxIndex: 0,
|
||||||
|
TxHash: tx.Hash(),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
// Lower the basefee to 0 to avoid breaking EVM
|
// Lower the basefee to 0 to avoid breaking EVM
|
||||||
// invariants (basefee < feecap).
|
// invariants (basefee < feecap).
|
||||||
|
|
@ -984,7 +990,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
if config != nil {
|
if config != nil {
|
||||||
traceConfig = &config.TraceConfig
|
traceConfig = &config.TraceConfig
|
||||||
}
|
}
|
||||||
return api.traceTx(ctx, tx, msg, new(Context), vmctx, statedb, traceConfig)
|
return api.traceTx(ctx, tx, msg, txContext, vmctx, statedb, traceConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// traceTx configures a new tracer according to the provided configuration, and
|
// traceTx configures a new tracer according to the provided configuration, and
|
||||||
|
|
@ -1014,7 +1020,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The actual TxContext will be created as part of ApplyTransactionWithEVM.
|
// The actual TxContext will be created as part of ApplyTransaction.
|
||||||
evm := vm.NewEVM(vmctx, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
evm := vm.NewEVM(vmctx, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
||||||
evm.SetTxContext(vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap})
|
evm.SetTxContext(vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap})
|
||||||
|
|
||||||
|
|
@ -1037,7 +1043,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
||||||
|
|
||||||
// Call Prepare to clear out the statedb access list
|
// Call Prepare to clear out the statedb access list
|
||||||
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
|
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
|
||||||
_, err = core.ApplyTransactionWithEVM(message, new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, evm)
|
_, err = core.ApplyTransactionWithHooks(message, new(core.GasPool).AddGas(message.GasLimit), statedb, tx, txctx.TxIndex, txctx.BlockHash, &usedGas, evm, tracer.Hooks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
txes = make([]*types.Transaction, len(block.Calls))
|
txes = make([]*types.Transaction, len(block.Calls))
|
||||||
callResults = make([]simCallResult, len(block.Calls))
|
callResults = make([]simCallResult, len(block.Calls))
|
||||||
receipts = make([]*types.Receipt, len(block.Calls))
|
receipts = make([]*types.Receipt, len(block.Calls))
|
||||||
|
|
||||||
// Block hash will be repaired after execution.
|
// Block hash will be repaired after execution.
|
||||||
tracer = newTracer(sim.traceTransfers, blockContext.BlockNumber.Uint64(), common.Hash{}, common.Hash{}, 0)
|
tracer = newTracer(sim.traceTransfers, blockContext.BlockNumber.Uint64(), common.Hash{}, common.Hash{}, 0)
|
||||||
vmConfig = &vm.Config{
|
vmConfig = &vm.Config{
|
||||||
|
|
@ -205,7 +206,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
tx := call.ToTransaction(types.DynamicFeeTxType)
|
tx := call.ToTransaction(types.DynamicFeeTxType)
|
||||||
txes[i] = tx
|
txes[i] = tx
|
||||||
tracer.reset(tx.Hash(), uint(i))
|
tracer.reset(tx.Hash(), uint(i))
|
||||||
// EoA check is always skipped, even in validation mode.
|
|
||||||
|
// EOA check is always skipped, even in validation mode.
|
||||||
msg := call.ToMessage(header.BaseFee, !sim.validate, true)
|
msg := call.ToMessage(header.BaseFee, !sim.validate, true)
|
||||||
evm.SetTxContext(core.NewEVMTxContext(msg))
|
evm.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
|
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
|
||||||
|
|
@ -221,10 +223,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes()
|
root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes()
|
||||||
}
|
}
|
||||||
gasUsed += result.UsedGas
|
gasUsed += result.UsedGas
|
||||||
receipts[i] = core.MakeReceipt(evm, result, sim.state, blockContext.BlockNumber, common.Hash{}, tx, gasUsed, root)
|
receipts[i] = core.MakeReceipt(evm, result, sim.state, tx, gasUsed, root)
|
||||||
blobGasUsed += receipts[i].BlobGasUsed
|
blobGasUsed += tx.BlobGas()
|
||||||
logs := tracer.Logs()
|
|
||||||
callRes := simCallResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)}
|
callRes := simCallResult{ReturnValue: result.Return(), Logs: tracer.Logs(), GasUsed: hexutil.Uint64(result.UsedGas)}
|
||||||
if result.Failed() {
|
if result.Failed() {
|
||||||
callRes.Status = hexutil.Uint64(types.ReceiptStatusFailed)
|
callRes.Status = hexutil.Uint64(types.ReceiptStatusFailed)
|
||||||
if errors.Is(result.Err, vm.ErrExecutionReverted) {
|
if errors.Is(result.Err, vm.ErrExecutionReverted) {
|
||||||
|
|
@ -241,6 +243,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
}
|
}
|
||||||
header.Root = sim.state.IntermediateRoot(true)
|
header.Root = sim.state.IntermediateRoot(true)
|
||||||
header.GasUsed = gasUsed
|
header.GasUsed = gasUsed
|
||||||
|
|
||||||
if sim.chainConfig.IsCancun(header.Number, header.Time) {
|
if sim.chainConfig.IsCancun(header.Number, header.Time) {
|
||||||
header.BlobGasUsed = &blobGasUsed
|
header.BlobGasUsed = &blobGasUsed
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
|
|
@ -133,13 +134,13 @@ func (miner *Miner) BuildPayload(args *BuildPayloadArgs, witness bool) (*Payload
|
||||||
// getPending retrieves the pending block based on the current head block.
|
// getPending retrieves the pending block based on the current head block.
|
||||||
// The result might be nil if pending generation is failed.
|
// The result might be nil if pending generation is failed.
|
||||||
func (miner *Miner) getPending() *newPayloadResult {
|
func (miner *Miner) getPending() *newPayloadResult {
|
||||||
header := miner.chain.CurrentHeader()
|
|
||||||
miner.pendingMu.Lock()
|
miner.pendingMu.Lock()
|
||||||
defer miner.pendingMu.Unlock()
|
defer miner.pendingMu.Unlock()
|
||||||
|
|
||||||
|
header := miner.chain.CurrentHeader()
|
||||||
if cached := miner.pending.resolve(header.Hash()); cached != nil {
|
if cached := miner.pending.resolve(header.Hash()); cached != nil {
|
||||||
return cached
|
return cached
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
timestamp = uint64(time.Now().Unix())
|
timestamp = uint64(time.Now().Unix())
|
||||||
withdrawal types.Withdrawals
|
withdrawal types.Withdrawals
|
||||||
|
|
@ -160,6 +161,15 @@ func (miner *Miner) getPending() *newPayloadResult {
|
||||||
if ret.err != nil {
|
if ret.err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// Derive the receipt fields for RPC querying.
|
||||||
|
var blobGasPrice *big.Int
|
||||||
|
if ret.block.ExcessBlobGas() != nil {
|
||||||
|
blobGasPrice = eip4844.CalcBlobFee(*ret.block.ExcessBlobGas())
|
||||||
|
}
|
||||||
|
err := types.Receipts(ret.receipts).DeriveFields(miner.chain.Config(), ret.block.Hash(), ret.block.NumberU64(), ret.block.Time(), ret.block.BaseFee(), blobGasPrice, ret.block.Transactions())
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
miner.pending.update(header.Hash(), ret)
|
miner.pending.update(header.Hash(), ret)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ type newPayloadResult struct {
|
||||||
fees *big.Int // total block fees
|
fees *big.Int // total block fees
|
||||||
sidecars []*types.BlobTxSidecar // collected blobs of blob transactions
|
sidecars []*types.BlobTxSidecar // collected blobs of blob transactions
|
||||||
stateDB *state.StateDB // StateDB after executing the transactions
|
stateDB *state.StateDB // StateDB after executing the transactions
|
||||||
receipts []*types.Receipt // Receipts collected during construction
|
receipts []*types.Receipt // Receipts collected during construction, only contain consensus fields
|
||||||
requests [][]byte // Consensus layer requests collected during block construction
|
requests [][]byte // Consensus layer requests collected during block construction
|
||||||
witness *stateless.Witness // Witness is an optional stateless proof
|
witness *stateless.Witness // Witness is an optional stateless proof
|
||||||
}
|
}
|
||||||
|
|
@ -113,11 +113,10 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo
|
||||||
}
|
}
|
||||||
|
|
||||||
body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals}
|
body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals}
|
||||||
allLogs := make([]*types.Log, 0)
|
var allLogs [][]*types.Log
|
||||||
for _, r := range work.receipts {
|
for _, r := range work.receipts {
|
||||||
allLogs = append(allLogs, r.Logs...)
|
allLogs = append(allLogs, r.Logs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect consensus-layer requests if Prague is enabled.
|
// Collect consensus-layer requests if Prague is enabled.
|
||||||
var requests [][]byte
|
var requests [][]byte
|
||||||
if miner.chainConfig.IsPrague(work.header.Number, work.header.Time) {
|
if miner.chainConfig.IsPrague(work.header.Number, work.header.Time) {
|
||||||
|
|
@ -138,7 +137,6 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo
|
||||||
reqHash := types.CalcRequestsHash(requests)
|
reqHash := types.CalcRequestsHash(requests)
|
||||||
work.header.RequestsHash = &reqHash
|
work.header.RequestsHash = &reqHash
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts)
|
block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &newPayloadResult{err: err}
|
return &newPayloadResult{err: err}
|
||||||
|
|
@ -309,7 +307,7 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
|
||||||
snap = env.state.Snapshot()
|
snap = env.state.Snapshot()
|
||||||
gp = env.gasPool.Gas()
|
gp = env.gasPool.Gas()
|
||||||
)
|
)
|
||||||
receipt, err := core.ApplyTransaction(env.evm, env.gasPool, env.state, env.header, tx, &env.header.GasUsed)
|
receipt, err := core.ApplyTransaction(env.signer, env.gasPool, env.state, tx, &env.header.GasUsed, env.evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
env.state.RevertToSnapshot(snap)
|
env.state.RevertToSnapshot(snap)
|
||||||
env.gasPool.SetGas(gp)
|
env.gasPool.SetGas(gp)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue