@@ -1772,55 +1772,61 @@ func formatError(err error) string {
1772
1772
// TraceTransaction returns the structured logs created during the execution of EVM
1773
1773
// and returns them as a JSON object.
1774
1774
func (s * PrivateDebugAPI ) TraceTransaction (txHash common.Hash , logger vm.LogConfig ) (* ExecutionResult , error ) {
1775
- // Retrieve the tx from the chain
1776
- tx , _ , blockIndex , _ := core .GetTransaction (s .eth .ChainDb (), txHash )
1777
-
1775
+ // Retrieve the tx from the chain and the containing block
1776
+ tx , blockHash , _ , txIndex := core .GetTransaction (s .eth .ChainDb (), txHash )
1778
1777
if tx == nil {
1779
- return nil , fmt .Errorf ("Transaction not found" )
1778
+ return nil , fmt .Errorf ("transaction %x not found" , txHash )
1780
1779
}
1781
-
1782
- block := s .eth .BlockChain ().GetBlockByNumber (blockIndex - 1 )
1780
+ block := s .eth .BlockChain ().GetBlock (blockHash )
1783
1781
if block == nil {
1784
- return nil , fmt .Errorf ("Unable to retrieve prior block" )
1782
+ return nil , fmt .Errorf ("block %x not found" , blockHash )
1785
1783
}
1786
-
1787
- // Create the state database
1788
- stateDb , err := state .New (block .Root (), s .eth .ChainDb ())
1789
- if err != nil {
1790
- return nil , err
1784
+ // Create the state database to mutate and eventually trace
1785
+ parent := s .eth .BlockChain ().GetBlock (block .ParentHash ())
1786
+ if parent == nil {
1787
+ return nil , fmt .Errorf ("block parent %x not found" , block .ParentHash ())
1791
1788
}
1792
-
1793
- txFrom , err := tx .FromFrontier ()
1794
-
1789
+ stateDb , err := state .New (parent .Root (), s .eth .ChainDb ())
1795
1790
if err != nil {
1796
- return nil , fmt .Errorf ("Unable to create transaction sender" )
1797
- }
1798
- from := stateDb .GetOrNewStateObject (txFrom )
1799
- msg := callmsg {
1800
- from : from ,
1801
- to : tx .To (),
1802
- gas : tx .Gas (),
1803
- gasPrice : tx .GasPrice (),
1804
- value : tx .Value (),
1805
- data : tx .Data (),
1791
+ return nil , err
1806
1792
}
1807
-
1808
- vmenv := core .NewEnv (stateDb , s .config , s .eth .BlockChain (), msg , block .Header (), vm.Config {
1809
- Debug : true ,
1810
- Logger : logger ,
1811
- })
1812
- gp := new (core.GasPool ).AddGas (block .GasLimit ())
1813
-
1814
- ret , gas , err := core .ApplyMessage (vmenv , msg , gp )
1815
- if err != nil {
1816
- return nil , fmt .Errorf ("Error executing transaction %v" , err )
1793
+ // Mutate the state and trace the selected transaction
1794
+ for idx , tx := range block .Transactions () {
1795
+ // Assemble the transaction call message
1796
+ from , err := tx .FromFrontier ()
1797
+ if err != nil {
1798
+ return nil , fmt .Errorf ("sender retrieval failed: %v" , err )
1799
+ }
1800
+ msg := callmsg {
1801
+ from : stateDb .GetOrNewStateObject (from ),
1802
+ to : tx .To (),
1803
+ gas : tx .Gas (),
1804
+ gasPrice : tx .GasPrice (),
1805
+ value : tx .Value (),
1806
+ data : tx .Data (),
1807
+ }
1808
+ // Mutate the state if we haven't reached the tracing transaction yet
1809
+ if uint64 (idx ) < txIndex {
1810
+ vmenv := core .NewEnv (stateDb , s .config , s .eth .BlockChain (), msg , parent .Header (), vm.Config {})
1811
+ _ , _ , err := core .ApplyMessage (vmenv , msg , new (core.GasPool ).AddGas (tx .Gas ()))
1812
+ if err != nil {
1813
+ return nil , fmt .Errorf ("mutation failed: %v" , err )
1814
+ }
1815
+ continue
1816
+ }
1817
+ // Otherwise trace the transaction and return
1818
+ vmenv := core .NewEnv (stateDb , s .config , s .eth .BlockChain (), msg , parent .Header (), vm.Config {Debug : true , Logger : logger })
1819
+ ret , gas , err := core .ApplyMessage (vmenv , msg , new (core.GasPool ).AddGas (tx .Gas ()))
1820
+ if err != nil {
1821
+ return nil , fmt .Errorf ("tracing failed: %v" , err )
1822
+ }
1823
+ return & ExecutionResult {
1824
+ Gas : gas ,
1825
+ ReturnValue : fmt .Sprintf ("%x" , ret ),
1826
+ StructLogs : formatLogs (vmenv .StructLogs ()),
1827
+ }, nil
1817
1828
}
1818
-
1819
- return & ExecutionResult {
1820
- Gas : gas ,
1821
- ReturnValue : fmt .Sprintf ("%x" , ret ),
1822
- StructLogs : formatLogs (vmenv .StructLogs ()),
1823
- }, nil
1829
+ return nil , errors .New ("database inconsistency" )
1824
1830
}
1825
1831
1826
1832
func (s * PublicBlockChainAPI ) TraceCall (args CallArgs , blockNr rpc.BlockNumber ) (* ExecutionResult , error ) {
0 commit comments