github.com/puppeth/go-ethereum@v0.8.6-0.20171014130046-e9295163aa25/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 "context" 21 "math/big" 22 23 "github.com/ethereum/go-ethereum" 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/common/hexutil" 26 "github.com/ethereum/go-ethereum/core/types" 27 "github.com/ethereum/go-ethereum/internal/ethapi" 28 "github.com/ethereum/go-ethereum/rlp" 29 "github.com/ethereum/go-ethereum/rpc" 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 // Ethereum 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, new(ethapi.AddrLocker)), 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 return b.bcapi.GetCode(ctx, contract, toBlockNumber(blockNum)) 58 } 59 60 // CodeAt retrieves any code associated with the contract from the local API. 61 func (b *ContractBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { 62 return b.bcapi.GetCode(ctx, contract, rpc.PendingBlockNumber) 63 } 64 65 // ContractCall implements bind.ContractCaller executing an Ethereum contract 66 // call with the specified data as the input. The pending flag requests execution 67 // against the pending block, not the stable head of the chain. 68 func (b *ContractBackend) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNum *big.Int) ([]byte, error) { 69 out, err := b.bcapi.Call(ctx, toCallArgs(msg), toBlockNumber(blockNum)) 70 return out, err 71 } 72 73 // ContractCall implements bind.ContractCaller executing an Ethereum contract 74 // call with the specified data as the input. The pending flag requests execution 75 // against the pending block, not the stable head of the chain. 76 func (b *ContractBackend) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { 77 out, err := b.bcapi.Call(ctx, toCallArgs(msg), rpc.PendingBlockNumber) 78 return out, err 79 } 80 81 func toCallArgs(msg ethereum.CallMsg) ethapi.CallArgs { 82 args := ethapi.CallArgs{ 83 To: msg.To, 84 From: msg.From, 85 Data: msg.Data, 86 } 87 if msg.Gas != nil { 88 args.Gas = hexutil.Big(*msg.Gas) 89 } 90 if msg.GasPrice != nil { 91 args.GasPrice = hexutil.Big(*msg.GasPrice) 92 } 93 if msg.Value != nil { 94 args.Value = hexutil.Big(*msg.Value) 95 } 96 return args 97 } 98 99 func toBlockNumber(num *big.Int) rpc.BlockNumber { 100 if num == nil { 101 return rpc.LatestBlockNumber 102 } 103 return rpc.BlockNumber(num.Int64()) 104 } 105 106 // PendingAccountNonce implements bind.ContractTransactor retrieving the current 107 // pending nonce associated with an account. 108 func (b *ContractBackend) PendingNonceAt(ctx context.Context, account common.Address) (nonce uint64, err error) { 109 out, err := b.txapi.GetTransactionCount(ctx, account, rpc.PendingBlockNumber) 110 if out != nil { 111 nonce = uint64(*out) 112 } 113 return nonce, err 114 } 115 116 // SuggestGasPrice implements bind.ContractTransactor retrieving the currently 117 // suggested gas price to allow a timely execution of a transaction. 118 func (b *ContractBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 119 return b.eapi.GasPrice(ctx) 120 } 121 122 // EstimateGasLimit implements bind.ContractTransactor triing to estimate the gas 123 // needed to execute a specific transaction based on the current pending state of 124 // the backend blockchain. There is no guarantee that this is the true gas limit 125 // requirement as other transactions may be added or removed by miners, but it 126 // should provide a basis for setting a reasonable default. 127 func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) { 128 out, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg)) 129 return out.ToInt(), err 130 } 131 132 // SendTransaction implements bind.ContractTransactor injects the transaction 133 // into the pending pool for execution. 134 func (b *ContractBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { 135 raw, _ := rlp.EncodeToBytes(tx) 136 _, err := b.txapi.SendRawTransaction(ctx, raw) 137 return err 138 }