github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/eth/bind.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package eth 18 19 import ( 20 "math/big" 21 22 "github.com/ethereum/go-ethereum" 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/common/hexutil" 25 "github.com/ethereum/go-ethereum/core/types" 26 "github.com/ethereum/go-ethereum/internal/ethapi" 27 "github.com/ethereum/go-ethereum/rlp" 28 "github.com/ethereum/go-ethereum/rpc" 29 "golang.org/x/net/context" 30 ) 31 32 // ContractBackend implements bind.ContractBackend with direct calls to Ethereum 33 // internals to support operating on contracts within subprotocols like eth and 34 // swarm. 35 // 36 // Internally this backend uses the already exposed API endpoints of the Ethereum 37 // object. These should be rewritten to internal Go method calls when the Go API 38 // is refactored to support a clean library use. 39 type ContractBackend struct { 40 eapi *ethapi.PublicEthereumAPI // Wrapper around the Ethereum object to access metadata 41 bcapi *ethapi.PublicBlockChainAPI // Wrapper around the blockchain to access chain data 42 txapi *ethapi.PublicTransactionPoolAPI // Wrapper around the transaction pool to access transaction data 43 } 44 45 // NewContractBackend creates a new native contract backend using an existing 46 // Etheruem object. 47 func NewContractBackend(apiBackend ethapi.Backend) *ContractBackend { 48 return &ContractBackend{ 49 eapi: ethapi.NewPublicEthereumAPI(apiBackend), 50 bcapi: ethapi.NewPublicBlockChainAPI(apiBackend), 51 txapi: ethapi.NewPublicTransactionPoolAPI(apiBackend), 52 } 53 } 54 55 // CodeAt retrieves any code associated with the contract from the local API. 56 func (b *ContractBackend) CodeAt(ctx context.Context, contract common.Address, blockNum *big.Int) ([]byte, error) { 57 out, err := b.bcapi.GetCode(ctx, contract, toBlockNumber(blockNum)) 58 return common.FromHex(out), err 59 } 60 61 // CodeAt retrieves any code associated with the contract from the local API. 62 func (b *ContractBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { 63 out, err := b.bcapi.GetCode(ctx, contract, rpc.PendingBlockNumber) 64 return common.FromHex(out), err 65 } 66 67 // ContractCall implements bind.ContractCaller executing an Ethereum contract 68 // call with the specified data as the input. The pending flag requests execution 69 // against the pending block, not the stable head of the chain. 70 func (b *ContractBackend) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNum *big.Int) ([]byte, error) { 71 out, err := b.bcapi.Call(ctx, toCallArgs(msg), toBlockNumber(blockNum)) 72 return common.FromHex(out), err 73 } 74 75 // ContractCall implements bind.ContractCaller executing an Ethereum contract 76 // call with the specified data as the input. The pending flag requests execution 77 // against the pending block, not the stable head of the chain. 78 func (b *ContractBackend) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { 79 out, err := b.bcapi.Call(ctx, toCallArgs(msg), rpc.PendingBlockNumber) 80 return common.FromHex(out), err 81 } 82 83 func toCallArgs(msg ethereum.CallMsg) ethapi.CallArgs { 84 args := ethapi.CallArgs{ 85 To: msg.To, 86 From: msg.From, 87 Data: msg.Data, 88 } 89 if msg.Gas != nil { 90 args.Gas = hexutil.Big(*msg.Gas) 91 } 92 if msg.GasPrice != nil { 93 args.GasPrice = hexutil.Big(*msg.GasPrice) 94 } 95 if msg.Value != nil { 96 args.Value = hexutil.Big(*msg.Value) 97 } 98 return args 99 } 100 101 func toBlockNumber(num *big.Int) rpc.BlockNumber { 102 if num == nil { 103 return rpc.LatestBlockNumber 104 } 105 return rpc.BlockNumber(num.Int64()) 106 } 107 108 // PendingAccountNonce implements bind.ContractTransactor retrieving the current 109 // pending nonce associated with an account. 110 func (b *ContractBackend) PendingNonceAt(ctx context.Context, account common.Address) (nonce uint64, err error) { 111 out, err := b.txapi.GetTransactionCount(ctx, account, rpc.PendingBlockNumber) 112 if out != nil { 113 nonce = uint64(*out) 114 } 115 return nonce, err 116 } 117 118 // SuggestGasPrice implements bind.ContractTransactor retrieving the currently 119 // suggested gas price to allow a timely execution of a transaction. 120 func (b *ContractBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 121 return b.eapi.GasPrice(ctx) 122 } 123 124 // EstimateGasLimit implements bind.ContractTransactor triing to estimate the gas 125 // needed to execute a specific transaction based on the current pending state of 126 // the backend blockchain. There is no guarantee that this is the true gas limit 127 // requirement as other transactions may be added or removed by miners, but it 128 // should provide a basis for setting a reasonable default. 129 func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) { 130 out, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg)) 131 return out.ToInt(), err 132 } 133 134 // SendTransaction implements bind.ContractTransactor injects the transaction 135 // into the pending pool for execution. 136 func (b *ContractBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { 137 raw, _ := rlp.EncodeToBytes(tx) 138 _, err := b.txapi.SendRawTransaction(ctx, raw) 139 return err 140 }