aboutsummaryrefslogtreecommitdiffstats
path: root/rpc/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'rpc/util.go')
-rw-r--r--rpc/util.go74
1 files changed, 72 insertions, 2 deletions
diff --git a/rpc/util.go b/rpc/util.go
index 3e8ca3fef..8ff3c6d31 100644
--- a/rpc/util.go
+++ b/rpc/util.go
@@ -18,8 +18,11 @@ package rpc
import (
"encoding/json"
+ "fmt"
"io"
+ "math/big"
"net/http"
+ "reflect"
"time"
"github.com/ethereum/go-ethereum/ethutil"
@@ -32,9 +35,63 @@ var rpclogger = logger.NewLogger("RPC")
type JsonWrapper struct{}
+// Unmarshal state is a helper method which has the ability to decode messsages
+// that use the `defaultBlock` (https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter)
+// For example a `call`: [{to: "0x....", data:"0x..."}, "latest"]. The first argument is the transaction
+// message and the second one refers to the block height (or state) to which to apply this `call`.
+func UnmarshalRawMessages(b []byte, iface interface{}, number *int64) (err error) {
+ var data []json.RawMessage
+ if err = json.Unmarshal(b, &data); err != nil && len(data) == 0 {
+ return errDecodeArgs
+ }
+
+ // Number index determines the index in the array for a possible block number
+ numberIndex := 0
+
+ value := reflect.ValueOf(iface)
+ rvalue := reflect.Indirect(value)
+
+ switch rvalue.Kind() {
+ case reflect.Slice:
+ // This is a bit of a cheat, but `data` is expected to be larger than 2 if iface is a slice
+ if number != nil {
+ numberIndex = len(data) - 1
+ } else {
+ numberIndex = len(data)
+ }
+
+ slice := reflect.MakeSlice(rvalue.Type(), numberIndex, numberIndex)
+ for i, raw := range data[0:numberIndex] {
+ v := slice.Index(i).Interface()
+ if err = json.Unmarshal(raw, &v); err != nil {
+ fmt.Println(err, v)
+ return err
+ }
+ slice.Index(i).Set(reflect.ValueOf(v))
+ }
+ reflect.Indirect(rvalue).Set(slice) //value.Set(slice)
+ case reflect.Struct:
+ fallthrough
+ default:
+ if err = json.Unmarshal(data[0], iface); err != nil {
+ return errDecodeArgs
+ }
+ numberIndex = 1
+ }
+
+ // <0 index means out of bound for block number
+ if numberIndex >= 0 && len(data) > numberIndex {
+ if err = blockNumber(data[numberIndex], number); err != nil {
+ return errDecodeArgs
+ }
+ }
+
+ return nil
+}
+
func (self JsonWrapper) Send(writer io.Writer, v interface{}) (n int, err error) {
var payload []byte
- payload, err = json.Marshal(v)
+ payload, err = json.MarshalIndent(v, "", "\t")
if err != nil {
rpclogger.Fatalln("Error marshalling JSON", err)
return 0, err
@@ -63,18 +120,31 @@ func (self JsonWrapper) ParseRequestBody(req *http.Request) (RpcRequest, error)
}
func toHex(b []byte) string {
- return "0x" + ethutil.Bytes2Hex(b)
+ hex := ethutil.Bytes2Hex(b)
+ // Prefer output of "0x0" instead of "0x"
+ if len(hex) == 0 {
+ hex = "0"
+ }
+ return "0x" + hex
}
+
func fromHex(s string) []byte {
if len(s) > 1 {
if s[0:2] == "0x" {
s = s[2:]
}
+ if len(s)%2 == 1 {
+ s = "0" + s
+ }
return ethutil.Hex2Bytes(s)
}
return nil
}
+func i2hex(n int) string {
+ return toHex(big.NewInt(int64(n)).Bytes())
+}
+
type RpcServer interface {
Start()
Stop()