github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/api_tracer.go (about)

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