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