github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/api_tracer.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:38</date>
    10  //</624342633036124160>
    11  
    12  
    13  package eth
    14  
    15  import (
    16  	"bytes"
    17  	"context"
    18  	"errors"
    19  	"fmt"
    20  	"io/ioutil"
    21  	"runtime"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/common/hexutil"
    27  	"github.com/ethereum/go-ethereum/core"
    28  	"github.com/ethereum/go-ethereum/core/rawdb"
    29  	"github.com/ethereum/go-ethereum/core/state"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/core/vm"
    32  	"github.com/ethereum/go-ethereum/eth/tracers"
    33  	"github.com/ethereum/go-ethereum/internal/ethapi"
    34  	"github.com/ethereum/go-ethereum/log"
    35  	"github.com/ethereum/go-ethereum/rlp"
    36  	"github.com/ethereum/go-ethereum/rpc"
    37  	"github.com/ethereum/go-ethereum/trie"
    38  )
    39  
    40  const (
    41  //DefaultTraceTimeout是单个事务可以执行的时间量
    42  //默认情况下,在强制中止之前。
    43  	defaultTraceTimeout = 5 * time.Second
    44  
    45  //defaulttracereexec是跟踪程序愿意返回的块数。
    46  //重新执行以产生运行特定
    47  //痕迹。
    48  	defaultTraceReexec = uint64(128)
    49  )
    50  
    51  //traceconfig保存跟踪函数的额外参数。
    52  type TraceConfig struct {
    53  	*vm.LogConfig
    54  	Tracer  *string
    55  	Timeout *string
    56  	Reexec  *uint64
    57  }
    58  
    59  //txtracesult是单个事务跟踪的结果。
    60  type txTraceResult struct {
    61  Result interface{} `json:"result,omitempty"` //示踪剂产生的示踪结果
    62  Error  string      `json:"error,omitempty"`  //示踪剂产生的示踪失效
    63  }
    64  
    65  //当整个链为
    66  //被追踪。
    67  type blockTraceTask struct {
    68  statedb *state.StateDB   //准备跟踪的中间状态
    69  block   *types.Block     //用于跟踪事务的块
    70  rootref common.Hash      //为此任务保留的trie根引用
    71  results []*txTraceResult //跟踪结果按任务进行
    72  }
    73  
    74  //blocktraceresult represets当一个完整的
    75  //正在跟踪链。
    76  type blockTraceResult struct {
    77  Block  hexutil.Uint64   `json:"block"`  //与此跟踪对应的块号
    78  Hash   common.Hash      `json:"hash"`   //与此跟踪对应的块哈希
    79  Traces []*txTraceResult `json:"traces"` //跟踪任务生成的结果
    80  }
    81  
    82  //txtracetask表示当整个块
    83  //正在跟踪。
    84  type txTraceTask struct {
    85  statedb *state.StateDB //准备跟踪的中间状态
    86  index   int            //块中的事务偏移量
    87  }
    88  
    89  //tracechain返回在执行evm期间创建的结构化日志
    90  //在两个块之间(不包括start),并将它们作为JSON对象返回。
    91  func (api *PrivateDebugAPI) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) {
    92  //获取要跟踪的块间隔
    93  	var from, to *types.Block
    94  
    95  	switch start {
    96  	case rpc.PendingBlockNumber:
    97  		from = api.eth.miner.PendingBlock()
    98  	case rpc.LatestBlockNumber:
    99  		from = api.eth.blockchain.CurrentBlock()
   100  	default:
   101  		from = api.eth.blockchain.GetBlockByNumber(uint64(start))
   102  	}
   103  	switch end {
   104  	case rpc.PendingBlockNumber:
   105  		to = api.eth.miner.PendingBlock()
   106  	case rpc.LatestBlockNumber:
   107  		to = api.eth.blockchain.CurrentBlock()
   108  	default:
   109  		to = api.eth.blockchain.GetBlockByNumber(uint64(end))
   110  	}
   111  //如果我们找到了所有的区块,就追踪这条链。
   112  	if from == nil {
   113  		return nil, fmt.Errorf("starting block #%d not found", start)
   114  	}
   115  	if to == nil {
   116  		return nil, fmt.Errorf("end block #%d not found", end)
   117  	}
   118  	if from.Number().Cmp(to.Number()) >= 0 {
   119  		return nil, fmt.Errorf("end block (#%d) needs to come after start block (#%d)", end, start)
   120  	}
   121  	return api.traceChain(ctx, from, to, config)
   122  }
   123  
   124  //tracechain根据提供的配置配置配置新的跟踪程序,以及
   125  //执行中包含的所有事务。返回值将是一个项目
   126  //每个事务,取决于请求的跟踪程序。
   127  func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Block, config *TraceConfig) (*rpc.Subscription, error) {
   128  //跟踪链是一个**长**的操作,只处理订阅
   129  	notifier, supported := rpc.NotifierFromContext(ctx)
   130  	if !supported {
   131  		return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
   132  	}
   133  	sub := notifier.CreateSubscription()
   134  
   135  //在进行任何工作之前,确保我们有一个有效的启动状态
   136  	origin := start.NumberU64()
   137  	database := state.NewDatabase(api.eth.ChainDb())
   138  
   139  	if number := start.NumberU64(); number > 0 {
   140  		start = api.eth.blockchain.GetBlock(start.ParentHash(), start.NumberU64()-1)
   141  		if start == nil {
   142  			return nil, fmt.Errorf("parent block #%d not found", number-1)
   143  		}
   144  	}
   145  	statedb, err := state.New(start.Root(), database)
   146  	if err != nil {
   147  //如果缺少起始状态,则允许重新执行一些块。
   148  		reexec := defaultTraceReexec
   149  		if config != nil && config.Reexec != nil {
   150  			reexec = *config.Reexec
   151  		}
   152  //查找具有可用状态的最新块
   153  		for i := uint64(0); i < reexec; i++ {
   154  			start = api.eth.blockchain.GetBlock(start.ParentHash(), start.NumberU64()-1)
   155  			if start == nil {
   156  				break
   157  			}
   158  			if statedb, err = state.New(start.Root(), database); err == nil {
   159  				break
   160  			}
   161  		}
   162  //如果我们还没有州政府的支持,那就纾困吧。
   163  		if err != nil {
   164  			switch err.(type) {
   165  			case *trie.MissingNodeError:
   166  				return nil, errors.New("required historical state unavailable")
   167  			default:
   168  				return nil, err
   169  			}
   170  		}
   171  	}
   172  //为每个块同时执行链中包含的所有事务
   173  	blocks := int(end.NumberU64() - origin)
   174  
   175  	threads := runtime.NumCPU()
   176  	if threads > blocks {
   177  		threads = blocks
   178  	}
   179  	var (
   180  		pend    = new(sync.WaitGroup)
   181  		tasks   = make(chan *blockTraceTask, threads)
   182  		results = make(chan *blockTraceTask, threads)
   183  	)
   184  	for th := 0; th < threads; th++ {
   185  		pend.Add(1)
   186  		go func() {
   187  			defer pend.Done()
   188  
   189  //获取并执行下一个块跟踪任务
   190  			for task := range tasks {
   191  				signer := types.MakeSigner(api.config, task.block.Number())
   192  
   193  //跟踪包含在
   194  				for i, tx := range task.block.Transactions() {
   195  					msg, _ := tx.AsMessage(signer)
   196  					vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain, nil)
   197  
   198  					res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
   199  					if err != nil {
   200  						task.results[i] = &txTraceResult{Error: err.Error()}
   201  						log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
   202  						break
   203  					}
   204  					task.statedb.Finalise(true)
   205  					task.results[i] = &txTraceResult{Result: res}
   206  				}
   207  //将结果返回给用户或在拆卸时中止
   208  				select {
   209  				case results <- task:
   210  				case <-notifier.Closed():
   211  					return
   212  				}
   213  			}
   214  		}()
   215  	}
   216  //启动一个GODUTIN将所有的块输入示踪剂
   217  	begin := time.Now()
   218  
   219  	go func() {
   220  		var (
   221  			logged time.Time
   222  			number uint64
   223  			traced uint64
   224  			failed error
   225  			proot  common.Hash
   226  		)
   227  //确保所有出口通道上的物品都被正确清理干净。
   228  		defer func() {
   229  			close(tasks)
   230  			pend.Wait()
   231  
   232  			switch {
   233  			case failed != nil:
   234  				log.Warn("Chain tracing failed", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin), "err", failed)
   235  			case number < end.NumberU64():
   236  				log.Warn("Chain tracing aborted", "start", start.NumberU64(), "end", end.NumberU64(), "abort", number, "transactions", traced, "elapsed", time.Since(begin))
   237  			default:
   238  				log.Info("Chain tracing finished", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin))
   239  			}
   240  			close(results)
   241  		}()
   242  //同时将所有块都输入跟踪程序以及快速处理
   243  		for number = start.NumberU64() + 1; number <= end.NumberU64(); number++ {
   244  //如果请求中断,则停止跟踪
   245  			select {
   246  			case <-notifier.Closed():
   247  				return
   248  			default:
   249  			}
   250  //如果经过足够长的时间,则打印进度日志
   251  			if time.Since(logged) > 8*time.Second {
   252  				if number > origin {
   253  					nodes, imgs := database.TrieDB().Size()
   254  					log.Info("Tracing chain segment", "start", origin, "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin), "memory", nodes+imgs)
   255  				} else {
   256  					log.Info("Preparing state for chain trace", "block", number, "start", origin, "elapsed", time.Since(begin))
   257  				}
   258  				logged = time.Now()
   259  			}
   260  //检索下一个要跟踪的块
   261  			block := api.eth.blockchain.GetBlockByNumber(number)
   262  			if block == nil {
   263  				failed = fmt.Errorf("block #%d not found", number)
   264  				break
   265  			}
   266  //将块发送到并发跟踪程序(如果不是在快进阶段)
   267  			if number > origin {
   268  				txs := block.Transactions()
   269  
   270  				select {
   271  				case tasks <- &blockTraceTask{statedb: statedb.Copy(), block: block, rootref: proot, results: make([]*txTraceResult, len(txs))}:
   272  				case <-notifier.Closed():
   273  					return
   274  				}
   275  				traced += uint64(len(txs))
   276  			}
   277  //快速生成下一个状态快照,无需跟踪
   278  			_, _, _, err := api.eth.blockchain.Processor().Process(block, statedb, vm.Config{})
   279  			if err != nil {
   280  				failed = err
   281  				break
   282  			}
   283  //最终确定状态,以便将任何修改写入trie
   284  			root, err := statedb.Commit(true)
   285  			if err != nil {
   286  				failed = err
   287  				break
   288  			}
   289  			if err := statedb.Reset(root); err != nil {
   290  				failed = err
   291  				break
   292  			}
   293  //两次,一次给我们,一次给出纳员
   294  			database.TrieDB().Reference(root, common.Hash{})
   295  			if number >= origin {
   296  				database.TrieDB().Reference(root, common.Hash{})
   297  			}
   298  //取消引用我们自己已经完成的所有尝试
   299  			if proot != (common.Hash{}) {
   300  				database.TrieDB().Dereference(proot)
   301  			}
   302  			proot = root
   303  
   304  //托多(卡拉贝拉):我们需要预成像吗?他们不会积累太多吗?
   305  		}
   306  	}()
   307  
   308  //继续读取跟踪结果并将其传输给用户
   309  	go func() {
   310  		var (
   311  			done = make(map[uint64]*blockTraceResult)
   312  			next = origin + 1
   313  		)
   314  		for res := range results {
   315  //排队等待下一个接收结果
   316  			result := &blockTraceResult{
   317  				Block:  hexutil.Uint64(res.block.NumberU64()),
   318  				Hash:   res.block.Hash(),
   319  				Traces: res.results,
   320  			}
   321  			done[uint64(result.Block)] = result
   322  
   323  //取消引用此任务在内存中保留的任何paret尝试
   324  			database.TrieDB().Dereference(res.rootref)
   325  
   326  //流完成对用户的跟踪,在第一个错误上中止
   327  			for result, ok := done[next]; ok; result, ok = done[next] {
   328  				if len(result.Traces) > 0 || next == end.NumberU64() {
   329  					notifier.Notify(sub.ID, result)
   330  				}
   331  				delete(done, next)
   332  				next++
   333  			}
   334  		}
   335  	}()
   336  	return sub, nil
   337  }
   338  
   339  //traceBlockByNumber返回在执行期间创建的结构化日志
   340  //EVM并将其作为JSON对象返回。
   341  func (api *PrivateDebugAPI) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
   342  //获取要跟踪的块
   343  	var block *types.Block
   344  
   345  	switch number {
   346  	case rpc.PendingBlockNumber:
   347  		block = api.eth.miner.PendingBlock()
   348  	case rpc.LatestBlockNumber:
   349  		block = api.eth.blockchain.CurrentBlock()
   350  	default:
   351  		block = api.eth.blockchain.GetBlockByNumber(uint64(number))
   352  	}
   353  //如果找到块,跟踪它
   354  	if block == nil {
   355  		return nil, fmt.Errorf("block #%d not found", number)
   356  	}
   357  	return api.traceBlock(ctx, block, config)
   358  }
   359  
   360  //traceBlockByHash返回在执行期间创建的结构化日志
   361  //EVM并将其作为JSON对象返回。
   362  func (api *PrivateDebugAPI) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
   363  	block := api.eth.blockchain.GetBlockByHash(hash)
   364  	if block == nil {
   365  		return nil, fmt.Errorf("block #%x not found", hash)
   366  	}
   367  	return api.traceBlock(ctx, block, config)
   368  }
   369  
   370  //traceblock返回在执行evm期间创建的结构化日志
   371  //并将它们作为JSON对象返回。
   372  func (api *PrivateDebugAPI) TraceBlock(ctx context.Context, blob []byte, config *TraceConfig) ([]*txTraceResult, error) {
   373  	block := new(types.Block)
   374  	if err := rlp.Decode(bytes.NewReader(blob), block); err != nil {
   375  		return nil, fmt.Errorf("could not decode block: %v", err)
   376  	}
   377  	return api.traceBlock(ctx, block, config)
   378  }
   379  
   380  //traceblockfromfile返回在执行期间创建的结构化日志
   381  //EVM并将其作为JSON对象返回。
   382  func (api *PrivateDebugAPI) TraceBlockFromFile(ctx context.Context, file string, config *TraceConfig) ([]*txTraceResult, error) {
   383  	blob, err := ioutil.ReadFile(file)
   384  	if err != nil {
   385  		return nil, fmt.Errorf("could not read file: %v", err)
   386  	}
   387  	return api.TraceBlock(ctx, blob, config)
   388  }
   389  
   390  //跟踪块根据提供的配置配置配置新的跟踪程序,以及
   391  //执行中包含的所有事务。返回值将是一个项目
   392  //每个事务,取决于请求的跟踪程序。
   393  //跟踪块根据提供的配置配置配置新的跟踪程序,以及
   394  //执行中包含的所有事务。返回值将是一个项目
   395  //每个事务,取决于请求的跟踪程序。
   396  func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
   397  //创建父状态数据库
   398  	bi := api.eth.blockchain.GetHeaderByNumber(0).BlockInterval
   399  	if err := api.eth.engine.VerifyHeader(api.eth.blockchain, block.Header(), true, bi); err != nil {
   400  		return nil, err
   401  	}
   402  	parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
   403  	if parent == nil {
   404  		return nil, fmt.Errorf("parent %x not found", block.ParentHash())
   405  	}
   406  	reexec := defaultTraceReexec
   407  	if config != nil && config.Reexec != nil {
   408  		reexec = *config.Reexec
   409  	}
   410  	statedb, err := api.computeStateDB(parent, reexec)
   411  	if err != nil {
   412  		return nil, err
   413  	}
   414  //同时执行块内包含的所有事务
   415  	var (
   416  		signer = types.MakeSigner(api.config, block.Number())
   417  
   418  		txs     = block.Transactions()
   419  		results = make([]*txTraceResult, len(txs))
   420  
   421  		pend = new(sync.WaitGroup)
   422  		jobs = make(chan *txTraceTask, len(txs))
   423  	)
   424  	threads := runtime.NumCPU()
   425  	if threads > len(txs) {
   426  		threads = len(txs)
   427  	}
   428  	for th := 0; th < threads; th++ {
   429  		pend.Add(1)
   430  		go func() {
   431  			defer pend.Done()
   432  
   433  //获取并执行下一个事务跟踪任务
   434  			for task := range jobs {
   435  				msg, _ := txs[task.index].AsMessage(signer)
   436  				vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
   437  
   438  				res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
   439  				if err != nil {
   440  					results[task.index] = &txTraceResult{Error: err.Error()}
   441  					continue
   442  				}
   443  				results[task.index] = &txTraceResult{Result: res}
   444  			}
   445  		}()
   446  	}
   447  //将事务输入跟踪程序并返回
   448  	var failed error
   449  	for i, tx := range txs {
   450  //发送跟踪任务以供执行
   451  		jobs <- &txTraceTask{statedb: statedb.Copy(), index: i}
   452  
   453  //快速生成下一个状态快照,无需跟踪
   454  		msg, _ := tx.AsMessage(signer)
   455  		vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
   456  
   457  		vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{})
   458  		if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
   459  			failed = err
   460  			break
   461  		}
   462  //最终确定状态,以便将任何修改写入trie
   463  		statedb.Finalise(true)
   464  	}
   465  	close(jobs)
   466  	pend.Wait()
   467  
   468  //如果执行失败,则中止
   469  	if failed != nil {
   470  		return nil, failed
   471  	}
   472  	return results, nil
   473  }
   474  //ComputeTestedB检索与某个块关联的状态数据库。
   475  //如果给定块没有本地可用的状态,则有许多块
   476  //试图重新执行以生成所需状态。
   477  func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (*state.StateDB, error) {
   478  //如果我们的状态完全可用,请使用
   479  	statedb, err := api.eth.blockchain.StateAt(block.Root())
   480  	if err == nil {
   481  		return statedb, nil
   482  	}
   483  //否则,尝试重新执行块,直到找到状态或达到限制
   484  	origin := block.NumberU64()
   485  	database := state.NewDatabase(api.eth.ChainDb())
   486  
   487  	for i := uint64(0); i < reexec; i++ {
   488  		block = api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
   489  		if block == nil {
   490  			break
   491  		}
   492  		if statedb, err = state.New(block.Root(), database); err == nil {
   493  			break
   494  		}
   495  	}
   496  	if err != nil {
   497  		switch err.(type) {
   498  		case *trie.MissingNodeError:
   499  			return nil, errors.New("required historical state unavailable")
   500  		default:
   501  			return nil, err
   502  		}
   503  	}
   504  //状态在历史点可用,重新生成
   505  	var (
   506  		start  = time.Now()
   507  		logged time.Time
   508  		proot  common.Hash
   509  	)
   510  	for block.NumberU64() < origin {
   511  //如果经过足够长的时间,则打印进度日志
   512  		if time.Since(logged) > 8*time.Second {
   513  			log.Info("Regenerating historical state", "block", block.NumberU64()+1, "target", origin, "elapsed", time.Since(start))
   514  			logged = time.Now()
   515  		}
   516  //检索下一个块以重新生成并处理它
   517  		if block = api.eth.blockchain.GetBlockByNumber(block.NumberU64() + 1); block == nil {
   518  			return nil, fmt.Errorf("block #%d not found", block.NumberU64()+1)
   519  		}
   520  		_, _, _, err := api.eth.blockchain.Processor().Process(block, statedb, vm.Config{})
   521  		if err != nil {
   522  			return nil, err
   523  		}
   524  //最终确定状态,以便将任何修改写入trie
   525  		root, err := statedb.Commit(true)
   526  		if err != nil {
   527  			return nil, err
   528  		}
   529  		if err := statedb.Reset(root); err != nil {
   530  			return nil, err
   531  		}
   532  		database.TrieDB().Reference(root, common.Hash{})
   533  		if proot != (common.Hash{}) {
   534  			database.TrieDB().Dereference(proot)
   535  		}
   536  		proot = root
   537  	}
   538  	nodes, imgs := database.TrieDB().Size()
   539  	log.Info("Historical state regenerated", "block", block.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs)
   540  	return statedb, nil
   541  }
   542  
   543  //traceTransaction返回执行evm期间创建的结构化日志
   544  //并将它们作为JSON对象返回。
   545  func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
   546  //检索事务并组装其EVM上下文
   547  	tx, blockHash, _, index := rawdb.ReadTransaction(api.eth.ChainDb(), hash)
   548  	if tx == nil {
   549  		return nil, fmt.Errorf("transaction %x not found", hash)
   550  	}
   551  	reexec := defaultTraceReexec
   552  	if config != nil && config.Reexec != nil {
   553  		reexec = *config.Reexec
   554  	}
   555  	msg, vmctx, statedb, err := api.computeTxEnv(blockHash, int(index), reexec)
   556  	if err != nil {
   557  		return nil, err
   558  	}
   559  //跟踪事务和返回
   560  	return api.traceTx(ctx, msg, vmctx, statedb, config)
   561  }
   562  
   563  //tracetx根据提供的配置配置配置新的跟踪程序,以及
   564  //在提供的环境中执行给定的消息。返回值将
   565  //取决于示踪剂。
   566  func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
   567  //组装结构化记录器或JavaScript跟踪程序
   568  	var (
   569  		tracer vm.Tracer
   570  		err    error
   571  	)
   572  	switch {
   573  	case config != nil && config.Tracer != nil:
   574  //定义单个事务跟踪的有意义的超时
   575  		timeout := defaultTraceTimeout
   576  		if config.Timeout != nil {
   577  			if timeout, err = time.ParseDuration(*config.Timeout); err != nil {
   578  				return nil, err
   579  			}
   580  		}
   581  //构造要用其执行的javascript跟踪程序
   582  		if tracer, err = tracers.New(*config.Tracer); err != nil {
   583  			return nil, err
   584  		}
   585  //处理超时和RPC取消
   586  		deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
   587  		go func() {
   588  			<-deadlineCtx.Done()
   589  			tracer.(*tracers.Tracer).Stop(errors.New("execution timeout"))
   590  		}()
   591  		defer cancel()
   592  
   593  	case config == nil:
   594  		tracer = vm.NewStructLogger(nil)
   595  
   596  	default:
   597  		tracer = vm.NewStructLogger(config.LogConfig)
   598  	}
   599  //在启用跟踪的情况下运行事务。
   600  	vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{Debug: true, Tracer: tracer})
   601  
   602  	ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
   603  	if err != nil {
   604  		return nil, fmt.Errorf("tracing failed: %v", err)
   605  	}
   606  //根据跟踪类型、格式和返回输出
   607  	switch tracer := tracer.(type) {
   608  	case *vm.StructLogger:
   609  		return &ethapi.ExecutionResult{
   610  			Gas:         gas,
   611  			Failed:      failed,
   612  			ReturnValue: fmt.Sprintf("%x", ret),
   613  			StructLogs:  ethapi.FormatLogs(tracer.StructLogs()),
   614  		}, nil
   615  
   616  	case *tracers.Tracer:
   617  		return tracer.GetResult()
   618  
   619  	default:
   620  		panic(fmt.Sprintf("bad tracer type %T", tracer))
   621  	}
   622  }
   623  
   624  //computetxenv返回特定事务的执行环境。
   625  func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) {
   626  //创建父状态数据库
   627  	block := api.eth.blockchain.GetBlockByHash(blockHash)
   628  	if block == nil {
   629  		return nil, vm.Context{}, nil, fmt.Errorf("block %x not found", blockHash)
   630  	}
   631  	parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
   632  	if parent == nil {
   633  		return nil, vm.Context{}, nil, fmt.Errorf("parent %x not found", block.ParentHash())
   634  	}
   635  	statedb, err := api.computeStateDB(parent, reexec)
   636  	if err != nil {
   637  		return nil, vm.Context{}, nil, err
   638  	}
   639  //重新计算达到目标索引的事务。
   640  	signer := types.MakeSigner(api.config, block.Number())
   641  
   642  	for idx, tx := range block.Transactions() {
   643  //组装事务调用消息并返回请求的偏移量
   644  		msg, _ := tx.AsMessage(signer)
   645  		context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
   646  		if idx == txIndex {
   647  			return msg, context, statedb, nil
   648  		}
   649  //尚未搜索到事务,请在当前状态的基础上执行
   650  		vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{})
   651  		if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
   652  			return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
   653  		}
   654  //确保对国家进行任何修改
   655  		statedb.Finalise(true)
   656  	}
   657  	return nil, vm.Context{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash)
   658  }
   659