github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/api.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  //版权所有2015 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  	"compress/gzip"
    29  	"context"
    30  	"errors"
    31  	"fmt"
    32  	"io"
    33  	"math/big"
    34  	"os"
    35  	"strings"
    36  //“时间”
    37  
    38  	"github.com/ethereum/go-ethereum/common"
    39  	"github.com/ethereum/go-ethereum/common/hexutil"
    40  	"github.com/ethereum/go-ethereum/core"
    41  	"github.com/ethereum/go-ethereum/core/rawdb"
    42  	"github.com/ethereum/go-ethereum/core/state"
    43  	"github.com/ethereum/go-ethereum/core/types"
    44  	"github.com/ethereum/go-ethereum/internal/ethapi"
    45  	"github.com/ethereum/go-ethereum/log"
    46  	"github.com/ethereum/go-ethereum/params"
    47  	"github.com/ethereum/go-ethereum/rlp"
    48  	"github.com/ethereum/go-ethereum/rpc"
    49  	"github.com/ethereum/go-ethereum/trie"
    50  )
    51  
    52  //PublicEthereumAPI提供了一个API,用于访问与Ethereum完整节点相关的
    53  //信息。
    54  type PublicEthereumAPI struct {
    55  	e *Ethereum
    56  }
    57  
    58  //NewPublicEthereumAPI为完整节点创建新的Ethereum协议API。
    59  func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI {
    60  	return &PublicEthereumAPI{e}
    61  }
    62  
    63  //EtherBase是采矿奖励将发送到的地址
    64  /*
    65  func(api*publicethereumpi)etherbase()(common.address,错误)
    66   返回api.e.etherbase()。
    67  */
    68  
    69  
    70  //validator是挖掘签名者的地址
    71  func (api *PublicEthereumAPI) Validator() (common.Address, error) {
    72  	return api.e.Validator()
    73  }
    74  
    75  //CoinBase是采矿奖励将发送到的地址
    76  func (api *PublicEthereumAPI) Coinbase() (common.Address, error) {
    77  	return api.e.Coinbase()
    78  }
    79  //CoinBase是采矿奖励将发送到的地址(EtherBase的别名)
    80  /*
    81  func(api*publicethereumpi)coinbase()(common.address,错误)
    82   返回api.etherbase()。
    83  */
    84  
    85  
    86  //hashRate返回pow hashRate
    87  func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 {
    88  	return hexutil.Uint64(api.e.Miner().HashRate())
    89  }
    90  
    91  //publicMinerapi提供了一个API来控制矿工。
    92  //它只提供对数据进行操作的方法,这些数据在公开访问时不会带来安全风险。
    93  type PublicMinerAPI struct {
    94  	e *Ethereum
    95  }
    96  
    97  //NewPublicMinerapi创建新的PublicMinerapi实例。
    98  func NewPublicMinerAPI(e *Ethereum) *PublicMinerAPI {
    99  	return &PublicMinerAPI{e}
   100  }
   101  
   102  //挖掘返回当前是否正在挖掘此节点的指示。
   103  func (api *PublicMinerAPI) Mining() bool {
   104  	return api.e.IsMining()
   105  }
   106  
   107  //privateminerapi提供私有的RPC方法来控制矿工。
   108  //这些方法可能会被外部用户滥用,并且必须被认为不受信任的用户使用是不安全的。
   109  type PrivateMinerAPI struct {
   110  	e *Ethereum
   111  }
   112  
   113  //newprivateminerapi创建一个新的RPC服务,该服务控制此节点的矿工。
   114  func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI {
   115  	return &PrivateMinerAPI{e: e}
   116  }
   117  
   118  //用给定数量的线程启动矿工。如果线程为零,则为数字
   119  //启动的工作线程数等于
   120  //这个过程。如果挖掘已在运行,则此方法将调整
   121  //允许使用和更新事务所需的最低价格的线程
   122  //池。
   123  func (api *PrivateMinerAPI) Start(threads *int) error {
   124  //如果密封发动机支持,设置螺纹数
   125  	if threads == nil {
   126  		threads = new(int)
   127  	} else if *threads == 0 {
   128  *threads = -1 //从内部禁用矿工
   129  	}
   130  	type threaded interface {
   131  		SetThreads(threads int)
   132  	}
   133  	if th, ok := api.e.engine.(threaded); ok {
   134  		log.Info("Updated mining threads", "threads", *threads)
   135  		th.SetThreads(*threads)
   136  	}
   137  //启动矿工并返回
   138  	if !api.e.IsMining() {
   139  //将初始价格点传播到交易池
   140  		api.e.lock.RLock()
   141  		price := api.e.gasPrice
   142  		api.e.lock.RUnlock()
   143  		api.e.txPool.SetGasPrice(price)
   144  		return api.e.StartMining(true)
   145  	}
   146  	return nil
   147  }
   148  
   149  //阻止矿工
   150  func (api *PrivateMinerAPI) Stop() bool {
   151  	type threaded interface {
   152  		SetThreads(threads int)
   153  	}
   154  	if th, ok := api.e.engine.(threaded); ok {
   155  		th.SetThreads(-1)
   156  	}
   157  	api.e.StopMining()
   158  	return true
   159  }
   160  
   161  //setextra设置此矿工挖掘块时包含的额外数据字符串。
   162  func (api *PrivateMinerAPI) SetExtra(extra string) (bool, error) {
   163  	if err := api.e.Miner().SetExtra([]byte(extra)); err != nil {
   164  		return false, err
   165  	}
   166  	return true, nil
   167  }
   168  
   169  //setgasprice为矿工设定了最低可接受的天然气价格。
   170  func (api *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
   171  	api.e.lock.Lock()
   172  	api.e.gasPrice = (*big.Int)(&gasPrice)
   173  	api.e.lock.Unlock()
   174  
   175  	api.e.txPool.SetGasPrice((*big.Int)(&gasPrice))
   176  	return true
   177  }
   178  
   179  //setetherbase设置矿工的etherbase
   180  /*
   181  func(api*privateminerapi)setetherbase(etherbase common.address)bool_
   182   api.e.setetherbase(以太网)
   183   返回真
   184  */
   185  
   186  
   187  //setrecommittinterval更新矿工密封工作重新投入的时间间隔。
   188  func (api *PrivateMinerAPI) SetRecommitInterval(interval int) {
   189  //api.e.miner().setRecommitInterval(time.duration(interval)*time.millisecond)
   190  	return
   191  }
   192  
   193  //GetHashrate返回矿工的当前哈希率。
   194  func (api *PrivateMinerAPI) GetHashrate() uint64 {
   195  	return api.e.miner.HashRate()
   196  }
   197  
   198  //privateAdminAPI是以太坊完整节点相关API的集合。
   199  //在私有管理终结点上公开。
   200  type PrivateAdminAPI struct {
   201  	eth *Ethereum
   202  }
   203  
   204  //newprivateadminapi为完整节点private创建新的api定义
   205  //EAUTHUM服务的管理方法。
   206  func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI {
   207  	return &PrivateAdminAPI{eth: eth}
   208  }
   209  
   210  //exportchain将当前区块链导出到本地文件中。
   211  func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
   212  //确保我们可以创建要导出到的文件
   213  	out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
   214  	if err != nil {
   215  		return false, err
   216  	}
   217  	defer out.Close()
   218  
   219  	var writer io.Writer = out
   220  	if strings.HasSuffix(file, ".gz") {
   221  		writer = gzip.NewWriter(writer)
   222  		defer writer.(*gzip.Writer).Close()
   223  	}
   224  
   225  //导出区块链
   226  	if err := api.eth.BlockChain().Export(writer); err != nil {
   227  		return false, err
   228  	}
   229  	return true, nil
   230  }
   231  
   232  func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
   233  	for _, b := range bs {
   234  		if !chain.HasBlock(b.Hash(), b.NumberU64()) {
   235  			return false
   236  		}
   237  	}
   238  
   239  	return true
   240  }
   241  
   242  //importchain从本地文件导入区块链。
   243  func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
   244  //确保可以访问要导入的文件
   245  	in, err := os.Open(file)
   246  	if err != nil {
   247  		return false, err
   248  	}
   249  	defer in.Close()
   250  
   251  	var reader io.Reader = in
   252  	if strings.HasSuffix(file, ".gz") {
   253  		if reader, err = gzip.NewReader(reader); err != nil {
   254  			return false, err
   255  		}
   256  	}
   257  
   258  //在预配置的批中实际运行导入
   259  	stream := rlp.NewStream(reader, 0)
   260  
   261  	blocks, index := make([]*types.Block, 0, 2500), 0
   262  	for batch := 0; ; batch++ {
   263  //从输入文件加载一批块
   264  		for len(blocks) < cap(blocks) {
   265  			block := new(types.Block)
   266  			if err := stream.Decode(block); err == io.EOF {
   267  				break
   268  			} else if err != nil {
   269  				return false, fmt.Errorf("block %d: failed to parse: %v", index, err)
   270  			}
   271  			blocks = append(blocks, block)
   272  			index++
   273  		}
   274  		if len(blocks) == 0 {
   275  			break
   276  		}
   277  
   278  		if hasAllBlocks(api.eth.BlockChain(), blocks) {
   279  			blocks = blocks[:0]
   280  			continue
   281  		}
   282  //导入批并重置缓冲区
   283  		if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil {
   284  			return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err)
   285  		}
   286  		blocks = blocks[:0]
   287  	}
   288  	return true, nil
   289  }
   290  
   291  //publicDebugAPI是公开的以太坊完整节点API的集合
   292  //在公共调试终结点上。
   293  type PublicDebugAPI struct {
   294  	eth *Ethereum
   295  }
   296  
   297  //newpublicDebugAPI为完整节点创建新的API定义-
   298  //以太坊服务的相关公共调试方法。
   299  func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI {
   300  	return &PublicDebugAPI{eth: eth}
   301  }
   302  
   303  //dumpblock在给定的块中检索数据库的整个状态。
   304  func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
   305  	if blockNr == rpc.PendingBlockNumber {
   306  //如果我们要抛弃这个悬而未决的国家,我们需要请求
   307  //挂起块和来自的挂起状态
   308  //矿工和操作这些
   309  		_, stateDb := api.eth.miner.Pending()
   310  		return stateDb.RawDump(), nil
   311  	}
   312  	var block *types.Block
   313  	if blockNr == rpc.LatestBlockNumber {
   314  		block = api.eth.blockchain.CurrentBlock()
   315  	} else {
   316  		block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
   317  	}
   318  	if block == nil {
   319  		return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
   320  	}
   321  	stateDb, err := api.eth.BlockChain().StateAt(block.Root())
   322  	if err != nil {
   323  		return state.Dump{}, err
   324  	}
   325  	return stateDb.RawDump(), nil
   326  }
   327  
   328  //privatedebugapi是通过
   329  //专用调试终结点。
   330  type PrivateDebugAPI struct {
   331  	config *params.ChainConfig
   332  	eth    *Ethereum
   333  }
   334  
   335  //NealPrimeDebug GAPI为完整的节点创建一个新的API定义
   336  //以太坊服务的专用调试方法。
   337  func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
   338  	return &PrivateDebugAPI{config: config, eth: eth}
   339  }
   340  
   341  //PrimI图是一个调试API函数,它返回Sh3哈希的预图像,如果已知的话。
   342  func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
   343  	if preimage := rawdb.ReadPreimage(api.eth.ChainDb(), hash); preimage != nil {
   344  		return preimage, nil
   345  	}
   346  	return nil, errors.New("unknown preimage")
   347  }
   348  
   349  //badblockargs表示查询坏块时返回的列表中的条目。
   350  type BadBlockArgs struct {
   351  	Hash  common.Hash            `json:"hash"`
   352  	Block map[string]interface{} `json:"block"`
   353  	RLP   string                 `json:"rlp"`
   354  }
   355  
   356  //GetBadBlocks返回客户端在网络上看到的最后一个“坏块”的列表
   357  //并将其作为块哈希的JSON列表返回
   358  func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error) {
   359  	blocks := api.eth.BlockChain().BadBlocks()
   360  	results := make([]*BadBlockArgs, len(blocks))
   361  
   362  	var err error
   363  	for i, block := range blocks {
   364  		results[i] = &BadBlockArgs{
   365  			Hash: block.Hash(),
   366  		}
   367  		if rlpBytes, err := rlp.EncodeToBytes(block); err != nil {
   368  results[i].RLP = err.Error() //哈奇,但是嘿,它起作用了
   369  		} else {
   370  			results[i].RLP = fmt.Sprintf("0x%x", rlpBytes)
   371  		}
   372  		if results[i].Block, err = ethapi.RPCMarshalBlock(block, true, true); err != nil {
   373  			results[i].Block = map[string]interface{}{"error": err.Error()}
   374  		}
   375  	}
   376  	return results, nil
   377  }
   378  
   379  //StestAgRangeReSurt是Debug的StasgStAgReangRangeAPI调用的结果。
   380  type StorageRangeResult struct {
   381  	Storage storageMap   `json:"storage"`
   382  NextKey *common.Hash `json:"nextKey"` //如果存储包含trie中的最后一个密钥,则为nil。
   383  }
   384  
   385  type storageMap map[common.Hash]storageEntry
   386  
   387  type storageEntry struct {
   388  	Key   *common.Hash `json:"key"`
   389  	Value common.Hash  `json:"value"`
   390  }
   391  
   392  //storagerangeat返回给定块高度和事务索引下的存储。
   393  func (api *PrivateDebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) {
   394  	_, _, statedb, err := api.computeTxEnv(blockHash, txIndex, 0)
   395  	if err != nil {
   396  		return StorageRangeResult{}, err
   397  	}
   398  	st := statedb.StorageTrie(contractAddress)
   399  	if st == nil {
   400  		return StorageRangeResult{}, fmt.Errorf("account %x doesn't exist", contractAddress)
   401  	}
   402  	return storageRangeAt(st, keyStart, maxResult)
   403  }
   404  
   405  func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeResult, error) {
   406  	it := trie.NewIterator(st.NodeIterator(start))
   407  	result := StorageRangeResult{Storage: storageMap{}}
   408  	for i := 0; i < maxResult && it.Next(); i++ {
   409  		_, content, _, err := rlp.Split(it.Value)
   410  		if err != nil {
   411  			return StorageRangeResult{}, err
   412  		}
   413  		e := storageEntry{Value: common.BytesToHash(content)}
   414  		if preimage := st.GetKey(it.Key); preimage != nil {
   415  			preimage := common.BytesToHash(preimage)
   416  			e.Key = &preimage
   417  		}
   418  		result.Storage[common.BytesToHash(it.Key)] = e
   419  	}
   420  //添加“下一个密钥”,以便客户端可以继续下载。
   421  	if it.Next() {
   422  		next := common.BytesToHash(it.Key)
   423  		result.NextKey = &next
   424  	}
   425  	return result, nil
   426  }
   427  
   428  //GetModifiedAccountsByNumber返回在
   429  //指定两个块。变化被定义为非现金、余额和
   430  //代码哈希或存储哈希。
   431  //
   432  //使用一个参数,返回在指定块中修改的帐户列表。
   433  func (api *PrivateDebugAPI) GetModifiedAccountsByNumber(startNum uint64, endNum *uint64) ([]common.Address, error) {
   434  	var startBlock, endBlock *types.Block
   435  
   436  	startBlock = api.eth.blockchain.GetBlockByNumber(startNum)
   437  	if startBlock == nil {
   438  		return nil, fmt.Errorf("start block %x not found", startNum)
   439  	}
   440  
   441  	if endNum == nil {
   442  		endBlock = startBlock
   443  		startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash())
   444  		if startBlock == nil {
   445  			return nil, fmt.Errorf("block %x has no parent", endBlock.Number())
   446  		}
   447  	} else {
   448  		endBlock = api.eth.blockchain.GetBlockByNumber(*endNum)
   449  		if endBlock == nil {
   450  			return nil, fmt.Errorf("end block %d not found", *endNum)
   451  		}
   452  	}
   453  	return api.getModifiedAccounts(startBlock, endBlock)
   454  }
   455  
   456  //GetModifiedAccountsByHash返回在
   457  //指定两个块。变化被定义为非现金、余额和
   458  //代码哈希或存储哈希。
   459  //
   460  //使用一个参数,返回在指定块中修改的帐户列表。
   461  func (api *PrivateDebugAPI) GetModifiedAccountsByHash(startHash common.Hash, endHash *common.Hash) ([]common.Address, error) {
   462  	var startBlock, endBlock *types.Block
   463  	startBlock = api.eth.blockchain.GetBlockByHash(startHash)
   464  	if startBlock == nil {
   465  		return nil, fmt.Errorf("start block %x not found", startHash)
   466  	}
   467  
   468  	if endHash == nil {
   469  		endBlock = startBlock
   470  		startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash())
   471  		if startBlock == nil {
   472  			return nil, fmt.Errorf("block %x has no parent", endBlock.Number())
   473  		}
   474  	} else {
   475  		endBlock = api.eth.blockchain.GetBlockByHash(*endHash)
   476  		if endBlock == nil {
   477  			return nil, fmt.Errorf("end block %x not found", *endHash)
   478  		}
   479  	}
   480  	return api.getModifiedAccounts(startBlock, endBlock)
   481  }
   482  
   483  func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]common.Address, error) {
   484  	if startBlock.Number().Uint64() >= endBlock.Number().Uint64() {
   485  		return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startBlock.Number().Uint64(), endBlock.Number().Uint64())
   486  	}
   487  
   488  	oldTrie, err := trie.NewSecure(startBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0)
   489  	if err != nil {
   490  		return nil, err
   491  	}
   492  	newTrie, err := trie.NewSecure(endBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0)
   493  	if err != nil {
   494  		return nil, err
   495  	}
   496  
   497  	diff, _ := trie.NewDifferenceIterator(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}))
   498  	iter := trie.NewIterator(diff)
   499  
   500  	var dirty []common.Address
   501  	for iter.Next() {
   502  		key := newTrie.GetKey(iter.Key)
   503  		if key == nil {
   504  			return nil, fmt.Errorf("no preimage found for hash %x", iter.Key)
   505  		}
   506  		dirty = append(dirty, common.BytesToAddress(key))
   507  	}
   508  	return dirty, nil
   509  }