computeTxEnv returns the execution environment of a certain transaction.
(blockHash common.Hash, txIndex int, reexec uint64)
| 649 | |
| 650 | // computeTxEnv returns the execution environment of a certain transaction. |
| 651 | func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) { |
| 652 | // Create the parent state database |
| 653 | block := api.cpc.blockchain.GetBlockByHash(blockHash) |
| 654 | if block == nil { |
| 655 | return nil, vm.Context{}, nil, fmt.Errorf("block %x not found", blockHash) |
| 656 | } |
| 657 | parent := api.cpc.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) |
| 658 | if parent == nil { |
| 659 | return nil, vm.Context{}, nil, fmt.Errorf("parent %x not found", block.ParentHash()) |
| 660 | } |
| 661 | pubStateDB, err := api.computeStateDB(parent, reexec) |
| 662 | if err != nil { |
| 663 | return nil, vm.Context{}, nil, err |
| 664 | } |
| 665 | |
| 666 | privStateDB, err := api.computeStatePrivDB(parent) |
| 667 | if err != nil { |
| 668 | // TODO: log the fatal error |
| 669 | panic(err) |
| 670 | } |
| 671 | |
| 672 | // Recompute transactions up to the target index. |
| 673 | signer := types.MakeSigner(api.config) |
| 674 | |
| 675 | for idx, tx := range block.Transactions() { |
| 676 | // Assemble the transaction call message and return if the requested offset |
| 677 | msg, _ := tx.AsMessage(signer) |
| 678 | context := core.NewEVMContext(msg, block.Header(), api.cpc.blockchain, nil) |
| 679 | |
| 680 | var statedb *state.StateDB |
| 681 | if tx.IsPrivate() { |
| 682 | statedb = privStateDB // replace with private database. |
| 683 | } else { |
| 684 | statedb = pubStateDB |
| 685 | } |
| 686 | |
| 687 | if idx == txIndex { |
| 688 | return msg, context, statedb, nil |
| 689 | } |
| 690 | |
| 691 | // Not yet the searched for transaction, execute on top of the current state |
| 692 | vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{}) |
| 693 | if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { |
| 694 | return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err) |
| 695 | } |
| 696 | // Ensure any modifications are committed to the state |
| 697 | statedb.Finalise(true) |
| 698 | } |
| 699 | return nil, vm.Context{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash) |
| 700 | } |
no test coverage detected