github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/mobile/ethclient.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  //版权所有2016 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  //包含以太坊客户端的包装。
    26  
    27  package geth
    28  
    29  import (
    30  	"math/big"
    31  
    32  	"github.com/ethereum/go-ethereum/core/types"
    33  	"github.com/ethereum/go-ethereum/ethclient"
    34  )
    35  
    36  //以太坊客户端提供对以太坊API的访问。
    37  type EthereumClient struct {
    38  	client *ethclient.Client
    39  }
    40  
    41  //newethereumclient将客户机连接到给定的URL。
    42  func NewEthereumClient(rawurl string) (client *EthereumClient, _ error) {
    43  	rawClient, err := ethclient.Dial(rawurl)
    44  	return &EthereumClient{rawClient}, err
    45  }
    46  
    47  //GetBlockByHash返回给定的完整块。
    48  func (ec *EthereumClient) GetBlockByHash(ctx *Context, hash *Hash) (block *Block, _ error) {
    49  	rawBlock, err := ec.client.BlockByHash(ctx.context, hash.hash)
    50  	return &Block{rawBlock}, err
    51  }
    52  
    53  //GetBlockByNumber返回当前规范链中的块。如果数字小于0,则
    54  //返回最新的已知块。
    55  func (ec *EthereumClient) GetBlockByNumber(ctx *Context, number int64) (block *Block, _ error) {
    56  	if number < 0 {
    57  		rawBlock, err := ec.client.BlockByNumber(ctx.context, nil)
    58  		return &Block{rawBlock}, err
    59  	}
    60  	rawBlock, err := ec.client.BlockByNumber(ctx.context, big.NewInt(number))
    61  	return &Block{rawBlock}, err
    62  }
    63  
    64  //GetHeaderByHash返回具有给定哈希的块头。
    65  func (ec *EthereumClient) GetHeaderByHash(ctx *Context, hash *Hash) (header *Header, _ error) {
    66  	rawHeader, err := ec.client.HeaderByHash(ctx.context, hash.hash)
    67  	return &Header{rawHeader}, err
    68  }
    69  
    70  //GetHeaderByNumber返回当前规范链的块头。如果数字小于0,
    71  //返回最新的已知头。
    72  func (ec *EthereumClient) GetHeaderByNumber(ctx *Context, number int64) (header *Header, _ error) {
    73  	if number < 0 {
    74  		rawHeader, err := ec.client.HeaderByNumber(ctx.context, nil)
    75  		return &Header{rawHeader}, err
    76  	}
    77  	rawHeader, err := ec.client.HeaderByNumber(ctx.context, big.NewInt(number))
    78  	return &Header{rawHeader}, err
    79  }
    80  
    81  //GetTransactionByHash返回具有给定哈希的事务。
    82  func (ec *EthereumClient) GetTransactionByHash(ctx *Context, hash *Hash) (tx *Transaction, _ error) {
    83  //TODO(karalabe):句柄显示
    84  	rawTx, _, err := ec.client.TransactionByHash(ctx.context, hash.hash)
    85  	return &Transaction{rawTx}, err
    86  }
    87  
    88  //GetTransactionSsender返回事务的发件人地址。交易必须
    89  //在给定的块和索引中包含在区块链中。
    90  func (ec *EthereumClient) GetTransactionSender(ctx *Context, tx *Transaction, blockhash *Hash, index int) (sender *Address, _ error) {
    91  	addr, err := ec.client.TransactionSender(ctx.context, tx.tx, blockhash.hash, uint(index))
    92  	return &Address{addr}, err
    93  }
    94  
    95  //GetTransactionCount返回给定块中的事务总数。
    96  func (ec *EthereumClient) GetTransactionCount(ctx *Context, hash *Hash) (count int, _ error) {
    97  	rawCount, err := ec.client.TransactionCount(ctx.context, hash.hash)
    98  	return int(rawCount), err
    99  }
   100  
   101  //GetTransactionInBlock返回给定块中索引处的单个事务。
   102  func (ec *EthereumClient) GetTransactionInBlock(ctx *Context, hash *Hash, index int) (tx *Transaction, _ error) {
   103  	rawTx, err := ec.client.TransactionInBlock(ctx.context, hash.hash, uint(index))
   104  	return &Transaction{rawTx}, err
   105  
   106  }
   107  
   108  //GetTransactionReceipt按事务哈希返回事务的接收。
   109  //请注意,收据不可用于待处理的交易。
   110  func (ec *EthereumClient) GetTransactionReceipt(ctx *Context, hash *Hash) (receipt *Receipt, _ error) {
   111  	rawReceipt, err := ec.client.TransactionReceipt(ctx.context, hash.hash)
   112  	return &Receipt{rawReceipt}, err
   113  }
   114  
   115  //SyncProgress检索同步算法的当前进度。如果有
   116  //当前没有运行同步,它返回零。
   117  func (ec *EthereumClient) SyncProgress(ctx *Context) (progress *SyncProgress, _ error) {
   118  	rawProgress, err := ec.client.SyncProgress(ctx.context)
   119  	if rawProgress == nil {
   120  		return nil, err
   121  	}
   122  	return &SyncProgress{*rawProgress}, err
   123  }
   124  
   125  //NewHeadHandler是一个客户端订阅回调,用于在事件和
   126  //订阅失败。
   127  type NewHeadHandler interface {
   128  	OnNewHead(header *Header)
   129  	OnError(failure string)
   130  }
   131  
   132  //订阅订阅当前区块链头的通知
   133  //在给定的频道上。
   134  func (ec *EthereumClient) SubscribeNewHead(ctx *Context, handler NewHeadHandler, buffer int) (sub *Subscription, _ error) {
   135  //在内部订阅事件
   136  	ch := make(chan *types.Header, buffer)
   137  	rawSub, err := ec.client.SubscribeNewHead(ctx.context, ch)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  //启动一个调度器以反馈回拨
   142  	go func() {
   143  		for {
   144  			select {
   145  			case header := <-ch:
   146  				handler.OnNewHead(&Header{header})
   147  
   148  			case err := <-rawSub.Err():
   149  				handler.OnError(err.Error())
   150  				return
   151  			}
   152  		}
   153  	}()
   154  	return &Subscription{rawSub}, nil
   155  }
   156  
   157  //状态访问
   158  
   159  //getbalanceat返回给定帐户的wei余额。
   160  //块编号可以小于0,在这种情况下,余额取自最新的已知块。
   161  func (ec *EthereumClient) GetBalanceAt(ctx *Context, account *Address, number int64) (balance *BigInt, _ error) {
   162  	if number < 0 {
   163  		rawBalance, err := ec.client.BalanceAt(ctx.context, account.address, nil)
   164  		return &BigInt{rawBalance}, err
   165  	}
   166  	rawBalance, err := ec.client.BalanceAt(ctx.context, account.address, big.NewInt(number))
   167  	return &BigInt{rawBalance}, err
   168  }
   169  
   170  //GetStorageAt返回给定帐户的合同存储中密钥的值。
   171  //块编号可以小于0,在这种情况下,该值取自最新的已知块。
   172  func (ec *EthereumClient) GetStorageAt(ctx *Context, account *Address, key *Hash, number int64) (storage []byte, _ error) {
   173  	if number < 0 {
   174  		return ec.client.StorageAt(ctx.context, account.address, key.hash, nil)
   175  	}
   176  	return ec.client.StorageAt(ctx.context, account.address, key.hash, big.NewInt(number))
   177  }
   178  
   179  //getcodeat返回给定帐户的合同代码。
   180  //块编号可以小于0,在这种情况下,代码取自最新的已知块。
   181  func (ec *EthereumClient) GetCodeAt(ctx *Context, account *Address, number int64) (code []byte, _ error) {
   182  	if number < 0 {
   183  		return ec.client.CodeAt(ctx.context, account.address, nil)
   184  	}
   185  	return ec.client.CodeAt(ctx.context, account.address, big.NewInt(number))
   186  }
   187  
   188  //getnonceat返回给定帐户的nonce帐户。
   189  //块号可以小于0,在这种情况下,nonce是从最新的已知块中获取的。
   190  func (ec *EthereumClient) GetNonceAt(ctx *Context, account *Address, number int64) (nonce int64, _ error) {
   191  	if number < 0 {
   192  		rawNonce, err := ec.client.NonceAt(ctx.context, account.address, nil)
   193  		return int64(rawNonce), err
   194  	}
   195  	rawNonce, err := ec.client.NonceAt(ctx.context, account.address, big.NewInt(number))
   196  	return int64(rawNonce), err
   197  }
   198  
   199  //过滤器
   200  
   201  //filterlogs执行筛选器查询。
   202  func (ec *EthereumClient) FilterLogs(ctx *Context, query *FilterQuery) (logs *Logs, _ error) {
   203  	rawLogs, err := ec.client.FilterLogs(ctx.context, query.query)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  //由于vm.logs为[]*vm.log,临时黑客
   208  	res := make([]*types.Log, len(rawLogs))
   209  	for i := range rawLogs {
   210  		res[i] = &rawLogs[i]
   211  	}
   212  	return &Logs{res}, nil
   213  }
   214  
   215  //filterlogshandler是一个客户端订阅回调,用于在事件和
   216  //订阅失败。
   217  type FilterLogsHandler interface {
   218  	OnFilterLogs(log *Log)
   219  	OnError(failure string)
   220  }
   221  
   222  //subscribeFilterLogs订阅流式筛选查询的结果。
   223  func (ec *EthereumClient) SubscribeFilterLogs(ctx *Context, query *FilterQuery, handler FilterLogsHandler, buffer int) (sub *Subscription, _ error) {
   224  //在内部订阅事件
   225  	ch := make(chan types.Log, buffer)
   226  	rawSub, err := ec.client.SubscribeFilterLogs(ctx.context, query.query, ch)
   227  	if err != nil {
   228  		return nil, err
   229  	}
   230  //启动一个调度器以反馈回拨
   231  	go func() {
   232  		for {
   233  			select {
   234  			case log := <-ch:
   235  				handler.OnFilterLogs(&Log{&log})
   236  
   237  			case err := <-rawSub.Err():
   238  				handler.OnError(err.Error())
   239  				return
   240  			}
   241  		}
   242  	}()
   243  	return &Subscription{rawSub}, nil
   244  }
   245  
   246  //预备状态
   247  
   248  //getPendingBalanceAt返回处于挂起状态的给定帐户的wei余额。
   249  func (ec *EthereumClient) GetPendingBalanceAt(ctx *Context, account *Address) (balance *BigInt, _ error) {
   250  	rawBalance, err := ec.client.PendingBalanceAt(ctx.context, account.address)
   251  	return &BigInt{rawBalance}, err
   252  }
   253  
   254  //GetPendingStorageAt返回处于挂起状态的给定帐户的合同存储中键的值。
   255  func (ec *EthereumClient) GetPendingStorageAt(ctx *Context, account *Address, key *Hash) (storage []byte, _ error) {
   256  	return ec.client.PendingStorageAt(ctx.context, account.address, key.hash)
   257  }
   258  
   259  //GetPendingCodeAt返回处于挂起状态的给定帐户的合同代码。
   260  func (ec *EthereumClient) GetPendingCodeAt(ctx *Context, account *Address) (code []byte, _ error) {
   261  	return ec.client.PendingCodeAt(ctx.context, account.address)
   262  }
   263  
   264  //GetPendingOnCate返回处于挂起状态的给定帐户的帐户nonce。
   265  //这是应该用于下一个事务的nonce。
   266  func (ec *EthereumClient) GetPendingNonceAt(ctx *Context, account *Address) (nonce int64, _ error) {
   267  	rawNonce, err := ec.client.PendingNonceAt(ctx.context, account.address)
   268  	return int64(rawNonce), err
   269  }
   270  
   271  //GetPendingtTransactionCount返回处于挂起状态的事务总数。
   272  func (ec *EthereumClient) GetPendingTransactionCount(ctx *Context) (count int, _ error) {
   273  	rawCount, err := ec.client.PendingTransactionCount(ctx.context)
   274  	return int(rawCount), err
   275  }
   276  
   277  //合同呼叫
   278  
   279  //CallContract执行消息调用事务,该事务直接在VM中执行
   280  //但从未开发到区块链中。
   281  //
   282  //BlockNumber选择运行调用的块高度。它可以小于0,其中
   283  //如果代码取自最新的已知块。注意这个状态从很老
   284  //块可能不可用。
   285  func (ec *EthereumClient) CallContract(ctx *Context, msg *CallMsg, number int64) (output []byte, _ error) {
   286  	if number < 0 {
   287  		return ec.client.CallContract(ctx.context, msg.msg, nil)
   288  	}
   289  	return ec.client.CallContract(ctx.context, msg.msg, big.NewInt(number))
   290  }
   291  
   292  //PendingCallContract使用EVM执行消息调用事务。
   293  //合同调用所看到的状态是挂起状态。
   294  func (ec *EthereumClient) PendingCallContract(ctx *Context, msg *CallMsg) (output []byte, _ error) {
   295  	return ec.client.PendingCallContract(ctx.context, msg.msg)
   296  }
   297  
   298  //SuggestGasprice检索当前建议的天然气价格,以便及时
   299  //交易的执行。
   300  func (ec *EthereumClient) SuggestGasPrice(ctx *Context) (price *BigInt, _ error) {
   301  	rawPrice, err := ec.client.SuggestGasPrice(ctx.context)
   302  	return &BigInt{rawPrice}, err
   303  }
   304  
   305  //EstimateGas试图根据
   306  //后端区块链的当前挂起状态。不能保证这是
   307  //矿工可能增加或移除的其他交易的实际气体限制要求,
   308  //但它应为设定合理违约提供依据。
   309  func (ec *EthereumClient) EstimateGas(ctx *Context, msg *CallMsg) (gas int64, _ error) {
   310  	rawGas, err := ec.client.EstimateGas(ctx.context, msg.msg)
   311  	return int64(rawGas), err
   312  }
   313  
   314  //sendTransaction将签名的事务注入挂起池以执行。
   315  //
   316  //如果事务是合同创建,请使用TransactionReceipt方法获取
   317  //挖掘交易记录后的合同地址。
   318  func (ec *EthereumClient) SendTransaction(ctx *Context, tx *Transaction) error {
   319  	return ec.client.SendTransaction(ctx.context, tx.tx)
   320  }