aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Godeps/Godeps.json14
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/LICENSE27
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/README.md14
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext.go27
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go20
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go28
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go79
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_test.go79
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go34
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/.travis.yml4
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/LICENSE19
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/README.md84
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/bench_test.go37
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/cors.go308
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/cors_test.go288
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go24
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go18
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go22
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go23
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go26
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go20
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go22
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/utils.go27
-rw-r--r--Godeps/_workspace/src/github.com/rs/cors/utils_test.go28
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/client.go113
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go31
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go26
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go564
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go590
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/server.go114
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go411
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/websocket_test.go414
-rw-r--r--accounts/account_manager.go2
-rw-r--r--cmd/geth/js.go172
-rw-r--r--cmd/geth/js_test.go101
-rw-r--r--cmd/geth/main.go51
-rw-r--r--cmd/geth/monitorcmd.go47
-rw-r--r--cmd/geth/usage.go8
-rw-r--r--cmd/gethrpctest/main.go53
-rw-r--r--cmd/utils/api.go74
-rw-r--r--cmd/utils/client.go176
-rw-r--r--cmd/utils/flags.go157
-rw-r--r--cmd/utils/jeth.go (renamed from rpc/jeth.go)81
-rw-r--r--common/natspec/natspec.go2
-rw-r--r--common/natspec/natspec_e2e_test.go2
-rw-r--r--common/natspec/natspec_test.go2
-rw-r--r--common/registrar/ethreg/api.go265
-rw-r--r--common/registrar/ethreg/ethreg.go48
-rw-r--r--docker/Dockerfile21
-rw-r--r--docker/develop/Dockerfile17
-rw-r--r--docker/master/Dockerfile17
-rw-r--r--eth/api.go97
-rw-r--r--eth/backend.go36
-rw-r--r--eth/downloader/api.go2
-rw-r--r--eth/filters/api.go2
-rw-r--r--jsre/ethereum_js.go4
-rw-r--r--light/state_object.go2
-rw-r--r--logger/glog/glog.go94
-rw-r--r--logger/glog/glog_test.go51
-rw-r--r--miner/api.go2
-rw-r--r--node/api.go118
-rw-r--r--node/node.go7
-rw-r--r--node/node_example_test.go2
-rw-r--r--node/service.go2
-rw-r--r--node/utils_test.go2
-rw-r--r--rpc/api/admin.go477
-rw-r--r--rpc/api/admin_args.go490
-rw-r--r--rpc/api/admin_js.go149
-rw-r--r--rpc/api/api.go26
-rw-r--r--rpc/api/api_test.go170
-rw-r--r--rpc/api/args.go74
-rw-r--r--rpc/api/args_test.go2649
-rw-r--r--rpc/api/db.go144
-rw-r--r--rpc/api/db_args.go126
-rw-r--r--rpc/api/db_js.go29
-rw-r--r--rpc/api/debug.go303
-rw-r--r--rpc/api/debug_args.go87
-rw-r--r--rpc/api/debug_js.go71
-rw-r--r--rpc/api/eth.go721
-rw-r--r--rpc/api/eth_args.go1104
-rw-r--r--rpc/api/eth_js.go66
-rw-r--r--rpc/api/mergedapi.go88
-rw-r--r--rpc/api/miner.go177
-rw-r--r--rpc/api/miner_args.go142
-rw-r--r--rpc/api/miner_js.go83
-rw-r--r--rpc/api/net.go99
-rw-r--r--rpc/api/net_js.go39
-rw-r--r--rpc/api/parsing.go522
-rw-r--r--rpc/api/personal.go139
-rw-r--r--rpc/api/personal_args.go85
-rw-r--r--rpc/api/personal_js.go51
-rw-r--r--rpc/api/shh.go196
-rw-r--r--rpc/api/shh_args.go174
-rw-r--r--rpc/api/shh_js.go34
-rw-r--r--rpc/api/txpool.go92
-rw-r--r--rpc/api/txpool_js.go33
-rw-r--r--rpc/api/utils.go226
-rw-r--r--rpc/api/web3.go99
-rw-r--r--rpc/codec/codec.go65
-rw-r--r--rpc/codec/json.go149
-rw-r--r--rpc/codec/json_test.go157
-rw-r--r--rpc/comms/comms.go150
-rw-r--r--rpc/comms/http.go345
-rw-r--r--rpc/comms/inproc.go82
-rw-r--r--rpc/comms/ipc.go158
-rw-r--r--rpc/comms/ipc_unix.go82
-rw-r--r--rpc/doc.go (renamed from rpc/v2/doc.go)128
-rw-r--r--rpc/errors.go (renamed from rpc/v2/errors.go)14
-rw-r--r--rpc/http.go368
-rw-r--r--rpc/ipc.go84
-rw-r--r--rpc/ipc_unix.go (renamed from rpc/api/web3_args.go)42
-rw-r--r--rpc/ipc_windows.go (renamed from rpc/comms/ipc_windows.go)56
-rw-r--r--rpc/javascript.go414
-rw-r--r--rpc/json.go (renamed from rpc/v2/json.go)28
-rw-r--r--rpc/json_test.go (renamed from rpc/v2/json_test.go)2
-rw-r--r--rpc/server.go (renamed from rpc/v2/server.go)61
-rw-r--r--rpc/server_test.go (renamed from rpc/v2/server_test.go)32
-rw-r--r--rpc/shared/errors.go126
-rw-r--r--rpc/shared/types.go108
-rw-r--r--rpc/shared/utils.go43
-rw-r--r--rpc/types.go (renamed from rpc/v2/types.go)18
-rw-r--r--rpc/types_test.go (renamed from rpc/v2/types_test.go)18
-rw-r--r--rpc/useragent/agent.go24
-rw-r--r--rpc/useragent/remote_frontend.go166
-rw-r--r--rpc/utils.go (renamed from rpc/v2/utils.go)34
-rw-r--r--rpc/websocket.go235
-rw-r--r--rpc/xeth.go77
-rw-r--r--whisper/api.go2
-rw-r--r--whisper/whisper.go2
-rw-r--r--xeth/frontend.go48
-rw-r--r--xeth/state.go51
-rw-r--r--xeth/types.go237
-rw-r--r--xeth/whisper.go121
-rw-r--r--xeth/whisper_filter.go100
-rw-r--r--xeth/whisper_message.go53
-rw-r--r--xeth/xeth.go1137
-rw-r--r--xeth/xeth_test.go26
137 files changed, 4842 insertions, 14418 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 06f4b3b2d..b5703f7f2 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1,6 +1,6 @@
{
"ImportPath": "github.com/ethereum/go-ethereum",
- "GoVersion": "go1.4",
+ "GoVersion": "go1.5.2",
"Packages": [
"./..."
],
@@ -41,10 +41,6 @@
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
},
{
- "ImportPath": "github.com/kardianos/osext",
- "Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
- },
- {
"ImportPath": "github.com/mattn/go-isatty",
"Rev": "7fcbc72f853b92b5720db4a6b8482be612daef24"
},
@@ -74,10 +70,6 @@
"Rev": "dea31a3d392779af358ec41f77a07fcc7e9d04ba"
},
{
- "ImportPath": "github.com/rs/cors",
- "Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb"
- },
- {
"ImportPath": "github.com/shiena/ansicolor",
"Rev": "a5e2b567a4dd6cc74545b8a4f27c9d63b9e7735b"
},
@@ -110,6 +102,10 @@
"Rev": "e0403b4e005737430c05a57aac078479844f919c"
},
{
+ "ImportPath": "golang.org/x/net/websocket",
+ "Rev": "e0403b4e005737430c05a57aac078479844f919c"
+ },
+ {
"ImportPath": "golang.org/x/text/encoding",
"Rev": "c93e7c9fff19fb9139b5ab04ce041833add0134e"
},
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/LICENSE b/Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
deleted file mode 100644
index 744875676..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2012 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/README.md b/Godeps/_workspace/src/github.com/kardianos/osext/README.md
deleted file mode 100644
index 820e1ecb5..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-### Extensions to the "os" package.
-
-## Find the current Executable and ExecutableFolder.
-
-There is sometimes utility in finding the current executable file
-that is running. This can be used for upgrading the current executable
-or finding resources located relative to the executable file.
-
-Multi-platform and supports:
- * Linux
- * OS X
- * Windows
- * Plan 9
- * BSDs.
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/osext.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext.go
deleted file mode 100644
index 4ed4b9aa3..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/osext.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Extensions to the standard "os" package.
-package osext
-
-import "path/filepath"
-
-// Executable returns an absolute path that can be used to
-// re-invoke the current program.
-// It may not be valid after the current program exits.
-func Executable() (string, error) {
- p, err := executable()
- return filepath.Clean(p), err
-}
-
-// Returns same path as Executable, returns just the folder
-// path. Excludes the executable name.
-func ExecutableFolder() (string, error) {
- p, err := Executable()
- if err != nil {
- return "", err
- }
- folder, _ := filepath.Split(p)
- return folder, nil
-}
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go
deleted file mode 100644
index 655750c54..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package osext
-
-import (
- "os"
- "strconv"
- "syscall"
-)
-
-func executable() (string, error) {
- f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
- if err != nil {
- return "", err
- }
- defer f.Close()
- return syscall.Fd2path(int(f.Fd()))
-}
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go
deleted file mode 100644
index a50021ad5..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build linux netbsd openbsd solaris dragonfly
-
-package osext
-
-import (
- "errors"
- "fmt"
- "os"
- "runtime"
-)
-
-func executable() (string, error) {
- switch runtime.GOOS {
- case "linux":
- return os.Readlink("/proc/self/exe")
- case "netbsd":
- return os.Readlink("/proc/curproc/exe")
- case "openbsd", "dragonfly":
- return os.Readlink("/proc/curproc/file")
- case "solaris":
- return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
- }
- return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
-}
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
deleted file mode 100644
index b66cac878..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin freebsd
-
-package osext
-
-import (
- "os"
- "path/filepath"
- "runtime"
- "syscall"
- "unsafe"
-)
-
-var initCwd, initCwdErr = os.Getwd()
-
-func executable() (string, error) {
- var mib [4]int32
- switch runtime.GOOS {
- case "freebsd":
- mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
- case "darwin":
- mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
- }
-
- n := uintptr(0)
- // Get length.
- _, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
- if errNum != 0 {
- return "", errNum
- }
- if n == 0 { // This shouldn't happen.
- return "", nil
- }
- buf := make([]byte, n)
- _, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
- if errNum != 0 {
- return "", errNum
- }
- if n == 0 { // This shouldn't happen.
- return "", nil
- }
- for i, v := range buf {
- if v == 0 {
- buf = buf[:i]
- break
- }
- }
- var err error
- execPath := string(buf)
- // execPath will not be empty due to above checks.
- // Try to get the absolute path if the execPath is not rooted.
- if execPath[0] != '/' {
- execPath, err = getAbs(execPath)
- if err != nil {
- return execPath, err
- }
- }
- // For darwin KERN_PROCARGS may return the path to a symlink rather than the
- // actual executable.
- if runtime.GOOS == "darwin" {
- if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
- return execPath, err
- }
- }
- return execPath, nil
-}
-
-func getAbs(execPath string) (string, error) {
- if initCwdErr != nil {
- return execPath, initCwdErr
- }
- // The execPath may begin with a "../" or a "./" so clean it first.
- // Join the two paths, trailing and starting slashes undetermined, so use
- // the generic Join function.
- return filepath.Join(initCwd, filepath.Clean(execPath)), nil
-}
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/osext_test.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_test.go
deleted file mode 100644
index dc661dbc2..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/osext_test.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin linux freebsd netbsd windows
-
-package osext
-
-import (
- "fmt"
- "os"
- oexec "os/exec"
- "path/filepath"
- "runtime"
- "testing"
-)
-
-const execPath_EnvVar = "OSTEST_OUTPUT_EXECPATH"
-
-func TestExecPath(t *testing.T) {
- ep, err := Executable()
- if err != nil {
- t.Fatalf("ExecPath failed: %v", err)
- }
- // we want fn to be of the form "dir/prog"
- dir := filepath.Dir(filepath.Dir(ep))
- fn, err := filepath.Rel(dir, ep)
- if err != nil {
- t.Fatalf("filepath.Rel: %v", err)
- }
- cmd := &oexec.Cmd{}
- // make child start with a relative program path
- cmd.Dir = dir
- cmd.Path = fn
- // forge argv[0] for child, so that we can verify we could correctly
- // get real path of the executable without influenced by argv[0].
- cmd.Args = []string{"-", "-test.run=XXXX"}
- cmd.Env = []string{fmt.Sprintf("%s=1", execPath_EnvVar)}
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("exec(self) failed: %v", err)
- }
- outs := string(out)
- if !filepath.IsAbs(outs) {
- t.Fatalf("Child returned %q, want an absolute path", out)
- }
- if !sameFile(outs, ep) {
- t.Fatalf("Child returned %q, not the same file as %q", out, ep)
- }
-}
-
-func sameFile(fn1, fn2 string) bool {
- fi1, err := os.Stat(fn1)
- if err != nil {
- return false
- }
- fi2, err := os.Stat(fn2)
- if err != nil {
- return false
- }
- return os.SameFile(fi1, fi2)
-}
-
-func init() {
- if e := os.Getenv(execPath_EnvVar); e != "" {
- // first chdir to another path
- dir := "/"
- if runtime.GOOS == "windows" {
- dir = filepath.VolumeName(".")
- }
- os.Chdir(dir)
- if ep, err := Executable(); err != nil {
- fmt.Fprint(os.Stderr, "ERROR: ", err)
- } else {
- fmt.Fprint(os.Stderr, ep)
- }
- os.Exit(0)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go
deleted file mode 100644
index 72d282cf8..000000000
--- a/Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package osext
-
-import (
- "syscall"
- "unicode/utf16"
- "unsafe"
-)
-
-var (
- kernel = syscall.MustLoadDLL("kernel32.dll")
- getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
-)
-
-// GetModuleFileName() with hModule = NULL
-func executable() (exePath string, err error) {
- return getModuleFileName()
-}
-
-func getModuleFileName() (string, error) {
- var n uint32
- b := make([]uint16, syscall.MAX_PATH)
- size := uint32(len(b))
-
- r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
- n = uint32(r0)
- if n == 0 {
- return "", e1
- }
- return string(utf16.Decode(b[0:n])), nil
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/.travis.yml b/Godeps/_workspace/src/github.com/rs/cors/.travis.yml
deleted file mode 100644
index bbb5185a2..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/.travis.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-language: go
-go:
-- 1.3
-- 1.4
diff --git a/Godeps/_workspace/src/github.com/rs/cors/LICENSE b/Godeps/_workspace/src/github.com/rs/cors/LICENSE
deleted file mode 100644
index d8e2df5a4..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2014 Olivier Poitrey <rs@dailymotion.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is furnished
-to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/Godeps/_workspace/src/github.com/rs/cors/README.md b/Godeps/_workspace/src/github.com/rs/cors/README.md
deleted file mode 100644
index 6f70c30ac..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/README.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![build](https://img.shields.io/travis/rs/cors.svg?style=flat)](https://travis-ci.org/rs/cors)
-
-CORS is a `net/http` handler implementing [Cross Origin Resource Sharing W3 specification](http://www.w3.org/TR/cors/) in Golang.
-
-## Getting Started
-
-After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`.
-
-```go
-package main
-
-import (
- "net/http"
-
- "github.com/rs/cors"
-)
-
-func main() {
- h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- // cors.Default() setup the middleware with default options being
- // all origins accepted with simple methods (GET, POST). See
- // documentation below for more options.
- handler = cors.Default().Handler(h)
- http.ListenAndServe(":8080", handler)
-}
-```
-
-Install `cors`:
-
- go get github.com/rs/cors
-
-Then run your server:
-
- go run server.go
-
-The server now runs on `localhost:8080`:
-
- $ curl -D - -H 'Origin: http://foo.com' http://localhost:8080/
- HTTP/1.1 200 OK
- Access-Control-Allow-Origin: foo.com
- Content-Type: application/json
- Date: Sat, 25 Oct 2014 03:43:57 GMT
- Content-Length: 18
-
- {"hello": "world"}
-
-### More Examples
-
-* `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go)
-* [Goji](https://goji.io): [examples/goji/server.go](https://github.com/rs/cors/blob/master/examples/goji/server.go)
-* [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go)
-* [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go)
-* [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go)
-
-## Parameters
-
-Parameters are passed to the middleware thru the `cors.New` method as follow:
-
-```go
-c := cors.New(cors.Options{
- AllowedOrigins: []string{"http://foo.com"},
- AllowCredentials: true,
-})
-
-// Insert the middleware
-handler = c.Handler(handler)
-```
-
-* **AllowedOrigins** `[]string`: A list of origins a cross-domain request can be executed from. If the special `*` value is present in the list, all origins will be allowed. The default value is `*`.
-* **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests.
-* **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`)
-* **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification
-* **AllowCredentials** `bool`: Indicates whether the request can include user credentials like cookies, HTTP authentication or client side SSL certificates. The default is `false`.
-* **MaxAge** `int`: Indicates how long (in seconds) the results of a preflight request can be cached. The default is `0` which stands for no max age.
-
-See [API documentation](http://godoc.org/github.com/rs/cors) for more info.
-
-## Licenses
-
-All source code is licensed under the [MIT License](https://raw.github.com/rs/cors/master/LICENSE).
diff --git a/Godeps/_workspace/src/github.com/rs/cors/bench_test.go b/Godeps/_workspace/src/github.com/rs/cors/bench_test.go
deleted file mode 100644
index 454375d2c..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/bench_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package cors
-
-import (
- "net/http"
- "net/http/httptest"
- "testing"
-)
-
-func BenchmarkWithout(b *testing.B) {
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
-
- for i := 0; i < b.N; i++ {
- testHandler.ServeHTTP(res, req)
- }
-}
-
-func BenchmarkDefault(b *testing.B) {
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- handler := Default()
-
- for i := 0; i < b.N; i++ {
- handler.Handler(testHandler).ServeHTTP(res, req)
- }
-}
-
-func BenchmarkPreflight(b *testing.B) {
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Access-Control-Request-Method", "GET")
- handler := Default()
-
- for i := 0; i < b.N; i++ {
- handler.Handler(testHandler).ServeHTTP(res, req)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/cors.go b/Godeps/_workspace/src/github.com/rs/cors/cors.go
deleted file mode 100644
index 276bc40bb..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/cors.go
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
-Package cors is net/http handler to handle CORS related requests
-as defined by http://www.w3.org/TR/cors/
-
-You can configure it by passing an option struct to cors.New:
-
- c := cors.New(cors.Options{
- AllowedOrigins: []string{"foo.com"},
- AllowedMethods: []string{"GET", "POST", "DELETE"},
- AllowCredentials: true,
- })
-
-Then insert the handler in the chain:
-
- handler = c.Handler(handler)
-
-See Options documentation for more options.
-
-The resulting handler is a standard net/http handler.
-*/
-package cors
-
-import (
- "log"
- "net/http"
- "os"
- "strconv"
- "strings"
-)
-
-// Options is a configuration container to setup the CORS middleware.
-type Options struct {
- // AllowedOrigins is a list of origins a cross-domain request can be executed from.
- // If the special "*" value is present in the list, all origins will be allowed.
- // Default value is ["*"]
- AllowedOrigins []string
- // AllowedMethods is a list of methods the client is allowed to use with
- // cross-domain requests. Default value is simple methods (GET and POST)
- AllowedMethods []string
- // AllowedHeaders is list of non simple headers the client is allowed to use with
- // cross-domain requests.
- // If the special "*" value is present in the list, all headers will be allowed.
- // Default value is [] but "Origin" is always appended to the list.
- AllowedHeaders []string
- // ExposedHeaders indicates which headers are safe to expose to the API of a CORS
- // API specification
- ExposedHeaders []string
- // AllowCredentials indicates whether the request can include user credentials like
- // cookies, HTTP authentication or client side SSL certificates.
- AllowCredentials bool
- // MaxAge indicates how long (in seconds) the results of a preflight request
- // can be cached
- MaxAge int
- // Debugging flag adds additional output to debug server side CORS issues
- Debug bool
- // log object to use when debugging
- log *log.Logger
-}
-
-type Cors struct {
- // The CORS Options
- options Options
-}
-
-// New creates a new Cors handler with the provided options.
-func New(options Options) *Cors {
- // Normalize options
- // Note: for origins and methods matching, the spec requires a case-sensitive matching.
- // As it may error prone, we chose to ignore the spec here.
- normOptions := Options{
- AllowedOrigins: convert(options.AllowedOrigins, strings.ToLower),
- AllowedMethods: convert(options.AllowedMethods, strings.ToUpper),
- // Origin is always appended as some browsers will always request
- // for this header at preflight
- AllowedHeaders: convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey),
- ExposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey),
- AllowCredentials: options.AllowCredentials,
- MaxAge: options.MaxAge,
- Debug: options.Debug,
- log: log.New(os.Stdout, "[cors] ", log.LstdFlags),
- }
- if len(normOptions.AllowedOrigins) == 0 {
- // Default is all origins
- normOptions.AllowedOrigins = []string{"*"}
- }
- if len(normOptions.AllowedHeaders) == 1 {
- // Add some sensible defaults
- normOptions.AllowedHeaders = []string{"Origin", "Accept", "Content-Type"}
- }
- if len(normOptions.AllowedMethods) == 0 {
- // Default is simple methods
- normOptions.AllowedMethods = []string{"GET", "POST"}
- }
-
- if normOptions.Debug {
- normOptions.log.Printf("Options: %v", normOptions)
- }
- return &Cors{
- options: normOptions,
- }
-}
-
-// Default creates a new Cors handler with default options
-func Default() *Cors {
- return New(Options{})
-}
-
-// Handler apply the CORS specification on the request, and add relevant CORS headers
-// as necessary.
-func (cors *Cors) Handler(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if r.Method == "OPTIONS" {
- cors.logf("Handler: Preflight request")
- cors.handlePreflight(w, r)
- // Preflight requests are standalone and should stop the chain as some other
- // middleware may not handle OPTIONS requests correctly. One typical example
- // is authentication middleware ; OPTIONS requests won't carry authentication
- // headers (see #1)
- } else {
- cors.logf("Handler: Actual request")
- cors.handleActualRequest(w, r)
- h.ServeHTTP(w, r)
- }
- })
-}
-
-// Martini compatible handler
-func (cors *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) {
- if r.Method == "OPTIONS" {
- cors.logf("HandlerFunc: Preflight request")
- cors.handlePreflight(w, r)
- } else {
- cors.logf("HandlerFunc: Actual request")
- cors.handleActualRequest(w, r)
- }
-}
-
-// Negroni compatible interface
-func (cors *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
- if r.Method == "OPTIONS" {
- cors.logf("ServeHTTP: Preflight request")
- cors.handlePreflight(w, r)
- // Preflight requests are standalone and should stop the chain as some other
- // middleware may not handle OPTIONS requests correctly. One typical example
- // is authentication middleware ; OPTIONS requests won't carry authentication
- // headers (see #1)
- } else {
- cors.logf("ServeHTTP: Actual request")
- cors.handleActualRequest(w, r)
- next(w, r)
- }
-}
-
-// handlePreflight handles pre-flight CORS requests
-func (cors *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
- options := cors.options
- headers := w.Header()
- origin := r.Header.Get("Origin")
-
- if r.Method != "OPTIONS" {
- cors.logf(" Preflight aborted: %s!=OPTIONS", r.Method)
- return
- }
- if origin == "" {
- cors.logf(" Preflight aborted: empty origin")
- return
- }
- if !cors.isOriginAllowed(origin) {
- cors.logf(" Preflight aborted: origin '%s' not allowed", origin)
- return
- }
-
- reqMethod := r.Header.Get("Access-Control-Request-Method")
- if !cors.isMethodAllowed(reqMethod) {
- cors.logf(" Preflight aborted: method '%s' not allowed", reqMethod)
- return
- }
- reqHeaders := parseHeaderList(r.Header.Get("Access-Control-Request-Headers"))
- if !cors.areHeadersAllowed(reqHeaders) {
- cors.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders)
- return
- }
- headers.Set("Access-Control-Allow-Origin", origin)
- headers.Add("Vary", "Origin")
- // Spec says: Since the list of methods can be unbounded, simply returning the method indicated
- // by Access-Control-Request-Method (if supported) can be enough
- headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod))
- if len(reqHeaders) > 0 {
-
- // Spec says: Since the list of headers can be unbounded, simply returning supported headers
- // from Access-Control-Request-Headers can be enough
- headers.Set("Access-Control-Allow-Headers", strings.Join(reqHeaders, ", "))
- }
- if options.AllowCredentials {
- headers.Set("Access-Control-Allow-Credentials", "true")
- }
- if options.MaxAge > 0 {
- headers.Set("Access-Control-Max-Age", strconv.Itoa(options.MaxAge))
- }
- cors.logf(" Preflight response headers: %v", headers)
-}
-
-// handleActualRequest handles simple cross-origin requests, actual request or redirects
-func (cors *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
- options := cors.options
- headers := w.Header()
- origin := r.Header.Get("Origin")
-
- if r.Method == "OPTIONS" {
- cors.logf(" Actual request no headers added: method == %s", r.Method)
- return
- }
- if origin == "" {
- cors.logf(" Actual request no headers added: missing origin")
- return
- }
- if !cors.isOriginAllowed(origin) {
- cors.logf(" Actual request no headers added: origin '%s' not allowed", origin)
- return
- }
-
- // Note that spec does define a way to specifically disallow a simple method like GET or
- // POST. Access-Control-Allow-Methods is only used for pre-flight requests and the
- // spec doesn't instruct to check the allowed methods for simple cross-origin requests.
- // We think it's a nice feature to be able to have control on those methods though.
- if !cors.isMethodAllowed(r.Method) {
- if cors.options.Debug {
- cors.logf(" Actual request no headers added: method '%s' not allowed",
- r.Method)
- }
-
- return
- }
- headers.Set("Access-Control-Allow-Origin", origin)
- headers.Add("Vary", "Origin")
- if len(options.ExposedHeaders) > 0 {
- headers.Set("Access-Control-Expose-Headers", strings.Join(options.ExposedHeaders, ", "))
- }
- if options.AllowCredentials {
- headers.Set("Access-Control-Allow-Credentials", "true")
- }
- cors.logf(" Actual response added headers: %v", headers)
-}
-
-// convenience method. checks if debugging is turned on before printing
-func (cors *Cors) logf(format string, a ...interface{}) {
- if cors.options.Debug {
- cors.options.log.Printf(format, a...)
- }
-}
-
-// isOriginAllowed checks if a given origin is allowed to perform cross-domain requests
-// on the endpoint
-func (cors *Cors) isOriginAllowed(origin string) bool {
- allowedOrigins := cors.options.AllowedOrigins
- origin = strings.ToLower(origin)
- for _, allowedOrigin := range allowedOrigins {
- switch allowedOrigin {
- case "*":
- return true
- case origin:
- return true
- }
- }
- return false
-}
-
-// isMethodAllowed checks if a given method can be used as part of a cross-domain request
-// on the endpoing
-func (cors *Cors) isMethodAllowed(method string) bool {
- allowedMethods := cors.options.AllowedMethods
- if len(allowedMethods) == 0 {
- // If no method allowed, always return false, even for preflight request
- return false
- }
- method = strings.ToUpper(method)
- if method == "OPTIONS" {
- // Always allow preflight requests
- return true
- }
- for _, allowedMethod := range allowedMethods {
- if allowedMethod == method {
- return true
- }
- }
- return false
-}
-
-// areHeadersAllowed checks if a given list of headers are allowed to used within
-// a cross-domain request.
-func (cors *Cors) areHeadersAllowed(requestedHeaders []string) bool {
- if len(requestedHeaders) == 0 {
- return true
- }
- for _, header := range requestedHeaders {
- found := false
- for _, allowedHeader := range cors.options.AllowedHeaders {
- if allowedHeader == "*" || allowedHeader == header {
- found = true
- break
- }
- }
- if !found {
- return false
- }
- }
- return true
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/cors_test.go b/Godeps/_workspace/src/github.com/rs/cors/cors_test.go
deleted file mode 100644
index f215018c9..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/cors_test.go
+++ /dev/null
@@ -1,288 +0,0 @@
-package cors
-
-import (
- "net/http"
- "net/http/httptest"
- "testing"
-)
-
-var testHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("bar"))
-})
-
-func assertHeaders(t *testing.T, resHeaders http.Header, reqHeaders map[string]string) {
- for name, value := range reqHeaders {
- if resHeaders.Get(name) != value {
- t.Errorf("Invalid header `%s', wanted `%s', got `%s'", name, value, resHeaders.Get(name))
- }
- }
-}
-
-func TestNoConfig(t *testing.T) {
- s := New(Options{
- // Intentionally left blank.
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestWildcardOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"*"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestDisallowedOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://barbaz.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedMethod(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedMethods: []string{"PUT", "DELETE"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "PUT")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "PUT",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestDisallowedMethod(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedMethods: []string{"PUT", "DELETE"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "PATCH")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedHeaders: []string{"X-Header-1", "x-header-2"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "X-Header-2, X-Header-1",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedWildcardHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedHeaders: []string{"*"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "X-Header-2, X-Header-1",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestDisallowedHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedHeaders: []string{"X-Header-1", "x-header-2"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "X-Header-3, X-Header-1")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestOriginHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "origin")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "Origin",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestExposedHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- ExposedHeaders: []string{"X-Header-1", "x-header-2"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "X-Header-1, X-Header-2",
- })
-}
-
-func TestAllowedCredentials(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowCredentials: true,
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "true",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go
deleted file mode 100644
index 0a3e15cb8..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package main
-
-import (
- "net/http"
-
- "github.com/justinas/alice"
- "github.com/rs/cors"
-)
-
-func main() {
- c := cors.New(cors.Options{
- AllowedOrigins: []string{"http://foo.com"},
- })
-
- mux := http.NewServeMux()
-
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- chain := alice.New(c.Handler).Then(mux)
- http.ListenAndServe(":8080", chain)
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go
deleted file mode 100644
index 851ac41d0..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package main
-
-import (
- "net/http"
-
- "github.com/rs/cors"
-)
-
-func main() {
- h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- // Use default options
- handler := cors.Default().Handler(h)
- http.ListenAndServe(":8080", handler)
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go
deleted file mode 100644
index 1fb4073aa..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package main
-
-import (
- "net/http"
-
- "github.com/rs/cors"
- "github.com/zenazn/goji"
-)
-
-func main() {
- c := cors.New(cors.Options{
- AllowedOrigins: []string{"http://foo.com"},
- })
- goji.Use(c.Handler)
-
- goji.Get("/", func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- goji.Serve()
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go
deleted file mode 100644
index 081af32f9..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package main
-
-import (
- "github.com/go-martini/martini"
- "github.com/martini-contrib/render"
- "github.com/rs/cors"
-)
-
-func main() {
- c := cors.New(cors.Options{
- AllowedOrigins: []string{"http://foo.com"},
- })
-
- m := martini.Classic()
- m.Use(render.Renderer())
- m.Use(c.HandlerFunc)
-
- m.Get("/", func(r render.Render) {
- r.JSON(200, map[string]interface{}{"hello": "world"})
- })
-
- m.Run()
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go
deleted file mode 100644
index 3cb33bff6..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package main
-
-import (
- "net/http"
-
- "github.com/codegangsta/negroni"
- "github.com/rs/cors"
-)
-
-func main() {
- c := cors.New(cors.Options{
- AllowedOrigins: []string{"http://foo.com"},
- })
-
- mux := http.NewServeMux()
-
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- n := negroni.Classic()
- n.Use(c)
- n.UseHandler(mux)
- n.Run(":3000")
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go
deleted file mode 100644
index eaa775e44..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package main
-
-import (
- "net/http"
-
- "github.com/rs/cors"
-)
-
-func main() {
- c := cors.New(cors.Options{
- AllowedOrigins: []string{"http://foo.com"},
- })
-
- handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- http.ListenAndServe(":8080", c.Handler(handler))
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go
deleted file mode 100644
index 094042300..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package main
-
-import (
- "net/http"
-
- "github.com/rs/cors"
-)
-
-func main() {
- c := cors.New(cors.Options{
- AllowedOrigins: []string{"*"},
- AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
- AllowCredentials: true,
- })
-
- h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- http.ListenAndServe(":8080", c.Handler(h))
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/utils.go b/Godeps/_workspace/src/github.com/rs/cors/utils.go
deleted file mode 100644
index 429ab1114..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/utils.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package cors
-
-import (
- "net/http"
- "strings"
-)
-
-type converter func(string) string
-
-// convert converts a list of string using the passed converter function
-func convert(s []string, c converter) []string {
- out := []string{}
- for _, i := range s {
- out = append(out, c(i))
- }
- return out
-}
-
-func parseHeaderList(headerList string) (headers []string) {
- for _, header := range strings.Split(headerList, ",") {
- header = http.CanonicalHeaderKey(strings.TrimSpace(header))
- if header != "" {
- headers = append(headers, header)
- }
- }
- return headers
-}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/utils_test.go b/Godeps/_workspace/src/github.com/rs/cors/utils_test.go
deleted file mode 100644
index 3fc77fc1e..000000000
--- a/Godeps/_workspace/src/github.com/rs/cors/utils_test.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package cors
-
-import (
- "strings"
- "testing"
-)
-
-func TestConvert(t *testing.T) {
- s := convert([]string{"A", "b", "C"}, strings.ToLower)
- e := []string{"a", "b", "c"}
- if s[0] != e[0] || s[1] != e[1] || s[2] != e[2] {
- t.Errorf("%v != %v", s, e)
- }
-}
-
-func TestParseHeaderList(t *testing.T) {
- h := parseHeaderList("header, second-header, THIRD-HEADER")
- e := []string{"Header", "Second-Header", "Third-Header"}
- if h[0] != e[0] || h[1] != e[1] || h[2] != e[2] {
- t.Errorf("%v != %v", h, e)
- }
-}
-
-func TestParseHeaderListEmpty(t *testing.T) {
- if len(parseHeaderList("")) != 0 {
- t.Error("should be empty sclice")
- }
-}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/client.go b/Godeps/_workspace/src/golang.org/x/net/websocket/client.go
new file mode 100644
index 000000000..20d1e1e38
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/client.go
@@ -0,0 +1,113 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+import (
+ "bufio"
+ "crypto/tls"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+)
+
+// DialError is an error that occurs while dialling a websocket server.
+type DialError struct {
+ *Config
+ Err error
+}
+
+func (e *DialError) Error() string {
+ return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
+}
+
+// NewConfig creates a new WebSocket config for client connection.
+func NewConfig(server, origin string) (config *Config, err error) {
+ config = new(Config)
+ config.Version = ProtocolVersionHybi13
+ config.Location, err = url.ParseRequestURI(server)
+ if err != nil {
+ return
+ }
+ config.Origin, err = url.ParseRequestURI(origin)
+ if err != nil {
+ return
+ }
+ config.Header = http.Header(make(map[string][]string))
+ return
+}
+
+// NewClient creates a new WebSocket client connection over rwc.
+func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
+ br := bufio.NewReader(rwc)
+ bw := bufio.NewWriter(rwc)
+ err = hybiClientHandshake(config, br, bw)
+ if err != nil {
+ return
+ }
+ buf := bufio.NewReadWriter(br, bw)
+ ws = newHybiClientConn(config, buf, rwc)
+ return
+}
+
+// Dial opens a new client connection to a WebSocket.
+func Dial(url_, protocol, origin string) (ws *Conn, err error) {
+ config, err := NewConfig(url_, origin)
+ if err != nil {
+ return nil, err
+ }
+ if protocol != "" {
+ config.Protocol = []string{protocol}
+ }
+ return DialConfig(config)
+}
+
+var portMap = map[string]string{
+ "ws": "80",
+ "wss": "443",
+}
+
+func parseAuthority(location *url.URL) string {
+ if _, ok := portMap[location.Scheme]; ok {
+ if _, _, err := net.SplitHostPort(location.Host); err != nil {
+ return net.JoinHostPort(location.Host, portMap[location.Scheme])
+ }
+ }
+ return location.Host
+}
+
+// DialConfig opens a new client connection to a WebSocket with a config.
+func DialConfig(config *Config) (ws *Conn, err error) {
+ var client net.Conn
+ if config.Location == nil {
+ return nil, &DialError{config, ErrBadWebSocketLocation}
+ }
+ if config.Origin == nil {
+ return nil, &DialError{config, ErrBadWebSocketOrigin}
+ }
+ switch config.Location.Scheme {
+ case "ws":
+ client, err = net.Dial("tcp", parseAuthority(config.Location))
+
+ case "wss":
+ client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig)
+
+ default:
+ err = ErrBadScheme
+ }
+ if err != nil {
+ goto Error
+ }
+
+ ws, err = NewClient(config, client)
+ if err != nil {
+ client.Close()
+ goto Error
+ }
+ return
+
+Error:
+ return nil, &DialError{config, err}
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go
new file mode 100644
index 000000000..72bb9d48e
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go
@@ -0,0 +1,31 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket_test
+
+import (
+ "fmt"
+ "log"
+
+ "golang.org/x/net/websocket"
+)
+
+// This example demonstrates a trivial client.
+func ExampleDial() {
+ origin := "http://localhost/"
+ url := "ws://localhost:12345/ws"
+ ws, err := websocket.Dial(url, "", origin)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
+ log.Fatal(err)
+ }
+ var msg = make([]byte, 512)
+ var n int
+ if n, err = ws.Read(msg); err != nil {
+ log.Fatal(err)
+ }
+ fmt.Printf("Received: %s.\n", msg[:n])
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go
new file mode 100644
index 000000000..f22a98fcd
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go
@@ -0,0 +1,26 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket_test
+
+import (
+ "io"
+ "net/http"
+
+ "golang.org/x/net/websocket"
+)
+
+// Echo the data received on the WebSocket.
+func EchoServer(ws *websocket.Conn) {
+ io.Copy(ws, ws)
+}
+
+// This example demonstrates a trivial echo server.
+func ExampleHandler() {
+ http.Handle("/echo", websocket.Handler(EchoServer))
+ err := http.ListenAndServe(":12345", nil)
+ if err != nil {
+ panic("ListenAndServe: " + err.Error())
+ }
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go
new file mode 100644
index 000000000..f8c0b2e29
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go
@@ -0,0 +1,564 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+// This file implements a protocol of hybi draft.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/rand"
+ "crypto/sha1"
+ "encoding/base64"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+const (
+ websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+ closeStatusNormal = 1000
+ closeStatusGoingAway = 1001
+ closeStatusProtocolError = 1002
+ closeStatusUnsupportedData = 1003
+ closeStatusFrameTooLarge = 1004
+ closeStatusNoStatusRcvd = 1005
+ closeStatusAbnormalClosure = 1006
+ closeStatusBadMessageData = 1007
+ closeStatusPolicyViolation = 1008
+ closeStatusTooBigData = 1009
+ closeStatusExtensionMismatch = 1010
+
+ maxControlFramePayloadLength = 125
+)
+
+var (
+ ErrBadMaskingKey = &ProtocolError{"bad masking key"}
+ ErrBadPongMessage = &ProtocolError{"bad pong message"}
+ ErrBadClosingStatus = &ProtocolError{"bad closing status"}
+ ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
+ ErrNotImplemented = &ProtocolError{"not implemented"}
+
+ handshakeHeader = map[string]bool{
+ "Host": true,
+ "Upgrade": true,
+ "Connection": true,
+ "Sec-Websocket-Key": true,
+ "Sec-Websocket-Origin": true,
+ "Sec-Websocket-Version": true,
+ "Sec-Websocket-Protocol": true,
+ "Sec-Websocket-Accept": true,
+ }
+)
+
+// A hybiFrameHeader is a frame header as defined in hybi draft.
+type hybiFrameHeader struct {
+ Fin bool
+ Rsv [3]bool
+ OpCode byte
+ Length int64
+ MaskingKey []byte
+
+ data *bytes.Buffer
+}
+
+// A hybiFrameReader is a reader for hybi frame.
+type hybiFrameReader struct {
+ reader io.Reader
+
+ header hybiFrameHeader
+ pos int64
+ length int
+}
+
+func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
+ n, err = frame.reader.Read(msg)
+ if err != nil {
+ return 0, err
+ }
+ if frame.header.MaskingKey != nil {
+ for i := 0; i < n; i++ {
+ msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
+ frame.pos++
+ }
+ }
+ return n, err
+}
+
+func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
+
+func (frame *hybiFrameReader) HeaderReader() io.Reader {
+ if frame.header.data == nil {
+ return nil
+ }
+ if frame.header.data.Len() == 0 {
+ return nil
+ }
+ return frame.header.data
+}
+
+func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
+
+func (frame *hybiFrameReader) Len() (n int) { return frame.length }
+
+// A hybiFrameReaderFactory creates new frame reader based on its frame type.
+type hybiFrameReaderFactory struct {
+ *bufio.Reader
+}
+
+// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
+// See Section 5.2 Base Framing protocol for detail.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
+func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
+ hybiFrame := new(hybiFrameReader)
+ frame = hybiFrame
+ var header []byte
+ var b byte
+ // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
+ for i := 0; i < 3; i++ {
+ j := uint(6 - i)
+ hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
+ }
+ hybiFrame.header.OpCode = header[0] & 0x0f
+
+ // Second byte. Mask/Payload len(7bits)
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ mask := (b & 0x80) != 0
+ b &= 0x7f
+ lengthFields := 0
+ switch {
+ case b <= 125: // Payload length 7bits.
+ hybiFrame.header.Length = int64(b)
+ case b == 126: // Payload length 7+16bits
+ lengthFields = 2
+ case b == 127: // Payload length 7+64bits
+ lengthFields = 8
+ }
+ for i := 0; i < lengthFields; i++ {
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
+ }
+ if mask {
+ // Masking key. 4 bytes.
+ for i := 0; i < 4; i++ {
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
+ }
+ }
+ hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
+ hybiFrame.header.data = bytes.NewBuffer(header)
+ hybiFrame.length = len(header) + int(hybiFrame.header.Length)
+ return
+}
+
+// A HybiFrameWriter is a writer for hybi frame.
+type hybiFrameWriter struct {
+ writer *bufio.Writer
+
+ header *hybiFrameHeader
+}
+
+func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
+ var header []byte
+ var b byte
+ if frame.header.Fin {
+ b |= 0x80
+ }
+ for i := 0; i < 3; i++ {
+ if frame.header.Rsv[i] {
+ j := uint(6 - i)
+ b |= 1 << j
+ }
+ }
+ b |= frame.header.OpCode
+ header = append(header, b)
+ if frame.header.MaskingKey != nil {
+ b = 0x80
+ } else {
+ b = 0
+ }
+ lengthFields := 0
+ length := len(msg)
+ switch {
+ case length <= 125:
+ b |= byte(length)
+ case length < 65536:
+ b |= 126
+ lengthFields = 2
+ default:
+ b |= 127
+ lengthFields = 8
+ }
+ header = append(header, b)
+ for i := 0; i < lengthFields; i++ {
+ j := uint((lengthFields - i - 1) * 8)
+ b = byte((length >> j) & 0xff)
+ header = append(header, b)
+ }
+ if frame.header.MaskingKey != nil {
+ if len(frame.header.MaskingKey) != 4 {
+ return 0, ErrBadMaskingKey
+ }
+ header = append(header, frame.header.MaskingKey...)
+ frame.writer.Write(header)
+ data := make([]byte, length)
+ for i := range data {
+ data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
+ }
+ frame.writer.Write(data)
+ err = frame.writer.Flush()
+ return length, err
+ }
+ frame.writer.Write(header)
+ frame.writer.Write(msg)
+ err = frame.writer.Flush()
+ return length, err
+}
+
+func (frame *hybiFrameWriter) Close() error { return nil }
+
+type hybiFrameWriterFactory struct {
+ *bufio.Writer
+ needMaskingKey bool
+}
+
+func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
+ if buf.needMaskingKey {
+ frameHeader.MaskingKey, err = generateMaskingKey()
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
+}
+
+type hybiFrameHandler struct {
+ conn *Conn
+ payloadType byte
+}
+
+func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
+ if handler.conn.IsServerConn() {
+ // The client MUST mask all frames sent to the server.
+ if frame.(*hybiFrameReader).header.MaskingKey == nil {
+ handler.WriteClose(closeStatusProtocolError)
+ return nil, io.EOF
+ }
+ } else {
+ // The server MUST NOT mask all frames.
+ if frame.(*hybiFrameReader).header.MaskingKey != nil {
+ handler.WriteClose(closeStatusProtocolError)
+ return nil, io.EOF
+ }
+ }
+ if header := frame.HeaderReader(); header != nil {
+ io.Copy(ioutil.Discard, header)
+ }
+ switch frame.PayloadType() {
+ case ContinuationFrame:
+ frame.(*hybiFrameReader).header.OpCode = handler.payloadType
+ case TextFrame, BinaryFrame:
+ handler.payloadType = frame.PayloadType()
+ case CloseFrame:
+ return nil, io.EOF
+ case PingFrame:
+ pingMsg := make([]byte, maxControlFramePayloadLength)
+ n, err := io.ReadFull(frame, pingMsg)
+ if err != nil && err != io.ErrUnexpectedEOF {
+ return nil, err
+ }
+ io.Copy(ioutil.Discard, frame)
+ n, err = handler.WritePong(pingMsg[:n])
+ if err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case PongFrame:
+ return nil, ErrNotImplemented
+ }
+ return frame, nil
+}
+
+func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
+ handler.conn.wio.Lock()
+ defer handler.conn.wio.Unlock()
+ w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
+ if err != nil {
+ return err
+ }
+ msg := make([]byte, 2)
+ binary.BigEndian.PutUint16(msg, uint16(status))
+ _, err = w.Write(msg)
+ w.Close()
+ return err
+}
+
+func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
+ handler.conn.wio.Lock()
+ defer handler.conn.wio.Unlock()
+ w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
+ if err != nil {
+ return 0, err
+ }
+ n, err = w.Write(msg)
+ w.Close()
+ return n, err
+}
+
+// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
+func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ if buf == nil {
+ br := bufio.NewReader(rwc)
+ bw := bufio.NewWriter(rwc)
+ buf = bufio.NewReadWriter(br, bw)
+ }
+ ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
+ frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
+ frameWriterFactory: hybiFrameWriterFactory{
+ buf.Writer, request == nil},
+ PayloadType: TextFrame,
+ defaultCloseStatus: closeStatusNormal}
+ ws.frameHandler = &hybiFrameHandler{conn: ws}
+ return ws
+}
+
+// generateMaskingKey generates a masking key for a frame.
+func generateMaskingKey() (maskingKey []byte, err error) {
+ maskingKey = make([]byte, 4)
+ if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
+ return
+ }
+ return
+}
+
+// generateNonce generates a nonce consisting of a randomly selected 16-byte
+// value that has been base64-encoded.
+func generateNonce() (nonce []byte) {
+ key := make([]byte, 16)
+ if _, err := io.ReadFull(rand.Reader, key); err != nil {
+ panic(err)
+ }
+ nonce = make([]byte, 24)
+ base64.StdEncoding.Encode(nonce, key)
+ return
+}
+
+// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
+// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
+func getNonceAccept(nonce []byte) (expected []byte, err error) {
+ h := sha1.New()
+ if _, err = h.Write(nonce); err != nil {
+ return
+ }
+ if _, err = h.Write([]byte(websocketGUID)); err != nil {
+ return
+ }
+ expected = make([]byte, 28)
+ base64.StdEncoding.Encode(expected, h.Sum(nil))
+ return
+}
+
+// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
+func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
+ bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
+
+ bw.WriteString("Host: " + config.Location.Host + "\r\n")
+ bw.WriteString("Upgrade: websocket\r\n")
+ bw.WriteString("Connection: Upgrade\r\n")
+ nonce := generateNonce()
+ if config.handshakeData != nil {
+ nonce = []byte(config.handshakeData["key"])
+ }
+ bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
+ bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
+
+ if config.Version != ProtocolVersionHybi13 {
+ return ErrBadProtocolVersion
+ }
+
+ bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
+ if len(config.Protocol) > 0 {
+ bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
+ }
+ // TODO(ukai): send Sec-WebSocket-Extensions.
+ err = config.Header.WriteSubset(bw, handshakeHeader)
+ if err != nil {
+ return err
+ }
+
+ bw.WriteString("\r\n")
+ if err = bw.Flush(); err != nil {
+ return err
+ }
+
+ resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode != 101 {
+ return ErrBadStatus
+ }
+ if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
+ strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
+ return ErrBadUpgrade
+ }
+ expectedAccept, err := getNonceAccept(nonce)
+ if err != nil {
+ return err
+ }
+ if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
+ return ErrChallengeResponse
+ }
+ if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
+ return ErrUnsupportedExtensions
+ }
+ offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
+ if offeredProtocol != "" {
+ protocolMatched := false
+ for i := 0; i < len(config.Protocol); i++ {
+ if config.Protocol[i] == offeredProtocol {
+ protocolMatched = true
+ break
+ }
+ }
+ if !protocolMatched {
+ return ErrBadWebSocketProtocol
+ }
+ config.Protocol = []string{offeredProtocol}
+ }
+
+ return nil
+}
+
+// newHybiClientConn creates a client WebSocket connection after handshake.
+func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
+ return newHybiConn(config, buf, rwc, nil)
+}
+
+// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
+type hybiServerHandshaker struct {
+ *Config
+ accept []byte
+}
+
+func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
+ c.Version = ProtocolVersionHybi13
+ if req.Method != "GET" {
+ return http.StatusMethodNotAllowed, ErrBadRequestMethod
+ }
+ // HTTP version can be safely ignored.
+
+ if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
+ !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
+ return http.StatusBadRequest, ErrNotWebSocket
+ }
+
+ key := req.Header.Get("Sec-Websocket-Key")
+ if key == "" {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+ version := req.Header.Get("Sec-Websocket-Version")
+ switch version {
+ case "13":
+ c.Version = ProtocolVersionHybi13
+ default:
+ return http.StatusBadRequest, ErrBadWebSocketVersion
+ }
+ var scheme string
+ if req.TLS != nil {
+ scheme = "wss"
+ } else {
+ scheme = "ws"
+ }
+ c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+ protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
+ if protocol != "" {
+ protocols := strings.Split(protocol, ",")
+ for i := 0; i < len(protocols); i++ {
+ c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
+ }
+ }
+ c.accept, err = getNonceAccept([]byte(key))
+ if err != nil {
+ return http.StatusInternalServerError, err
+ }
+ return http.StatusSwitchingProtocols, nil
+}
+
+// Origin parses Origin header in "req".
+// If origin is "null", returns (nil, nil).
+func Origin(config *Config, req *http.Request) (*url.URL, error) {
+ var origin string
+ switch config.Version {
+ case ProtocolVersionHybi13:
+ origin = req.Header.Get("Origin")
+ }
+ if origin == "null" {
+ return nil, nil
+ }
+ return url.ParseRequestURI(origin)
+}
+
+func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
+ if len(c.Protocol) > 0 {
+ if len(c.Protocol) != 1 {
+ // You need choose a Protocol in Handshake func in Server.
+ return ErrBadWebSocketProtocol
+ }
+ }
+ buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
+ buf.WriteString("Upgrade: websocket\r\n")
+ buf.WriteString("Connection: Upgrade\r\n")
+ buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
+ if len(c.Protocol) > 0 {
+ buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
+ }
+ // TODO(ukai): send Sec-WebSocket-Extensions.
+ if c.Header != nil {
+ err := c.Header.WriteSubset(buf, handshakeHeader)
+ if err != nil {
+ return err
+ }
+ }
+ buf.WriteString("\r\n")
+ return buf.Flush()
+}
+
+func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ return newHybiServerConn(c.Config, buf, rwc, request)
+}
+
+// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
+func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ return newHybiConn(config, buf, rwc, request)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go
new file mode 100644
index 000000000..d6a19108a
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go
@@ -0,0 +1,590 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+)
+
+// Test the getNonceAccept function with values in
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
+func TestSecWebSocketAccept(t *testing.T) {
+ nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
+ expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
+ accept, err := getNonceAccept(nonce)
+ if err != nil {
+ t.Errorf("getNonceAccept: returned error %v", err)
+ return
+ }
+ if !bytes.Equal(expected, accept) {
+ t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
+ }
+}
+
+func TestHybiClientHandshake(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+ br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+Sec-WebSocket-Protocol: chat
+
+`))
+ var err error
+ config := new(Config)
+ config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+ config.Origin, err = url.ParseRequestURI("http://example.com")
+ if err != nil {
+ t.Fatal("origin url", err)
+ }
+ config.Protocol = append(config.Protocol, "chat")
+ config.Protocol = append(config.Protocol, "superchat")
+ config.Version = ProtocolVersionHybi13
+
+ config.handshakeData = map[string]string{
+ "key": "dGhlIHNhbXBsZSBub25jZQ==",
+ }
+ err = hybiClientHandshake(config, br, bw)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ req, err := http.ReadRequest(bufio.NewReader(b))
+ if err != nil {
+ t.Fatalf("read request: %v", err)
+ }
+ if req.Method != "GET" {
+ t.Errorf("request method expected GET, but got %q", req.Method)
+ }
+ if req.URL.Path != "/chat" {
+ t.Errorf("request path expected /chat, but got %q", req.URL.Path)
+ }
+ if req.Proto != "HTTP/1.1" {
+ t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
+ }
+ if req.Host != "server.example.com" {
+ t.Errorf("request Host expected server.example.com, but got %v", req.Host)
+ }
+ var expectedHeader = map[string]string{
+ "Connection": "Upgrade",
+ "Upgrade": "websocket",
+ "Sec-Websocket-Key": config.handshakeData["key"],
+ "Origin": config.Origin.String(),
+ "Sec-Websocket-Protocol": "chat, superchat",
+ "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
+ }
+ for k, v := range expectedHeader {
+ if req.Header.Get(k) != v {
+ t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
+ }
+ }
+}
+
+func TestHybiClientHandshakeWithHeader(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+ br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+Sec-WebSocket-Protocol: chat
+
+`))
+ var err error
+ config := new(Config)
+ config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+ config.Origin, err = url.ParseRequestURI("http://example.com")
+ if err != nil {
+ t.Fatal("origin url", err)
+ }
+ config.Protocol = append(config.Protocol, "chat")
+ config.Protocol = append(config.Protocol, "superchat")
+ config.Version = ProtocolVersionHybi13
+ config.Header = http.Header(make(map[string][]string))
+ config.Header.Add("User-Agent", "test")
+
+ config.handshakeData = map[string]string{
+ "key": "dGhlIHNhbXBsZSBub25jZQ==",
+ }
+ err = hybiClientHandshake(config, br, bw)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ req, err := http.ReadRequest(bufio.NewReader(b))
+ if err != nil {
+ t.Fatalf("read request: %v", err)
+ }
+ if req.Method != "GET" {
+ t.Errorf("request method expected GET, but got %q", req.Method)
+ }
+ if req.URL.Path != "/chat" {
+ t.Errorf("request path expected /chat, but got %q", req.URL.Path)
+ }
+ if req.Proto != "HTTP/1.1" {
+ t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
+ }
+ if req.Host != "server.example.com" {
+ t.Errorf("request Host expected server.example.com, but got %v", req.Host)
+ }
+ var expectedHeader = map[string]string{
+ "Connection": "Upgrade",
+ "Upgrade": "websocket",
+ "Sec-Websocket-Key": config.handshakeData["key"],
+ "Origin": config.Origin.String(),
+ "Sec-Websocket-Protocol": "chat, superchat",
+ "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
+ "User-Agent": "test",
+ }
+ for k, v := range expectedHeader {
+ if req.Header.Get(k) != v {
+ t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
+ }
+ }
+}
+
+func TestHybiServerHandshake(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ expectedProtocols := []string{"chat", "superchat"}
+ if fmt.Sprintf("%v", config.Protocol) != fmt.Sprintf("%v", expectedProtocols) {
+ t.Errorf("protocol expected %q but got %q", expectedProtocols, config.Protocol)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ config.Protocol = config.Protocol[:1]
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "Sec-WebSocket-Protocol: chat",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
+
+func TestHybiServerHandshakeNoSubProtocol(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ if len(config.Protocol) != 0 {
+ t.Errorf("len(config.Protocol) expected 0, but got %q", len(config.Protocol))
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
+
+func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Sec-WebSocket-Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 9
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != ErrBadWebSocketVersion {
+ t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
+ }
+ if code != http.StatusBadRequest {
+ t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
+ }
+}
+
+func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
+ b := bytes.NewBuffer([]byte{})
+ frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
+ w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
+ w.(*hybiFrameWriter).header = frameHeader
+ _, err := w.Write(testPayload)
+ w.Close()
+ if err != nil {
+ t.Errorf("Write error %q", err)
+ }
+ var expectedFrame []byte
+ expectedFrame = append(expectedFrame, testHeader...)
+ expectedFrame = append(expectedFrame, testMaskedPayload...)
+ if !bytes.Equal(expectedFrame, b.Bytes()) {
+ t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
+ }
+ frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
+ r, err := frameReaderFactory.NewFrameReader()
+ if err != nil {
+ t.Errorf("Read error %q", err)
+ }
+ if header := r.HeaderReader(); header == nil {
+ t.Errorf("no header")
+ } else {
+ actualHeader := make([]byte, r.Len())
+ n, err := header.Read(actualHeader)
+ if err != nil {
+ t.Errorf("Read header error %q", err)
+ } else {
+ if n < len(testHeader) {
+ t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
+ }
+ if !bytes.Equal(testHeader, actualHeader[:n]) {
+ t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
+ }
+ }
+ }
+ if trailer := r.TrailerReader(); trailer != nil {
+ t.Errorf("unexpected trailer %q", trailer)
+ }
+ frame := r.(*hybiFrameReader)
+ if frameHeader.Fin != frame.header.Fin ||
+ frameHeader.OpCode != frame.header.OpCode ||
+ len(testPayload) != int(frame.header.Length) {
+ t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
+ }
+ payload := make([]byte, len(testPayload))
+ _, err = r.Read(payload)
+ if err != nil {
+ t.Errorf("read %v", err)
+ }
+ if !bytes.Equal(testPayload, payload) {
+ t.Errorf("payload %q vs %q", testPayload, payload)
+ }
+}
+
+func TestHybiShortTextFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
+
+ payload = make([]byte, 125)
+ testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
+}
+
+func TestHybiShortMaskedTextFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
+ MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
+ payload := []byte("hello")
+ maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
+ header := []byte{0x81, 0x85}
+ header = append(header, frameHeader.MaskingKey...)
+ testHybiFrame(t, header, payload, maskedPayload, frameHeader)
+}
+
+func TestHybiShortBinaryFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
+
+ payload = make([]byte, 125)
+ testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
+}
+
+func TestHybiControlFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
+ testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
+ payload = []byte{0x03, 0xe8} // 1000
+ testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
+}
+
+func TestHybiLongFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
+ payload := make([]byte, 126)
+ testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
+
+ payload = make([]byte, 65535)
+ testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
+
+ payload = make([]byte, 65536)
+ testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
+}
+
+func TestHybiClientRead(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
+ 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
+ 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ msg := make([]byte, 512)
+ n, err := conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 1st frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 1st frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(wireData[2:7], msg[:n]) {
+ t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
+ }
+ n, err = conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 2nd frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 2nd frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(wireData[16:21], msg[:n]) {
+ t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
+ }
+ n, err = conn.Read(msg)
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+}
+
+func TestHybiShortRead(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
+ 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
+ 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ step := 0
+ pos := 0
+ expectedPos := []int{2, 5, 16, 19}
+ expectedLen := []int{3, 2, 3, 2}
+ for {
+ msg := make([]byte, 3)
+ n, err := conn.Read(msg)
+ if step >= len(expectedPos) {
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+ return
+ }
+ pos = expectedPos[step]
+ endPos := pos + expectedLen[step]
+ if err != nil {
+ t.Errorf("read from %d, got error %q", pos, err)
+ return
+ }
+ if n != endPos-pos {
+ t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
+ }
+ if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
+ t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
+ }
+ step++
+ }
+}
+
+func TestHybiServerRead(t *testing.T) {
+ wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
+ 0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
+ 0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
+ 0x9a, 0xec, 0xc6, 0x48, 0x89, // world
+ }
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
+
+ expected := [][]byte{[]byte("hello"), []byte("world")}
+
+ msg := make([]byte, 512)
+ n, err := conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 1st frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 1st frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(expected[0], msg[:n]) {
+ t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
+ }
+
+ n, err = conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 2nd frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 2nd frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(expected[1], msg[:n]) {
+ t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
+ }
+
+ n, err = conn.Read(msg)
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+}
+
+func TestHybiServerReadWithoutMasking(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
+ // server MUST close the connection upon receiving a non-masked frame.
+ msg := make([]byte, 512)
+ _, err := conn.Read(msg)
+ if err != io.EOF {
+ t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
+ }
+}
+
+func TestHybiClientReadWithMasking(t *testing.T) {
+ wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
+ }
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ // client MUST close the connection upon receiving a masked frame.
+ msg := make([]byte, 512)
+ _, err := conn.Read(msg)
+ if err != io.EOF {
+ t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
+ }
+}
+
+// Test the hybiServerHandshaker supports firefox implementation and
+// checks Connection request header include (but it's not necessary
+// equal to) "upgrade"
+func TestHybiServerFirefoxHandshake(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: keep-alive, upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ config.Protocol = []string{"chat"}
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "Sec-WebSocket-Protocol: chat",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/server.go b/Godeps/_workspace/src/golang.org/x/net/websocket/server.go
new file mode 100644
index 000000000..70322133c
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/server.go
@@ -0,0 +1,114 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
+ var hs serverHandshaker = &hybiServerHandshaker{Config: config}
+ code, err := hs.ReadHandshake(buf.Reader, req)
+ if err == ErrBadWebSocketVersion {
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
+ buf.WriteString("\r\n")
+ buf.WriteString(err.Error())
+ buf.Flush()
+ return
+ }
+ if err != nil {
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ buf.WriteString("\r\n")
+ buf.WriteString(err.Error())
+ buf.Flush()
+ return
+ }
+ if handshake != nil {
+ err = handshake(config, req)
+ if err != nil {
+ code = http.StatusForbidden
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ buf.WriteString("\r\n")
+ buf.Flush()
+ return
+ }
+ }
+ err = hs.AcceptHandshake(buf.Writer)
+ if err != nil {
+ code = http.StatusBadRequest
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ buf.WriteString("\r\n")
+ buf.Flush()
+ return
+ }
+ conn = hs.NewServerConn(buf, rwc, req)
+ return
+}
+
+// Server represents a server of a WebSocket.
+type Server struct {
+ // Config is a WebSocket configuration for new WebSocket connection.
+ Config
+
+ // Handshake is an optional function in WebSocket handshake.
+ // For example, you can check, or don't check Origin header.
+ // Another example, you can select config.Protocol.
+ Handshake func(*Config, *http.Request) error
+
+ // Handler handles a WebSocket connection.
+ Handler
+}
+
+// ServeHTTP implements the http.Handler interface for a WebSocket
+func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ s.serveWebSocket(w, req)
+}
+
+func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
+ rwc, buf, err := w.(http.Hijacker).Hijack()
+ if err != nil {
+ panic("Hijack failed: " + err.Error())
+ return
+ }
+ // The server should abort the WebSocket connection if it finds
+ // the client did not send a handshake that matches with protocol
+ // specification.
+ defer rwc.Close()
+ conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
+ if err != nil {
+ return
+ }
+ if conn == nil {
+ panic("unexpected nil conn")
+ }
+ s.Handler(conn)
+}
+
+// Handler is a simple interface to a WebSocket browser client.
+// It checks if Origin header is valid URL by default.
+// You might want to verify websocket.Conn.Config().Origin in the func.
+// If you use Server instead of Handler, you could call websocket.Origin and
+// check the origin in your Handshake func. So, if you want to accept
+// non-browser client, which doesn't send Origin header, you could use Server
+//. that doesn't check origin in its Handshake.
+type Handler func(*Conn)
+
+func checkOrigin(config *Config, req *http.Request) (err error) {
+ config.Origin, err = Origin(config, req)
+ if err == nil && config.Origin == nil {
+ return fmt.Errorf("null origin")
+ }
+ return err
+}
+
+// ServeHTTP implements the http.Handler interface for a WebSocket
+func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ s := Server{Handler: h, Handshake: checkOrigin}
+ s.serveWebSocket(w, req)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go
new file mode 100644
index 000000000..0f4917bf7
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go
@@ -0,0 +1,411 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package websocket implements a client and server for the WebSocket protocol
+// as specified in RFC 6455.
+package websocket
+
+import (
+ "bufio"
+ "crypto/tls"
+ "encoding/json"
+ "errors"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "net/url"
+ "sync"
+ "time"
+)
+
+const (
+ ProtocolVersionHybi13 = 13
+ ProtocolVersionHybi = ProtocolVersionHybi13
+ SupportedProtocolVersion = "13"
+
+ ContinuationFrame = 0
+ TextFrame = 1
+ BinaryFrame = 2
+ CloseFrame = 8
+ PingFrame = 9
+ PongFrame = 10
+ UnknownFrame = 255
+)
+
+// ProtocolError represents WebSocket protocol errors.
+type ProtocolError struct {
+ ErrorString string
+}
+
+func (err *ProtocolError) Error() string { return err.ErrorString }
+
+var (
+ ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
+ ErrBadScheme = &ProtocolError{"bad scheme"}
+ ErrBadStatus = &ProtocolError{"bad status"}
+ ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
+ ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
+ ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
+ ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
+ ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
+ ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
+ ErrBadFrame = &ProtocolError{"bad frame"}
+ ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
+ ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
+ ErrBadRequestMethod = &ProtocolError{"bad method"}
+ ErrNotSupported = &ProtocolError{"not supported"}
+)
+
+// Addr is an implementation of net.Addr for WebSocket.
+type Addr struct {
+ *url.URL
+}
+
+// Network returns the network type for a WebSocket, "websocket".
+func (addr *Addr) Network() string { return "websocket" }
+
+// Config is a WebSocket configuration
+type Config struct {
+ // A WebSocket server address.
+ Location *url.URL
+
+ // A Websocket client origin.
+ Origin *url.URL
+
+ // WebSocket subprotocols.
+ Protocol []string
+
+ // WebSocket protocol version.
+ Version int
+
+ // TLS config for secure WebSocket (wss).
+ TlsConfig *tls.Config
+
+ // Additional header fields to be sent in WebSocket opening handshake.
+ Header http.Header
+
+ handshakeData map[string]string
+}
+
+// serverHandshaker is an interface to handle WebSocket server side handshake.
+type serverHandshaker interface {
+ // ReadHandshake reads handshake request message from client.
+ // Returns http response code and error if any.
+ ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
+
+ // AcceptHandshake accepts the client handshake request and sends
+ // handshake response back to client.
+ AcceptHandshake(buf *bufio.Writer) (err error)
+
+ // NewServerConn creates a new WebSocket connection.
+ NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
+}
+
+// frameReader is an interface to read a WebSocket frame.
+type frameReader interface {
+ // Reader is to read payload of the frame.
+ io.Reader
+
+ // PayloadType returns payload type.
+ PayloadType() byte
+
+ // HeaderReader returns a reader to read header of the frame.
+ HeaderReader() io.Reader
+
+ // TrailerReader returns a reader to read trailer of the frame.
+ // If it returns nil, there is no trailer in the frame.
+ TrailerReader() io.Reader
+
+ // Len returns total length of the frame, including header and trailer.
+ Len() int
+}
+
+// frameReaderFactory is an interface to creates new frame reader.
+type frameReaderFactory interface {
+ NewFrameReader() (r frameReader, err error)
+}
+
+// frameWriter is an interface to write a WebSocket frame.
+type frameWriter interface {
+ // Writer is to write payload of the frame.
+ io.WriteCloser
+}
+
+// frameWriterFactory is an interface to create new frame writer.
+type frameWriterFactory interface {
+ NewFrameWriter(payloadType byte) (w frameWriter, err error)
+}
+
+type frameHandler interface {
+ HandleFrame(frame frameReader) (r frameReader, err error)
+ WriteClose(status int) (err error)
+}
+
+// Conn represents a WebSocket connection.
+type Conn struct {
+ config *Config
+ request *http.Request
+
+ buf *bufio.ReadWriter
+ rwc io.ReadWriteCloser
+
+ rio sync.Mutex
+ frameReaderFactory
+ frameReader
+
+ wio sync.Mutex
+ frameWriterFactory
+
+ frameHandler
+ PayloadType byte
+ defaultCloseStatus int
+}
+
+// Read implements the io.Reader interface:
+// it reads data of a frame from the WebSocket connection.
+// if msg is not large enough for the frame data, it fills the msg and next Read
+// will read the rest of the frame data.
+// it reads Text frame or Binary frame.
+func (ws *Conn) Read(msg []byte) (n int, err error) {
+ ws.rio.Lock()
+ defer ws.rio.Unlock()
+again:
+ if ws.frameReader == nil {
+ frame, err := ws.frameReaderFactory.NewFrameReader()
+ if err != nil {
+ return 0, err
+ }
+ ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
+ if err != nil {
+ return 0, err
+ }
+ if ws.frameReader == nil {
+ goto again
+ }
+ }
+ n, err = ws.frameReader.Read(msg)
+ if err == io.EOF {
+ if trailer := ws.frameReader.TrailerReader(); trailer != nil {
+ io.Copy(ioutil.Discard, trailer)
+ }
+ ws.frameReader = nil
+ goto again
+ }
+ return n, err
+}
+
+// Write implements the io.Writer interface:
+// it writes data as a frame to the WebSocket connection.
+func (ws *Conn) Write(msg []byte) (n int, err error) {
+ ws.wio.Lock()
+ defer ws.wio.Unlock()
+ w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
+ if err != nil {
+ return 0, err
+ }
+ n, err = w.Write(msg)
+ w.Close()
+ if err != nil {
+ return n, err
+ }
+ return n, err
+}
+
+// Close implements the io.Closer interface.
+func (ws *Conn) Close() error {
+ err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
+ if err != nil {
+ return err
+ }
+ return ws.rwc.Close()
+}
+
+func (ws *Conn) IsClientConn() bool { return ws.request == nil }
+func (ws *Conn) IsServerConn() bool { return ws.request != nil }
+
+// LocalAddr returns the WebSocket Origin for the connection for client, or
+// the WebSocket location for server.
+func (ws *Conn) LocalAddr() net.Addr {
+ if ws.IsClientConn() {
+ return &Addr{ws.config.Origin}
+ }
+ return &Addr{ws.config.Location}
+}
+
+// RemoteAddr returns the WebSocket location for the connection for client, or
+// the Websocket Origin for server.
+func (ws *Conn) RemoteAddr() net.Addr {
+ if ws.IsClientConn() {
+ return &Addr{ws.config.Location}
+ }
+ return &Addr{ws.config.Origin}
+}
+
+var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
+
+// SetDeadline sets the connection's network read & write deadlines.
+func (ws *Conn) SetDeadline(t time.Time) error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetDeadline(t)
+ }
+ return errSetDeadline
+}
+
+// SetReadDeadline sets the connection's network read deadline.
+func (ws *Conn) SetReadDeadline(t time.Time) error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetReadDeadline(t)
+ }
+ return errSetDeadline
+}
+
+// SetWriteDeadline sets the connection's network write deadline.
+func (ws *Conn) SetWriteDeadline(t time.Time) error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetWriteDeadline(t)
+ }
+ return errSetDeadline
+}
+
+// Config returns the WebSocket config.
+func (ws *Conn) Config() *Config { return ws.config }
+
+// Request returns the http request upgraded to the WebSocket.
+// It is nil for client side.
+func (ws *Conn) Request() *http.Request { return ws.request }
+
+// Codec represents a symmetric pair of functions that implement a codec.
+type Codec struct {
+ Marshal func(v interface{}) (data []byte, payloadType byte, err error)
+ Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
+}
+
+// Send sends v marshaled by cd.Marshal as single frame to ws.
+func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
+ data, payloadType, err := cd.Marshal(v)
+ if err != nil {
+ return err
+ }
+ ws.wio.Lock()
+ defer ws.wio.Unlock()
+ w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(data)
+ w.Close()
+ return err
+}
+
+// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
+func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
+ ws.rio.Lock()
+ defer ws.rio.Unlock()
+ if ws.frameReader != nil {
+ _, err = io.Copy(ioutil.Discard, ws.frameReader)
+ if err != nil {
+ return err
+ }
+ ws.frameReader = nil
+ }
+again:
+ frame, err := ws.frameReaderFactory.NewFrameReader()
+ if err != nil {
+ return err
+ }
+ frame, err = ws.frameHandler.HandleFrame(frame)
+ if err != nil {
+ return err
+ }
+ if frame == nil {
+ goto again
+ }
+ payloadType := frame.PayloadType()
+ data, err := ioutil.ReadAll(frame)
+ if err != nil {
+ return err
+ }
+ return cd.Unmarshal(data, payloadType, v)
+}
+
+func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
+ switch data := v.(type) {
+ case string:
+ return []byte(data), TextFrame, nil
+ case []byte:
+ return data, BinaryFrame, nil
+ }
+ return nil, UnknownFrame, ErrNotSupported
+}
+
+func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
+ switch data := v.(type) {
+ case *string:
+ *data = string(msg)
+ return nil
+ case *[]byte:
+ *data = msg
+ return nil
+ }
+ return ErrNotSupported
+}
+
+/*
+Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
+To send/receive text frame, use string type.
+To send/receive binary frame, use []byte type.
+
+Trivial usage:
+
+ import "websocket"
+
+ // receive text frame
+ var message string
+ websocket.Message.Receive(ws, &message)
+
+ // send text frame
+ message = "hello"
+ websocket.Message.Send(ws, message)
+
+ // receive binary frame
+ var data []byte
+ websocket.Message.Receive(ws, &data)
+
+ // send binary frame
+ data = []byte{0, 1, 2}
+ websocket.Message.Send(ws, data)
+
+*/
+var Message = Codec{marshal, unmarshal}
+
+func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
+ msg, err = json.Marshal(v)
+ return msg, TextFrame, err
+}
+
+func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
+ return json.Unmarshal(msg, v)
+}
+
+/*
+JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
+
+Trivial usage:
+
+ import "websocket"
+
+ type T struct {
+ Msg string
+ Count int
+ }
+
+ // receive JSON type T
+ var data T
+ websocket.JSON.Receive(ws, &data)
+
+ // send JSON type T
+ websocket.JSON.Send(ws, data)
+*/
+var JSON = Codec{jsonMarshal, jsonUnmarshal}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/websocket_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket_test.go
new file mode 100644
index 000000000..a376abacf
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket_test.go
@@ -0,0 +1,414 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "strings"
+ "sync"
+ "testing"
+)
+
+var serverAddr string
+var once sync.Once
+
+func echoServer(ws *Conn) { io.Copy(ws, ws) }
+
+type Count struct {
+ S string
+ N int
+}
+
+func countServer(ws *Conn) {
+ for {
+ var count Count
+ err := JSON.Receive(ws, &count)
+ if err != nil {
+ return
+ }
+ count.N++
+ count.S = strings.Repeat(count.S, count.N)
+ err = JSON.Send(ws, count)
+ if err != nil {
+ return
+ }
+ }
+}
+
+func subProtocolHandshake(config *Config, req *http.Request) error {
+ for _, proto := range config.Protocol {
+ if proto == "chat" {
+ config.Protocol = []string{proto}
+ return nil
+ }
+ }
+ return ErrBadWebSocketProtocol
+}
+
+func subProtoServer(ws *Conn) {
+ for _, proto := range ws.Config().Protocol {
+ io.WriteString(ws, proto)
+ }
+}
+
+func startServer() {
+ http.Handle("/echo", Handler(echoServer))
+ http.Handle("/count", Handler(countServer))
+ subproto := Server{
+ Handshake: subProtocolHandshake,
+ Handler: Handler(subProtoServer),
+ }
+ http.Handle("/subproto", subproto)
+ server := httptest.NewServer(nil)
+ serverAddr = server.Listener.Addr().String()
+ log.Print("Test WebSocket server listening on ", serverAddr)
+}
+
+func newConfig(t *testing.T, path string) *Config {
+ config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
+ return config
+}
+
+func TestEcho(t *testing.T) {
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/echo"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ msg := []byte("hello, world\n")
+ if _, err := conn.Write(msg); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ var actual_msg = make([]byte, 512)
+ n, err := conn.Read(actual_msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ actual_msg = actual_msg[0:n]
+ if !bytes.Equal(msg, actual_msg) {
+ t.Errorf("Echo: expected %q got %q", msg, actual_msg)
+ }
+ conn.Close()
+}
+
+func TestAddr(t *testing.T) {
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/echo"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ ra := conn.RemoteAddr().String()
+ if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
+ t.Errorf("Bad remote addr: %v", ra)
+ }
+ la := conn.LocalAddr().String()
+ if !strings.HasPrefix(la, "http://") {
+ t.Errorf("Bad local addr: %v", la)
+ }
+ conn.Close()
+}
+
+func TestCount(t *testing.T) {
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/count"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ var count Count
+ count.S = "hello"
+ if err := JSON.Send(conn, count); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ if err := JSON.Receive(conn, &count); err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if count.N != 1 {
+ t.Errorf("count: expected %d got %d", 1, count.N)
+ }
+ if count.S != "hello" {
+ t.Errorf("count: expected %q got %q", "hello", count.S)
+ }
+ if err := JSON.Send(conn, count); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ if err := JSON.Receive(conn, &count); err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if count.N != 2 {
+ t.Errorf("count: expected %d got %d", 2, count.N)
+ }
+ if count.S != "hellohello" {
+ t.Errorf("count: expected %q got %q", "hellohello", count.S)
+ }
+ conn.Close()
+}
+
+func TestWithQuery(t *testing.T) {
+ once.Do(startServer)
+
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+
+ config := newConfig(t, "/echo")
+ config.Location, err = url.ParseRequestURI(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+
+ ws, err := NewClient(config, client)
+ if err != nil {
+ t.Errorf("WebSocket handshake: %v", err)
+ return
+ }
+ ws.Close()
+}
+
+func testWithProtocol(t *testing.T, subproto []string) (string, error) {
+ once.Do(startServer)
+
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+
+ config := newConfig(t, "/subproto")
+ config.Protocol = subproto
+
+ ws, err := NewClient(config, client)
+ if err != nil {
+ return "", err
+ }
+ msg := make([]byte, 16)
+ n, err := ws.Read(msg)
+ if err != nil {
+ return "", err
+ }
+ ws.Close()
+ return string(msg[:n]), nil
+}
+
+func TestWithProtocol(t *testing.T) {
+ proto, err := testWithProtocol(t, []string{"chat"})
+ if err != nil {
+ t.Errorf("SubProto: unexpected error: %v", err)
+ }
+ if proto != "chat" {
+ t.Errorf("SubProto: expected %q, got %q", "chat", proto)
+ }
+}
+
+func TestWithTwoProtocol(t *testing.T) {
+ proto, err := testWithProtocol(t, []string{"test", "chat"})
+ if err != nil {
+ t.Errorf("SubProto: unexpected error: %v", err)
+ }
+ if proto != "chat" {
+ t.Errorf("SubProto: expected %q, got %q", "chat", proto)
+ }
+}
+
+func TestWithBadProtocol(t *testing.T) {
+ _, err := testWithProtocol(t, []string{"test"})
+ if err != ErrBadStatus {
+ t.Errorf("SubProto: expected %v, got %v", ErrBadStatus, err)
+ }
+}
+
+func TestHTTP(t *testing.T) {
+ once.Do(startServer)
+
+ // If the client did not send a handshake that matches the protocol
+ // specification, the server MUST return an HTTP response with an
+ // appropriate error code (such as 400 Bad Request)
+ resp, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
+ if err != nil {
+ t.Errorf("Get: error %#v", err)
+ return
+ }
+ if resp == nil {
+ t.Error("Get: resp is null")
+ return
+ }
+ if resp.StatusCode != http.StatusBadRequest {
+ t.Errorf("Get: expected %q got %q", http.StatusBadRequest, resp.StatusCode)
+ }
+}
+
+func TestTrailingSpaces(t *testing.T) {
+ // http://code.google.com/p/go/issues/detail?id=955
+ // The last runs of this create keys with trailing spaces that should not be
+ // generated by the client.
+ once.Do(startServer)
+ config := newConfig(t, "/echo")
+ for i := 0; i < 30; i++ {
+ // body
+ ws, err := DialConfig(config)
+ if err != nil {
+ t.Errorf("Dial #%d failed: %v", i, err)
+ break
+ }
+ ws.Close()
+ }
+}
+
+func TestDialConfigBadVersion(t *testing.T) {
+ once.Do(startServer)
+ config := newConfig(t, "/echo")
+ config.Version = 1234
+
+ _, err := DialConfig(config)
+
+ if dialerr, ok := err.(*DialError); ok {
+ if dialerr.Err != ErrBadProtocolVersion {
+ t.Errorf("dial expected err %q but got %q", ErrBadProtocolVersion, dialerr.Err)
+ }
+ }
+}
+
+func TestSmallBuffer(t *testing.T) {
+ // http://code.google.com/p/go/issues/detail?id=1145
+ // Read should be able to handle reading a fragment of a frame.
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/echo"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ msg := []byte("hello, world\n")
+ if _, err := conn.Write(msg); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ var small_msg = make([]byte, 8)
+ n, err := conn.Read(small_msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if !bytes.Equal(msg[:len(small_msg)], small_msg) {
+ t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
+ }
+ var second_msg = make([]byte, len(msg))
+ n, err = conn.Read(second_msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ second_msg = second_msg[0:n]
+ if !bytes.Equal(msg[len(small_msg):], second_msg) {
+ t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
+ }
+ conn.Close()
+}
+
+var parseAuthorityTests = []struct {
+ in *url.URL
+ out string
+}{
+ {
+ &url.URL{
+ Scheme: "ws",
+ Host: "www.google.com",
+ },
+ "www.google.com:80",
+ },
+ {
+ &url.URL{
+ Scheme: "wss",
+ Host: "www.google.com",
+ },
+ "www.google.com:443",
+ },
+ {
+ &url.URL{
+ Scheme: "ws",
+ Host: "www.google.com:80",
+ },
+ "www.google.com:80",
+ },
+ {
+ &url.URL{
+ Scheme: "wss",
+ Host: "www.google.com:443",
+ },
+ "www.google.com:443",
+ },
+ // some invalid ones for parseAuthority. parseAuthority doesn't
+ // concern itself with the scheme unless it actually knows about it
+ {
+ &url.URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ },
+ "www.google.com",
+ },
+ {
+ &url.URL{
+ Scheme: "http",
+ Host: "www.google.com:80",
+ },
+ "www.google.com:80",
+ },
+ {
+ &url.URL{
+ Scheme: "asdf",
+ Host: "127.0.0.1",
+ },
+ "127.0.0.1",
+ },
+ {
+ &url.URL{
+ Scheme: "asdf",
+ Host: "www.google.com",
+ },
+ "www.google.com",
+ },
+}
+
+func TestParseAuthority(t *testing.T) {
+ for _, tt := range parseAuthorityTests {
+ out := parseAuthority(tt.in)
+ if out != tt.out {
+ t.Errorf("got %v; want %v", out, tt.out)
+ }
+ }
+}
diff --git a/accounts/account_manager.go b/accounts/account_manager.go
index 74006395c..34cf0fa53 100644
--- a/accounts/account_manager.go
+++ b/accounts/account_manager.go
@@ -100,7 +100,7 @@ func (am *Manager) Lock(addr common.Address) error {
am.mutex.Lock()
if unl, found := am.unlocked[addr]; found {
am.mutex.Unlock()
- am.expire(addr, unl, time.Duration(0) * time.Nanosecond)
+ am.expire(addr, unl, time.Duration(0)*time.Nanosecond)
} else {
am.mutex.Unlock()
}
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index cdafab7fa..3d0251f08 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -24,23 +24,16 @@ import (
"os/signal"
"path/filepath"
"regexp"
- "strings"
-
"sort"
+ "strings"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/natspec"
"github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/eth"
re "github.com/ethereum/go-ethereum/jsre"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/rpc/api"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/comms"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
"github.com/peterh/liner"
"github.com/robertkrimen/otto"
)
@@ -79,82 +72,90 @@ func (r dumbterm) AppendHistory(string) {}
type jsre struct {
re *re.JSRE
stack *node.Node
- xeth *xeth.XEth
wait chan *big.Int
ps1 string
atexit func()
corsDomain string
- client comms.EthereumClient
+ client rpc.Client
prompter
}
var (
- loadedModulesMethods map[string][]string
+ loadedModulesMethods map[string][]string
+ autoCompleteStatement = "function _autocomplete(obj) {var results = []; for (var e in obj) { results.push(e); }; return results; }; _autocomplete(%s)"
)
-func keywordCompleter(line string) []string {
- results := make([]string, 0)
-
- if strings.Contains(line, ".") {
- elements := strings.Split(line, ".")
- if len(elements) == 2 {
- module := elements[0]
- partialMethod := elements[1]
- if methods, found := loadedModulesMethods[module]; found {
- for _, method := range methods {
- if strings.HasPrefix(method, partialMethod) { // e.g. debug.se
- results = append(results, module+"."+method)
- }
- }
- }
- }
- } else {
- for module, methods := range loadedModulesMethods {
- if line == module { // user typed in full module name, show all methods
- for _, method := range methods {
- results = append(results, module+"."+method)
+func keywordCompleter(jsre *jsre, line string) []string {
+ var results []string
+ parts := strings.Split(line, ".")
+ objRef := "this"
+ prefix := line
+ if len(parts) > 1 {
+ objRef = strings.Join(parts[0:len(parts) - 1], ".")
+ prefix = parts[len(parts) - 1]
+ }
+
+ result, _ := jsre.re.Run(fmt.Sprintf(autoCompleteStatement, objRef))
+ raw, _ := result.Export()
+ if keys, ok := raw.([]interface{}); ok {
+ for _, k := range keys {
+ if strings.HasPrefix(fmt.Sprintf("%s", k), prefix) {
+ if objRef == "this" {
+ results = append(results, fmt.Sprintf("%s", k))
+ } else {
+ results = append(results, fmt.Sprintf("%s.%s", strings.Join(parts[:len(parts) - 1], "."), k))
}
- } else if strings.HasPrefix(module, line) { // partial method name, e.g. admi
- results = append(results, module)
}
}
}
- return results
-}
-func apiWordCompleter(line string, pos int) (head string, completions []string, tail string) {
- if len(line) == 0 || pos == 0 {
- return "", nil, ""
+ // e.g. web3<tab><tab> append dot since its an object
+ isObj, _ := jsre.re.Run(fmt.Sprintf("typeof(%s) === 'object'", line))
+ if isObject, _ := isObj.ToBoolean(); isObject {
+ results = append(results, line + ".")
}
- i := 0
- for i = pos - 1; i > 0; i-- {
- if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') {
- continue
+ sort.Strings(results)
+ return results
+}
+
+func apiWordCompleterWithContext(jsre *jsre) liner.WordCompleter {
+ completer := func(line string, pos int) (head string, completions []string, tail string) {
+ if len(line) == 0 || pos == 0 {
+ return "", nil, ""
}
- if i >= 3 && line[i] == '3' && line[i-3] == 'w' && line[i-2] == 'e' && line[i-1] == 'b' {
- continue
+
+ // chuck data to relevant part for autocompletion, e.g. in case of nested lines eth.getBalance(eth.coinb<tab><tab>
+ i := 0
+ for i = pos - 1; i > 0; i-- {
+ if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') {
+ continue
+ }
+ if i >= 3 && line[i] == '3' && line[i - 3] == 'w' && line[i - 2] == 'e' && line[i - 1] == 'b' {
+ continue
+ }
+ i += 1
+ break
}
- i += 1
- break
- }
- begin := line[:i]
- keyword := line[i:pos]
- end := line[pos:]
+ begin := line[:i]
+ keyword := line[i:pos]
+ end := line[pos:]
+
+ completionWords := keywordCompleter(jsre, keyword)
+ return begin, completionWords, end
+ }
- completionWords := keywordCompleter(keyword)
- return begin, completionWords, end
+ return completer
}
-func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir string, interactive bool) *jsre {
+func newLightweightJSRE(docRoot string, client rpc.Client, datadir string, interactive bool) *jsre {
js := &jsre{ps1: "> "}
js.wait = make(chan *big.Int)
js.client = client
- // update state in separare forever blocks
js.re = re.New(docRoot)
- if err := js.apiBindings(js); err != nil {
+ if err := js.apiBindings(); err != nil {
utils.Fatalf("Unable to initialize console - %v", err)
}
@@ -165,7 +166,7 @@ func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir str
js.withHistory(datadir, func(hist *os.File) { lr.ReadHistory(hist) })
lr.SetCtrlCAborts(true)
js.loadAutoCompletion()
- lr.SetWordCompleter(apiWordCompleter)
+ lr.SetWordCompleter(apiWordCompleterWithContext(js))
lr.SetTabCompletionStyle(liner.TabPrints)
js.prompter = lr
js.atexit = func() {
@@ -177,25 +178,15 @@ func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir str
return js
}
-func newJSRE(stack *node.Node, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
+func newJSRE(stack *node.Node, docRoot, corsDomain string, client rpc.Client, interactive bool) *jsre {
js := &jsre{stack: stack, ps1: "> "}
// set default cors domain used by startRpc from CLI flag
js.corsDomain = corsDomain
- if f == nil {
- f = js
- }
- js.xeth = xeth.New(stack, f)
- js.wait = js.xeth.UpdateState()
+ js.wait = make(chan *big.Int)
js.client = client
- if clt, ok := js.client.(*comms.InProcClient); ok {
- if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, stack); err == nil {
- clt.Initialize(api.Merge(offeredApis...))
- }
- }
- // update state in separare forever blocks
js.re = re.New(docRoot)
- if err := js.apiBindings(f); err != nil {
+ if err := js.apiBindings(); err != nil {
utils.Fatalf("Unable to connect - %v", err)
}
@@ -206,7 +197,7 @@ func newJSRE(stack *node.Node, docRoot, corsDomain string, client comms.Ethereum
js.withHistory(stack.DataDir(), func(hist *os.File) { lr.ReadHistory(hist) })
lr.SetCtrlCAborts(true)
js.loadAutoCompletion()
- lr.SetWordCompleter(apiWordCompleter)
+ lr.SetWordCompleter(apiWordCompleterWithContext(js))
lr.SetTabCompletionStyle(liner.TabPrints)
js.prompter = lr
js.atexit = func() {
@@ -222,7 +213,7 @@ func (self *jsre) loadAutoCompletion() {
if modules, err := self.supportedApis(); err == nil {
loadedModulesMethods = make(map[string][]string)
for module, _ := range modules {
- loadedModulesMethods[module] = api.AutoCompletion[module]
+ loadedModulesMethods[module] = rpc.AutoCompletion[module]
}
}
}
@@ -258,7 +249,6 @@ func (self *jsre) welcome() {
loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version))
}
sort.Strings(loadedModules)
-
}
}
@@ -266,7 +256,7 @@ func (self *jsre) supportedApis() (map[string]string, error) {
return self.client.SupportedModules()
}
-func (js *jsre) apiBindings(f xeth.Frontend) error {
+func (js *jsre) apiBindings() error {
apis, err := js.supportedApis()
if err != nil {
return err
@@ -277,12 +267,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
apiNames = append(apiNames, a)
}
- apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.stack)
- if err != nil {
- utils.Fatalf("Unable to determine supported api's: %v", err)
- }
-
- jeth := rpc.NewJeth(api.Merge(apiImpl...), js.re, js.client, f)
+ jeth := utils.NewJeth(js.re, js.client)
js.re.Set("jeth", struct{}{})
t, _ := js.re.Get("jeth")
jethObj := t.Object()
@@ -313,14 +298,16 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
// load only supported API's in javascript runtime
shortcuts := "var eth = web3.eth; "
for _, apiName := range apiNames {
- if apiName == shared.Web3ApiName {
- continue // manually mapped
+ if apiName == "web3" || apiName == "rpc" {
+ continue // manually mapped or ignore
}
- if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), api.Javascript(apiName)); err == nil {
- shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName)
- } else {
- utils.Fatalf("Error loading %s.js: %v", apiName, err)
+ if jsFile, ok := rpc.WEB3Extensions[apiName]; ok {
+ if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), jsFile); err == nil {
+ shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName)
+ } else {
+ utils.Fatalf("Error loading %s.js: %v", apiName, err)
+ }
}
}
@@ -375,14 +362,13 @@ func (self *jsre) ConfirmTransaction(tx string) bool {
return false
}
// If natspec is enabled, ask for permission
- if ethereum.NatSpec {
- notice := natspec.GetNotice(self.xeth, tx, ethereum.HTTPClient())
- fmt.Println(notice)
- answer, _ := self.Prompt("Confirm Transaction [y/n]")
- return strings.HasPrefix(strings.Trim(answer, " "), "y")
- } else {
- return true
+ if ethereum.NatSpec && false /* disabled for now */ {
+ // notice := natspec.GetNotice(self.xeth, tx, ethereum.HTTPClient())
+ // fmt.Println(notice)
+ // answer, _ := self.Prompt("Confirm Transaction [y/n]")
+ // return strings.HasPrefix(strings.Trim(answer, " "), "y")
}
+ return true
}
func (self *jsre) UnlockAccount(addr []byte) bool {
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index ca636188f..19583c5ef 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -32,30 +32,27 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/common/httpclient"
- "github.com/ethereum/go-ethereum/common/natspec"
- "github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/comms"
+ "github.com/ethereum/go-ethereum/cmd/utils"
)
const (
testSolcPath = ""
- solcVersion = "0.9.23"
+ solcVersion = "0.9.23"
- testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
+ testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
testBalance = "10000000000000000000"
- // of empty string
+// of empty string
testHash = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)
var (
- versionRE = regexp.MustCompile(strconv.Quote(`"compilerVersion":"` + solcVersion + `"`))
+ versionRE = regexp.MustCompile(strconv.Quote(`"compilerVersion":"` + solcVersion + `"`))
testNodeKey = crypto.ToECDSA(common.Hex2Bytes("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f"))
testGenesis = `{"` + testAddress[2:] + `": {"balance": "` + testBalance + `"}}`
)
@@ -77,15 +74,16 @@ func (self *testjethre) UnlockAccount(acc []byte) bool {
return true
}
-func (self *testjethre) ConfirmTransaction(tx string) bool {
- var ethereum *eth.Ethereum
- self.stack.Service(&ethereum)
-
- if ethereum.NatSpec {
- self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.client)
- }
- return true
-}
+// Temporary disabled while natspec hasn't been migrated
+//func (self *testjethre) ConfirmTransaction(tx string) bool {
+// var ethereum *eth.Ethereum
+// self.stack.Service(&ethereum)
+//
+// if ethereum.NatSpec {
+// self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.client)
+// }
+// return true
+//}
func testJEthRE(t *testing.T) (string, *testjethre, *node.Node) {
return testREPL(t, nil)
@@ -118,7 +116,9 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
if config != nil {
config(ethConf)
}
- if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
+ if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
+ return eth.New(ctx, ethConf)
+ }); err != nil {
t.Fatalf("failed to register ethereum protocol: %v", err)
}
// Initialize all the keys for testing
@@ -141,9 +141,10 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
stack.Service(&ethereum)
assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
- client := comms.NewInProcClient(codec.JSON)
+ //client := comms.NewInProcClient(codec.JSON)
+ client := utils.NewInProcRPCClient(stack)
tf := &testjethre{client: ethereum.HTTPClient()}
- repl := newJSRE(stack, assetPath, "", client, false, tf)
+ repl := newJSRE(stack, assetPath, "", client, false)
tf.jsre = repl
return tmp, tf, stack
}
@@ -166,8 +167,8 @@ func TestAccounts(t *testing.T) {
defer node.Stop()
defer os.RemoveAll(tmp)
- checkEvalJSON(t, repl, `eth.accounts`, `["`+testAddress+`"]`)
- checkEvalJSON(t, repl, `eth.coinbase`, `"`+testAddress+`"`)
+ checkEvalJSON(t, repl, `eth.accounts`, `["` + testAddress + `"]`)
+ checkEvalJSON(t, repl, `eth.coinbase`, `"` + testAddress + `"`)
val, err := repl.re.Run(`jeth.newAccount("password")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
@@ -177,7 +178,7 @@ func TestAccounts(t *testing.T) {
t.Errorf("address not hex: %q", addr)
}
- checkEvalJSON(t, repl, `eth.accounts`, `["`+testAddress+`","`+addr+`"]`)
+ checkEvalJSON(t, repl, `eth.accounts`, `["` + testAddress + `","` + addr + `"]`)
}
@@ -205,13 +206,13 @@ func TestBlockChain(t *testing.T) {
node.Service(&ethereum)
ethereum.BlockChain().Reset()
- checkEvalJSON(t, repl, `admin.exportChain(`+tmpfileq+`)`, `true`)
+ checkEvalJSON(t, repl, `admin.exportChain(` + tmpfileq + `)`, `true`)
if _, err := os.Stat(tmpfile); err != nil {
t.Fatal(err)
}
// check import, verify that dumpBlock gives the same result.
- checkEvalJSON(t, repl, `admin.importChain(`+tmpfileq+`)`, `true`)
+ checkEvalJSON(t, repl, `admin.importChain(` + tmpfileq + `)`, `true`)
checkEvalJSON(t, repl, `debug.dumpBlock(eth.blockNumber)`, beforeExport)
}
@@ -239,7 +240,7 @@ func TestCheckTestAccountBalance(t *testing.T) {
defer os.RemoveAll(tmp)
repl.re.Run(`primary = "` + testAddress + `"`)
- checkEvalJSON(t, repl, `eth.getBalance(primary)`, `"`+testBalance+`"`)
+ checkEvalJSON(t, repl, `eth.getBalance(primary)`, `"` + testBalance + `"`)
}
func TestSignature(t *testing.T) {
@@ -278,19 +279,20 @@ func TestContract(t *testing.T) {
defer ethereum.Stop()
defer os.RemoveAll(tmp)
- reg := registrar.New(repl.xeth)
- _, err := reg.SetGlobalRegistrar("", coinbase)
- if err != nil {
- t.Errorf("error setting HashReg: %v", err)
- }
- _, err = reg.SetHashReg("", coinbase)
- if err != nil {
- t.Errorf("error setting HashReg: %v", err)
- }
- _, err = reg.SetUrlHint("", coinbase)
- if err != nil {
- t.Errorf("error setting HashReg: %v", err)
- }
+ // Temporary disabled while registrar isn't migrated
+ //reg := registrar.New(repl.xeth)
+ //_, err := reg.SetGlobalRegistrar("", coinbase)
+ //if err != nil {
+ // t.Errorf("error setting HashReg: %v", err)
+ //}
+ //_, err = reg.SetHashReg("", coinbase)
+ //if err != nil {
+ // t.Errorf("error setting HashReg: %v", err)
+ //}
+ //_, err = reg.SetUrlHint("", coinbase)
+ //if err != nil {
+ // t.Errorf("error setting HashReg: %v", err)
+ //}
/* TODO:
* lookup receipt and contract addresses by tx hash
* name registration for HashReg and UrlHint addresses
@@ -299,11 +301,11 @@ func TestContract(t *testing.T) {
*/
source := `contract test {\n` +
- " /// @notice Will multiply `a` by 7." + `\n` +
- ` function multiply(uint a) returns(uint d) {\n` +
- ` return a * 7;\n` +
- ` }\n` +
- `}\n`
+ " /// @notice Will multiply `a` by 7." + `\n` +
+ ` function multiply(uint a) returns(uint d) {\n` +
+ ` return a * 7;\n` +
+ ` }\n` +
+ `}\n`
if checkEvalJSON(t, repl, `admin.stopNatSpec()`, `true`) != nil {
return
@@ -313,10 +315,10 @@ func TestContract(t *testing.T) {
if err != nil {
t.Fatalf("%v", err)
}
- if checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`) != nil {
+ if checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"` + testAddress + `"`) != nil {
return
}
- if checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`) != nil {
+ if checkEvalJSON(t, repl, `source = "` + source + `"`, `"` + source + `"`) != nil {
return
}
@@ -394,7 +396,7 @@ multiply7 = Multiply7.at(contractaddress);
var contentHash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"`
if sol != nil && solcVersion != sol.Version() {
- modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"`+sol.Version()+`"`))
+ modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"` + sol.Version() + `"`))
fmt.Printf("modified contractinfo:\n%s\n", modContractInfo)
contentHash = `"` + common.ToHex(crypto.Sha3([]byte(modContractInfo))) + `"`
}
@@ -474,11 +476,12 @@ func processTxs(repl *testjethre, t *testing.T, expTxc int) bool {
defer ethereum.StopMining()
timer := time.NewTimer(100 * time.Second)
- height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1))
+ blockNr := ethereum.BlockChain().CurrentBlock().Number()
+ height := new(big.Int).Add(blockNr, big.NewInt(1))
repl.wait <- height
select {
case <-timer.C:
- // if times out make sure the xeth loop does not block
+ // if times out make sure the xeth loop does not block
go func() {
select {
case repl.wait <- nil:
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index f2bb27552..e6d190914 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -40,8 +40,6 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/comms"
)
const (
@@ -263,11 +261,11 @@ See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
Name: "attach",
Usage: `Geth Console: interactive JavaScript environment (connect to node)`,
Description: `
-The Geth console is an interactive shell for the JavaScript runtime environment
-which exposes a node admin interface as well as the Ðapp JavaScript API.
-See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
-This command allows to open a console on a running geth node.
-`,
+ The Geth console is an interactive shell for the JavaScript runtime environment
+ which exposes a node admin interface as well as the Ðapp JavaScript API.
+ See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
+ This command allows to open a console on a running geth node.
+ `,
},
{
Action: execScripts,
@@ -309,11 +307,15 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
- utils.RpcApiFlag,
+ utils.RPCApiFlag,
+ utils.WSEnabledFlag,
+ utils.WSListenAddrFlag,
+ utils.WSPortFlag,
+ utils.WSApiFlag,
+ utils.WSAllowedDomainsFlag,
utils.IPCDisabledFlag,
utils.IPCApiFlag,
utils.IPCPathFlag,
- utils.IPCExperimental,
utils.ExecFlag,
utils.WhisperEnabledFlag,
utils.DevModeFlag,
@@ -392,20 +394,12 @@ func geth(ctx *cli.Context) {
node.Wait()
}
+// attach will connect to a running geth instance attaching a JavaScript console and to it.
func attach(ctx *cli.Context) {
- var client comms.EthereumClient
- var err error
- if ctx.Args().Present() {
- client, err = comms.ClientFromEndpoint(ctx.Args().First(), codec.JSON)
- } else {
- cfg := comms.IpcConfig{
- Endpoint: utils.IpcSocketPath(ctx),
- }
- client, err = comms.NewIpcClient(cfg, codec.JSON)
- }
-
+ // attach to a running geth instance
+ client, err := utils.NewRemoteRPCClient(ctx)
if err != nil {
- utils.Fatalf("Unable to attach to geth node - %v", err)
+ utils.Fatalf("Unable to attach to geth - %v", err)
}
repl := newLightweightJSRE(
@@ -431,11 +425,12 @@ func console(ctx *cli.Context) {
startNode(ctx, node)
// Attach to the newly started node, and either execute script or become interactive
- client := comms.NewInProcClient(codec.JSON)
+ client := utils.NewInProcRPCClient(node)
+
repl := newJSRE(node,
ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
- client, true, nil)
+ client, true)
if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
repl.batch(script)
@@ -454,11 +449,12 @@ func execScripts(ctx *cli.Context) {
startNode(ctx, node)
// Attach to the newly started node and execute the given scripts
- client := comms.NewInProcClient(codec.JSON)
+ client := utils.NewInProcRPCClient(node)
+
repl := newJSRE(node,
ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
- client, false, nil)
+ client, false)
for _, file := range ctx.Args() {
repl.exec(file)
@@ -517,6 +513,11 @@ func startNode(ctx *cli.Context, stack *node.Node) {
utils.Fatalf("Failed to start RPC: %v", err)
}
}
+ if ctx.GlobalBool(utils.WSEnabledFlag.Name) {
+ if err := utils.StartWS(stack, ctx); err != nil {
+ utils.Fatalf("Failed to start WS: %v", err)
+ }
+ }
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
utils.Fatalf("Failed to start mining: %v", err)
diff --git a/cmd/geth/monitorcmd.go b/cmd/geth/monitorcmd.go
index a45d29b8f..1d7bf3f6a 100644
--- a/cmd/geth/monitorcmd.go
+++ b/cmd/geth/monitorcmd.go
@@ -21,16 +21,15 @@ import (
"math"
"reflect"
"runtime"
- "sort"
"strings"
"time"
+ "sort"
+
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/comms"
"github.com/gizak/termui"
)
@@ -70,20 +69,18 @@ to display multiple metrics simultaneously.
// monitor starts a terminal UI based monitoring tool for the requested metrics.
func monitor(ctx *cli.Context) {
var (
- client comms.EthereumClient
+ client rpc.Client
err error
)
// Attach to an Ethereum node over IPC or RPC
endpoint := ctx.String(monitorCommandAttachFlag.Name)
- if client, err = comms.ClientFromEndpoint(endpoint, codec.JSON); err != nil {
+ if client, err = utils.NewRemoteRPCClientFromString(endpoint); err != nil {
utils.Fatalf("Unable to attach to geth node: %v", err)
}
defer client.Close()
- xeth := rpc.NewXeth(client)
-
// Retrieve all the available metrics and resolve the user pattens
- metrics, err := retrieveMetrics(xeth)
+ metrics, err := retrieveMetrics(client)
if err != nil {
utils.Fatalf("Failed to retrieve system metrics: %v", err)
}
@@ -133,7 +130,7 @@ func monitor(ctx *cli.Context) {
}
termui.Body.AddRows(termui.NewRow(termui.NewCol(12, 0, footer)))
- refreshCharts(xeth, monitored, data, units, charts, ctx, footer)
+ refreshCharts(client, monitored, data, units, charts, ctx, footer)
termui.Body.Align()
termui.Render(termui.Body)
@@ -154,7 +151,7 @@ func monitor(ctx *cli.Context) {
termui.Render(termui.Body)
}
case <-refresh:
- if refreshCharts(xeth, monitored, data, units, charts, ctx, footer) {
+ if refreshCharts(client, monitored, data, units, charts, ctx, footer) {
termui.Body.Align()
}
termui.Render(termui.Body)
@@ -164,8 +161,30 @@ func monitor(ctx *cli.Context) {
// retrieveMetrics contacts the attached geth node and retrieves the entire set
// of collected system metrics.
-func retrieveMetrics(xeth *rpc.Xeth) (map[string]interface{}, error) {
- return xeth.Call("debug_metrics", []interface{}{true})
+func retrieveMetrics(client rpc.Client) (map[string]interface{}, error) {
+ req := map[string]interface{}{
+ "id": new(int64),
+ "method": "debug_metrics",
+ "jsonrpc": "2.0",
+ "params": []interface{}{true},
+ }
+
+ if err := client.Send(req); err != nil {
+ return nil, err
+ }
+
+ var res rpc.JSONSuccessResponse
+ if err := client.Recv(&res); err != nil {
+ return nil, err
+ }
+
+ if res.Result != nil {
+ if mets, ok := res.Result.(map[string]interface{}); ok {
+ return mets, nil
+ }
+ }
+
+ return nil, fmt.Errorf("unable to retrieve metrics")
}
// resolveMetrics takes a list of input metric patterns, and resolves each to one
@@ -253,8 +272,8 @@ func fetchMetric(metrics map[string]interface{}, metric string) float64 {
// refreshCharts retrieves a next batch of metrics, and inserts all the new
// values into the active datasets and charts
-func refreshCharts(xeth *rpc.Xeth, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
- values, err := retrieveMetrics(xeth)
+func refreshCharts(client rpc.Client, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
+ values, err := retrieveMetrics(client)
for i, metric := range metrics {
if len(data) < 512 {
data[i] = append([]float64{fetchMetric(values, metric)}, data[i]...)
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index 7a6ff704c..a9fce6418 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -87,7 +87,12 @@ var AppHelpFlagGroups = []flagGroup{
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
- utils.RpcApiFlag,
+ utils.RPCApiFlag,
+ utils.WSEnabledFlag,
+ utils.WSListenAddrFlag,
+ utils.WSPortFlag,
+ utils.WSApiFlag,
+ utils.WSAllowedDomainsFlag,
utils.IPCDisabledFlag,
utils.IPCApiFlag,
utils.IPCPathFlag,
@@ -158,7 +163,6 @@ var AppHelpFlagGroups = []flagGroup{
Flags: []cli.Flag{
utils.WhisperEnabledFlag,
utils.NatspecEnabledFlag,
- utils.IPCExperimental,
},
},
{
diff --git a/cmd/gethrpctest/main.go b/cmd/gethrpctest/main.go
index ae815c4a6..b4530ca51 100644
--- a/cmd/gethrpctest/main.go
+++ b/cmd/gethrpctest/main.go
@@ -26,8 +26,9 @@ import (
"path/filepath"
"runtime"
+ "errors"
+
"github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
@@ -35,13 +36,9 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/rpc/api"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/comms"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/tests"
"github.com/ethereum/go-ethereum/whisper"
- "github.com/ethereum/go-ethereum/xeth"
)
const defaultTestKey = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
@@ -176,21 +173,25 @@ func RunTest(stack *node.Node, test *tests.BlockTest) error {
// StartRPC initializes an RPC interface to the given protocol stack.
func StartRPC(stack *node.Node) error {
- config := comms.HttpConfig{
- ListenAddress: "127.0.0.1",
- ListenPort: 8545,
+ /*
+ web3 := NewPublicWeb3API(stack)
+ server.RegisterName("web3", web3)
+ net := NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
+ server.RegisterName("net", net)
+ */
+
+ for _, api := range stack.APIs() {
+ if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
+ _, err := adminApi.StartRPC("127.0.0.1", 8545, "", "admin,db,eth,debug,miner,net,shh,txpool,personal,web3")
+ return err
+ }
}
- xeth := xeth.New(stack, nil)
- codec := codec.JSON
- apis, err := api.ParseApiString(comms.DefaultHttpRpcApis, codec, xeth, stack)
- if err != nil {
- return err
- }
- return comms.StartHttp(config, codec, api.Merge(apis...))
+ glog.V(logger.Error).Infof("Unable to start RPC-HTTP interface, could not find admin API")
+ return errors.New("Unable to start RPC-HTTP interface")
}
-// StartRPC initializes an IPC interface to the given protocol stack.
+// StartIPC initializes an IPC interface to the given protocol stack.
func StartIPC(stack *node.Node) error {
var ethereum *eth.Ethereum
if err := stack.Service(&ethereum); err != nil {
@@ -202,11 +203,7 @@ func StartIPC(stack *node.Node) error {
endpoint = filepath.Join(common.DefaultDataDir(), "geth.ipc")
}
- config := comms.IpcConfig{
- Endpoint: endpoint,
- }
-
- listener, err := comms.CreateListener(config)
+ listener, err := rpc.CreateIPCListener(endpoint)
if err != nil {
return err
}
@@ -217,16 +214,16 @@ func StartIPC(stack *node.Node) error {
offered := stack.APIs()
for _, api := range offered {
server.RegisterName(api.Namespace, api.Service)
- glog.V(logger.Debug).Infof("Register %T@%s for IPC service\n", api.Service, api.Namespace)
+ glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace)
}
- web3 := utils.NewPublicWeb3API(stack)
- server.RegisterName("web3", web3)
- net := utils.NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
- server.RegisterName("net", net)
+ //var ethereum *eth.Ethereum
+ //if err := stack.Service(&ethereum); err != nil {
+ // return err
+ //}
go func() {
- glog.V(logger.Info).Infof("Start IPC server on %s\n", config.Endpoint)
+ glog.V(logger.Info).Infof("Start IPC server on %s\n", endpoint)
for {
conn, err := listener.Accept()
if err != nil {
diff --git a/cmd/utils/api.go b/cmd/utils/api.go
deleted file mode 100644
index 59f0dab74..000000000
--- a/cmd/utils/api.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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 utils
-
-import (
- "fmt"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/p2p"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
-)
-
-// PublicWeb3API offers helper utils
-type PublicWeb3API struct {
- stack *node.Node
-}
-
-// NewPublicWeb3API creates a new Web3Service instance
-func NewPublicWeb3API(stack *node.Node) *PublicWeb3API {
- return &PublicWeb3API{stack}
-}
-
-// ClientVersion returns the node name
-func (s *PublicWeb3API) ClientVersion() string {
- return s.stack.Server().Name
-}
-
-// Sha3 applies the ethereum sha3 implementation on the input.
-// It assumes the input is hex encoded.
-func (s *PublicWeb3API) Sha3(input string) string {
- return common.ToHex(crypto.Sha3(common.FromHex(input)))
-}
-
-// PublicNetAPI offers network related RPC methods
-type PublicNetAPI struct {
- net *p2p.Server
- networkVersion int
-}
-
-// NewPublicNetAPI creates a new net api instance.
-func NewPublicNetAPI(net *p2p.Server, networkVersion int) *PublicNetAPI {
- return &PublicNetAPI{net, networkVersion}
-}
-
-// Listening returns an indication if the node is listening for network connections.
-func (s *PublicNetAPI) Listening() bool {
- return true // always listening
-}
-
-// Peercount returns the number of connected peers
-func (s *PublicNetAPI) PeerCount() *rpc.HexNumber {
- return rpc.NewHexNumber(s.net.PeerCount())
-}
-
-// ProtocolVersion returns the current ethereum protocol version.
-func (s *PublicNetAPI) Version() string {
- return fmt.Sprintf("%d", s.networkVersion)
-}
diff --git a/cmd/utils/client.go b/cmd/utils/client.go
new file mode 100644
index 000000000..bac456491
--- /dev/null
+++ b/cmd/utils/client.go
@@ -0,0 +1,176 @@
+// 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 utils
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "strings"
+
+ "github.com/codegangsta/cli"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// NewInProcRPCClient will start a new RPC server for the given node and returns a client to interact with it.
+func NewInProcRPCClient(stack *node.Node) *inProcClient {
+ server := rpc.NewServer()
+
+ offered := stack.APIs()
+ for _, api := range offered {
+ server.RegisterName(api.Namespace, api.Service)
+ }
+
+ web3 := node.NewPublicWeb3API(stack)
+ server.RegisterName("web3", web3)
+
+ var ethereum *eth.Ethereum
+ if err := stack.Service(&ethereum); err == nil {
+ net := eth.NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
+ server.RegisterName("net", net)
+ } else {
+ glog.V(logger.Warn).Infof("%v\n", err)
+ }
+
+ buf := &buf{
+ requests: make(chan []byte),
+ responses: make(chan []byte),
+ }
+ client := &inProcClient{
+ server: server,
+ buf: buf,
+ }
+
+ go func() {
+ server.ServeCodec(rpc.NewJSONCodec(client.buf))
+ }()
+
+ return client
+}
+
+// buf represents the connection between the RPC server and console
+type buf struct {
+ readBuf []byte // store remaining request bytes after a partial read
+ requests chan []byte // list with raw serialized requests
+ responses chan []byte // list with raw serialized responses
+}
+
+// will read the next request in json format
+func (b *buf) Read(p []byte) (int, error) {
+ // last read didn't read entire request, return remaining bytes
+ if len(b.readBuf) > 0 {
+ n := copy(p, b.readBuf)
+ if n < len(b.readBuf) {
+ b.readBuf = b.readBuf[:n]
+ } else {
+ b.readBuf = b.readBuf[:0]
+ }
+ return n, nil
+ }
+
+ // read next request
+ req := <-b.requests
+ n := copy(p, req)
+ if n < len(req) {
+ // buf too small, store remaining chunk for next read
+ b.readBuf = req[n:]
+ }
+
+ return n, nil
+}
+
+// Write send the given buffer to the backend
+func (b *buf) Write(p []byte) (n int, err error) {
+ b.responses <- p
+ return len(p), nil
+}
+
+// Close cleans up obtained resources.
+func (b *buf) Close() error {
+ close(b.requests)
+ close(b.responses)
+
+ return nil
+}
+
+// inProcClient starts a RPC server and uses buf to communicate with it.
+type inProcClient struct {
+ server *rpc.Server
+ buf *buf
+}
+
+// Close will stop the RPC server
+func (c *inProcClient) Close() {
+ c.server.Stop()
+}
+
+// Send a msg to the endpoint
+func (c *inProcClient) Send(msg interface{}) error {
+ d, err := json.Marshal(msg)
+ if err != nil {
+ return err
+ }
+ c.buf.requests <- d
+ return nil
+}
+
+// Recv reads a message and tries to parse it into the given msg
+func (c *inProcClient) Recv(msg interface{}) error {
+ data := <-c.buf.responses
+ return json.Unmarshal(data, &msg)
+}
+
+// Returns the collection of modules the RPC server offers.
+func (c *inProcClient) SupportedModules() (map[string]string, error) {
+ return rpc.SupportedModules(c)
+}
+
+// NewRemoteRPCClient returns a RPC client which connects to a running geth instance.
+// Depending on the given context this can either be a IPC or a HTTP client.
+func NewRemoteRPCClient(ctx *cli.Context) (rpc.Client, error) {
+ if ctx.Args().Present() {
+ endpoint := ctx.Args().First()
+ return NewRemoteRPCClientFromString(endpoint)
+ }
+
+ // use IPC by default
+ endpoint := IPCSocketPath(ctx)
+ return rpc.NewIPCClient(endpoint)
+}
+
+// NewRemoteRPCClientFromString returns a RPC client which connects to the given
+// endpoint. It must start with either `ipc:` or `rpc:` (HTTP).
+func NewRemoteRPCClientFromString(endpoint string) (rpc.Client, error) {
+ if strings.HasPrefix(endpoint, "ipc:") {
+ return rpc.NewIPCClient(endpoint[4:])
+ }
+ if strings.HasPrefix(endpoint, "rpc:") {
+ return rpc.NewHTTPClient(endpoint[4:])
+ }
+ if strings.HasPrefix(endpoint, "http://") {
+ return rpc.NewHTTPClient(endpoint)
+ }
+ if strings.HasPrefix(endpoint, "ws:") {
+ return rpc.NewWSClient(endpoint)
+ }
+
+ return nil, fmt.Errorf("invalid endpoint")
+}
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 63efa08ee..9199432d8 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -23,7 +23,6 @@ import (
"log"
"math"
"math/big"
- "net"
"net/http"
"os"
"path/filepath"
@@ -31,6 +30,8 @@ import (
"strconv"
"strings"
+ "errors"
+
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
@@ -49,14 +50,8 @@ import (
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rpc/api"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/comms"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/rpc/useragent"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/whisper"
- "github.com/ethereum/go-ethereum/xeth"
)
func init() {
@@ -282,10 +277,10 @@ var (
Usage: "Domains from which to accept cross origin requests (browser enforced)",
Value: "",
}
- RpcApiFlag = cli.StringFlag{
+ RPCApiFlag = cli.StringFlag{
Name: "rpcapi",
Usage: "API's offered over the HTTP-RPC interface",
- Value: comms.DefaultHttpRpcApis,
+ Value: rpc.DefaultHttpRpcApis,
}
IPCDisabledFlag = cli.BoolFlag{
Name: "ipcdisable",
@@ -294,16 +289,36 @@ var (
IPCApiFlag = cli.StringFlag{
Name: "ipcapi",
Usage: "API's offered over the IPC-RPC interface",
- Value: comms.DefaultIpcApis,
+ Value: rpc.DefaultIpcApis,
}
IPCPathFlag = DirectoryFlag{
Name: "ipcpath",
Usage: "Filename for IPC socket/pipe",
Value: DirectoryString{common.DefaultIpcPath()},
}
- IPCExperimental = cli.BoolFlag{
- Name: "ipcexp",
- Usage: "Enable the new RPC implementation",
+ WSEnabledFlag = cli.BoolFlag{
+ Name: "ws",
+ Usage: "Enable the WS-RPC server",
+ }
+ WSListenAddrFlag = cli.StringFlag{
+ Name: "wsaddr",
+ Usage: "WS-RPC server listening interface",
+ Value: "127.0.0.1",
+ }
+ WSPortFlag = cli.IntFlag{
+ Name: "wsport",
+ Usage: "WS-RPC server listening port",
+ Value: 8546,
+ }
+ WSApiFlag = cli.StringFlag{
+ Name: "wsapi",
+ Usage: "API's offered over the WS-RPC interface",
+ Value: rpc.DefaultHttpRpcApis,
+ }
+ WSAllowedDomainsFlag = cli.StringFlag{
+ Name: "wsdomains",
+ Usage: "Domains from which to accept websockets requests",
+ Value: "",
}
ExecFlag = cli.StringFlag{
Name: "exec",
@@ -760,7 +775,7 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
return chain, chainDb
}
-func IpcSocketPath(ctx *cli.Context) (ipcpath string) {
+func IPCSocketPath(ctx *cli.Context) (ipcpath string) {
if runtime.GOOS == "windows" {
ipcpath = common.DefaultIpcPath()
if ctx.GlobalIsSet(IPCPathFlag.Name) {
@@ -780,79 +795,83 @@ func IpcSocketPath(ctx *cli.Context) (ipcpath string) {
}
func StartIPC(stack *node.Node, ctx *cli.Context) error {
- config := comms.IpcConfig{
- Endpoint: IpcSocketPath(ctx),
- }
-
var ethereum *eth.Ethereum
if err := stack.Service(&ethereum); err != nil {
return err
}
- if ctx.GlobalIsSet(IPCExperimental.Name) {
- listener, err := comms.CreateListener(config)
- if err != nil {
- return err
- }
+ endpoint := IPCSocketPath(ctx)
+ listener, err := rpc.CreateIPCListener(endpoint)
+ if err != nil {
+ return err
+ }
- server := rpc.NewServer()
+ server := rpc.NewServer()
- // register package API's this node provides
- offered := stack.APIs()
- for _, api := range offered {
- server.RegisterName(api.Namespace, api.Service)
- glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace)
- }
+ // register package API's this node provides
+ offered := stack.APIs()
+ for _, api := range offered {
+ server.RegisterName(api.Namespace, api.Service)
+ glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace)
+ }
- web3 := NewPublicWeb3API(stack)
- server.RegisterName("web3", web3)
- net := NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
- server.RegisterName("net", net)
-
- go func() {
- glog.V(logger.Info).Infof("Start IPC server on %s\n", config.Endpoint)
- for {
- conn, err := listener.Accept()
- if err != nil {
- glog.V(logger.Error).Infof("Unable to accept connection - %v\n", err)
- }
-
- codec := rpc.NewJSONCodec(conn)
- go server.ServeCodec(codec)
+ go func() {
+ glog.V(logger.Info).Infof("Start IPC server on %s\n", endpoint)
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ glog.V(logger.Error).Infof("Unable to accept connection - %v\n", err)
}
- }()
-
- return nil
- }
- initializer := func(conn net.Conn) (comms.Stopper, shared.EthereumApi, error) {
- fe := useragent.NewRemoteFrontend(conn, ethereum.AccountManager())
- xeth := xeth.New(stack, fe)
- apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec.JSON, xeth, stack)
- if err != nil {
- return nil, nil, err
+ codec := rpc.NewJSONCodec(conn)
+ go server.ServeCodec(codec)
}
- return xeth, api.Merge(apis...), nil
- }
- return comms.StartIpc(config, codec.JSON, initializer)
+ }()
+
+ return nil
+
}
// StartRPC starts a HTTP JSON-RPC API server.
func StartRPC(stack *node.Node, ctx *cli.Context) error {
- config := comms.HttpConfig{
- ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name),
- ListenPort: uint(ctx.GlobalInt(RPCPortFlag.Name)),
- CorsDomain: ctx.GlobalString(RPCCORSDomainFlag.Name),
+ for _, api := range stack.APIs() {
+ if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
+ address := ctx.GlobalString(RPCListenAddrFlag.Name)
+ port := ctx.GlobalInt(RPCPortFlag.Name)
+ cors := ctx.GlobalString(RPCCORSDomainFlag.Name)
+ apiStr := ""
+ if ctx.GlobalIsSet(RPCApiFlag.Name) {
+ apiStr = ctx.GlobalString(RPCApiFlag.Name)
+ }
+
+ _, err := adminApi.StartRPC(address, port, cors, apiStr)
+ return err
+ }
}
- xeth := xeth.New(stack, nil)
- codec := codec.JSON
+ glog.V(logger.Error).Infof("Unable to start RPC-HTTP interface, could not find admin API")
+ return errors.New("Unable to start RPC-HTTP interface")
+}
- apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, stack)
- if err != nil {
- return err
+// StartWS starts a websocket JSON-RPC API server.
+func StartWS(stack *node.Node, ctx *cli.Context) error {
+ for _, api := range stack.APIs() {
+ if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
+ address := ctx.GlobalString(WSListenAddrFlag.Name)
+ port := ctx.GlobalInt(WSAllowedDomainsFlag.Name)
+ allowedDomains := ctx.GlobalString(WSAllowedDomainsFlag.Name)
+ apiStr := ""
+ if ctx.GlobalIsSet(WSApiFlag.Name) {
+ apiStr = ctx.GlobalString(WSApiFlag.Name)
+ }
+
+ _, err := adminApi.StartWS(address, port, allowedDomains, apiStr)
+ return err
+ }
}
- return comms.StartHttp(config, codec, api.Merge(apis...))
+
+ glog.V(logger.Error).Infof("Unable to start RPC-WS interface, could not find admin API")
+ return errors.New("Unable to start RPC-WS interface")
}
func StartPProf(ctx *cli.Context) {
diff --git a/rpc/jeth.go b/cmd/utils/jeth.go
index b195a4965..b460597c1 100644
--- a/rpc/jeth.go
+++ b/cmd/utils/jeth.go
@@ -14,38 +14,39 @@
// 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 rpc
+package utils
import (
"encoding/json"
"fmt"
"time"
- "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/jsre"
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/rpc/comms"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/rpc/useragent"
- "github.com/ethereum/go-ethereum/xeth"
+ "github.com/ethereum/go-ethereum/rpc"
"github.com/robertkrimen/otto"
)
type Jeth struct {
- ethApi shared.EthereumApi
re *jsre.JSRE
- client comms.EthereumClient
- fe xeth.Frontend
+ client rpc.Client
}
-func NewJeth(ethApi shared.EthereumApi, re *jsre.JSRE, client comms.EthereumClient, fe xeth.Frontend) *Jeth {
- return &Jeth{ethApi, re, client, fe}
+// NewJeth create a new backend for the JSRE console
+func NewJeth(re *jsre.JSRE, client rpc.Client) *Jeth {
+ return &Jeth{re, client}
}
-func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) {
- m := shared.NewRpcErrorResponse(id, shared.JsonRpcVersion, code, fmt.Errorf(msg))
+func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id *int64) (response otto.Value) {
+ m := rpc.JSONErrResponse{
+ Version: "2.0",
+ Id: id,
+ Error: rpc.JSONError{
+ Code: code,
+ Message: msg,
+ },
+ }
+
errObj, _ := json.Marshal(m.Error)
errRes, _ := json.Marshal(m)
@@ -71,7 +72,7 @@ func (self *Jeth) UnlockAccount(call otto.FunctionCall) (response otto.Value) {
if account, ok = accountExport.(string); ok {
if len(call.ArgumentList) == 1 {
fmt.Printf("Unlock account %s\n", account)
- passwd, err = utils.PromptPassword("Passphrase: ", true)
+ passwd, err = PromptPassword("Passphrase: ", true)
if err != nil {
return otto.FalseValue()
}
@@ -102,11 +103,11 @@ func (self *Jeth) UnlockAccount(call otto.FunctionCall) (response otto.Value) {
// NewAccount asks the user for the password and than executes the jeth.newAccount callback in the jsre
func (self *Jeth) NewAccount(call otto.FunctionCall) (response otto.Value) {
if len(call.ArgumentList) == 0 {
- passwd, err := utils.PromptPassword("Passphrase: ", true)
+ passwd, err := PromptPassword("Passphrase: ", true)
if err != nil {
return otto.FalseValue()
}
- passwd2, err := utils.PromptPassword("Repeat passphrase: ", true)
+ passwd2, err := PromptPassword("Repeat passphrase: ", true)
if err != nil {
return otto.FalseValue()
}
@@ -134,11 +135,11 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
}
jsonreq, err := json.Marshal(reqif)
- var reqs []shared.Request
+ var reqs []rpc.JSONRequest
batch := true
err = json.Unmarshal(jsonreq, &reqs)
if err != nil {
- reqs = make([]shared.Request, 1)
+ reqs = make([]rpc.JSONRequest, 1)
err = json.Unmarshal(jsonreq, &reqs[0])
batch = false
}
@@ -147,42 +148,38 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
call.Otto.Run("var ret_response = new Array(response_len);")
for i, req := range reqs {
- var respif interface{}
err := self.client.Send(&req)
if err != nil {
return self.err(call, -32603, err.Error(), req.Id)
}
- recv:
- respif, err = self.client.Recv()
+ result := make(map[string]interface{})
+ err = self.client.Recv(&result)
if err != nil {
return self.err(call, -32603, err.Error(), req.Id)
}
- agentreq, isRequest := respif.(*shared.Request)
- if isRequest {
- self.handleRequest(agentreq)
- goto recv // receive response after agent interaction
- }
-
- sucres, isSuccessResponse := respif.(*shared.SuccessResponse)
- errres, isErrorResponse := respif.(*shared.ErrorResponse)
+ _, isSuccessResponse := result["result"]
+ _, isErrorResponse := result["error"]
if !isSuccessResponse && !isErrorResponse {
- return self.err(call, -32603, fmt.Sprintf("Invalid response type (%T)", respif), req.Id)
+ return self.err(call, -32603, fmt.Sprintf("Invalid response"), new(int64))
}
- call.Otto.Set("ret_jsonrpc", shared.JsonRpcVersion)
- call.Otto.Set("ret_id", req.Id)
+ id, _ := result["id"]
+ call.Otto.Set("ret_id", id)
- var res []byte
+ jsonver, _ := result["jsonrpc"]
+ call.Otto.Set("ret_jsonrpc", jsonver)
+
+ var payload []byte
if isSuccessResponse {
- res, err = json.Marshal(sucres.Result)
+ payload, _ = json.Marshal(result["result"])
} else if isErrorResponse {
- res, err = json.Marshal(errres.Error)
+ payload, _ = json.Marshal(result["error"])
}
-
- call.Otto.Set("ret_result", string(res))
+ call.Otto.Set("ret_result", string(payload))
call.Otto.Set("response_idx", i)
+
response, err = call.Otto.Run(`
ret_response[response_idx] = { jsonrpc: ret_jsonrpc, id: ret_id, result: JSON.parse(ret_result) };
`)
@@ -195,7 +192,7 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
if call.Argument(1).IsObject() {
call.Otto.Set("callback", call.Argument(1))
call.Otto.Run(`
- if (Object.prototype.toString.call(callback) == '[object Function]') {
+ if (Object.prototype.toString.call(callback) == '[object Function]') {
callback(null, ret_response);
}
`)
@@ -204,6 +201,7 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
return
}
+/*
// handleRequest will handle user agent requests by interacting with the user and sending
// the user response back to the geth service
func (self *Jeth) handleRequest(req *shared.Request) bool {
@@ -235,7 +233,7 @@ func (self *Jeth) askPassword(id interface{}, jsonrpc string, args []interface{}
return false
}
}
- passwd, err = utils.PromptPassword("Passphrase: ", true)
+ passwd, err = PromptPassword("Passphrase: ", true)
if err = self.client.Send(shared.NewRpcResponse(id, jsonrpc, passwd, err)); err != nil {
glog.V(logger.Info).Infof("Unable to send user agent ask password response - %v\n", err)
@@ -248,6 +246,7 @@ func (self *Jeth) confirmTransaction(id interface{}, jsonrpc string, args []inte
// Accept all tx which are send from this console
return self.client.Send(shared.NewRpcResponse(id, jsonrpc, true, nil)) == nil
}
+*/
// throwJSExeception panics on an otto value, the Otto VM will then throw msg as a javascript error.
func throwJSExeception(msg interface{}) otto.Value {
diff --git a/common/natspec/natspec.go b/common/natspec/natspec.go
index d9627b4e1..2e4d8d7a4 100644
--- a/common/natspec/natspec.go
+++ b/common/natspec/natspec.go
@@ -13,6 +13,8 @@
//
// 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/>.
+//
+// +build ignore
package natspec
diff --git a/common/natspec/natspec_e2e_test.go b/common/natspec/natspec_e2e_test.go
index 95109ec07..4a9b92eb6 100644
--- a/common/natspec/natspec_e2e_test.go
+++ b/common/natspec/natspec_e2e_test.go
@@ -13,6 +13,8 @@
//
// 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/>.
+//
+// +build ignore
package natspec
diff --git a/common/natspec/natspec_test.go b/common/natspec/natspec_test.go
index 9ec14829a..53e6a3a90 100644
--- a/common/natspec/natspec_test.go
+++ b/common/natspec/natspec_test.go
@@ -13,6 +13,8 @@
//
// 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/>.
+//
+// +build ignore
package natspec
diff --git a/common/registrar/ethreg/api.go b/common/registrar/ethreg/api.go
new file mode 100644
index 000000000..92e885b10
--- /dev/null
+++ b/common/registrar/ethreg/api.go
@@ -0,0 +1,265 @@
+// 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 ethreg
+
+import (
+ "errors"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/compiler"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "github.com/ethereum/go-ethereum/common/registrar"
+)
+
+// registryAPIBackend is a backend for an Ethereum Registry.
+type registryAPIBackend struct {
+ bc *core.BlockChain
+ chainDb ethdb.Database
+ txPool *core.TxPool
+ am *accounts.Manager
+}
+
+// PrivateRegistarAPI offers various functions to access the Ethereum registry.
+type PrivateRegistarAPI struct {
+ be *registryAPIBackend
+}
+
+// NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
+func NewPrivateRegistarAPI(bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
+ return &PrivateRegistarAPI{&registryAPIBackend{bc, chainDb, txPool, am}}
+}
+
+// SetGlobalRegistrar allows clients to set the global registry for the node.
+// This method can be used to deploy a new registry. First zero out the current
+// address by calling the method with namereg = '0x0' and then call this method
+// again with '' as namereg. This will submit a transaction to the network which
+// will deploy a new registry on execution. The TX hash is returned. When called
+// with namereg '' and the current address is not zero the current global is
+// address is returned..
+func (api *PrivateRegistarAPI) SetGlobalRegistrar(namereg string, from common.Address) (string, error) {
+ return registrar.New(api.be).SetGlobalRegistrar(namereg, from)
+}
+
+// SetHashReg queries the registry for a hash.
+func (api *PrivateRegistarAPI) SetHashReg(hashreg string, from common.Address) (string, error) {
+ return registrar.New(api.be).SetHashReg(hashreg, from)
+}
+
+// SetUrlHint queries the registry for an url.
+func (api *PrivateRegistarAPI) SetUrlHint(hashreg string, from common.Address) (string, error) {
+ return registrar.New(api.be).SetUrlHint(hashreg, from)
+}
+
+// SaveInfo stores contract information on the local file system.
+func (api *PrivateRegistarAPI) SaveInfo(info *compiler.ContractInfo, filename string) (contenthash common.Hash, err error) {
+ return compiler.SaveInfo(info, filename)
+}
+
+// Register registers a new content hash in the registry.
+func (api *PrivateRegistarAPI) Register(sender common.Address, addr common.Address, contentHashHex string) (bool, error) {
+ block := api.be.bc.CurrentBlock()
+ state, err := state.New(block.Root(), api.be.chainDb)
+ if err != nil {
+ return false, err
+ }
+
+ codeb := state.GetCode(addr)
+ codeHash := common.BytesToHash(crypto.Sha3(codeb))
+ contentHash := common.HexToHash(contentHashHex)
+
+ _, err = registrar.New(api.be).SetHashToHash(sender, codeHash, contentHash)
+ return err == nil, err
+}
+
+// RegisterUrl registers a new url in the registry.
+func (api *PrivateRegistarAPI) RegisterUrl(sender common.Address, contentHashHex string, url string) (bool, error) {
+ _, err := registrar.New(api.be).SetUrlToHash(sender, common.HexToHash(contentHashHex), url)
+ return err == nil, err
+}
+
+// callmsg is the message type used for call transations.
+type callmsg struct {
+ from *state.StateObject
+ to *common.Address
+ gas, gasPrice *big.Int
+ value *big.Int
+ data []byte
+}
+
+// accessor boilerplate to implement core.Message
+func (m callmsg) From() (common.Address, error) {
+ return m.from.Address(), nil
+}
+func (m callmsg) Nonce() uint64 {
+ return m.from.Nonce()
+}
+func (m callmsg) To() *common.Address {
+ return m.to
+}
+func (m callmsg) GasPrice() *big.Int {
+ return m.gasPrice
+}
+func (m callmsg) Gas() *big.Int {
+ return m.gas
+}
+func (m callmsg) Value() *big.Int {
+ return m.value
+}
+func (m callmsg) Data() []byte {
+ return m.data
+}
+
+// Call forms a transaction from the given arguments and tries to execute it on
+// a private VM with a copy of the state. Any changes are therefore only temporary
+// and not part of the actual state. This allows for local execution/queries.
+func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) {
+ block := be.bc.CurrentBlock()
+ statedb, err := state.New(block.Root(), be.chainDb)
+ if err != nil {
+ return "", "", err
+ }
+
+ var from *state.StateObject
+ if len(fromStr) == 0 {
+ accounts, err := be.am.Accounts()
+ if err != nil || len(accounts) == 0 {
+ from = statedb.GetOrNewStateObject(common.Address{})
+ } else {
+ from = statedb.GetOrNewStateObject(accounts[0].Address)
+ }
+ } else {
+ from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr))
+ }
+
+ from.SetBalance(common.MaxBig)
+
+ msg := callmsg{
+ from: from,
+ gas: common.Big(gasStr),
+ gasPrice: common.Big(gasPriceStr),
+ value: common.Big(valueStr),
+ data: common.FromHex(dataStr),
+ }
+ if len(toStr) > 0 {
+ addr := common.HexToAddress(toStr)
+ msg.to = &addr
+ }
+
+ if msg.gas.Cmp(big.NewInt(0)) == 0 {
+ msg.gas = big.NewInt(50000000)
+ }
+
+ if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
+ msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
+ }
+
+ header := be.bc.CurrentBlock().Header()
+ vmenv := core.NewEnv(statedb, be.bc, msg, header)
+ gp := new(core.GasPool).AddGas(common.MaxBig)
+ res, gas, err := core.ApplyMessage(vmenv, msg, gp)
+
+ return common.ToHex(res), gas.String(), err
+}
+
+// StorageAt returns the data stores in the state for the given address and location.
+func (be *registryAPIBackend) StorageAt(addr string, storageAddr string) string {
+ block := be.bc.CurrentBlock()
+ state, err := state.New(block.Root(), be.chainDb)
+ if err != nil {
+ return ""
+ }
+ return state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex()
+}
+
+// Transact forms a transaction from the given arguments and submits it to the
+// transactio pool for execution.
+func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
+ if len(toStr) > 0 && toStr != "0x" && !common.IsHexAddress(toStr) {
+ return "", errors.New("invalid address")
+ }
+
+ var (
+ from = common.HexToAddress(fromStr)
+ to = common.HexToAddress(toStr)
+ value = common.Big(valueStr)
+ gas *big.Int
+ price *big.Int
+ data []byte
+ contractCreation bool
+ )
+
+ if len(gasStr) == 0 {
+ gas = big.NewInt(90000)
+ } else {
+ gas = common.Big(gasStr)
+ }
+
+ if len(gasPriceStr) == 0 {
+ price = big.NewInt(10000000000000)
+ } else {
+ price = common.Big(gasPriceStr)
+ }
+
+ data = common.FromHex(codeStr)
+ if len(toStr) == 0 {
+ contractCreation = true
+ }
+
+ nonce := be.txPool.State().GetNonce(from)
+ if len(nonceStr) != 0 {
+ nonce = common.Big(nonceStr).Uint64()
+ }
+
+ var tx *types.Transaction
+ if contractCreation {
+ tx = types.NewContractCreation(nonce, value, gas, price, data)
+ } else {
+ tx = types.NewTransaction(nonce, to, value, gas, price, data)
+ }
+
+ acc := accounts.Account{from}
+ signature, err := be.am.Sign(acc, tx.SigHash().Bytes())
+ if err != nil {
+ return "", err
+ }
+ signedTx, err := tx.WithSignature(signature)
+ if err != nil {
+ return "", err
+ }
+
+ be.txPool.SetLocal(signedTx)
+ if err := be.txPool.Add(signedTx); err != nil {
+ return "", nil
+ }
+
+ if contractCreation {
+ addr := crypto.CreateAddress(from, nonce)
+ glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
+ } else {
+ glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
+ }
+
+ return signedTx.Hash().Hex(), nil
+}
diff --git a/common/registrar/ethreg/ethreg.go b/common/registrar/ethreg/ethreg.go
deleted file mode 100644
index 626ebe1d7..000000000
--- a/common/registrar/ethreg/ethreg.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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 ethreg
-
-import (
- "math/big"
-
- "github.com/ethereum/go-ethereum/common/registrar"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-// implements a versioned Registrar on an archiving full node
-type EthReg struct {
- backend *xeth.XEth
- registry *registrar.Registrar
-}
-
-func New(xe *xeth.XEth) (self *EthReg) {
- self = &EthReg{backend: xe}
- self.registry = registrar.New(xe)
- return
-}
-
-func (self *EthReg) Registry() *registrar.Registrar {
- return self.registry
-}
-
-func (self *EthReg) Resolver(n *big.Int) *registrar.Registrar {
- xe := self.backend
- if n != nil {
- xe = self.backend.AtStateNum(n.Int64())
- }
- return registrar.New(xe)
-}
diff --git a/docker/Dockerfile b/docker/Dockerfile
deleted file mode 100644
index ba5b05d14..000000000
--- a/docker/Dockerfile
+++ /dev/null
@@ -1,21 +0,0 @@
-FROM ubuntu:wily
-MAINTAINER caktux
-
-ENV DEBIAN_FRONTEND noninteractive
-
-# Usual update / upgrade
-RUN apt-get update
-RUN apt-get upgrade -q -y
-RUN apt-get dist-upgrade -q -y
-
-# Install Ethereum
-RUN apt-get install -q -y software-properties-common
-RUN add-apt-repository ppa:ethereum/ethereum
-RUN add-apt-repository ppa:ethereum/ethereum-dev
-RUN apt-get update
-RUN apt-get install -q -y geth
-
-EXPOSE 8545
-EXPOSE 30303
-
-ENTRYPOINT ["/usr/bin/geth"]
diff --git a/docker/develop/Dockerfile b/docker/develop/Dockerfile
new file mode 100644
index 000000000..98b4aadf8
--- /dev/null
+++ b/docker/develop/Dockerfile
@@ -0,0 +1,17 @@
+FROM ubuntu:wily
+MAINTAINER caktux
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update && \
+ apt-get upgrade -q -y && \
+ apt-get dist-upgrade -q -y && \
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 923F6CA9 && \
+ echo "deb http://ppa.launchpad.net/ethereum/ethereum-dev/ubuntu wily main" | tee -a /etc/apt/sources.list.d/ethereum.list && \
+ apt-get update && \
+ apt-get install -q -y geth
+
+EXPOSE 8545
+EXPOSE 30303
+
+ENTRYPOINT ["/usr/bin/geth"]
diff --git a/docker/master/Dockerfile b/docker/master/Dockerfile
new file mode 100644
index 000000000..2c6de28c9
--- /dev/null
+++ b/docker/master/Dockerfile
@@ -0,0 +1,17 @@
+FROM ubuntu:wily
+MAINTAINER caktux
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update && \
+ apt-get upgrade -q -y && \
+ apt-get dist-upgrade -q -y && \
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 923F6CA9 && \
+ echo "deb http://ppa.launchpad.net/ethereum/ethereum/ubuntu wily main" | tee -a /etc/apt/sources.list.d/ethereum.list && \
+ apt-get update && \
+ apt-get install -q -y geth
+
+EXPOSE 8545
+EXPOSE 30303
+
+ENTRYPOINT ["/usr/bin/geth"]
diff --git a/eth/api.go b/eth/api.go
index a1630e2d1..08b103a4c 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -42,8 +42,10 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
+ "github.com/ethereum/go-ethereum/miner"
+ "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
const (
@@ -51,6 +53,19 @@ const (
defaultGas = uint64(90000)
)
+// blockByNumber is a commonly used helper function which retrieves and returns the block for the given block number. It
+// returns nil when no block could be found.
+func blockByNumber(m *miner.Miner, bc *core.BlockChain, blockNr rpc.BlockNumber) *types.Block {
+ if blockNr == rpc.PendingBlockNumber {
+ return m.PendingBlock()
+ }
+ if blockNr == rpc.LatestBlockNumber {
+ return bc.CurrentBlock()
+ }
+
+ return bc.GetBlockByNumber(uint64(blockNr))
+}
+
// PublicEthereumAPI provides an API to access Ethereum related information.
// It offers only methods that operate on public data that is freely available to anyone.
type PublicEthereumAPI struct {
@@ -293,11 +308,12 @@ type PublicBlockChainAPI struct {
chainDb ethdb.Database
eventMux *event.TypeMux
am *accounts.Manager
+ miner *miner.Miner
}
// NewPublicBlockChainAPI creates a new Etheruem blockchain API.
-func NewPublicBlockChainAPI(bc *core.BlockChain, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI {
- return &PublicBlockChainAPI{bc: bc, chainDb: chainDb, eventMux: eventMux, am: am}
+func NewPublicBlockChainAPI(bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI {
+ return &PublicBlockChainAPI{bc: bc, miner: m, chainDb: chainDb, eventMux: eventMux, am: am}
}
// BlockNumber returns the block number of the chain head.
@@ -308,7 +324,7 @@ func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
// GetBalance returns the amount of wei for the given address in the state of the given block number.
// When block number equals rpc.LatestBlockNumber the current block is used.
func (s *PublicBlockChainAPI) GetBalance(address common.Address, blockNr rpc.BlockNumber) (*big.Int, error) {
- block := blockByNumber(s.bc, blockNr)
+ block := blockByNumber(s.miner, s.bc, blockNr)
if block == nil {
return nil, nil
}
@@ -320,20 +336,10 @@ func (s *PublicBlockChainAPI) GetBalance(address common.Address, blockNr rpc.Blo
return state.GetBalance(address), nil
}
-// blockByNumber is a commonly used helper function which retrieves and returns the block for the given block number. It
-// returns nil when no block could be found.
-func blockByNumber(bc *core.BlockChain, blockNr rpc.BlockNumber) *types.Block {
- if blockNr == rpc.LatestBlockNumber {
- return bc.CurrentBlock()
- }
-
- return bc.GetBlockByNumber(uint64(blockNr))
-}
-
// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetBlockByNumber(blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
return s.rpcOutputBlock(block, true, fullTx)
}
return nil, nil
@@ -355,7 +361,7 @@ func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(blockNr rpc.BlockNum
return nil, nil
}
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
uncles := block.Uncles()
if index.Int() < 0 || index.Int() >= len(uncles) {
glog.V(logger.Debug).Infof("uncle block on index %d not found for block #%d", index.Int(), blockNr)
@@ -388,7 +394,7 @@ func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(blockNr rpc.BlockNumber
return rpc.NewHexNumber(0)
}
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
return rpc.NewHexNumber(len(block.Uncles()))
}
return nil
@@ -433,7 +439,7 @@ func (s *PublicBlockChainAPI) GetCode(address common.Address, blockNr rpc.BlockN
// GetData returns the data stored at the given address in the state for the given block number.
func (s *PublicBlockChainAPI) GetData(address common.Address, blockNr rpc.BlockNumber) (string, error) {
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
state, err := state.New(block.Root(), s.chainDb)
if err != nil {
return "", err
@@ -450,7 +456,7 @@ func (s *PublicBlockChainAPI) GetData(address common.Address, blockNr rpc.BlockN
// GetStorageAt returns the storage from the state at the given address, key and block number.
func (s *PublicBlockChainAPI) GetStorageAt(address common.Address, key string, blockNr rpc.BlockNumber) (string, error) {
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
state, err := state.New(block.Root(), s.chainDb)
if err != nil {
return "", err
@@ -490,7 +496,7 @@ type CallArgs struct {
}
func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) {
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
stateDb, err := state.New(block.Root(), s.chainDb)
if err != nil {
return "0x", nil, err
@@ -684,19 +690,21 @@ type PublicTransactionPoolAPI struct {
eventMux *event.TypeMux
chainDb ethdb.Database
bc *core.BlockChain
+ miner *miner.Miner
am *accounts.Manager
txPool *core.TxPool
txMu sync.Mutex
}
// NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool.
-func NewPublicTransactionPoolAPI(txPool *core.TxPool, chainDb ethdb.Database, eventMux *event.TypeMux, bc *core.BlockChain, am *accounts.Manager) *PublicTransactionPoolAPI {
+func NewPublicTransactionPoolAPI(txPool *core.TxPool, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, bc *core.BlockChain, am *accounts.Manager) *PublicTransactionPoolAPI {
return &PublicTransactionPoolAPI{
eventMux: eventMux,
chainDb: chainDb,
bc: bc,
am: am,
txPool: txPool,
+ miner: m,
}
}
@@ -724,7 +732,7 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(blockNr rpc.
return rpc.NewHexNumber(0)
}
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
return rpc.NewHexNumber(len(block.Transactions()))
}
@@ -741,7 +749,7 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(blockHash comm
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(blockNr rpc.BlockNumber, index rpc.HexNumber) (*RPCTransaction, error) {
- if block := blockByNumber(s.bc, blockNr); block != nil {
+ if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
return newRPCTransactionFromBlockIndex(block, index.Int())
}
return nil, nil
@@ -757,7 +765,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(blockHash c
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
func (s *PublicTransactionPoolAPI) GetTransactionCount(address common.Address, blockNr rpc.BlockNumber) (*rpc.HexNumber, error) {
- block := blockByNumber(s.bc, blockNr)
+ block := blockByNumber(s.miner, s.bc, blockNr)
if block == nil {
return nil, nil
}
@@ -1256,6 +1264,16 @@ func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
return true, nil
}
+func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
+ for _, b := range bs {
+ if !chain.HasBlock(b.Hash()) {
+ return false
+ }
+ }
+
+ return true
+}
+
// ImportChain imports a blockchain from a local file.
func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
// Make sure the can access the file to import
@@ -1284,6 +1302,11 @@ func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
if len(blocks) == 0 {
break
}
+
+ if hasAllBlocks(api.eth.BlockChain(), blocks) {
+ blocks = blocks[:0]
+ continue
+ }
// Import the batch and reset the buffer
if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil {
return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err)
@@ -1403,3 +1426,29 @@ func (api *PrivateDebugAPI) ProcessBlock(number uint64) (bool, error) {
func (api *PrivateDebugAPI) SetHead(number uint64) {
api.eth.BlockChain().SetHead(number)
}
+
+// PublicNetAPI offers network related RPC methods
+type PublicNetAPI struct {
+ net *p2p.Server
+ networkVersion int
+}
+
+// NewPublicNetAPI creates a new net api instance.
+func NewPublicNetAPI(net *p2p.Server, networkVersion int) *PublicNetAPI {
+ return &PublicNetAPI{net, networkVersion}
+}
+
+// Listening returns an indication if the node is listening for network connections.
+func (s *PublicNetAPI) Listening() bool {
+ return true // always listening
+}
+
+// Peercount returns the number of connected peers
+func (s *PublicNetAPI) PeerCount() *rpc.HexNumber {
+ return rpc.NewHexNumber(s.net.PeerCount())
+}
+
+// ProtocolVersion returns the current ethereum protocol version.
+func (s *PublicNetAPI) Version() string {
+ return fmt.Sprintf("%d", s.networkVersion)
+}
diff --git a/eth/backend.go b/eth/backend.go
index abd1214ca..352522f61 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/common/httpclient"
+ "github.com/ethereum/go-ethereum/common/registrar/ethreg"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader"
@@ -44,7 +45,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
const (
@@ -121,14 +122,15 @@ type Ethereum struct {
eventMux *event.TypeMux
miner *miner.Miner
- Mining bool
- MinerThreads int
- NatSpec bool
- AutoDAG bool
- PowTest bool
- autodagquit chan bool
- etherbase common.Address
- netVersionId int
+ Mining bool
+ MinerThreads int
+ NatSpec bool
+ AutoDAG bool
+ PowTest bool
+ autodagquit chan bool
+ etherbase common.Address
+ netVersionId int
+ netRPCService *PublicNetAPI
}
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
@@ -262,12 +264,12 @@ func (s *Ethereum) APIs() []rpc.API {
}, {
Namespace: "eth",
Version: "1.0",
- Service: NewPublicBlockChainAPI(s.BlockChain(), s.ChainDb(), s.EventMux(), s.AccountManager()),
+ Service: NewPublicBlockChainAPI(s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()),
Public: true,
}, {
Namespace: "eth",
Version: "1.0",
- Service: NewPublicTransactionPoolAPI(s.TxPool(), s.ChainDb(), s.EventMux(), s.BlockChain(), s.AccountManager()),
+ Service: NewPublicTransactionPoolAPI(s.TxPool(), s.Miner(), s.ChainDb(), s.EventMux(), s.BlockChain(), s.AccountManager()),
Public: true,
}, {
Namespace: "eth",
@@ -307,6 +309,15 @@ func (s *Ethereum) APIs() []rpc.API {
Namespace: "debug",
Version: "1.0",
Service: NewPrivateDebugAPI(s),
+ }, {
+ Namespace: "net",
+ Version: "1.0",
+ Service: s.netRPCService,
+ Public: true,
+ }, {
+ Namespace: "admin",
+ Version: "1.0",
+ Service: ethreg.NewPrivateRegistarAPI(s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()),
},
}
}
@@ -356,11 +367,12 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
-func (s *Ethereum) Start(*p2p.Server) error {
+func (s *Ethereum) Start(srvr *p2p.Server) error {
if s.AutoDAG {
s.StartAutoDAG()
}
s.protocolManager.Start()
+ s.netRPCService = NewPublicNetAPI(srvr, s.NetVersion())
return nil
}
diff --git a/eth/downloader/api.go b/eth/downloader/api.go
index 9deff22a1..cc79e669f 100644
--- a/eth/downloader/api.go
+++ b/eth/downloader/api.go
@@ -17,7 +17,7 @@
package downloader
import (
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
// PublicDownloaderAPI provides an API which gives informatoin about the current synchronisation status.
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 411d8e5a3..f2b0ed32f 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -32,7 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
var (
diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go
index 7063a90ec..94e4fde82 100644
--- a/jsre/ethereum_js.go
+++ b/jsre/ethereum_js.go
@@ -5740,7 +5740,9 @@ Property.prototype.extractCallback = function (args) {
*/
Property.prototype.attachToObject = function (obj) {
var proto = {
- get: this.buildGet()
+ //get: this.buildGet()
+ get: this.buildGet(),
+ enumerable: true
};
var names = this.name.split('.');
diff --git a/light/state_object.go b/light/state_object.go
index 7660c3883..d67fd7e40 100644
--- a/light/state_object.go
+++ b/light/state_object.go
@@ -264,4 +264,4 @@ func DecodeObject(ctx context.Context, address common.Address, odr OdrBackend, d
obj.balance = ext.Balance
obj.codeHash = ext.CodeHash
return obj, nil
-} \ No newline at end of file
+}
diff --git a/logger/glog/glog.go b/logger/glog/glog.go
index 008c0e036..b8eaf9359 100644
--- a/logger/glog/glog.go
+++ b/logger/glog/glog.go
@@ -63,11 +63,17 @@
// Enable V-leveled logging at the specified level.
// -vmodule=""
// The syntax of the argument is a comma-separated list of pattern=N,
-// where pattern is a literal file name (minus the ".go" suffix) or
-// "glob" pattern and N is a V level. For instance,
-// -vmodule=gopher*=3
-// sets the V level to 3 in all Go files whose names begin "gopher".
+// where pattern is a literal file name or "glob" pattern matching
+// and N is a V level. For instance,
//
+// -vmodule=gopher.go=3
+// sets the V level to 3 in all Go files named "gopher.go".
+//
+// -vmodule=foo=3
+// sets V to 3 in all files of any packages whose import path ends in "foo".
+//
+// -vmodule=foo/*=3
+// sets V to 3 in all files of any packages whose import path contains "foo".
package glog
import (
@@ -78,7 +84,7 @@ import (
"io"
stdLog "log"
"os"
- "path/filepath"
+ "regexp"
"runtime"
"strconv"
"strings"
@@ -113,11 +119,30 @@ var severityName = []string{
fatalLog: "FATAL",
}
+// these path prefixes are trimmed for display, but not when
+// matching vmodule filters.
+var trimPrefixes = []string{
+ "/github.com/ethereum/go-ethereum",
+ "/github.com/ethereum/ethash",
+}
+
+func trimToImportPath(file string) string {
+ if root := strings.LastIndex(file, "src/"); root != 0 {
+ file = file[root+3:]
+ }
+ return file
+}
+
// SetV sets the global verbosity level
func SetV(v int) {
logging.verbosity.set(Level(v))
}
+// SetVmodule sets the global verbosity patterns.
+func SetVmodule(pat string) error {
+ return logging.vmodule.Set(pat)
+}
+
// SetToStderr sets the global output style
func SetToStderr(toStderr bool) {
logging.toStderr = toStderr
@@ -261,21 +286,10 @@ type moduleSpec struct {
// modulePat contains a filter for the -vmodule flag.
// It holds a verbosity level and a file pattern to match.
type modulePat struct {
- pattern string
- literal bool // The pattern is a literal string
+ pattern *regexp.Regexp
level Level
}
-// match reports whether the file matches the pattern. It uses a string
-// comparison if the pattern contains no metacharacters.
-func (m *modulePat) match(file string) bool {
- if m.literal {
- return file == m.pattern
- }
- match, _ := filepath.Match(m.pattern, file)
- return match
-}
-
func (m *moduleSpec) String() string {
// Lock because the type is not atomic. TODO: clean this up.
logging.mu.Lock()
@@ -322,7 +336,8 @@ func (m *moduleSpec) Set(value string) error {
continue // Ignore. It's harmless but no point in paying the overhead.
}
// TODO: check syntax of filter?
- filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
+ re, _ := compileModulePattern(pattern)
+ filter = append(filter, modulePat{re, Level(v)})
}
logging.mu.Lock()
defer logging.mu.Unlock()
@@ -330,10 +345,21 @@ func (m *moduleSpec) Set(value string) error {
return nil
}
-// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters
-// that require filepath.Match to be called to match the pattern.
-func isLiteral(pattern string) bool {
- return !strings.ContainsAny(pattern, `\*?[]`)
+// compiles a vmodule pattern to a regular expression.
+func compileModulePattern(pat string) (*regexp.Regexp, error) {
+ re := ".*"
+ for _, comp := range strings.Split(pat, "/") {
+ if comp == "*" {
+ re += "(/.*)?"
+ } else if comp != "" {
+ // TODO: maybe return error if comp contains *
+ re += "/" + regexp.QuoteMeta(comp)
+ }
+ }
+ if !strings.HasSuffix(pat, ".go") {
+ re += "/[^/]+\\.go"
+ }
+ return regexp.Compile(re + "$")
}
// traceLocation represents the setting of the -log_backtrace_at flag.
@@ -556,10 +582,14 @@ func (l *loggingT) header(s severity, depth int) (*buffer, string, int) {
file = "???"
line = 1
} else {
- slash := strings.LastIndex(file, "/")
- if slash >= 0 {
- file = file[slash+1:]
+ file = trimToImportPath(file)
+ for _, p := range trimPrefixes {
+ if strings.HasPrefix(file, p) {
+ file = file[len(p):]
+ break
+ }
}
+ file = file[1:] // drop '/'
}
return l.formatHeader(s, file, line), file, line
}
@@ -592,9 +622,7 @@ func (l *loggingT) formatHeader(s severity, file string, line int) *buffer {
buf.tmp[14] = '.'
buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
buf.tmp[21] = ' '
- buf.nDigits(7, 22, pid, ' ') // TODO: should be TID
- buf.tmp[29] = ' '
- buf.Write(buf.tmp[:30])
+ buf.Write(buf.tmp[:22])
buf.WriteString(file)
buf.tmp[0] = ':'
n := buf.someDigits(1, line)
@@ -976,15 +1004,9 @@ func (lb logBridge) Write(b []byte) (n int, err error) {
func (l *loggingT) setV(pc uintptr) Level {
fn := runtime.FuncForPC(pc)
file, _ := fn.FileLine(pc)
- // The file is something like /a/b/c/d.go. We want just the d.
- if strings.HasSuffix(file, ".go") {
- file = file[:len(file)-3]
- }
- if slash := strings.LastIndex(file, "/"); slash >= 0 {
- file = file[slash+1:]
- }
+ file = trimToImportPath(file)
for _, filter := range l.vmodule.filter {
- if filter.match(file) {
+ if filter.pattern.MatchString(file) {
l.vmap[pc] = filter.level
return filter.level
}
diff --git a/logger/glog/glog_test.go b/logger/glog/glog_test.go
index 0fb376e1f..30861a48d 100644
--- a/logger/glog/glog_test.go
+++ b/logger/glog/glog_test.go
@@ -180,7 +180,7 @@ func TestHeader(t *testing.T) {
pid = 1234
Info("test")
var line int
- format := "I0102 15:04:05.067890 1234 glog_test.go:%d] test\n"
+ format := "I0102 15:04:05.067890 logger/glog/glog_test.go:%d] test\n"
n, err := fmt.Sscanf(contents(infoLog), format, &line)
if n != 1 || err != nil {
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, contents(infoLog))
@@ -253,7 +253,7 @@ func TestV(t *testing.T) {
func TestVmoduleOn(t *testing.T) {
setFlags()
defer logging.swap(logging.newBuffers())
- logging.vmodule.Set("glog_test=2")
+ logging.vmodule.Set("glog_test.go=2")
defer logging.vmodule.Set("")
if !V(1) {
t.Error("V not enabled for 1")
@@ -290,22 +290,43 @@ func TestVmoduleOff(t *testing.T) {
}
}
+var patternTests = []struct{ input, want string }{
+ {"foo/bar/x.go", ".*/foo/bar/x\\.go$"},
+ {"foo/*/x.go", ".*/foo(/.*)?/x\\.go$"},
+ {"foo/*", ".*/foo(/.*)?/[^/]+\\.go$"},
+}
+
+func TestCompileModulePattern(t *testing.T) {
+ for _, test := range patternTests {
+ re, err := compileModulePattern(test.input)
+ if err != nil {
+ t.Fatalf("%s: %v", err)
+ }
+ if re.String() != test.want {
+ t.Errorf("mismatch for %q: got %q, want %q", test.input, re.String(), test.want)
+ }
+ }
+}
+
// vGlobs are patterns that match/don't match this file at V=2.
var vGlobs = map[string]bool{
// Easy to test the numeric match here.
- "glog_test=1": false, // If -vmodule sets V to 1, V(2) will fail.
- "glog_test=2": true,
- "glog_test=3": true, // If -vmodule sets V to 1, V(3) will succeed.
- // These all use 2 and check the patterns. All are true.
- "*=2": true,
- "?l*=2": true,
- "????_*=2": true,
- "??[mno]?_*t=2": true,
- // These all use 2 and check the patterns. All are false.
- "*x=2": false,
- "m*=2": false,
- "??_*=2": false,
- "?[abc]?_*t=2": false,
+ "glog_test.go=1": false, // If -vmodule sets V to 1, V(2) will fail.
+ "glog_test.go=2": true,
+ "glog_test.go=3": true, // If -vmodule sets V to 1, V(3) will succeed.
+
+ // Import path prefix matching
+ "logger/glog=1": false,
+ "logger/glog=2": true,
+ "logger/glog=3": true,
+
+ // Import path glob matching
+ "logger/*=1": false,
+ "logger/*=2": true,
+ "logger/*=3": true,
+
+ // These all use 2 and check the patterns.
+ "*=2": true,
}
// Test that vmodule globbing works as advertised.
diff --git a/miner/api.go b/miner/api.go
index 65d106afd..42678b5ad 100644
--- a/miner/api.go
+++ b/miner/api.go
@@ -21,7 +21,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger/glog"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
// PublicMinerAPI provides an API to control the miner.
diff --git a/node/api.go b/node/api.go
index a44ee16c0..7b247dc51 100644
--- a/node/api.go
+++ b/node/api.go
@@ -21,11 +21,15 @@ import (
"strings"
"time"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
- "github.com/ethereum/go-ethereum/rpc/comms"
+ "github.com/ethereum/go-ethereum/rpc"
"github.com/rcrowley/go-metrics"
+
+ "gopkg.in/fatih/set.v0"
)
// PrivateAdminAPI is the collection of administrative API methods exposed only
@@ -59,27 +63,83 @@ func (api *PrivateAdminAPI) AddPeer(url string) (bool, error) {
// StartRPC starts the HTTP RPC API server.
func (api *PrivateAdminAPI) StartRPC(address string, port int, cors string, apis string) (bool, error) {
- /*// Parse the list of API modules to make available
- apis, err := api.ParseApiString(apis, codec.JSON, xeth.New(api.node, nil), api.node)
- if err != nil {
- return false, err
+ var offeredAPIs []rpc.API
+ if len(apis) > 0 {
+ namespaces := set.New()
+ for _, a := range strings.Split(apis, ",") {
+ namespaces.Add(strings.TrimSpace(a))
+ }
+ for _, api := range api.node.APIs() {
+ if namespaces.Has(api.Namespace) {
+ offeredAPIs = append(offeredAPIs, api)
+ }
+ }
+ } else { // use by default all public API's
+ for _, api := range api.node.APIs() {
+ if api.Public {
+ offeredAPIs = append(offeredAPIs, api)
+ }
+ }
}
- // Configure and start the HTTP RPC server
- config := comms.HttpConfig{
- ListenAddress: address,
- ListenPort: port,
- CorsDomain: cors,
+
+ if address == "" {
+ address = "127.0.0.1"
}
- if err := comms.StartHttp(config, self.codec, api.Merge(apis...)); err != nil {
- return false, err
+ if port == 0 {
+ port = 8545
}
- return true, nil*/
- return false, fmt.Errorf("needs new RPC implementation to resolve circular dependency")
+
+ corsDomains := strings.Split(cors, " ")
+ err := rpc.StartHTTP(address, port, corsDomains, offeredAPIs)
+ return err == nil, err
}
// StopRPC terminates an already running HTTP RPC API endpoint.
-func (api *PrivateAdminAPI) StopRPC() {
- comms.StopHttp()
+func (api *PrivateAdminAPI) StopRPC() (bool, error) {
+ err := rpc.StopHTTP()
+ return err == nil, err
+}
+
+
+// StartWS starts the websocket RPC API server.
+func (api *PrivateAdminAPI) StartWS(address string, port int, cors string, apis string) (bool, error) {
+ var offeredAPIs []rpc.API
+ if len(apis) > 0 {
+ namespaces := set.New()
+ for _, a := range strings.Split(apis, ",") {
+ namespaces.Add(strings.TrimSpace(a))
+ }
+ for _, api := range api.node.APIs() {
+ if namespaces.Has(api.Namespace) {
+ offeredAPIs = append(offeredAPIs, api)
+ }
+ }
+ } else {
+ // use by default all public API's
+ for _, api := range api.node.APIs() {
+ if api.Public {
+ offeredAPIs = append(offeredAPIs, api)
+ }
+ }
+ }
+
+ if address == "" {
+ address = "127.0.0.1"
+ }
+ if port == 0 {
+ port = 8546
+ }
+
+ corsDomains := strings.Split(cors, " ")
+
+ err := rpc.StartWS(address, port, corsDomains, offeredAPIs)
+ return err == nil, err
+}
+
+// StopRPC terminates an already running websocket RPC API endpoint.
+func (api *PrivateAdminAPI) StopWS() (bool, error) {
+ err := rpc.StopWS()
+ return err == nil, err
}
// PublicAdminAPI is the collection of administrative API methods exposed over
@@ -138,6 +198,11 @@ func (api *PrivateDebugAPI) Verbosity(level int) {
glog.SetV(level)
}
+// Vmodule updates the node's logging verbosity pattern.
+func (api *PrivateDebugAPI) Vmodule(pattern string) error {
+ return glog.SetVmodule(pattern)
+}
+
// PublicDebugAPI is the collection of debugging related API methods exposed over
// both secure and unsecure RPC channels.
type PublicDebugAPI struct {
@@ -242,3 +307,24 @@ func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) {
})
return counters, nil
}
+
+// PublicWeb3API offers helper utils
+type PublicWeb3API struct {
+ stack *Node
+}
+
+// NewPublicWeb3API creates a new Web3Service instance
+func NewPublicWeb3API(stack *Node) *PublicWeb3API {
+ return &PublicWeb3API{stack}
+}
+
+// ClientVersion returns the node name
+func (s *PublicWeb3API) ClientVersion() string {
+ return s.stack.Server().Name
+}
+
+// Sha3 applies the ethereum sha3 implementation on the input.
+// It assumes the input is hex encoded.
+func (s *PublicWeb3API) Sha3(input string) string {
+ return common.ToHex(crypto.Sha3(common.FromHex(input)))
+}
diff --git a/node/node.go b/node/node.go
index 5d7b5869c..3d077b0bd 100644
--- a/node/node.go
+++ b/node/node.go
@@ -27,7 +27,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
var (
@@ -290,6 +290,11 @@ func (n *Node) APIs() []rpc.API {
Version: "1.0",
Service: NewPublicDebugAPI(n),
Public: true,
+ }, {
+ Namespace: "web3",
+ Version: "1.0",
+ Service: NewPublicWeb3API(n),
+ Public: true,
},
}
// Inject all the APIs owned by various services
diff --git a/node/node_example_test.go b/node/node_example_test.go
index ef41dddaf..5ff5d06a6 100644
--- a/node/node_example_test.go
+++ b/node/node_example_test.go
@@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
// SampleService is a trivial network service that can be attached to a node for
diff --git a/node/service.go b/node/service.go
index b83d4c80d..26e9f1624 100644
--- a/node/service.go
+++ b/node/service.go
@@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
// ServiceContext is a collection of service independent options inherited from
diff --git a/node/utils_test.go b/node/utils_test.go
index 2b7bfadbe..7755605ae 100644
--- a/node/utils_test.go
+++ b/node/utils_test.go
@@ -23,7 +23,7 @@ import (
"reflect"
"github.com/ethereum/go-ethereum/p2p"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
// NoopService is a trivial implementation of the Service interface.
diff --git a/rpc/api/admin.go b/rpc/api/admin.go
deleted file mode 100644
index 1133c9bca..000000000
--- a/rpc/api/admin.go
+++ /dev/null
@@ -1,477 +0,0 @@
-// 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 (
- "fmt"
- "io"
- "math/big"
- "os"
- "time"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/compiler"
- "github.com/ethereum/go-ethereum/common/natspec"
- "github.com/ethereum/go-ethereum/common/registrar"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/p2p/discover"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/comms"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/rpc/useragent"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-const (
- AdminApiversion = "1.0"
- importBatchSize = 2500
-)
-
-var (
- // mapping between methods and handlers
- AdminMapping = map[string]adminhandler{
- "admin_addPeer": (*adminApi).AddPeer,
- "admin_peers": (*adminApi).Peers,
- "admin_nodeInfo": (*adminApi).NodeInfo,
- "admin_exportChain": (*adminApi).ExportChain,
- "admin_importChain": (*adminApi).ImportChain,
- "admin_verbosity": (*adminApi).Verbosity,
- "admin_setSolc": (*adminApi).SetSolc,
- "admin_datadir": (*adminApi).DataDir,
- "admin_startRPC": (*adminApi).StartRPC,
- "admin_stopRPC": (*adminApi).StopRPC,
- "admin_setGlobalRegistrar": (*adminApi).SetGlobalRegistrar,
- "admin_setHashReg": (*adminApi).SetHashReg,
- "admin_setUrlHint": (*adminApi).SetUrlHint,
- "admin_saveInfo": (*adminApi).SaveInfo,
- "admin_register": (*adminApi).Register,
- "admin_registerUrl": (*adminApi).RegisterUrl,
- "admin_startNatSpec": (*adminApi).StartNatSpec,
- "admin_stopNatSpec": (*adminApi).StopNatSpec,
- "admin_getContractInfo": (*adminApi).GetContractInfo,
- "admin_httpGet": (*adminApi).HttpGet,
- "admin_sleepBlocks": (*adminApi).SleepBlocks,
- "admin_sleep": (*adminApi).Sleep,
- "admin_enableUserAgent": (*adminApi).EnableUserAgent,
- }
-)
-
-// admin callback handler
-type adminhandler func(*adminApi, *shared.Request) (interface{}, error)
-
-// admin api provider
-type adminApi struct {
- xeth *xeth.XEth
- stack *node.Node
- ethereum *eth.Ethereum
- codec codec.Codec
- coder codec.ApiCoder
-}
-
-// create a new admin api instance
-func NewAdminApi(xeth *xeth.XEth, stack *node.Node, codec codec.Codec) *adminApi {
- api := &adminApi{
- xeth: xeth,
- stack: stack,
- codec: codec,
- coder: codec.New(nil),
- }
- if stack != nil {
- stack.Service(&api.ethereum)
- }
- return api
-}
-
-// collection with supported methods
-func (self *adminApi) Methods() []string {
- methods := make([]string, len(AdminMapping))
- i := 0
- for k := range AdminMapping {
- methods[i] = k
- i++
- }
- return methods
-}
-
-// Execute given request
-func (self *adminApi) Execute(req *shared.Request) (interface{}, error) {
- if callback, ok := AdminMapping[req.Method]; ok {
- return callback(self, req)
- }
-
- return nil, &shared.NotImplementedError{req.Method}
-}
-
-func (self *adminApi) Name() string {
- return shared.AdminApiName
-}
-
-func (self *adminApi) ApiVersion() string {
- return AdminApiversion
-}
-
-func (self *adminApi) AddPeer(req *shared.Request) (interface{}, error) {
- args := new(AddPeerArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
- node, err := discover.ParseNode(args.Url)
- if err != nil {
- return nil, fmt.Errorf("invalid node URL: %v", err)
- }
- self.stack.Server().AddPeer(node)
- return true, nil
-}
-
-func (self *adminApi) Peers(req *shared.Request) (interface{}, error) {
- return self.stack.Server().PeersInfo(), nil
-}
-
-func (self *adminApi) NodeInfo(req *shared.Request) (interface{}, error) {
- return self.stack.Server().NodeInfo(), nil
-}
-
-func (self *adminApi) DataDir(req *shared.Request) (interface{}, error) {
- return self.stack.DataDir(), nil
-}
-
-func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
- for _, b := range bs {
- if !chain.HasBlock(b.Hash()) {
- return false
- }
- }
- return true
-}
-
-func (self *adminApi) ImportChain(req *shared.Request) (interface{}, error) {
- args := new(ImportExportChainArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- fh, err := os.Open(args.Filename)
- if err != nil {
- return false, err
- }
- defer fh.Close()
- stream := rlp.NewStream(fh, 0)
-
- // Run actual the import.
- blocks := make(types.Blocks, importBatchSize)
- n := 0
- for batch := 0; ; batch++ {
-
- i := 0
- for ; i < importBatchSize; i++ {
- var b types.Block
- if err := stream.Decode(&b); err == io.EOF {
- break
- } else if err != nil {
- return false, fmt.Errorf("at block %d: %v", n, err)
- }
- blocks[i] = &b
- n++
- }
- if i == 0 {
- break
- }
- // Import the batch.
- if hasAllBlocks(self.ethereum.BlockChain(), blocks[:i]) {
- continue
- }
- if _, err := self.ethereum.BlockChain().InsertChain(blocks[:i]); err != nil {
- return false, fmt.Errorf("invalid block %d: %v", n, err)
- }
- }
- return true, nil
-}
-
-func (self *adminApi) ExportChain(req *shared.Request) (interface{}, error) {
- args := new(ImportExportChainArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- fh, err := os.OpenFile(args.Filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
- if err != nil {
- return false, err
- }
- defer fh.Close()
- if err := self.ethereum.BlockChain().Export(fh); err != nil {
- return false, err
- }
-
- return true, nil
-}
-
-func (self *adminApi) Verbosity(req *shared.Request) (interface{}, error) {
- args := new(VerbosityArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- glog.SetV(args.Level)
- return true, nil
-}
-
-func (self *adminApi) SetSolc(req *shared.Request) (interface{}, error) {
- args := new(SetSolcArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- solc, err := self.xeth.SetSolc(args.Path)
- if err != nil {
- return nil, err
- }
- return solc.Info(), nil
-}
-
-func (self *adminApi) StartRPC(req *shared.Request) (interface{}, error) {
- args := new(StartRPCArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- cfg := comms.HttpConfig{
- ListenAddress: args.ListenAddress,
- ListenPort: args.ListenPort,
- CorsDomain: args.CorsDomain,
- }
-
- apis, err := ParseApiString(args.Apis, self.codec, self.xeth, self.stack)
- if err != nil {
- return false, err
- }
-
- err = comms.StartHttp(cfg, self.codec, Merge(apis...))
- if err == nil {
- return true, nil
- }
- return false, err
-}
-
-func (self *adminApi) StopRPC(req *shared.Request) (interface{}, error) {
- comms.StopHttp()
- return true, nil
-}
-
-func (self *adminApi) SleepBlocks(req *shared.Request) (interface{}, error) {
- args := new(SleepBlocksArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
- var timer <-chan time.Time
- var height *big.Int
- var err error
- if args.Timeout > 0 {
- timer = time.NewTimer(time.Duration(args.Timeout) * time.Second).C
- }
-
- height = new(big.Int).Add(self.xeth.CurrentBlock().Number(), big.NewInt(args.N))
- height, err = sleepBlocks(self.xeth.UpdateState(), height, timer)
- if err != nil {
- return nil, err
- }
- return height.Uint64(), nil
-}
-
-func sleepBlocks(wait chan *big.Int, height *big.Int, timer <-chan time.Time) (newHeight *big.Int, err error) {
- wait <- height
- select {
- case <-timer:
- // if times out make sure the xeth loop does not block
- go func() {
- select {
- case wait <- nil:
- case <-wait:
- }
- }()
- return nil, fmt.Errorf("timeout")
- case newHeight = <-wait:
- }
- return
-}
-
-func (self *adminApi) Sleep(req *shared.Request) (interface{}, error) {
- args := new(SleepArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
- time.Sleep(time.Duration(args.S) * time.Second)
- return nil, nil
-}
-
-func (self *adminApi) SetGlobalRegistrar(req *shared.Request) (interface{}, error) {
- args := new(SetGlobalRegistrarArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- sender := common.HexToAddress(args.ContractAddress)
-
- reg := registrar.New(self.xeth)
- txhash, err := reg.SetGlobalRegistrar(args.NameReg, sender)
- if err != nil {
- return false, err
- }
-
- return txhash, nil
-}
-
-func (self *adminApi) SetHashReg(req *shared.Request) (interface{}, error) {
- args := new(SetHashRegArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- reg := registrar.New(self.xeth)
- sender := common.HexToAddress(args.Sender)
- txhash, err := reg.SetHashReg(args.HashReg, sender)
- if err != nil {
- return false, err
- }
-
- return txhash, nil
-}
-
-func (self *adminApi) SetUrlHint(req *shared.Request) (interface{}, error) {
- args := new(SetUrlHintArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- urlHint := args.UrlHint
- sender := common.HexToAddress(args.Sender)
-
- reg := registrar.New(self.xeth)
- txhash, err := reg.SetUrlHint(urlHint, sender)
- if err != nil {
- return nil, err
- }
-
- return txhash, nil
-}
-
-func (self *adminApi) SaveInfo(req *shared.Request) (interface{}, error) {
- args := new(SaveInfoArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- contenthash, err := compiler.SaveInfo(&args.ContractInfo, args.Filename)
- if err != nil {
- return nil, err
- }
-
- return contenthash.Hex(), nil
-}
-
-func (self *adminApi) Register(req *shared.Request) (interface{}, error) {
- args := new(RegisterArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- sender := common.HexToAddress(args.Sender)
- // sender and contract address are passed as hex strings
- codeb := self.xeth.CodeAtBytes(args.Address)
- codeHash := common.BytesToHash(crypto.Sha3(codeb))
- contentHash := common.HexToHash(args.ContentHashHex)
- registry := registrar.New(self.xeth)
-
- _, err := registry.SetHashToHash(sender, codeHash, contentHash)
- if err != nil {
- return false, err
- }
-
- return true, nil
-}
-
-func (self *adminApi) RegisterUrl(req *shared.Request) (interface{}, error) {
- args := new(RegisterUrlArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- sender := common.HexToAddress(args.Sender)
- registry := registrar.New(self.xeth)
- _, err := registry.SetUrlToHash(sender, common.HexToHash(args.ContentHash), args.Url)
- if err != nil {
- return false, err
- }
-
- return true, nil
-}
-
-func (self *adminApi) StartNatSpec(req *shared.Request) (interface{}, error) {
- self.ethereum.NatSpec = true
- return true, nil
-}
-
-func (self *adminApi) StopNatSpec(req *shared.Request) (interface{}, error) {
- self.ethereum.NatSpec = false
- return true, nil
-}
-
-func (self *adminApi) GetContractInfo(req *shared.Request) (interface{}, error) {
- args := new(GetContractInfoArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- infoDoc, err := natspec.FetchDocsForContract(args.Contract, self.xeth, self.ethereum.HTTPClient())
- if err != nil {
- return nil, err
- }
-
- var info interface{}
- err = self.coder.Decode(infoDoc, &info)
- if err != nil {
- return nil, err
- }
-
- return info, nil
-}
-
-func (self *adminApi) HttpGet(req *shared.Request) (interface{}, error) {
- args := new(HttpGetArgs)
- if err := self.coder.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- resp, err := self.ethereum.HTTPClient().Get(args.Uri, args.Path)
- if err != nil {
- return nil, err
- }
-
- return string(resp), nil
-}
-
-func (self *adminApi) EnableUserAgent(req *shared.Request) (interface{}, error) {
- if fe, ok := self.xeth.Frontend().(*useragent.RemoteFrontend); ok {
- fe.Enable()
- }
- return true, nil
-}
diff --git a/rpc/api/admin_args.go b/rpc/api/admin_args.go
deleted file mode 100644
index e3a2f72bf..000000000
--- a/rpc/api/admin_args.go
+++ /dev/null
@@ -1,490 +0,0 @@
-// 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 (
- "encoding/json"
-
- "github.com/ethereum/go-ethereum/common/compiler"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type AddPeerArgs struct {
- Url string
-}
-
-func (args *AddPeerArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) != 1 {
- return shared.NewDecodeParamError("Expected enode as argument")
- }
-
- urlstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("url", "not a string")
- }
- args.Url = urlstr
-
- return nil
-}
-
-type ImportExportChainArgs struct {
- Filename string
-}
-
-func (args *ImportExportChainArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) != 1 {
- return shared.NewDecodeParamError("Expected filename as argument")
- }
-
- filename, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("filename", "not a string")
- }
- args.Filename = filename
-
- return nil
-}
-
-type VerbosityArgs struct {
- Level int
-}
-
-func (args *VerbosityArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) != 1 {
- return shared.NewDecodeParamError("Expected enode as argument")
- }
-
- level, err := numString(obj[0])
- if err == nil {
- args.Level = int(level.Int64())
- }
-
- return nil
-}
-
-type SetSolcArgs struct {
- Path string
-}
-
-func (args *SetSolcArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) != 1 {
- return shared.NewDecodeParamError("Expected path as argument")
- }
-
- if pathstr, ok := obj[0].(string); ok {
- args.Path = pathstr
- return nil
- }
-
- return shared.NewInvalidTypeError("path", "not a string")
-}
-
-type StartRPCArgs struct {
- ListenAddress string
- ListenPort uint
- CorsDomain string
- Apis string
-}
-
-func (args *StartRPCArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- args.ListenAddress = "127.0.0.1"
- args.ListenPort = 8545
- args.Apis = "net,eth,web3"
-
- if len(obj) >= 1 && obj[0] != nil {
- if addr, ok := obj[0].(string); ok {
- args.ListenAddress = addr
- } else {
- return shared.NewInvalidTypeError("listenAddress", "not a string")
- }
- }
-
- if len(obj) >= 2 && obj[1] != nil {
- if port, ok := obj[1].(float64); ok && port >= 0 && port <= 64*1024 {
- args.ListenPort = uint(port)
- } else {
- return shared.NewInvalidTypeError("listenPort", "not a valid port number")
- }
- }
-
- if len(obj) >= 3 && obj[2] != nil {
- if corsDomain, ok := obj[2].(string); ok {
- args.CorsDomain = corsDomain
- } else {
- return shared.NewInvalidTypeError("corsDomain", "not a string")
- }
- }
-
- if len(obj) >= 4 && obj[3] != nil {
- if apis, ok := obj[3].(string); ok {
- args.Apis = apis
- } else {
- return shared.NewInvalidTypeError("apis", "not a string")
- }
- }
-
- return nil
-}
-
-type SleepArgs struct {
- S int
-}
-
-func (args *SleepArgs) UnmarshalJSON(b []byte) (err error) {
-
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
- if len(obj) >= 1 {
- if obj[0] != nil {
- if n, err := numString(obj[0]); err == nil {
- args.S = int(n.Int64())
- } else {
- return shared.NewInvalidTypeError("N", "not an integer: "+err.Error())
- }
- } else {
- return shared.NewInsufficientParamsError(0, 1)
- }
- }
- return nil
-}
-
-type SleepBlocksArgs struct {
- N int64
- Timeout int64
-}
-
-func (args *SleepBlocksArgs) UnmarshalJSON(b []byte) (err error) {
-
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- args.N = 1
- args.Timeout = 0
- if len(obj) >= 1 && obj[0] != nil {
- if n, err := numString(obj[0]); err == nil {
- args.N = n.Int64()
- } else {
- return shared.NewInvalidTypeError("N", "not an integer: "+err.Error())
- }
- }
-
- if len(obj) >= 2 && obj[1] != nil {
- if n, err := numString(obj[1]); err == nil {
- args.Timeout = n.Int64()
- } else {
- return shared.NewInvalidTypeError("Timeout", "not an integer: "+err.Error())
- }
- }
-
- return nil
-}
-
-type SetGlobalRegistrarArgs struct {
- NameReg string
- ContractAddress string
-}
-
-func (args *SetGlobalRegistrarArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) == 0 {
- return shared.NewDecodeParamError("Expected namereg address")
- }
-
- if len(obj) >= 1 {
- if namereg, ok := obj[0].(string); ok {
- args.NameReg = namereg
- } else {
- return shared.NewInvalidTypeError("NameReg", "not a string")
- }
- }
-
- if len(obj) >= 2 && obj[1] != nil {
- if addr, ok := obj[1].(string); ok {
- args.ContractAddress = addr
- } else {
- return shared.NewInvalidTypeError("ContractAddress", "not a string")
- }
- }
-
- return nil
-}
-
-type SetHashRegArgs struct {
- HashReg string
- Sender string
-}
-
-func (args *SetHashRegArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) >= 1 && obj[0] != nil {
- if hashreg, ok := obj[0].(string); ok {
- args.HashReg = hashreg
- } else {
- return shared.NewInvalidTypeError("HashReg", "not a string")
- }
- }
-
- if len(obj) >= 2 && obj[1] != nil {
- if sender, ok := obj[1].(string); ok {
- args.Sender = sender
- } else {
- return shared.NewInvalidTypeError("Sender", "not a string")
- }
- }
-
- return nil
-}
-
-type SetUrlHintArgs struct {
- UrlHint string
- Sender string
-}
-
-func (args *SetUrlHintArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) >= 1 && obj[0] != nil {
- if urlhint, ok := obj[0].(string); ok {
- args.UrlHint = urlhint
- } else {
- return shared.NewInvalidTypeError("UrlHint", "not a string")
- }
- }
-
- if len(obj) >= 2 && obj[1] != nil {
- if sender, ok := obj[1].(string); ok {
- args.Sender = sender
- } else {
- return shared.NewInvalidTypeError("Sender", "not a string")
- }
- }
-
- return nil
-}
-
-type SaveInfoArgs struct {
- ContractInfo compiler.ContractInfo
- Filename string
-}
-
-func (args *SaveInfoArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- if jsonraw, err := json.Marshal(obj[0]); err == nil {
- if err = json.Unmarshal(jsonraw, &args.ContractInfo); err != nil {
- return err
- }
- } else {
- return err
- }
-
- if filename, ok := obj[1].(string); ok {
- args.Filename = filename
- } else {
- return shared.NewInvalidTypeError("Filename", "not a string")
- }
-
- return nil
-}
-
-type RegisterArgs struct {
- Sender string
- Address string
- ContentHashHex string
-}
-
-func (args *RegisterArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 3 {
- return shared.NewInsufficientParamsError(len(obj), 3)
- }
-
- if len(obj) >= 1 {
- if sender, ok := obj[0].(string); ok {
- args.Sender = sender
- } else {
- return shared.NewInvalidTypeError("Sender", "not a string")
- }
- }
-
- if len(obj) >= 2 {
- if address, ok := obj[1].(string); ok {
- args.Address = address
- } else {
- return shared.NewInvalidTypeError("Address", "not a string")
- }
- }
-
- if len(obj) >= 3 {
- if hex, ok := obj[2].(string); ok {
- args.ContentHashHex = hex
- } else {
- return shared.NewInvalidTypeError("ContentHashHex", "not a string")
- }
- }
-
- return nil
-}
-
-type RegisterUrlArgs struct {
- Sender string
- ContentHash string
- Url string
-}
-
-func (args *RegisterUrlArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) >= 1 {
- if sender, ok := obj[0].(string); ok {
- args.Sender = sender
- } else {
- return shared.NewInvalidTypeError("Sender", "not a string")
- }
- }
-
- if len(obj) >= 2 {
- if sender, ok := obj[1].(string); ok {
- args.ContentHash = sender
- } else {
- return shared.NewInvalidTypeError("ContentHash", "not a string")
- }
- }
-
- if len(obj) >= 3 {
- if sender, ok := obj[2].(string); ok {
- args.Url = sender
- } else {
- return shared.NewInvalidTypeError("Url", "not a string")
- }
- }
-
- return nil
-}
-
-type GetContractInfoArgs struct {
- Contract string
-}
-
-func (args *GetContractInfoArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- if len(obj) >= 1 {
- if contract, ok := obj[0].(string); ok {
- args.Contract = contract
- } else {
- return shared.NewInvalidTypeError("Contract", "not a string")
- }
- }
-
- return nil
-}
-
-type HttpGetArgs struct {
- Uri string
- Path string
-}
-
-func (args *HttpGetArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- if len(obj) >= 1 {
- if uri, ok := obj[0].(string); ok {
- args.Uri = uri
- } else {
- return shared.NewInvalidTypeError("Uri", "not a string")
- }
- }
-
- if len(obj) >= 2 && obj[1] != nil {
- if path, ok := obj[1].(string); ok {
- args.Path = path
- } else {
- return shared.NewInvalidTypeError("Path", "not a string")
- }
- }
-
- return nil
-}
diff --git a/rpc/api/admin_js.go b/rpc/api/admin_js.go
deleted file mode 100644
index 413ea8d47..000000000
--- a/rpc/api/admin_js.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// 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
-
-const Admin_JS = `
-web3._extend({
- property: 'admin',
- methods:
- [
- new web3._extend.Method({
- name: 'addPeer',
- call: 'admin_addPeer',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'exportChain',
- call: 'admin_exportChain',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'importChain',
- call: 'admin_importChain',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'sleepBlocks',
- call: 'admin_sleepBlocks',
- params: 2,
- inputFormatter: [null, null]
- }),
- new web3._extend.Method({
- name: 'verbosity',
- call: 'admin_verbosity',
- params: 1,
- inputFormatter: [web3._extend.utils.fromDecimal]
- }),
- new web3._extend.Method({
- name: 'setSolc',
- call: 'admin_setSolc',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'startRPC',
- call: 'admin_startRPC',
- params: 4,
- inputFormatter: [null, null, null, null]
- }),
- new web3._extend.Method({
- name: 'stopRPC',
- call: 'admin_stopRPC',
- params: 0,
- inputFormatter: []
- }),
- new web3._extend.Method({
- name: 'setGlobalRegistrar',
- call: 'admin_setGlobalRegistrar',
- params: 2,
- inputFormatter: [null,null]
- }),
- new web3._extend.Method({
- name: 'setHashReg',
- call: 'admin_setHashReg',
- params: 2,
- inputFormatter: [null,null]
- }),
- new web3._extend.Method({
- name: 'setUrlHint',
- call: 'admin_setUrlHint',
- params: 2,
- inputFormatter: [null,null]
- }),
- new web3._extend.Method({
- name: 'saveInfo',
- call: 'admin_saveInfo',
- params: 2,
- inputFormatter: [null,null]
- }),
- new web3._extend.Method({
- name: 'register',
- call: 'admin_register',
- params: 3,
- inputFormatter: [null,null,null]
- }),
- new web3._extend.Method({
- name: 'registerUrl',
- call: 'admin_registerUrl',
- params: 3,
- inputFormatter: [null,null,null]
- }),
- new web3._extend.Method({
- name: 'startNatSpec',
- call: 'admin_startNatSpec',
- params: 0,
- inputFormatter: []
- }),
- new web3._extend.Method({
- name: 'stopNatSpec',
- call: 'admin_stopNatSpec',
- params: 0,
- inputFormatter: []
- }),
- new web3._extend.Method({
- name: 'getContractInfo',
- call: 'admin_getContractInfo',
- params: 1,
- inputFormatter: [null],
- }),
- new web3._extend.Method({
- name: 'httpGet',
- call: 'admin_httpGet',
- params: 2,
- inputFormatter: [null, null]
- })
- ],
- properties:
- [
- new web3._extend.Property({
- name: 'nodeInfo',
- getter: 'admin_nodeInfo'
- }),
- new web3._extend.Property({
- name: 'peers',
- getter: 'admin_peers'
- }),
- new web3._extend.Property({
- name: 'datadir',
- getter: 'admin_datadir'
- })
- ]
-});
-`
diff --git a/rpc/api/api.go b/rpc/api/api.go
deleted file mode 100644
index e03250ec6..000000000
--- a/rpc/api/api.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 (
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-// Merge multiple API's to a single API instance
-func Merge(apis ...shared.EthereumApi) shared.EthereumApi {
- return newMergedApi(apis...)
-}
diff --git a/rpc/api/api_test.go b/rpc/api/api_test.go
deleted file mode 100644
index eb63e8151..000000000
--- a/rpc/api/api_test.go
+++ /dev/null
@@ -1,170 +0,0 @@
-// 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 (
- "testing"
-
- "encoding/json"
- "strconv"
-
- "github.com/ethereum/go-ethereum/common/compiler"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-func TestParseApiString(t *testing.T) {
- apis, err := ParseApiString("", codec.JSON, nil, nil)
- if err == nil {
- t.Errorf("Expected an err from parsing empty API string but got nil")
- }
-
- if len(apis) != 0 {
- t.Errorf("Expected 0 apis from empty API string")
- }
-
- apis, err = ParseApiString("eth", codec.JSON, nil, nil)
- if err != nil {
- t.Errorf("Expected nil err from parsing empty API string but got %v", err)
- }
-
- if len(apis) != 1 {
- t.Errorf("Expected 1 apis but got %d - %v", apis, apis)
- }
-
- apis, err = ParseApiString("eth,eth", codec.JSON, nil, nil)
- if err != nil {
- t.Errorf("Expected nil err from parsing empty API string but got \"%v\"", err)
- }
-
- if len(apis) != 2 {
- t.Errorf("Expected 2 apis but got %d - %v", apis, apis)
- }
-
- apis, err = ParseApiString("eth,invalid", codec.JSON, nil, nil)
- if err == nil {
- t.Errorf("Expected an err but got no err")
- }
-
-}
-
-const solcVersion = "0.9.23"
-
-func TestCompileSolidity(t *testing.T) {
-
- solc, err := compiler.New("")
- if solc == nil {
- t.Skip("no solc found: skip")
- } else if solc.Version() != solcVersion {
- t.Skip("WARNING: skipping test because of solc different version (%v, test written for %v, may need to update)", solc.Version(), solcVersion)
- }
- source := `contract test {\n` +
- " /// @notice Will multiply `a` by 7." + `\n` +
- ` function multiply(uint a) returns(uint d) {\n` +
- ` return a * 7;\n` +
- ` }\n` +
- `}\n`
-
- jsonstr := `{"jsonrpc":"2.0","method":"eth_compileSolidity","params":["` + source + `"],"id":64}`
-
- expCode := "0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"
- expAbiDefinition := `[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]`
- expUserDoc := `{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}}`
- expDeveloperDoc := `{"methods":{}}`
- expCompilerVersion := solc.Version()
- expLanguage := "Solidity"
- expLanguageVersion := "0"
- expSource := source
-
- eth := &eth.Ethereum{}
- xeth := xeth.NewTest(nil, nil)
- api := NewEthApi(xeth, eth, codec.JSON)
-
- var rpcRequest shared.Request
- json.Unmarshal([]byte(jsonstr), &rpcRequest)
-
- response, err := api.CompileSolidity(&rpcRequest)
- if err != nil {
- t.Errorf("Execution failed, %v", err)
- }
-
- respjson, err := json.Marshal(response)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- var contracts = make(map[string]*compiler.Contract)
- err = json.Unmarshal(respjson, &contracts)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- if len(contracts) != 1 {
- t.Errorf("expected one contract, got %v", len(contracts))
- }
-
- contract := contracts["test"]
-
- if contract.Code != expCode {
- t.Errorf("Expected \n%s got \n%s", expCode, contract.Code)
- }
-
- if strconv.Quote(contract.Info.Source) != `"`+expSource+`"` {
- t.Errorf("Expected \n'%s' got \n'%s'", expSource, strconv.Quote(contract.Info.Source))
- }
-
- if contract.Info.Language != expLanguage {
- t.Errorf("Expected %s got %s", expLanguage, contract.Info.Language)
- }
-
- if contract.Info.LanguageVersion != expLanguageVersion {
- t.Errorf("Expected %s got %s", expLanguageVersion, contract.Info.LanguageVersion)
- }
-
- if contract.Info.CompilerVersion != expCompilerVersion {
- t.Errorf("Expected %s got %s", expCompilerVersion, contract.Info.CompilerVersion)
- }
-
- userdoc, err := json.Marshal(contract.Info.UserDoc)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- devdoc, err := json.Marshal(contract.Info.DeveloperDoc)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- abidef, err := json.Marshal(contract.Info.AbiDefinition)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- if string(abidef) != expAbiDefinition {
- t.Errorf("Expected \n'%s' got \n'%s'", expAbiDefinition, string(abidef))
- }
-
- if string(userdoc) != expUserDoc {
- t.Errorf("Expected \n'%s' got \n'%s'", expUserDoc, string(userdoc))
- }
-
- if string(devdoc) != expDeveloperDoc {
- t.Errorf("Expected %s got %s", expDeveloperDoc, string(devdoc))
- }
-}
diff --git a/rpc/api/args.go b/rpc/api/args.go
deleted file mode 100644
index 20f073b67..000000000
--- a/rpc/api/args.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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 (
- "encoding/json"
-
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type CompileArgs struct {
- Source string
-}
-
-func (args *CompileArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
- argstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("arg0", "is not a string")
- }
- args.Source = argstr
-
- return nil
-}
-
-type FilterStringArgs struct {
- Word string
-}
-
-func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- var argstr string
- argstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("filter", "not a string")
- }
- switch argstr {
- case "latest", "pending":
- break
- default:
- return shared.NewValidationError("Word", "Must be `latest` or `pending`")
- }
- args.Word = argstr
- return nil
-}
diff --git a/rpc/api/args_test.go b/rpc/api/args_test.go
deleted file mode 100644
index 130315bd9..000000000
--- a/rpc/api/args_test.go
+++ /dev/null
@@ -1,2649 +0,0 @@
-// 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"
- "fmt"
- "math/big"
- "testing"
-
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-func TestBlockheightInvalidString(t *testing.T) {
- v := "foo"
- var num int64
-
- str := ExpectInvalidTypeError(blockHeight(v, &num))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockheightEarliest(t *testing.T) {
- v := "earliest"
- e := int64(0)
- var num int64
-
- err := blockHeight(v, &num)
- if err != nil {
- t.Error(err)
- }
-
- if num != e {
- t.Errorf("Expected %s but got %s", e, num)
- }
-}
-
-func TestBlockheightLatest(t *testing.T) {
- v := "latest"
- e := int64(-1)
- var num int64
-
- err := blockHeight(v, &num)
- if err != nil {
- t.Error(err)
- }
-
- if num != e {
- t.Errorf("Expected %s but got %s", e, num)
- }
-}
-
-func TestBlockheightPending(t *testing.T) {
- v := "pending"
- e := int64(-2)
- var num int64
-
- err := blockHeight(v, &num)
- if err != nil {
- t.Error(err)
- }
-
- if num != e {
- t.Errorf("Expected %s but got %s", e, num)
- }
-}
-
-func ExpectValidationError(err error) string {
- var str string
- switch err.(type) {
- case nil:
- str = "Expected error but didn't get one"
- case *shared.ValidationError:
- break
- default:
- str = fmt.Sprintf("Expected *rpc.ValidationError but got %T with message `%s`", err, err.Error())
- }
- return str
-}
-
-func ExpectInvalidTypeError(err error) string {
- var str string
- switch err.(type) {
- case nil:
- str = "Expected error but didn't get one"
- case *shared.InvalidTypeError:
- break
- default:
- str = fmt.Sprintf("Expected *rpc.InvalidTypeError but got %T with message `%s`", err, err.Error())
- }
- return str
-}
-
-func ExpectInsufficientParamsError(err error) string {
- var str string
- switch err.(type) {
- case nil:
- str = "Expected error but didn't get one"
- case *shared.InsufficientParamsError:
- break
- default:
- str = fmt.Sprintf("Expected *rpc.InsufficientParamsError but got %T with message %s", err, err.Error())
- }
- return str
-}
-
-func ExpectDecodeParamError(err error) string {
- var str string
- switch err.(type) {
- case nil:
- str = "Expected error but didn't get one"
- case *shared.DecodeParamError:
- break
- default:
- str = fmt.Sprintf("Expected *rpc.DecodeParamError but got %T with message `%s`", err, err.Error())
- }
- return str
-}
-
-func TestSha3(t *testing.T) {
- input := `["0x68656c6c6f20776f726c64"]`
- expected := "0x68656c6c6f20776f726c64"
-
- args := new(Sha3Args)
- json.Unmarshal([]byte(input), &args)
-
- if args.Data != expected {
- t.Error("got %s expected %s", input, expected)
- }
-}
-
-func TestSha3ArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(Sha3Args)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSha3ArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(Sha3Args)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-func TestSha3ArgsDataInvalid(t *testing.T) {
- input := `[4]`
-
- args := new(Sha3Args)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBalanceArgs(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "0x1f"]`
- expected := new(GetBalanceArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.BlockNumber = 31
-
- args := new(GetBalanceArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.Address != expected.Address {
- t.Errorf("Address should be %v but is %v", expected.Address, args.Address)
- }
-
- if args.BlockNumber != expected.BlockNumber {
- t.Errorf("BlockNumber should be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetBalanceArgsBlocknumMissing(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1"]`
- expected := new(GetBalanceArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.BlockNumber = -1
-
- args := new(GetBalanceArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.Address != expected.Address {
- t.Errorf("Address should be %v but is %v", expected.Address, args.Address)
- }
-
- if args.BlockNumber != expected.BlockNumber {
- t.Errorf("BlockNumber should be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetBalanceArgsLatest(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"]`
- expected := new(GetBalanceArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.BlockNumber = -1
-
- args := new(GetBalanceArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.Address != expected.Address {
- t.Errorf("Address should be %v but is %v", expected.Address, args.Address)
- }
-
- if args.BlockNumber != expected.BlockNumber {
- t.Errorf("BlockNumber should be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetBalanceArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(GetBalanceArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBalanceArgsInvalid(t *testing.T) {
- input := `6`
-
- args := new(GetBalanceArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBalanceArgsBlockInvalid(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", false]`
-
- args := new(GetBalanceArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBalanceArgsAddressInvalid(t *testing.T) {
- input := `[-9, "latest"]`
-
- args := new(GetBalanceArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBlockByHashArgs(t *testing.T) {
- input := `["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", true]`
- expected := new(GetBlockByHashArgs)
- expected.BlockHash = "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
- expected.IncludeTxs = true
-
- args := new(GetBlockByHashArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.BlockHash != expected.BlockHash {
- t.Errorf("BlockHash should be %v but is %v", expected.BlockHash, args.BlockHash)
- }
-
- if args.IncludeTxs != expected.IncludeTxs {
- t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
- }
-}
-
-func TestGetBlockByHashArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(GetBlockByHashArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBlockByHashArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(GetBlockByHashArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBlockByHashArgsHashInt(t *testing.T) {
- input := `[8]`
-
- args := new(GetBlockByHashArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBlockByHashArgsHashBool(t *testing.T) {
- input := `[false, true]`
-
- args := new(GetBlockByHashArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBlockByNumberArgsBlockNum(t *testing.T) {
- input := `[436, false]`
- expected := new(GetBlockByNumberArgs)
- expected.BlockNumber = 436
- expected.IncludeTxs = false
-
- args := new(GetBlockByNumberArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.BlockNumber != expected.BlockNumber {
- t.Errorf("BlockNumber should be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-
- if args.IncludeTxs != expected.IncludeTxs {
- t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
- }
-}
-
-func TestGetBlockByNumberArgsBlockHex(t *testing.T) {
- input := `["0x1b4", false]`
- expected := new(GetBlockByNumberArgs)
- expected.BlockNumber = 436
- expected.IncludeTxs = false
-
- args := new(GetBlockByNumberArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.BlockNumber != expected.BlockNumber {
- t.Errorf("BlockNumber should be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-
- if args.IncludeTxs != expected.IncludeTxs {
- t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
- }
-}
-func TestGetBlockByNumberArgsWords(t *testing.T) {
- input := `["earliest", true]`
- expected := new(GetBlockByNumberArgs)
- expected.BlockNumber = 0
- expected.IncludeTxs = true
-
- args := new(GetBlockByNumberArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.BlockNumber != expected.BlockNumber {
- t.Errorf("BlockNumber should be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-
- if args.IncludeTxs != expected.IncludeTxs {
- t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
- }
-}
-
-func TestGetBlockByNumberEmpty(t *testing.T) {
- input := `[]`
-
- args := new(GetBlockByNumberArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBlockByNumberShort(t *testing.T) {
- input := `["0xbbb"]`
-
- args := new(GetBlockByNumberArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetBlockByNumberBool(t *testing.T) {
- input := `[true, true]`
-
- args := new(GetBlockByNumberArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-func TestGetBlockByNumberBlockObject(t *testing.T) {
- input := `{}`
-
- args := new(GetBlockByNumberArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestNewTxArgs(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
- "0x10"]`
- expected := new(NewTxArgs)
- expected.From = "0xb60e8dd61c5d32be8058bb8eb970870f07233155"
- expected.To = "0xd46e8dd67c5d32be8058bb8eb970870f072445675"
- expected.Gas = big.NewInt(30400)
- expected.GasPrice = big.NewInt(10000000000000)
- expected.Value = big.NewInt(10000000000000)
- expected.Data = "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- expected.BlockNumber = big.NewInt(16).Int64()
-
- args := new(NewTxArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.From != args.From {
- t.Errorf("From shoud be %#v but is %#v", expected.From, args.From)
- }
-
- if expected.To != args.To {
- t.Errorf("To shoud be %#v but is %#v", expected.To, args.To)
- }
-
- if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
- t.Errorf("Gas shoud be %#v but is %#v", expected.Gas.Bytes(), args.Gas.Bytes())
- }
-
- if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
- t.Errorf("GasPrice shoud be %#v but is %#v", expected.GasPrice, args.GasPrice)
- }
-
- if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
- t.Errorf("Value shoud be %#v but is %#v", expected.Value, args.Value)
- }
-
- if expected.Data != args.Data {
- t.Errorf("Data shoud be %#v but is %#v", expected.Data, args.Data)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestNewTxArgsInt(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": 100,
- "gasPrice": 50,
- "value": 8765456789,
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
- 5]`
- expected := new(NewTxArgs)
- expected.Gas = big.NewInt(100)
- expected.GasPrice = big.NewInt(50)
- expected.Value = big.NewInt(8765456789)
- expected.BlockNumber = int64(5)
-
- args := new(NewTxArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
- t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas)
- }
-
- if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
- t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice)
- }
-
- if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
- t.Errorf("Value shoud be %v but is %v", expected.Value, args.Value)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestNewTxArgsBlockBool(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
- false]`
-
- args := new(NewTxArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestNewTxArgsGasInvalid(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": false,
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(NewTxArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestNewTxArgsGaspriceInvalid(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": false,
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(NewTxArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestNewTxArgsValueInvalid(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": false,
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(NewTxArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestNewTxArgsGasMissing(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
- expected := new(NewTxArgs)
- expected.Gas = nil
-
- args := new(NewTxArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.Gas != expected.Gas {
- // if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
- t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas)
- }
-}
-
-func TestNewTxArgsBlockGaspriceMissing(t *testing.T) {
- input := `[{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
- expected := new(NewTxArgs)
- expected.GasPrice = nil
-
- args := new(NewTxArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.GasPrice != expected.GasPrice {
- // if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
- t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice)
- }
-
-}
-
-func TestNewTxArgsValueMissing(t *testing.T) {
- input := `[{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
- expected := new(NewTxArgs)
- expected.Value = big.NewInt(0)
-
- args := new(NewTxArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
- t.Errorf("Value shoud be %v but is %v", expected.Value, args.Value)
- }
-
-}
-
-func TestNewTxArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(NewTxArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestNewTxArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(NewTxArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-func TestNewTxArgsNotStrings(t *testing.T) {
- input := `[{"from":6}]`
-
- args := new(NewTxArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestNewTxArgsFromEmpty(t *testing.T) {
- input := `[{"to": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]`
-
- args := new(NewTxArgs)
- str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCallArgs(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
- "0x10"]`
- expected := new(CallArgs)
- expected.From = "0xb60e8dd61c5d32be8058bb8eb970870f07233155"
- expected.To = "0xd46e8dd67c5d32be8058bb8eb970870f072445675"
- expected.Gas = big.NewInt(30400)
- expected.GasPrice = big.NewInt(10000000000000)
- expected.Value = big.NewInt(10000000000000)
- expected.Data = "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- expected.BlockNumber = big.NewInt(16).Int64()
-
- args := new(CallArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.To != args.To {
- t.Errorf("To shoud be %#v but is %#v", expected.To, args.To)
- }
-
- if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
- t.Errorf("Gas shoud be %#v but is %#v", expected.Gas.Bytes(), args.Gas.Bytes())
- }
-
- if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
- t.Errorf("GasPrice shoud be %#v but is %#v", expected.GasPrice, args.GasPrice)
- }
-
- if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
- t.Errorf("Value shoud be %#v but is %#v", expected.Value, args.Value)
- }
-
- if expected.Data != args.Data {
- t.Errorf("Data shoud be %#v but is %#v", expected.Data, args.Data)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestCallArgsInt(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": 100,
- "gasPrice": 50,
- "value": 8765456789,
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
- 5]`
- expected := new(CallArgs)
- expected.Gas = big.NewInt(100)
- expected.GasPrice = big.NewInt(50)
- expected.Value = big.NewInt(8765456789)
- expected.BlockNumber = int64(5)
-
- args := new(CallArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
- t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas)
- }
-
- if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
- t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice)
- }
-
- if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
- t.Errorf("Value shoud be %v but is %v", expected.Value, args.Value)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %v but is %v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestCallArgsBlockBool(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
- false]`
-
- args := new(CallArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCallArgsGasInvalid(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": false,
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(CallArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCallArgsGaspriceInvalid(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": false,
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(CallArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCallArgsValueInvalid(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": false,
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(CallArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCallArgsGasMissing(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(CallArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- expected := new(CallArgs)
- expected.Gas = nil
-
- if args.Gas != expected.Gas {
- // if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
- t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas)
- }
-
-}
-
-func TestCallArgsBlockGaspriceMissing(t *testing.T) {
- input := `[{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "value": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(CallArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- expected := new(CallArgs)
- expected.GasPrice = nil
-
- if args.GasPrice != expected.GasPrice {
- // if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
- t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice)
- }
-}
-
-func TestCallArgsValueMissing(t *testing.T) {
- input := `[{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }]`
-
- args := new(CallArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- expected := new(CallArgs)
- expected.Value = big.NewInt(int64(0))
-
- if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
- t.Errorf("GasPrice shoud be %v but is %v", expected.Value, args.Value)
- }
-}
-
-func TestCallArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(CallArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCallArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(CallArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-func TestCallArgsNotStrings(t *testing.T) {
- input := `[{"from":6}]`
-
- args := new(CallArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCallArgsToEmpty(t *testing.T) {
- input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]`
- args := new(CallArgs)
- err := json.Unmarshal([]byte(input), &args)
- if err != nil {
- t.Error("Did not expect error. Got", err)
- }
-}
-
-func TestGetStorageArgs(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"]`
- expected := new(GetStorageArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.BlockNumber = -1
-
- args := new(GetStorageArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetStorageArgsMissingBlocknum(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1"]`
- expected := new(GetStorageArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.BlockNumber = -1
-
- args := new(GetStorageArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetStorageInvalidArgs(t *testing.T) {
- input := `{}`
-
- args := new(GetStorageArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageInvalidBlockheight(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", {}]`
-
- args := new(GetStorageArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageEmptyArgs(t *testing.T) {
- input := `[]`
-
- args := new(GetStorageArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageAddressInt(t *testing.T) {
- input := `[32456785432456, "latest"]`
-
- args := new(GetStorageArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageAtArgs(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "0x0", "0x2"]`
- expected := new(GetStorageAtArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.Key = "0x0"
- expected.BlockNumber = 2
-
- args := new(GetStorageAtArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.Key != args.Key {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetStorageAtArgsMissingBlocknum(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "0x0"]`
- expected := new(GetStorageAtArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.Key = "0x0"
- expected.BlockNumber = -1
-
- args := new(GetStorageAtArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.Key != args.Key {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetStorageAtEmptyArgs(t *testing.T) {
- input := `[]`
-
- args := new(GetStorageAtArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageAtArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(GetStorageAtArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageAtArgsAddressNotString(t *testing.T) {
- input := `[true, "0x0", "0x2"]`
-
- args := new(GetStorageAtArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageAtArgsKeyNotString(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", true, "0x2"]`
-
- args := new(GetStorageAtArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetStorageAtArgsValueNotString(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "0x1", true]`
-
- args := new(GetStorageAtArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetTxCountArgs(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "pending"]`
- expected := new(GetTxCountArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.BlockNumber = -2
-
- args := new(GetTxCountArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetTxCountEmptyArgs(t *testing.T) {
- input := `[]`
-
- args := new(GetTxCountArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetTxCountEmptyArgsInvalid(t *testing.T) {
- input := `false`
-
- args := new(GetTxCountArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetTxCountAddressNotString(t *testing.T) {
- input := `[false, "pending"]`
-
- args := new(GetTxCountArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetTxCountBlockheightMissing(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1"]`
- expected := new(GetTxCountArgs)
- expected.Address = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
- expected.BlockNumber = -1
-
- args := new(GetTxCountArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetTxCountBlockheightInvalid(t *testing.T) {
- input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", {}]`
-
- args := new(GetTxCountArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetDataArgs(t *testing.T) {
- input := `["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8", "latest"]`
- expected := new(GetDataArgs)
- expected.Address = "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"
- expected.BlockNumber = -1
-
- args := new(GetDataArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetDataArgsBlocknumMissing(t *testing.T) {
- input := `["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"]`
- expected := new(GetDataArgs)
- expected.Address = "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"
- expected.BlockNumber = -1
-
- args := new(GetDataArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Address != args.Address {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestGetDataArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(GetDataArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetDataArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(GetDataArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetDataArgsAddressNotString(t *testing.T) {
- input := `[12, "latest"]`
-
- args := new(GetDataArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestGetDataArgsBlocknumberNotString(t *testing.T) {
- input := `["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8", false]`
-
- args := new(GetDataArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgs(t *testing.T) {
- input := `[{
- "fromBlock": "0x1",
- "toBlock": "0x2",
- "limit": "0x3",
- "offset": "0x0",
- "address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
- "topics":
- [
- ["0xAA", "0xBB"],
- ["0xCC", "0xDD"]
- ]
- }]`
-
- expected := new(BlockFilterArgs)
- expected.Earliest = 1
- expected.Latest = 2
- expected.Max = 3
- expected.Skip = 0
- expected.Address = []string{"0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"}
- expected.Topics = [][]string{
- []string{"0xAA", "0xBB"},
- []string{"0xCC", "0xDD"},
- }
-
- args := new(BlockFilterArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Earliest != args.Earliest {
- t.Errorf("Earliest shoud be %#v but is %#v", expected.Earliest, args.Earliest)
- }
-
- if expected.Latest != args.Latest {
- t.Errorf("Latest shoud be %#v but is %#v", expected.Latest, args.Latest)
- }
-
- if expected.Max != args.Max {
- t.Errorf("Max shoud be %#v but is %#v", expected.Max, args.Max)
- }
-
- if expected.Skip != args.Skip {
- t.Errorf("Skip shoud be %#v but is %#v", expected.Skip, args.Skip)
- }
-
- if expected.Address[0] != args.Address[0] {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.Topics[0][0] != args.Topics[0][0] {
- t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
- }
- if expected.Topics[0][1] != args.Topics[0][1] {
- t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
- }
- if expected.Topics[1][0] != args.Topics[1][0] {
- t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
- }
- if expected.Topics[1][1] != args.Topics[1][1] {
- t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
- }
-
-}
-
-func TestBlockFilterArgsDefaults(t *testing.T) {
- input := `[{
- "address": ["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"],
- "topics": ["0xAA","0xBB"]
- }]`
- expected := new(BlockFilterArgs)
- expected.Earliest = -1
- expected.Latest = -1
- expected.Max = 100
- expected.Skip = 0
- expected.Address = []string{"0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"}
- expected.Topics = [][]string{[]string{"0xAA"}, []string{"0xBB"}}
-
- args := new(BlockFilterArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Earliest != args.Earliest {
- t.Errorf("Earliest shoud be %#v but is %#v", expected.Earliest, args.Earliest)
- }
-
- if expected.Latest != args.Latest {
- t.Errorf("Latest shoud be %#v but is %#v", expected.Latest, args.Latest)
- }
-
- if expected.Max != args.Max {
- t.Errorf("Max shoud be %#v but is %#v", expected.Max, args.Max)
- }
-
- if expected.Skip != args.Skip {
- t.Errorf("Skip shoud be %#v but is %#v", expected.Skip, args.Skip)
- }
-
- if expected.Address[0] != args.Address[0] {
- t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
- }
-
- if expected.Topics[0][0] != args.Topics[0][0] {
- t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
- }
-
- if expected.Topics[1][0] != args.Topics[1][0] {
- t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
- }
-}
-
-func TestBlockFilterArgsWords(t *testing.T) {
- input := `[{"fromBlock": "latest", "toBlock": "latest"}]`
- expected := new(BlockFilterArgs)
- expected.Earliest = -1
- expected.Latest = -1
-
- args := new(BlockFilterArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Earliest != args.Earliest {
- t.Errorf("Earliest shoud be %#v but is %#v", expected.Earliest, args.Earliest)
- }
-
- input = `[{"toBlock": "pending"}]`
- if err := json.Unmarshal([]byte(input), &args); err == nil {
- t.Errorf("Pending isn't currently supported and should raise an unsupported error")
- }
-}
-
-func TestBlockFilterArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(BlockFilterArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsFromBool(t *testing.T) {
- input := `[{
- "fromBlock": true,
- "toBlock": "pending"
- }]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsToBool(t *testing.T) {
- input := `[{
- "fromBlock": "pending",
- "toBlock": true
- }]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsEmptyArgs(t *testing.T) {
- input := `[]`
-
- args := new(BlockFilterArgs)
- err := json.Unmarshal([]byte(input), &args)
- if err == nil {
- t.Error("Expected error but didn't get one")
- }
-}
-
-func TestBlockFilterArgsLimitInvalid(t *testing.T) {
- input := `[{"limit": false}]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsOffsetInvalid(t *testing.T) {
- input := `[{"offset": true}]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsAddressInt(t *testing.T) {
- input := `[{
- "address": 1,
- "topics": "0x12341234"}]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsAddressSliceInt(t *testing.T) {
- input := `[{
- "address": [1],
- "topics": "0x12341234"}]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsTopicInt(t *testing.T) {
- input := `[{
- "address": ["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"],
- "topics": 1}]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsTopicSliceInt(t *testing.T) {
- input := `[{
- "address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
- "topics": [1]}]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsTopicSliceInt2(t *testing.T) {
- input := `[{
- "address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
- "topics": ["0xAA", [1]]}]`
-
- args := new(BlockFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockFilterArgsTopicComplex(t *testing.T) {
- input := `[{
- "address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
- "topics": ["0xAA", ["0xBB", "0xCC"]]
- }]`
-
- args := new(BlockFilterArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- fmt.Printf("%v\n", args)
- return
- }
-
- if args.Topics[0][0] != "0xAA" {
- t.Errorf("Topic should be %s but is %s", "0xAA", args.Topics[0][0])
- }
-
- if args.Topics[1][0] != "0xBB" {
- t.Errorf("Topic should be %s but is %s", "0xBB", args.Topics[0][0])
- }
-
- if args.Topics[1][1] != "0xCC" {
- t.Errorf("Topic should be %s but is %s", "0xCC", args.Topics[0][0])
- }
-}
-
-func TestDbArgs(t *testing.T) {
- input := `["testDB","myKey","0xbeef"]`
- expected := new(DbArgs)
- expected.Database = "testDB"
- expected.Key = "myKey"
- expected.Value = []byte("0xbeef")
-
- args := new(DbArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if err := args.requirements(); err != nil {
- t.Error(err)
- }
-
- if expected.Database != args.Database {
- t.Errorf("Database shoud be %#v but is %#v", expected.Database, args.Database)
- }
-
- if expected.Key != args.Key {
- t.Errorf("Key shoud be %#v but is %#v", expected.Key, args.Key)
- }
-
- if bytes.Compare(expected.Value, args.Value) != 0 {
- t.Errorf("Value shoud be %#v but is %#v", expected.Value, args.Value)
- }
-}
-
-func TestDbArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(DbArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(DbArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbArgsDatabaseType(t *testing.T) {
- input := `[true, "keyval", "valval"]`
-
- args := new(DbArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbArgsKeyType(t *testing.T) {
- input := `["dbval", 3, "valval"]`
-
- args := new(DbArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbArgsValType(t *testing.T) {
- input := `["dbval", "keyval", {}]`
-
- args := new(DbArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbArgsDatabaseEmpty(t *testing.T) {
- input := `["", "keyval", "valval"]`
-
- args := new(DbArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err.Error())
- }
-
- str := ExpectValidationError(args.requirements())
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbArgsKeyEmpty(t *testing.T) {
- input := `["dbval", "", "valval"]`
-
- args := new(DbArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err.Error())
- }
-
- str := ExpectValidationError(args.requirements())
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbHexArgs(t *testing.T) {
- input := `["testDB","myKey","0xbeef"]`
- expected := new(DbHexArgs)
- expected.Database = "testDB"
- expected.Key = "myKey"
- expected.Value = []byte{0xbe, 0xef}
-
- args := new(DbHexArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if err := args.requirements(); err != nil {
- t.Error(err)
- }
-
- if expected.Database != args.Database {
- t.Errorf("Database shoud be %#v but is %#v", expected.Database, args.Database)
- }
-
- if expected.Key != args.Key {
- t.Errorf("Key shoud be %#v but is %#v", expected.Key, args.Key)
- }
-
- if bytes.Compare(expected.Value, args.Value) != 0 {
- t.Errorf("Value shoud be %#v but is %#v", expected.Value, args.Value)
- }
-}
-
-func TestDbHexArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(DbHexArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbHexArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(DbHexArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbHexArgsDatabaseType(t *testing.T) {
- input := `[true, "keyval", "valval"]`
-
- args := new(DbHexArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbHexArgsKeyType(t *testing.T) {
- input := `["dbval", 3, "valval"]`
-
- args := new(DbHexArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbHexArgsValType(t *testing.T) {
- input := `["dbval", "keyval", {}]`
-
- args := new(DbHexArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbHexArgsDatabaseEmpty(t *testing.T) {
- input := `["", "keyval", "valval"]`
-
- args := new(DbHexArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err.Error())
- }
-
- str := ExpectValidationError(args.requirements())
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDbHexArgsKeyEmpty(t *testing.T) {
- input := `["dbval", "", "valval"]`
-
- args := new(DbHexArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err.Error())
- }
-
- str := ExpectValidationError(args.requirements())
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperMessageArgs(t *testing.T) {
- input := `[{"from":"0xc931d93e97ab07fe42d923478ba2465f2",
- "topics": ["0x68656c6c6f20776f726c64"],
- "payload":"0x68656c6c6f20776f726c64",
- "ttl": "0x64",
- "priority": "0x64"}]`
- expected := new(WhisperMessageArgs)
- expected.From = "0xc931d93e97ab07fe42d923478ba2465f2"
- expected.To = ""
- expected.Payload = "0x68656c6c6f20776f726c64"
- expected.Priority = 100
- expected.Ttl = 100
- // expected.Topics = []string{"0x68656c6c6f20776f726c64"}
-
- args := new(WhisperMessageArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.From != args.From {
- t.Errorf("From shoud be %#v but is %#v", expected.From, args.From)
- }
-
- if expected.To != args.To {
- t.Errorf("To shoud be %#v but is %#v", expected.To, args.To)
- }
-
- if expected.Payload != args.Payload {
- t.Errorf("Value shoud be %#v but is %#v", expected.Payload, args.Payload)
- }
-
- if expected.Ttl != args.Ttl {
- t.Errorf("Ttl shoud be %#v but is %#v", expected.Ttl, args.Ttl)
- }
-
- if expected.Priority != args.Priority {
- t.Errorf("Priority shoud be %#v but is %#v", expected.Priority, args.Priority)
- }
-
- // if expected.Topics != args.Topics {
- // t.Errorf("Topic shoud be %#v but is %#v", expected.Topic, args.Topic)
- // }
-}
-
-func TestWhisperMessageArgsInt(t *testing.T) {
- input := `[{"from":"0xc931d93e97ab07fe42d923478ba2465f2",
- "topics": ["0x68656c6c6f20776f726c64"],
- "payload":"0x68656c6c6f20776f726c64",
- "ttl": 12,
- "priority": 16}]`
- expected := new(WhisperMessageArgs)
- expected.From = "0xc931d93e97ab07fe42d923478ba2465f2"
- expected.To = ""
- expected.Payload = "0x68656c6c6f20776f726c64"
- expected.Priority = 16
- expected.Ttl = 12
- // expected.Topics = []string{"0x68656c6c6f20776f726c64"}
-
- args := new(WhisperMessageArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.From != args.From {
- t.Errorf("From shoud be %#v but is %#v", expected.From, args.From)
- }
-
- if expected.To != args.To {
- t.Errorf("To shoud be %#v but is %#v", expected.To, args.To)
- }
-
- if expected.Payload != args.Payload {
- t.Errorf("Value shoud be %#v but is %#v", expected.Payload, args.Payload)
- }
-
- if expected.Ttl != args.Ttl {
- t.Errorf("Ttl shoud be %v but is %v", expected.Ttl, args.Ttl)
- }
-
- if expected.Priority != args.Priority {
- t.Errorf("Priority shoud be %v but is %v", expected.Priority, args.Priority)
- }
-
- // if expected.Topics != args.Topics {
- // t.Errorf("Topic shoud be %#v but is %#v", expected.Topic, args.Topic)
- // }
-}
-
-func TestWhisperMessageArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(WhisperMessageArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperMessageArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(WhisperMessageArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperMessageArgsTtlBool(t *testing.T) {
- input := `[{"from":"0xc931d93e97ab07fe42d923478ba2465f2",
- "topics": ["0x68656c6c6f20776f726c64"],
- "payload":"0x68656c6c6f20776f726c64",
- "ttl": true,
- "priority": "0x64"}]`
- args := new(WhisperMessageArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperMessageArgsPriorityBool(t *testing.T) {
- input := `[{"from":"0xc931d93e97ab07fe42d923478ba2465f2",
- "topics": ["0x68656c6c6f20776f726c64"],
- "payload":"0x68656c6c6f20776f726c64",
- "ttl": "0x12",
- "priority": true}]`
- args := new(WhisperMessageArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestFilterIdArgs(t *testing.T) {
- input := `["0x7"]`
- expected := new(FilterIdArgs)
- expected.Id = 7
-
- args := new(FilterIdArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Id != args.Id {
- t.Errorf("Id shoud be %#v but is %#v", expected.Id, args.Id)
- }
-}
-
-func TestFilterIdArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(FilterIdArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestFilterIdArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(FilterIdArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestFilterIdArgsBool(t *testing.T) {
- input := `[true]`
-
- args := new(FilterIdArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestWhisperFilterArgs(t *testing.T) {
- input := `[{"topics": ["0x68656c6c6f20776f726c64"], "to": "0x34ag445g3455b34"}]`
- expected := new(WhisperFilterArgs)
- expected.To = "0x34ag445g3455b34"
- expected.Topics = [][]string{[]string{"0x68656c6c6f20776f726c64"}}
-
- args := new(WhisperFilterArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.To != args.To {
- t.Errorf("To shoud be %#v but is %#v", expected.To, args.To)
- }
-
- // if expected.Topics != args.Topics {
- // t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
- // }
-}
-
-func TestWhisperFilterArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(WhisperFilterArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperFilterArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(WhisperFilterArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperFilterArgsToInt(t *testing.T) {
- input := `[{"to": 2}]`
-
- args := new(WhisperFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperFilterArgsToBool(t *testing.T) {
- input := `[{"topics": ["0x68656c6c6f20776f726c64"], "to": false}]`
-
- args := new(WhisperFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestWhisperFilterArgsToMissing(t *testing.T) {
- input := `[{"topics": ["0x68656c6c6f20776f726c64"]}]`
- expected := new(WhisperFilterArgs)
- expected.To = ""
-
- args := new(WhisperFilterArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if args.To != expected.To {
- t.Errorf("To shoud be %v but is %v", expected.To, args.To)
- }
-}
-
-func TestWhisperFilterArgsTopicInt(t *testing.T) {
- input := `[{"topics": [6], "to": "0x34ag445g3455b34"}]`
-
- args := new(WhisperFilterArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCompileArgs(t *testing.T) {
- input := `["contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"]`
- expected := new(CompileArgs)
- expected.Source = `contract test { function multiply(uint a) returns(uint d) { return a * 7; } }`
-
- args := new(CompileArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Source != args.Source {
- t.Errorf("Source shoud be %#v but is %#v", expected.Source, args.Source)
- }
-}
-
-func TestCompileArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(CompileArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCompileArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(CompileArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestCompileArgsBool(t *testing.T) {
- input := `[false]`
-
- args := new(CompileArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestFilterStringArgs(t *testing.T) {
- input := `["pending"]`
- expected := new(FilterStringArgs)
- expected.Word = "pending"
-
- args := new(FilterStringArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Word != args.Word {
- t.Errorf("Word shoud be %#v but is %#v", expected.Word, args.Word)
- }
-}
-
-func TestFilterStringEmptyArgs(t *testing.T) {
- input := `[]`
-
- args := new(FilterStringArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestFilterStringInvalidArgs(t *testing.T) {
- input := `{}`
-
- args := new(FilterStringArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestFilterStringWordInt(t *testing.T) {
- input := `[7]`
-
- args := new(FilterStringArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestFilterStringWordWrong(t *testing.T) {
- input := `["foo"]`
-
- args := new(FilterStringArgs)
- str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestWhisperIdentityArgs(t *testing.T) {
- input := `["0xc931d93e97ab07fe42d923478ba2465f283"]`
- expected := new(WhisperIdentityArgs)
- expected.Identity = "0xc931d93e97ab07fe42d923478ba2465f283"
-
- args := new(WhisperIdentityArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Identity != args.Identity {
- t.Errorf("Identity shoud be %#v but is %#v", expected.Identity, args.Identity)
- }
-}
-
-func TestWhisperIdentityArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(WhisperIdentityArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestWhisperIdentityArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(WhisperIdentityArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestWhisperIdentityArgsInt(t *testing.T) {
- input := `[4]`
-
- args := new(WhisperIdentityArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Errorf(str)
- }
-}
-
-func TestBlockNumArgs(t *testing.T) {
- input := `["0x29a"]`
- expected := new(BlockNumIndexArgs)
- expected.BlockNumber = 666
-
- args := new(BlockNumArg)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestBlockNumArgsWord(t *testing.T) {
- input := `["pending"]`
- expected := new(BlockNumIndexArgs)
- expected.BlockNumber = -2
-
- args := new(BlockNumArg)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-}
-
-func TestBlockNumArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(BlockNumArg)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockNumArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(BlockNumArg)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-func TestBlockNumArgsBool(t *testing.T) {
- input := `[true]`
-
- args := new(BlockNumArg)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockNumIndexArgs(t *testing.T) {
- input := `["0x29a", "0x0"]`
- expected := new(BlockNumIndexArgs)
- expected.BlockNumber = 666
- expected.Index = 0
-
- args := new(BlockNumIndexArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-
- if expected.Index != args.Index {
- t.Errorf("Index shoud be %#v but is %#v", expected.Index, args.Index)
- }
-}
-
-func TestBlockNumIndexArgsWord(t *testing.T) {
- input := `["latest", 67]`
- expected := new(BlockNumIndexArgs)
- expected.BlockNumber = -1
- expected.Index = 67
-
- args := new(BlockNumIndexArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.BlockNumber != args.BlockNumber {
- t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
- }
-
- if expected.Index != args.Index {
- t.Errorf("Index shoud be %#v but is %#v", expected.Index, args.Index)
- }
-}
-
-func TestBlockNumIndexArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(BlockNumIndexArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockNumIndexArgsInvalid(t *testing.T) {
- input := `"foo"`
-
- args := new(BlockNumIndexArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockNumIndexArgsBlocknumInvalid(t *testing.T) {
- input := `[{}, "0x1"]`
-
- args := new(BlockNumIndexArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockNumIndexArgsIndexInvalid(t *testing.T) {
- input := `["0x29a", true]`
-
- args := new(BlockNumIndexArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestHashIndexArgs(t *testing.T) {
- input := `["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b", "0x1"]`
- expected := new(HashIndexArgs)
- expected.Hash = "0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
- expected.Index = 1
-
- args := new(HashIndexArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Hash != args.Hash {
- t.Errorf("Hash shoud be %#v but is %#v", expected.Hash, args.Hash)
- }
-
- if expected.Index != args.Index {
- t.Errorf("Index shoud be %#v but is %#v", expected.Index, args.Index)
- }
-}
-
-func TestHashIndexArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(HashIndexArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestHashIndexArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(HashIndexArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestHashIndexArgsInvalidHash(t *testing.T) {
- input := `[7, "0x1"]`
-
- args := new(HashIndexArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestHashIndexArgsInvalidIndex(t *testing.T) {
- input := `["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b", false]`
-
- args := new(HashIndexArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestHashArgs(t *testing.T) {
- input := `["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"]`
- expected := new(HashIndexArgs)
- expected.Hash = "0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
-
- args := new(HashArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Hash != args.Hash {
- t.Errorf("Hash shoud be %#v but is %#v", expected.Hash, args.Hash)
- }
-}
-
-func TestHashArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(HashArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestHashArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(HashArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestHashArgsInvalidHash(t *testing.T) {
- input := `[7]`
-
- args := new(HashArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSubmitWorkArgs(t *testing.T) {
- input := `["0x0000000000000001", "0x1234567890abcdef1234567890abcdef", "0xD1GE5700000000000000000000000000"]`
- expected := new(SubmitWorkArgs)
- expected.Nonce = 1
- expected.Header = "0x1234567890abcdef1234567890abcdef"
- expected.Digest = "0xD1GE5700000000000000000000000000"
-
- args := new(SubmitWorkArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Nonce != args.Nonce {
- t.Errorf("Nonce shoud be %d but is %d", expected.Nonce, args.Nonce)
- }
-
- if expected.Header != args.Header {
- t.Errorf("Header shoud be %#v but is %#v", expected.Header, args.Header)
- }
-
- if expected.Digest != args.Digest {
- t.Errorf("Digest shoud be %#v but is %#v", expected.Digest, args.Digest)
- }
-}
-
-func TestSubmitWorkArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(SubmitWorkArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSubmitWorkArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(SubmitWorkArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSubmitWorkArgsNonceInt(t *testing.T) {
- input := `[1, "0x1234567890abcdef1234567890abcdef", "0xD1GE5700000000000000000000000000"]`
-
- args := new(SubmitWorkArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-func TestSubmitWorkArgsHeaderInt(t *testing.T) {
- input := `["0x0000000000000001", 1, "0xD1GE5700000000000000000000000000"]`
-
- args := new(SubmitWorkArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-func TestSubmitWorkArgsDigestInt(t *testing.T) {
- input := `["0x0000000000000001", "0x1234567890abcdef1234567890abcdef", 1]`
-
- args := new(SubmitWorkArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestBlockHeightFromJsonInvalid(t *testing.T) {
- var num int64
- var msg json.RawMessage = []byte(`}{`)
- str := ExpectDecodeParamError(blockHeightFromJson(msg, &num))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSourceArgsEmpty(t *testing.T) {
- input := `[]`
-
- args := new(SourceArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSigArgs(t *testing.T) {
- input := `["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0"]`
- expected := new(NewSigArgs)
- expected.From = "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"
- expected.Data = "0x0"
-
- args := new(NewSigArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.From != args.From {
- t.Errorf("From should be %v but is %v", expected.From, args.From)
- }
-
- if expected.Data != args.Data {
- t.Errorf("Data should be %v but is %v", expected.Data, args.Data)
- }
-}
-
-func TestSigArgsEmptyData(t *testing.T) {
- input := `["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", ""]`
-
- args := new(NewSigArgs)
- str := ExpectValidationError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSigArgsDataType(t *testing.T) {
- input := `["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", 13]`
-
- args := new(NewSigArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSigArgsEmptyFrom(t *testing.T) {
- input := `["", "0x0"]`
-
- args := new(NewSigArgs)
- str := ExpectValidationError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSigArgsFromType(t *testing.T) {
- input := `[false, "0x0"]`
-
- args := new(NewSigArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestSigArgsEmpty(t *testing.T) {
- input := `[]`
- args := new(NewSigArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDataArgs(t *testing.T) {
- input := `["0x0123"]`
- expected := new(NewDataArgs)
- expected.Data = "0x0123"
-
- args := new(NewDataArgs)
- if err := json.Unmarshal([]byte(input), &args); err != nil {
- t.Error(err)
- }
-
- if expected.Data != args.Data {
- t.Errorf("Data should be %v but is %v", expected.Data, args.Data)
- }
-}
-
-func TestDataArgsEmptyData(t *testing.T) {
- input := `[""]`
-
- args := new(NewDataArgs)
- str := ExpectValidationError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDataArgsDataType(t *testing.T) {
- input := `[13]`
-
- args := new(NewDataArgs)
- str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDataArgsEmpty(t *testing.T) {
- input := `[]`
- args := new(NewDataArgs)
- str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
-
-func TestDataArgsInvalid(t *testing.T) {
- input := `{}`
-
- args := new(NewDataArgs)
- str := ExpectDecodeParamError(json.Unmarshal([]byte(input), args))
- if len(str) > 0 {
- t.Error(str)
- }
-}
diff --git a/rpc/api/db.go b/rpc/api/db.go
deleted file mode 100644
index 0eddc410e..000000000
--- a/rpc/api/db.go
+++ /dev/null
@@ -1,144 +0,0 @@
-// 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 (
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-const (
- DbApiversion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- DbMapping = map[string]dbhandler{
- "db_getString": (*dbApi).GetString,
- "db_putString": (*dbApi).PutString,
- "db_getHex": (*dbApi).GetHex,
- "db_putHex": (*dbApi).PutHex,
- }
-)
-
-// db callback handler
-type dbhandler func(*dbApi, *shared.Request) (interface{}, error)
-
-// db api provider
-type dbApi struct {
- xeth *xeth.XEth
- ethereum *eth.Ethereum
- methods map[string]dbhandler
- codec codec.ApiCoder
-}
-
-// create a new db api instance
-func NewDbApi(xeth *xeth.XEth, ethereum *eth.Ethereum, coder codec.Codec) *dbApi {
- return &dbApi{
- xeth: xeth,
- ethereum: ethereum,
- methods: DbMapping,
- codec: coder.New(nil),
- }
-}
-
-// collection with supported methods
-func (self *dbApi) 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 *dbApi) Execute(req *shared.Request) (interface{}, error) {
- if callback, ok := self.methods[req.Method]; ok {
- return callback(self, req)
- }
-
- return nil, &shared.NotImplementedError{req.Method}
-}
-
-func (self *dbApi) Name() string {
- return shared.DbApiName
-}
-
-func (self *dbApi) ApiVersion() string {
- return DbApiversion
-}
-
-func (self *dbApi) GetString(req *shared.Request) (interface{}, error) {
- args := new(DbArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- if err := args.requirements(); err != nil {
- return nil, err
- }
-
- ret, err := self.xeth.DbGet([]byte(args.Database + args.Key))
- return string(ret), err
-}
-
-func (self *dbApi) PutString(req *shared.Request) (interface{}, error) {
- args := new(DbArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- if err := args.requirements(); err != nil {
- return nil, err
- }
-
- return self.xeth.DbPut([]byte(args.Database+args.Key), args.Value), nil
-}
-
-func (self *dbApi) GetHex(req *shared.Request) (interface{}, error) {
- args := new(DbHexArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- if err := args.requirements(); err != nil {
- return nil, err
- }
-
- if res, err := self.xeth.DbGet([]byte(args.Database + args.Key)); err == nil {
- return newHexData(res), nil
- } else {
- return nil, err
- }
-}
-
-func (self *dbApi) PutHex(req *shared.Request) (interface{}, error) {
- args := new(DbHexArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- if err := args.requirements(); err != nil {
- return nil, err
- }
-
- return self.xeth.DbPut([]byte(args.Database+args.Key), args.Value), nil
-}
diff --git a/rpc/api/db_args.go b/rpc/api/db_args.go
deleted file mode 100644
index d61ea77ee..000000000
--- a/rpc/api/db_args.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// 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 (
- "encoding/json"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type DbArgs struct {
- Database string
- Key string
- Value []byte
-}
-
-func (args *DbArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- var objstr string
- var ok bool
-
- if objstr, ok = obj[0].(string); !ok {
- return shared.NewInvalidTypeError("database", "not a string")
- }
- args.Database = objstr
-
- if objstr, ok = obj[1].(string); !ok {
- return shared.NewInvalidTypeError("key", "not a string")
- }
- args.Key = objstr
-
- if len(obj) > 2 {
- objstr, ok = obj[2].(string)
- if !ok {
- return shared.NewInvalidTypeError("value", "not a string")
- }
-
- args.Value = []byte(objstr)
- }
-
- return nil
-}
-
-func (a *DbArgs) requirements() error {
- if len(a.Database) == 0 {
- return shared.NewValidationError("Database", "cannot be blank")
- }
- if len(a.Key) == 0 {
- return shared.NewValidationError("Key", "cannot be blank")
- }
- return nil
-}
-
-type DbHexArgs struct {
- Database string
- Key string
- Value []byte
-}
-
-func (args *DbHexArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- var objstr string
- var ok bool
-
- if objstr, ok = obj[0].(string); !ok {
- return shared.NewInvalidTypeError("database", "not a string")
- }
- args.Database = objstr
-
- if objstr, ok = obj[1].(string); !ok {
- return shared.NewInvalidTypeError("key", "not a string")
- }
- args.Key = objstr
-
- if len(obj) > 2 {
- objstr, ok = obj[2].(string)
- if !ok {
- return shared.NewInvalidTypeError("value", "not a string")
- }
-
- args.Value = common.FromHex(objstr)
- }
-
- return nil
-}
-
-func (a *DbHexArgs) requirements() error {
- if len(a.Database) == 0 {
- return shared.NewValidationError("Database", "cannot be blank")
- }
- if len(a.Key) == 0 {
- return shared.NewValidationError("Key", "cannot be blank")
- }
- return nil
-}
diff --git a/rpc/api/db_js.go b/rpc/api/db_js.go
deleted file mode 100644
index 899f8abd9..000000000
--- a/rpc/api/db_js.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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
-
-const Db_JS = `
-web3._extend({
- property: 'db',
- methods:
- [
- ],
- properties:
- [
- ]
-});
-`
diff --git a/rpc/api/debug.go b/rpc/api/debug.go
deleted file mode 100644
index a6faa335e..000000000
--- a/rpc/api/debug.go
+++ /dev/null
@@ -1,303 +0,0 @@
-// 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 (
- "fmt"
- "strings"
- "time"
-
- "github.com/ethereum/ethash"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/vm"
- "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"
- "github.com/rcrowley/go-metrics"
-)
-
-const (
- DebugApiVersion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- DebugMapping = map[string]debughandler{
- "debug_dumpBlock": (*debugApi).DumpBlock,
- "debug_getBlockRlp": (*debugApi).GetBlockRlp,
- "debug_printBlock": (*debugApi).PrintBlock,
- "debug_processBlock": (*debugApi).ProcessBlock,
- "debug_seedHash": (*debugApi).SeedHash,
- "debug_setHead": (*debugApi).SetHead,
- "debug_metrics": (*debugApi).Metrics,
- }
-)
-
-// debug callback handler
-type debughandler func(*debugApi, *shared.Request) (interface{}, error)
-
-// admin api provider
-type debugApi struct {
- xeth *xeth.XEth
- ethereum *eth.Ethereum
- methods map[string]debughandler
- codec codec.ApiCoder
-}
-
-// create a new debug api instance
-func NewDebugApi(xeth *xeth.XEth, ethereum *eth.Ethereum, coder codec.Codec) *debugApi {
- return &debugApi{
- xeth: xeth,
- ethereum: ethereum,
- methods: DebugMapping,
- codec: coder.New(nil),
- }
-}
-
-// collection with supported methods
-func (self *debugApi) 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 *debugApi) Execute(req *shared.Request) (interface{}, error) {
- if callback, ok := self.methods[req.Method]; ok {
- return callback(self, req)
- }
-
- return nil, &shared.NotImplementedError{req.Method}
-}
-
-func (self *debugApi) Name() string {
- return shared.DebugApiName
-}
-
-func (self *debugApi) ApiVersion() string {
- return DebugApiVersion
-}
-
-func (self *debugApi) PrintBlock(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)
- return fmt.Sprintf("%s", block), nil
-}
-
-func (self *debugApi) DumpBlock(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, fmt.Errorf("block #%d not found", args.BlockNumber)
- }
-
- stateDb, err := state.New(block.Root(), self.ethereum.ChainDb())
- if err != nil {
- return nil, err
- }
-
- return stateDb.RawDump(), nil
-}
-
-func (self *debugApi) GetBlockRlp(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, fmt.Errorf("block #%d not found", args.BlockNumber)
- }
- encoded, err := rlp.EncodeToBytes(block)
- return fmt.Sprintf("%x", encoded), err
-}
-
-func (self *debugApi) SetHead(req *shared.Request) (interface{}, error) {
- args := new(BlockNumArg)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
- self.ethereum.BlockChain().SetHead(uint64(args.BlockNumber))
-
- return nil, nil
-}
-
-func (self *debugApi) ProcessBlock(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, fmt.Errorf("block #%d not found", args.BlockNumber)
- }
-
- old := vm.Debug
- defer func() { vm.Debug = old }()
- vm.Debug = true
-
- var (
- blockchain = self.ethereum.BlockChain()
- validator = blockchain.Validator()
- processor = blockchain.Processor()
- )
-
- err := core.ValidateHeader(blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false)
- if err != nil {
- return false, err
- }
- statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), self.ethereum.ChainDb())
- if err != nil {
- return false, err
- }
- receipts, _, usedGas, err := processor.Process(block, statedb)
- if err != nil {
- return false, err
- }
- err = validator.ValidateState(block, blockchain.GetBlock(block.ParentHash()), statedb, receipts, usedGas)
- if err != nil {
- return false, err
- }
-
- return true, nil
-}
-
-func (self *debugApi) SeedHash(req *shared.Request) (interface{}, error) {
- args := new(BlockNumArg)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- if hash, err := ethash.GetSeedHash(uint64(args.BlockNumber)); err == nil {
- return fmt.Sprintf("0x%x", hash), nil
- } else {
- return nil, err
- }
-}
-
-func (self *debugApi) Metrics(req *shared.Request) (interface{}, error) {
- args := new(MetricsArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
- // Create a rate formatter
- units := []string{"", "K", "M", "G", "T", "E", "P"}
- round := func(value float64, prec int) string {
- unit := 0
- for value >= 1000 {
- unit, value, prec = unit+1, value/1000, 2
- }
- return fmt.Sprintf(fmt.Sprintf("%%.%df%s", prec, units[unit]), value)
- }
- format := func(total float64, rate float64) string {
- return fmt.Sprintf("%s (%s/s)", round(total, 0), round(rate, 2))
- }
- // Iterate over all the metrics, and just dump for now
- counters := make(map[string]interface{})
- metrics.DefaultRegistry.Each(func(name string, metric interface{}) {
- // Create or retrieve the counter hierarchy for this metric
- root, parts := counters, strings.Split(name, "/")
- for _, part := range parts[:len(parts)-1] {
- if _, ok := root[part]; !ok {
- root[part] = make(map[string]interface{})
- }
- root = root[part].(map[string]interface{})
- }
- name = parts[len(parts)-1]
-
- // Fill the counter with the metric details, formatting if requested
- if args.Raw {
- switch metric := metric.(type) {
- case metrics.Meter:
- root[name] = map[string]interface{}{
- "AvgRate01Min": metric.Rate1(),
- "AvgRate05Min": metric.Rate5(),
- "AvgRate15Min": metric.Rate15(),
- "MeanRate": metric.RateMean(),
- "Overall": float64(metric.Count()),
- }
-
- case metrics.Timer:
- root[name] = map[string]interface{}{
- "AvgRate01Min": metric.Rate1(),
- "AvgRate05Min": metric.Rate5(),
- "AvgRate15Min": metric.Rate15(),
- "MeanRate": metric.RateMean(),
- "Overall": float64(metric.Count()),
- "Percentiles": map[string]interface{}{
- "5": metric.Percentile(0.05),
- "20": metric.Percentile(0.2),
- "50": metric.Percentile(0.5),
- "80": metric.Percentile(0.8),
- "95": metric.Percentile(0.95),
- },
- }
-
- default:
- root[name] = "Unknown metric type"
- }
- } else {
- switch metric := metric.(type) {
- case metrics.Meter:
- root[name] = map[string]interface{}{
- "Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
- "Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
- "Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
- "Overall": format(float64(metric.Count()), metric.RateMean()),
- }
-
- case metrics.Timer:
- root[name] = map[string]interface{}{
- "Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
- "Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
- "Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
- "Overall": format(float64(metric.Count()), metric.RateMean()),
- "Maximum": time.Duration(metric.Max()).String(),
- "Minimum": time.Duration(metric.Min()).String(),
- "Percentiles": map[string]interface{}{
- "5": time.Duration(metric.Percentile(0.05)).String(),
- "20": time.Duration(metric.Percentile(0.2)).String(),
- "50": time.Duration(metric.Percentile(0.5)).String(),
- "80": time.Duration(metric.Percentile(0.8)).String(),
- "95": time.Duration(metric.Percentile(0.95)).String(),
- },
- }
-
- default:
- root[name] = "Unknown metric type"
- }
- }
- })
- return counters, nil
-}
diff --git a/rpc/api/debug_args.go b/rpc/api/debug_args.go
deleted file mode 100644
index 041ad6b6a..000000000
--- a/rpc/api/debug_args.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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 (
- "encoding/json"
- "fmt"
- "math/big"
- "reflect"
-
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type WaitForBlockArgs struct {
- MinHeight int
- Timeout int // in seconds
-}
-
-func (args *WaitForBlockArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) > 2 {
- return fmt.Errorf("waitForArgs needs 0, 1, 2 arguments")
- }
-
- // default values when not provided
- args.MinHeight = -1
- args.Timeout = -1
-
- if len(obj) >= 1 {
- var minHeight *big.Int
- if minHeight, err = numString(obj[0]); err != nil {
- return err
- }
- args.MinHeight = int(minHeight.Int64())
- }
-
- if len(obj) >= 2 {
- timeout, err := numString(obj[1])
- if err != nil {
- return err
- }
- args.Timeout = int(timeout.Int64())
- }
-
- return nil
-}
-
-type MetricsArgs struct {
- Raw bool
-}
-
-func (args *MetricsArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
- if len(obj) > 1 {
- return fmt.Errorf("metricsArgs needs 0, 1 arguments")
- }
- // default values when not provided
- if len(obj) >= 1 && obj[0] != nil {
- if value, ok := obj[0].(bool); !ok {
- return fmt.Errorf("invalid argument %v", reflect.TypeOf(obj[0]))
- } else {
- args.Raw = value
- }
- }
- return nil
-}
diff --git a/rpc/api/debug_js.go b/rpc/api/debug_js.go
deleted file mode 100644
index 03755ada0..000000000
--- a/rpc/api/debug_js.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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
-
-const Debug_JS = `
-web3._extend({
- property: 'debug',
- methods:
- [
- new web3._extend.Method({
- name: 'printBlock',
- call: 'debug_printBlock',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'getBlockRlp',
- call: 'debug_getBlockRlp',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'setHead',
- call: 'debug_setHead',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'processBlock',
- call: 'debug_processBlock',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'seedHash',
- call: 'debug_seedHash',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'dumpBlock',
- call: 'debug_dumpBlock',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'metrics',
- call: 'debug_metrics',
- params: 1,
- inputFormatter: [null]
- })
- ],
- properties:
- [
- ]
-});
-`
diff --git a/rpc/api/eth.go b/rpc/api/eth.go
deleted file mode 100644
index db7a643d8..000000000
--- a/rpc/api/eth.go
+++ /dev/null
@@ -1,721 +0,0 @@
-// 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 &ethApi{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
-}
diff --git a/rpc/api/eth_args.go b/rpc/api/eth_args.go
deleted file mode 100644
index ed3d761f1..000000000
--- a/rpc/api/eth_args.go
+++ /dev/null
@@ -1,1104 +0,0 @@
-// 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 (
- "encoding/json"
- "fmt"
- "math/big"
- "strconv"
- "strings"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-const (
- defaultLogLimit = 100
- defaultLogOffset = 0
-)
-
-type GetBalanceArgs struct {
- Address string
- BlockNumber int64
-}
-
-func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- addstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("address", "not a string")
- }
- args.Address = addstr
-
- if len(obj) > 1 {
- if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
- return err
- }
- } else {
- args.BlockNumber = -1
- }
-
- return nil
-}
-
-type GetStorageArgs struct {
- Address string
- BlockNumber int64
-}
-
-func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- addstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("address", "not a string")
- }
- args.Address = addstr
-
- if len(obj) > 1 {
- if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
- return err
- }
- } else {
- args.BlockNumber = -1
- }
-
- return nil
-}
-
-type GetStorageAtArgs struct {
- Address string
- BlockNumber int64
- Key string
-}
-
-func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- addstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("address", "not a string")
- }
- args.Address = addstr
-
- keystr, ok := obj[1].(string)
- if !ok {
- return shared.NewInvalidTypeError("key", "not a string")
- }
- args.Key = keystr
-
- if len(obj) > 2 {
- if err := blockHeight(obj[2], &args.BlockNumber); err != nil {
- return err
- }
- } else {
- args.BlockNumber = -1
- }
-
- return nil
-}
-
-type GetTxCountArgs struct {
- Address string
- BlockNumber int64
-}
-
-func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- addstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("address", "not a string")
- }
- args.Address = addstr
-
- if len(obj) > 1 {
- if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
- return err
- }
- } else {
- args.BlockNumber = -1
- }
-
- return nil
-}
-
-type SubmitHashRateArgs struct {
- Id string
- Rate uint64
-}
-
-func (args *SubmitHashRateArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- arg0, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("hash", "not a string")
- }
- args.Id = arg0
-
- arg1, ok := obj[1].(string)
- if !ok {
- return shared.NewInvalidTypeError("rate", "not a string")
- }
-
- args.Rate = common.String2Big(arg1).Uint64()
-
- return nil
-}
-
-type HashArgs struct {
- Hash string
-}
-
-func (args *HashArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- arg0, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("hash", "not a string")
- }
- args.Hash = arg0
-
- return nil
-}
-
-type BlockNumArg struct {
- BlockNumber int64
-}
-
-func (args *BlockNumArg) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
- return err
- }
-
- return nil
-}
-
-type GetDataArgs struct {
- Address string
- BlockNumber int64
-}
-
-func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- addstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("address", "not a string")
- }
- args.Address = addstr
-
- if len(obj) > 1 {
- if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
- return err
- }
- } else {
- args.BlockNumber = -1
- }
-
- return nil
-}
-
-type NewDataArgs struct {
- Data string
-}
-
-func (args *NewDataArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
-
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- // Check for sufficient params
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- data, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("data", "not a string")
- }
- args.Data = data
-
- if len(args.Data) == 0 {
- return shared.NewValidationError("data", "is required")
- }
-
- return nil
-}
-
-type NewSigArgs struct {
- From string
- Data string
-}
-
-func (args *NewSigArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
-
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- // Check for sufficient params
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- from, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("from", "not a string")
- }
- args.From = from
-
- if len(args.From) == 0 {
- return shared.NewValidationError("from", "is required")
- }
-
- data, ok := obj[1].(string)
- if !ok {
- return shared.NewInvalidTypeError("data", "not a string")
- }
- args.Data = data
-
- if len(args.Data) == 0 {
- return shared.NewValidationError("data", "is required")
- }
-
- return nil
-}
-
-type NewTxArgs struct {
- From string
- To string
- Nonce *big.Int
- Value *big.Int
- Gas *big.Int
- GasPrice *big.Int
- Data string
-
- BlockNumber int64
-}
-
-func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []json.RawMessage
- var ext struct {
- From string
- To string
- Nonce interface{}
- Value interface{}
- Gas interface{}
- GasPrice interface{}
- Data string
- }
-
- // Decode byte slice to array of RawMessages
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- // Check for sufficient params
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- // Decode 0th RawMessage to temporary struct
- if err := json.Unmarshal(obj[0], &ext); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(ext.From) == 0 {
- return shared.NewValidationError("from", "is required")
- }
-
- args.From = ext.From
- args.To = ext.To
- args.Data = ext.Data
-
- var num *big.Int
- if ext.Nonce != nil {
- num, err = numString(ext.Nonce)
- if err != nil {
- return err
- }
- }
- args.Nonce = num
-
- if ext.Value == nil {
- num = big.NewInt(0)
- } else {
- num, err = numString(ext.Value)
- if err != nil {
- return err
- }
- }
- args.Value = num
-
- num = nil
- if ext.Gas != nil {
- if num, err = numString(ext.Gas); err != nil {
- return err
- }
- }
- args.Gas = num
-
- num = nil
- if ext.GasPrice != nil {
- if num, err = numString(ext.GasPrice); err != nil {
- return err
- }
- }
- args.GasPrice = num
-
- // Check for optional BlockNumber param
- if len(obj) > 1 {
- if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
- return err
- }
- } else {
- args.BlockNumber = -1
- }
-
- return nil
-}
-
-type SourceArgs struct {
- Source string
-}
-
-func (args *SourceArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- arg0, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("source code", "not a string")
- }
- args.Source = arg0
-
- return nil
-}
-
-type CallArgs struct {
- From string
- To string
- Value *big.Int
- Gas *big.Int
- GasPrice *big.Int
- Data string
-
- BlockNumber int64
-}
-
-func (args *CallArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []json.RawMessage
- var ext struct {
- From string
- To string
- Value interface{}
- Gas interface{}
- GasPrice interface{}
- Data string
- }
-
- // Decode byte slice to array of RawMessages
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- // Check for sufficient params
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- // Decode 0th RawMessage to temporary struct
- if err := json.Unmarshal(obj[0], &ext); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- args.From = ext.From
- args.To = ext.To
-
- var num *big.Int
- if ext.Value == nil {
- num = big.NewInt(0)
- } else {
- if num, err = numString(ext.Value); err != nil {
- return err
- }
- }
- args.Value = num
-
- if ext.Gas != nil {
- if num, err = numString(ext.Gas); err != nil {
- return err
- }
- } else {
- num = nil
- }
- args.Gas = num
-
- if ext.GasPrice != nil {
- if num, err = numString(ext.GasPrice); err != nil {
- return err
- }
- } else {
- num = nil
- }
- args.GasPrice = num
-
- args.Data = ext.Data
-
- // Check for optional BlockNumber param
- if len(obj) > 1 {
- if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
- return err
- }
- } else {
- args.BlockNumber = -1
- }
-
- return nil
-}
-
-type HashIndexArgs struct {
- Hash string
- Index int64
-}
-
-func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- arg0, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("hash", "not a string")
- }
- args.Hash = arg0
-
- arg1, ok := obj[1].(string)
- if !ok {
- return shared.NewInvalidTypeError("index", "not a string")
- }
- args.Index = common.Big(arg1).Int64()
-
- return nil
-}
-
-type BlockNumIndexArgs struct {
- BlockNumber int64
- Index int64
-}
-
-func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
- return err
- }
-
- var arg1 *big.Int
- if arg1, err = numString(obj[1]); err != nil {
- return err
- }
- args.Index = arg1.Int64()
-
- return nil
-}
-
-type GetBlockByHashArgs struct {
- BlockHash string
- IncludeTxs bool
-}
-
-func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
-
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- argstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("blockHash", "not a string")
- }
- args.BlockHash = argstr
-
- args.IncludeTxs = obj[1].(bool)
-
- if inclTx, ok := obj[1].(bool); ok {
- args.IncludeTxs = inclTx
- return nil
- }
-
- return shared.NewInvalidTypeError("includeTxs", "not a bool")
-}
-
-type GetBlockByNumberArgs struct {
- BlockNumber int64
- IncludeTxs bool
-}
-
-func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
- }
-
- if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
- return err
- }
-
- if inclTx, ok := obj[1].(bool); ok {
- args.IncludeTxs = inclTx
- return nil
- }
-
- return shared.NewInvalidTypeError("includeTxs", "not a bool")
-}
-
-type BlockFilterArgs struct {
- Earliest int64
- Latest int64
- Address []string
- Topics [][]string
- Skip int
- Max int
-}
-
-func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []struct {
- FromBlock interface{} `json:"fromBlock"`
- ToBlock interface{} `json:"toBlock"`
- Limit interface{} `json:"limit"`
- Offset interface{} `json:"offset"`
- Address interface{} `json:"address"`
- Topics interface{} `json:"topics"`
- }
-
- if err = json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- // args.Earliest, err = toNumber(obj[0].ToBlock)
- // if err != nil {
- // return shared.NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
- // }
- // args.Latest, err = toNumber(obj[0].FromBlock)
- // if err != nil {
- // return shared.NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
-
- var num int64
- var numBig *big.Int
-
- // if blank then latest
- if obj[0].FromBlock == nil {
- num = -1
- } else {
- if err := blockHeight(obj[0].FromBlock, &num); err != nil {
- return err
- }
- }
- // if -2 or other "silly" number, use latest
- if num < 0 {
- args.Earliest = -1 //latest block
- } else {
- args.Earliest = num
- }
-
- // if blank than latest
- if obj[0].ToBlock == nil {
- num = -1
- } else {
- if err := blockHeight(obj[0].ToBlock, &num); err != nil {
- return err
- }
- }
-
- if num == -2 {
- return fmt.Errorf("\"pending\" is unsupported")
- } else if num < -2 {
- return fmt.Errorf("Invalid to block number")
- }
-
- args.Latest = num
-
- if obj[0].Limit == nil {
- numBig = big.NewInt(defaultLogLimit)
- } else {
- if numBig, err = numString(obj[0].Limit); err != nil {
- return err
- }
- }
- args.Max = int(numBig.Int64())
-
- if obj[0].Offset == nil {
- numBig = big.NewInt(defaultLogOffset)
- } else {
- if numBig, err = numString(obj[0].Offset); err != nil {
- return err
- }
- }
- args.Skip = int(numBig.Int64())
-
- if obj[0].Address != nil {
- marg, ok := obj[0].Address.([]interface{})
- if ok {
- v := make([]string, len(marg))
- for i, arg := range marg {
- argstr, ok := arg.(string)
- if !ok {
- return shared.NewInvalidTypeError(fmt.Sprintf("address[%d]", i), "is not a string")
- }
- v[i] = argstr
- }
- args.Address = v
- } else {
- argstr, ok := obj[0].Address.(string)
- if ok {
- v := make([]string, 1)
- v[0] = argstr
- args.Address = v
- } else {
- return shared.NewInvalidTypeError("address", "is not a string or array")
- }
- }
- }
-
- if obj[0].Topics != nil {
- other, ok := obj[0].Topics.([]interface{})
- if ok {
- topicdbl := make([][]string, len(other))
- for i, iv := range other {
- if argstr, ok := iv.(string); ok {
- // Found a string, push into first element of array
- topicsgl := make([]string, 1)
- topicsgl[0] = argstr
- topicdbl[i] = topicsgl
- } else if argarray, ok := iv.([]interface{}); ok {
- // Found an array of other
- topicdbl[i] = make([]string, len(argarray))
- for j, jv := range argarray {
- if v, ok := jv.(string); ok {
- topicdbl[i][j] = v
- } else if jv == nil {
- topicdbl[i][j] = ""
- } else {
- return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", i, j), "is not a string")
- }
- }
- } else if iv == nil {
- topicdbl[i] = []string{""}
- } else {
- return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d]", i), "not a string or array")
- }
- }
- args.Topics = topicdbl
- return nil
- } else {
- return shared.NewInvalidTypeError("topic", "is not a string or array")
- }
- }
-
- return nil
-}
-
-type FilterIdArgs struct {
- Id int
-}
-
-func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- var num *big.Int
- if num, err = numString(obj[0]); err != nil {
- return err
- }
- args.Id = int(num.Int64())
-
- return nil
-}
-
-type LogRes struct {
- Address *hexdata `json:"address"`
- Topics []*hexdata `json:"topics"`
- Data *hexdata `json:"data"`
- BlockNumber *hexnum `json:"blockNumber"`
- LogIndex *hexnum `json:"logIndex"`
- BlockHash *hexdata `json:"blockHash"`
- TransactionHash *hexdata `json:"transactionHash"`
- TransactionIndex *hexnum `json:"transactionIndex"`
-}
-
-func NewLogRes(log *vm.Log) LogRes {
- var l LogRes
- l.Topics = make([]*hexdata, len(log.Topics))
- for j, topic := range log.Topics {
- l.Topics[j] = newHexData(topic)
- }
- l.Address = newHexData(log.Address)
- l.Data = newHexData(log.Data)
- l.BlockNumber = newHexNum(log.BlockNumber)
- l.LogIndex = newHexNum(log.Index)
- l.TransactionHash = newHexData(log.TxHash)
- l.TransactionIndex = newHexNum(log.TxIndex)
- l.BlockHash = newHexData(log.BlockHash)
-
- return l
-}
-
-func NewLogsRes(logs vm.Logs) (ls []LogRes) {
- ls = make([]LogRes, len(logs))
-
- for i, log := range logs {
- ls[i] = NewLogRes(log)
- }
-
- return
-}
-
-func NewHashesRes(hs []common.Hash) []string {
- hashes := make([]string, len(hs))
-
- for i, hash := range hs {
- hashes[i] = hash.Hex()
- }
-
- return hashes
-}
-
-type SubmitWorkArgs struct {
- Nonce uint64
- Header string
- Digest string
-}
-
-func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err = json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 3 {
- return shared.NewInsufficientParamsError(len(obj), 3)
- }
-
- var objstr string
- var ok bool
- if objstr, ok = obj[0].(string); !ok {
- return shared.NewInvalidTypeError("nonce", "not a string")
- }
-
- args.Nonce = common.String2Big(objstr).Uint64()
- if objstr, ok = obj[1].(string); !ok {
- return shared.NewInvalidTypeError("header", "not a string")
- }
-
- args.Header = objstr
-
- if objstr, ok = obj[2].(string); !ok {
- return shared.NewInvalidTypeError("digest", "not a string")
- }
-
- args.Digest = objstr
-
- return nil
-}
-
-type tx struct {
- tx *types.Transaction
-
- To string `json:"to"`
- From string `json:"from"`
- Nonce string `json:"nonce"`
- Value string `json:"value"`
- Data string `json:"data"`
- GasLimit string `json:"gas"`
- GasPrice string `json:"gasPrice"`
- Hash string `json:"hash"`
-}
-
-func newTx(t *types.Transaction) *tx {
- from, _ := t.From()
- var to string
- if t := t.To(); t != nil {
- to = t.Hex()
- }
-
- return &tx{
- tx: t,
- To: to,
- From: from.Hex(),
- Value: t.Value().String(),
- Nonce: strconv.Itoa(int(t.Nonce())),
- Data: "0x" + common.Bytes2Hex(t.Data()),
- GasLimit: t.Gas().String(),
- GasPrice: t.GasPrice().String(),
- Hash: t.Hash().Hex(),
- }
-}
-
-type ResendArgs struct {
- Tx *tx
- GasPrice string
- GasLimit string
-}
-
-func (tx *tx) UnmarshalJSON(b []byte) (err error) {
- var fields map[string]interface{}
- if err := json.Unmarshal(b, &fields); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- var (
- nonce uint64
- to common.Address
- amount = new(big.Int).Set(common.Big0)
- gasLimit = new(big.Int).Set(common.Big0)
- gasPrice = new(big.Int).Set(common.Big0)
- data []byte
- contractCreation = true
- )
-
- if val, found := fields["Hash"]; found {
- if hashVal, ok := val.(string); ok {
- tx.Hash = hashVal
- }
- }
-
- if val, found := fields["To"]; found {
- if strVal, ok := val.(string); ok && len(strVal) > 0 {
- tx.To = strVal
- to = common.HexToAddress(strVal)
- contractCreation = false
- }
- }
-
- if val, found := fields["From"]; found {
- if strVal, ok := val.(string); ok {
- tx.From = strVal
- }
- }
-
- if val, found := fields["Nonce"]; found {
- if strVal, ok := val.(string); ok {
- tx.Nonce = strVal
- if nonce, err = strconv.ParseUint(strVal, 10, 64); err != nil {
- return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.Nonce - %v", err))
- }
- }
- } else {
- return shared.NewDecodeParamError("tx.Nonce not found")
- }
-
- var parseOk bool
- if val, found := fields["Value"]; found {
- if strVal, ok := val.(string); ok {
- tx.Value = strVal
- if _, parseOk = amount.SetString(strVal, 0); !parseOk {
- return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.Amount - %v", err))
- }
- }
- }
-
- if val, found := fields["Data"]; found {
- if strVal, ok := val.(string); ok {
- tx.Data = strVal
- if strings.HasPrefix(strVal, "0x") {
- data = common.Hex2Bytes(strVal[2:])
- } else {
- data = common.Hex2Bytes(strVal)
- }
- }
- }
-
- if val, found := fields["GasLimit"]; found {
- if strVal, ok := val.(string); ok {
- tx.GasLimit = strVal
- if _, parseOk = gasLimit.SetString(strVal, 0); !parseOk {
- return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.GasLimit - %v", err))
- }
- }
- }
-
- if val, found := fields["GasPrice"]; found {
- if strVal, ok := val.(string); ok {
- tx.GasPrice = strVal
- if _, parseOk = gasPrice.SetString(strVal, 0); !parseOk {
- return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.GasPrice - %v", err))
- }
- }
- }
-
- if contractCreation {
- tx.tx = types.NewContractCreation(nonce, amount, gasLimit, gasPrice, data)
- } else {
- tx.tx = types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
- }
-
- return nil
-}
-
-func (args *ResendArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err = json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- data, err := json.Marshal(obj[0])
- if err != nil {
- return shared.NewDecodeParamError("Unable to parse transaction object")
- }
-
- trans := new(tx)
- err = json.Unmarshal(data, trans)
- if err != nil {
- return shared.NewDecodeParamError("Unable to parse transaction object")
- }
-
- if trans == nil || trans.tx == nil {
- return shared.NewDecodeParamError("Unable to parse transaction object")
- }
-
- gasLimit, gasPrice := trans.GasLimit, trans.GasPrice
-
- if len(obj) > 1 && obj[1] != nil {
- if gp, ok := obj[1].(string); ok {
- gasPrice = gp
- } else {
- return shared.NewInvalidTypeError("gasPrice", "not a string")
- }
- }
- if len(obj) > 2 && obj[2] != nil {
- if gl, ok := obj[2].(string); ok {
- gasLimit = gl
- } else {
- return shared.NewInvalidTypeError("gasLimit", "not a string")
- }
- }
-
- args.Tx = trans
- args.GasPrice = gasPrice
- args.GasLimit = gasLimit
-
- return nil
-}
diff --git a/rpc/api/eth_js.go b/rpc/api/eth_js.go
deleted file mode 100644
index dfc104ad8..000000000
--- a/rpc/api/eth_js.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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
-
-// JS api provided by web3.js
-// eth_sign not standard
-
-const Eth_JS = `
-web3._extend({
- property: 'eth',
- methods:
- [
- new web3._extend.Method({
- name: 'sign',
- call: 'eth_sign',
- params: 2,
- inputFormatter: [web3._extend.utils.toAddress, null]
- }),
- new web3._extend.Method({
- name: 'resend',
- call: 'eth_resend',
- params: 3,
- inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
- }),
- new web3._extend.Method({
- name: 'getNatSpec',
- call: 'eth_getNatSpec',
- params: 1,
- inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
- }),
- new web3._extend.Method({
- name: 'signTransaction',
- call: 'eth_signTransaction',
- params: 1,
- inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
- }),
- new web3._extend.Method({
- name: 'submitTransaction',
- call: 'eth_submitTransaction',
- params: 1,
- inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
- })
- ],
- properties:
- [
- new web3._extend.Property({
- name: 'pendingTransactions',
- getter: 'eth_pendingTransactions'
- })
- ]
-});
-`
diff --git a/rpc/api/mergedapi.go b/rpc/api/mergedapi.go
deleted file mode 100644
index 92e1e2bb7..000000000
--- a/rpc/api/mergedapi.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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 (
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-const (
- MergedApiVersion = "1.0"
-)
-
-// combines multiple API's
-type MergedApi struct {
- apis map[string]string
- methods map[string]shared.EthereumApi
-}
-
-// create new merged api instance
-func newMergedApi(apis ...shared.EthereumApi) *MergedApi {
- mergedApi := new(MergedApi)
- mergedApi.apis = make(map[string]string, len(apis))
- mergedApi.methods = make(map[string]shared.EthereumApi)
-
- for _, api := range apis {
- if api != nil {
- mergedApi.apis[api.Name()] = api.ApiVersion()
- for _, method := range api.Methods() {
- mergedApi.methods[method] = api
- }
- }
- }
- return mergedApi
-}
-
-// Supported RPC methods
-func (self *MergedApi) Methods() []string {
- all := make([]string, len(self.methods))
- for method, _ := range self.methods {
- all = append(all, method)
- }
- return all
-}
-
-// Call the correct API's Execute method for the given request
-func (self *MergedApi) Execute(req *shared.Request) (interface{}, error) {
- glog.V(logger.Detail).Infof("%s %s", req.Method, req.Params)
-
- if res, _ := self.handle(req); res != nil {
- return res, nil
- }
- if api, found := self.methods[req.Method]; found {
- return api.Execute(req)
- }
- return nil, shared.NewNotImplementedError(req.Method)
-}
-
-func (self *MergedApi) Name() string {
- return shared.MergedApiName
-}
-
-func (self *MergedApi) ApiVersion() string {
- return MergedApiVersion
-}
-
-func (self *MergedApi) handle(req *shared.Request) (interface{}, error) {
- if req.Method == "modules" { // provided API's
- return self.apis, nil
- }
-
- return nil, nil
-}
diff --git a/rpc/api/miner.go b/rpc/api/miner.go
deleted file mode 100644
index e07855dd2..000000000
--- a/rpc/api/miner.go
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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 (
- "github.com/ethereum/ethash"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-const (
- MinerApiVersion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- MinerMapping = map[string]minerhandler{
- "miner_hashrate": (*minerApi).Hashrate,
- "miner_makeDAG": (*minerApi).MakeDAG,
- "miner_setExtra": (*minerApi).SetExtra,
- "miner_setGasPrice": (*minerApi).SetGasPrice,
- "miner_setEtherbase": (*minerApi).SetEtherbase,
- "miner_startAutoDAG": (*minerApi).StartAutoDAG,
- "miner_start": (*minerApi).StartMiner,
- "miner_stopAutoDAG": (*minerApi).StopAutoDAG,
- "miner_stop": (*minerApi).StopMiner,
- }
-)
-
-// miner callback handler
-type minerhandler func(*minerApi, *shared.Request) (interface{}, error)
-
-// miner api provider
-type minerApi struct {
- ethereum *eth.Ethereum
- methods map[string]minerhandler
- codec codec.ApiCoder
-}
-
-// create a new miner api instance
-func NewMinerApi(ethereum *eth.Ethereum, coder codec.Codec) *minerApi {
- return &minerApi{
- ethereum: ethereum,
- methods: MinerMapping,
- codec: coder.New(nil),
- }
-}
-
-// Execute given request
-func (self *minerApi) Execute(req *shared.Request) (interface{}, error) {
- if callback, ok := self.methods[req.Method]; ok {
- return callback(self, req)
- }
-
- return nil, &shared.NotImplementedError{req.Method}
-}
-
-// collection with supported methods
-func (self *minerApi) Methods() []string {
- methods := make([]string, len(self.methods))
- i := 0
- for k := range self.methods {
- methods[i] = k
- i++
- }
- return methods
-}
-
-func (self *minerApi) Name() string {
- return shared.MinerApiName
-}
-
-func (self *minerApi) ApiVersion() string {
- return MinerApiVersion
-}
-
-func (self *minerApi) StartMiner(req *shared.Request) (interface{}, error) {
- args := new(StartMinerArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
- if args.Threads == -1 { // (not specified by user, use default)
- args.Threads = self.ethereum.MinerThreads
- }
-
- self.ethereum.StartAutoDAG()
- err := self.ethereum.StartMining(args.Threads, "")
- if err == nil {
- return true, nil
- }
-
- return false, err
-}
-
-func (self *minerApi) StopMiner(req *shared.Request) (interface{}, error) {
- self.ethereum.StopMining()
- return true, nil
-}
-
-func (self *minerApi) Hashrate(req *shared.Request) (interface{}, error) {
- return self.ethereum.Miner().HashRate(), nil
-}
-
-func (self *minerApi) SetExtra(req *shared.Request) (interface{}, error) {
- args := new(SetExtraArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- if err := self.ethereum.Miner().SetExtra([]byte(args.Data)); err != nil {
- return false, err
- }
-
- return true, nil
-}
-
-func (self *minerApi) SetGasPrice(req *shared.Request) (interface{}, error) {
- args := new(GasPriceArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return false, err
- }
-
- self.ethereum.Miner().SetGasPrice(common.String2Big(args.Price))
- return true, nil
-}
-
-func (self *minerApi) SetEtherbase(req *shared.Request) (interface{}, error) {
- args := new(SetEtherbaseArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return false, err
- }
- self.ethereum.SetEtherbase(args.Etherbase)
- return nil, nil
-}
-
-func (self *minerApi) StartAutoDAG(req *shared.Request) (interface{}, error) {
- self.ethereum.StartAutoDAG()
- return true, nil
-}
-
-func (self *minerApi) StopAutoDAG(req *shared.Request) (interface{}, error) {
- self.ethereum.StopAutoDAG()
- return true, nil
-}
-
-func (self *minerApi) MakeDAG(req *shared.Request) (interface{}, error) {
- args := new(MakeDAGArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- if args.BlockNumber < 0 {
- return false, shared.NewValidationError("BlockNumber", "BlockNumber must be positive")
- }
-
- err := ethash.MakeDAG(uint64(args.BlockNumber), "")
- if err == nil {
- return true, nil
- }
- return false, err
-}
diff --git a/rpc/api/miner_args.go b/rpc/api/miner_args.go
deleted file mode 100644
index 5ceb244fe..000000000
--- a/rpc/api/miner_args.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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 (
- "encoding/json"
-
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type StartMinerArgs struct {
- Threads int
-}
-
-func (args *StartMinerArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) == 0 || obj[0] == nil {
- args.Threads = -1
- return nil
- }
-
- var num *big.Int
- if num, err = numString(obj[0]); err != nil {
- return err
- }
- args.Threads = int(num.Int64())
- return nil
-}
-
-type SetExtraArgs struct {
- Data string
-}
-
-func (args *SetExtraArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- extrastr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("Price", "not a string")
- }
- args.Data = extrastr
-
- return nil
-}
-
-type GasPriceArgs struct {
- Price string
-}
-
-func (args *GasPriceArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- if pricestr, ok := obj[0].(string); ok {
- args.Price = pricestr
- return nil
- }
-
- return shared.NewInvalidTypeError("Price", "not a string")
-}
-
-type SetEtherbaseArgs struct {
- Etherbase common.Address
-}
-
-func (args *SetEtherbaseArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- if addr, ok := obj[0].(string); ok {
- args.Etherbase = common.HexToAddress(addr)
- if (args.Etherbase == common.Address{}) {
- return shared.NewInvalidTypeError("Etherbase", "not a valid address")
- }
- return nil
- }
-
- return shared.NewInvalidTypeError("Etherbase", "not a string")
-}
-
-type MakeDAGArgs struct {
- BlockNumber int64
-}
-
-func (args *MakeDAGArgs) UnmarshalJSON(b []byte) (err error) {
- args.BlockNumber = -1
- var obj []interface{}
-
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
- return err
- }
-
- return nil
-}
diff --git a/rpc/api/miner_js.go b/rpc/api/miner_js.go
deleted file mode 100644
index 0998a9f41..000000000
--- a/rpc/api/miner_js.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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
-
-const Miner_JS = `
-web3._extend({
- property: 'miner',
- methods:
- [
- new web3._extend.Method({
- name: 'start',
- call: 'miner_start',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'stop',
- call: 'miner_stop',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'setEtherbase',
- call: 'miner_setEtherbase',
- params: 1,
- inputFormatter: [web3._extend.formatters.formatInputInt],
- outputFormatter: web3._extend.formatters.formatOutputBool
- }),
- new web3._extend.Method({
- name: 'setExtra',
- call: 'miner_setExtra',
- params: 1,
- inputFormatter: [null]
- }),
- new web3._extend.Method({
- name: 'setGasPrice',
- call: 'miner_setGasPrice',
- params: 1,
- inputFormatter: [web3._extend.utils.fromDecial]
- }),
- new web3._extend.Method({
- name: 'startAutoDAG',
- call: 'miner_startAutoDAG',
- params: 0,
- inputFormatter: []
- }),
- new web3._extend.Method({
- name: 'stopAutoDAG',
- call: 'miner_stopAutoDAG',
- params: 0,
- inputFormatter: []
- }),
- new web3._extend.Method({
- name: 'makeDAG',
- call: 'miner_makeDAG',
- params: 1,
- inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter]
- })
- ],
- properties:
- [
- new web3._extend.Property({
- name: 'hashrate',
- getter: 'miner_hashrate',
- outputFormatter: web3._extend.utils.toDecimal
- })
- ]
-});
-`
diff --git a/rpc/api/net.go b/rpc/api/net.go
deleted file mode 100644
index 9c6369615..000000000
--- a/rpc/api/net.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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 (
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-const (
- NetApiVersion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- netMapping = map[string]nethandler{
- "net_peerCount": (*netApi).PeerCount,
- "net_listening": (*netApi).IsListening,
- "net_version": (*netApi).Version,
- }
-)
-
-// net callback handler
-type nethandler func(*netApi, *shared.Request) (interface{}, error)
-
-// net api provider
-type netApi struct {
- xeth *xeth.XEth
- ethereum *eth.Ethereum
- methods map[string]nethandler
- codec codec.ApiCoder
-}
-
-// create a new net api instance
-func NewNetApi(xeth *xeth.XEth, eth *eth.Ethereum, coder codec.Codec) *netApi {
- return &netApi{
- xeth: xeth,
- ethereum: eth,
- methods: netMapping,
- codec: coder.New(nil),
- }
-}
-
-// collection with supported methods
-func (self *netApi) 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 *netApi) 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 *netApi) Name() string {
- return shared.NetApiName
-}
-
-func (self *netApi) ApiVersion() string {
- return NetApiVersion
-}
-
-// Number of connected peers
-func (self *netApi) PeerCount(req *shared.Request) (interface{}, error) {
- return newHexNum(self.xeth.PeerCount()), nil
-}
-
-func (self *netApi) IsListening(req *shared.Request) (interface{}, error) {
- return self.xeth.IsListening(), nil
-}
-
-func (self *netApi) Version(req *shared.Request) (interface{}, error) {
- return self.xeth.NetworkVersion(), nil
-}
diff --git a/rpc/api/net_js.go b/rpc/api/net_js.go
deleted file mode 100644
index 2ee1f0041..000000000
--- a/rpc/api/net_js.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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
-
-const Net_JS = `
-web3._extend({
- property: 'net',
- methods:
- [
- new web3._extend.Method({
- name: 'addPeer',
- call: 'net_addPeer',
- params: 1,
- inputFormatter: [null]
- })
- ],
- properties:
- [
- new web3._extend.Property({
- name: 'version',
- getter: 'net_version'
- })
- ]
-});
-`
diff --git a/rpc/api/parsing.go b/rpc/api/parsing.go
deleted file mode 100644
index 7667616ff..000000000
--- a/rpc/api/parsing.go
+++ /dev/null
@@ -1,522 +0,0 @@
-// 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/binary"
- "encoding/hex"
- "encoding/json"
- "math/big"
- "strings"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type hexdata struct {
- data []byte
- isNil bool
-}
-
-func (d *hexdata) String() string {
- return "0x" + common.Bytes2Hex(d.data)
-}
-
-func (d *hexdata) MarshalJSON() ([]byte, error) {
- if d.isNil {
- return json.Marshal(nil)
- }
- return json.Marshal(d.String())
-}
-
-func newHexData(input interface{}) *hexdata {
- d := new(hexdata)
-
- if input == nil {
- d.isNil = true
- return d
- }
- switch input := input.(type) {
- case []byte:
- d.data = input
- case common.Hash:
- d.data = input.Bytes()
- case *common.Hash:
- if input == nil {
- d.isNil = true
- } else {
- d.data = input.Bytes()
- }
- case common.Address:
- d.data = input.Bytes()
- case *common.Address:
- if input == nil {
- d.isNil = true
- } else {
- d.data = input.Bytes()
- }
- case types.Bloom:
- d.data = input.Bytes()
- case *types.Bloom:
- if input == nil {
- d.isNil = true
- } else {
- d.data = input.Bytes()
- }
- case *big.Int:
- if input == nil {
- d.isNil = true
- } else {
- d.data = input.Bytes()
- }
- case int64:
- d.data = big.NewInt(input).Bytes()
- case uint64:
- buff := make([]byte, 8)
- binary.BigEndian.PutUint64(buff, input)
- d.data = buff
- case int:
- d.data = big.NewInt(int64(input)).Bytes()
- case uint:
- d.data = big.NewInt(int64(input)).Bytes()
- case int8:
- d.data = big.NewInt(int64(input)).Bytes()
- case uint8:
- d.data = big.NewInt(int64(input)).Bytes()
- case int16:
- d.data = big.NewInt(int64(input)).Bytes()
- case uint16:
- buff := make([]byte, 2)
- binary.BigEndian.PutUint16(buff, input)
- d.data = buff
- case int32:
- d.data = big.NewInt(int64(input)).Bytes()
- case uint32:
- buff := make([]byte, 4)
- binary.BigEndian.PutUint32(buff, input)
- d.data = buff
- case string: // hexstring
- // aaargh ffs TODO: avoid back-and-forth hex encodings where unneeded
- bytes, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
- if err != nil {
- d.isNil = true
- } else {
- d.data = bytes
- }
- default:
- d.isNil = true
- }
-
- return d
-}
-
-type hexnum struct {
- data []byte
- isNil bool
-}
-
-func (d *hexnum) String() string {
- // Get hex string from bytes
- out := common.Bytes2Hex(d.data)
- // Trim leading 0s
- out = strings.TrimLeft(out, "0")
- // Output "0x0" when value is 0
- if len(out) == 0 {
- out = "0"
- }
- return "0x" + out
-}
-
-func (d *hexnum) MarshalJSON() ([]byte, error) {
- if d.isNil {
- return json.Marshal(nil)
- }
- return json.Marshal(d.String())
-}
-
-func newHexNum(input interface{}) *hexnum {
- d := new(hexnum)
-
- d.data = newHexData(input).data
-
- return d
-}
-
-type BlockRes struct {
- fullTx bool
-
- BlockNumber *hexnum `json:"number"`
- BlockHash *hexdata `json:"hash"`
- ParentHash *hexdata `json:"parentHash"`
- Nonce *hexdata `json:"nonce"`
- Sha3Uncles *hexdata `json:"sha3Uncles"`
- LogsBloom *hexdata `json:"logsBloom"`
- TransactionRoot *hexdata `json:"transactionsRoot"`
- StateRoot *hexdata `json:"stateRoot"`
- ReceiptRoot *hexdata `json:"receiptRoot"`
- Miner *hexdata `json:"miner"`
- Difficulty *hexnum `json:"difficulty"`
- TotalDifficulty *hexnum `json:"totalDifficulty"`
- Size *hexnum `json:"size"`
- ExtraData *hexdata `json:"extraData"`
- GasLimit *hexnum `json:"gasLimit"`
- GasUsed *hexnum `json:"gasUsed"`
- UnixTimestamp *hexnum `json:"timestamp"`
- Transactions []*TransactionRes `json:"transactions"`
- Uncles []*UncleRes `json:"uncles"`
-}
-
-func (b *BlockRes) MarshalJSON() ([]byte, error) {
- if b.fullTx {
- var ext struct {
- BlockNumber *hexnum `json:"number"`
- BlockHash *hexdata `json:"hash"`
- ParentHash *hexdata `json:"parentHash"`
- Nonce *hexdata `json:"nonce"`
- Sha3Uncles *hexdata `json:"sha3Uncles"`
- LogsBloom *hexdata `json:"logsBloom"`
- TransactionRoot *hexdata `json:"transactionsRoot"`
- StateRoot *hexdata `json:"stateRoot"`
- ReceiptRoot *hexdata `json:"receiptRoot"`
- Miner *hexdata `json:"miner"`
- Difficulty *hexnum `json:"difficulty"`
- TotalDifficulty *hexnum `json:"totalDifficulty"`
- Size *hexnum `json:"size"`
- ExtraData *hexdata `json:"extraData"`
- GasLimit *hexnum `json:"gasLimit"`
- GasUsed *hexnum `json:"gasUsed"`
- UnixTimestamp *hexnum `json:"timestamp"`
- Transactions []*TransactionRes `json:"transactions"`
- Uncles []*hexdata `json:"uncles"`
- }
-
- ext.BlockNumber = b.BlockNumber
- ext.BlockHash = b.BlockHash
- ext.ParentHash = b.ParentHash
- ext.Nonce = b.Nonce
- ext.Sha3Uncles = b.Sha3Uncles
- ext.LogsBloom = b.LogsBloom
- ext.TransactionRoot = b.TransactionRoot
- ext.StateRoot = b.StateRoot
- ext.ReceiptRoot = b.ReceiptRoot
- ext.Miner = b.Miner
- ext.Difficulty = b.Difficulty
- ext.TotalDifficulty = b.TotalDifficulty
- ext.Size = b.Size
- ext.ExtraData = b.ExtraData
- ext.GasLimit = b.GasLimit
- ext.GasUsed = b.GasUsed
- ext.UnixTimestamp = b.UnixTimestamp
- ext.Transactions = b.Transactions
- ext.Uncles = make([]*hexdata, len(b.Uncles))
- for i, u := range b.Uncles {
- ext.Uncles[i] = u.BlockHash
- }
- return json.Marshal(ext)
- } else {
- var ext struct {
- BlockNumber *hexnum `json:"number"`
- BlockHash *hexdata `json:"hash"`
- ParentHash *hexdata `json:"parentHash"`
- Nonce *hexdata `json:"nonce"`
- Sha3Uncles *hexdata `json:"sha3Uncles"`
- LogsBloom *hexdata `json:"logsBloom"`
- TransactionRoot *hexdata `json:"transactionsRoot"`
- StateRoot *hexdata `json:"stateRoot"`
- ReceiptRoot *hexdata `json:"receiptRoot"`
- Miner *hexdata `json:"miner"`
- Difficulty *hexnum `json:"difficulty"`
- TotalDifficulty *hexnum `json:"totalDifficulty"`
- Size *hexnum `json:"size"`
- ExtraData *hexdata `json:"extraData"`
- GasLimit *hexnum `json:"gasLimit"`
- GasUsed *hexnum `json:"gasUsed"`
- UnixTimestamp *hexnum `json:"timestamp"`
- Transactions []*hexdata `json:"transactions"`
- Uncles []*hexdata `json:"uncles"`
- }
-
- ext.BlockNumber = b.BlockNumber
- ext.BlockHash = b.BlockHash
- ext.ParentHash = b.ParentHash
- ext.Nonce = b.Nonce
- ext.Sha3Uncles = b.Sha3Uncles
- ext.LogsBloom = b.LogsBloom
- ext.TransactionRoot = b.TransactionRoot
- ext.StateRoot = b.StateRoot
- ext.ReceiptRoot = b.ReceiptRoot
- ext.Miner = b.Miner
- ext.Difficulty = b.Difficulty
- ext.TotalDifficulty = b.TotalDifficulty
- ext.Size = b.Size
- ext.ExtraData = b.ExtraData
- ext.GasLimit = b.GasLimit
- ext.GasUsed = b.GasUsed
- ext.UnixTimestamp = b.UnixTimestamp
- ext.Transactions = make([]*hexdata, len(b.Transactions))
- for i, tx := range b.Transactions {
- ext.Transactions[i] = tx.Hash
- }
- ext.Uncles = make([]*hexdata, len(b.Uncles))
- for i, u := range b.Uncles {
- ext.Uncles[i] = u.BlockHash
- }
- return json.Marshal(ext)
- }
-}
-
-func NewBlockRes(block *types.Block, td *big.Int, fullTx bool) *BlockRes {
- if block == nil {
- return nil
- }
-
- res := new(BlockRes)
- res.fullTx = fullTx
- res.BlockNumber = newHexNum(block.Number())
- res.BlockHash = newHexData(block.Hash())
- res.ParentHash = newHexData(block.ParentHash())
- res.Nonce = newHexData(block.Nonce())
- res.Sha3Uncles = newHexData(block.UncleHash())
- res.LogsBloom = newHexData(block.Bloom())
- res.TransactionRoot = newHexData(block.TxHash())
- res.StateRoot = newHexData(block.Root())
- res.ReceiptRoot = newHexData(block.ReceiptHash())
- res.Miner = newHexData(block.Coinbase())
- res.Difficulty = newHexNum(block.Difficulty())
- res.TotalDifficulty = newHexNum(td)
- res.Size = newHexNum(block.Size().Int64())
- res.ExtraData = newHexData(block.Extra())
- res.GasLimit = newHexNum(block.GasLimit())
- res.GasUsed = newHexNum(block.GasUsed())
- res.UnixTimestamp = newHexNum(block.Time())
-
- txs := block.Transactions()
- res.Transactions = make([]*TransactionRes, len(txs))
- for i, tx := range txs {
- res.Transactions[i] = NewTransactionRes(tx)
- res.Transactions[i].BlockHash = res.BlockHash
- res.Transactions[i].BlockNumber = res.BlockNumber
- res.Transactions[i].TxIndex = newHexNum(i)
- }
-
- uncles := block.Uncles()
- res.Uncles = make([]*UncleRes, len(uncles))
- for i, uncle := range uncles {
- res.Uncles[i] = NewUncleRes(uncle)
- }
-
- return res
-}
-
-type TransactionRes struct {
- Hash *hexdata `json:"hash"`
- Nonce *hexnum `json:"nonce"`
- BlockHash *hexdata `json:"blockHash"`
- BlockNumber *hexnum `json:"blockNumber"`
- TxIndex *hexnum `json:"transactionIndex"`
- From *hexdata `json:"from"`
- To *hexdata `json:"to"`
- Value *hexnum `json:"value"`
- Gas *hexnum `json:"gas"`
- GasPrice *hexnum `json:"gasPrice"`
- Input *hexdata `json:"input"`
-}
-
-func NewTransactionRes(tx *types.Transaction) *TransactionRes {
- if tx == nil {
- return nil
- }
-
- var v = new(TransactionRes)
- v.Hash = newHexData(tx.Hash())
- v.Nonce = newHexNum(tx.Nonce())
- // v.BlockHash =
- // v.BlockNumber =
- // v.TxIndex =
- from, _ := tx.From()
- v.From = newHexData(from)
- v.To = newHexData(tx.To())
- v.Value = newHexNum(tx.Value())
- v.Gas = newHexNum(tx.Gas())
- v.GasPrice = newHexNum(tx.GasPrice())
- v.Input = newHexData(tx.Data())
- return v
-}
-
-type UncleRes struct {
- BlockNumber *hexnum `json:"number"`
- BlockHash *hexdata `json:"hash"`
- ParentHash *hexdata `json:"parentHash"`
- Nonce *hexdata `json:"nonce"`
- Sha3Uncles *hexdata `json:"sha3Uncles"`
- ReceiptHash *hexdata `json:"receiptHash"`
- LogsBloom *hexdata `json:"logsBloom"`
- TransactionRoot *hexdata `json:"transactionsRoot"`
- StateRoot *hexdata `json:"stateRoot"`
- Miner *hexdata `json:"miner"`
- Difficulty *hexnum `json:"difficulty"`
- ExtraData *hexdata `json:"extraData"`
- GasLimit *hexnum `json:"gasLimit"`
- GasUsed *hexnum `json:"gasUsed"`
- UnixTimestamp *hexnum `json:"timestamp"`
-}
-
-func NewUncleRes(h *types.Header) *UncleRes {
- if h == nil {
- return nil
- }
-
- var v = new(UncleRes)
- v.BlockNumber = newHexNum(h.Number)
- v.BlockHash = newHexData(h.Hash())
- v.ParentHash = newHexData(h.ParentHash)
- v.Sha3Uncles = newHexData(h.UncleHash)
- v.Nonce = newHexData(h.Nonce[:])
- v.LogsBloom = newHexData(h.Bloom)
- v.TransactionRoot = newHexData(h.TxHash)
- v.StateRoot = newHexData(h.Root)
- v.Miner = newHexData(h.Coinbase)
- v.Difficulty = newHexNum(h.Difficulty)
- v.ExtraData = newHexData(h.Extra)
- v.GasLimit = newHexNum(h.GasLimit)
- v.GasUsed = newHexNum(h.GasUsed)
- v.UnixTimestamp = newHexNum(h.Time)
- v.ReceiptHash = newHexData(h.ReceiptHash)
-
- return v
-}
-
-// type FilterLogRes struct {
-// Hash string `json:"hash"`
-// Address string `json:"address"`
-// Data string `json:"data"`
-// BlockNumber string `json:"blockNumber"`
-// TransactionHash string `json:"transactionHash"`
-// BlockHash string `json:"blockHash"`
-// TransactionIndex string `json:"transactionIndex"`
-// LogIndex string `json:"logIndex"`
-// }
-
-// type FilterWhisperRes struct {
-// Hash string `json:"hash"`
-// From string `json:"from"`
-// To string `json:"to"`
-// Expiry string `json:"expiry"`
-// Sent string `json:"sent"`
-// Ttl string `json:"ttl"`
-// Topics string `json:"topics"`
-// Payload string `json:"payload"`
-// WorkProved string `json:"workProved"`
-// }
-
-type ReceiptRes struct {
- TransactionHash *hexdata `json:"transactionHash"`
- TransactionIndex *hexnum `json:"transactionIndex"`
- BlockNumber *hexnum `json:"blockNumber"`
- BlockHash *hexdata `json:"blockHash"`
- CumulativeGasUsed *hexnum `json:"cumulativeGasUsed"`
- GasUsed *hexnum `json:"gasUsed"`
- ContractAddress *hexdata `json:"contractAddress"`
- Logs *[]interface{} `json:"logs"`
-}
-
-func NewReceiptRes(rec *types.Receipt) *ReceiptRes {
- if rec == nil {
- return nil
- }
-
- var v = new(ReceiptRes)
- v.TransactionHash = newHexData(rec.TxHash)
- if rec.GasUsed != nil {
- v.GasUsed = newHexNum(rec.GasUsed.Bytes())
- }
- v.CumulativeGasUsed = newHexNum(rec.CumulativeGasUsed)
-
- // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
- if bytes.Compare(rec.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 {
- v.ContractAddress = newHexData(rec.ContractAddress)
- }
-
- logs := make([]interface{}, len(rec.Logs))
- for i, log := range rec.Logs {
- logs[i] = NewLogRes(log)
- }
- v.Logs = &logs
-
- return v
-}
-
-func numString(raw interface{}) (*big.Int, error) {
- var number *big.Int
- // Parse as integer
- num, ok := raw.(float64)
- if ok {
- number = big.NewInt(int64(num))
- return number, nil
- }
-
- // Parse as string/hexstring
- str, ok := raw.(string)
- if ok {
- number = common.String2Big(str)
- return number, nil
- }
-
- return nil, shared.NewInvalidTypeError("", "not a number or string")
-}
-
-func blockHeight(raw interface{}, number *int64) error {
- // Parse as integer
- num, ok := raw.(float64)
- if ok {
- *number = int64(num)
- return nil
- }
-
- // Parse as string/hexstring
- str, ok := raw.(string)
- if !ok {
- return shared.NewInvalidTypeError("", "not a number or string")
- }
-
- switch str {
- case "earliest":
- *number = 0
- case "latest":
- *number = -1
- case "pending":
- *number = -2
- default:
- if common.HasHexPrefix(str) {
- *number = common.String2Big(str).Int64()
- } else {
- return shared.NewInvalidTypeError("blockNumber", "is not a valid string")
- }
- }
-
- return nil
-}
-
-func blockHeightFromJson(msg json.RawMessage, number *int64) error {
- var raw interface{}
- if err := json.Unmarshal(msg, &raw); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
- return blockHeight(raw, number)
-}
diff --git a/rpc/api/personal.go b/rpc/api/personal.go
deleted file mode 100644
index 4f347c610..000000000
--- a/rpc/api/personal.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// 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 (
- "fmt"
- "time"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-const (
- PersonalApiVersion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- personalMapping = map[string]personalhandler{
- "personal_listAccounts": (*personalApi).ListAccounts,
- "personal_newAccount": (*personalApi).NewAccount,
- "personal_unlockAccount": (*personalApi).UnlockAccount,
- }
-)
-
-// net callback handler
-type personalhandler func(*personalApi, *shared.Request) (interface{}, error)
-
-// net api provider
-type personalApi struct {
- xeth *xeth.XEth
- ethereum *eth.Ethereum
- methods map[string]personalhandler
- codec codec.ApiCoder
-}
-
-// create a new net api instance
-func NewPersonalApi(xeth *xeth.XEth, eth *eth.Ethereum, coder codec.Codec) *personalApi {
- return &personalApi{
- xeth: xeth,
- ethereum: eth,
- methods: personalMapping,
- codec: coder.New(nil),
- }
-}
-
-// collection with supported methods
-func (self *personalApi) 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 *personalApi) 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 *personalApi) Name() string {
- return shared.PersonalApiName
-}
-
-func (self *personalApi) ApiVersion() string {
- return PersonalApiVersion
-}
-
-func (self *personalApi) ListAccounts(req *shared.Request) (interface{}, error) {
- return self.xeth.Accounts(), nil
-}
-
-func (self *personalApi) NewAccount(req *shared.Request) (interface{}, error) {
- args := new(NewAccountArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
- var passwd string
- if args.Passphrase == nil {
- fe := self.xeth.Frontend()
- if fe == nil {
- return false, fmt.Errorf("unable to create account: unable to interact with user")
- }
- var ok bool
- passwd, ok = fe.AskPassword()
- if !ok {
- return false, fmt.Errorf("unable to create account: no password given")
- }
- } else {
- passwd = *args.Passphrase
- }
- am := self.ethereum.AccountManager()
- acc, err := am.NewAccount(passwd)
- return acc.Address.Hex(), err
-}
-
-func (self *personalApi) UnlockAccount(req *shared.Request) (interface{}, error) {
- args := new(UnlockAccountArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, shared.NewDecodeParamError(err.Error())
- }
-
- if args.Passphrase == nil {
- fe := self.xeth.Frontend()
- if fe == nil {
- return false, fmt.Errorf("No password provided")
- }
- return fe.UnlockAccount(common.HexToAddress(args.Address).Bytes()), nil
- }
-
- am := self.ethereum.AccountManager()
- addr := common.HexToAddress(args.Address)
-
- err := am.TimedUnlock(addr, *args.Passphrase, time.Duration(args.Duration)*time.Second)
- return err == nil, err
-}
diff --git a/rpc/api/personal_args.go b/rpc/api/personal_args.go
deleted file mode 100644
index 5d215c71d..000000000
--- a/rpc/api/personal_args.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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 (
- "encoding/json"
-
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type NewAccountArgs struct {
- Passphrase *string
-}
-
-func (args *NewAccountArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) >= 1 && obj[0] != nil {
- if passphrasestr, ok := obj[0].(string); ok {
- args.Passphrase = &passphrasestr
- } else {
- return shared.NewInvalidTypeError("passphrase", "not a string")
- }
- }
-
- return nil
-}
-
-type UnlockAccountArgs struct {
- Address string
- Passphrase *string
- Duration int
-}
-
-func (args *UnlockAccountArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- args.Duration = 0
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- if addrstr, ok := obj[0].(string); ok {
- args.Address = addrstr
- } else {
- return shared.NewInvalidTypeError("address", "not a string")
- }
-
- if len(obj) >= 2 && obj[1] != nil {
- if passphrasestr, ok := obj[1].(string); ok {
- args.Passphrase = &passphrasestr
- } else {
- return shared.NewInvalidTypeError("passphrase", "not a string")
- }
- }
-
- if len(obj) >= 3 && obj[2] != nil {
- if duration, ok := obj[2].(float64); ok {
- args.Duration = int(duration)
- }
- }
-
- return nil
-}
diff --git a/rpc/api/personal_js.go b/rpc/api/personal_js.go
deleted file mode 100644
index 84c669af7..000000000
--- a/rpc/api/personal_js.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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
-
-const Personal_JS = `
-web3._extend({
- property: 'personal',
- methods:
- [
- new web3._extend.Method({
- name: 'newAccount',
- call: 'personal_newAccount',
- params: 1,
- inputFormatter: [null],
- outputFormatter: web3._extend.utils.toAddress
- }),
- new web3._extend.Method({
- name: 'unlockAccount',
- call: 'personal_unlockAccount',
- params: 3,
- inputFormatter: [null, null, null]
- }),
- new web3._extend.Method({
- name: 'lockAccount',
- call: 'personal_lockAccount',
- params: 1
- })
- ],
- properties:
- [
- new web3._extend.Property({
- name: 'listAccounts',
- getter: 'personal_listAccounts'
- })
- ]
-});
-`
diff --git a/rpc/api/shh.go b/rpc/api/shh.go
deleted file mode 100644
index 60e805605..000000000
--- a/rpc/api/shh.go
+++ /dev/null
@@ -1,196 +0,0 @@
-// 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 (
- "math/big"
-
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-const (
- ShhApiVersion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- shhMapping = map[string]shhhandler{
- "shh_version": (*shhApi).Version,
- "shh_post": (*shhApi).Post,
- "shh_hasIdentity": (*shhApi).HasIdentity,
- "shh_newIdentity": (*shhApi).NewIdentity,
- "shh_newFilter": (*shhApi).NewFilter,
- "shh_uninstallFilter": (*shhApi).UninstallFilter,
- "shh_getMessages": (*shhApi).GetMessages,
- "shh_getFilterChanges": (*shhApi).GetFilterChanges,
- }
-)
-
-func newWhisperOfflineError(method string) error {
- return shared.NewNotAvailableError(method, "whisper offline")
-}
-
-// net callback handler
-type shhhandler func(*shhApi, *shared.Request) (interface{}, error)
-
-// shh api provider
-type shhApi struct {
- xeth *xeth.XEth
- ethereum *eth.Ethereum
- methods map[string]shhhandler
- codec codec.ApiCoder
-}
-
-// create a new whisper api instance
-func NewShhApi(xeth *xeth.XEth, eth *eth.Ethereum, coder codec.Codec) *shhApi {
- return &shhApi{
- xeth: xeth,
- ethereum: eth,
- methods: shhMapping,
- codec: coder.New(nil),
- }
-}
-
-// collection with supported methods
-func (self *shhApi) 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 *shhApi) 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 *shhApi) Name() string {
- return shared.ShhApiName
-}
-
-func (self *shhApi) ApiVersion() string {
- return ShhApiVersion
-}
-
-func (self *shhApi) Version(req *shared.Request) (interface{}, error) {
- w := self.xeth.Whisper()
- if w == nil {
- return nil, newWhisperOfflineError(req.Method)
- }
-
- return w.Version(), nil
-}
-
-func (self *shhApi) Post(req *shared.Request) (interface{}, error) {
- w := self.xeth.Whisper()
- if w == nil {
- return nil, newWhisperOfflineError(req.Method)
- }
-
- args := new(WhisperMessageArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- err := w.Post(args.Payload, args.To, args.From, args.Topics, args.Priority, args.Ttl)
- if err != nil {
- return false, err
- }
-
- return true, nil
-}
-
-func (self *shhApi) HasIdentity(req *shared.Request) (interface{}, error) {
- w := self.xeth.Whisper()
- if w == nil {
- return nil, newWhisperOfflineError(req.Method)
- }
-
- args := new(WhisperIdentityArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- return w.HasIdentity(args.Identity), nil
-}
-
-func (self *shhApi) NewIdentity(req *shared.Request) (interface{}, error) {
- w := self.xeth.Whisper()
- if w == nil {
- return nil, newWhisperOfflineError(req.Method)
- }
-
- return w.NewIdentity(), nil
-}
-
-func (self *shhApi) NewFilter(req *shared.Request) (interface{}, error) {
- args := new(WhisperFilterArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- id := self.xeth.NewWhisperFilter(args.To, args.From, args.Topics)
- return newHexNum(big.NewInt(int64(id)).Bytes()), nil
-}
-
-func (self *shhApi) UninstallFilter(req *shared.Request) (interface{}, error) {
- args := new(FilterIdArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
- return self.xeth.UninstallWhisperFilter(args.Id), nil
-}
-
-func (self *shhApi) GetFilterChanges(req *shared.Request) (interface{}, error) {
- w := self.xeth.Whisper()
- if w == nil {
- return nil, newWhisperOfflineError(req.Method)
- }
-
- // Retrieve all the new messages arrived since the last request
- args := new(FilterIdArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- return self.xeth.WhisperMessagesChanged(args.Id), nil
-}
-
-func (self *shhApi) GetMessages(req *shared.Request) (interface{}, error) {
- w := self.xeth.Whisper()
- if w == nil {
- return nil, newWhisperOfflineError(req.Method)
- }
-
- // Retrieve all the cached messages matching a specific, existing filter
- args := new(FilterIdArgs)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- return self.xeth.WhisperMessages(args.Id), nil
-}
diff --git a/rpc/api/shh_args.go b/rpc/api/shh_args.go
deleted file mode 100644
index 468a0b98f..000000000
--- a/rpc/api/shh_args.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// 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 (
- "encoding/json"
- "fmt"
- "math/big"
-
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type WhisperMessageArgs struct {
- Payload string
- To string
- From string
- Topics []string
- Priority uint32
- Ttl uint32
-}
-
-func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []struct {
- Payload string
- To string
- From string
- Topics []string
- Priority interface{}
- Ttl interface{}
- }
-
- if err = json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
- args.Payload = obj[0].Payload
- args.To = obj[0].To
- args.From = obj[0].From
- args.Topics = obj[0].Topics
-
- var num *big.Int
- if num, err = numString(obj[0].Priority); err != nil {
- return err
- }
- args.Priority = uint32(num.Int64())
-
- if num, err = numString(obj[0].Ttl); err != nil {
- return err
- }
- args.Ttl = uint32(num.Int64())
-
- return nil
-}
-
-type WhisperIdentityArgs struct {
- Identity string
-}
-
-func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
-
- argstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("arg0", "not a string")
- }
-
- args.Identity = argstr
-
- return nil
-}
-
-type WhisperFilterArgs struct {
- To string
- From string
- Topics [][]string
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a
-// JSON message blob into a WhisperFilterArgs structure.
-func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
- // Unmarshal the JSON message and sanity check
- var obj []struct {
- To interface{} `json:"to"`
- From interface{} `json:"from"`
- Topics interface{} `json:"topics"`
- }
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
- }
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
- }
- // Retrieve the simple data contents of the filter arguments
- if obj[0].To == nil {
- args.To = ""
- } else {
- argstr, ok := obj[0].To.(string)
- if !ok {
- return shared.NewInvalidTypeError("to", "is not a string")
- }
- args.To = argstr
- }
- if obj[0].From == nil {
- args.From = ""
- } else {
- argstr, ok := obj[0].From.(string)
- if !ok {
- return shared.NewInvalidTypeError("from", "is not a string")
- }
- args.From = argstr
- }
- // Construct the nested topic array
- if obj[0].Topics != nil {
- // Make sure we have an actual topic array
- list, ok := obj[0].Topics.([]interface{})
- if !ok {
- return shared.NewInvalidTypeError("topics", "is not an array")
- }
- // Iterate over each topic and handle nil, string or array
- topics := make([][]string, len(list))
- for idx, field := range list {
- switch value := field.(type) {
- case nil:
- topics[idx] = []string{}
-
- case string:
- topics[idx] = []string{value}
-
- case []interface{}:
- topics[idx] = make([]string, len(value))
- for i, nested := range value {
- switch value := nested.(type) {
- case nil:
- topics[idx][i] = ""
-
- case string:
- topics[idx][i] = value
-
- default:
- return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", idx, i), "is not a string")
- }
- }
- default:
- return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d]", idx), "not a string or array")
- }
- }
- args.Topics = topics
- }
- return nil
-}
diff --git a/rpc/api/shh_js.go b/rpc/api/shh_js.go
deleted file mode 100644
index a92ad1644..000000000
--- a/rpc/api/shh_js.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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
-
-const Shh_JS = `
-web3._extend({
- property: 'shh',
- methods:
- [
-
- ],
- properties:
- [
- new web3._extend.Property({
- name: 'version',
- getter: 'shh_version'
- })
- ]
-});
-`
diff --git a/rpc/api/txpool.go b/rpc/api/txpool.go
deleted file mode 100644
index 27e40cae5..000000000
--- a/rpc/api/txpool.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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 (
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-const (
- TxPoolApiVersion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- txpoolMapping = map[string]txpoolhandler{
- "txpool_status": (*txPoolApi).Status,
- }
-)
-
-// net callback handler
-type txpoolhandler func(*txPoolApi, *shared.Request) (interface{}, error)
-
-// txpool api provider
-type txPoolApi struct {
- xeth *xeth.XEth
- ethereum *eth.Ethereum
- methods map[string]txpoolhandler
- codec codec.ApiCoder
-}
-
-// create a new txpool api instance
-func NewTxPoolApi(xeth *xeth.XEth, eth *eth.Ethereum, coder codec.Codec) *txPoolApi {
- return &txPoolApi{
- xeth: xeth,
- ethereum: eth,
- methods: txpoolMapping,
- codec: coder.New(nil),
- }
-}
-
-// collection with supported methods
-func (self *txPoolApi) 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 *txPoolApi) 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 *txPoolApi) Name() string {
- return shared.TxPoolApiName
-}
-
-func (self *txPoolApi) ApiVersion() string {
- return TxPoolApiVersion
-}
-
-func (self *txPoolApi) Status(req *shared.Request) (interface{}, error) {
- pending, queue := self.ethereum.TxPool().Stats()
- return map[string]int{
- "pending": pending,
- "queued": queue,
- }, nil
-}
diff --git a/rpc/api/txpool_js.go b/rpc/api/txpool_js.go
deleted file mode 100644
index b6c29871a..000000000
--- a/rpc/api/txpool_js.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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
-
-const TxPool_JS = `
-web3._extend({
- property: 'txpool',
- methods:
- [
- ],
- properties:
- [
- new web3._extend.Property({
- name: 'status',
- getter: 'txpool_status'
- })
- ]
-});
-`
diff --git a/rpc/api/utils.go b/rpc/api/utils.go
deleted file mode 100644
index 794b6abee..000000000
--- a/rpc/api/utils.go
+++ /dev/null
@@ -1,226 +0,0 @@
-// 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 (
- "strings"
-
- "fmt"
-
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-var (
- // Mapping between the different methods each api supports
- AutoCompletion = map[string][]string{
- "admin": []string{
- "addPeer",
- "datadir",
- "enableUserAgent",
- "exportChain",
- "getContractInfo",
- "httpGet",
- "importChain",
- "nodeInfo",
- "peers",
- "register",
- "registerUrl",
- "saveInfo",
- "setGlobalRegistrar",
- "setHashReg",
- "setUrlHint",
- "setSolc",
- "sleep",
- "sleepBlocks",
- "startNatSpec",
- "startRPC",
- "stopNatSpec",
- "stopRPC",
- "verbosity",
- },
- "db": []string{
- "getString",
- "putString",
- "getHex",
- "putHex",
- },
- "debug": []string{
- "dumpBlock",
- "getBlockRlp",
- "metrics",
- "printBlock",
- "processBlock",
- "seedHash",
- "setHead",
- },
- "eth": []string{
- "accounts",
- "blockNumber",
- "call",
- "contract",
- "coinbase",
- "compile.lll",
- "compile.serpent",
- "compile.solidity",
- "contract",
- "defaultAccount",
- "defaultBlock",
- "estimateGas",
- "filter",
- "getBalance",
- "getBlock",
- "getBlockTransactionCount",
- "getBlockUncleCount",
- "getCode",
- "getNatSpec",
- "getCompilers",
- "gasPrice",
- "getStorageAt",
- "getTransaction",
- "getTransactionCount",
- "getTransactionFromBlock",
- "getTransactionReceipt",
- "getUncle",
- "hashrate",
- "mining",
- "namereg",
- "pendingTransactions",
- "resend",
- "sendRawTransaction",
- "sendTransaction",
- "sign",
- "syncing",
- },
- "miner": []string{
- "hashrate",
- "makeDAG",
- "setEtherbase",
- "setExtra",
- "setGasPrice",
- "startAutoDAG",
- "start",
- "stopAutoDAG",
- "stop",
- },
- "net": []string{
- "peerCount",
- "listening",
- },
- "personal": []string{
- "listAccounts",
- "newAccount",
- "unlockAccount",
- },
- "shh": []string{
- "post",
- "newIdentity",
- "hasIdentity",
- "newGroup",
- "addToGroup",
- "filter",
- },
- "txpool": []string{
- "status",
- },
- "web3": []string{
- "sha3",
- "version",
- "fromWei",
- "toWei",
- "toHex",
- "toAscii",
- "fromAscii",
- "toBigNumber",
- "isAddress",
- },
- }
-)
-
-// Parse a comma separated API string to individual api's
-func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, stack *node.Node) ([]shared.EthereumApi, error) {
- if len(strings.TrimSpace(apistr)) == 0 {
- return nil, fmt.Errorf("Empty apistr provided")
- }
-
- names := strings.Split(apistr, ",")
- apis := make([]shared.EthereumApi, len(names))
-
- var eth *eth.Ethereum
- if stack != nil {
- if err := stack.Service(&eth); err != nil {
- return nil, err
- }
- }
- for i, name := range names {
- switch strings.ToLower(strings.TrimSpace(name)) {
- case shared.AdminApiName:
- apis[i] = NewAdminApi(xeth, stack, codec)
- case shared.DebugApiName:
- apis[i] = NewDebugApi(xeth, eth, codec)
- case shared.DbApiName:
- apis[i] = NewDbApi(xeth, eth, codec)
- case shared.EthApiName:
- apis[i] = NewEthApi(xeth, eth, codec)
- case shared.MinerApiName:
- apis[i] = NewMinerApi(eth, codec)
- case shared.NetApiName:
- apis[i] = NewNetApi(xeth, eth, codec)
- case shared.ShhApiName:
- apis[i] = NewShhApi(xeth, eth, codec)
- case shared.TxPoolApiName:
- apis[i] = NewTxPoolApi(xeth, eth, codec)
- case shared.PersonalApiName:
- apis[i] = NewPersonalApi(xeth, eth, codec)
- case shared.Web3ApiName:
- apis[i] = NewWeb3Api(xeth, codec)
- case "rpc": // gives information about the RPC interface
- continue
- default:
- return nil, fmt.Errorf("Unknown API '%s'", name)
- }
- }
- return apis, nil
-}
-
-func Javascript(name string) string {
- switch strings.ToLower(strings.TrimSpace(name)) {
- case shared.AdminApiName:
- return Admin_JS
- case shared.DebugApiName:
- return Debug_JS
- case shared.DbApiName:
- return Db_JS
- case shared.EthApiName:
- return Eth_JS
- case shared.MinerApiName:
- return Miner_JS
- case shared.NetApiName:
- return Net_JS
- case shared.ShhApiName:
- return Shh_JS
- case shared.TxPoolApiName:
- return TxPool_JS
- case shared.PersonalApiName:
- return Personal_JS
- }
-
- return ""
-}
diff --git a/rpc/api/web3.go b/rpc/api/web3.go
deleted file mode 100644
index e2d8543d3..000000000
--- a/rpc/api/web3.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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 (
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/xeth"
-)
-
-const (
- Web3ApiVersion = "1.0"
-)
-
-var (
- // mapping between methods and handlers
- Web3Mapping = map[string]web3handler{
- "web3_sha3": (*web3Api).Sha3,
- "web3_clientVersion": (*web3Api).ClientVersion,
- }
-)
-
-// web3 callback handler
-type web3handler func(*web3Api, *shared.Request) (interface{}, error)
-
-// web3 api provider
-type web3Api struct {
- xeth *xeth.XEth
- methods map[string]web3handler
- codec codec.ApiCoder
-}
-
-// create a new web3 api instance
-func NewWeb3Api(xeth *xeth.XEth, coder codec.Codec) *web3Api {
- return &web3Api{
- xeth: xeth,
- methods: Web3Mapping,
- codec: coder.New(nil),
- }
-}
-
-// collection with supported methods
-func (self *web3Api) 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 *web3Api) Execute(req *shared.Request) (interface{}, error) {
- if callback, ok := self.methods[req.Method]; ok {
- return callback(self, req)
- }
-
- return nil, &shared.NotImplementedError{req.Method}
-}
-
-func (self *web3Api) Name() string {
- return shared.Web3ApiName
-}
-
-func (self *web3Api) ApiVersion() string {
- return Web3ApiVersion
-}
-
-// Calculates the sha3 over req.Params.Data
-func (self *web3Api) Sha3(req *shared.Request) (interface{}, error) {
- args := new(Sha3Args)
- if err := self.codec.Decode(req.Params, &args); err != nil {
- return nil, err
- }
-
- return common.ToHex(crypto.Sha3(common.FromHex(args.Data))), nil
-}
-
-// returns the xeth client vrsion
-func (self *web3Api) ClientVersion(req *shared.Request) (interface{}, error) {
- return self.xeth.ClientVersion(), nil
-}
diff --git a/rpc/codec/codec.go b/rpc/codec/codec.go
deleted file mode 100644
index 786080b44..000000000
--- a/rpc/codec/codec.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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 codec
-
-import (
- "net"
- "strconv"
-
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type Codec int
-
-// (de)serialization support for rpc interface
-type ApiCoder interface {
- // Parse message to request from underlying stream
- ReadRequest() ([]*shared.Request, bool, error)
- // Parse response message from underlying stream
- ReadResponse() (interface{}, error)
- // Read raw message from underlying stream
- Recv() (interface{}, error)
- // Encode response to encoded form in underlying stream
- WriteResponse(interface{}) error
- // Decode single message from data
- Decode([]byte, interface{}) error
- // Encode msg to encoded form
- Encode(msg interface{}) ([]byte, error)
- // close the underlying stream
- Close()
-}
-
-// supported codecs
-const (
- JSON Codec = iota
- nCodecs
-)
-
-var (
- // collection with supported coders
- coders = make([]func(net.Conn) ApiCoder, nCodecs)
-)
-
-// create a new coder instance
-func (c Codec) New(conn net.Conn) ApiCoder {
- switch c {
- case JSON:
- return NewJsonCoder(conn)
- }
-
- panic("codec: request for codec #" + strconv.Itoa(int(c)) + " is unavailable")
-}
diff --git a/rpc/codec/json.go b/rpc/codec/json.go
deleted file mode 100644
index cfc449143..000000000
--- a/rpc/codec/json.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// 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 codec
-
-import (
- "encoding/json"
- "fmt"
- "net"
- "time"
- "strings"
-
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-const (
- READ_TIMEOUT = 60 // in seconds
- MAX_REQUEST_SIZE = 1024 * 1024
- MAX_RESPONSE_SIZE = 1024 * 1024
-)
-
-// Json serialization support
-type JsonCodec struct {
- c net.Conn
- d *json.Decoder
-}
-
-// Create new JSON coder instance
-func NewJsonCoder(conn net.Conn) ApiCoder {
- return &JsonCodec{
- c: conn,
- d: json.NewDecoder(conn),
- }
-}
-
-// Read incoming request and parse it to RPC request
-func (self *JsonCodec) ReadRequest() (requests []*shared.Request, isBatch bool, err error) {
- deadline := time.Now().Add(READ_TIMEOUT * time.Second)
- if err := self.c.SetDeadline(deadline); err != nil {
- return nil, false, err
- }
-
- var incoming json.RawMessage
- err = self.d.Decode(&incoming)
- if err == nil {
- isBatch = incoming[0] == '['
- if isBatch {
- requests = make([]*shared.Request, 0)
- err = json.Unmarshal(incoming, &requests)
- } else {
- requests = make([]*shared.Request, 1)
- var singleRequest shared.Request
- if err = json.Unmarshal(incoming, &singleRequest); err == nil {
- requests[0] = &singleRequest
- }
- }
- return
- }
-
- self.c.Close()
- return nil, false, err
-}
-
-func (self *JsonCodec) Recv() (interface{}, error) {
- var msg json.RawMessage
- err := self.d.Decode(&msg)
- if err != nil {
- self.c.Close()
- return nil, err
- }
-
- return msg, err
-}
-
-func (self *JsonCodec) ReadResponse() (interface{}, error) {
- in, err := self.Recv()
- if err != nil {
- return nil, err
- }
-
- if msg, ok := in.(json.RawMessage); ok {
- var req *shared.Request
- if err = json.Unmarshal(msg, &req); err == nil && strings.HasPrefix(req.Method, "agent_") {
- return req, nil
- }
-
- var failure *shared.ErrorResponse
- if err = json.Unmarshal(msg, &failure); err == nil && failure.Error != nil {
- return failure, fmt.Errorf(failure.Error.Message)
- }
-
- var success *shared.SuccessResponse
- if err = json.Unmarshal(msg, &success); err == nil {
- return success, nil
- }
- }
-
- return in, err
-}
-
-// Decode data
-func (self *JsonCodec) Decode(data []byte, msg interface{}) error {
- return json.Unmarshal(data, msg)
-}
-
-// Encode message
-func (self *JsonCodec) Encode(msg interface{}) ([]byte, error) {
- return json.Marshal(msg)
-}
-
-// Parse JSON data from conn to obj
-func (self *JsonCodec) WriteResponse(res interface{}) error {
- data, err := json.Marshal(res)
- if err != nil {
- self.c.Close()
- return err
- }
-
- bytesWritten := 0
-
- for bytesWritten < len(data) {
- n, err := self.c.Write(data[bytesWritten:])
- if err != nil {
- self.c.Close()
- return err
- }
- bytesWritten += n
- }
-
- return nil
-}
-
-// Close decoder and encoder
-func (self *JsonCodec) Close() {
- self.c.Close()
-}
diff --git a/rpc/codec/json_test.go b/rpc/codec/json_test.go
deleted file mode 100644
index 01ef77e57..000000000
--- a/rpc/codec/json_test.go
+++ /dev/null
@@ -1,157 +0,0 @@
-// 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 codec
-
-import (
- "bytes"
- "io"
- "net"
- "testing"
- "time"
-)
-
-type jsonTestConn struct {
- buffer *bytes.Buffer
-}
-
-func newJsonTestConn(data []byte) *jsonTestConn {
- return &jsonTestConn{
- buffer: bytes.NewBuffer(data),
- }
-}
-
-func (self *jsonTestConn) Read(p []byte) (n int, err error) {
- return self.buffer.Read(p)
-}
-
-func (self *jsonTestConn) Write(p []byte) (n int, err error) {
- return self.buffer.Write(p)
-}
-
-func (self *jsonTestConn) Close() error {
- // not implemented
- return nil
-}
-
-func (self *jsonTestConn) LocalAddr() net.Addr {
- // not implemented
- return nil
-}
-
-func (self *jsonTestConn) RemoteAddr() net.Addr {
- // not implemented
- return nil
-}
-
-func (self *jsonTestConn) SetDeadline(t time.Time) error {
- return nil
-}
-
-func (self *jsonTestConn) SetReadDeadline(t time.Time) error {
- return nil
-}
-
-func (self *jsonTestConn) SetWriteDeadline(t time.Time) error {
- return nil
-}
-
-func TestJsonDecoderWithValidRequest(t *testing.T) {
- reqdata := []byte(`{"jsonrpc":"2.0","method":"modules","params":[],"id":64}`)
- decoder := newJsonTestConn(reqdata)
-
- jsonDecoder := NewJsonCoder(decoder)
- requests, batch, err := jsonDecoder.ReadRequest()
-
- if err != nil {
- t.Errorf("Read valid request failed - %v", err)
- }
-
- if len(requests) != 1 {
- t.Errorf("Expected to get a single request but got %d", len(requests))
- }
-
- if batch {
- t.Errorf("Got batch indication while expecting single request")
- }
-
- if requests[0].Id != float64(64) {
- t.Errorf("Expected req.Id == 64 but got %v", requests[0].Id)
- }
-
- if requests[0].Method != "modules" {
- t.Errorf("Expected req.Method == 'modules' got '%s'", requests[0].Method)
- }
-}
-
-func TestJsonDecoderWithValidBatchRequest(t *testing.T) {
- reqdata := []byte(`[{"jsonrpc":"2.0","method":"modules","params":[],"id":64},
- {"jsonrpc":"2.0","method":"modules","params":[],"id":64}]`)
- decoder := newJsonTestConn(reqdata)
-
- jsonDecoder := NewJsonCoder(decoder)
- requests, batch, err := jsonDecoder.ReadRequest()
-
- if err != nil {
- t.Errorf("Read valid batch request failed - %v", err)
- }
-
- if len(requests) != 2 {
- t.Errorf("Expected to get two requests but got %d", len(requests))
- }
-
- if !batch {
- t.Errorf("Got no batch indication while expecting batch request")
- }
-
- for i := 0; i < len(requests); i++ {
- if requests[i].Id != float64(64) {
- t.Errorf("Expected req.Id == 64 but got %v", requests[i].Id)
- }
-
- if requests[i].Method != "modules" {
- t.Errorf("Expected req.Method == 'modules' got '%s'", requests[i].Method)
- }
- }
-}
-
-func TestJsonDecoderWithInvalidIncompleteMessage(t *testing.T) {
- reqdata := []byte(`{"jsonrpc":"2.0","method":"modules","pa`)
- decoder := newJsonTestConn(reqdata)
-
- jsonDecoder := NewJsonCoder(decoder)
- requests, batch, err := jsonDecoder.ReadRequest()
-
- if err != io.ErrUnexpectedEOF {
- t.Errorf("Expected to read an incomplete request err but got %v", err)
- }
-
- // remaining message
- decoder.Write([]byte(`rams":[],"id:64"}`))
- requests, batch, err = jsonDecoder.ReadRequest()
-
- if err == nil {
- t.Errorf("Expected an error but got nil")
- }
-
- if len(requests) != 0 {
- t.Errorf("Expected to get no requests but got %d", len(requests))
- }
-
- if batch {
- t.Errorf("Got batch indication while expecting non batch")
- }
-}
diff --git a/rpc/comms/comms.go b/rpc/comms/comms.go
deleted file mode 100644
index 61fba5722..000000000
--- a/rpc/comms/comms.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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 comms
-
-import (
- "io"
- "net"
-
- "fmt"
- "strings"
-
- "strconv"
-
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-const (
- maxHttpSizeReqLength = 1024 * 1024 // 1MB
-)
-
-var (
- // List with all API's which are offered over the in proc interface by default
- DefaultInProcApis = shared.AllApis
-
- // List with all API's which are offered over the IPC interface by default
- DefaultIpcApis = shared.AllApis
-
- // List with API's which are offered over thr HTTP/RPC interface by default
- DefaultHttpRpcApis = strings.Join([]string{
- shared.DbApiName, shared.EthApiName, shared.NetApiName, shared.Web3ApiName,
- }, ",")
-)
-
-type EthereumClient interface {
- // Close underlying connection
- Close()
- // Send request
- Send(interface{}) error
- // Receive response
- Recv() (interface{}, error)
- // List with modules this client supports
- SupportedModules() (map[string]string, error)
-}
-
-func handle(id int, conn net.Conn, api shared.EthereumApi, c codec.Codec) {
- codec := c.New(conn)
-
- defer func() {
- if r := recover(); r != nil {
- glog.Errorf("panic: %v\n", r)
- }
- codec.Close()
- }()
-
- for {
- requests, isBatch, err := codec.ReadRequest()
- if err == io.EOF {
- return
- } else if err != nil {
- glog.V(logger.Debug).Infof("Closed IPC Conn %06d recv err - %v\n", id, err)
- return
- }
-
- if isBatch {
- responses := make([]*interface{}, len(requests))
- responseCount := 0
- for _, req := range requests {
- res, err := api.Execute(req)
- if req.Id != nil {
- rpcResponse := shared.NewRpcResponse(req.Id, req.Jsonrpc, res, err)
- responses[responseCount] = rpcResponse
- responseCount += 1
- }
- }
-
- err = codec.WriteResponse(responses[:responseCount])
- if err != nil {
- glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err)
- return
- }
- } else {
- var rpcResponse interface{}
- res, err := api.Execute(requests[0])
-
- rpcResponse = shared.NewRpcResponse(requests[0].Id, requests[0].Jsonrpc, res, err)
- err = codec.WriteResponse(rpcResponse)
- if err != nil {
- glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err)
- return
- }
- }
- }
-}
-
-// Endpoint must be in the form of:
-// ${protocol}:${path}
-// e.g. ipc:/tmp/geth.ipc
-// rpc:localhost:8545
-func ClientFromEndpoint(endpoint string, c codec.Codec) (EthereumClient, error) {
- if strings.HasPrefix(endpoint, "ipc:") {
- cfg := IpcConfig{
- Endpoint: endpoint[4:],
- }
- return NewIpcClient(cfg, codec.JSON)
- }
-
- if strings.HasPrefix(endpoint, "rpc:") {
- parts := strings.Split(endpoint, ":")
- addr := "http://localhost"
- port := uint(8545)
- if len(parts) >= 3 {
- addr = parts[1] + ":" + parts[2]
- }
-
- if len(parts) >= 4 {
- p, err := strconv.Atoi(parts[3])
-
- if err != nil {
- return nil, err
- }
- port = uint(p)
- }
-
- cfg := HttpConfig{
- ListenAddress: addr,
- ListenPort: port,
- }
-
- return NewHttpClient(cfg, codec.JSON), nil
- }
-
- return nil, fmt.Errorf("Invalid endpoint")
-}
diff --git a/rpc/comms/http.go b/rpc/comms/http.go
deleted file mode 100644
index f4a930d0e..000000000
--- a/rpc/comms/http.go
+++ /dev/null
@@ -1,345 +0,0 @@
-// 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 comms
-
-import (
- "encoding/json"
- "fmt"
- "net"
- "net/http"
- "strings"
- "sync"
- "time"
-
- "bytes"
- "io"
- "io/ioutil"
-
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/rs/cors"
-)
-
-const (
- serverIdleTimeout = 10 * time.Second // idle keep-alive connections
- serverReadTimeout = 15 * time.Second // per-request read timeout
- serverWriteTimeout = 15 * time.Second // per-request read timeout
-)
-
-var (
- httpServerMu sync.Mutex
- httpServer *stopServer
-)
-
-type HttpConfig struct {
- ListenAddress string
- ListenPort uint
- CorsDomain string
-}
-
-// stopServer augments http.Server with idle connection tracking.
-// Idle keep-alive connections are shut down when Close is called.
-type stopServer struct {
- *http.Server
- l net.Listener
- // connection tracking state
- mu sync.Mutex
- shutdown bool // true when Stop has returned
- idle map[net.Conn]struct{}
-}
-
-type handler struct {
- codec codec.Codec
- api shared.EthereumApi
-}
-
-// StartHTTP starts listening for RPC requests sent via HTTP.
-func StartHttp(cfg HttpConfig, codec codec.Codec, api shared.EthereumApi) error {
- httpServerMu.Lock()
- defer httpServerMu.Unlock()
-
- addr := fmt.Sprintf("%s:%d", cfg.ListenAddress, cfg.ListenPort)
- if httpServer != nil {
- if addr != httpServer.Addr {
- return fmt.Errorf("RPC service already running on %s ", httpServer.Addr)
- }
- return nil // RPC service already running on given host/port
- }
- // Set up the request handler, wrapping it with CORS headers if configured.
- handler := http.Handler(&handler{codec, api})
- if len(cfg.CorsDomain) > 0 {
- opts := cors.Options{
- AllowedMethods: []string{"POST"},
- AllowedOrigins: strings.Split(cfg.CorsDomain, " "),
- }
- handler = cors.New(opts).Handler(handler)
- }
- // Start the server.
- s, err := listenHTTP(addr, handler)
- if err != nil {
- glog.V(logger.Error).Infof("Can't listen on %s:%d: %v", cfg.ListenAddress, cfg.ListenPort, err)
- return err
- }
- httpServer = s
- return nil
-}
-
-func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- w.Header().Set("Content-Type", "application/json")
-
- // Limit request size to resist DoS
- if req.ContentLength > maxHttpSizeReqLength {
- err := fmt.Errorf("Request too large")
- response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err)
- sendJSON(w, &response)
- return
- }
-
- defer req.Body.Close()
- payload, err := ioutil.ReadAll(req.Body)
- if err != nil {
- err := fmt.Errorf("Could not read request body")
- response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err)
- sendJSON(w, &response)
- return
- }
-
- c := h.codec.New(nil)
- var rpcReq shared.Request
- if err = c.Decode(payload, &rpcReq); err == nil {
- reply, err := h.api.Execute(&rpcReq)
- res := shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
- sendJSON(w, &res)
- return
- }
-
- var reqBatch []shared.Request
- if err = c.Decode(payload, &reqBatch); err == nil {
- resBatch := make([]*interface{}, len(reqBatch))
- resCount := 0
- for i, rpcReq := range reqBatch {
- reply, err := h.api.Execute(&rpcReq)
- if rpcReq.Id != nil { // this leaves nil entries in the response batch for later removal
- resBatch[i] = shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
- resCount += 1
- }
- }
- // make response omitting nil entries
- sendJSON(w, resBatch[:resCount])
- return
- }
-
- // invalid request
- err = fmt.Errorf("Could not decode request")
- res := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32600, err)
- sendJSON(w, res)
-}
-
-func sendJSON(w io.Writer, v interface{}) {
- if glog.V(logger.Detail) {
- if payload, err := json.MarshalIndent(v, "", "\t"); err == nil {
- glog.Infof("Sending payload: %s", payload)
- }
- }
- if err := json.NewEncoder(w).Encode(v); err != nil {
- glog.V(logger.Error).Infoln("Error sending JSON:", err)
- }
-}
-
-// Stop closes all active HTTP connections and shuts down the server.
-func StopHttp() {
- httpServerMu.Lock()
- defer httpServerMu.Unlock()
- if httpServer != nil {
- httpServer.Close()
- httpServer = nil
- }
-}
-
-func listenHTTP(addr string, h http.Handler) (*stopServer, error) {
- l, err := net.Listen("tcp", addr)
- if err != nil {
- return nil, err
- }
- s := &stopServer{l: l, idle: make(map[net.Conn]struct{})}
- s.Server = &http.Server{
- Addr: addr,
- Handler: h,
- ReadTimeout: serverReadTimeout,
- WriteTimeout: serverWriteTimeout,
- ConnState: s.connState,
- }
- go s.Serve(l)
- return s, nil
-}
-
-func (s *stopServer) connState(c net.Conn, state http.ConnState) {
- s.mu.Lock()
- defer s.mu.Unlock()
- // Close c immediately if we're past shutdown.
- if s.shutdown {
- if state != http.StateClosed {
- c.Close()
- }
- return
- }
- if state == http.StateIdle {
- s.idle[c] = struct{}{}
- } else {
- delete(s.idle, c)
- }
-}
-
-func (s *stopServer) Close() {
- s.mu.Lock()
- defer s.mu.Unlock()
- // Shut down the acceptor. No new connections can be created.
- s.l.Close()
- // Drop all idle connections. Non-idle connections will be
- // closed by connState as soon as they become idle.
- s.shutdown = true
- for c := range s.idle {
- glog.V(logger.Detail).Infof("closing idle connection %v", c.RemoteAddr())
- c.Close()
- delete(s.idle, c)
- }
-}
-
-type httpClient struct {
- address string
- port uint
- codec codec.ApiCoder
- lastRes interface{}
- lastErr error
-}
-
-// Create a new in process client
-func NewHttpClient(cfg HttpConfig, c codec.Codec) *httpClient {
- return &httpClient{
- address: cfg.ListenAddress,
- port: cfg.ListenPort,
- codec: c.New(nil),
- }
-}
-
-func (self *httpClient) Close() {
- // do nothing
-}
-
-func (self *httpClient) Send(req interface{}) error {
- var body []byte
- var err error
-
- self.lastRes = nil
- self.lastErr = nil
-
- if body, err = self.codec.Encode(req); err != nil {
- return err
- }
-
- httpReq, err := http.NewRequest("POST", fmt.Sprintf("%s:%d", self.address, self.port), bytes.NewBuffer(body))
- if err != nil {
- return err
- }
- httpReq.Header.Set("Content-Type", "application/json")
-
- client := http.Client{}
- resp, err := client.Do(httpReq)
- if err != nil {
- return err
- }
-
- defer resp.Body.Close()
-
- if resp.Status == "200 OK" {
- reply, _ := ioutil.ReadAll(resp.Body)
- var rpcSuccessResponse shared.SuccessResponse
- if err = self.codec.Decode(reply, &rpcSuccessResponse); err == nil {
- self.lastRes = &rpcSuccessResponse
- self.lastErr = err
- return nil
- } else {
- var rpcErrorResponse shared.ErrorResponse
- if err = self.codec.Decode(reply, &rpcErrorResponse); err == nil {
- self.lastRes = &rpcErrorResponse
- self.lastErr = err
- return nil
- } else {
- return err
- }
- }
- }
-
- return fmt.Errorf("Not implemented")
-}
-
-func (self *httpClient) Recv() (interface{}, error) {
- return self.lastRes, self.lastErr
-}
-
-func (self *httpClient) SupportedModules() (map[string]string, error) {
- var body []byte
- var err error
-
- payload := shared.Request{
- Id: 1,
- Jsonrpc: "2.0",
- Method: "modules",
- }
-
- if body, err = self.codec.Encode(payload); err != nil {
- return nil, err
- }
-
- req, err := http.NewRequest("POST", fmt.Sprintf("%s:%d", self.address, self.port), bytes.NewBuffer(body))
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", "application/json")
-
- client := http.Client{}
- resp, err := client.Do(req)
- if err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- if resp.Status == "200 OK" {
- reply, _ := ioutil.ReadAll(resp.Body)
- var rpcRes shared.SuccessResponse
- if err = self.codec.Decode(reply, &rpcRes); err != nil {
- return nil, err
- }
-
- result := make(map[string]string)
- if modules, ok := rpcRes.Result.(map[string]interface{}); ok {
- for a, v := range modules {
- result[a] = fmt.Sprintf("%s", v)
- }
- return result, nil
- }
- err = fmt.Errorf("Unable to parse module response - %v", rpcRes.Result)
- } else {
- fmt.Printf("resp.Status = %s\n", resp.Status)
- fmt.Printf("err = %v\n", err)
- }
-
- return nil, err
-}
diff --git a/rpc/comms/inproc.go b/rpc/comms/inproc.go
deleted file mode 100644
index e8058e32b..000000000
--- a/rpc/comms/inproc.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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 comms
-
-import (
- "fmt"
-
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type InProcClient struct {
- api shared.EthereumApi
- codec codec.Codec
- lastId interface{}
- lastJsonrpc string
- lastErr error
- lastRes interface{}
-}
-
-// Create a new in process client
-func NewInProcClient(codec codec.Codec) *InProcClient {
- return &InProcClient{
- codec: codec,
- }
-}
-
-func (self *InProcClient) Close() {
- // do nothing
-}
-
-// Need to setup api support
-func (self *InProcClient) Initialize(offeredApi shared.EthereumApi) {
- self.api = offeredApi
-}
-
-func (self *InProcClient) Send(req interface{}) error {
- if r, ok := req.(*shared.Request); ok {
- self.lastId = r.Id
- self.lastJsonrpc = r.Jsonrpc
- self.lastRes, self.lastErr = self.api.Execute(r)
- return self.lastErr
- }
-
- return fmt.Errorf("Invalid request (%T)", req)
-}
-
-func (self *InProcClient) Recv() (interface{}, error) {
- return *shared.NewRpcResponse(self.lastId, self.lastJsonrpc, self.lastRes, self.lastErr), nil
-}
-
-func (self *InProcClient) SupportedModules() (map[string]string, error) {
- req := shared.Request{
- Id: 1,
- Jsonrpc: "2.0",
- Method: "modules",
- }
-
- if res, err := self.api.Execute(&req); err == nil {
- if result, ok := res.(map[string]string); ok {
- return result, nil
- }
- } else {
- return nil, err
- }
-
- return nil, fmt.Errorf("Invalid response")
-}
diff --git a/rpc/comms/ipc.go b/rpc/comms/ipc.go
deleted file mode 100644
index 3ba747b1d..000000000
--- a/rpc/comms/ipc.go
+++ /dev/null
@@ -1,158 +0,0 @@
-// 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 comms
-
-import (
- "fmt"
- "math/rand"
- "net"
- "os"
-
- "encoding/json"
-
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-type Stopper interface {
- Stop()
-}
-
-type InitFunc func(conn net.Conn) (Stopper, shared.EthereumApi, error)
-
-type IpcConfig struct {
- Endpoint string
-}
-
-type ipcClient struct {
- endpoint string
- c net.Conn
- codec codec.Codec
- coder codec.ApiCoder
-}
-
-func (self *ipcClient) Close() {
- self.coder.Close()
-}
-
-func (self *ipcClient) Send(msg interface{}) error {
- var err error
- if err = self.coder.WriteResponse(msg); err != nil {
- if err = self.reconnect(); err == nil {
- err = self.coder.WriteResponse(msg)
- }
- }
- return err
-}
-
-func (self *ipcClient) Recv() (interface{}, error) {
- return self.coder.ReadResponse()
-}
-
-func (self *ipcClient) SupportedModules() (map[string]string, error) {
- req := shared.Request{
- Id: 1,
- Jsonrpc: "2.0",
- Method: "rpc_modules",
- }
-
- if err := self.coder.WriteResponse(req); err != nil {
- return nil, err
- }
-
- res, _ := self.coder.ReadResponse()
- if sucRes, ok := res.(*shared.SuccessResponse); ok {
- data, _ := json.Marshal(sucRes.Result)
- modules := make(map[string]string)
- if err := json.Unmarshal(data, &modules); err == nil {
- return modules, nil
- }
- }
-
- // old version uses modules instead of rpc_modules, this can be removed after full migration
- req.Method = "modules"
- if err := self.coder.WriteResponse(req); err != nil {
- return nil, err
- }
-
- res, err := self.coder.ReadResponse()
- if err != nil {
- return nil, err
- }
-
- if sucRes, ok := res.(*shared.SuccessResponse); ok {
- data, _ := json.Marshal(sucRes.Result)
- modules := make(map[string]string)
- err = json.Unmarshal(data, &modules)
- if err == nil {
- return modules, nil
- }
- }
-
- return nil, fmt.Errorf("Invalid response")
-}
-
-// Create a new IPC client, UNIX domain socket on posix, named pipe on Windows
-func NewIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
- return newIpcClient(cfg, codec)
-}
-
-// Start IPC server
-func StartIpc(cfg IpcConfig, codec codec.Codec, initializer InitFunc) error {
- l, err := ipcListen(cfg)
- if err != nil {
- return err
- }
- go ipcLoop(cfg, codec, initializer, l)
- return nil
-}
-
-// CreateListener creates an listener, on Unix platforms this is a unix socket, on Windows this is a named pipe
-func CreateListener(cfg IpcConfig) (net.Listener, error) {
- return ipcListen(cfg)
-}
-
-func ipcLoop(cfg IpcConfig, codec codec.Codec, initializer InitFunc, l net.Listener) {
- glog.V(logger.Info).Infof("IPC service started (%s)\n", cfg.Endpoint)
- defer os.Remove(cfg.Endpoint)
- defer l.Close()
- for {
- conn, err := l.Accept()
- if err != nil {
- glog.V(logger.Debug).Infof("accept: %v", err)
- return
- }
- id := newIpcConnId()
- go func() {
- defer conn.Close()
- glog.V(logger.Debug).Infof("new connection with id %06d started", id)
- stopper, api, err := initializer(conn)
- if err != nil {
- glog.V(logger.Error).Infof("Unable to initialize IPC connection: %v", err)
- return
- }
- defer stopper.Stop()
- handle(id, conn, api, codec)
- }()
- }
-}
-
-func newIpcConnId() int {
- return rand.Int() % 1000000
-}
diff --git a/rpc/comms/ipc_unix.go b/rpc/comms/ipc_unix.go
deleted file mode 100644
index 4b839572a..000000000
--- a/rpc/comms/ipc_unix.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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/>.
-
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
-
-package comms
-
-import (
- "net"
- "os"
- "path/filepath"
-
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/rpc/useragent"
-)
-
-func newIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
- c, err := net.DialUnix("unix", nil, &net.UnixAddr{cfg.Endpoint, "unix"})
- if err != nil {
- return nil, err
- }
-
- coder := codec.New(c)
- msg := shared.Request{
- Id: 0,
- Method: useragent.EnableUserAgentMethod,
- Jsonrpc: shared.JsonRpcVersion,
- Params: []byte("[]"),
- }
-
- coder.WriteResponse(msg)
- coder.Recv()
-
- return &ipcClient{cfg.Endpoint, c, codec, coder}, nil
-}
-
-func (self *ipcClient) reconnect() error {
- self.coder.Close()
- c, err := net.DialUnix("unix", nil, &net.UnixAddr{self.endpoint, "unix"})
- if err == nil {
- self.coder = self.codec.New(c)
-
- msg := shared.Request{
- Id: 0,
- Method: useragent.EnableUserAgentMethod,
- Jsonrpc: shared.JsonRpcVersion,
- Params: []byte("[]"),
- }
- self.coder.WriteResponse(msg)
- self.coder.Recv()
- }
-
- return err
-}
-
-func ipcListen(cfg IpcConfig) (net.Listener, error) {
- // Ensure the IPC path exists and remove any previous leftover
- if err := os.MkdirAll(filepath.Dir(cfg.Endpoint), 0751); err != nil {
- return nil, err
- }
- os.Remove(cfg.Endpoint)
- l, err := net.Listen("unix", cfg.Endpoint)
- if err != nil {
- return nil, err
- }
- os.Chmod(cfg.Endpoint, 0600)
- return l, nil
-}
diff --git a/rpc/v2/doc.go b/rpc/doc.go
index e51494adb..e8f8f977b 100644
--- a/rpc/v2/doc.go
+++ b/rpc/doc.go
@@ -99,4 +99,130 @@ Subscriptions are deleted when:
- the user sends an unsubscribe request
- the connection which was used to create the subscription is closed
*/
-package v2
+package rpc
+
+var (
+ // Mapping between the different methods each api supports
+ AutoCompletion = map[string][]string{
+ "admin": []string{
+ "addPeer",
+ "datadir",
+ "enableUserAgent",
+ "exportChain",
+ "getContractInfo",
+ "httpGet",
+ "importChain",
+ "nodeInfo",
+ "peers",
+ "register",
+ "registerUrl",
+ "saveInfo",
+ "setGlobalRegistrar",
+ "setHashReg",
+ "setUrlHint",
+ "setSolc",
+ "sleep",
+ "sleepBlocks",
+ "startNatSpec",
+ "startRPC",
+ "stopNatSpec",
+ "stopRPC",
+ "verbosity",
+ },
+ "db": []string{
+ "getString",
+ "putString",
+ "getHex",
+ "putHex",
+ },
+ "debug": []string{
+ "dumpBlock",
+ "getBlockRlp",
+ "metrics",
+ "printBlock",
+ "processBlock",
+ "seedHash",
+ "setHead",
+ },
+ "eth": []string{
+ "accounts",
+ "blockNumber",
+ "call",
+ "contract",
+ "coinbase",
+ "compile.lll",
+ "compile.serpent",
+ "compile.solidity",
+ "contract",
+ "defaultAccount",
+ "defaultBlock",
+ "estimateGas",
+ "filter",
+ "getBalance",
+ "getBlock",
+ "getBlockTransactionCount",
+ "getBlockUncleCount",
+ "getCode",
+ "getNatSpec",
+ "getCompilers",
+ "gasPrice",
+ "getStorageAt",
+ "getTransaction",
+ "getTransactionCount",
+ "getTransactionFromBlock",
+ "getTransactionReceipt",
+ "getUncle",
+ "hashrate",
+ "mining",
+ "namereg",
+ "pendingTransactions",
+ "resend",
+ "sendRawTransaction",
+ "sendTransaction",
+ "sign",
+ "syncing",
+ },
+ "miner": []string{
+ "hashrate",
+ "makeDAG",
+ "setEtherbase",
+ "setExtra",
+ "setGasPrice",
+ "startAutoDAG",
+ "start",
+ "stopAutoDAG",
+ "stop",
+ },
+ "net": []string{
+ "peerCount",
+ "listening",
+ },
+ "personal": []string{
+ "listAccounts",
+ "newAccount",
+ "unlockAccount",
+ },
+ "shh": []string{
+ "post",
+ "newIdentity",
+ "hasIdentity",
+ "newGroup",
+ "addToGroup",
+ "filter",
+ },
+ "txpool": []string{
+ "status",
+ },
+ "web3": []string{
+ "sha3",
+ "version",
+ "fromWei",
+ "toWei",
+ "toHex",
+ "toAscii",
+ "fromAscii",
+ "toBigNumber",
+ "isAddress",
+ },
+ }
+)
diff --git a/rpc/v2/errors.go b/rpc/errors.go
index a06d19d84..bc352fc45 100644
--- a/rpc/v2/errors.go
+++ b/rpc/errors.go
@@ -14,7 +14,7 @@
// 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 v2
+package rpc
import "fmt"
@@ -83,3 +83,15 @@ func (e *callbackError) Code() int {
func (e *callbackError) Error() string {
return e.message
}
+
+// issued when a request is received after the server is issued to stop.
+type shutdownError struct {
+}
+
+func (e *shutdownError) Code() int {
+ return -32000
+}
+
+func (e *shutdownError) Error() string {
+ return "server is shutting down"
+}
diff --git a/rpc/http.go b/rpc/http.go
new file mode 100644
index 000000000..e4b25bed8
--- /dev/null
+++ b/rpc/http.go
@@ -0,0 +1,368 @@
+// 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 rpc
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ "errors"
+ "sync"
+
+ "bytes"
+ "encoding/json"
+ "io/ioutil"
+ "net/url"
+
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "gopkg.in/fatih/set.v0"
+)
+
+const (
+ httpReadDeadLine = 60 * time.Second // wait max httpReadDeadeline for next request
+)
+
+var (
+ httpServerMu sync.Mutex // prevent concurrent access to the httpListener and httpServer
+ httpListener net.Listener // listener for the http server
+ httpRPCServer *Server // the node can only start 1 HTTP RPC server instance
+)
+
+// httpMessageStream is the glue between a HTTP connection which is message based
+// and the RPC codecs that expect json requests to be read from a stream. It will
+// parse HTTP messages and offer the bodies of these requests as a stream through
+// the Read method. This will require full control of the connection and thus need
+// a "hijacked" HTTP connection.
+type httpMessageStream struct {
+ conn net.Conn // TCP connection
+ rw *bufio.ReadWriter // buffered where HTTP requests/responses are read/written from/to
+ currentReq *http.Request // pending request, codec can pass in a too small buffer for a single read
+ // we need to keep track of the current requests if it was not read at once
+ payloadBytesRead int64 // number of bytes which are read from the current request
+ allowedOrigins *set.Set // allowed CORS domains
+ origin string // origin of this connection/request
+}
+
+// NewHttpMessageStream will create a new http message stream parser that can be
+// used by the codes in the RPC package. It will take full control of the given
+// connection and thus needs to be hijacked. It will read and write HTTP messages
+// from the passed rwbuf. The allowed origins are the RPC CORS domains the user has supplied.
+func NewHTTPMessageStream(c net.Conn, rwbuf *bufio.ReadWriter, initialReq *http.Request, allowdOrigins []string) *httpMessageStream {
+ r := &httpMessageStream{conn: c, rw: rwbuf, currentReq: initialReq, allowedOrigins: set.New()}
+ for _, origin := range allowdOrigins {
+ r.allowedOrigins.Add(origin)
+ }
+ return r
+}
+
+// handleOptionsRequest handles the HTTP preflight requests (OPTIONS) that browsers
+// make to enforce CORS rules. Only the POST method is allowed and the origin must
+// be on the rpccorsdomain list the user has specified.
+func (h *httpMessageStream) handleOptionsRequest(req *http.Request) error {
+ headers := req.Header
+
+ if !strings.EqualFold(req.Method, "OPTIONS") {
+ return fmt.Errorf("preflight aborted: %s!=OPTIONS", req.Method)
+ }
+
+ origin := headers.Get("Origin")
+ if origin == "" {
+ return fmt.Errorf("preflight aborted: empty origin")
+ }
+
+ responseHeaders := make(http.Header)
+ responseHeaders.Set("Access-Control-Allow-Methods", "POST")
+ if h.allowedOrigins.Has(origin) || h.allowedOrigins.Has("*") {
+ responseHeaders.Set("Access-Control-Allow-Origin", origin)
+ } else {
+ glog.V(logger.Info).Infof("origin '%s' not allowed", origin)
+ }
+ responseHeaders.Set("Access-Control-Allow-Headers", "Content-Type")
+ responseHeaders.Set("Date", string(httpTimestamp(time.Now())))
+ responseHeaders.Set("Content-Type", "text/plain; charset=utf-8")
+ responseHeaders.Set("Content-Length", "0")
+ responseHeaders.Set("Vary", "Origin")
+
+ defer h.rw.Flush()
+
+ if _, err := h.rw.WriteString("HTTP/1.1 200 OK\r\n"); err != nil {
+ glog.V(logger.Error).Infof("unable to write OPTIONS response: %v\n", err)
+ return err
+ }
+ if err := responseHeaders.Write(h.rw); err != nil {
+ glog.V(logger.Error).Infof("unable to write OPTIONS headers: %v\n", err)
+ }
+ if _, err := h.rw.WriteString("\r\n"); err != nil {
+ glog.V(logger.Error).Infof("unable to write OPTIONS response: %v\n", err)
+ }
+
+ return nil
+}
+
+// Read will read incoming HTTP requests and reads the body data from these requests
+// as an endless stream of data.
+func (h *httpMessageStream) Read(buf []byte) (n int, err error) {
+ h.conn.SetReadDeadline(time.Now().Add(httpReadDeadLine))
+ for {
+ // if the last request was read completely try to read the next request
+ if h.currentReq == nil {
+ if h.currentReq, err = http.ReadRequest(bufio.NewReader(h.rw)); err != nil {
+ return 0, err
+ }
+ }
+
+ // The "options" method is http specific and not interested for the RPC server.
+ // Handle it internally and wait for the next request.
+ if strings.EqualFold(h.currentReq.Method, "OPTIONS") {
+ if err = h.handleOptionsRequest(h.currentReq); err != nil {
+ glog.V(logger.Info).Infof("RPC/HTTP OPTIONS error: %v\n", err)
+ h.currentReq = nil
+ return 0, err
+ }
+
+ // processed valid request -> reset deadline
+ h.conn.SetReadDeadline(time.Now().Add(httpReadDeadLine))
+ h.currentReq = nil
+ continue
+ }
+
+ if strings.EqualFold(h.currentReq.Method, "POST") {
+ n, err := h.currentReq.Body.Read(buf)
+ h.payloadBytesRead += int64(n)
+
+ // entire payload read, read new request next time
+ if err == io.EOF || h.payloadBytesRead >= h.currentReq.ContentLength {
+ h.origin = h.currentReq.Header.Get("origin")
+ h.payloadBytesRead = 0
+ h.currentReq.Body.Close()
+ h.currentReq = nil
+ err = nil // io.EOF is not an error
+ } else if err != nil {
+ // unable to read body
+ h.currentReq.Body.Close()
+ h.currentReq = nil
+ h.payloadBytesRead = 0
+ }
+
+ // partial read of body
+ return n, err
+ }
+
+ h.currentReq = nil
+ return 0, fmt.Errorf("unsupported HTTP method '%s'", h.currentReq.Method)
+ }
+}
+
+// Write will create a HTTP response with the given payload and send it to the peer.
+func (h *httpMessageStream) Write(payload []byte) (int, error) {
+ defer h.rw.Flush()
+
+ responseHeaders := make(http.Header)
+ responseHeaders.Set("Content-Type", "application/json")
+ responseHeaders.Set("Content-Length", strconv.Itoa(len(payload)))
+ if h.origin != "" {
+ responseHeaders.Set("Access-Control-Allow-Origin", h.origin)
+ }
+
+ h.rw.WriteString("HTTP/1.1 200 OK\r\n")
+ responseHeaders.Write(h.rw)
+ h.rw.WriteString("\r\n")
+
+ return h.rw.Write(payload)
+}
+
+// Close will close the underlying TCP connection this instance has taken ownership over.
+func (h *httpMessageStream) Close() error {
+ h.rw.Flush()
+ return h.conn.Close()
+}
+
+// TimeFormat is the time format to use with time.Parse and time.Time.Format when
+// parsing or generating times in HTTP headers. It is like time.RFC1123 but hard
+// codes GMT as the time zone.
+const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
+
+// httpTimestamp formats the given t as specified in RFC1123.
+func httpTimestamp(t time.Time) []byte {
+ const days = "SunMonTueWedThuFriSat"
+ const months = "JanFebMarAprMayJunJulAugSepOctNovDec"
+
+ b := make([]byte, 0)
+ t = t.UTC()
+ yy, mm, dd := t.Date()
+ hh, mn, ss := t.Clock()
+ day := days[3 * t.Weekday():]
+ mon := months[3 * (mm - 1):]
+
+ return append(b,
+ day[0], day[1], day[2], ',', ' ',
+ byte('0' + dd / 10), byte('0' + dd % 10), ' ',
+ mon[0], mon[1], mon[2], ' ',
+ byte('0' + yy / 1000), byte('0' + (yy / 100) % 10), byte('0' + (yy / 10) % 10), byte('0' + yy % 10), ' ',
+ byte('0' + hh / 10), byte('0' + hh % 10), ':',
+ byte('0' + mn / 10), byte('0' + mn % 10), ':',
+ byte('0' + ss / 10), byte('0' + ss % 10), ' ',
+ 'G', 'M', 'T')
+}
+
+// httpConnHijacker is a http.Handler implementation that will hijack the HTTP
+// connection, wraps it in a HttpMessageStream that is then wrapped in a JSON
+// codec which will be served on the rpcServer.
+type httpConnHijacker struct {
+ corsdomains []string
+ rpcServer *Server
+}
+
+// ServeHTTP will hijack the connection, wraps the captured connection in a
+// HttpMessageStream which is then used as codec.
+func (h *httpConnHijacker) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ hj, ok := w.(http.Hijacker)
+ if !ok {
+ http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
+ return
+ }
+
+ conn, rwbuf, err := hj.Hijack()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ httpRequestStream := NewHTTPMessageStream(conn, rwbuf, req, h.corsdomains)
+
+ codec := NewJSONCodec(httpRequestStream)
+ go h.rpcServer.ServeCodec(codec)
+}
+
+// StartHTTP will start the JSONRPC HTTP RPC interface when its not yet running.
+func StartHTTP(address string, port int, corsdomains []string, apis []API) error {
+ httpServerMu.Lock()
+ defer httpServerMu.Unlock()
+
+ if httpRPCServer != nil {
+ return fmt.Errorf("HTTP RPC interface already started on %s", httpListener.Addr())
+ }
+
+ rpcServer := NewServer()
+
+ for _, api := range apis {
+ if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
+ return err
+ }
+ }
+
+ listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", address, port))
+ if err != nil {
+ return err
+ }
+
+ httpServer := http.Server{Handler: &httpConnHijacker{corsdomains, rpcServer}}
+ go httpServer.Serve(listener)
+
+ httpListener = listener
+ httpRPCServer = rpcServer
+
+ return nil
+}
+
+// StopHTTP will stop the running HTTP interface. If it is not running an error will be returned.
+func StopHTTP() error {
+ httpServerMu.Lock()
+ defer httpServerMu.Unlock()
+
+ if httpRPCServer == nil {
+ return errors.New("HTTP RPC interface not started")
+ }
+
+ httpListener.Close()
+ httpRPCServer.Stop()
+
+ httpRPCServer = nil
+ httpListener = nil
+
+ return nil
+}
+
+// httpClient connects to a geth RPC server over HTTP.
+type httpClient struct {
+ endpoint *url.URL // HTTP-RPC server endpoint
+ lastRes []byte // HTTP requests are synchronous, store last response
+}
+
+// NewHTTPClient create a new RPC clients that connection to a geth RPC server
+// over HTTP.
+func NewHTTPClient(endpoint string) (*httpClient, error) {
+ url, err := url.Parse(endpoint)
+ if err != nil {
+ return nil, err
+ }
+ return &httpClient{endpoint: url}, nil
+}
+
+// Send will serialize the given msg to JSON and sends it to the RPC server.
+// Since HTTP is synchronous the response is stored until Recv is called.
+func (client *httpClient) Send(msg interface{}) error {
+ var body []byte
+ var err error
+
+ client.lastRes = nil
+
+ if body, err = json.Marshal(msg); err != nil {
+ return err
+ }
+
+ httpReq, err := http.NewRequest("POST", client.endpoint.String(), bytes.NewBuffer(body))
+ if err != nil {
+ return err
+ }
+ httpReq.Header.Set("Content-Type", "application/json")
+
+ httpClient := http.Client{}
+ resp, err := httpClient.Do(httpReq)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode == http.StatusOK {
+ client.lastRes, err = ioutil.ReadAll(resp.Body)
+ return err
+ }
+
+ return fmt.Errorf("unable to handle request")
+}
+
+// Recv will try to deserialize the last received response into the given msg.
+func (client *httpClient) Recv(msg interface{}) error {
+ return json.Unmarshal(client.lastRes, &msg)
+}
+
+// Close is not necessary for httpClient
+func (client *httpClient) Close() {
+}
+
+// SupportedModules will return the collection of offered RPC modules.
+func (client *httpClient) SupportedModules() (map[string]string, error) {
+ return SupportedModules(client)
+}
diff --git a/rpc/ipc.go b/rpc/ipc.go
new file mode 100644
index 000000000..b87bfcbd7
--- /dev/null
+++ b/rpc/ipc.go
@@ -0,0 +1,84 @@
+// 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 rpc
+
+import (
+ "encoding/json"
+ "net"
+)
+
+// CreateIPCListener creates an listener, on Unix platforms this is a unix socket, on Windows this is a named pipe
+func CreateIPCListener(endpoint string) (net.Listener, error) {
+ return ipcListen(endpoint)
+}
+
+// ipcClient represent an IPC RPC client. It will connect to a given endpoint and tries to communicate with a node using
+// JSON serialization.
+type ipcClient struct {
+ endpoint string
+ conn net.Conn
+ out *json.Encoder
+ in *json.Decoder
+}
+
+// NewIPCClient create a new IPC client that will connect on the given endpoint. Messages are JSON encoded and encoded.
+// On Unix it assumes the endpoint is the full path to a unix socket, and Windows the endpoint is an identifier for a
+// named pipe.
+func NewIPCClient(endpoint string) (*ipcClient, error) {
+ conn, err := newIPCConnection(endpoint)
+ if err != nil {
+ return nil, err
+ }
+ return &ipcClient{endpoint: endpoint, conn: conn, in: json.NewDecoder(conn), out: json.NewEncoder(conn)}, nil
+}
+
+// Send will serialize the given message and send it to the server.
+// When sending the message fails it will try to reconnect once and send the message again.
+func (client *ipcClient) Send(msg interface{}) error {
+ if err := client.out.Encode(msg); err == nil {
+ return nil
+ }
+
+ // retry once
+ client.conn.Close()
+
+ conn, err := newIPCConnection(client.endpoint)
+ if err != nil {
+ return err
+ }
+
+ client.conn = conn
+ client.in = json.NewDecoder(conn)
+ client.out = json.NewEncoder(conn)
+
+ return client.out.Encode(msg)
+}
+
+// Recv will read a message from the connection and tries to parse it. It assumes the received message is JSON encoded.
+func (client *ipcClient) Recv(msg interface{}) error {
+ return client.in.Decode(&msg)
+}
+
+// Close will close the underlying IPC connection
+func (client *ipcClient) Close() {
+ client.conn.Close()
+}
+
+// SupportedModules will return the collection of offered RPC modules.
+func (client *ipcClient) SupportedModules() (map[string]string, error) {
+ return SupportedModules(client)
+}
diff --git a/rpc/api/web3_args.go b/rpc/ipc_unix.go
index 9e39f7130..310286e96 100644
--- a/rpc/api/web3_args.go
+++ b/rpc/ipc_unix.go
@@ -14,32 +14,32 @@
// 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
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
-import (
- "encoding/json"
+package rpc
- "github.com/ethereum/go-ethereum/rpc/shared"
+import (
+ "net"
+ "os"
+ "path/filepath"
)
-type Sha3Args struct {
- Data string
-}
-
-func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
- var obj []interface{}
- if err := json.Unmarshal(b, &obj); err != nil {
- return shared.NewDecodeParamError(err.Error())
+// ipcListen will create a Unix socket on the given endpoint.
+func ipcListen(endpoint string) (net.Listener, error) {
+ // Ensure the IPC path exists and remove any previous leftover
+ if err := os.MkdirAll(filepath.Dir(endpoint), 0751); err != nil {
+ return nil, err
}
-
- if len(obj) < 1 {
- return shared.NewInsufficientParamsError(len(obj), 1)
+ os.Remove(endpoint)
+ l, err := net.Listen("unix", endpoint)
+ if err != nil {
+ return nil, err
}
+ os.Chmod(endpoint, 0600)
+ return l, nil
+}
- argstr, ok := obj[0].(string)
- if !ok {
- return shared.NewInvalidTypeError("data", "is not a string")
- }
- args.Data = argstr
- return nil
+// newIPCConnection will connect to a Unix socket on the given endpoint.
+func newIPCConnection(endpoint string) (net.Conn, error) {
+ return net.DialUnix("unix", nil, &net.UnixAddr{endpoint, "unix"})
}
diff --git a/rpc/comms/ipc_windows.go b/rpc/ipc_windows.go
index e25fba253..1d4672ad2 100644
--- a/rpc/comms/ipc_windows.go
+++ b/rpc/ipc_windows.go
@@ -16,21 +16,16 @@
// +build windows
-package comms
+package rpc
import (
"fmt"
"io"
"net"
- "os"
"sync"
"syscall"
"time"
"unsafe"
-
- "github.com/ethereum/go-ethereum/rpc/codec"
- "github.com/ethereum/go-ethereum/rpc/shared"
- "github.com/ethereum/go-ethereum/rpc/useragent"
)
var (
@@ -649,49 +644,12 @@ func timeout(addr string) PipeError {
return PipeError{fmt.Sprintf("Pipe IO timed out waiting for '%s'", addr), true}
}
-func newIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
- c, err := Dial(cfg.Endpoint)
- if err != nil {
- return nil, err
- }
-
- coder := codec.New(c)
- msg := shared.Request{
- Id: 0,
- Method: useragent.EnableUserAgentMethod,
- Jsonrpc: shared.JsonRpcVersion,
- Params: []byte("[]"),
- }
-
- coder.WriteResponse(msg)
- coder.Recv()
-
- return &ipcClient{cfg.Endpoint, c, codec, coder}, nil
-}
-
-func (self *ipcClient) reconnect() error {
- c, err := Dial(self.endpoint)
- if err == nil {
- self.coder = self.codec.New(c)
-
- req := shared.Request{
- Id: 0,
- Method: useragent.EnableUserAgentMethod,
- Jsonrpc: shared.JsonRpcVersion,
- Params: []byte("[]"),
- }
- self.coder.WriteResponse(req)
- self.coder.Recv()
- }
- return err
+// ipcListen will create a named pipe on the given endpoint.
+func ipcListen(endpoint string) (net.Listener, error) {
+ return Listen(endpoint)
}
-func ipcListen(cfg IpcConfig) (net.Listener, error) {
- os.Remove(cfg.Endpoint) // in case it still exists from a previous run
- l, err := Listen(cfg.Endpoint)
- if err != nil {
- return nil, err
- }
- os.Chmod(cfg.Endpoint, 0600)
- return l, nil
+// newIPCConnection will connect to a named pipe with the given endpoint as name.
+func newIPCConnection(endpoint string) (net.Conn, error) {
+ return Dial(endpoint)
}
diff --git a/rpc/javascript.go b/rpc/javascript.go
new file mode 100644
index 000000000..d147aa045
--- /dev/null
+++ b/rpc/javascript.go
@@ -0,0 +1,414 @@
+// 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 rpc
+
+var (
+ // Holds geth specific RPC extends which can be used to extend web3
+ WEB3Extensions = map[string]string{
+ "personal": Personal_JS,
+ "txpool": TxPool_JS,
+ "admin": Admin_JS,
+ "db": Db_JS,
+ "eth": Eth_JS,
+ "miner": Miner_JS,
+ "debug": Debug_JS,
+ "net": Net_JS,
+ }
+)
+
+const Personal_JS = `
+web3._extend({
+ property: 'personal',
+ methods:
+ [
+ new web3._extend.Method({
+ name: 'newAccount',
+ call: 'personal_newAccount',
+ params: 1,
+ outputFormatter: web3._extend.utils.toAddress
+ }),
+ new web3._extend.Method({
+ name: 'unlockAccount',
+ call: 'personal_unlockAccount',
+ params: 3,
+ }),
+ new web3._extend.Method({
+ name: 'lockAccount',
+ call: 'personal_lockAccount',
+ params: 1
+ })
+ ],
+ properties:
+ [
+ new web3._extend.Property({
+ name: 'listAccounts',
+ getter: 'personal_listAccounts'
+ })
+ ]
+});
+`
+
+const TxPool_JS = `
+web3._extend({
+ property: 'txpool',
+ methods:
+ [
+ ],
+ properties:
+ [
+ new web3._extend.Property({
+ name: 'status',
+ getter: 'txpool_status'
+ outputFormatter: function(status) {
+ status.pending = web3._extend.utils.toDecimal(status.pending);
+ status.queued = web3._extend.utils.toDecimal(status.queued);
+ return status;
+ }
+ })
+ ]
+});
+`
+
+const Admin_JS = `
+web3._extend({
+ property: 'admin',
+ methods:
+ [
+ new web3._extend.Method({
+ name: 'addPeer',
+ call: 'admin_addPeer',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'exportChain',
+ call: 'admin_exportChain',
+ params: 1,
+ inputFormatter: [null]
+ }),
+ new web3._extend.Method({
+ name: 'importChain',
+ call: 'admin_importChain',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'sleepBlocks',
+ call: 'admin_sleepBlocks',
+ params: 2
+ }),
+ new web3._extend.Method({
+ name: 'verbosity',
+ call: 'admin_verbosity',
+ params: 1,
+ inputFormatter: [web3._extend.utils.fromDecimal]
+ }),
+ new web3._extend.Method({
+ name: 'setSolc',
+ call: 'admin_setSolc',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'startRPC',
+ call: 'admin_startRPC',
+ params: 4
+ }),
+ new web3._extend.Method({
+ name: 'stopRPC',
+ call: 'admin_stopRPC',
+ params: 0
+ }),
+ new web3._extend.Method({
+ name: 'startWS',
+ call: 'admin_startWS',
+ params: 4
+ }),
+ new web3._extend.Method({
+ name: 'stopWS',
+ call: 'admin_stopWS',
+ params: 0
+ }),
+ new web3._extend.Method({
+ name: 'setGlobalRegistrar',
+ call: 'admin_setGlobalRegistrar',
+ params: 2
+ }),
+ new web3._extend.Method({
+ name: 'setHashReg',
+ call: 'admin_setHashReg',
+ params: 2
+ }),
+ new web3._extend.Method({
+ name: 'setUrlHint',
+ call: 'admin_setUrlHint',
+ params: 2
+ }),
+ new web3._extend.Method({
+ name: 'saveInfo',
+ call: 'admin_saveInfo',
+ params: 2
+ }),
+ new web3._extend.Method({
+ name: 'register',
+ call: 'admin_register',
+ params: 3
+ }),
+ new web3._extend.Method({
+ name: 'registerUrl',
+ call: 'admin_registerUrl',
+ params: 3
+ }),
+ new web3._extend.Method({
+ name: 'startNatSpec',
+ call: 'admin_startNatSpec',
+ params: 0
+ }),
+ new web3._extend.Method({
+ name: 'stopNatSpec',
+ call: 'admin_stopNatSpec',
+ params: 0
+ }),
+ new web3._extend.Method({
+ name: 'getContractInfo',
+ call: 'admin_getContractInfo',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'httpGet',
+ call: 'admin_httpGet',
+ params: 2
+ })
+ ],
+ properties:
+ [
+ new web3._extend.Property({
+ name: 'nodeInfo',
+ getter: 'admin_nodeInfo'
+ }),
+ new web3._extend.Property({
+ name: 'peers',
+ getter: 'admin_peers'
+ }),
+ new web3._extend.Property({
+ name: 'datadir',
+ getter: 'admin_datadir'
+ })
+ ]
+});
+`
+
+const Db_JS = `
+web3._extend({
+ property: 'db',
+ methods:
+ [
+ ],
+ properties:
+ [
+ ]
+});
+`
+
+const Eth_JS = `
+web3._extend({
+ property: 'eth',
+ methods:
+ [
+ new web3._extend.Method({
+ name: 'sign',
+ call: 'eth_sign',
+ params: 2,
+ inputFormatter: [web3._extend.utils.toAddress, null]
+ }),
+ new web3._extend.Method({
+ name: 'resend',
+ call: 'eth_resend',
+ params: 3,
+ inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
+ }),
+ new web3._extend.Method({
+ name: 'getNatSpec',
+ call: 'eth_getNatSpec',
+ params: 1,
+ inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
+ }),
+ new web3._extend.Method({
+ name: 'signTransaction',
+ call: 'eth_signTransaction',
+ params: 1,
+ inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
+ }),
+ new web3._extend.Method({
+ name: 'submitTransaction',
+ call: 'eth_submitTransaction',
+ params: 1,
+ inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
+ })
+ ],
+ properties:
+ [
+ new web3._extend.Property({
+ name: 'pendingTransactions',
+ getter: 'eth_pendingTransactions'
+ })
+ ]
+});
+`
+
+const Net_JS = `
+web3._extend({
+ property: 'net',
+ methods:
+ [
+ new web3._extend.Method({
+ name: 'addPeer',
+ call: 'net_addPeer',
+ params: 1
+ })
+ ],
+ properties:
+ [
+ new web3._extend.Property({
+ name: 'version',
+ getter: 'net_version'
+ })
+ ]
+});
+`
+
+const Debug_JS = `
+web3._extend({
+ property: 'debug',
+ methods:
+ [
+ new web3._extend.Method({
+ name: 'printBlock',
+ call: 'debug_printBlock',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'getBlockRlp',
+ call: 'debug_getBlockRlp',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'setHead',
+ call: 'debug_setHead',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'processBlock',
+ call: 'debug_processBlock',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'seedHash',
+ call: 'debug_seedHash',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'dumpBlock',
+ call: 'debug_dumpBlock',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'metrics',
+ call: 'debug_metrics',
+ params: 1
+ })
+ ],
+ properties:
+ [
+ ]
+});
+`
+
+const Miner_JS = `
+web3._extend({
+ property: 'miner',
+ methods:
+ [
+ new web3._extend.Method({
+ name: 'start',
+ call: 'miner_start',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'stop',
+ call: 'miner_stop',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'setEtherbase',
+ call: 'miner_setEtherbase',
+ params: 1,
+ inputFormatter: [web3._extend.formatters.formatInputInt],
+ outputFormatter: web3._extend.formatters.formatOutputBool
+ }),
+ new web3._extend.Method({
+ name: 'setExtra',
+ call: 'miner_setExtra',
+ params: 1
+ }),
+ new web3._extend.Method({
+ name: 'setGasPrice',
+ call: 'miner_setGasPrice',
+ params: 1,
+ inputFormatter: [web3._extend.utils.fromDecial]
+ }),
+ new web3._extend.Method({
+ name: 'startAutoDAG',
+ call: 'miner_startAutoDAG',
+ params: 0
+ }),
+ new web3._extend.Method({
+ name: 'stopAutoDAG',
+ call: 'miner_stopAutoDAG',
+ params: 0
+ }),
+ new web3._extend.Method({
+ name: 'makeDAG',
+ call: 'miner_makeDAG',
+ params: 1,
+ inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter]
+ })
+ ],
+ properties:
+ [
+ new web3._extend.Property({
+ name: 'hashrate',
+ getter: 'miner_hashrate',
+ outputFormatter: web3._extend.utils.toDecimal
+ })
+ ]
+});
+`
+
+const Shh_JS = `
+web3._extend({
+ property: 'shh',
+ methods:
+ [
+
+ ],
+ properties:
+ [
+ new web3._extend.Property({
+ name: 'version',
+ getter: 'shh_version'
+ })
+ ]
+});
+`
diff --git a/rpc/v2/json.go b/rpc/json.go
index 9208e2d37..8bdb4665d 100644
--- a/rpc/v2/json.go
+++ b/rpc/json.go
@@ -14,7 +14,7 @@
// 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 v2
+package rpc
import (
"encoding/json"
@@ -37,7 +37,7 @@ const (
)
// JSON-RPC request
-type jsonRequest struct {
+type JSONRequest struct {
Method string `json:"method"`
Version string `json:"jsonrpc"`
Id *int64 `json:"id,omitempty"`
@@ -45,24 +45,24 @@ type jsonRequest struct {
}
// JSON-RPC response
-type jsonSuccessResponse struct {
+type JSONSuccessResponse struct {
Version string `json:"jsonrpc"`
Id int64 `json:"id"`
Result interface{} `json:"result,omitempty"`
}
// JSON-RPC error object
-type jsonError struct {
+type JSONError struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// JSON-RPC error response
-type jsonErrResponse struct {
+type JSONErrResponse struct {
Version string `json:"jsonrpc"`
Id *int64 `json:"id,omitempty"`
- Error jsonError `json:"error"`
+ Error JSONError `json:"error"`
}
// JSON-RPC notification payload
@@ -85,7 +85,7 @@ type jsonCodec struct {
isClosed int32
d *json.Decoder
e *json.Encoder
- req jsonRequest
+ req JSONRequest
rw io.ReadWriteCloser
}
@@ -126,7 +126,7 @@ func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, RPCError) {
// parseRequest will parse a single request from the given RawMessage. It will return the parsed request, an indication
// if the request was a batch or an error when the request could not be parsed.
func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) {
- var in jsonRequest
+ var in JSONRequest
if err := json.Unmarshal(incomingMsg, &in); err != nil {
return nil, false, &invalidMessageError{err.Error()}
}
@@ -175,7 +175,7 @@ func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) {
// parseBatchRequest will parse a batch request into a collection of requests from the given RawMessage, an indication
// if the request was a batch or an error when the request could not be read.
func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) {
- var in []jsonRequest
+ var in []JSONRequest
if err := json.Unmarshal(incomingMsg, &in); err != nil {
return nil, false, &invalidMessageError{err.Error()}
}
@@ -296,21 +296,21 @@ func parsePositionalArguments(args json.RawMessage, argTypes []reflect.Type) ([]
// CreateResponse will create a JSON-RPC success response with the given id and reply as result.
func (c *jsonCodec) CreateResponse(id int64, reply interface{}) interface{} {
if isHexNum(reflect.TypeOf(reply)) {
- return &jsonSuccessResponse{Version: jsonRPCVersion, Id: id, Result: fmt.Sprintf(`%#x`, reply)}
+ return &JSONSuccessResponse{Version: jsonRPCVersion, Id: id, Result: fmt.Sprintf(`%#x`, reply)}
}
- return &jsonSuccessResponse{Version: jsonRPCVersion, Id: id, Result: reply}
+ return &JSONSuccessResponse{Version: jsonRPCVersion, Id: id, Result: reply}
}
// CreateErrorResponse will create a JSON-RPC error response with the given id and error.
func (c *jsonCodec) CreateErrorResponse(id *int64, err RPCError) interface{} {
- return &jsonErrResponse{Version: jsonRPCVersion, Id: id, Error: jsonError{Code: err.Code(), Message: err.Error()}}
+ return &JSONErrResponse{Version: jsonRPCVersion, Id: id, Error: JSONError{Code: err.Code(), Message: err.Error()}}
}
// CreateErrorResponseWithInfo will create a JSON-RPC error response with the given id and error.
// info is optional and contains additional information about the error. When an empty string is passed it is ignored.
func (c *jsonCodec) CreateErrorResponseWithInfo(id *int64, err RPCError, info interface{}) interface{} {
- return &jsonErrResponse{Version: jsonRPCVersion, Id: id,
- Error: jsonError{Code: err.Code(), Message: err.Error(), Data: info}}
+ return &JSONErrResponse{Version: jsonRPCVersion, Id: id,
+ Error: JSONError{Code: err.Code(), Message: err.Error(), Data: info}}
}
// CreateNotification will create a JSON-RPC notification with the given subscription id and event as params.
diff --git a/rpc/v2/json_test.go b/rpc/json_test.go
index dc8a345d7..39aae1f54 100644
--- a/rpc/v2/json_test.go
+++ b/rpc/json_test.go
@@ -1,4 +1,4 @@
-package v2
+package rpc
import (
"bufio"
diff --git a/rpc/v2/server.go b/rpc/server.go
index 4c04f04d2..0b93a4e64 100644
--- a/rpc/v2/server.go
+++ b/rpc/server.go
@@ -14,23 +14,37 @@
// 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 v2
+package rpc
import (
"fmt"
"reflect"
-
"runtime"
+ "sync/atomic"
+ "time"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"golang.org/x/net/context"
+ "gopkg.in/fatih/set.v0"
+)
+
+const (
+ stopPendingRequestTimeout = 3 * time.Second // give pending requests stopPendingRequestTimeout the time to finish when the server is stopped
+
+ DefaultIpcApis = "admin,eth,debug,miner,net,shh,txpool,personal,web3"
+ DefaultHttpRpcApis = "eth,net,web3"
)
// NewServer will create a new server instance with no registered handlers.
func NewServer() *Server {
- server := &Server{services: make(serviceRegistry), subscriptions: make(subscriptionRegistry)}
+ server := &Server{
+ services: make(serviceRegistry),
+ subscriptions: make(subscriptionRegistry),
+ codecs: set.New(),
+ run: 1,
+ }
// register a default service which will provide meta information about the RPC service such as the services and
// methods it offers.
@@ -124,14 +138,37 @@ func (s *Server) ServeCodec(codec ServerCodec) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- for {
+ s.codecsMu.Lock()
+ if atomic.LoadInt32(&s.run) != 1 { // server stopped
+ s.codecsMu.Unlock()
+ return
+ }
+ s.codecs.Add(codec)
+ s.codecsMu.Unlock()
+
+ for atomic.LoadInt32(&s.run) == 1 {
reqs, batch, err := s.readRequest(codec)
+
if err != nil {
glog.V(logger.Debug).Infof("%v\n", err)
codec.Write(codec.CreateErrorResponse(nil, err))
break
}
+ if atomic.LoadInt32(&s.run) != 1 {
+ err = &shutdownError{}
+ if batch {
+ resps := make([]interface{}, len(reqs))
+ for i, r := range reqs {
+ resps[i] = codec.CreateErrorResponse(&r.id, err)
+ }
+ codec.Write(resps)
+ } else {
+ codec.Write(codec.CreateErrorResponse(&reqs[0].id, err))
+ }
+ break
+ }
+
if batch {
go s.execBatch(ctx, codec, reqs)
} else {
@@ -140,6 +177,22 @@ func (s *Server) ServeCodec(codec ServerCodec) {
}
}
+// Stop will stop reading new requests, wait for stopPendingRequestTimeout to allow pending requests to finish,
+// close all codecs which will cancels pending requests/subscriptions.
+func (s *Server) Stop() {
+ if atomic.CompareAndSwapInt32(&s.run, 1, 0) {
+ glog.V(logger.Debug).Infoln("RPC Server shutdown initiatied")
+ time.AfterFunc(stopPendingRequestTimeout, func() {
+ s.codecsMu.Lock()
+ defer s.codecsMu.Unlock()
+ s.codecs.Each(func(c interface{}) bool {
+ c.(ServerCodec).Close()
+ return true
+ })
+ })
+ }
+}
+
// sendNotification will create a notification from the given event by serializing member fields of the event.
// It will then send the notification to the client, when it fails the codec is closed. When the event has multiple
// fields an array of values is returned.
diff --git a/rpc/v2/server_test.go b/rpc/server_test.go
index f250c184f..5b91fe42a 100644
--- a/rpc/v2/server_test.go
+++ b/rpc/server_test.go
@@ -1,4 +1,20 @@
-package v2
+// 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 rpc
import (
"encoding/json"
@@ -91,7 +107,7 @@ func (c *ServerTestCodec) ReadRequestHeaders() ([]rpcRequest, bool, RPCError) {
c.counter += 1
if c.counter == 1 {
- var req jsonRequest
+ var req JSONRequest
json.Unmarshal(c.input, &req)
return []rpcRequest{rpcRequest{id: *req.Id, isPubSub: false, service: "test", method: req.Method, params: req.Payload}}, false, nil
}
@@ -157,16 +173,16 @@ func (c *ServerTestCodec) ParseRequestArguments(argTypes []reflect.Type, payload
}
func (c *ServerTestCodec) CreateResponse(id int64, reply interface{}) interface{} {
- return &jsonSuccessResponse{Version: jsonRPCVersion, Id: id, Result: reply}
+ return &JSONSuccessResponse{Version: jsonRPCVersion, Id: id, Result: reply}
}
func (c *ServerTestCodec) CreateErrorResponse(id *int64, err RPCError) interface{} {
- return &jsonErrResponse{Version: jsonRPCVersion, Id: id, Error: jsonError{Code: err.Code(), Message: err.Error()}}
+ return &JSONErrResponse{Version: jsonRPCVersion, Id: id, Error: JSONError{Code: err.Code(), Message: err.Error()}}
}
func (c *ServerTestCodec) CreateErrorResponseWithInfo(id *int64, err RPCError, info interface{}) interface{} {
- return &jsonErrResponse{Version: jsonRPCVersion, Id: id,
- Error: jsonError{Code: err.Code(), Message: err.Error(), Data: info}}
+ return &JSONErrResponse{Version: jsonRPCVersion, Id: id,
+ Error: JSONError{Code: err.Code(), Message: err.Error(), Data: info}}
}
func (c *ServerTestCodec) CreateNotification(subid string, event interface{}) interface{} {
@@ -203,7 +219,7 @@ func TestServerMethodExecution(t *testing.T) {
}
id := int64(12345)
- req := jsonRequest{
+ req := JSONRequest{
Method: "echo",
Version: "2.0",
Id: &id,
@@ -233,7 +249,7 @@ func TestServerMethodWithCtx(t *testing.T) {
}
id := int64(12345)
- req := jsonRequest{
+ req := JSONRequest{
Method: "echoWithCtx",
Version: "2.0",
Id: &id,
diff --git a/rpc/shared/errors.go b/rpc/shared/errors.go
deleted file mode 100644
index d5a7011f9..000000000
--- a/rpc/shared/errors.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// 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 shared
-
-import "fmt"
-
-type InvalidTypeError struct {
- method string
- msg string
-}
-
-func (e *InvalidTypeError) Error() string {
- return fmt.Sprintf("invalid type on field %s: %s", e.method, e.msg)
-}
-
-func NewInvalidTypeError(method, msg string) *InvalidTypeError {
- return &InvalidTypeError{
- method: method,
- msg: msg,
- }
-}
-
-type InsufficientParamsError struct {
- have int
- want int
-}
-
-func (e *InsufficientParamsError) Error() string {
- return fmt.Sprintf("insufficient params, want %d have %d", e.want, e.have)
-}
-
-func NewInsufficientParamsError(have int, want int) *InsufficientParamsError {
- return &InsufficientParamsError{
- have: have,
- want: want,
- }
-}
-
-type NotImplementedError struct {
- Method string
-}
-
-func (e *NotImplementedError) Error() string {
- return fmt.Sprintf("%s method not implemented", e.Method)
-}
-
-func NewNotImplementedError(method string) *NotImplementedError {
- return &NotImplementedError{
- Method: method,
- }
-}
-
-type NotReadyError struct {
- Resource string
-}
-
-func (e *NotReadyError) Error() string {
- return fmt.Sprintf("%s not ready", e.Resource)
-}
-
-func NewNotReadyError(resource string) *NotReadyError {
- return &NotReadyError{
- Resource: resource,
- }
-}
-
-type DecodeParamError struct {
- err string
-}
-
-func (e *DecodeParamError) Error() string {
- return fmt.Sprintf("could not decode, %s", e.err)
-
-}
-
-func NewDecodeParamError(errstr string) error {
- return &DecodeParamError{
- err: errstr,
- }
-}
-
-type ValidationError struct {
- ParamName string
- msg string
-}
-
-func (e *ValidationError) Error() string {
- return fmt.Sprintf("%s not valid, %s", e.ParamName, e.msg)
-}
-
-func NewValidationError(param string, msg string) error {
- return &ValidationError{
- ParamName: param,
- msg: msg,
- }
-}
-
-type NotAvailableError struct {
- Method string
- Reason string
-}
-
-func (e *NotAvailableError) Error() string {
- return fmt.Sprintf("%s method not available: %s", e.Method, e.Reason)
-}
-
-func NewNotAvailableError(method string, reason string) *NotAvailableError {
- return &NotAvailableError{
- Method: method,
- Reason: reason,
- }
-}
diff --git a/rpc/shared/types.go b/rpc/shared/types.go
deleted file mode 100644
index db328234d..000000000
--- a/rpc/shared/types.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// 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 shared
-
-import (
- "encoding/json"
-
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
-)
-
-// Ethereum RPC API interface
-type EthereumApi interface {
- // API identifier
- Name() string
-
- // API version
- ApiVersion() string
-
- // Execute the given request and returns the response or an error
- Execute(*Request) (interface{}, error)
-
- // List of supported RCP methods this API provides
- Methods() []string
-}
-
-// RPC request
-type Request struct {
- Id interface{} `json:"id"`
- Jsonrpc string `json:"jsonrpc"`
- Method string `json:"method"`
- Params json.RawMessage `json:"params"`
-}
-
-// RPC response
-type Response struct {
- Id interface{} `json:"id"`
- Jsonrpc string `json:"jsonrpc"`
-}
-
-// RPC success response
-type SuccessResponse struct {
- Id interface{} `json:"id"`
- Jsonrpc string `json:"jsonrpc"`
- Result interface{} `json:"result"`
-}
-
-// RPC error response
-type ErrorResponse struct {
- Id interface{} `json:"id"`
- Jsonrpc string `json:"jsonrpc"`
- Error *ErrorObject `json:"error"`
-}
-
-// RPC error response details
-type ErrorObject struct {
- Code int `json:"code"`
- Message string `json:"message"`
- // Data interface{} `json:"data"`
-}
-
-// Create RPC error response, this allows for custom error codes
-func NewRpcErrorResponse(id interface{}, jsonrpcver string, errCode int, err error) *ErrorResponse {
- jsonerr := &ErrorObject{errCode, err.Error()}
- response := ErrorResponse{Jsonrpc: jsonrpcver, Id: id, Error: jsonerr}
-
- glog.V(logger.Detail).Infof("Generated error response: %s", response)
- return &response
-}
-
-// Create RPC response
-func NewRpcResponse(id interface{}, jsonrpcver string, reply interface{}, err error) *interface{} {
- var response interface{}
-
- switch err.(type) {
- case nil:
- response = &SuccessResponse{Jsonrpc: jsonrpcver, Id: id, Result: reply}
- case *NotImplementedError:
- jsonerr := &ErrorObject{-32601, err.Error()}
- response = &ErrorResponse{Jsonrpc: jsonrpcver, Id: id, Error: jsonerr}
- case *NotReadyError:
- jsonerr := &ErrorObject{-32000, err.Error()}
- response = &ErrorResponse{Jsonrpc: jsonrpcver, Id: id, Error: jsonerr}
- case *DecodeParamError, *InsufficientParamsError, *ValidationError, *InvalidTypeError:
- jsonerr := &ErrorObject{-32602, err.Error()}
- response = &ErrorResponse{Jsonrpc: jsonrpcver, Id: id, Error: jsonerr}
- default:
- jsonerr := &ErrorObject{-32603, err.Error()}
- response = &ErrorResponse{Jsonrpc: jsonrpcver, Id: id, Error: jsonerr}
- }
-
- glog.V(logger.Detail).Infof("Generated response: %T %s", response, response)
- return &response
-}
diff --git a/rpc/shared/utils.go b/rpc/shared/utils.go
deleted file mode 100644
index b13e9eb1b..000000000
--- a/rpc/shared/utils.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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 shared
-
-import "strings"
-
-const (
- AdminApiName = "admin"
- EthApiName = "eth"
- DbApiName = "db"
- DebugApiName = "debug"
- MergedApiName = "merged"
- MinerApiName = "miner"
- NetApiName = "net"
- ShhApiName = "shh"
- TxPoolApiName = "txpool"
- PersonalApiName = "personal"
- Web3ApiName = "web3"
-
- JsonRpcVersion = "2.0"
-)
-
-var (
- // All API's
- AllApis = strings.Join([]string{
- AdminApiName, DbApiName, EthApiName, DebugApiName, MinerApiName, NetApiName,
- ShhApiName, TxPoolApiName, PersonalApiName, Web3ApiName,
- }, ",")
-)
diff --git a/rpc/v2/types.go b/rpc/types.go
index 8e638726f..02295a022 100644
--- a/rpc/v2/types.go
+++ b/rpc/types.go
@@ -14,7 +14,7 @@
// 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 v2
+package rpc
import (
"fmt"
@@ -25,6 +25,7 @@ import (
"sync"
"github.com/ethereum/go-ethereum/event"
+ "gopkg.in/fatih/set.v0"
)
// API describes the set of methods offered over the RPC interface
@@ -75,6 +76,10 @@ type Server struct {
services serviceRegistry
muSubcriptions sync.Mutex // protects subscriptions
subscriptions subscriptionRegistry
+
+ run int32
+ codecsMu sync.Mutex
+ codecs *set.Set
}
// rpcRequest represents a raw incoming RPC request
@@ -350,3 +355,14 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
func (bn *BlockNumber) Int64() int64 {
return (int64)(*bn)
}
+
+// Client defines the interface for go client that wants to connect to a geth RPC endpoint
+type Client interface {
+ // SupportedModules returns the collection of API's the server offers
+ SupportedModules() (map[string]string, error)
+
+ Send(req interface{}) error
+ Recv(msg interface{}) error
+
+ Close()
+}
diff --git a/rpc/v2/types_test.go b/rpc/types_test.go
index f73a2369e..c2c5c6db6 100644
--- a/rpc/v2/types_test.go
+++ b/rpc/types_test.go
@@ -1,4 +1,20 @@
-package v2
+// 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 rpc
import (
"bytes"
diff --git a/rpc/useragent/agent.go b/rpc/useragent/agent.go
deleted file mode 100644
index df0739e65..000000000
--- a/rpc/useragent/agent.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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 user agent provides frontends and agents which can interact with the user
-package useragent
-
-var (
- AskPasswordMethod = "agent_askPassword"
- ConfirmTransactionMethod = "agent_confirmTransaction"
- EnableUserAgentMethod = "admin_enableUserAgent"
-)
diff --git a/rpc/useragent/remote_frontend.go b/rpc/useragent/remote_frontend.go
deleted file mode 100644
index 944ab287a..000000000
--- a/rpc/useragent/remote_frontend.go
+++ /dev/null
@@ -1,166 +0,0 @@
-// 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 useragent
-
-import (
- "encoding/json"
- "fmt"
- "net"
-
- "github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-// remoteFrontend implements xeth.Frontend and will communicate with an external
-// user agent over a connection
-type RemoteFrontend struct {
- enabled bool
- mgr *accounts.Manager
- d *json.Decoder
- e *json.Encoder
- n int
-}
-
-// NewRemoteFrontend creates a new frontend which will interact with an user agent
-// over the given connection
-func NewRemoteFrontend(conn net.Conn, mgr *accounts.Manager) *RemoteFrontend {
- return &RemoteFrontend{false, mgr, json.NewDecoder(conn), json.NewEncoder(conn), 0}
-}
-
-// Enable will enable user interaction
-func (fe *RemoteFrontend) Enable() {
- fe.enabled = true
-}
-
-func (fe *RemoteFrontend) AskPassword() (string, bool) {
- if !fe.enabled {
- return "", false
- }
-
- err := fe.send(AskPasswordMethod)
- if err != nil {
- glog.V(logger.Error).Infof("Unable to send password request to agent - %v\n", err)
- return "", false
- }
-
- passwdRes, err := fe.recv()
- if err != nil {
- glog.V(logger.Error).Infof("Unable to recv password response from agent - %v\n", err)
- return "", false
- }
-
- if passwd, ok := passwdRes.Result.(string); ok {
- return passwd, true
- }
-
- return "", false
-
-}
-
-// UnlockAccount asks the user agent for the user password and tries to unlock the account.
-// It will try 3 attempts before giving up.
-func (fe *RemoteFrontend) UnlockAccount(address []byte) bool {
- if !fe.enabled {
- return false
- }
-
- err := fe.send(AskPasswordMethod, common.Bytes2Hex(address))
- if err != nil {
- glog.V(logger.Error).Infof("Unable to send password request to agent - %v\n", err)
- return false
- }
-
- passwdRes, err := fe.recv()
- if err != nil {
- glog.V(logger.Error).Infof("Unable to recv password response from agent - %v\n", err)
- return false
- }
-
- if passwd, ok := passwdRes.Result.(string); ok {
- err = fe.mgr.Unlock(common.BytesToAddress(address), passwd)
- }
-
- if err == nil {
- return true
- }
-
- glog.V(logger.Debug).Infoln("3 invalid account unlock attempts")
- return false
-}
-
-// ConfirmTransaction asks the user for approval
-func (fe *RemoteFrontend) ConfirmTransaction(tx string) bool {
- if !fe.enabled {
- return true // backwards compatibility
- }
-
- err := fe.send(ConfirmTransactionMethod, tx)
- if err != nil {
- glog.V(logger.Error).Infof("Unable to send tx confirmation request to agent - %v\n", err)
- return false
- }
-
- confirmResponse, err := fe.recv()
- if err != nil {
- glog.V(logger.Error).Infof("Unable to recv tx confirmation response from agent - %v\n", err)
- return false
- }
-
- if confirmed, ok := confirmResponse.Result.(bool); ok {
- return confirmed
- }
-
- return false
-}
-
-// send request to the agent
-func (fe *RemoteFrontend) send(method string, params ...interface{}) error {
- fe.n += 1
-
- p, err := json.Marshal(params)
- if err != nil {
- glog.V(logger.Info).Infof("Unable to send agent request %v\n", err)
- return err
- }
-
- req := shared.Request{
- Method: method,
- Jsonrpc: shared.JsonRpcVersion,
- Id: fe.n,
- Params: p,
- }
-
- return fe.e.Encode(&req)
-}
-
-// recv user response from agent
-func (fe *RemoteFrontend) recv() (*shared.SuccessResponse, error) {
- var res json.RawMessage
- if err := fe.d.Decode(&res); err != nil {
- return nil, err
- }
-
- var response shared.SuccessResponse
- if err := json.Unmarshal(res, &response); err == nil {
- return &response, nil
- }
-
- return nil, fmt.Errorf("Invalid user agent response")
-}
diff --git a/rpc/v2/utils.go b/rpc/utils.go
index ca37924a3..25321c543 100644
--- a/rpc/v2/utils.go
+++ b/rpc/utils.go
@@ -14,7 +14,7 @@
// 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 v2
+package rpc
import (
"crypto/rand"
@@ -25,6 +25,8 @@ import (
"unicode"
"unicode/utf8"
+ "fmt"
+
"golang.org/x/net/context"
)
@@ -212,3 +214,33 @@ func newSubscriptionId() (string, error) {
}
return "0x" + hex.EncodeToString(subid[:]), nil
}
+
+// SupportedModules returns the collection of API's that the RPC server offers
+// on which the given client connects.
+func SupportedModules(client Client) (map[string]string, error) {
+ req := map[string]interface{}{
+ "id": 1,
+ "method": "rpc_modules",
+ }
+
+ if err := client.Send(req); err != nil {
+ return nil, err
+ }
+
+ var response map[string]interface{}
+ if err := client.Recv(&response); err != nil {
+ return nil, err
+ }
+
+ if payload, ok := response["result"]; ok {
+ mods := make(map[string]string)
+ if modules, ok := payload.(map[string]interface{}); ok {
+ for m, v := range modules {
+ mods[m] = fmt.Sprintf("%s", v)
+ }
+ return mods, nil
+ }
+ }
+
+ return nil, fmt.Errorf("unable to retrieve modules")
+}
diff --git a/rpc/websocket.go b/rpc/websocket.go
new file mode 100644
index 000000000..b5bcbf4f6
--- /dev/null
+++ b/rpc/websocket.go
@@ -0,0 +1,235 @@
+// 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 rpc
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "net/http"
+ "sync"
+
+ "os"
+
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "golang.org/x/net/websocket"
+ "gopkg.in/fatih/set.v0"
+)
+
+var (
+ wsServerMu sync.Mutex
+ wsRPCServer *Server
+ wsListener net.Listener
+)
+
+// wsReaderWriterCloser reads and write payloads from and to a websocket connection.
+type wsReaderWriterCloser struct {
+ c *websocket.Conn
+}
+
+// Read will read incoming payload data into p.
+func (rw *wsReaderWriterCloser) Read(p []byte) (int, error) {
+ return rw.c.Read(p)
+}
+
+// Write writes p to the websocket.
+func (rw *wsReaderWriterCloser) Write(p []byte) (int, error) {
+ return rw.c.Write(p)
+}
+
+// Close closes the websocket connection.
+func (rw *wsReaderWriterCloser) Close() error {
+ return rw.c.Close()
+}
+
+// wsHandler accepts a websocket connection and handles incoming RPC requests.
+// Will return when the websocket connection is closed, either by the client or
+// server.
+func wsHandler(conn *websocket.Conn) {
+ rwc := &wsReaderWriterCloser{conn}
+ wsRPCServer.ServeCodec(NewJSONCodec(rwc))
+}
+
+// wsHandshakeValidator returns a handler that verifies the origin during the
+// websocket upgrade process. When a '*' is specified as an allowed origins all
+// connections are accepted.
+func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http.Request) error {
+ origins := set.New()
+ allowAllOrigins := false
+
+ for _, origin := range allowedOrigins {
+ if origin == "*" {
+ allowAllOrigins = true
+ }
+ if origin != "" {
+ origins.Add(origin)
+ }
+ }
+
+ // allow localhost if no allowedOrigins are specified
+ if len(origins.List()) == 0 {
+ origins.Add("http://localhost")
+ if hostname, err := os.Hostname(); err == nil {
+ origins.Add("http://" + hostname)
+ }
+ }
+
+ glog.V(logger.Debug).Infof("Allowed origin(s) for WS RPC interface %v\n", origins.List())
+
+ f := func(cfg *websocket.Config, req *http.Request) error {
+ origin := req.Header.Get("Origin")
+ if allowAllOrigins || origins.Has(origin) {
+ return nil
+ }
+ glog.V(logger.Debug).Infof("origin '%s' not allowed on WS-RPC interface\n", origin)
+ return fmt.Errorf("origin %s not allowed", origin)
+ }
+
+ return f
+}
+
+// StartWS will start a websocket RPC server on the given address and port.
+func StartWS(address string, port int, corsdomains []string, apis []API) error {
+ wsServerMu.Lock()
+ defer wsServerMu.Unlock()
+
+ if wsRPCServer != nil {
+ return fmt.Errorf("WS RPC interface already started on %s", wsListener.Addr())
+ }
+
+ rpcServer := NewServer()
+ for _, api := range apis {
+ if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
+ return err
+ }
+ }
+
+ listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", address, port))
+ if err != nil {
+ return err
+ }
+
+ wsServer := websocket.Server{Handshake: wsHandshakeValidator(corsdomains), Handler: wsHandler}
+ wsHTTPServer := http.Server{Handler: wsServer}
+
+ go wsHTTPServer.Serve(listener)
+
+ wsListener = listener
+ wsRPCServer = rpcServer
+
+ return nil
+}
+
+// StopWS stops the running websocket RPC server.
+func StopWS() error {
+ wsServerMu.Lock()
+ defer wsServerMu.Unlock()
+
+ if wsRPCServer == nil {
+ return errors.New("HTTP RPC interface not started")
+ }
+
+ wsListener.Close()
+ wsRPCServer.Stop()
+
+ wsRPCServer = nil
+ wsListener = nil
+
+ return nil
+}
+
+// wsClient represents a RPC client that communicates over websockets with a
+// RPC server.
+type wsClient struct {
+ endpoint string
+ connMu sync.Mutex
+ conn *websocket.Conn
+}
+
+// NewWSClientj creates a new RPC client that communicates with a RPC server
+// that is listening on the given endpoint using JSON encoding.
+func NewWSClient(endpoint string) (*wsClient, error) {
+ return &wsClient{endpoint: endpoint}, nil
+}
+
+// connection will return a websocket connection to the RPC server. It will
+// (re)connect when necessary.
+func (client *wsClient) connection() (*websocket.Conn, error) {
+ if client.conn != nil {
+ return client.conn, nil
+ }
+
+ origin, err := os.Hostname()
+ if err != nil {
+ return nil, err
+ }
+
+ origin = "http://" + origin
+ client.conn, err = websocket.Dial(client.endpoint, "", origin)
+
+ return client.conn, err
+}
+
+// SupportedModules is the collection of modules the RPC server offers.
+func (client *wsClient) SupportedModules() (map[string]string, error) {
+ return SupportedModules(client)
+}
+
+// Send writes the JSON serialized msg to the websocket. It will create a new
+// websocket connection to the server if the client is currently not connected.
+func (client *wsClient) Send(msg interface{}) (err error) {
+ client.connMu.Lock()
+ defer client.connMu.Unlock()
+
+ var conn *websocket.Conn
+ if conn, err = client.connection(); err == nil {
+ if err = websocket.JSON.Send(conn, msg); err != nil {
+ client.conn.Close()
+ client.conn = nil
+ }
+ }
+
+ return err
+}
+
+// Recv reads a JSON message from the websocket and unmarshals it into msg.
+func (client *wsClient) Recv(msg interface{}) (err error) {
+ client.connMu.Lock()
+ defer client.connMu.Unlock()
+
+ var conn *websocket.Conn
+ if conn, err = client.connection(); err == nil {
+ if err = websocket.JSON.Receive(conn, msg); err != nil {
+ client.conn.Close()
+ client.conn = nil
+ }
+ }
+ return
+}
+
+// Close closes the underlaying websocket connection.
+func (client *wsClient) Close() {
+ client.connMu.Lock()
+ defer client.connMu.Unlock()
+
+ if client.conn != nil {
+ client.conn.Close()
+ client.conn = nil
+ }
+
+}
diff --git a/rpc/xeth.go b/rpc/xeth.go
deleted file mode 100644
index 9527a96c0..000000000
--- a/rpc/xeth.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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 rpc implements the Ethereum JSON-RPC API.
-package rpc
-
-import (
- "encoding/json"
- "fmt"
- "reflect"
- "sync/atomic"
-
- "github.com/ethereum/go-ethereum/rpc/comms"
- "github.com/ethereum/go-ethereum/rpc/shared"
-)
-
-// Xeth is a native API interface to a remote node.
-type Xeth struct {
- client comms.EthereumClient
- reqId uint32
-}
-
-// NewXeth constructs a new native API interface to a remote node.
-func NewXeth(client comms.EthereumClient) *Xeth {
- return &Xeth{
- client: client,
- }
-}
-
-// Call invokes a method with the given parameters are the remote node.
-func (self *Xeth) Call(method string, params []interface{}) (map[string]interface{}, error) {
- // Assemble the json RPC request
- data, err := json.Marshal(params)
- if err != nil {
- return nil, err
- }
- req := &shared.Request{
- Id: atomic.AddUint32(&self.reqId, 1),
- Jsonrpc: "2.0",
- Method: method,
- Params: data,
- }
- // Send the request over and retrieve the response
- if err := self.client.Send(req); err != nil {
- return nil, err
- }
- res, err := self.client.Recv()
- if err != nil {
- return nil, err
- }
- // Ensure the response is valid, and extract the results
- success, isSuccessResponse := res.(*shared.SuccessResponse)
- failure, isFailureResponse := res.(*shared.ErrorResponse)
- switch {
- case isFailureResponse:
- return nil, fmt.Errorf("Method invocation failed: %v", failure.Error)
-
- case isSuccessResponse:
- return success.Result.(map[string]interface{}), nil
-
- default:
- return nil, fmt.Errorf("Invalid response type: %v", reflect.TypeOf(res))
- }
-}
diff --git a/whisper/api.go b/whisper/api.go
index 16f8bd329..575b9bc89 100644
--- a/whisper/api.go
+++ b/whisper/api.go
@@ -24,7 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
)
// PublicWhisperAPI provides the whisper RPC service.
diff --git a/whisper/whisper.go b/whisper/whisper.go
index e99950b76..e5f686e43 100644
--- a/whisper/whisper.go
+++ b/whisper/whisper.go
@@ -28,7 +28,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p"
- rpc "github.com/ethereum/go-ethereum/rpc/v2"
+ "github.com/ethereum/go-ethereum/rpc"
"gopkg.in/fatih/set.v0"
)
diff --git a/xeth/frontend.go b/xeth/frontend.go
deleted file mode 100644
index 70d99ebc4..000000000
--- a/xeth/frontend.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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 xeth
-
-// Frontend should be implemented by users of XEth. Its methods are
-// called whenever XEth makes a decision that requires user input.
-type Frontend interface {
- // AskPassword is called when a new account is created or updated
- AskPassword() (string, bool)
-
- // UnlockAccount is called when a transaction needs to be signed
- // but the key corresponding to the transaction's sender is
- // locked.
- //
- // It should unlock the account with the given address and return
- // true if unlocking succeeded.
- UnlockAccount(address []byte) bool
-
- // This is called for all transactions inititated through
- // Transact. It should prompt the user to confirm the transaction
- // and return true if the transaction was acknowledged.
- //
- // ConfirmTransaction is not used for Call transactions
- // because they cannot change any state.
- ConfirmTransaction(tx string) bool
-}
-
-// dummyFrontend is a non-interactive frontend that allows all
-// transactions but cannot not unlock any keys.
-type dummyFrontend struct{}
-
-func (dummyFrontend) AskPassword() (string, bool) { return "", false }
-func (dummyFrontend) UnlockAccount([]byte) bool { return false }
-func (dummyFrontend) ConfirmTransaction(string) bool { return true }
diff --git a/xeth/state.go b/xeth/state.go
deleted file mode 100644
index 7daccb525..000000000
--- a/xeth/state.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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 xeth
-
-import (
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/state"
-)
-
-type State struct {
- xeth *XEth
- state *state.StateDB
-}
-
-func NewState(xeth *XEth, statedb *state.StateDB) *State {
- return &State{xeth, statedb}
-}
-
-func (self *State) State() *state.StateDB {
- return self.state
-}
-
-func (self *State) Get(addr string) *Object {
- return &Object{self.state.GetStateObject(common.HexToAddress(addr))}
-}
-
-func (self *State) SafeGet(addr string) *Object {
- return &Object{self.safeGet(addr)}
-}
-
-func (self *State) safeGet(addr string) *state.StateObject {
- object := self.state.GetStateObject(common.HexToAddress(addr))
- if object == nil {
- object = state.NewStateObject(common.HexToAddress(addr), self.xeth.EthereumService().ChainDb())
- }
- return object
-}
diff --git a/xeth/types.go b/xeth/types.go
deleted file mode 100644
index 090115b7e..000000000
--- a/xeth/types.go
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2014 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 xeth
-
-import (
- "bytes"
- "fmt"
- "math/big"
- "strings"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-type Object struct {
- *state.StateObject
-}
-
-func NewObject(state *state.StateObject) *Object {
- return &Object{state}
-}
-
-func (self *Object) StorageString(str string) []byte {
- if common.IsHex(str) {
- return self.storage(common.Hex2Bytes(str[2:]))
- } else {
- return self.storage(common.RightPadBytes([]byte(str), 32))
- }
-}
-
-func (self *Object) storage(addr []byte) []byte {
- return self.StateObject.GetState(common.BytesToHash(addr)).Bytes()
-}
-
-func (self *Object) Storage() (storage map[string]string) {
- storage = make(map[string]string)
-
- it := self.StateObject.Trie().Iterator()
- for it.Next() {
- var data []byte
- rlp.Decode(bytes.NewReader(it.Value), &data)
- storage[common.ToHex(self.Trie().GetKey(it.Key))] = common.ToHex(data)
- }
-
- return
-}
-
-// Block interface exposed to QML
-type Block struct {
- //Transactions string `json:"transactions"`
- ref *types.Block
- Size string `json:"size"`
- Number int `json:"number"`
- Hash string `json:"hash"`
- Transactions *common.List `json:"transactions"`
- Uncles *common.List `json:"uncles"`
- Time *big.Int `json:"time"`
- Coinbase string `json:"coinbase"`
- Name string `json:"name"`
- GasLimit string `json:"gasLimit"`
- GasUsed string `json:"gasUsed"`
- PrevHash string `json:"prevHash"`
- Bloom string `json:"bloom"`
- Raw string `json:"raw"`
-}
-
-// Creates a new QML Block from a chain block
-func NewBlock(block *types.Block) *Block {
- if block == nil {
- return &Block{}
- }
-
- ptxs := make([]*Transaction, len(block.Transactions()))
- /*
- for i, tx := range block.Transactions() {
- ptxs[i] = NewTx(tx)
- }
- */
- txlist := common.NewList(ptxs)
-
- puncles := make([]*Block, len(block.Uncles()))
- /*
- for i, uncle := range block.Uncles() {
- puncles[i] = NewBlock(types.NewBlockWithHeader(uncle))
- }
- */
- ulist := common.NewList(puncles)
-
- return &Block{
- ref: block, Size: block.Size().String(),
- Number: int(block.NumberU64()), GasUsed: block.GasUsed().String(),
- GasLimit: block.GasLimit().String(), Hash: block.Hash().Hex(),
- Transactions: txlist, Uncles: ulist,
- Time: block.Time(),
- Coinbase: block.Coinbase().Hex(),
- PrevHash: block.ParentHash().Hex(),
- Bloom: common.ToHex(block.Bloom().Bytes()),
- Raw: block.String(),
- }
-}
-
-func (self *Block) ToString() string {
- if self.ref != nil {
- return self.ref.String()
- }
-
- return ""
-}
-
-func (self *Block) GetTransaction(hash string) *Transaction {
- tx := self.ref.Transaction(common.HexToHash(hash))
- if tx == nil {
- return nil
- }
-
- return NewTx(tx)
-}
-
-type Transaction struct {
- ref *types.Transaction
-
- Value string `json:"value"`
- Gas string `json:"gas"`
- GasPrice string `json:"gasPrice"`
- Hash string `json:"hash"`
- Address string `json:"address"`
- Sender string `json:"sender"`
- RawData string `json:"rawData"`
- Data string `json:"data"`
- Contract bool `json:"isContract"`
- CreatesContract bool `json:"createsContract"`
- Confirmations int `json:"confirmations"`
-}
-
-func NewTx(tx *types.Transaction) *Transaction {
- sender, err := tx.From()
- if err != nil {
- return nil
- }
- hash := tx.Hash().Hex()
-
- var receiver string
- if to := tx.To(); to != nil {
- receiver = to.Hex()
- } else {
- from, _ := tx.From()
- receiver = crypto.CreateAddress(from, tx.Nonce()).Hex()
- }
- createsContract := core.MessageCreatesContract(tx)
-
- var data string
- if createsContract {
- data = strings.Join(core.Disassemble(tx.Data()), "\n")
- } else {
- data = common.ToHex(tx.Data())
- }
-
- return &Transaction{ref: tx, Hash: hash, Value: common.CurrencyToString(tx.Value()), Address: receiver, Contract: createsContract, Gas: tx.Gas().String(), GasPrice: tx.GasPrice().String(), Data: data, Sender: sender.Hex(), CreatesContract: createsContract, RawData: common.ToHex(tx.Data())}
-}
-
-func (self *Transaction) ToString() string {
- return self.ref.String()
-}
-
-type PReceipt struct {
- CreatedContract bool `json:"createdContract"`
- Address string `json:"address"`
- Hash string `json:"hash"`
- Sender string `json:"sender"`
-}
-
-func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) *PReceipt {
- return &PReceipt{
- contractCreation,
- common.ToHex(creationAddress),
- common.ToHex(hash),
- common.ToHex(address),
- }
-}
-
-// Peer interface exposed to QML
-
-type Peer struct {
- ref *p2p.Peer
- Ip string `json:"ip"`
- Version string `json:"version"`
- Caps string `json:"caps"`
-}
-
-func NewPeer(peer *p2p.Peer) *Peer {
- var caps []string
- for _, cap := range peer.Caps() {
- caps = append(caps, fmt.Sprintf("%s/%d", cap.Name, cap.Version))
- }
-
- return &Peer{
- ref: peer,
- Ip: fmt.Sprintf("%v", peer.RemoteAddr()),
- Version: fmt.Sprintf("%v", peer.ID()),
- Caps: fmt.Sprintf("%v", caps),
- }
-}
-
-type Receipt struct {
- CreatedContract bool `json:"createdContract"`
- Address string `json:"address"`
- Hash string `json:"hash"`
- Sender string `json:"sender"`
-}
-
-func NewReciept(contractCreation bool, creationAddress, hash, address []byte) *Receipt {
- return &Receipt{
- contractCreation,
- common.ToHex(creationAddress),
- common.ToHex(hash),
- common.ToHex(address),
- }
-}
diff --git a/xeth/whisper.go b/xeth/whisper.go
deleted file mode 100644
index e7130978f..000000000
--- a/xeth/whisper.go
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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/>.
-
-// Contains the external API to the whisper sub-protocol.
-
-package xeth
-
-import (
- "fmt"
- "time"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/whisper"
-)
-
-var qlogger = logger.NewLogger("XSHH")
-
-// Whisper represents the API wrapper around the internal whisper implementation.
-type Whisper struct {
- *whisper.Whisper
-}
-
-// NewWhisper wraps an internal whisper client into an external API version.
-func NewWhisper(w *whisper.Whisper) *Whisper {
- return &Whisper{w}
-}
-
-// NewIdentity generates a new cryptographic identity for the client, and injects
-// it into the known identities for message decryption.
-func (self *Whisper) NewIdentity() string {
- identity := self.Whisper.NewIdentity()
- return common.ToHex(crypto.FromECDSAPub(&identity.PublicKey))
-}
-
-// HasIdentity checks if the the whisper node is configured with the private key
-// of the specified public pair.
-func (self *Whisper) HasIdentity(key string) bool {
- return self.Whisper.HasIdentity(crypto.ToECDSAPub(common.FromHex(key)))
-}
-
-// Post injects a message into the whisper network for distribution.
-func (self *Whisper) Post(payload string, to, from string, topics []string, priority, ttl uint32) error {
- // Decode the topic strings
- topicsDecoded := make([][]byte, len(topics))
- for i, topic := range topics {
- topicsDecoded[i] = common.FromHex(topic)
- }
- // Construct the whisper message and transmission options
- message := whisper.NewMessage(common.FromHex(payload))
- options := whisper.Options{
- To: crypto.ToECDSAPub(common.FromHex(to)),
- TTL: time.Duration(ttl) * time.Second,
- Topics: whisper.NewTopics(topicsDecoded...),
- }
- if len(from) != 0 {
- if key := self.Whisper.GetIdentity(crypto.ToECDSAPub(common.FromHex(from))); key != nil {
- options.From = key
- } else {
- return fmt.Errorf("unknown identity to send from: %s", from)
- }
- }
- // Wrap and send the message
- pow := time.Duration(priority) * time.Millisecond
- envelope, err := message.Wrap(pow, options)
- if err != nil {
- return err
- }
- if err := self.Whisper.Send(envelope); err != nil {
- return err
- }
- return nil
-}
-
-// Watch installs a new message handler to run in case a matching packet arrives
-// from the whisper network.
-func (self *Whisper) Watch(to, from string, topics [][]string, fn func(WhisperMessage)) int {
- // Decode the topic strings
- topicsDecoded := make([][][]byte, len(topics))
- for i, condition := range topics {
- topicsDecoded[i] = make([][]byte, len(condition))
- for j, topic := range condition {
- topicsDecoded[i][j] = common.FromHex(topic)
- }
- }
- // Assemble and inject the filter into the whisper client
- filter := whisper.Filter{
- To: crypto.ToECDSAPub(common.FromHex(to)),
- From: crypto.ToECDSAPub(common.FromHex(from)),
- Topics: whisper.NewFilterTopics(topicsDecoded...),
- }
- filter.Fn = func(message *whisper.Message) {
- fn(NewWhisperMessage(message))
- }
- return self.Whisper.Watch(filter)
-}
-
-// Messages retrieves all the currently pooled messages matching a filter id.
-func (self *Whisper) Messages(id int) []WhisperMessage {
- pool := self.Whisper.Messages(id)
-
- messages := make([]WhisperMessage, len(pool))
- for i, message := range pool {
- messages[i] = NewWhisperMessage(message)
- }
- return messages
-}
diff --git a/xeth/whisper_filter.go b/xeth/whisper_filter.go
deleted file mode 100644
index fdf5cebae..000000000
--- a/xeth/whisper_filter.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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/>.
-
-// Contains the external API side message filter for watching, pooling and polling
-// matched whisper messages, also serializing data access to avoid duplications.
-
-package xeth
-
-import (
- "sync"
- "time"
-
- "github.com/ethereum/go-ethereum/common"
-)
-
-// whisperFilter is the message cache matching a specific filter, accumulating
-// inbound messages until the are requested by the client.
-type whisperFilter struct {
- id int // Filter identifier for old message retrieval
- ref *Whisper // Whisper reference for old message retrieval
-
- cache []WhisperMessage // Cache of messages not yet polled
- skip map[common.Hash]struct{} // List of retrieved messages to avoid duplication
- update time.Time // Time of the last message query
-
- lock sync.RWMutex // Lock protecting the filter internals
-}
-
-// newWhisperFilter creates a new serialized, poll based whisper topic filter.
-func newWhisperFilter(id int, ref *Whisper) *whisperFilter {
- return &whisperFilter{
- id: id,
- ref: ref,
-
- update: time.Now(),
- skip: make(map[common.Hash]struct{}),
- }
-}
-
-// messages retrieves all the cached messages from the entire pool matching the
-// filter, resetting the filter's change buffer.
-func (w *whisperFilter) messages() []WhisperMessage {
- w.lock.Lock()
- defer w.lock.Unlock()
-
- w.cache = nil
- w.update = time.Now()
-
- w.skip = make(map[common.Hash]struct{})
- messages := w.ref.Messages(w.id)
- for _, message := range messages {
- w.skip[message.ref.Hash] = struct{}{}
- }
- return messages
-}
-
-// insert injects a new batch of messages into the filter cache.
-func (w *whisperFilter) insert(messages ...WhisperMessage) {
- w.lock.Lock()
- defer w.lock.Unlock()
-
- for _, message := range messages {
- if _, ok := w.skip[message.ref.Hash]; !ok {
- w.cache = append(w.cache, messages...)
- }
- }
-}
-
-// retrieve fetches all the cached messages from the filter.
-func (w *whisperFilter) retrieve() (messages []WhisperMessage) {
- w.lock.Lock()
- defer w.lock.Unlock()
-
- messages, w.cache = w.cache, nil
- w.update = time.Now()
-
- return
-}
-
-// activity returns the last time instance when client requests were executed on
-// the filter.
-func (w *whisperFilter) activity() time.Time {
- w.lock.RLock()
- defer w.lock.RUnlock()
-
- return w.update
-}
diff --git a/xeth/whisper_message.go b/xeth/whisper_message.go
deleted file mode 100644
index b3014a697..000000000
--- a/xeth/whisper_message.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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/>.
-
-// Contains the external API representation of a whisper message.
-
-package xeth
-
-import (
- "time"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/whisper"
-)
-
-// WhisperMessage is the external API representation of a whisper.Message.
-type WhisperMessage struct {
- ref *whisper.Message
-
- Payload string `json:"payload"`
- To string `json:"to"`
- From string `json:"from"`
- Sent int64 `json:"sent"`
- TTL int64 `json:"ttl"`
- Hash string `json:"hash"`
-}
-
-// NewWhisperMessage converts an internal message into an API version.
-func NewWhisperMessage(message *whisper.Message) WhisperMessage {
- return WhisperMessage{
- ref: message,
-
- Payload: common.ToHex(message.Payload),
- From: common.ToHex(crypto.FromECDSAPub(message.Recover())),
- To: common.ToHex(crypto.FromECDSAPub(message.To)),
- Sent: message.Sent.Unix(),
- TTL: int64(message.TTL / time.Second),
- Hash: common.ToHex(message.Hash.Bytes()),
- }
-}
diff --git a/xeth/xeth.go b/xeth/xeth.go
deleted file mode 100644
index 5a5399a3e..000000000
--- a/xeth/xeth.go
+++ /dev/null
@@ -1,1137 +0,0 @@
-// Copyright 2014 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 xeth is the interface to all Ethereum functionality.
-package xeth
-
-import (
- "bytes"
- "encoding/json"
- "errors"
- "fmt"
- "math/big"
- "regexp"
- "sync"
- "time"
-
- "github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/compiler"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/eth/filters"
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/miner"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/whisper"
-)
-
-var (
- filterTickerTime = 5 * time.Minute
- defaultGasPrice = big.NewInt(10000000000000) //150000000000
- defaultGas = big.NewInt(90000) //500000
- dappStorePre = []byte("dapp-")
- addrReg = regexp.MustCompile(`^(0x)?[a-fA-F0-9]{40}$`)
-)
-
-// byte will be inferred
-const (
- UnknownFilterTy = iota
- BlockFilterTy
- TransactionFilterTy
- LogFilterTy
-)
-
-type XEth struct {
- quit chan struct{}
-
- logMu sync.RWMutex
- logQueue map[int]*logQueue
-
- blockMu sync.RWMutex
- blockQueue map[int]*hashQueue
-
- transactionMu sync.RWMutex
- transactionQueue map[int]*hashQueue
-
- messagesMu sync.RWMutex
- messages map[int]*whisperFilter
-
- transactMu sync.Mutex
-
- // read-only fields
- backend *node.Node
- frontend Frontend
- agent *miner.RemoteAgent
- gpo *eth.GasPriceOracle
- state *State
- whisper *Whisper
- filterManager *filters.FilterSystem
-}
-
-func NewTest(stack *node.Node, frontend Frontend) *XEth {
- return &XEth{backend: stack, frontend: frontend}
-}
-
-// New creates an XEth that uses the given frontend.
-// If a nil Frontend is provided, a default frontend which
-// confirms all transactions will be used.
-func New(stack *node.Node, frontend Frontend) *XEth {
- var (
- ethereum *eth.Ethereum
- whisper *whisper.Whisper
- )
- stack.Service(&ethereum)
- stack.Service(&whisper)
-
- xeth := &XEth{
- backend: stack,
- frontend: frontend,
- quit: make(chan struct{}),
- filterManager: filters.NewFilterSystem(stack.EventMux()),
- logQueue: make(map[int]*logQueue),
- blockQueue: make(map[int]*hashQueue),
- transactionQueue: make(map[int]*hashQueue),
- messages: make(map[int]*whisperFilter),
- agent: miner.NewRemoteAgent(),
- gpo: eth.NewGasPriceOracle(ethereum),
- }
- if whisper != nil {
- xeth.whisper = NewWhisper(whisper)
- }
- ethereum.Miner().Register(xeth.agent)
- if frontend == nil {
- xeth.frontend = dummyFrontend{}
- }
- state, _ := ethereum.BlockChain().State()
- xeth.state = NewState(xeth, state)
- go xeth.start()
- return xeth
-}
-
-func (self *XEth) EthereumService() *eth.Ethereum {
- var ethereum *eth.Ethereum
- if err := self.backend.Service(&ethereum); err != nil {
- return nil
- }
- return ethereum
-}
-
-func (self *XEth) WhisperService() *whisper.Whisper {
- var whisper *whisper.Whisper
- if err := self.backend.Service(&whisper); err != nil {
- return nil
- }
- return whisper
-}
-
-func (self *XEth) start() {
- timer := time.NewTicker(2 * time.Second)
- defer timer.Stop()
-done:
- for {
- select {
- case <-timer.C:
- self.logMu.Lock()
- for id, filter := range self.logQueue {
- if time.Since(filter.timeout) > filterTickerTime {
- self.filterManager.Remove(id)
- delete(self.logQueue, id)
- }
- }
- self.logMu.Unlock()
-
- self.blockMu.Lock()
- for id, filter := range self.blockQueue {
- if time.Since(filter.timeout) > filterTickerTime {
- self.filterManager.Remove(id)
- delete(self.blockQueue, id)
- }
- }
- self.blockMu.Unlock()
-
- self.transactionMu.Lock()
- for id, filter := range self.transactionQueue {
- if time.Since(filter.timeout) > filterTickerTime {
- self.filterManager.Remove(id)
- delete(self.transactionQueue, id)
- }
- }
- self.transactionMu.Unlock()
-
- self.messagesMu.Lock()
- for id, filter := range self.messages {
- if time.Since(filter.activity()) > filterTickerTime {
- self.Whisper().Unwatch(id)
- delete(self.messages, id)
- }
- }
- self.messagesMu.Unlock()
- case <-self.quit:
- break done
- }
- }
-}
-
-// Stop releases any resources associated with self.
-// It may not be called more than once.
-func (self *XEth) Stop() {
- close(self.quit)
- self.filterManager.Stop()
- self.EthereumService().Miner().Unregister(self.agent)
-}
-
-func cAddress(a []string) []common.Address {
- bslice := make([]common.Address, len(a))
- for i, addr := range a {
- bslice[i] = common.HexToAddress(addr)
- }
- return bslice
-}
-
-func cTopics(t [][]string) [][]common.Hash {
- topics := make([][]common.Hash, len(t))
- for i, iv := range t {
- topics[i] = make([]common.Hash, len(iv))
- for j, jv := range iv {
- topics[i][j] = common.HexToHash(jv)
- }
- }
- return topics
-}
-
-func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) }
-
-func (self *XEth) DefaultGasPrice() *big.Int {
- return self.gpo.SuggestPrice()
-}
-
-func (self *XEth) RemoteMining() *miner.RemoteAgent { return self.agent }
-
-func (self *XEth) AtStateNum(num int64) *XEth {
- var st *state.StateDB
- var err error
- switch num {
- case -2:
- st = self.EthereumService().Miner().PendingState().Copy()
- default:
- if block := self.getBlockByHeight(num); block != nil {
- st, err = state.New(block.Root(), self.EthereumService().ChainDb())
- if err != nil {
- return nil
- }
- } else {
- st, err = state.New(self.EthereumService().BlockChain().GetBlockByNumber(0).Root(), self.EthereumService().ChainDb())
- if err != nil {
- return nil
- }
- }
- }
- return self.WithState(st)
-}
-
-func (self *XEth) WithState(statedb *state.StateDB) *XEth {
- xeth := &XEth{
- backend: self.backend,
- frontend: self.frontend,
- gpo: self.gpo,
- }
-
- xeth.state = NewState(xeth, statedb)
- return xeth
-}
-
-func (self *XEth) State() *State { return self.state }
-
-// subscribes to new head block events and
-// waits until blockchain height is greater n at any time
-// given the current head, waits for the next chain event
-// sets the state to the current head
-// loop is async and quit by closing the channel
-// used in tests and JS console debug module to control advancing private chain manually
-// Note: this is not threadsafe, only called in JS single process and tests
-func (self *XEth) UpdateState() (wait chan *big.Int) {
- wait = make(chan *big.Int)
- go func() {
- eventSub := self.backend.EventMux().Subscribe(core.ChainHeadEvent{})
- defer eventSub.Unsubscribe()
-
- var m, n *big.Int
- var ok bool
-
- eventCh := eventSub.Chan()
- for {
- select {
- case event, ok := <-eventCh:
- if !ok {
- // Event subscription closed, set the channel to nil to stop spinning
- eventCh = nil
- continue
- }
- // A real event arrived, process if new head block assignment
- if event, ok := event.Data.(core.ChainHeadEvent); ok {
- m = event.Block.Number()
- if n != nil && n.Cmp(m) < 0 {
- wait <- n
- n = nil
- }
- statedb, err := state.New(event.Block.Root(), self.EthereumService().ChainDb())
- if err != nil {
- glog.V(logger.Error).Infoln("Could not create new state: %v", err)
- return
- }
- self.state = NewState(self, statedb)
- }
- case n, ok = <-wait:
- if !ok {
- return
- }
- }
- }
- }()
- return
-}
-
-func (self *XEth) Whisper() *Whisper { return self.whisper }
-
-func (self *XEth) getBlockByHeight(height int64) *types.Block {
- var num uint64
-
- switch height {
- case -2:
- return self.EthereumService().Miner().PendingBlock()
- case -1:
- return self.CurrentBlock()
- default:
- if height < 0 {
- return nil
- }
-
- num = uint64(height)
- }
-
- return self.EthereumService().BlockChain().GetBlockByNumber(num)
-}
-
-func (self *XEth) BlockByHash(strHash string) *Block {
- hash := common.HexToHash(strHash)
- block := self.EthereumService().BlockChain().GetBlock(hash)
-
- return NewBlock(block)
-}
-
-func (self *XEth) EthBlockByHash(strHash string) *types.Block {
- hash := common.HexToHash(strHash)
- block := self.EthereumService().BlockChain().GetBlock(hash)
-
- return block
-}
-
-func (self *XEth) EthTransactionByHash(hash string) (*types.Transaction, common.Hash, uint64, uint64) {
- ethereum := self.EthereumService()
- if tx, hash, number, index := core.GetTransaction(ethereum.ChainDb(), common.HexToHash(hash)); tx != nil {
- return tx, hash, number, index
- }
- return ethereum.TxPool().GetTransaction(common.HexToHash(hash)), common.Hash{}, 0, 0
-}
-
-func (self *XEth) BlockByNumber(num int64) *Block {
- return NewBlock(self.getBlockByHeight(num))
-}
-
-func (self *XEth) EthBlockByNumber(num int64) *types.Block {
- return self.getBlockByHeight(num)
-}
-
-func (self *XEth) Td(hash common.Hash) *big.Int {
- return self.EthereumService().BlockChain().GetTd(hash)
-}
-
-func (self *XEth) CurrentBlock() *types.Block {
- return self.EthereumService().BlockChain().CurrentBlock()
-}
-
-func (self *XEth) GetBlockReceipts(bhash common.Hash) types.Receipts {
- return core.GetBlockReceipts(self.EthereumService().ChainDb(), bhash)
-}
-
-func (self *XEth) GetTxReceipt(txhash common.Hash) *types.Receipt {
- return core.GetReceipt(self.EthereumService().ChainDb(), txhash)
-}
-
-func (self *XEth) GasLimit() *big.Int {
- return self.EthereumService().BlockChain().GasLimit()
-}
-
-func (self *XEth) Block(v interface{}) *Block {
- if n, ok := v.(int32); ok {
- return self.BlockByNumber(int64(n))
- } else if str, ok := v.(string); ok {
- return self.BlockByHash(str)
- } else if f, ok := v.(float64); ok { // JSON numbers are represented as float64
- return self.BlockByNumber(int64(f))
- }
-
- return nil
-}
-
-func (self *XEth) Accounts() []string {
- // TODO: check err?
- accounts, _ := self.EthereumService().AccountManager().Accounts()
- accountAddresses := make([]string, len(accounts))
- for i, ac := range accounts {
- accountAddresses[i] = ac.Address.Hex()
- }
- return accountAddresses
-}
-
-// accessor for solidity compiler.
-// memoized if available, retried on-demand if not
-func (self *XEth) Solc() (*compiler.Solidity, error) {
- return self.EthereumService().Solc()
-}
-
-// set in js console via admin interface or wrapper from cli flags
-func (self *XEth) SetSolc(solcPath string) (*compiler.Solidity, error) {
- self.EthereumService().SetSolc(solcPath)
- return self.Solc()
-}
-
-// store DApp value in extra database
-func (self *XEth) DbPut(key, val []byte) bool {
- self.EthereumService().DappDb().Put(append(dappStorePre, key...), val)
- return true
-}
-
-// retrieve DApp value from extra database
-func (self *XEth) DbGet(key []byte) ([]byte, error) {
- val, err := self.EthereumService().DappDb().Get(append(dappStorePre, key...))
- return val, err
-}
-
-func (self *XEth) PeerCount() int {
- return self.backend.Server().PeerCount()
-}
-
-func (self *XEth) IsMining() bool {
- return self.EthereumService().IsMining()
-}
-
-func (self *XEth) HashRate() int64 {
- return self.EthereumService().Miner().HashRate()
-}
-
-func (self *XEth) EthVersion() string {
- return fmt.Sprintf("%d", self.EthereumService().EthVersion())
-}
-
-func (self *XEth) NetworkVersion() string {
- return fmt.Sprintf("%d", self.EthereumService().NetVersion())
-}
-
-func (self *XEth) WhisperVersion() string {
- return fmt.Sprintf("%d", self.WhisperService().Version())
-}
-
-func (self *XEth) ClientVersion() string {
- return self.backend.Server().Name
-}
-
-func (self *XEth) SetMining(shouldmine bool, threads int) bool {
- ismining := self.EthereumService().IsMining()
- if shouldmine && !ismining {
- err := self.EthereumService().StartMining(threads, "")
- return err == nil
- }
- if ismining && !shouldmine {
- self.EthereumService().StopMining()
- }
- return self.EthereumService().IsMining()
-}
-
-func (self *XEth) IsListening() bool {
- return true
-}
-
-func (self *XEth) Coinbase() string {
- eb, err := self.EthereumService().Etherbase()
- if err != nil {
- return "0x0"
- }
- return eb.Hex()
-}
-
-func (self *XEth) NumberToHuman(balance string) string {
- b := common.Big(balance)
-
- return common.CurrencyToString(b)
-}
-
-func (self *XEth) StorageAt(addr, storageAddr string) string {
- return self.State().state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex()
-}
-
-func (self *XEth) BalanceAt(addr string) string {
- return common.ToHex(self.State().state.GetBalance(common.HexToAddress(addr)).Bytes())
-}
-
-func (self *XEth) TxCountAt(address string) int {
- return int(self.State().state.GetNonce(common.HexToAddress(address)))
-}
-
-func (self *XEth) CodeAt(address string) string {
- return common.ToHex(self.State().state.GetCode(common.HexToAddress(address)))
-}
-
-func (self *XEth) CodeAtBytes(address string) []byte {
- return self.State().SafeGet(address).Code()
-}
-
-func (self *XEth) IsContract(address string) bool {
- return len(self.State().SafeGet(address).Code()) > 0
-}
-
-func (self *XEth) UninstallFilter(id int) bool {
- defer self.filterManager.Remove(id)
-
- if _, ok := self.logQueue[id]; ok {
- self.logMu.Lock()
- defer self.logMu.Unlock()
- delete(self.logQueue, id)
- return true
- }
- if _, ok := self.blockQueue[id]; ok {
- self.blockMu.Lock()
- defer self.blockMu.Unlock()
- delete(self.blockQueue, id)
- return true
- }
- if _, ok := self.transactionQueue[id]; ok {
- self.transactionMu.Lock()
- defer self.transactionMu.Unlock()
- delete(self.transactionQueue, id)
- return true
- }
-
- return false
-}
-
-func (self *XEth) NewLogFilter(earliest, latest int64, skip, max int, address []string, topics [][]string) int {
- self.logMu.Lock()
- defer self.logMu.Unlock()
-
- filter := filters.New(self.EthereumService().ChainDb())
- id := self.filterManager.Add(filter)
- self.logQueue[id] = &logQueue{timeout: time.Now()}
-
- filter.SetBeginBlock(earliest)
- filter.SetEndBlock(latest)
- filter.SetAddresses(cAddress(address))
- filter.SetTopics(cTopics(topics))
- filter.LogsCallback = func(logs vm.Logs) {
- self.logMu.Lock()
- defer self.logMu.Unlock()
-
- if queue := self.logQueue[id]; queue != nil {
- queue.add(logs...)
- }
- }
-
- return id
-}
-
-func (self *XEth) NewTransactionFilter() int {
- self.transactionMu.Lock()
- defer self.transactionMu.Unlock()
-
- filter := filters.New(self.EthereumService().ChainDb())
- id := self.filterManager.Add(filter)
- self.transactionQueue[id] = &hashQueue{timeout: time.Now()}
-
- filter.TransactionCallback = func(tx *types.Transaction) {
- self.transactionMu.Lock()
- defer self.transactionMu.Unlock()
-
- if queue := self.transactionQueue[id]; queue != nil {
- queue.add(tx.Hash())
- }
- }
- return id
-}
-
-func (self *XEth) NewBlockFilter() int {
- self.blockMu.Lock()
- defer self.blockMu.Unlock()
-
- filter := filters.New(self.EthereumService().ChainDb())
- id := self.filterManager.Add(filter)
- self.blockQueue[id] = &hashQueue{timeout: time.Now()}
-
- filter.BlockCallback = func(block *types.Block, logs vm.Logs) {
- self.blockMu.Lock()
- defer self.blockMu.Unlock()
-
- if queue := self.blockQueue[id]; queue != nil {
- queue.add(block.Hash())
- }
- }
- return id
-}
-
-func (self *XEth) GetFilterType(id int) byte {
- if _, ok := self.blockQueue[id]; ok {
- return BlockFilterTy
- } else if _, ok := self.transactionQueue[id]; ok {
- return TransactionFilterTy
- } else if _, ok := self.logQueue[id]; ok {
- return LogFilterTy
- }
-
- return UnknownFilterTy
-}
-
-func (self *XEth) LogFilterChanged(id int) vm.Logs {
- self.logMu.Lock()
- defer self.logMu.Unlock()
-
- if self.logQueue[id] != nil {
- return self.logQueue[id].get()
- }
- return nil
-}
-
-func (self *XEth) BlockFilterChanged(id int) []common.Hash {
- self.blockMu.Lock()
- defer self.blockMu.Unlock()
-
- if self.blockQueue[id] != nil {
- return self.blockQueue[id].get()
- }
- return nil
-}
-
-func (self *XEth) TransactionFilterChanged(id int) []common.Hash {
- self.blockMu.Lock()
- defer self.blockMu.Unlock()
-
- if self.transactionQueue[id] != nil {
- return self.transactionQueue[id].get()
- }
- return nil
-}
-
-func (self *XEth) Logs(id int) vm.Logs {
- filter := self.filterManager.Get(id)
- if filter != nil {
- return filter.Find()
- }
-
- return nil
-}
-
-func (self *XEth) AllLogs(earliest, latest int64, skip, max int, address []string, topics [][]string) vm.Logs {
- filter := filters.New(self.EthereumService().ChainDb())
- filter.SetBeginBlock(earliest)
- filter.SetEndBlock(latest)
- filter.SetAddresses(cAddress(address))
- filter.SetTopics(cTopics(topics))
-
- return filter.Find()
-}
-
-// NewWhisperFilter creates and registers a new message filter to watch for
-// inbound whisper messages. All parameters at this point are assumed to be
-// HEX encoded.
-func (p *XEth) NewWhisperFilter(to, from string, topics [][]string) int {
- // Pre-define the id to be filled later
- var id int
-
- // Callback to delegate core whisper messages to this xeth filter
- callback := func(msg WhisperMessage) {
- p.messagesMu.RLock() // Only read lock to the filter pool
- defer p.messagesMu.RUnlock()
- if p.messages[id] != nil {
- p.messages[id].insert(msg)
- }
- }
- // Initialize the core whisper filter and wrap into xeth
- id = p.Whisper().Watch(to, from, topics, callback)
-
- p.messagesMu.Lock()
- p.messages[id] = newWhisperFilter(id, p.Whisper())
- p.messagesMu.Unlock()
-
- return id
-}
-
-// UninstallWhisperFilter disables and removes an existing filter.
-func (p *XEth) UninstallWhisperFilter(id int) bool {
- p.messagesMu.Lock()
- defer p.messagesMu.Unlock()
-
- if _, ok := p.messages[id]; ok {
- delete(p.messages, id)
- return true
- }
- return false
-}
-
-// WhisperMessages retrieves all the known messages that match a specific filter.
-func (self *XEth) WhisperMessages(id int) []WhisperMessage {
- self.messagesMu.RLock()
- defer self.messagesMu.RUnlock()
-
- if self.messages[id] != nil {
- return self.messages[id].messages()
- }
- return nil
-}
-
-// WhisperMessagesChanged retrieves all the new messages matched by a filter
-// since the last retrieval
-func (self *XEth) WhisperMessagesChanged(id int) []WhisperMessage {
- self.messagesMu.RLock()
- defer self.messagesMu.RUnlock()
-
- if self.messages[id] != nil {
- return self.messages[id].retrieve()
- }
- return nil
-}
-
-// func (self *XEth) Register(args string) bool {
-// self.regmut.Lock()
-// defer self.regmut.Unlock()
-
-// if _, ok := self.register[args]; ok {
-// self.register[args] = nil // register with empty
-// }
-// return true
-// }
-
-// func (self *XEth) Unregister(args string) bool {
-// self.regmut.Lock()
-// defer self.regmut.Unlock()
-
-// if _, ok := self.register[args]; ok {
-// delete(self.register, args)
-// return true
-// }
-
-// return false
-// }
-
-// // TODO improve return type
-// func (self *XEth) PullWatchTx(args string) []*interface{} {
-// self.regmut.Lock()
-// defer self.regmut.Unlock()
-
-// txs := self.register[args]
-// self.register[args] = nil
-
-// return txs
-// }
-
-type KeyVal struct {
- Key string `json:"key"`
- Value string `json:"value"`
-}
-
-func (self *XEth) EachStorage(addr string) string {
- var values []KeyVal
- object := self.State().SafeGet(addr)
- it := object.Trie().Iterator()
- for it.Next() {
- values = append(values, KeyVal{common.ToHex(object.Trie().GetKey(it.Key)), common.ToHex(it.Value)})
- }
-
- valuesJson, err := json.Marshal(values)
- if err != nil {
- return ""
- }
-
- return string(valuesJson)
-}
-
-func (self *XEth) ToAscii(str string) string {
- padded := common.RightPadBytes([]byte(str), 32)
-
- return "0x" + common.ToHex(padded)
-}
-
-func (self *XEth) FromAscii(str string) string {
- if common.IsHex(str) {
- str = str[2:]
- }
-
- return string(bytes.Trim(common.FromHex(str), "\x00"))
-}
-
-func (self *XEth) FromNumber(str string) string {
- if common.IsHex(str) {
- str = str[2:]
- }
-
- return common.BigD(common.FromHex(str)).String()
-}
-
-func (self *XEth) PushTx(encodedTx string) (string, error) {
- tx := new(types.Transaction)
- err := rlp.DecodeBytes(common.FromHex(encodedTx), tx)
- if err != nil {
- glog.V(logger.Error).Infoln(err)
- return "", err
- }
-
- err = self.EthereumService().TxPool().Add(tx)
- if err != nil {
- return "", err
- }
-
- if tx.To() == nil {
- from, err := tx.From()
- if err != nil {
- return "", err
- }
-
- addr := crypto.CreateAddress(from, tx.Nonce())
- glog.V(logger.Info).Infof("Tx(%x) created: %x\n", tx.Hash(), addr)
- } else {
- glog.V(logger.Info).Infof("Tx(%x) to: %x\n", tx.Hash(), tx.To())
- }
-
- return tx.Hash().Hex(), nil
-}
-
-func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) {
- statedb := self.State().State().Copy()
- var from *state.StateObject
- if len(fromStr) == 0 {
- accounts, err := self.EthereumService().AccountManager().Accounts()
- if err != nil || len(accounts) == 0 {
- from = statedb.GetOrNewStateObject(common.Address{})
- } else {
- from = statedb.GetOrNewStateObject(accounts[0].Address)
- }
- } else {
- from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr))
- }
-
- from.SetBalance(common.MaxBig)
-
- msg := callmsg{
- from: from,
- gas: common.Big(gasStr),
- gasPrice: common.Big(gasPriceStr),
- value: common.Big(valueStr),
- data: common.FromHex(dataStr),
- }
- if len(toStr) > 0 {
- addr := common.HexToAddress(toStr)
- msg.to = &addr
- }
-
- if msg.gas.Cmp(big.NewInt(0)) == 0 {
- msg.gas = big.NewInt(50000000)
- }
-
- if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
- msg.gasPrice = self.DefaultGasPrice()
- }
-
- header := self.CurrentBlock().Header()
- vmenv := core.NewEnv(statedb, self.EthereumService().BlockChain(), msg, header)
- gp := new(core.GasPool).AddGas(common.MaxBig)
- res, gas, err := core.ApplyMessage(vmenv, msg, gp)
- return common.ToHex(res), gas.String(), err
-}
-
-func (self *XEth) ConfirmTransaction(tx string) bool {
- return self.frontend.ConfirmTransaction(tx)
-}
-
-func (self *XEth) doSign(from common.Address, hash common.Hash, didUnlock bool) ([]byte, error) {
- sig, err := self.EthereumService().AccountManager().Sign(accounts.Account{Address: from}, hash.Bytes())
- if err == accounts.ErrLocked {
- if didUnlock {
- return nil, fmt.Errorf("signer account still locked after successful unlock")
- }
- if !self.frontend.UnlockAccount(from.Bytes()) {
- return nil, fmt.Errorf("could not unlock signer account")
- }
- // retry signing, the account should now be unlocked.
- return self.doSign(from, hash, true)
- } else if err != nil {
- return nil, err
- }
- return sig, nil
-}
-
-func (self *XEth) Sign(fromStr, hashStr string, didUnlock bool) (string, error) {
- var (
- from = common.HexToAddress(fromStr)
- hash = common.HexToHash(hashStr)
- )
- sig, err := self.doSign(from, hash, didUnlock)
- if err != nil {
- return "", err
- }
- return common.ToHex(sig), nil
-}
-
-func isAddress(addr string) bool {
- return addrReg.MatchString(addr)
-}
-
-func (self *XEth) Frontend() Frontend {
- return self.frontend
-}
-
-func (self *XEth) SignTransaction(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (*types.Transaction, error) {
- if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) {
- return nil, errors.New("Invalid address")
- }
-
- var (
- from = common.HexToAddress(fromStr)
- to = common.HexToAddress(toStr)
- value = common.Big(valueStr)
- gas *big.Int
- price *big.Int
- data []byte
- contractCreation bool
- )
-
- if len(gasStr) == 0 {
- gas = DefaultGas()
- } else {
- gas = common.Big(gasStr)
- }
-
- if len(gasPriceStr) == 0 {
- price = self.DefaultGasPrice()
- } else {
- price = common.Big(gasPriceStr)
- }
-
- data = common.FromHex(codeStr)
- if len(toStr) == 0 {
- contractCreation = true
- }
-
- var nonce uint64
- if len(nonceStr) != 0 {
- nonce = common.Big(nonceStr).Uint64()
- } else {
- state := self.EthereumService().TxPool().State()
- nonce = state.GetNonce(from)
- }
- var tx *types.Transaction
- if contractCreation {
- tx = types.NewContractCreation(nonce, value, gas, price, data)
- } else {
- tx = types.NewTransaction(nonce, to, value, gas, price, data)
- }
-
- signed, err := self.sign(tx, from, false)
- if err != nil {
- return nil, err
- }
-
- return signed, nil
-}
-
-func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
-
- // this minimalistic recoding is enough (works for natspec.js)
- var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, toStr, codeStr)
- if !self.ConfirmTransaction(jsontx) {
- err := fmt.Errorf("Transaction not confirmed")
- return "", err
- }
-
- if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) {
- return "", errors.New("Invalid address")
- }
-
- var (
- from = common.HexToAddress(fromStr)
- to = common.HexToAddress(toStr)
- value = common.Big(valueStr)
- gas *big.Int
- price *big.Int
- data []byte
- contractCreation bool
- )
-
- if len(gasStr) == 0 {
- gas = DefaultGas()
- } else {
- gas = common.Big(gasStr)
- }
-
- if len(gasPriceStr) == 0 {
- price = self.DefaultGasPrice()
- } else {
- price = common.Big(gasPriceStr)
- }
-
- data = common.FromHex(codeStr)
- if len(toStr) == 0 {
- contractCreation = true
- }
-
- // 2015-05-18 Is this still needed?
- // TODO if no_private_key then
- //if _, exists := p.register[args.From]; exists {
- // p.register[args.From] = append(p.register[args.From], args)
- //} else {
- /*
- account := accounts.Get(common.FromHex(args.From))
- if account != nil {
- if account.Unlocked() {
- if !unlockAccount(account) {
- return
- }
- }
-
- result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data))
- if len(result) > 0 {
- *reply = common.ToHex(result)
- }
- } else if _, exists := p.register[args.From]; exists {
- p.register[ags.From] = append(p.register[args.From], args)
- }
- */
-
- self.transactMu.Lock()
- defer self.transactMu.Unlock()
-
- var nonce uint64
- if len(nonceStr) != 0 {
- nonce = common.Big(nonceStr).Uint64()
- } else {
- state := self.EthereumService().TxPool().State()
- nonce = state.GetNonce(from)
- }
- var tx *types.Transaction
- if contractCreation {
- tx = types.NewContractCreation(nonce, value, gas, price, data)
- } else {
- tx = types.NewTransaction(nonce, to, value, gas, price, data)
- }
-
- signed, err := self.sign(tx, from, false)
- if err != nil {
- return "", err
- }
- self.EthereumService().TxPool().SetLocal(signed)
- if err = self.EthereumService().TxPool().Add(signed); err != nil {
- return "", err
- }
-
- if contractCreation {
- addr := crypto.CreateAddress(from, nonce)
- glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signed.Hash().Hex(), addr.Hex())
- } else {
- glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signed.Hash().Hex(), tx.To().Hex())
- }
-
- return signed.Hash().Hex(), nil
-}
-
-func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) (*types.Transaction, error) {
- hash := tx.SigHash()
- sig, err := self.doSign(from, hash, didUnlock)
- if err != nil {
- return tx, err
- }
- return tx.WithSignature(sig)
-}
-
-// callmsg is the message type used for call transations.
-type callmsg struct {
- from *state.StateObject
- to *common.Address
- gas, gasPrice *big.Int
- value *big.Int
- data []byte
-}
-
-// accessor boilerplate to implement core.Message
-func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
-func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
-func (m callmsg) To() *common.Address { return m.to }
-func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
-func (m callmsg) Gas() *big.Int { return m.gas }
-func (m callmsg) Value() *big.Int { return m.value }
-func (m callmsg) Data() []byte { return m.data }
-
-type logQueue struct {
- mu sync.Mutex
-
- logs vm.Logs
- timeout time.Time
- id int
-}
-
-func (l *logQueue) add(logs ...*vm.Log) {
- l.mu.Lock()
- defer l.mu.Unlock()
-
- l.logs = append(l.logs, logs...)
-}
-
-func (l *logQueue) get() vm.Logs {
- l.mu.Lock()
- defer l.mu.Unlock()
-
- l.timeout = time.Now()
- tmp := l.logs
- l.logs = nil
- return tmp
-}
-
-type hashQueue struct {
- mu sync.Mutex
-
- hashes []common.Hash
- timeout time.Time
- id int
-}
-
-func (l *hashQueue) add(hashes ...common.Hash) {
- l.mu.Lock()
- defer l.mu.Unlock()
-
- l.hashes = append(l.hashes, hashes...)
-}
-
-func (l *hashQueue) get() []common.Hash {
- l.mu.Lock()
- defer l.mu.Unlock()
-
- l.timeout = time.Now()
- tmp := l.hashes
- l.hashes = nil
- return tmp
-}
diff --git a/xeth/xeth_test.go b/xeth/xeth_test.go
deleted file mode 100644
index e649d20ef..000000000
--- a/xeth/xeth_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package xeth
-
-import "testing"
-
-func TestIsAddress(t *testing.T) {
- for _, invalid := range []string{
- "0x00",
- "0xNN",
- "0x00000000000000000000000000000000000000NN",
- "0xAAar000000000000000000000000000000000000",
- } {
- if isAddress(invalid) {
- t.Error("Expected", invalid, "to be invalid")
- }
- }
-
- for _, valid := range []string{
- "0x0000000000000000000000000000000000000000",
- "0xAABBbbCCccff9900000000000000000000000000",
- "AABBbbCCccff9900000000000000000000000000",
- } {
- if !isAddress(valid) {
- t.Error("Expected", valid, "to be valid")
- }
- }
-}