go-ethereum/rpc/packages.go

237 lines
5.8 KiB
Go
Raw Normal View History

2015-01-13 09:13:43 -06:00
/*
This file is part of go-ethereum
go-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
go-ethereum 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
2015-01-12 23:44:56 -06:00
/*
For each request type, define the following:
1. RpcRequest "To" method [message.go], which does basic validation and conversion to "Args" type via json.Decoder()
2015-01-28 11:35:49 -06:00
2. json.Decoder() calls "UnmarshalON" defined on each "Args" struct
3. EthereumApi method, taking the "Args" type and replying with an interface to be marshalled to ON
2015-01-12 23:44:56 -06:00
*/
2014-10-21 06:24:48 -05:00
package rpc
import (
"fmt"
2014-10-21 06:24:48 -05:00
"math/big"
"strings"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
2014-10-31 08:30:08 -05:00
"github.com/ethereum/go-ethereum/xeth"
2014-10-21 06:24:48 -05:00
)
type RpcServer interface {
Start()
Stop()
}
2015-01-28 11:35:49 -06:00
func NewEthereumApi(xeth *xeth.XEth) *EthereumApi {
2015-01-28 11:14:28 -06:00
return &EthereumApi{xeth: xeth}
}
2014-10-21 06:24:48 -05:00
type EthereumApi struct {
2015-01-28 11:35:49 -06:00
xeth *xeth.XEth
2014-10-21 06:24:48 -05:00
}
func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error {
err := args.requirements()
if err != nil {
return err
}
2014-10-21 06:24:48 -05:00
if args.BlockNumber > 0 {
2015-01-28 11:14:28 -06:00
*reply = p.xeth.BlockByNumber(args.BlockNumber)
} else {
2015-01-28 11:14:28 -06:00
*reply = p.xeth.BlockByHash(args.Hash)
}
return nil
2014-10-21 06:24:48 -05:00
}
func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
err := args.requirements()
if err != nil {
return err
}
result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
*reply = result
return nil
}
func (p *EthereumApi) Call(args *NewTxArgs, reply *interface{}) error {
result, err := p.xeth.Call( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
if err != nil {
return err
}
*reply = result
return nil
2014-10-21 06:24:48 -05:00
}
func (p *EthereumApi) PushTx(args *PushTxArgs, reply *interface{}) error {
err := args.requirementsPushTx()
2014-10-21 06:24:48 -05:00
if err != nil {
return err
2014-10-21 06:24:48 -05:00
}
2015-01-28 11:14:28 -06:00
result, _ := p.xeth.PushTx(args.Tx)
*reply = result
return nil
2014-10-21 06:24:48 -05:00
}
func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) error {
err := args.requirements()
2014-10-21 06:24:48 -05:00
if err != nil {
return err
2014-10-21 06:24:48 -05:00
}
2015-01-28 11:14:28 -06:00
state := p.xeth.State().SafeGet(args.Address)
var hx string
if strings.Index(args.Key, "0x") == 0 {
hx = string([]byte(args.Key)[2:])
} else {
// Convert the incoming string (which is a bigint) into hex
i, _ := new(big.Int).SetString(args.Key, 10)
hx = ethutil.Bytes2Hex(i.Bytes())
}
rpclogger.Debugf("GetStorageAt(%s, %s)\n", args.Address, hx)
value := state.Storage(ethutil.Hex2Bytes(hx))
*reply = GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value.Str()}
return nil
2014-10-21 06:24:48 -05:00
}
func (p *EthereumApi) GetPeerCount(reply *interface{}) error {
2015-01-28 11:14:28 -06:00
*reply = p.xeth.PeerCount()
return nil
}
func (p *EthereumApi) GetIsListening(reply *interface{}) error {
2015-01-28 11:14:28 -06:00
*reply = p.xeth.IsListening()
return nil
}
func (p *EthereumApi) GetCoinbase(reply *interface{}) error {
2015-01-28 11:14:28 -06:00
*reply = p.xeth.Coinbase()
return nil
}
func (p *EthereumApi) GetIsMining(reply *interface{}) error {
2015-01-28 11:14:28 -06:00
*reply = p.xeth.IsMining()
return nil
}
func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) error {
err := args.requirements()
if err != nil {
return err
2014-10-21 06:24:48 -05:00
}
2015-01-28 11:14:28 -06:00
*reply = p.xeth.TxCountAt(args.Address)
2014-10-21 06:24:48 -05:00
return nil
}
func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *interface{}) error {
2014-10-21 06:24:48 -05:00
err := args.requirements()
if err != nil {
return err
}
2015-01-28 11:14:28 -06:00
state := p.xeth.State().SafeGet(args.Address)
*reply = BalanceRes{Balance: state.Balance().String(), Address: args.Address}
return nil
}
2015-01-13 09:27:36 -06:00
func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error {
err := args.requirements()
if err != nil {
return err
}
2015-01-28 11:14:28 -06:00
*reply = p.xeth.CodeAt(args.Address)
2015-01-13 09:27:36 -06:00
return nil
}
func (p *EthereumApi) Sha3(args *Sha3Args, reply *interface{}) error {
*reply = ethutil.Bytes2Hex(crypto.Sha3(ethutil.Hex2Bytes(args.Data)))
return nil
}
func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error {
2015-01-28 11:35:49 -06:00
// Spec at https://github.com/ethereum/wiki/wiki/Generic-ON-RPC
rpclogger.DebugDetailf("%T %s", req.Params, req.Params)
switch req.Method {
case "eth_coinbase":
return p.GetCoinbase(reply)
case "eth_listening":
return p.GetIsListening(reply)
case "eth_mining":
return p.GetIsMining(reply)
case "eth_peerCount":
return p.GetPeerCount(reply)
case "eth_countAt":
args, err := req.ToGetTxCountArgs()
if err != nil {
return err
}
return p.GetTxCountAt(args, reply)
case "eth_codeAt":
args, err := req.ToGetCodeAtArgs()
if err != nil {
return err
}
return p.GetCodeAt(args, reply)
case "eth_balanceAt":
args, err := req.ToGetBalanceArgs()
if err != nil {
return err
}
return p.GetBalanceAt(args, reply)
case "eth_stateAt":
args, err := req.ToGetStorageArgs()
if err != nil {
return err
}
return p.GetStorageAt(args, reply)
case "eth_blockByNumber", "eth_blockByHash":
args, err := req.ToGetBlockArgs()
if err != nil {
return err
}
return p.GetBlock(args, reply)
2015-01-29 05:01:51 -06:00
case "eth_transact":
args, err := req.ToNewTxArgs()
if err != nil {
return err
}
return p.Transact(args, reply)
case "eth_call":
args, err := req.ToNewTxArgs()
if err != nil {
return err
}
return p.Call(args, reply)
case "web3_sha3":
args, err := req.ToSha3Args()
if err != nil {
return err
}
return p.Sha3(args, reply)
default:
return NewErrorResponse(fmt.Sprintf("%v %s", ErrorNotImplemented, req.Method))
}
rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
2015-01-13 09:27:36 -06:00
return nil
}