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
|
*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
|
// 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}
|
||||||
if result.Failed() {
|
if result.Failed() {
|
||||||
receipt.Status = types.ReceiptStatusFailed
|
receipt.Status = types.ReceiptStatusFailed
|
||||||
} else {
|
} 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 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())
|
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.BlockHash = blockHash
|
||||||
receipt.BlockNumber = blockNumber
|
receipt.BlockNumber = blockNumber
|
||||||
receipt.TransactionIndex = uint(statedb.TxIndex())
|
receipt.TransactionIndex = uint(statedb.TxIndex())
|
||||||
return receipt, err
|
return receipt
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyTransaction attempts to apply a transaction to the given state database
|
// 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)
|
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
|
// Wait for the context to be done and cancel the evm. Even if the
|
||||||
// EVM has finished, cancelling may be done (repeatedly)
|
// EVM has finished, cancelling may be done (repeatedly)
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
||||||
|
|
@ -162,29 +162,54 @@ func (mc *multicall) execute(ctx context.Context, opts mcOpts) ([]mcBlockResult,
|
||||||
gasUsed uint64
|
gasUsed uint64
|
||||||
txes = make([]*types.Transaction, len(block.Calls))
|
txes = make([]*types.Transaction, len(block.Calls))
|
||||||
callResults = make([]mcCallResult, 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 {
|
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 {
|
if err := mc.sanitizeCall(&call, state, &gasUsed, blockContext); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tx := call.ToTransaction()
|
tx := call.ToTransaction()
|
||||||
txes[i] = tx
|
txes[i] = tx
|
||||||
// TODO: repair log block hashes post execution.
|
|
||||||
vmConfig := &vm.Config{
|
msg, err := call.ToMessage(gp.Gas(), header.BaseFee, !opts.Validation)
|
||||||
NoBaseFee: true,
|
if err != nil {
|
||||||
// Block hash will be repaired after execution.
|
return nil, err
|
||||||
Tracer: newTracer(opts.TraceTransfers, blockContext.BlockNumber.Uint64(), common.Hash{}, tx.Hash(), uint(i)),
|
|
||||||
}
|
}
|
||||||
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 {
|
if err != nil {
|
||||||
txErr := txValidationError(err)
|
txErr := txValidationError(err)
|
||||||
return nil, txErr
|
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 the result contains a revert reason, try to unpack it.
|
||||||
if len(result.Revert()) > 0 {
|
if len(result.Revert()) > 0 {
|
||||||
result.Err = newRevertError(result.Revert())
|
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)}
|
callRes := mcCallResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)}
|
||||||
if result.Failed() {
|
if result.Failed() {
|
||||||
callRes.Status = hexutil.Uint64(types.ReceiptStatusFailed)
|
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)
|
callRes.Status = hexutil.Uint64(types.ReceiptStatusSuccessful)
|
||||||
}
|
}
|
||||||
callResults[i] = callRes
|
callResults[i] = callRes
|
||||||
gasUsed += result.UsedGas
|
|
||||||
state.Finalise(true)
|
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
parentHash common.Hash
|
parentHash common.Hash
|
||||||
|
|
@ -212,6 +235,7 @@ func (mc *multicall) execute(ctx context.Context, opts mcOpts) ([]mcBlockResult,
|
||||||
header.Root = state.IntermediateRoot(true)
|
header.Root = state.IntermediateRoot(true)
|
||||||
header.GasUsed = gasUsed
|
header.GasUsed = gasUsed
|
||||||
header.TxHash = types.DeriveSha(types.Transactions(txes), trie.NewStackTrie(nil))
|
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)
|
results[bi] = mcBlockResultFromHeader(header, callResults)
|
||||||
repairLogs(results, header.Hash())
|
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())
|
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 {
|
func (t *tracer) Logs() []*types.Log {
|
||||||
return t.logs[0]
|
return t.logs[0]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue