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 }