Commit 4c596809 authored by obscuren's avatar obscuren

Merge branch 'jsonrpc' into qt5.4

parents f3e78c8f 159c4d56
......@@ -15,3 +15,5 @@
.#*
*#
*~
.project
.settings
......@@ -40,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/websocket"
"github.com/ethereum/go-ethereum/xeth"
)
......@@ -200,6 +201,13 @@ func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
}
}
func StartWebSockets(eth *eth.Ethereum) {
clilogger.Infoln("Starting WebSockets")
sock := websocket.NewWebSocketServer(eth)
go sock.Serv()
}
var gminer *miner.Miner
func GetMiner() *miner.Miner {
......
package rpc
import (
"encoding/json"
)
type GetBlockArgs struct {
BlockNumber int32
Hash string
}
func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) {
argint, argstr := int32(0), ""
if err = json.Unmarshal(b, &argint); err == nil {
obj.BlockNumber = argint
return
}
if err = json.Unmarshal(b, &argstr); err == nil {
obj.Hash = argstr
return
}
return NewErrorResponse(ErrorDecodeArgs)
}
func (obj *GetBlockArgs) requirements() error {
if obj.BlockNumber == 0 && obj.Hash == "" {
return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument")
}
return nil
}
type NewTxArgs struct {
Sec string `json:"sec"`
Recipient string `json:"recipient"`
Value string `json:"value"`
Gas string `json:"gas"`
GasPrice string `json:"gasprice"`
Init string `json:"init"`
Body string `json:"body"`
}
// type TxResponse struct {
// Hash string
// }
func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
if err = json.Unmarshal(b, obj); err == nil {
return
}
return NewErrorResponse(ErrorDecodeArgs)
}
func (a *NewTxArgs) requirements() error {
if a.Recipient == "" {
return NewErrorResponse("Transact requires a 'recipient' address as argument")
}
if a.Value == "" {
return NewErrorResponse("Transact requires a 'value' as argument")
}
if a.Gas == "" {
return NewErrorResponse("Transact requires a 'gas' value as argument")
}
if a.GasPrice == "" {
return NewErrorResponse("Transact requires a 'gasprice' value as argument")
}
return nil
}
func (a *NewTxArgs) requirementsContract() error {
if a.Value == "" {
return NewErrorResponse("Create requires a 'value' as argument")
}
if a.Gas == "" {
return NewErrorResponse("Create requires a 'gas' value as argument")
}
if a.GasPrice == "" {
return NewErrorResponse("Create requires a 'gasprice' value as argument")
}
if a.Body == "" {
return NewErrorResponse("Create requires a 'body' value as argument")
}
return nil
}
type PushTxArgs struct {
Tx string `json:"tx"`
}
func (obj *PushTxArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := ""
if err = json.Unmarshal(b, arg0); err == nil {
obj.Tx = arg0
return
}
return NewErrorResponse(ErrorDecodeArgs)
}
func (a *PushTxArgs) requirementsPushTx() error {
if a.Tx == "" {
return NewErrorResponse("PushTx requires a 'tx' as argument")
}
return nil
}
type GetStorageArgs struct {
Address string
Key string
}
func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := ""
if err = json.Unmarshal(b, arg0); err == nil {
obj.Address = arg0
return
}
return NewErrorResponse(ErrorDecodeArgs)
}
func (a *GetStorageArgs) requirements() error {
if a.Address == "" {
return NewErrorResponse("GetStorageAt requires an 'address' value as argument")
}
if a.Key == "" {
return NewErrorResponse("GetStorageAt requires an 'key' value as argument")
}
return nil
}
type GetStorageAtRes struct {
Key string `json:"key"`
Value string `json:"value"`
Address string `json:"address"`
}
type GetTxCountArgs struct {
Address string `json:"address"`
}
// type GetTxCountRes struct {
// Nonce int `json:"nonce"`
// }
func (obj *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := ""
if err = json.Unmarshal(b, arg0); err == nil {
obj.Address = arg0
return
}
return NewErrorResponse("Could not determine JSON parameters")
}
func (a *GetTxCountArgs) requirements() error {
if a.Address == "" {
return NewErrorResponse("GetTxCountAt requires an 'address' value as argument")
}
return nil
}
// type GetPeerCountRes struct {
// PeerCount int `json:"peerCount"`
// }
// type GetListeningRes struct {
// IsListening bool `json:"isListening"`
// }
// type GetCoinbaseRes struct {
// Coinbase string `json:"coinbase"`
// }
// type GetMiningRes struct {
// IsMining bool `json:"isMining"`
// }
type GetBalanceArgs struct {
Address string
}
func (obj *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := ""
if err = json.Unmarshal(b, &arg0); err == nil {
obj.Address = arg0
return
}
return NewErrorResponse("Could not determine JSON parameters")
}
func (a *GetBalanceArgs) requirements() error {
if a.Address == "" {
return NewErrorResponse("GetBalanceAt requires an 'address' value as argument")
}
return nil
}
type BalanceRes struct {
Balance string `json:"balance"`
Address string `json:"address"`
}
type GetCodeAtArgs struct {
Address string
}
func (obj *GetCodeAtArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := ""
if err = json.Unmarshal(b, &arg0); err == nil {
obj.Address = arg0
return
}
return NewErrorResponse(ErrorDecodeArgs)
}
func (a *GetCodeAtArgs) requirements() error {
if a.Address == "" {
return NewErrorResponse("GetCodeAt requires an 'address' value as argument")
}
return nil
}
/*
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/>.
*/
package rpc
import (
"encoding/json"
"io"
"net/http"
)
type jsonWrapper struct{}
......@@ -11,10 +28,30 @@ func (self jsonWrapper) Send(writer io.Writer, v interface{}) (n int, err error)
var payload []byte
payload, err = json.Marshal(v)
if err != nil {
jsonlogger.Fatalln("Error marshalling JSON", err)
return 0, err
}
jsonlogger.Infof("Sending payload: %s", payload)
return writer.Write(payload)
}
func (self jsonWrapper) ParseRequestBody(req *http.Request) (RpcRequest, error) {
var reqParsed RpcRequest
// Convert JSON to native types
d := json.NewDecoder(req.Body)
// d.UseNumber()
defer req.Body.Close()
err := d.Decode(&reqParsed)
if err != nil {
jsonlogger.Errorln("Error decoding JSON: ", err)
return reqParsed, err
}
jsonlogger.DebugDetailf("Parsed request: %s", reqParsed)
return reqParsed, nil
}
var JSON jsonWrapper
/*
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/>.
*/
package rpc
import "github.com/ethereum/go-ethereum/ethutil"
import (
"bytes"
"encoding/json"
"errors"
)
const (
ErrorArguments = "Error: Insufficient arguments"
ErrorNotImplemented = "Error: Method not implemented"
ErrorUnknown = "Error: Unknown error"
ErrorParseRequest = "Error: Could not parse request"
ErrorDecodeArgs = "Error: Could not decode arguments"
)
type ErrorResponse struct {
Error bool `json:"error"`
ErrorText string `json:"errorText"`
}
type RpcSuccessResponse struct {
ID int `json:"id"`
JsonRpc string `json:"jsonrpc"`
Error bool `json:"error"`
Result interface{} `json:"result"`
}
type RpcErrorResponse struct {
ID int `json:"id"`
JsonRpc string `json:"jsonrpc"`
Error bool `json:"error"`
ErrorText string `json:"errortext"`
}
type RpcRequest struct {
JsonRpc string `json:"jsonrpc"`
ID int `json:"id"`
Method string `json:"method"`
Params []json.RawMessage `json:"params"`
}
func (req *RpcRequest) ToGetBlockArgs() (*GetBlockArgs, error) {
if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments)
}
args := new(GetBlockArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs)
}
jsonlogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToNewTxArgs() (*NewTxArgs, error) {
if len(req.Params) < 7 {
return nil, NewErrorResponse(ErrorArguments)
}
args := new(NewTxArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs)
}
jsonlogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToPushTxArgs() (*PushTxArgs, error) {
if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments)
}
args := new(PushTxArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs)
}
jsonlogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToGetStorageArgs() (*GetStorageArgs, error) {
if len(req.Params) < 2 {
return nil, NewErrorResponse(ErrorArguments)
}
args := new(GetStorageArgs)
// TODO need to pass both arguments
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs)
}
jsonlogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToGetTxCountArgs() (*GetTxCountArgs, error) {
if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments)
}
args := new(GetTxCountArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs)
}
jsonlogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToGetBalanceArgs() (*GetBalanceArgs, error) {
if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments)
}
args := new(GetBalanceArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs)
}
jsonlogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) {
if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments)
}
type Message struct {
Call string `json:"call"`
Args []interface{} `json:"args"`
Id int `json:"_id"`
Data interface{} `json:"data"`
args := new(GetCodeAtArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs)
}
jsonlogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (self *Message) Arguments() *ethutil.Value {
return ethutil.NewValue(self.Args)
func NewErrorResponse(msg string) error {
return errors.New(msg)
}
This diff is collapsed.
/*
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/>.
*/
package rpc
import (
"fmt"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"net/http"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/xeth"
......@@ -38,17 +53,14 @@ func (s *JsonRpcServer) Stop() {
func (s *JsonRpcServer) Start() {
jsonlogger.Infoln("Starting JSON-RPC server")
go s.exitHandler()
rpc.Register(&EthereumApi{pipe: s.pipe})
rpc.HandleHTTP()
for {
conn, err := s.listener.Accept()
h := apiHandler(&EthereumApi{pipe: s.pipe})
http.Handle("/", h)
err := http.Serve(s.listener, nil)
// FIX Complains on shutdown due to listner already being closed
if err != nil {
jsonlogger.Infoln("Error starting JSON-RPC:", err)
break
}
jsonlogger.Debugln("Incoming request.")
go jsonrpc.ServeConn(conn)
jsonlogger.Errorln("Error on JSON-RPC interface:", err)
}
}
......@@ -65,3 +77,28 @@ func NewJsonRpcServer(pipe *xeth.JSXEth, port int) (*JsonRpcServer, error) {
pipe: pipe,
}, nil
}
func apiHandler(xeth *EthereumApi) http.Handler {
fn := func(w http.ResponseWriter, req *http.Request) {
jsonlogger.Debugln("Handling request")
reqParsed, reqerr := JSON.ParseRequestBody(req)
if reqerr != nil {
JSON.Send(w, &RpcErrorResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: true, ErrorText: ErrorParseRequest})
return
}
var response interface{}
reserr := xeth.GetRequestReply(&reqParsed, &response)
if reserr != nil {
jsonlogger.Errorln(reserr)
JSON.Send(w, &RpcErrorResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: true, ErrorText: reserr.Error()})
return
}
jsonlogger.Debugf("Generated response: %T %s", response, response)
JSON.Send(w, &RpcSuccessResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: false, Result: response})
}
return http.HandlerFunc(fn)
}
package rpc
/*
func pack(id int, v ...interface{}) Message {
return Message{Data: v, Id: id}
}
func WriteOn(msg *Message, writer io.Writer) {
//msg := &Message{Seed: seed, Data: data}
switch msg.Call {
case "compile":
data := ethutil.NewValue(msg.Args)
bcode, err := ethutil.Compile(data.Get(0).Str(), false)
if err != nil {
JSON.Send(writer, pack(msg.Id, err.Error()))
}
code := ethutil.Bytes2Hex(bcode)
JSON.Send(writer, pack(msg.Id, code, nil))
case "block":
args := msg.Arguments()
block := pipe.BlockByNumber(int32(args.Get(0).Uint()))
JSON.Send(writer, pack(msg.Id, block))
case "transact":
if mp, ok := msg.Args[0].(map[string]interface{}); ok {
object := mapToTxParams(mp)
JSON.Send(
writer,
pack(msg.Id, args(pipe.Transact(object["from"], object["to"], object["value"], object["gas"], object["gasPrice"], object["data"]))),
)
}
case "coinbase":
JSON.Send(writer, pack(msg.Id, pipe.CoinBase(), msg.Seed))
case "listening":
JSON.Send(writer, pack(msg.Id, pipe.IsListening()))
case "mining":
JSON.Send(writer, pack(msg.Id, pipe.IsMining()))
case "peerCoint":
JSON.Send(writer, pack(msg.Id, pipe.PeerCount()))
case "countAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, pipe.TxCountAt(args.Get(0).Str())))
case "codeAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, len(pipe.CodeAt(args.Get(0).Str()))))
case "stateAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str())))
case "balanceAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, pipe.BalanceAt(args.Get(0).Str())))
case "newFilter":
case "newFilterString":
case "messages":
// TODO
}
}
*/
......@@ -172,47 +172,47 @@ func RunVmTest(p string, t *testing.T) {
// I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail.
func TestVMArithmetic(t *testing.T) {
const fn = "../files/vmtests/vmArithmeticTest.json"
const fn = "../files/VMTests/vmArithmeticTest.json"
RunVmTest(fn, t)
}
func TestBitwiseLogicOperation(t *testing.T) {
const fn = "../files/vmtests/vmBitwiseLogicOperationTest.json"
const fn = "../files/VMTests/vmBitwiseLogicOperationTest.json"
RunVmTest(fn, t)
}
func TestBlockInfo(t *testing.T) {
const fn = "../files/vmtests/vmBlockInfoTest.json"
const fn = "../files/VMTests/vmBlockInfoTest.json"
RunVmTest(fn, t)
}
func TestEnvironmentalInfo(t *testing.T) {
const fn = "../files/vmtests/vmEnvironmentalInfoTest.json"
const fn = "../files/VMTests/vmEnvironmentalInfoTest.json"
RunVmTest(fn, t)
}
func TestFlowOperation(t *testing.T) {
const fn = "../files/vmtests/vmIOandFlowOperationsTest.json"
const fn = "../files/VMTests/vmIOandFlowOperationsTest.json"
RunVmTest(fn, t)
}
func TestPushDupSwap(t *testing.T) {
const fn = "../files/vmtests/vmPushDupSwapTest.json"
const fn = "../files/VMTests/vmPushDupSwapTest.json"
RunVmTest(fn, t)
}
func TestVMSha3(t *testing.T) {
const fn = "../files/vmtests/vmSha3Test.json"
const fn = "../files/VMTests/vmSha3Test.json"
RunVmTest(fn, t)
}
func TestVm(t *testing.T) {
const fn = "../files/vmtests/vmtests.json"
const fn = "../files/VMTests/vmtests.json"
RunVmTest(fn, t)
}
func TestVmLog(t *testing.T) {
const fn = "../files/vmtests/vmLogTest.json"
const fn = "../files/VMTests/vmLogTest.json"
RunVmTest(fn, t)
}
......
This diff is collapsed.
// +build !evmjit
package vm
import "fmt"
func NewJitVm(env Environment) VirtualMachine {
fmt.Printf("Warning! EVM JIT not enabled.\n")
return New(env)
}
......@@ -14,11 +14,7 @@
You should have received a copy of the GNU General Public License
along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @authors
* Jeffrey Wilcke <i@jev.io>
*/
package utils
package websocket
import (
"github.com/ethereum/go-ethereum/core"
......@@ -26,15 +22,11 @@ import (
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/ui"
"github.com/ethereum/go-ethereum/websocket"
"github.com/ethereum/go-ethereum/xeth"
)
var wslogger = logger.NewLogger("WS")
func args(v ...interface{}) []interface{} {
return v
}
......@@ -54,8 +46,8 @@ func NewWebSocketServer(eth *eth.Ethereum) *WebSocketServer {
func (self *WebSocketServer) Serv() {
pipe := xeth.NewJSXEth(self.eth)
wsServ := websocket.NewServer("/eth", ":40404")
wsServ.MessageFunc(func(c *websocket.Client, msg *websocket.Message) {
wsServ := NewServer("/eth", ":40404")
wsServ.MessageFunc(func(c *Client, msg *Message) {
switch msg.Call {
case "compile":
data := ethutil.NewValue(msg.Args)
......@@ -162,13 +154,6 @@ func toMessages(messages state.Messages) (msgs []xeth.JSMessage) {
return
}
func StartWebSockets(eth *eth.Ethereum) {
wslogger.Infoln("Starting WebSockets")
sock := NewWebSocketServer(eth)
go sock.Serv()
}
// TODO This is starting to become a generic method. Move to utils
func mapToTxParams(object map[string]interface{}) map[string]string {
// Default values
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment