forked from cerc-io/plugeth
6ea05f5a54
SignTransaction creates a transaction but does submit it to the network. SignTransaction returns a structure which includes the transaction object details as well as the RLP encoded transaction that could possibly be submitted by the SendRawTransaction method.
722 lines
23 KiB
Go
722 lines
23 KiB
Go
// Copyright 2015 The go-ethereum Authors
|
|
// This file is part of the go-ethereum library.
|
|
//
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package api
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"math/big"
|
|
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/natspec"
|
|
"github.com/ethereum/go-ethereum/eth"
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
"github.com/ethereum/go-ethereum/rpc/codec"
|
|
"github.com/ethereum/go-ethereum/rpc/shared"
|
|
"github.com/ethereum/go-ethereum/xeth"
|
|
"gopkg.in/fatih/set.v0"
|
|
)
|
|
|
|
const (
|
|
EthApiVersion = "1.0"
|
|
)
|
|
|
|
// eth api provider
|
|
// See https://github.com/ethereum/wiki/wiki/JSON-RPC
|
|
type ethApi struct {
|
|
xeth *xeth.XEth
|
|
ethereum *eth.Ethereum
|
|
methods map[string]ethhandler
|
|
codec codec.ApiCoder
|
|
}
|
|
|
|
// eth callback handler
|
|
type ethhandler func(*ethApi, *shared.Request) (interface{}, error)
|
|
|
|
var (
|
|
ethMapping = map[string]ethhandler{
|
|
"eth_accounts": (*ethApi).Accounts,
|
|
"eth_blockNumber": (*ethApi).BlockNumber,
|
|
"eth_getBalance": (*ethApi).GetBalance,
|
|
"eth_protocolVersion": (*ethApi).ProtocolVersion,
|
|
"eth_coinbase": (*ethApi).Coinbase,
|
|
"eth_mining": (*ethApi).IsMining,
|
|
"eth_syncing": (*ethApi).IsSyncing,
|
|
"eth_gasPrice": (*ethApi).GasPrice,
|
|
"eth_getStorage": (*ethApi).GetStorage,
|
|
"eth_storageAt": (*ethApi).GetStorage,
|
|
"eth_getStorageAt": (*ethApi).GetStorageAt,
|
|
"eth_getTransactionCount": (*ethApi).GetTransactionCount,
|
|
"eth_getBlockTransactionCountByHash": (*ethApi).GetBlockTransactionCountByHash,
|
|
"eth_getBlockTransactionCountByNumber": (*ethApi).GetBlockTransactionCountByNumber,
|
|
"eth_getUncleCountByBlockHash": (*ethApi).GetUncleCountByBlockHash,
|
|
"eth_getUncleCountByBlockNumber": (*ethApi).GetUncleCountByBlockNumber,
|
|
"eth_getData": (*ethApi).GetData,
|
|
"eth_getCode": (*ethApi).GetData,
|
|
"eth_getNatSpec": (*ethApi).GetNatSpec,
|
|
"eth_sign": (*ethApi).Sign,
|
|
"eth_sendRawTransaction": (*ethApi).SubmitTransaction,
|
|
"eth_submitTransaction": (*ethApi).SubmitTransaction,
|
|
"eth_sendTransaction": (*ethApi).SendTransaction,
|
|
"eth_signTransaction": (*ethApi).SignTransaction,
|
|
"eth_transact": (*ethApi).SendTransaction,
|
|
"eth_estimateGas": (*ethApi).EstimateGas,
|
|
"eth_call": (*ethApi).Call,
|
|
"eth_flush": (*ethApi).Flush,
|
|
"eth_getBlockByHash": (*ethApi).GetBlockByHash,
|
|
"eth_getBlockByNumber": (*ethApi).GetBlockByNumber,
|
|
"eth_getTransactionByHash": (*ethApi).GetTransactionByHash,
|
|
"eth_getTransactionByBlockNumberAndIndex": (*ethApi).GetTransactionByBlockNumberAndIndex,
|
|
"eth_getTransactionByBlockHashAndIndex": (*ethApi).GetTransactionByBlockHashAndIndex,
|
|
"eth_getUncleByBlockHashAndIndex": (*ethApi).GetUncleByBlockHashAndIndex,
|
|
"eth_getUncleByBlockNumberAndIndex": (*ethApi).GetUncleByBlockNumberAndIndex,
|
|
"eth_getCompilers": (*ethApi).GetCompilers,
|
|
"eth_compileSolidity": (*ethApi).CompileSolidity,
|
|
"eth_newFilter": (*ethApi).NewFilter,
|
|
"eth_newBlockFilter": (*ethApi).NewBlockFilter,
|
|
"eth_newPendingTransactionFilter": (*ethApi).NewPendingTransactionFilter,
|
|
"eth_uninstallFilter": (*ethApi).UninstallFilter,
|
|
"eth_getFilterChanges": (*ethApi).GetFilterChanges,
|
|
"eth_getFilterLogs": (*ethApi).GetFilterLogs,
|
|
"eth_getLogs": (*ethApi).GetLogs,
|
|
"eth_hashrate": (*ethApi).Hashrate,
|
|
"eth_getWork": (*ethApi).GetWork,
|
|
"eth_submitWork": (*ethApi).SubmitWork,
|
|
"eth_submitHashrate": (*ethApi).SubmitHashrate,
|
|
"eth_resend": (*ethApi).Resend,
|
|
"eth_pendingTransactions": (*ethApi).PendingTransactions,
|
|
"eth_getTransactionReceipt": (*ethApi).GetTransactionReceipt,
|
|
}
|
|
)
|
|
|
|
// create new ethApi instance
|
|
func NewEthApi(xeth *xeth.XEth, eth *eth.Ethereum, codec codec.Codec) *ethApi {
|
|
return ðApi{xeth, eth, ethMapping, codec.New(nil)}
|
|
}
|
|
|
|
// collection with supported methods
|
|
func (self *ethApi) Methods() []string {
|
|
methods := make([]string, len(self.methods))
|
|
i := 0
|
|
for k := range self.methods {
|
|
methods[i] = k
|
|
i++
|
|
}
|
|
return methods
|
|
}
|
|
|
|
// Execute given request
|
|
func (self *ethApi) Execute(req *shared.Request) (interface{}, error) {
|
|
if callback, ok := self.methods[req.Method]; ok {
|
|
return callback(self, req)
|
|
}
|
|
|
|
return nil, shared.NewNotImplementedError(req.Method)
|
|
}
|
|
|
|
func (self *ethApi) Name() string {
|
|
return shared.EthApiName
|
|
}
|
|
|
|
func (self *ethApi) ApiVersion() string {
|
|
return EthApiVersion
|
|
}
|
|
|
|
func (self *ethApi) Accounts(req *shared.Request) (interface{}, error) {
|
|
return self.xeth.Accounts(), nil
|
|
}
|
|
|
|
func (self *ethApi) Hashrate(req *shared.Request) (interface{}, error) {
|
|
return newHexNum(self.xeth.HashRate()), nil
|
|
}
|
|
|
|
func (self *ethApi) BlockNumber(req *shared.Request) (interface{}, error) {
|
|
num := self.xeth.CurrentBlock().Number()
|
|
return newHexNum(num.Bytes()), nil
|
|
}
|
|
|
|
func (self *ethApi) GetBalance(req *shared.Request) (interface{}, error) {
|
|
args := new(GetBalanceArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
return self.xeth.AtStateNum(args.BlockNumber).BalanceAt(args.Address), nil
|
|
}
|
|
|
|
func (self *ethApi) ProtocolVersion(req *shared.Request) (interface{}, error) {
|
|
return self.xeth.EthVersion(), nil
|
|
}
|
|
|
|
func (self *ethApi) Coinbase(req *shared.Request) (interface{}, error) {
|
|
return newHexData(self.xeth.Coinbase()), nil
|
|
}
|
|
|
|
func (self *ethApi) IsMining(req *shared.Request) (interface{}, error) {
|
|
return self.xeth.IsMining(), nil
|
|
}
|
|
|
|
func (self *ethApi) IsSyncing(req *shared.Request) (interface{}, error) {
|
|
origin, current, height := self.ethereum.Downloader().Progress()
|
|
if current < height {
|
|
return map[string]interface{}{
|
|
"startingBlock": newHexNum(big.NewInt(int64(origin)).Bytes()),
|
|
"currentBlock": newHexNum(big.NewInt(int64(current)).Bytes()),
|
|
"highestBlock": newHexNum(big.NewInt(int64(height)).Bytes()),
|
|
}, nil
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
func (self *ethApi) GasPrice(req *shared.Request) (interface{}, error) {
|
|
return newHexNum(self.xeth.DefaultGasPrice().Bytes()), nil
|
|
}
|
|
|
|
func (self *ethApi) GetStorage(req *shared.Request) (interface{}, error) {
|
|
args := new(GetStorageArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
return self.xeth.AtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage(), nil
|
|
}
|
|
|
|
func (self *ethApi) GetStorageAt(req *shared.Request) (interface{}, error) {
|
|
args := new(GetStorageAtArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
return self.xeth.AtStateNum(args.BlockNumber).StorageAt(args.Address, args.Key), nil
|
|
}
|
|
|
|
func (self *ethApi) GetTransactionCount(req *shared.Request) (interface{}, error) {
|
|
args := new(GetTxCountArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
count := self.xeth.AtStateNum(args.BlockNumber).TxCountAt(args.Address)
|
|
return fmt.Sprintf("%#x", count), nil
|
|
}
|
|
|
|
func (self *ethApi) GetBlockTransactionCountByHash(req *shared.Request) (interface{}, error) {
|
|
args := new(HashArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
block := self.xeth.EthBlockByHash(args.Hash)
|
|
if block == nil {
|
|
return nil, nil
|
|
}
|
|
return fmt.Sprintf("%#x", len(block.Transactions())), nil
|
|
}
|
|
|
|
func (self *ethApi) GetBlockTransactionCountByNumber(req *shared.Request) (interface{}, error) {
|
|
args := new(BlockNumArg)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
block := self.xeth.EthBlockByNumber(args.BlockNumber)
|
|
if block == nil {
|
|
return nil, nil
|
|
}
|
|
return fmt.Sprintf("%#x", len(block.Transactions())), nil
|
|
}
|
|
|
|
func (self *ethApi) GetUncleCountByBlockHash(req *shared.Request) (interface{}, error) {
|
|
args := new(HashArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
block := self.xeth.EthBlockByHash(args.Hash)
|
|
if block == nil {
|
|
return nil, nil
|
|
}
|
|
return fmt.Sprintf("%#x", len(block.Uncles())), nil
|
|
}
|
|
|
|
func (self *ethApi) GetUncleCountByBlockNumber(req *shared.Request) (interface{}, error) {
|
|
args := new(BlockNumArg)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
block := self.xeth.EthBlockByNumber(args.BlockNumber)
|
|
if block == nil {
|
|
return nil, nil
|
|
}
|
|
return fmt.Sprintf("%#x", len(block.Uncles())), nil
|
|
}
|
|
|
|
func (self *ethApi) GetData(req *shared.Request) (interface{}, error) {
|
|
args := new(GetDataArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
v := self.xeth.AtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
|
|
return newHexData(v), nil
|
|
}
|
|
|
|
func (self *ethApi) Sign(req *shared.Request) (interface{}, error) {
|
|
args := new(NewSigArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
v, err := self.xeth.Sign(args.From, args.Data, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
func (self *ethApi) SubmitTransaction(req *shared.Request) (interface{}, error) {
|
|
args := new(NewDataArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
v, err := self.xeth.PushTx(args.Data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
// JsonTransaction is returned as response by the JSON RPC. It contains the
|
|
// signed RLP encoded transaction as Raw and the signed transaction object as Tx.
|
|
type JsonTransaction struct {
|
|
Raw string `json:"raw"`
|
|
Tx *tx `json:"tx"`
|
|
}
|
|
|
|
func (self *ethApi) SignTransaction(req *shared.Request) (interface{}, error) {
|
|
args := new(NewTxArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
// nonce may be nil ("guess" mode)
|
|
var nonce string
|
|
if args.Nonce != nil {
|
|
nonce = args.Nonce.String()
|
|
}
|
|
|
|
var gas, price string
|
|
if args.Gas != nil {
|
|
gas = args.Gas.String()
|
|
}
|
|
if args.GasPrice != nil {
|
|
price = args.GasPrice.String()
|
|
}
|
|
tx, err := self.xeth.SignTransaction(args.From, args.To, nonce, args.Value.String(), gas, price, args.Data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data, err := rlp.EncodeToBytes(tx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return JsonTransaction{"0x" + common.Bytes2Hex(data), newTx(tx)}, nil
|
|
}
|
|
|
|
func (self *ethApi) SendTransaction(req *shared.Request) (interface{}, error) {
|
|
args := new(NewTxArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
// nonce may be nil ("guess" mode)
|
|
var nonce string
|
|
if args.Nonce != nil {
|
|
nonce = args.Nonce.String()
|
|
}
|
|
|
|
var gas, price string
|
|
if args.Gas != nil {
|
|
gas = args.Gas.String()
|
|
}
|
|
if args.GasPrice != nil {
|
|
price = args.GasPrice.String()
|
|
}
|
|
v, err := self.xeth.Transact(args.From, args.To, nonce, args.Value.String(), gas, price, args.Data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
func (self *ethApi) GetNatSpec(req *shared.Request) (interface{}, error) {
|
|
args := new(NewTxArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, args.To, args.Data)
|
|
notice := natspec.GetNotice(self.xeth, jsontx, self.ethereum.HTTPClient())
|
|
|
|
return notice, nil
|
|
}
|
|
|
|
func (self *ethApi) EstimateGas(req *shared.Request) (interface{}, error) {
|
|
_, gas, err := self.doCall(req.Params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO unwrap the parent method's ToHex call
|
|
if len(gas) == 0 {
|
|
return newHexNum(0), nil
|
|
} else {
|
|
return newHexNum(common.String2Big(gas)), err
|
|
}
|
|
}
|
|
|
|
func (self *ethApi) Call(req *shared.Request) (interface{}, error) {
|
|
v, _, err := self.doCall(req.Params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO unwrap the parent method's ToHex call
|
|
if v == "0x0" {
|
|
return newHexData([]byte{}), nil
|
|
} else {
|
|
return newHexData(common.FromHex(v)), nil
|
|
}
|
|
}
|
|
|
|
func (self *ethApi) Flush(req *shared.Request) (interface{}, error) {
|
|
return nil, shared.NewNotImplementedError(req.Method)
|
|
}
|
|
|
|
func (self *ethApi) doCall(params json.RawMessage) (string, string, error) {
|
|
args := new(CallArgs)
|
|
if err := self.codec.Decode(params, &args); err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
return self.xeth.AtStateNum(args.BlockNumber).Call(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
|
|
}
|
|
|
|
func (self *ethApi) GetBlockByHash(req *shared.Request) (interface{}, error) {
|
|
args := new(GetBlockByHashArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
block := self.xeth.EthBlockByHash(args.BlockHash)
|
|
if block == nil {
|
|
return nil, nil
|
|
}
|
|
return NewBlockRes(block, self.xeth.Td(block.Hash()), args.IncludeTxs), nil
|
|
}
|
|
|
|
func (self *ethApi) GetBlockByNumber(req *shared.Request) (interface{}, error) {
|
|
args := new(GetBlockByNumberArgs)
|
|
if err := json.Unmarshal(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
block := self.xeth.EthBlockByNumber(args.BlockNumber)
|
|
if block == nil {
|
|
return nil, nil
|
|
}
|
|
return NewBlockRes(block, self.xeth.Td(block.Hash()), args.IncludeTxs), nil
|
|
}
|
|
|
|
func (self *ethApi) GetTransactionByHash(req *shared.Request) (interface{}, error) {
|
|
args := new(HashArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
tx, bhash, bnum, txi := self.xeth.EthTransactionByHash(args.Hash)
|
|
if tx != nil {
|
|
v := NewTransactionRes(tx)
|
|
// if the blockhash is 0, assume this is a pending transaction
|
|
if bytes.Compare(bhash.Bytes(), bytes.Repeat([]byte{0}, 32)) != 0 {
|
|
v.BlockHash = newHexData(bhash)
|
|
v.BlockNumber = newHexNum(bnum)
|
|
v.TxIndex = newHexNum(txi)
|
|
}
|
|
return v, nil
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (self *ethApi) GetTransactionByBlockHashAndIndex(req *shared.Request) (interface{}, error) {
|
|
args := new(HashIndexArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
raw := self.xeth.EthBlockByHash(args.Hash)
|
|
if raw == nil {
|
|
return nil, nil
|
|
}
|
|
block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), true)
|
|
if args.Index >= int64(len(block.Transactions)) || args.Index < 0 {
|
|
return nil, nil
|
|
} else {
|
|
return block.Transactions[args.Index], nil
|
|
}
|
|
}
|
|
|
|
func (self *ethApi) GetTransactionByBlockNumberAndIndex(req *shared.Request) (interface{}, error) {
|
|
args := new(BlockNumIndexArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
raw := self.xeth.EthBlockByNumber(args.BlockNumber)
|
|
if raw == nil {
|
|
return nil, nil
|
|
}
|
|
block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), true)
|
|
if args.Index >= int64(len(block.Transactions)) || args.Index < 0 {
|
|
// return NewValidationError("Index", "does not exist")
|
|
return nil, nil
|
|
}
|
|
return block.Transactions[args.Index], nil
|
|
}
|
|
|
|
func (self *ethApi) GetUncleByBlockHashAndIndex(req *shared.Request) (interface{}, error) {
|
|
args := new(HashIndexArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
raw := self.xeth.EthBlockByHash(args.Hash)
|
|
if raw == nil {
|
|
return nil, nil
|
|
}
|
|
block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), false)
|
|
if args.Index >= int64(len(block.Uncles)) || args.Index < 0 {
|
|
// return NewValidationError("Index", "does not exist")
|
|
return nil, nil
|
|
}
|
|
return block.Uncles[args.Index], nil
|
|
}
|
|
|
|
func (self *ethApi) GetUncleByBlockNumberAndIndex(req *shared.Request) (interface{}, error) {
|
|
args := new(BlockNumIndexArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
raw := self.xeth.EthBlockByNumber(args.BlockNumber)
|
|
if raw == nil {
|
|
return nil, nil
|
|
}
|
|
block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), true)
|
|
if args.Index >= int64(len(block.Uncles)) || args.Index < 0 {
|
|
return nil, nil
|
|
} else {
|
|
return block.Uncles[args.Index], nil
|
|
}
|
|
}
|
|
|
|
func (self *ethApi) GetCompilers(req *shared.Request) (interface{}, error) {
|
|
var lang string
|
|
if solc, _ := self.xeth.Solc(); solc != nil {
|
|
lang = "Solidity"
|
|
}
|
|
c := []string{lang}
|
|
return c, nil
|
|
}
|
|
|
|
func (self *ethApi) CompileSolidity(req *shared.Request) (interface{}, error) {
|
|
solc, _ := self.xeth.Solc()
|
|
if solc == nil {
|
|
return nil, shared.NewNotAvailableError(req.Method, "solc (solidity compiler) not found")
|
|
}
|
|
|
|
args := new(SourceArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
contracts, err := solc.Compile(args.Source)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return contracts, nil
|
|
}
|
|
|
|
func (self *ethApi) NewFilter(req *shared.Request) (interface{}, error) {
|
|
args := new(BlockFilterArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
id := self.xeth.NewLogFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)
|
|
return newHexNum(big.NewInt(int64(id)).Bytes()), nil
|
|
}
|
|
|
|
func (self *ethApi) NewBlockFilter(req *shared.Request) (interface{}, error) {
|
|
return newHexNum(self.xeth.NewBlockFilter()), nil
|
|
}
|
|
|
|
func (self *ethApi) NewPendingTransactionFilter(req *shared.Request) (interface{}, error) {
|
|
return newHexNum(self.xeth.NewTransactionFilter()), nil
|
|
}
|
|
|
|
func (self *ethApi) UninstallFilter(req *shared.Request) (interface{}, error) {
|
|
args := new(FilterIdArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
return self.xeth.UninstallFilter(args.Id), nil
|
|
}
|
|
|
|
func (self *ethApi) GetFilterChanges(req *shared.Request) (interface{}, error) {
|
|
args := new(FilterIdArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
switch self.xeth.GetFilterType(args.Id) {
|
|
case xeth.BlockFilterTy:
|
|
return NewHashesRes(self.xeth.BlockFilterChanged(args.Id)), nil
|
|
case xeth.TransactionFilterTy:
|
|
return NewHashesRes(self.xeth.TransactionFilterChanged(args.Id)), nil
|
|
case xeth.LogFilterTy:
|
|
return NewLogsRes(self.xeth.LogFilterChanged(args.Id)), nil
|
|
default:
|
|
return []string{}, nil // reply empty string slice
|
|
}
|
|
}
|
|
|
|
func (self *ethApi) GetFilterLogs(req *shared.Request) (interface{}, error) {
|
|
args := new(FilterIdArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
return NewLogsRes(self.xeth.Logs(args.Id)), nil
|
|
}
|
|
|
|
func (self *ethApi) GetLogs(req *shared.Request) (interface{}, error) {
|
|
args := new(BlockFilterArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
return NewLogsRes(self.xeth.AllLogs(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)), nil
|
|
}
|
|
|
|
func (self *ethApi) GetWork(req *shared.Request) (interface{}, error) {
|
|
self.xeth.SetMining(true, 0)
|
|
ret, err := self.xeth.RemoteMining().GetWork()
|
|
if err != nil {
|
|
return nil, shared.NewNotReadyError("mining work")
|
|
} else {
|
|
return ret, nil
|
|
}
|
|
}
|
|
|
|
func (self *ethApi) SubmitWork(req *shared.Request) (interface{}, error) {
|
|
args := new(SubmitWorkArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
return self.xeth.RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header)), nil
|
|
}
|
|
|
|
func (self *ethApi) SubmitHashrate(req *shared.Request) (interface{}, error) {
|
|
args := new(SubmitHashRateArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return false, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
self.xeth.RemoteMining().SubmitHashrate(common.HexToHash(args.Id), args.Rate)
|
|
return true, nil
|
|
}
|
|
|
|
func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {
|
|
args := new(ResendArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
from := common.HexToAddress(args.Tx.From)
|
|
|
|
pending := self.ethereum.TxPool().GetTransactions()
|
|
for _, p := range pending {
|
|
if pFrom, err := p.From(); err == nil && pFrom == from && p.SigHash() == args.Tx.tx.SigHash() {
|
|
self.ethereum.TxPool().RemoveTx(common.HexToHash(args.Tx.Hash))
|
|
return self.xeth.Transact(args.Tx.From, args.Tx.To, args.Tx.Nonce, args.Tx.Value, args.GasLimit, args.GasPrice, args.Tx.Data)
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("Transaction %s not found", args.Tx.Hash)
|
|
}
|
|
|
|
func (self *ethApi) PendingTransactions(req *shared.Request) (interface{}, error) {
|
|
txs := self.ethereum.TxPool().GetTransactions()
|
|
|
|
// grab the accounts from the account manager. This will help with determining which
|
|
// transactions should be returned.
|
|
accounts, err := self.ethereum.AccountManager().Accounts()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Add the accouns to a new set
|
|
accountSet := set.New()
|
|
for _, account := range accounts {
|
|
accountSet.Add(account.Address)
|
|
}
|
|
|
|
var ltxs []*tx
|
|
for _, tx := range txs {
|
|
if from, _ := tx.From(); accountSet.Has(from) {
|
|
ltxs = append(ltxs, newTx(tx))
|
|
}
|
|
}
|
|
|
|
return ltxs, nil
|
|
}
|
|
|
|
func (self *ethApi) GetTransactionReceipt(req *shared.Request) (interface{}, error) {
|
|
args := new(HashArgs)
|
|
if err := self.codec.Decode(req.Params, &args); err != nil {
|
|
return nil, shared.NewDecodeParamError(err.Error())
|
|
}
|
|
|
|
txhash := common.BytesToHash(common.FromHex(args.Hash))
|
|
tx, bhash, bnum, txi := self.xeth.EthTransactionByHash(args.Hash)
|
|
rec := self.xeth.GetTxReceipt(txhash)
|
|
// We could have an error of "not found". Should disambiguate
|
|
// if err != nil {
|
|
// return err, nil
|
|
// }
|
|
if rec != nil && tx != nil {
|
|
v := NewReceiptRes(rec)
|
|
v.BlockHash = newHexData(bhash)
|
|
v.BlockNumber = newHexNum(bnum)
|
|
v.TransactionIndex = newHexNum(txi)
|
|
return v, nil
|
|
}
|
|
|
|
return nil, nil
|
|
}
|