mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
compute receipts
This commit is contained in:
parent
115117c682
commit
df14718291
4 changed files with 52 additions and 12 deletions
|
|
@ -124,9 +124,14 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
|
|||
}
|
||||
*usedGas += result.UsedGas
|
||||
|
||||
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), err
|
||||
}
|
||||
|
||||
// MakeReceipt generates the receipt object for a transaction given its execution result.
|
||||
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 {
|
||||
// Create a new receipt for the transaction, storing the intermediate root and gas used
|
||||
// by the tx.
|
||||
receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: *usedGas}
|
||||
receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: usedGas}
|
||||
if result.Failed() {
|
||||
receipt.Status = types.ReceiptStatusFailed
|
||||
} else {
|
||||
|
|
@ -141,7 +146,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
|
|||
}
|
||||
|
||||
// If the transaction created a contract, store the creation address in the receipt.
|
||||
if msg.To == nil {
|
||||
if tx.To() == nil {
|
||||
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +156,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
|
|||
receipt.BlockHash = blockHash
|
||||
receipt.BlockNumber = blockNumber
|
||||
receipt.TransactionIndex = uint(statedb.TxIndex())
|
||||
return receipt, err
|
||||
return receipt
|
||||
}
|
||||
|
||||
// ApplyTransaction attempts to apply a transaction to the given state database
|
||||
|
|
|
|||
|
|
@ -1147,6 +1147,10 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
|
|||
evm.SetPrecompiles(precompiles)
|
||||
}
|
||||
|
||||
return applyMessageWithEVM(ctx, evm, msg, state, timeout, gp)
|
||||
}
|
||||
|
||||
func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, state *state.StateDB, timeout time.Duration, gp *core.GasPool) (*core.ExecutionResult, error) {
|
||||
// Wait for the context to be done and cancel the evm. Even if the
|
||||
// EVM has finished, cancelling may be done (repeatedly)
|
||||
go func() {
|
||||
|
|
|
|||
|
|
@ -162,29 +162,54 @@ func (mc *multicall) execute(ctx context.Context, opts mcOpts) ([]mcBlockResult,
|
|||
gasUsed uint64
|
||||
txes = make([]*types.Transaction, len(block.Calls))
|
||||
callResults = make([]mcCallResult, len(block.Calls))
|
||||
receipts = make([]*types.Receipt, len(block.Calls))
|
||||
tracer = newTracer(opts.TraceTransfers, blockContext.BlockNumber.Uint64(), common.Hash{}, common.Hash{}, 0)
|
||||
config = mc.b.ChainConfig()
|
||||
vmConfig = &vm.Config{
|
||||
NoBaseFee: true,
|
||||
// Block hash will be repaired after execution.
|
||||
Tracer: tracer,
|
||||
}
|
||||
evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, state, config, *vmConfig)
|
||||
)
|
||||
if precompiles != nil {
|
||||
evm.SetPrecompiles(precompiles)
|
||||
}
|
||||
for i, call := range block.Calls {
|
||||
// TODO: Pre-estimate nonce and gas
|
||||
// TODO: Move gas fees sanitizing to beginning of func
|
||||
if err := mc.sanitizeCall(&call, state, &gasUsed, blockContext); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx := call.ToTransaction()
|
||||
txes[i] = tx
|
||||
// TODO: repair log block hashes post execution.
|
||||
vmConfig := &vm.Config{
|
||||
NoBaseFee: true,
|
||||
// Block hash will be repaired after execution.
|
||||
Tracer: newTracer(opts.TraceTransfers, blockContext.BlockNumber.Uint64(), common.Hash{}, tx.Hash(), uint(i)),
|
||||
|
||||
msg, err := call.ToMessage(gp.Gas(), header.BaseFee, !opts.Validation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := applyMessage(ctx, mc.b, call, state, header, timeout, gp, &blockContext, vmConfig, precompiles, !opts.Validation)
|
||||
tracer.reset(tx.Hash(), uint(i))
|
||||
evm.Reset(core.NewEVMTxContext(msg), state)
|
||||
result, err := applyMessageWithEVM(ctx, evm, msg, state, timeout, gp)
|
||||
if err != nil {
|
||||
txErr := txValidationError(err)
|
||||
return nil, txErr
|
||||
}
|
||||
// Update the state with pending changes.
|
||||
var root []byte
|
||||
if config.IsByzantium(blockContext.BlockNumber) {
|
||||
state.Finalise(true)
|
||||
} else {
|
||||
root = state.IntermediateRoot(config.IsEIP158(blockContext.BlockNumber)).Bytes()
|
||||
}
|
||||
gasUsed += result.UsedGas
|
||||
receipt := core.MakeReceipt(evm, result, state, blockContext.BlockNumber, common.Hash{}, tx, gasUsed, root)
|
||||
receipts[i] = receipt
|
||||
// If the result contains a revert reason, try to unpack it.
|
||||
if len(result.Revert()) > 0 {
|
||||
result.Err = newRevertError(result.Revert())
|
||||
}
|
||||
logs := vmConfig.Tracer.(*tracer).Logs()
|
||||
logs := tracer.Logs()
|
||||
callRes := mcCallResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)}
|
||||
if result.Failed() {
|
||||
callRes.Status = hexutil.Uint64(types.ReceiptStatusFailed)
|
||||
|
|
@ -197,8 +222,6 @@ func (mc *multicall) execute(ctx context.Context, opts mcOpts) ([]mcBlockResult,
|
|||
callRes.Status = hexutil.Uint64(types.ReceiptStatusSuccessful)
|
||||
}
|
||||
callResults[i] = callRes
|
||||
gasUsed += result.UsedGas
|
||||
state.Finalise(true)
|
||||
}
|
||||
var (
|
||||
parentHash common.Hash
|
||||
|
|
@ -212,6 +235,7 @@ func (mc *multicall) execute(ctx context.Context, opts mcOpts) ([]mcBlockResult,
|
|||
header.Root = state.IntermediateRoot(true)
|
||||
header.GasUsed = gasUsed
|
||||
header.TxHash = types.DeriveSha(types.Transactions(txes), trie.NewStackTrie(nil))
|
||||
header.ReceiptHash = types.DeriveSha(types.Receipts(receipts), trie.NewStackTrie(nil))
|
||||
results[bi] = mcBlockResultFromHeader(header, callResults)
|
||||
repairLogs(results, header.Hash())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,6 +175,13 @@ func (t *tracer) captureTransfer(from, to common.Address, value *big.Int) {
|
|||
t.captureLog(transferAddress, topics, common.BigToHash(value).Bytes())
|
||||
}
|
||||
|
||||
// reset prepares the tracer for the next transaction.
|
||||
func (t *tracer) reset(txHash common.Hash, txIdx uint) {
|
||||
t.logs = make([][]*types.Log, 1)
|
||||
t.txHash = txHash
|
||||
t.txIdx = txIdx
|
||||
}
|
||||
|
||||
func (t *tracer) Logs() []*types.Log {
|
||||
return t.logs[0]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue