From 24fc1f073dd5ec0302937fb51729991dd9a40ba3 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sun, 29 Mar 2015 21:21:14 +0200 Subject: [PATCH 01/50] Add flag to control CORS header #394 * Disabled on CLI * http://localhost on Mist --- cmd/geth/main.go | 1 + cmd/mist/main.go | 7 +++++++ cmd/utils/flags.go | 6 +++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 05e2e4ae65..62e30ac9a6 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -233,6 +233,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.VMDebugFlag, utils.ProtocolVersionFlag, utils.NetworkIdFlag, + utils.RPCCORSDomainFlag, } // missing: diff --git a/cmd/mist/main.go b/cmd/mist/main.go index fab651b228..6780cfb3a1 100644 --- a/cmd/mist/main.go +++ b/cmd/mist/main.go @@ -47,12 +47,19 @@ var ( Usage: "absolute path to GUI assets directory", Value: common.DefaultAssetPath(), } + rpcCorsFlag = utils.RPCCORSDomainFlag ) func init() { + // Mist-specific default + if len(rpcCorsFlag.Value) == 0 { + rpcCorsFlag.Value = "http://localhost" + } + app.Action = run app.Flags = []cli.Flag{ assetPathFlag, + rpcCorsFlag, utils.BootnodesFlag, utils.DataDirFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 2a3e2f4476..131f8a5c00 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -148,7 +148,11 @@ var ( Usage: "Port on which the JSON-RPC server should listen", Value: 8545, } - + RPCCORSDomainFlag = cli.StringFlag{ + Name: "rpccorsdomain", + Usage: "Domain on which to send Access-Control-Allow-Origin header", + Value: "", + } // Network Settings MaxPeersFlag = cli.IntFlag{ Name: "maxpeers", From 04a7c4ae1e7fe9683854fd759cad0e5e04a2f2c0 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sun, 29 Mar 2015 21:26:47 +0200 Subject: [PATCH 02/50] Abstract http into rpc package New RpcConfig object to pass growing config --- cmd/geth/admin.go | 16 +++++++++++----- cmd/utils/flags.go | 17 +++++++---------- rpc/http.go | 12 ++++++++++++ rpc/messages.go | 6 ++++++ 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go index 3a58b88814..b217e88b5a 100644 --- a/cmd/geth/admin.go +++ b/cmd/geth/admin.go @@ -2,8 +2,6 @@ package main import ( "fmt" - "net" - "net/http" "os" "time" @@ -70,12 +68,20 @@ func (js *jsre) startRPC(call otto.FunctionCall) otto.Value { return otto.FalseValue() } - l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port)) + config := rpc.RpcConfig{ + ListenAddress: addr, + ListenPort: uint(port), + // CorsDomain: ctx.GlobalString(RPCCORSDomainFlag.Name), + } + + xeth := xeth.New(js.ethereum, nil) + err = rpc.Start(xeth, config) + if err != nil { - fmt.Printf("Can't listen on %s:%d: %v", addr, port, err) + fmt.Printf(err.Error()) return otto.FalseValue() } - go http.Serve(l, rpc.JSONRPC(xeth.New(js.ethereum, nil))) + return otto.TrueValue() } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 131f8a5c00..e82fd9c285 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2,9 +2,6 @@ package utils import ( "crypto/ecdsa" - "fmt" - "net" - "net/http" "os" "path" "runtime" @@ -259,12 +256,12 @@ func GetAccountManager(ctx *cli.Context) *accounts.Manager { } func StartRPC(eth *eth.Ethereum, ctx *cli.Context) { - addr := ctx.GlobalString(RPCListenAddrFlag.Name) - port := ctx.GlobalInt(RPCPortFlag.Name) - fmt.Println("Starting RPC on port: ", port) - l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port)) - if err != nil { - Fatalf("Can't listen on %s:%d: %v", addr, port, err) + config := rpc.RpcConfig{ + ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name), + ListenPort: uint(ctx.GlobalInt(RPCPortFlag.Name)), + CorsDomain: ctx.GlobalString(RPCCORSDomainFlag.Name), } - go http.Serve(l, rpc.JSONRPC(xeth.New(eth, nil))) + + xeth := xeth.New(eth, nil) + _ = rpc.Start(xeth, config) } diff --git a/rpc/http.go b/rpc/http.go index 919c567bd5..d146f28a6b 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -2,8 +2,10 @@ package rpc import ( "encoding/json" + "fmt" "io" "io/ioutil" + "net" "net/http" "github.com/ethereum/go-ethereum/logger" @@ -17,6 +19,16 @@ const ( maxSizeReqLength = 1024 * 1024 // 1MB ) +func Start(pipe *xeth.XEth, config RpcConfig) error { + l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", config.ListenAddress, config.ListenPort)) + if err != nil { + rpclogger.Errorf("Can't listen on %s:%d: %v", config.ListenAddress, config.ListenPort, err) + return err + } + go http.Serve(l, JSONRPC(pipe)) + return nil +} + // JSONRPC returns a handler that implements the Ethereum JSON-RPC API. func JSONRPC(pipe *xeth.XEth) http.Handler { api := NewEthereumApi(pipe) diff --git a/rpc/messages.go b/rpc/messages.go index 5c498234f9..43c4d5e0d0 100644 --- a/rpc/messages.go +++ b/rpc/messages.go @@ -21,6 +21,12 @@ import ( "fmt" ) +type RpcConfig struct { + ListenAddress string + ListenPort uint + CorsDomain string +} + type InvalidTypeError struct { method string msg string From b6fde73ef130e80eb834a60e766ce288de800bef Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sun, 29 Mar 2015 21:56:04 +0200 Subject: [PATCH 03/50] Add settable domain to CORS handler #331 --- rpc/http.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/rpc/http.go b/rpc/http.go index d146f28a6b..f15d557ad1 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/xeth" + "github.com/rs/cors" ) var rpclogger = logger.NewLogger("RPC") @@ -25,7 +26,21 @@ func Start(pipe *xeth.XEth, config RpcConfig) error { rpclogger.Errorf("Can't listen on %s:%d: %v", config.ListenAddress, config.ListenPort, err) return err } - go http.Serve(l, JSONRPC(pipe)) + + var handler http.Handler + if len(config.CorsDomain) > 0 { + var opts cors.Options + opts.AllowedMethods = []string{"POST"} + opts.AllowedOrigins = []string{config.CorsDomain} + + c := cors.New(opts) + handler = c.Handler(JSONRPC(pipe)) + } else { + handler = JSONRPC(pipe) + } + + go http.Serve(l, handler) + return nil } @@ -34,8 +49,7 @@ func JSONRPC(pipe *xeth.XEth) http.Handler { api := NewEthereumApi(pipe) return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - // TODO this needs to be configurable - w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Content-Type", "application/json") // Limit request size to resist DoS if req.ContentLength > maxSizeReqLength { From 35d00e00c52ad7d7c13e53b598e61fc332052f7b Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sun, 29 Mar 2015 22:19:38 +0200 Subject: [PATCH 04/50] Update Godeps --- Godeps/Godeps.json | 4 + .../src/github.com/rs/cors/.travis.yml | 4 + .../_workspace/src/github.com/rs/cors/LICENSE | 19 ++ .../src/github.com/rs/cors/README.md | 84 +++++ .../src/github.com/rs/cors/bench_test.go | 37 +++ .../_workspace/src/github.com/rs/cors/cors.go | 308 ++++++++++++++++++ .../src/github.com/rs/cors/cors_test.go | 288 ++++++++++++++++ .../rs/cors/examples/alice/server.go | 24 ++ .../rs/cors/examples/default/server.go | 18 + .../rs/cors/examples/goji/server.go | 22 ++ .../rs/cors/examples/martini/server.go | 23 ++ .../rs/cors/examples/negroni/server.go | 26 ++ .../rs/cors/examples/nethttp/server.go | 20 ++ .../rs/cors/examples/openbar/server.go | 22 ++ .../src/github.com/rs/cors/utils.go | 27 ++ .../src/github.com/rs/cors/utils_test.go | 28 ++ 16 files changed, 954 insertions(+) create mode 100644 Godeps/_workspace/src/github.com/rs/cors/.travis.yml create mode 100644 Godeps/_workspace/src/github.com/rs/cors/LICENSE create mode 100644 Godeps/_workspace/src/github.com/rs/cors/README.md create mode 100644 Godeps/_workspace/src/github.com/rs/cors/bench_test.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/cors.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/cors_test.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/utils.go create mode 100644 Godeps/_workspace/src/github.com/rs/cors/utils_test.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 5ba6bb8cff..4c8c8281eb 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -90,6 +90,10 @@ "ImportPath": "github.com/robertkrimen/otto/token", "Rev": "dea31a3d392779af358ec41f77a07fcc7e9d04ba" }, + { + "ImportPath": "github.com/rs/cors", + "Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb" + }, { "ImportPath": "github.com/syndtr/goleveldb/leveldb", "Rev": "832fa7ed4d28545eab80f19e1831fc004305cade" diff --git a/Godeps/_workspace/src/github.com/rs/cors/.travis.yml b/Godeps/_workspace/src/github.com/rs/cors/.travis.yml new file mode 100644 index 0000000000..bbb5185a2e --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/.travis.yml @@ -0,0 +1,4 @@ +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 new file mode 100644 index 0000000000..d8e2df5a47 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Olivier Poitrey + +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 new file mode 100644 index 0000000000..6f70c30aca --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/README.md @@ -0,0 +1,84 @@ +# 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 new file mode 100644 index 0000000000..454375d2cc --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/bench_test.go @@ -0,0 +1,37 @@ +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 new file mode 100644 index 0000000000..276bc40bb2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/cors.go @@ -0,0 +1,308 @@ +/* +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 new file mode 100644 index 0000000000..f215018c96 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/cors_test.go @@ -0,0 +1,288 @@ +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 new file mode 100644 index 0000000000..0a3e15cb8a --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go @@ -0,0 +1,24 @@ +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 new file mode 100644 index 0000000000..851ac41d01 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go @@ -0,0 +1,18 @@ +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 new file mode 100644 index 0000000000..1fb4073aad --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go @@ -0,0 +1,22 @@ +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 new file mode 100644 index 0000000000..081af32f92 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go @@ -0,0 +1,23 @@ +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 new file mode 100644 index 0000000000..3cb33bff6f --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go @@ -0,0 +1,26 @@ +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 new file mode 100644 index 0000000000..eaa775e443 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go @@ -0,0 +1,20 @@ +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 new file mode 100644 index 0000000000..0940423006 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go @@ -0,0 +1,22 @@ +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 new file mode 100644 index 0000000000..429ab1114b --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/utils.go @@ -0,0 +1,27 @@ +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 new file mode 100644 index 0000000000..3fc77fc1e0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/rs/cors/utils_test.go @@ -0,0 +1,28 @@ +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") + } +} From 9feed3f61ebd3875fef8355fab9f1027989c03d6 Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Mon, 30 Mar 2015 15:59:14 +0200 Subject: [PATCH 05/50] Correct gas limit validation according to new algorithm * Use absolute value of (block's gas limit) - (parent's gas limit) in comparison with diff limit. * Ensure the diff is strictly smaller than the allowed size. --- core/block_processor.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/block_processor.go b/core/block_processor.go index bc3274eb5c..e970ad06ef 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -260,10 +260,13 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) } + // TODO: use use minGasLimit and gasLimitBoundDivisor from + // https://github.com/ethereum/common/blob/master/params.json // block.gasLimit - parent.gasLimit <= parent.gasLimit / 1024 a := new(big.Int).Sub(block.GasLimit, parent.GasLimit) + a.Abs(a) b := new(big.Int).Div(parent.GasLimit, big.NewInt(1024)) - if a.Cmp(b) > 0 { + if !(a.Cmp(b) < 0) { return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b) } From 2f3a9681360f5326137de3aeb0aa8e2130de562a Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Mon, 30 Mar 2015 16:20:30 +0200 Subject: [PATCH 06/50] New CallArgs Requirements for calls differ from transactions --- rpc/api.go | 2 +- rpc/args.go | 87 +++++++++++++++ rpc/args_test.go | 277 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 357 insertions(+), 9 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index 5020791777..bcd073ed2a 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -159,7 +159,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } *reply = v case "eth_call": - args := new(NewTxArgs) + args := new(CallArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } diff --git a/rpc/args.go b/rpc/args.go index 25a6c7a4f9..dd013147d9 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -238,6 +238,93 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) { 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 NewDecodeParamError(err.Error()) + } + + // Check for sufficient params + if len(obj) < 1 { + return NewInsufficientParamsError(len(obj), 1) + } + + // Decode 0th RawMessage to temporary struct + if err := json.Unmarshal(obj[0], &ext); err != nil { + return NewDecodeParamError(err.Error()) + } + + if len(ext.From) == 0 { + return NewValidationError("from", "is required") + } + args.From = ext.From + + if len(ext.To) == 0 { + return NewValidationError("to", "is required") + } + args.To = ext.To + + var num int64 + if ext.Value == nil { + num = int64(0) + } else { + if err := numString(ext.Value, &num); err != nil { + return err + } + } + args.Value = big.NewInt(num) + + if ext.Gas == nil { + num = int64(0) + } else { + if err := numString(ext.Gas, &num); err != nil { + return err + } + } + args.Gas = big.NewInt(num) + + if ext.GasPrice == nil { + num = int64(0) + } else { + if err := numString(ext.GasPrice, &num); err != nil { + return err + } + } + args.GasPrice = big.NewInt(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 + } + } + + return nil +} + type GetStorageArgs struct { Address string BlockNumber int64 diff --git a/rpc/args_test.go b/rpc/args_test.go index 602631b677..3635882c00 100644 --- a/rpc/args_test.go +++ b/rpc/args_test.go @@ -531,14 +531,275 @@ func TestNewTxArgsFromEmpty(t *testing.T) { input := `[{"to": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]` args := new(NewTxArgs) - err := json.Unmarshal([]byte(input), &args) - switch err.(type) { - case nil: - t.Error("Expected error but didn't get one") - case *ValidationError: - break - default: - t.Errorf("Expected *rpc.ValidationError, but got %T with message `%s`", err, err.Error()) + 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.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 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 = big.NewInt(0) + + 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 = big.NewInt(0) + + 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 TestCallArgsFromEmpty(t *testing.T) { + input := `[{"to": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]` + + args := new(CallArgs) + str := ExpectValidationError(json.Unmarshal([]byte(input), &args)) + if len(str) > 0 { + t.Error(str) + } +} + +func TestCallArgsToEmpty(t *testing.T) { + input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]` + + args := new(CallArgs) + str := ExpectValidationError(json.Unmarshal([]byte(input), &args)) + if len(str) > 0 { + t.Error(str) } } From 6daa4552438f1d84d231600aced702b2808ef30b Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Tue, 31 Mar 2015 14:14:29 +0200 Subject: [PATCH 07/50] Update Go bootnode address --- eth/backend.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/backend.go b/eth/backend.go index fed0da0169..b1fa68e729 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -31,7 +31,7 @@ var ( defaultBootNodes = []*discover.Node{ // ETH/DEV cmd/bootnode - discover.MustParseNode("enode://6cdd090303f394a1cac34ecc9f7cda18127eafa2a3a06de39f6d920b0e583e062a7362097c7c65ee490a758b442acd5c80c6fce4b148c6a391e946b45131365b@54.169.166.226:30303"), + discover.MustParseNode("enode://09fbeec0d047e9a37e63f60f8618aa9df0e49271f3fadb2c070dc09e2099b95827b63a8b837c6fd01d0802d457dd83e3bd48bd3e6509f8209ed90dabbc30e3d3@52.16.188.185:30303"), // ETH/DEV cpp-ethereum (poc-8.ethdev.com) discover.MustParseNode("enode://4a44599974518ea5b0f14c31c4463692ac0329cb84851f3435e6d1b18ee4eae4aa495f846a0fa1219bd58035671881d44423876e57db2abd57254d0197da0ebe@5.1.83.226:30303"), } From 3453f8c5d2cf075063bcb8cd716b72e005b93e39 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 31 Mar 2015 15:30:55 +0200 Subject: [PATCH 08/50] Added Code field --- core/genesis.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index e0d3e51b8b..716298231d 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -7,8 +7,8 @@ import ( "os" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" ) /* @@ -34,7 +34,10 @@ func GenesisBlock(db common.Database) *types.Block { genesis.SetTransactions(types.Transactions{}) genesis.SetReceipts(types.Receipts{}) - var accounts map[string]struct{ Balance string } + var accounts map[string]struct { + Balance string + Code string + } err := json.Unmarshal(genesisData, &accounts) if err != nil { fmt.Println("enable to decode genesis json data:", err) @@ -46,6 +49,7 @@ func GenesisBlock(db common.Database) *types.Block { codedAddr := common.Hex2Bytes(addr) accountState := statedb.GetAccount(common.BytesToAddress(codedAddr)) accountState.SetBalance(common.Big(account.Balance)) + accountState.SetCode(common.FromHex(account.Code)) statedb.UpdateStateObject(accountState) } statedb.Sync() From ec181b308addc30c04973e9058960d579c84eef5 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 31 Mar 2015 16:25:22 +0200 Subject: [PATCH 09/50] Squashed 'tests/files/' changes from c6d9629..29da5ea 29da5ea add JS block test example as state test 04108e0 Merge remote-tracking branch 'origin' into develop 6da7f35 JS failures 22b5dfc stQuadraticComplexity Refill with latest develop c97bf26 Memory / Solidity Test Update git-subtree-dir: tests/files git-subtree-split: 29da5ea53ab36d74bd3c0712337168086cabfb8d --- StateTests/RandomTests/st201503302200JS.json | 71 ++++++++ StateTests/RandomTests/st201503302202JS.json | 71 ++++++++ StateTests/RandomTests/st201503302206JS.json | 71 ++++++++ StateTests/RandomTests/st201503302208JS.json | 71 ++++++++ StateTests/RandomTests/st201503302210JS.json | 71 ++++++++ StateTests/RandomTests/st201503302211JS.json | 71 ++++++++ StateTests/stCallCreateCallCodeTest.json | 60 +++++++ StateTests/stMemoryStressTest.json | 85 +++++++++- StateTests/stQuadraticComplexityTest.json | 54 +++--- StateTests/stSolidityTest.json | 169 ++++++++++++------- 10 files changed, 702 insertions(+), 92 deletions(-) create mode 100644 StateTests/RandomTests/st201503302200JS.json create mode 100644 StateTests/RandomTests/st201503302202JS.json create mode 100644 StateTests/RandomTests/st201503302206JS.json create mode 100644 StateTests/RandomTests/st201503302208JS.json create mode 100644 StateTests/RandomTests/st201503302210JS.json create mode 100644 StateTests/RandomTests/st201503302211JS.json diff --git a/StateTests/RandomTests/st201503302200JS.json b/StateTests/RandomTests/st201503302200JS.json new file mode 100644 index 0000000000..04cda0cad6 --- /dev/null +++ b/StateTests/RandomTests/st201503302200JS.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000c350377f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000100000000000000000000000000000000000000000b3a09785b1084418866100af0868a3455", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1556088597", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998443911449", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "886793cb795aad67bef8747046a71428c332fac253236d4002e142f08f31602b", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000c350377f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000100000000000000000000000000000000000000000b3a09785b1084418866100af0868a3455", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000c350377f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000100000000000000000000000000000000000000000b3a09785b1084418866100af0868a34", + "gasLimit" : "0x5cc006e7", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "2056709657" + } + } +} diff --git a/StateTests/RandomTests/st201503302202JS.json b/StateTests/RandomTests/st201503302202JS.json new file mode 100644 index 0000000000..2bd3d6b881 --- /dev/null +++ b/StateTests/RandomTests/st201503302202JS.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000100000000000000000000000000000000000000004340427f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff52835a546b6685923465", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1241595343", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998758404703", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "adebc5b15e70b5b8ad3eb5d2d0bc7880149d6f86d96cbc861494f810c3d325c1", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000100000000000000000000000000000000000000004340427f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff52835a546b6685923465", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000100000000000000000000000000000000000000004340427f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff52835a546b6685923465", + "gasLimit" : "0x4a013da1", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1959890283" + } + } +} diff --git a/StateTests/RandomTests/st201503302206JS.json b/StateTests/RandomTests/st201503302206JS.json new file mode 100644 index 0000000000..86f9b42c9a --- /dev/null +++ b/StateTests/RandomTests/st201503302206JS.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe527f00000000000000000000000000000000000000000000000000000000000000017f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1944132934", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998055867112", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "16d58f4edca99e12b53543966af5ef6159af7dbf93ef4f085bce2972ecb413ad", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe527f00000000000000000000000000000000000000000000000000000000000000017f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe527f00000000000000000000000000000000000000000000000000000000000000017f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5", + "gasLimit" : "0x73e11d18", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1285310456" + } + } +} diff --git a/StateTests/RandomTests/st201503302208JS.json b/StateTests/RandomTests/st201503302208JS.json new file mode 100644 index 0000000000..9c49f721a5 --- /dev/null +++ b/StateTests/RandomTests/st201503302208JS.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe307f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000100000000000000000000000000000000000000005255", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1380924181", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998619075865", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "224160a19d11a6252067a26ecfc2963fd1aff5c2b484a2f12c12ec7d5bbc547d", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe307f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000100000000000000000000000000000000000000005255", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe307f00000000000000000000000100000000000000000000000000000000000000007f000000000000000000000001000000000000000000000000000000000000000052", + "gasLimit" : "0x524f3ae7", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "936808044" + } + } +} diff --git a/StateTests/RandomTests/st201503302210JS.json b/StateTests/RandomTests/st201503302210JS.json new file mode 100644 index 0000000000..42d53b12b6 --- /dev/null +++ b/StateTests/RandomTests/st201503302210JS.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000100000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001155933704", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1932635520", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998067364526", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "3c9d47fb3ada07b78c2e6470ed8b4107db21e513979a71c270d97da5a20186bc", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000100000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001155933704", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000100000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001155933704", + "gasLimit" : "0x7331ad52", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1499936335" + } + } +} diff --git a/StateTests/RandomTests/st201503302211JS.json b/StateTests/RandomTests/st201503302211JS.json new file mode 100644 index 0000000000..9bf18da150 --- /dev/null +++ b/StateTests/RandomTests/st201503302211JS.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000001000000000000000000000000000000000000000044457f0000000000000000000000000000000000000000000000000000000000000001187f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff52155955", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1283993444", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998716006602", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "af423ed22996f4161da21729d08e3d9138d94234b778a043313bb6dcbc55d93d", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000001000000000000000000000000000000000000000044457f0000000000000000000000000000000000000000000000000000000000000001187f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff52155955", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f000000000000000000000001000000000000000000000000000000000000000044457f0000000000000000000000000000000000000000000000000000000000000001187f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff521559", + "gasLimit" : "0x4c882f36", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "679746513" + } + } +} diff --git a/StateTests/stCallCreateCallCodeTest.json b/StateTests/stCallCreateCallCodeTest.json index 09b7aeb8da..abed20ae00 100644 --- a/StateTests/stCallCreateCallCodeTest.json +++ b/StateTests/stCallCreateCallCodeTest.json @@ -847,6 +847,66 @@ "value" : "100000" } }, + "createJS_ExampleContract" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056", + "post" : { + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "366356", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { + "balance" : "100000", + "code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056", + "nonce" : "0", + "storage" : { + "0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x01" : "0x42", + "0x02" : "0x23", + "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x05" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999999533644", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "239c509594811741c8f3ed0a2d89abb00c0398098c80f88a82cebc153dec5c4b", + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x60406103ca600439600451602451336000819055506000600481905550816001819055508060028190555042600581905550336003819055505050610381806100496000396000f30060003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b505600000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000023", + "gasLimit" : "600000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "100000" + } + }, "createNameRegistratorendowmentTooHigh" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", diff --git a/StateTests/stMemoryStressTest.json b/StateTests/stMemoryStressTest.json index 323aa7aa6f..3b09715511 100644 --- a/StateTests/stMemoryStressTest.json +++ b/StateTests/stMemoryStressTest.json @@ -1,4 +1,73 @@ { + "FillStack" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe457f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017f000000000000000000000000000000000000000000000000000000000000c3504357155320803a975560005155", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "3141638", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999996858408", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "fce3d23dbb978bf49908221f831b52381c8a13cc354cf20130f659c481515e83", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe457f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017f000000000000000000000000000000000000000000000000000000000000c3504357155320803a975560005155", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe457f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017f000000000000000000000000000000000000000000000000000000000000c3504357155320803a97", + "gasLimit" : "3141592", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "264050067" + } + }, "mload32bitBound" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -13,7 +82,7 @@ "out" : "0x", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000010", + "balance" : "1000000000000000000", "code" : "0x64010000000051600155", "nonce" : "0", "storage" : { @@ -27,14 +96,14 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "158330884724018", + "balance" : "158330884724028", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "090f17dba3bdd58cf107c8155b9066e54f53a9d75bd0ec5524c364f361e32d14", + "postStateRoot" : "8a47d8a8689889820bd4273dd667ece01f288b091ce244c671a6394dc4109f1f", "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", @@ -75,7 +144,7 @@ "out" : "0x", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000010", + "balance" : "1000000000000000000", "code" : "0x64017735940051600155", "nonce" : "0", "storage" : { @@ -89,14 +158,14 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340119723807253", + "balance" : "340119723807263", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "bc10fc8e26a51bad7dad35ee2a218076947efd3010ef12d869c3eae434a41b6d", + "postStateRoot" : "6965350d67785b430326cd01f5c523976fa9361740a6f09f2f8b1f1f7940b6ec", "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", @@ -141,7 +210,7 @@ "code" : "0x600163ffffffff5259600055", "nonce" : "0", "storage" : { - "0x" : "0x0100000020" + "0x" : "0x20" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { @@ -159,7 +228,7 @@ } } }, - "postStateRoot" : "f5cba7b1b92529ff627b7c99277dce9461d3b4cf23b030d82a3c67411d22315d", + "postStateRoot" : "2959cb7d4801e19f2f83560db82253c45d0f3ebe6fd24b683e3fb61cbf36d8c3", "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", diff --git a/StateTests/stQuadraticComplexityTest.json b/StateTests/stQuadraticComplexityTest.json index cd1d3d7a79..87bcdcb8b9 100644 --- a/StateTests/stQuadraticComplexityTest.json +++ b/StateTests/stQuadraticComplexityTest.json @@ -13,7 +13,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374606549268211445", + "balance" : "340282366920938463463374606549268211455", "code" : "0x", "nonce" : "1", "storage" : { @@ -34,14 +34,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x60016000540160005561040060005410601b5760016002556047565b60006000620f42406000600073bbbf5374fce5edbc8e2a8697c15331677e6ebf0b620f55c85a03f16001555b", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "663dc49e9b7325b42dada44e8783314a91be746a73a86e834f9592ba7c69fd3e", + "postStateRoot" : "41ae7b9b5d5a40a8cf673e75e87da34ee60e054579798da9de4b91add7119fc6", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -89,7 +89,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431683211445", + "balance" : "340282366920938463463374607431683211455", "code" : "0x", "nonce" : "1", "storage" : { @@ -110,14 +110,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x5b61c3506080511015603f576000600061c3506000600173aaaf5374fce5edbc8e2a8697c15331677e6ebf0b610640f16000556001608051016080526000565b608051600155", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "fa335ba0e63752360fc9eaf701cdcf4315e0f9038b898c008ba975fd66028ed4", + "postStateRoot" : "03b85800376c94106b746ac1714af750c6bccc95263fe92bfd673b623c2a9f58", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -165,7 +165,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431673711445", + "balance" : "340282366920938463463374607431673711455", "code" : "0x", "nonce" : "1", "storage" : { @@ -179,14 +179,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431768211465", + "balance" : "340282366920938463463374607431768211455", "code" : "0x5b61c3506080511015602c576000600061c3506000600160016101f4f16000556001608051016080526000565b608051600155", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "d036f16280564019d2bfab66b8e37fa41cfcad04025c949f897f511e321e5cb3", + "postStateRoot" : "1c10ca4d661261f2041a209c80878a85e70c568fcaca0d2672207bfbc8e5262c", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -227,7 +227,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431679961445", + "balance" : "340282366920938463463374607431679961455", "code" : "0x", "nonce" : "1", "storage" : { @@ -241,14 +241,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x5b61c3506080511015602c576000600061c35060006001600461061cf16000556001608051016080526000565b608051600155", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "5b62734d0f07edf448659b47743c07b3e255d22b7fd982f94afffe40cad36257", + "postStateRoot" : "5b598dad661bdec03972e39b4f8a81c4a5e660761ad43dce42f270963759d7eb", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -289,7 +289,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431679961445", + "balance" : "340282366920938463463374607431679961455", "code" : "0x", "nonce" : "1", "storage" : { @@ -303,14 +303,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x602a6001525b61c350608051101560325761c350600161c35060006001600461061cf16000556001608051016080526005565b608051600155600151600255", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "5216c8ba51b38440ac008c5667e3042a89135b89a9489d2e0f710d1b17f4046e", + "postStateRoot" : "0c99be86d6bc6d54547baa21ad24a66e033b1d2f66faa45f8a698dfefc89b58b", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -351,7 +351,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607427843211445", + "balance" : "340282366920938463463374607427843211455", "code" : "0x", "nonce" : "1", "storage" : { @@ -365,14 +365,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x5b61c3506080511015602d576000600061c35060006001600362013178f16000556001608051016080526000565b608051600155", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "13aaa7fe67364082aca2dea3277354b8fd6c67833900fc255dd8c11d560af5cc", + "postStateRoot" : "ee56d166321770f333bc9706cd878884698f94afeb9fdfdaba14b19488a3395a", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -721,7 +721,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431683211445", + "balance" : "340282366920938463463374607431683211455", "code" : "0x", "nonce" : "1", "storage" : { @@ -742,14 +742,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x5b61c3506080511015603f576000600061c3506000600173aaaf5374fce5edbc8e2a8697c15331677e6ebf0b610640f26000556001608051016080526000565b608051600155", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "e006bf33ef8b4299670ee9eeb3ccc19c783fd73677088bb76e056e07df70197d", + "postStateRoot" : "414b9e24bee6c3d77fe338f9830cbd0653b6ddbe64177dfdc16a3dd20f234697", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -7924,7 +7924,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431679961445", + "balance" : "340282366920938463463374607431679961455", "code" : "0x", "nonce" : "1", "storage" : { @@ -7945,14 +7945,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x5b61c3506080511015603f576000600061c3506000600073aaaf5374fce5edbc8e2a8697c15331677e6ebf0b61061cf16000556001608051016080526000565b608051600155", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "31d45315e75daa1099c6dec7a6ab85d39fdd6c5bb5d7f7d1b19a5cd85de7bce7", + "postStateRoot" : "722399a622a8b9b74621e7523708158e65293d659fee58c0a056d2f48b44a189", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", @@ -8000,7 +8000,7 @@ "out" : "0x", "post" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "340282366920938463463374607431679961445", + "balance" : "340282366920938463463374607431679961455", "code" : "0x", "nonce" : "1", "storage" : { @@ -8021,14 +8021,14 @@ } }, "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "4503599627370505", + "balance" : "4503599627370495", "code" : "0x5b61c3506080511015603f576000600061c3506000600073aaaf5374fce5edbc8e2a8697c15331677e6ebf0b61061cf16000556001608051016080526000565b608051600155", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "4d4f0332a3f18f34b3d4777ac84c7c99e91c0da4005834dc819dfa69f7cbd156", + "postStateRoot" : "a3d7da9aa50be0201d42a2d00f968aa675ba436172ff793a3bc174ad7ffee206", "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "340282366920938463463374607431768211455", diff --git a/StateTests/stSolidityTest.json b/StateTests/stSolidityTest.json index 322deeb0f1..f32425c4a5 100644 --- a/StateTests/stSolidityTest.json +++ b/StateTests/stSolidityTest.json @@ -53,7 +53,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "300000", "gasPrice" : "1", @@ -116,7 +115,6 @@ } }, "transaction" : { - "//" : "testInfiniteLoop()", "data" : "0x296df0df", "gasLimit" : "300000", "gasPrice" : "1", @@ -188,7 +186,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "350000", "gasPrice" : "1", @@ -213,31 +210,31 @@ "post" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a90048063296df0df1460295780634893d88a146035578063981a316514604157005b602f604d565b60006000f35b603b6062565b60006000f35b6047605a565b60006000f35b5b600115605857604e565b565b60606062565b565b6068605a565b56", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463296df0df811460415780634893d88a14604d578063981a316514605957005b60476065565b60006000f35b6053607a565b60006000f35b605f6072565b60006000f35b5b6001156070576066565b565b6078607a565b565b60806072565b56", "nonce" : "0", "storage" : { } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "30000", + "balance" : "60000", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "470000", + "balance" : "440000", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "34c16a291d6bdb8a48cabda1af07fc654e147e715705b1fde0e4f86d021ca627", + "postStateRoot" : "28775a9bfb2082afcf55670f0cec3345867d51cf068580a38bb823d375e44f1a", "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a90048063296df0df1460295780634893d88a146035578063981a316514604157005b602f604d565b60006000f35b603b6062565b60006000f35b6047605a565b60006000f35b5b600115605857604e565b565b60606062565b565b6068605a565b56", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463296df0df811460415780634893d88a14604d578063981a316514605957005b60476065565b60006000f35b6053607a565b60006000f35b605f6072565b60006000f35b5b6001156070576066565b565b6078607a565b565b60806072565b56", "nonce" : "0", "storage" : { } @@ -251,9 +248,8 @@ } }, "transaction" : { - "//" : "testRecursiveMethods()", "data" : "0x981a3165", - "gasLimit" : "30000", + "gasLimit" : "60000", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -321,7 +317,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "350000", "gasPrice" : "1", @@ -384,7 +379,6 @@ } }, "transaction" : { - "//" : "run(uint256)", "data" : "0xa444f5e90000000000000000000000000000000000000000000000000000000000000204", "gasLimit" : "300000", "gasPrice" : "1", @@ -480,7 +474,6 @@ } }, "transaction" : { - "//" : "run(uint256)", "data" : "0xa444f5e90000000000000000000000000000000000000000000000000000000000000004", "gasLimit" : "300000", "gasPrice" : "1", @@ -505,31 +498,32 @@ "post" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100100", - "code" : "0x60003560e060020a90048063c040622614610021578063e97384dc1461003357005b610029610045565b8060005260206000f35b61003b610054565b8060005260206000f35b600061004f610054565b905090565b60006001905041600160a060020a0316732adc25665018aa1fe0e6bc666dac8fc2697ff9ba14156100845761008d565b60009050610172565b446302b8feb0141561009e576100a7565b60009050610172565b45683635c9adc5dea0000014156100bd576100c6565b60009050610172565b43607814156100d4576100dd565b60009050610172565b33600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561010757610110565b60009050610172565b346064141561011e57610127565b60009050610172565b3a600114156101355761013e565b60009050610172565b32600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561016857610171565b60009050610172565b5b9056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c04062268114610039578063e97384dc1461004b57005b61004161005d565b8060005260206000f35b61005361008c565b8060005260206000f35b600061006761008c565b600060006101000a81548160ff0219169083021790555060ff60016000540416905090565b6001732adc25665018aa1fe0e6bc666dac8fc2697ff9ba73ffffffffffffffffffffffffffffffffffffffff411614156100c5576100cd565b5060006101c7565b446302b8feb014156100de576100e6565b5060006101c7565b45683635c9adc5dea0000014156100fc57610104565b5060006101c7565b43607814156101125761011a565b5060006101c7565b5a503373ffffffffffffffffffffffffffffffffffffffff1673a94f5374fce5edbc8e2a8697c15331677e6ebf0b14156101535761015b565b5060006101c7565b346064141561016957610171565b5060006101c7565b3a6001141561017f57610187565b5060006101c7565b3273ffffffffffffffffffffffffffffffffffffffff1673a94f5374fce5edbc8e2a8697c15331677e6ebf0b14156101be576101c6565b5060006101c7565b5b9056", "nonce" : "0", "storage" : { + "0x" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "21820", + "balance" : "41878", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "978080", + "balance" : "958022", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "989a1a0c1eb8ea72f8bccba220d7aaacc7aa51171a0a1e753bbb03893367cbb1", + "postStateRoot" : "7cd344479a3d29c91dd9d9492f35811b5671e6a756a6c6dc223961fd34a1038e", "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a90048063c040622614610021578063e97384dc1461003357005b610029610045565b8060005260206000f35b61003b610054565b8060005260206000f35b600061004f610054565b905090565b60006001905041600160a060020a0316732adc25665018aa1fe0e6bc666dac8fc2697ff9ba14156100845761008d565b60009050610172565b446302b8feb0141561009e576100a7565b60009050610172565b45683635c9adc5dea0000014156100bd576100c6565b60009050610172565b43607814156100d4576100dd565b60009050610172565b33600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561010757610110565b60009050610172565b346064141561011e57610127565b60009050610172565b3a600114156101355761013e565b60009050610172565b32600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561016857610171565b60009050610172565b5b9056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c04062268114610039578063e97384dc1461004b57005b61004161005d565b8060005260206000f35b61005361008c565b8060005260206000f35b600061006761008c565b600060006101000a81548160ff0219169083021790555060ff60016000540416905090565b6001732adc25665018aa1fe0e6bc666dac8fc2697ff9ba73ffffffffffffffffffffffffffffffffffffffff411614156100c5576100cd565b5060006101c7565b446302b8feb014156100de576100e6565b5060006101c7565b45683635c9adc5dea0000014156100fc57610104565b5060006101c7565b43607814156101125761011a565b5060006101c7565b5a503373ffffffffffffffffffffffffffffffffffffffff1673a94f5374fce5edbc8e2a8697c15331677e6ebf0b14156101535761015b565b5060006101c7565b346064141561016957610171565b5060006101c7565b3a6001141561017f57610187565b5060006101c7565b3273ffffffffffffffffffffffffffffffffffffffff1673a94f5374fce5edbc8e2a8697c15331677e6ebf0b14156101be576101c6565b5060006101c7565b5b9056", "nonce" : "0", "storage" : { } @@ -543,7 +537,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "350000", "gasPrice" : "1", @@ -568,20 +561,21 @@ "post" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100001", - "code" : "0x60003560e060020a90048063c040622614610021578063ed973fe91461003357005b6100296100ac565b8060005260206000f35b61003b610045565b8060005260206000f35b6000600060606100bc600039606060006000f0905080600160a060020a031663b9c3d0a5602060008260e060020a026000526004600060008660325a03f161008957005b505060005160e11461009a576100a3565b600191506100a8565b600091505b5090565b60006100b6610045565b9050905600605480600c6000396000f30060003560e060020a90048062f55d9d14601e578063b9c3d0a514602d57005b6027600435603d565b60006000f35b6033604b565b8060005260206000f35b80600160a060020a0316ff50565b600060e190509056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c04062268114610039578063ed973fe91461004b57005b6100416100ea565b8060005260206000f35b61005361005d565b8060005260206000f35b60006000608161011a600039608160006000f0905073ffffffffffffffffffffffffffffffffffffffff811663b9c3d0a5602060007fb9c3d0a50000000000000000000000000000000000000000000000000000000081526004600060008660325a03f16100c757005b505060005160e1146100d8576100e1565b600191506100e6565b600091505b5090565b60006100f461005d565b600060006101000a81548160ff0219169083021790555060ff600160005404169050905600607580600c6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350462f55d9d81146036578063b9c3d0a514604557005b603f6004356055565b60006000f35b604b6070565b8060005260206000f35b8073ffffffffffffffffffffffffffffffffffffffff16ff50565b60e19056", "nonce" : "1", "storage" : { + "0x" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "70652", + "balance" : "97325", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "929347", + "balance" : "902674", "code" : "0x", "nonce" : "1", "storage" : { @@ -589,17 +583,17 @@ }, "d2571607e241ecf590ed94b12d87c94babe36db6" : { "balance" : "0", - "code" : "0x60003560e060020a90048062f55d9d14601e578063b9c3d0a514602d57005b6027600435603d565b60006000f35b6033604b565b8060005260206000f35b80600160a060020a0316ff50565b600060e190509056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350462f55d9d81146036578063b9c3d0a514604557005b603f6004356055565b60006000f35b604b6070565b8060005260206000f35b8073ffffffffffffffffffffffffffffffffffffffff16ff50565b60e19056", "nonce" : "0", "storage" : { } } }, - "postStateRoot" : "4443b958061e0151621819e559aba5e36640e0a46aba770d2f4431faa9f484f9", + "postStateRoot" : "8af7e668bc981aaa612683f34062e73fbcbb262d9394b199bdb08663d93c53c0", "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a90048063c040622614610021578063ed973fe91461003357005b6100296100ac565b8060005260206000f35b61003b610045565b8060005260206000f35b6000600060606100bc600039606060006000f0905080600160a060020a031663b9c3d0a5602060008260e060020a026000526004600060008660325a03f161008957005b505060005160e11461009a576100a3565b600191506100a8565b600091505b5090565b60006100b6610045565b9050905600605480600c6000396000f30060003560e060020a90048062f55d9d14601e578063b9c3d0a514602d57005b6027600435603d565b60006000f35b6033604b565b8060005260206000f35b80600160a060020a0316ff50565b600060e190509056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c04062268114610039578063ed973fe91461004b57005b6100416100ea565b8060005260206000f35b61005361005d565b8060005260206000f35b60006000608161011a600039608160006000f0905073ffffffffffffffffffffffffffffffffffffffff811663b9c3d0a5602060007fb9c3d0a50000000000000000000000000000000000000000000000000000000081526004600060008660325a03f16100c757005b505060005160e1146100d8576100e1565b600191506100e6565b600091505b5090565b60006100f461005d565b600060006101000a81548160ff0219169083021790555060ff600160005404169050905600607580600c6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350462f55d9d81146036578063b9c3d0a514604557005b603f6004356055565b60006000f35b604b6070565b8060005260206000f35b8073ffffffffffffffffffffffffffffffffffffffff16ff50565b60e19056", "nonce" : "0", "storage" : { } @@ -613,7 +607,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "350000", "gasPrice" : "1", @@ -638,31 +631,32 @@ "post" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100001", - "code" : "0x60003560e060020a90048063a60eedda14610021578063c04062261461003357005b610029610045565b8060005260206000f35b61003b6100eb565b8060005260206000f35b6000600060606100fb600039606060006000f0905080600160a060020a031662f55d9d600060008260e060020a02600052600441600160a060020a03168152602001600060008660325a03f161009757005b505080600160a060020a031663b9c3d0a5602060008260e060020a026000526004600060008660325a03f16100c857005b505060005160e1146100d9576100e2565b600191506100e7565b600091505b5090565b60006100f5610045565b9050905600605480600c6000396000f30060003560e060020a90048062f55d9d14601e578063b9c3d0a514602d57005b60276004356046565b60006000f35b6033603d565b8060005260206000f35b600060e1905090565b80600160a060020a0316ff5056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463a60eedda8114610039578063c04062261461004b57005b61004161005d565b8060005260206000f35b61005361015a565b8060005260206000f35b60006000608161018a600039608160006000f0905073ffffffffffffffffffffffffffffffffffffffff811662f55d9d6000807ef55d9d00000000000000000000000000000000000000000000000000000000825260044173ffffffffffffffffffffffffffffffffffffffff168152602001600060008660325a03f16100e057005b505073ffffffffffffffffffffffffffffffffffffffff811663b9c3d0a5602060007fb9c3d0a50000000000000000000000000000000000000000000000000000000081526004600060008660325a03f161013757005b505060005160e11461014857610151565b60019150610156565b600091505b5090565b600061016461005d565b600060006101000a81548160ff0219169083021790555060ff600160005404169050905600607580600c6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350462f55d9d81146036578063b9c3d0a514604557005b603f600435605a565b60006000f35b604b6055565b8060005260206000f35b60e190565b8073ffffffffffffffffffffffffffffffffffffffff16ff5056", "nonce" : "1", "storage" : { + "0x" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "47010", + "balance" : "73539", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "952989", + "balance" : "926460", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "2d0ec35a9c5c2ccba2bb561164abb54e54f7d83954f0f75284d9b8633fe00e37", + "postStateRoot" : "367a4e05a146eef4824adcbb8c7e445dc01852707762a005b01b97ce1eb8622f", "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a90048063a60eedda14610021578063c04062261461003357005b610029610045565b8060005260206000f35b61003b6100eb565b8060005260206000f35b6000600060606100fb600039606060006000f0905080600160a060020a031662f55d9d600060008260e060020a02600052600441600160a060020a03168152602001600060008660325a03f161009757005b505080600160a060020a031663b9c3d0a5602060008260e060020a026000526004600060008660325a03f16100c857005b505060005160e1146100d9576100e2565b600191506100e7565b600091505b5090565b60006100f5610045565b9050905600605480600c6000396000f30060003560e060020a90048062f55d9d14601e578063b9c3d0a514602d57005b60276004356046565b60006000f35b6033603d565b8060005260206000f35b600060e1905090565b80600160a060020a0316ff5056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463a60eedda8114610039578063c04062261461004b57005b61004161005d565b8060005260206000f35b61005361015a565b8060005260206000f35b60006000608161018a600039608160006000f0905073ffffffffffffffffffffffffffffffffffffffff811662f55d9d6000807ef55d9d00000000000000000000000000000000000000000000000000000000825260044173ffffffffffffffffffffffffffffffffffffffff168152602001600060008660325a03f16100e057005b505073ffffffffffffffffffffffffffffffffffffffff811663b9c3d0a5602060007fb9c3d0a50000000000000000000000000000000000000000000000000000000081526004600060008660325a03f161013757005b505060005160e11461014857610151565b60019150610156565b600091505b5090565b600061016461005d565b600060006101000a81548160ff0219169083021790555060ff600160005404169050905600607580600c6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350462f55d9d81146036578063b9c3d0a514604557005b603f600435605a565b60006000f35b604b6055565b8060005260206000f35b60e190565b8073ffffffffffffffffffffffffffffffffffffffff16ff5056", "nonce" : "0", "storage" : { } @@ -676,7 +670,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "350000", "gasPrice" : "1", @@ -697,35 +690,98 @@ }, "logs" : [ ], - "out" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "out" : "0x", "post" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "100100", - "code" : "0x60003560e060020a90048063c040622614610021578063e0a9fd281461003357005b610029610045565b8060005260206000f35b61003b610054565b8060005260206000f35b600061004f610054565b905090565b60006001905060007f74657374737472696e67000000000000000000000000000000000000000000008152600a017f030d40000000000000000000000000000000000000000000000000000000000081526003016000207f43c4b4524adb81e4e9a5c4648a98e9d320e3908ac5b6c889144b642cd08ae16d14156100d7576100e0565b60009050610218565b60026020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a017f030d4000000000000000000000000000000000000000000000000000000000008152600301600060008560325a03f161014457005b506000517f3c8727e019a42b444667a587b6001251becadabbb36bfed8087a92c18882d11114156101745761017d565b60009050610218565b60036020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a017f030d4000000000000000000000000000000000000000000000000000000000008152600301600060008560325a03f16101e157005b50600051600160a060020a031673cd566972b5e50104011a92b59fa8e0b1234851ae141561020e57610217565b60009050610218565b5b9056", + "balance" : "100000", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c04062268114610039578063e0a9fd281461004b57005b61004161005d565b8060005260206000f35b61005361008c565b8060005260206000f35b600061006761008c565b600060006101000a81548160ff0219169083021790555060ff60016000540416905090565b600160007f74657374737472696e67000000000000000000000000000000000000000000008152600a016000207f43c4b4524adb81e4e9a5c4648a98e9d320e3908ac5b6c889144b642cd08ae16d14156100e5576100ed565b5060006101da565b60026020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a01600060008560325a03f161012b57005b507f3c8727e019a42b444667a587b6001251becadabbb36bfed8087a92c18882d111600051141561015b57610163565b5060006101da565b60036020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a01600060008560325a03f16101a157005b507fcd566972b5e50104011a92b59fa8e0b1234851ae00000000000000000000000060005114156101d1576101d9565b5060006101da565b5b9056", "nonce" : "0", "storage" : { } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "21544", + "balance" : "35000000", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "49978356", + "balance" : "15000000", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "940c34c6de77d43cccaf37a27032388bc2725da017a49427d7992c315edd70c4", + "postStateRoot" : "278ae629f0005a2579ea98acd0189bcbf0a57969b0116c4db92eff9515f5f5fb", "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a90048063c040622614610021578063e0a9fd281461003357005b610029610045565b8060005260206000f35b61003b610054565b8060005260206000f35b600061004f610054565b905090565b60006001905060007f74657374737472696e67000000000000000000000000000000000000000000008152600a017f030d40000000000000000000000000000000000000000000000000000000000081526003016000207f43c4b4524adb81e4e9a5c4648a98e9d320e3908ac5b6c889144b642cd08ae16d14156100d7576100e0565b60009050610218565b60026020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a017f030d4000000000000000000000000000000000000000000000000000000000008152600301600060008560325a03f161014457005b506000517f3c8727e019a42b444667a587b6001251becadabbb36bfed8087a92c18882d11114156101745761017d565b60009050610218565b60036020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a017f030d4000000000000000000000000000000000000000000000000000000000008152600301600060008560325a03f16101e157005b50600051600160a060020a031673cd566972b5e50104011a92b59fa8e0b1234851ae141561020e57610217565b60009050610218565b5b9056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c04062268114610039578063e0a9fd281461004b57005b61004161005d565b8060005260206000f35b61005361008c565b8060005260206000f35b600061006761008c565b600060006101000a81548160ff0219169083021790555060ff60016000540416905090565b600160007f74657374737472696e67000000000000000000000000000000000000000000008152600a016000207f43c4b4524adb81e4e9a5c4648a98e9d320e3908ac5b6c889144b642cd08ae16d14156100e5576100ed565b5060006101da565b60026020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a01600060008560325a03f161012b57005b507f3c8727e019a42b444667a587b6001251becadabbb36bfed8087a92c18882d111600051141561015b57610163565b5060006101da565b60036020600060007f74657374737472696e67000000000000000000000000000000000000000000008152600a01600060008560325a03f16101a157005b507fcd566972b5e50104011a92b59fa8e0b1234851ae00000000000000000000000060005114156101d1576101d9565b5060006101da565b5b9056", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "50000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0xc0406226", + "gasLimit" : "35000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100" + } + }, + "TestCryptographicFunctionsREM" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000000000000000000", + "currentNumber" : "120", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x0000000000000000000000000000000000000000000000000000000000000001", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100100", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c040622681146037578063e0a9fd2814604757005b603d60bc565b8060005260206000f35b604d6057565b8060005260206000f35b600160007f74657374737472696e67000000000000000000000000000000000000000000008152600a016000207f43c4b4524adb81e4e9a5c4648a98e9d320e3908ac5b6c889144b642cd08ae16d600102141560b15760b8565b50600060b9565b5b90565b600060c46057565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016821790555060ff6000541690509056", + "nonce" : "0", + "storage" : { + "0x" : "0x01" + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "41624", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "49958276", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "f8bddcc3fceb378c6b63f774547e8e60375ba8477dbbe000fc83988151198028", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100000", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463c040622681146037578063e0a9fd2814604757005b603d60bc565b8060005260206000f35b604d6057565b8060005260206000f35b600160007f74657374737472696e67000000000000000000000000000000000000000000008152600a016000207f43c4b4524adb81e4e9a5c4648a98e9d320e3908ac5b6c889144b642cd08ae16d600102141560b15760b8565b50600060b9565b5b90565b600060c46057565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016821790555060ff6000541690509056", "nonce" : "0", "storage" : { } @@ -739,7 +795,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "35000000", "gasPrice" : "1", @@ -764,31 +819,32 @@ "post" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100001", - "code" : "0x60003560e060020a90048063380e439614601f578063c040622614602f57005b6025603f565b8060005260206000f35b603560f0565b8060005260206000f35b60006000600060009150600092508160001460585760d3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe782131560ca575b600a82121560945781806001019250506080565b81600a14609f5760c6565b600a90505b60008160ff16111560c55781806001900392505080806001900391505060a4565b5b60d2565b6000925060eb565b5b8160001460de5760e6565b6001925060eb565b600092505b505090565b600060f8603f565b90509056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463380e439681146037578063c040622614604757005b603d6084565b8060005260206000f35b604d6057565b8060005260206000f35b6000605f6084565b600060006101000a81548160ff0219169083021790555060ff60016000540416905090565b6000808160011560cd575b600a82121560a157600190910190608f565b81600a1460ac5760c9565b50600a5b60008160ff16111560c85760019182900391900360b0565b5b60d5565b6000925060ed565b8160001460e05760e8565b6001925060ed565b600092505b50509056", "nonce" : "0", "storage" : { + "0x" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "23092", + "balance" : "42952", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "976907", + "balance" : "957047", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "9f6ebe6ef8a7b6bbf49e7bd85f60b5755d27454b887d000be929c6bcbe3775cc", + "postStateRoot" : "5d9414ffd30ec040a59e0a99b7a54097306ee5d426bd8adf8e5a99490ad083c5", "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a90048063380e439614601f578063c040622614602f57005b6025603f565b8060005260206000f35b603560f0565b8060005260206000f35b60006000600060009150600092508160001460585760d3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe782131560ca575b600a82121560945781806001019250506080565b81600a14609f5760c6565b600a90505b60008160ff16111560c55781806001900392505080806001900391505060a4565b5b60d2565b6000925060eb565b5b8160001460de5760e6565b6001925060eb565b600092505b505090565b600060f8603f565b90509056", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463380e439681146037578063c040622614604757005b603d6084565b8060005260206000f35b604d6057565b8060005260206000f35b6000605f6084565b600060006101000a81548160ff0219169083021790555060ff60016000540416905090565b6000808160011560cd575b600a82121560a157600190910190608f565b81600a1460ac5760c9565b50600a5b60008160ff16111560c85760019182900391900360b0565b5b60d5565b6000925060ed565b8160001460e05760e8565b6001925060ed565b600092505b50509056", "nonce" : "0", "storage" : { } @@ -802,7 +858,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "350000", "gasPrice" : "1", @@ -827,36 +882,37 @@ "post" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100100", - "code" : "0x60003560e060020a900480632a9afb8314610021578063c04062261461003357005b610029610045565b8060005260206000f35b61003b610136565b8060005260206000f35b60006001905060005460ff141561005b57610064565b60009050610133565b60025460005414156100755761007e565b60009050610133565b600154600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b14156100aa576100b3565b60009050610133565b6003547f676c6f62616c2064617461203332206c656e67746820737472696e670000000014156100e2576100eb565b60009050610133565b600460006000815260200190815260200160002054600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561012957610132565b60009050610133565b5b90565b600060ff60008190555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b60018190555060ff6002819055507f676c6f62616c2064617461203332206c656e67746820737472696e670000000060038190555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b6004600060008152602001908152602001600020819055506101bf610045565b90509056", + "code" : "0x7c010000000000000000000000000000000000000000000000000000000060003504632a9afb838114610039578063c04062261461004b57005b61004161005d565b8060005260206000f35b61005361016c565b8060005260206000f35b600160ff8154141561006e57610076565b506000610169565b60015460035414156100875761008f565b506000610169565b73a94f5374fce5edbc8e2a8697c15331677e6ebf0b73ffffffffffffffffffffffffffffffffffffffff60016002540481161614156100cd576100d5565b506000610169565b7f676c6f62616c2064617461203332206c656e67746820737472696e670000000060045414156101045761010c565b506000610169565b6005600080815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561016057610168565b506000610169565b5b90565b600060ff806001555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b6002805473ffffffffffffffffffffffffffffffffffffffff1916821790555060ff80600355507f676c6f62616c2064617461203332206c656e67746820737472696e6700000000806004555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b6005600080815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555061022f61005d565b600060006101000a81548160ff0219169083021790555060ff6001600054041690509056", "nonce" : "0", "storage" : { - "0x" : "0xff", - "0x01" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "0x02" : "0xff", - "0x03" : "0x676c6f62616c2064617461203332206c656e67746820737472696e6700000000", - "0x17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + "0x" : "0x01", + "0x01" : "0xff", + "0x02" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x03" : "0xff", + "0x04" : "0x676c6f62616c2064617461203332206c656e67746820737472696e6700000000", + "0x05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "122233", + "balance" : "142513", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "877667", + "balance" : "857387", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "cd199efc068169fa69288eea1531f3eee70c842750f58d1b873fc493ab4e8a80", + "postStateRoot" : "fabbcefefcd34f324da40464c4bd8df7a21d379e0a897796d290a2b49e974e88", "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", - "code" : "0x60003560e060020a900480632a9afb8314610021578063c04062261461003357005b610029610045565b8060005260206000f35b61003b610136565b8060005260206000f35b60006001905060005460ff141561005b57610064565b60009050610133565b60025460005414156100755761007e565b60009050610133565b600154600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b14156100aa576100b3565b60009050610133565b6003547f676c6f62616c2064617461203332206c656e67746820737472696e670000000014156100e2576100eb565b60009050610133565b600460006000815260200190815260200160002054600160a060020a031673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561012957610132565b60009050610133565b5b90565b600060ff60008190555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b60018190555060ff6002819055507f676c6f62616c2064617461203332206c656e67746820737472696e670000000060038190555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b6004600060008152602001908152602001600020819055506101bf610045565b90509056", + "code" : "0x7c010000000000000000000000000000000000000000000000000000000060003504632a9afb838114610039578063c04062261461004b57005b61004161005d565b8060005260206000f35b61005361016c565b8060005260206000f35b600160ff8154141561006e57610076565b506000610169565b60015460035414156100875761008f565b506000610169565b73a94f5374fce5edbc8e2a8697c15331677e6ebf0b73ffffffffffffffffffffffffffffffffffffffff60016002540481161614156100cd576100d5565b506000610169565b7f676c6f62616c2064617461203332206c656e67746820737472696e670000000060045414156101045761010c565b506000610169565b6005600080815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673a94f5374fce5edbc8e2a8697c15331677e6ebf0b141561016057610168565b506000610169565b5b90565b600060ff806001555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b6002805473ffffffffffffffffffffffffffffffffffffffff1916821790555060ff80600355507f676c6f62616c2064617461203332206c656e67746820737472696e6700000000806004555073a94f5374fce5edbc8e2a8697c15331677e6ebf0b6005600080815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555061022f61005d565b600060006101000a81548160ff0219169083021790555060ff6001600054041690509056", "nonce" : "0", "storage" : { } @@ -870,7 +926,6 @@ } }, "transaction" : { - "//" : "run()", "data" : "0xc0406226", "gasLimit" : "350000", "gasPrice" : "1", From 3a948b2dbaf22409507a2d3244032751b76432bb Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Tue, 31 Mar 2015 17:39:58 +0200 Subject: [PATCH 10/50] Add hexdata and hexnum types --- rpc/messages.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/rpc/messages.go b/rpc/messages.go index 5c498234f9..108a07ed8f 100644 --- a/rpc/messages.go +++ b/rpc/messages.go @@ -19,8 +19,84 @@ package rpc import ( "encoding/json" "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/common" ) +type hexdata struct { + data []byte +} + +func (d *hexdata) MarshalJSON() ([]byte, error) { + v := common.Bytes2Hex(d.data) + return json.Marshal("0x" + v) +} + +func (d *hexdata) UnmarshalJSON(b []byte) (err error) { + d.data = common.FromHex(string(b)) + return nil +} + +func newHexData(input interface{}) *hexdata { + d := new(hexdata) + + switch input.(type) { + case []byte: + d.data = input.([]byte) + case common.Hash: + d.data = input.(common.Hash).Bytes() + case common.Address: + d.data = input.(common.Address).Bytes() + case *big.Int: + d.data = input.(*big.Int).Bytes() + case int64: + d.data = big.NewInt(input.(int64)).Bytes() + case uint64: + d.data = big.NewInt(int64(input.(uint64))).Bytes() + case int: + d.data = big.NewInt(int64(input.(int))).Bytes() + case uint: + d.data = big.NewInt(int64(input.(uint))).Bytes() + case string: + d.data = common.Big(input.(string)).Bytes() + default: + d.data = nil + } + + return d +} + +type hexnum struct { + data []byte +} + +func (d *hexnum) MarshalJSON() ([]byte, error) { + // Get hex string from bytes + out := common.Bytes2Hex(d.data) + // Trim leading 0s + out = strings.Trim(out, "0") + // Output "0x0" when value is 0 + if len(out) == 0 { + out = "0" + } + return json.Marshal("0x" + out) +} + +func (d *hexnum) UnmarshalJSON(b []byte) (err error) { + d.data = common.FromHex(string(b)) + return nil +} + +func newHexNum(input interface{}) *hexnum { + d := new(hexnum) + + d.data = newHexData(input).data + + return d +} + type InvalidTypeError struct { method string msg string From 81aeb789765cde7d84dc8aa74a6cab0851ce8503 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Tue, 31 Mar 2015 17:40:35 +0200 Subject: [PATCH 11/50] Update output types to use hexnum or hexdata Benefits from automatic output formatting differences between quantities and data --- rpc/responses.go | 210 ++++++++++++++++++++++-------------------- rpc/responses_test.go | 8 +- 2 files changed, 112 insertions(+), 106 deletions(-) diff --git a/rpc/responses.go b/rpc/responses.go index 9767cac3b2..d2a6c2984b 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -36,45 +36,45 @@ type BlockRes struct { func (b *BlockRes) MarshalJSON() ([]byte, error) { var ext struct { - BlockNumber string `json:"number"` - BlockHash string `json:"hash"` - ParentHash string `json:"parentHash"` - Nonce string `json:"nonce"` - Sha3Uncles string `json:"sha3Uncles"` - LogsBloom string `json:"logsBloom"` - TransactionRoot string `json:"transactionRoot"` - StateRoot string `json:"stateRoot"` - Miner string `json:"miner"` - Difficulty string `json:"difficulty"` - TotalDifficulty string `json:"totalDifficulty"` - Size string `json:"size"` - ExtraData string `json:"extraData"` - GasLimit string `json:"gasLimit"` - MinGasPrice string `json:"minGasPrice"` - GasUsed string `json:"gasUsed"` - UnixTimestamp string `json:"timestamp"` + BlockNumber *hexnum `json:"number"` + BlockHash *hexdata `json:"hash"` + ParentHash *hexdata `json:"parentHash"` + Nonce *hexnum `json:"nonce"` + Sha3Uncles *hexdata `json:"sha3Uncles"` + LogsBloom *hexdata `json:"logsBloom"` + TransactionRoot *hexdata `json:"transactionRoot"` + StateRoot *hexdata `json:"stateRoot"` + Miner *hexdata `json:"miner"` + Difficulty *hexnum `json:"difficulty"` + TotalDifficulty *hexnum `json:"totalDifficulty"` + Size *hexnum `json:"size"` + ExtraData *hexdata `json:"extraData"` + GasLimit *hexnum `json:"gasLimit"` + MinGasPrice *hexnum `json:"minGasPrice"` + GasUsed *hexnum `json:"gasUsed"` + UnixTimestamp *hexnum `json:"timestamp"` Transactions []interface{} `json:"transactions"` - Uncles []string `json:"uncles"` + Uncles []*hexdata `json:"uncles"` } // convert strict types to hexified strings - ext.BlockNumber = common.ToHex(b.BlockNumber.Bytes()) - ext.BlockHash = b.BlockHash.Hex() - ext.ParentHash = b.ParentHash.Hex() - ext.Nonce = common.ToHex(b.Nonce[:]) - ext.Sha3Uncles = b.Sha3Uncles.Hex() - ext.LogsBloom = common.ToHex(b.LogsBloom[:]) - ext.TransactionRoot = b.TransactionRoot.Hex() - ext.StateRoot = b.StateRoot.Hex() - ext.Miner = b.Miner.Hex() - ext.Difficulty = common.ToHex(b.Difficulty.Bytes()) - ext.TotalDifficulty = common.ToHex(b.TotalDifficulty.Bytes()) - ext.Size = common.ToHex(b.Size.Bytes()) - ext.ExtraData = common.ToHex(b.ExtraData) - ext.GasLimit = common.ToHex(b.GasLimit.Bytes()) - // ext.MinGasPrice = common.ToHex(big.NewInt(b.MinGasPrice).Bytes()) - ext.GasUsed = common.ToHex(b.GasUsed.Bytes()) - ext.UnixTimestamp = common.ToHex(big.NewInt(b.UnixTimestamp).Bytes()) + ext.BlockNumber = newHexNum(b.BlockNumber.Bytes()) + ext.BlockHash = newHexData(b.BlockHash.Bytes()) + ext.ParentHash = newHexData(b.ParentHash.Bytes()) + ext.Nonce = newHexNum(b.Nonce[:]) + ext.Sha3Uncles = newHexData(b.Sha3Uncles.Bytes()) + ext.LogsBloom = newHexData(b.LogsBloom.Bytes()) + ext.TransactionRoot = newHexData(b.TransactionRoot.Bytes()) + ext.StateRoot = newHexData(b.StateRoot.Bytes()) + ext.Miner = newHexData(b.Miner.Bytes()) + ext.Difficulty = newHexNum(b.Difficulty.Bytes()) + ext.TotalDifficulty = newHexNum(b.TotalDifficulty.Bytes()) + ext.Size = newHexNum(b.Size.Bytes()) + ext.ExtraData = newHexData(b.ExtraData) + ext.GasLimit = newHexNum(b.GasLimit.Bytes()) + // ext.MinGasPrice = newHexNum(big.NewInt(b.MinGasPrice).Bytes()) + ext.GasUsed = newHexNum(b.GasUsed.Bytes()) + ext.UnixTimestamp = newHexNum(big.NewInt(b.UnixTimestamp).Bytes()) ext.Transactions = make([]interface{}, len(b.Transactions)) if b.fullTx { for i, tx := range b.Transactions { @@ -82,12 +82,12 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) { } } else { for i, tx := range b.Transactions { - ext.Transactions[i] = tx.Hash.Hex() + ext.Transactions[i] = newHexData(tx.Hash.Bytes()) } } - ext.Uncles = make([]string, len(b.Uncles)) + ext.Uncles = make([]*hexdata, len(b.Uncles)) for i, v := range b.Uncles { - ext.Uncles[i] = v.Hex() + ext.Uncles[i] = newHexData(v.Bytes()) } return json.Marshal(ext) @@ -134,9 +134,9 @@ func NewBlockRes(block *types.Block) *BlockRes { type TransactionRes struct { Hash common.Hash `json:"hash"` Nonce uint64 `json:"nonce"` - BlockHash common.Hash `json:"blockHash,omitempty"` - BlockNumber int64 `json:"blockNumber,omitempty"` - TxIndex int64 `json:"transactionIndex,omitempty"` + BlockHash common.Hash `json:"blockHash"` + BlockNumber int64 `json:"blockNumber"` + TxIndex int64 `json:"transactionIndex"` From common.Address `json:"from"` To *common.Address `json:"to"` Value *big.Int `json:"value"` @@ -147,34 +147,30 @@ type TransactionRes struct { func (t *TransactionRes) MarshalJSON() ([]byte, error) { var ext struct { - Hash string `json:"hash"` - Nonce string `json:"nonce"` - BlockHash string `json:"blockHash,omitempty"` - BlockNumber string `json:"blockNumber,omitempty"` - TxIndex string `json:"transactionIndex,omitempty"` - From string `json:"from"` - To interface{} `json:"to"` - Value string `json:"value"` - Gas string `json:"gas"` - GasPrice string `json:"gasPrice"` - Input string `json:"input"` + 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"` } - ext.Hash = t.Hash.Hex() - ext.Nonce = common.ToHex(big.NewInt(int64(t.Nonce)).Bytes()) - ext.BlockHash = t.BlockHash.Hex() - ext.BlockNumber = common.ToHex(big.NewInt(t.BlockNumber).Bytes()) - ext.TxIndex = common.ToHex(big.NewInt(t.TxIndex).Bytes()) - ext.From = t.From.Hex() - if t.To == nil { - ext.To = nil - } else { - ext.To = t.To.Hex() - } - ext.Value = common.ToHex(t.Value.Bytes()) - ext.Gas = common.ToHex(t.Gas.Bytes()) - ext.GasPrice = common.ToHex(t.GasPrice.Bytes()) - ext.Input = common.ToHex(t.Input) + ext.Hash = newHexData(t.Hash.Bytes()) + ext.Nonce = newHexNum(big.NewInt(int64(t.Nonce)).Bytes()) + ext.BlockHash = newHexData(t.BlockHash.Bytes()) + ext.BlockNumber = newHexNum(big.NewInt(t.BlockNumber).Bytes()) + ext.TxIndex = newHexNum(big.NewInt(t.TxIndex).Bytes()) + ext.From = newHexData(t.From.Bytes()) + ext.To = newHexData(t.To.Bytes()) + ext.Value = newHexNum(t.Value.Bytes()) + ext.Gas = newHexNum(t.Gas.Bytes()) + ext.GasPrice = newHexNum(t.GasPrice.Bytes()) + ext.Input = newHexData(t.Input) return json.Marshal(ext) } @@ -192,34 +188,39 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes { 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 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 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 LogRes struct { - Address common.Address `json:"address"` - Topics []common.Hash `json:"topics"` - Data []byte `json:"data"` - Number uint64 `json:"number"` + Address common.Address `json:"address"` + Topics []common.Hash `json:"topics"` + Data []byte `json:"data"` + BlockNumber uint64 `json:"blockNumber"` + Hash common.Hash `json:"hash"` + LogIndex uint64 `json:"logIndex"` + BlockHash common.Hash `json:"blockHash"` + TransactionHash common.Hash `json:"transactionHash"` + TransactionIndex uint64 `json:"transactionIndex"` } func NewLogRes(log state.Log) LogRes { @@ -227,7 +228,7 @@ func NewLogRes(log state.Log) LogRes { l.Topics = make([]common.Hash, len(log.Topics())) l.Address = log.Address() l.Data = log.Data() - l.Number = log.Number() + l.BlockNumber = log.Number() for j, topic := range log.Topics() { l.Topics[j] = topic } @@ -236,18 +237,23 @@ func NewLogRes(log state.Log) LogRes { func (l *LogRes) MarshalJSON() ([]byte, error) { var ext struct { - Address string `json:"address"` - Topics []string `json:"topics"` - Data string `json:"data"` - Number string `json:"number"` + Address *hexdata `json:"address"` + Topics []*hexdata `json:"topics"` + Data *hexdata `json:"data"` + BlockNumber *hexnum `json:"blockNumber"` + Hash *hexdata `json:"hash"` + LogIndex *hexnum `json:"logIndex"` + BlockHash *hexdata `json:"blockHash"` + TransactionHash *hexdata `json:"transactionHash"` + TransactionIndex *hexnum `json:"transactionIndex"` } - ext.Address = l.Address.Hex() - ext.Data = common.ToHex(l.Data) - ext.Number = common.ToHex(big.NewInt(int64(l.Number)).Bytes()) - ext.Topics = make([]string, len(l.Topics)) + ext.Address = newHexData(l.Address.Bytes()) + ext.Data = newHexData(l.Data) + ext.BlockNumber = newHexNum(l.BlockNumber) + ext.Topics = make([]*hexdata, len(l.Topics)) for i, v := range l.Topics { - ext.Topics[i] = v.Hex() + ext.Topics[i] = newHexData(v) } return json.Marshal(ext) diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 2789398307..80e97a7531 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -88,10 +88,10 @@ func TestLogRes(t *testing.T) { topics = append(topics, common.HexToHash("0x20")) v := &LogRes{ - Topics: topics, - Address: common.HexToAddress("0x0"), - Data: []byte{1, 2, 3}, - Number: uint64(5), + Topics: topics, + Address: common.HexToAddress("0x0"), + Data: []byte{1, 2, 3}, + BlockNumber: uint64(5), } _, _ = json.Marshal(v) From 8f0e095f4c269c48ac2c182c891e6346929de57b Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Tue, 31 Mar 2015 17:56:06 +0200 Subject: [PATCH 12/50] Index is zero-based #607 --- rpc/api.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index 5020791777..bce9a46e76 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -213,7 +213,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err br := NewBlockRes(block) br.fullTx = true - if args.Index > int64(len(br.Transactions)) || args.Index < 0 { + if args.Index >= int64(len(br.Transactions)) || args.Index < 0 { return NewValidationError("Index", "does not exist") } *reply = br.Transactions[args.Index] @@ -227,7 +227,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err v := NewBlockRes(block) v.fullTx = true - if args.Index > int64(len(v.Transactions)) || args.Index < 0 { + if args.Index >= int64(len(v.Transactions)) || args.Index < 0 { return NewValidationError("Index", "does not exist") } *reply = v.Transactions[args.Index] @@ -239,7 +239,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err br := NewBlockRes(api.xeth().EthBlockByHash(args.Hash)) - if args.Index > int64(len(br.Uncles)) || args.Index < 0 { + if args.Index >= int64(len(br.Uncles)) || args.Index < 0 { return NewValidationError("Index", "does not exist") } @@ -257,7 +257,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err v := NewBlockRes(block) v.fullTx = true - if args.Index > int64(len(v.Uncles)) || args.Index < 0 { + if args.Index >= int64(len(v.Uncles)) || args.Index < 0 { return NewValidationError("Index", "does not exist") } From a2501ecfcd0709db8bd43ecdc4077d072230fb28 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Tue, 31 Mar 2015 19:02:46 +0200 Subject: [PATCH 13/50] Make new types Stringers --- rpc/messages.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/rpc/messages.go b/rpc/messages.go index 108a07ed8f..1ad41654b2 100644 --- a/rpc/messages.go +++ b/rpc/messages.go @@ -29,9 +29,12 @@ type hexdata struct { data []byte } +func (d *hexdata) String() string { + return "0x" + common.Bytes2Hex(d.data) +} + func (d *hexdata) MarshalJSON() ([]byte, error) { - v := common.Bytes2Hex(d.data) - return json.Marshal("0x" + v) + return json.Marshal(d.String()) } func (d *hexdata) UnmarshalJSON(b []byte) (err error) { @@ -72,7 +75,7 @@ type hexnum struct { data []byte } -func (d *hexnum) MarshalJSON() ([]byte, error) { +func (d *hexnum) String() string { // Get hex string from bytes out := common.Bytes2Hex(d.data) // Trim leading 0s @@ -81,7 +84,11 @@ func (d *hexnum) MarshalJSON() ([]byte, error) { if len(out) == 0 { out = "0" } - return json.Marshal("0x" + out) + return "0x" + out +} + +func (d *hexnum) MarshalJSON() ([]byte, error) { + return json.Marshal(d.String()) } func (d *hexnum) UnmarshalJSON(b []byte) (err error) { From 7e3875b52720bf7456c9dd6162caeb7250d3686e Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Tue, 31 Mar 2015 19:04:02 +0200 Subject: [PATCH 14/50] Remove custom MarshalJSON methods Now formats based on underlying hexdata or hexnum type. Fields directly with respective constructors that cover from native types --- rpc/api.go | 4 +- rpc/responses.go | 278 +++++++++++++----------------------------- rpc/responses_test.go | 204 +++++++++++++++---------------- 3 files changed, 187 insertions(+), 299 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index bce9a46e76..3f5d33da6e 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -244,7 +244,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } uhash := br.Uncles[args.Index] - uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex())) + uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String())) *reply = uncle case "eth_getUncleByBlockNumberAndIndex": @@ -262,7 +262,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } uhash := v.Uncles[args.Index] - uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex())) + uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String())) *reply = uncle case "eth_getCompilers": diff --git a/rpc/responses.go b/rpc/responses.go index d2a6c2984b..3e9293fbb1 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -1,11 +1,6 @@ package rpc import ( - "encoding/json" - // "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" ) @@ -13,84 +8,25 @@ import ( type BlockRes struct { fullTx bool - BlockNumber *big.Int `json:"number"` - BlockHash common.Hash `json:"hash"` - ParentHash common.Hash `json:"parentHash"` - Nonce [8]byte `json:"nonce"` - Sha3Uncles common.Hash `json:"sha3Uncles"` - LogsBloom types.Bloom `json:"logsBloom"` - TransactionRoot common.Hash `json:"transactionRoot"` - StateRoot common.Hash `json:"stateRoot"` - Miner common.Address `json:"miner"` - Difficulty *big.Int `json:"difficulty"` - TotalDifficulty *big.Int `json:"totalDifficulty"` - Size *big.Int `json:"size"` - ExtraData []byte `json:"extraData"` - GasLimit *big.Int `json:"gasLimit"` - MinGasPrice int64 `json:"minGasPrice"` - GasUsed *big.Int `json:"gasUsed"` - UnixTimestamp int64 `json:"timestamp"` + BlockNumber *hexnum `json:"number"` + BlockHash *hexdata `json:"hash"` + ParentHash *hexdata `json:"parentHash"` + Nonce *hexnum `json:"nonce"` + Sha3Uncles *hexdata `json:"sha3Uncles"` + LogsBloom *hexdata `json:"logsBloom"` + TransactionRoot *hexdata `json:"transactionRoot"` + StateRoot *hexdata `json:"stateRoot"` + Miner *hexdata `json:"miner"` + Difficulty *hexnum `json:"difficulty"` + TotalDifficulty *hexnum `json:"totalDifficulty"` + Size *hexnum `json:"size"` + ExtraData *hexdata `json:"extraData"` + GasLimit *hexnum `json:"gasLimit"` + MinGasPrice *hexnum `json:"minGasPrice"` + GasUsed *hexnum `json:"gasUsed"` + UnixTimestamp *hexnum `json:"timestamp"` Transactions []*TransactionRes `json:"transactions"` - Uncles []common.Hash `json:"uncles"` -} - -func (b *BlockRes) MarshalJSON() ([]byte, error) { - var ext struct { - BlockNumber *hexnum `json:"number"` - BlockHash *hexdata `json:"hash"` - ParentHash *hexdata `json:"parentHash"` - Nonce *hexnum `json:"nonce"` - Sha3Uncles *hexdata `json:"sha3Uncles"` - LogsBloom *hexdata `json:"logsBloom"` - TransactionRoot *hexdata `json:"transactionRoot"` - StateRoot *hexdata `json:"stateRoot"` - Miner *hexdata `json:"miner"` - Difficulty *hexnum `json:"difficulty"` - TotalDifficulty *hexnum `json:"totalDifficulty"` - Size *hexnum `json:"size"` - ExtraData *hexdata `json:"extraData"` - GasLimit *hexnum `json:"gasLimit"` - MinGasPrice *hexnum `json:"minGasPrice"` - GasUsed *hexnum `json:"gasUsed"` - UnixTimestamp *hexnum `json:"timestamp"` - Transactions []interface{} `json:"transactions"` - Uncles []*hexdata `json:"uncles"` - } - - // convert strict types to hexified strings - ext.BlockNumber = newHexNum(b.BlockNumber.Bytes()) - ext.BlockHash = newHexData(b.BlockHash.Bytes()) - ext.ParentHash = newHexData(b.ParentHash.Bytes()) - ext.Nonce = newHexNum(b.Nonce[:]) - ext.Sha3Uncles = newHexData(b.Sha3Uncles.Bytes()) - ext.LogsBloom = newHexData(b.LogsBloom.Bytes()) - ext.TransactionRoot = newHexData(b.TransactionRoot.Bytes()) - ext.StateRoot = newHexData(b.StateRoot.Bytes()) - ext.Miner = newHexData(b.Miner.Bytes()) - ext.Difficulty = newHexNum(b.Difficulty.Bytes()) - ext.TotalDifficulty = newHexNum(b.TotalDifficulty.Bytes()) - ext.Size = newHexNum(b.Size.Bytes()) - ext.ExtraData = newHexData(b.ExtraData) - ext.GasLimit = newHexNum(b.GasLimit.Bytes()) - // ext.MinGasPrice = newHexNum(big.NewInt(b.MinGasPrice).Bytes()) - ext.GasUsed = newHexNum(b.GasUsed.Bytes()) - ext.UnixTimestamp = newHexNum(big.NewInt(b.UnixTimestamp).Bytes()) - ext.Transactions = make([]interface{}, len(b.Transactions)) - if b.fullTx { - for i, tx := range b.Transactions { - ext.Transactions[i] = tx - } - } else { - for i, tx := range b.Transactions { - ext.Transactions[i] = newHexData(tx.Hash.Bytes()) - } - } - ext.Uncles = make([]*hexdata, len(b.Uncles)) - for i, v := range b.Uncles { - ext.Uncles[i] = newHexData(v.Bytes()) - } - - return json.Marshal(ext) + Uncles []*hexdata `json:"uncles"` } func NewBlockRes(block *types.Block) *BlockRes { @@ -99,92 +35,67 @@ func NewBlockRes(block *types.Block) *BlockRes { } res := new(BlockRes) - res.BlockNumber = block.Number() - res.BlockHash = block.Hash() - res.ParentHash = block.ParentHash() - res.Nonce = block.Header().Nonce - res.Sha3Uncles = block.Header().UncleHash - res.LogsBloom = block.Bloom() - res.TransactionRoot = block.Header().TxHash - res.StateRoot = block.Root() - res.Miner = block.Header().Coinbase - res.Difficulty = block.Difficulty() - res.TotalDifficulty = block.Td - res.Size = big.NewInt(int64(block.Size())) - res.ExtraData = []byte(block.Header().Extra) - res.GasLimit = block.GasLimit() + res.BlockNumber = newHexNum(block.Number()) + res.BlockHash = newHexData(block.Hash()) + res.ParentHash = newHexData(block.ParentHash()) + res.Nonce = newHexNum(block.Header().Nonce) + res.Sha3Uncles = newHexData(block.Header().UncleHash) + res.LogsBloom = newHexData(block.Bloom()) + res.TransactionRoot = newHexData(block.Header().TxHash) + res.StateRoot = newHexData(block.Root()) + res.Miner = newHexData(block.Header().Coinbase) + res.Difficulty = newHexNum(block.Difficulty()) + res.TotalDifficulty = newHexNum(block.Td) + res.Size = newHexNum(block.Size()) + res.ExtraData = newHexData(block.Header().Extra) + res.GasLimit = newHexNum(block.GasLimit()) // res.MinGasPrice = - res.GasUsed = block.GasUsed() - res.UnixTimestamp = block.Time() - res.Transactions = make([]*TransactionRes, len(block.Transactions())) - for i, tx := range block.Transactions() { - v := NewTransactionRes(tx) - v.BlockHash = block.Hash() - v.BlockNumber = block.Number().Int64() - v.TxIndex = int64(i) - res.Transactions[i] = v - } - res.Uncles = make([]common.Hash, len(block.Uncles())) + res.GasUsed = newHexNum(block.GasUsed()) + res.UnixTimestamp = newHexNum(block.Time()) + res.Transactions = NewTransactionsRes(block.Transactions()) + res.Uncles = make([]*hexdata, len(block.Uncles())) for i, uncle := range block.Uncles() { - res.Uncles[i] = uncle.Hash() + res.Uncles[i] = newHexData(uncle.Hash()) } return res } type TransactionRes struct { - Hash common.Hash `json:"hash"` - Nonce uint64 `json:"nonce"` - BlockHash common.Hash `json:"blockHash"` - BlockNumber int64 `json:"blockNumber"` - TxIndex int64 `json:"transactionIndex"` - From common.Address `json:"from"` - To *common.Address `json:"to"` - Value *big.Int `json:"value"` - Gas *big.Int `json:"gas"` - GasPrice *big.Int `json:"gasPrice"` - Input []byte `json:"input"` -} - -func (t *TransactionRes) MarshalJSON() ([]byte, error) { - var ext 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"` - } - - ext.Hash = newHexData(t.Hash.Bytes()) - ext.Nonce = newHexNum(big.NewInt(int64(t.Nonce)).Bytes()) - ext.BlockHash = newHexData(t.BlockHash.Bytes()) - ext.BlockNumber = newHexNum(big.NewInt(t.BlockNumber).Bytes()) - ext.TxIndex = newHexNum(big.NewInt(t.TxIndex).Bytes()) - ext.From = newHexData(t.From.Bytes()) - ext.To = newHexData(t.To.Bytes()) - ext.Value = newHexNum(t.Value.Bytes()) - ext.Gas = newHexNum(t.Gas.Bytes()) - ext.GasPrice = newHexNum(t.GasPrice.Bytes()) - ext.Input = newHexData(t.Input) - - return json.Marshal(ext) + 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 { var v = new(TransactionRes) - v.Hash = tx.Hash() - v.Nonce = tx.Nonce() - v.From, _ = tx.From() - v.To = tx.To() - v.Value = tx.Value() - v.Gas = tx.Gas() - v.GasPrice = tx.GasPrice() - v.Input = tx.Data() + 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 +} + +func NewTransactionsRes(txs []*types.Transaction) []*TransactionRes { + v := make([]*TransactionRes, len(txs)) + for i, tx := range txs { + v[i] = NewTransactionRes(tx) + } return v } @@ -212,53 +123,30 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes { // } type LogRes struct { - Address common.Address `json:"address"` - Topics []common.Hash `json:"topics"` - Data []byte `json:"data"` - BlockNumber uint64 `json:"blockNumber"` - Hash common.Hash `json:"hash"` - LogIndex uint64 `json:"logIndex"` - BlockHash common.Hash `json:"blockHash"` - TransactionHash common.Hash `json:"transactionHash"` - TransactionIndex uint64 `json:"transactionIndex"` + Address *hexdata `json:"address"` + Topics []*hexdata `json:"topics"` + Data *hexdata `json:"data"` + BlockNumber *hexnum `json:"blockNumber"` + Hash *hexdata `json:"hash"` + LogIndex *hexnum `json:"logIndex"` + BlockHash *hexdata `json:"blockHash"` + TransactionHash *hexdata `json:"transactionHash"` + TransactionIndex *hexnum `json:"transactionIndex"` } func NewLogRes(log state.Log) LogRes { var l LogRes - l.Topics = make([]common.Hash, len(log.Topics())) - l.Address = log.Address() - l.Data = log.Data() - l.BlockNumber = log.Number() + l.Topics = make([]*hexdata, len(log.Topics())) for j, topic := range log.Topics() { - l.Topics[j] = topic + l.Topics[j] = newHexData(topic) } + l.Address = newHexData(log.Address()) + l.Data = newHexData(log.Data()) + l.BlockNumber = newHexNum(log.Number()) + return l } -func (l *LogRes) MarshalJSON() ([]byte, error) { - var ext struct { - Address *hexdata `json:"address"` - Topics []*hexdata `json:"topics"` - Data *hexdata `json:"data"` - BlockNumber *hexnum `json:"blockNumber"` - Hash *hexdata `json:"hash"` - LogIndex *hexnum `json:"logIndex"` - BlockHash *hexdata `json:"blockHash"` - TransactionHash *hexdata `json:"transactionHash"` - TransactionIndex *hexnum `json:"transactionIndex"` - } - - ext.Address = newHexData(l.Address.Bytes()) - ext.Data = newHexData(l.Data) - ext.BlockNumber = newHexNum(l.BlockNumber) - ext.Topics = make([]*hexdata, len(l.Topics)) - for i, v := range l.Topics { - ext.Topics[i] = newHexData(v) - } - - return json.Marshal(ext) -} - func NewLogsRes(logs state.Logs) (ls []LogRes) { ls = make([]LogRes, len(logs)) diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 80e97a7531..18598f0713 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -1,123 +1,123 @@ package rpc import ( - "encoding/json" - "math/big" - "testing" +// "encoding/json" +// "math/big" +// "testing" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" +// "github.com/ethereum/go-ethereum/common" +// "github.com/ethereum/go-ethereum/core/state" +// "github.com/ethereum/go-ethereum/core/types" ) -func TestNewBlockRes(t *testing.T) { - parentHash := common.HexToHash("0x01") - coinbase := common.HexToAddress("0x01") - root := common.HexToHash("0x01") - difficulty := common.Big1 - nonce := uint64(1) - extra := "" - block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) +// func TestNewBlockRes(t *testing.T) { +// parentHash := common.HexToHash("0x01") +// coinbase := common.HexToAddress("0x01") +// root := common.HexToHash("0x01") +// difficulty := common.Big1 +// nonce := uint64(1) +// extra := "" +// block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) - _ = NewBlockRes(block) -} +// _ = NewBlockRes(block) +// } -func TestBlockRes(t *testing.T) { - v := &BlockRes{ - BlockNumber: big.NewInt(0), - BlockHash: common.HexToHash("0x0"), - ParentHash: common.HexToHash("0x0"), - Nonce: [8]byte{0, 0, 0, 0, 0, 0, 0, 0}, - Sha3Uncles: common.HexToHash("0x0"), - LogsBloom: types.BytesToBloom([]byte{0}), - TransactionRoot: common.HexToHash("0x0"), - StateRoot: common.HexToHash("0x0"), - Miner: common.HexToAddress("0x0"), - Difficulty: big.NewInt(0), - TotalDifficulty: big.NewInt(0), - Size: big.NewInt(0), - ExtraData: []byte{}, - GasLimit: big.NewInt(0), - MinGasPrice: int64(0), - GasUsed: big.NewInt(0), - UnixTimestamp: int64(0), - // Transactions []*TransactionRes `json:"transactions"` - // Uncles []common.Hash `json:"uncles"` - } +// func TestBlockRes(t *testing.T) { +// v := &BlockRes{ +// BlockNumber: big.NewInt(0), +// BlockHash: common.HexToHash("0x0"), +// ParentHash: common.HexToHash("0x0"), +// Nonce: [8]byte{0, 0, 0, 0, 0, 0, 0, 0}, +// Sha3Uncles: common.HexToHash("0x0"), +// LogsBloom: types.BytesToBloom([]byte{0}), +// TransactionRoot: common.HexToHash("0x0"), +// StateRoot: common.HexToHash("0x0"), +// Miner: common.HexToAddress("0x0"), +// Difficulty: big.NewInt(0), +// TotalDifficulty: big.NewInt(0), +// Size: big.NewInt(0), +// ExtraData: []byte{}, +// GasLimit: big.NewInt(0), +// MinGasPrice: int64(0), +// GasUsed: big.NewInt(0), +// UnixTimestamp: int64(0), +// // Transactions []*TransactionRes `json:"transactions"` +// // Uncles []common.Hash `json:"uncles"` +// } - _, _ = json.Marshal(v) +// _, _ = json.Marshal(v) - // fmt.Println(string(j)) +// // fmt.Println(string(j)) -} +// } -func TestTransactionRes(t *testing.T) { - a := common.HexToAddress("0x0") - v := &TransactionRes{ - Hash: common.HexToHash("0x0"), - Nonce: uint64(0), - BlockHash: common.HexToHash("0x0"), - BlockNumber: int64(0), - TxIndex: int64(0), - From: common.HexToAddress("0x0"), - To: &a, - Value: big.NewInt(0), - Gas: big.NewInt(0), - GasPrice: big.NewInt(0), - Input: []byte{0}, - } +// func TestTransactionRes(t *testing.T) { +// a := common.HexToAddress("0x0") +// v := &TransactionRes{ +// Hash: common.HexToHash("0x0"), +// Nonce: uint64(0), +// BlockHash: common.HexToHash("0x0"), +// BlockNumber: int64(0), +// TxIndex: int64(0), +// From: common.HexToAddress("0x0"), +// To: &a, +// Value: big.NewInt(0), +// Gas: big.NewInt(0), +// GasPrice: big.NewInt(0), +// Input: []byte{0}, +// } - _, _ = json.Marshal(v) -} +// _, _ = json.Marshal(v) +// } -func TestNewTransactionRes(t *testing.T) { - to := common.HexToAddress("0x02") - amount := big.NewInt(1) - gasAmount := big.NewInt(1) - gasPrice := big.NewInt(1) - data := []byte{1, 2, 3} - tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data) +// func TestNewTransactionRes(t *testing.T) { +// to := common.HexToAddress("0x02") +// amount := big.NewInt(1) +// gasAmount := big.NewInt(1) +// gasPrice := big.NewInt(1) +// data := []byte{1, 2, 3} +// tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data) - _ = NewTransactionRes(tx) -} +// _ = NewTransactionRes(tx) +// } -func TestLogRes(t *testing.T) { - topics := make([]common.Hash, 3) - topics = append(topics, common.HexToHash("0x00")) - topics = append(topics, common.HexToHash("0x10")) - topics = append(topics, common.HexToHash("0x20")) +// func TestLogRes(t *testing.T) { +// topics := make([]common.Hash, 3) +// topics = append(topics, common.HexToHash("0x00")) +// topics = append(topics, common.HexToHash("0x10")) +// topics = append(topics, common.HexToHash("0x20")) - v := &LogRes{ - Topics: topics, - Address: common.HexToAddress("0x0"), - Data: []byte{1, 2, 3}, - BlockNumber: uint64(5), - } +// v := &LogRes{ +// Topics: topics, +// Address: common.HexToAddress("0x0"), +// Data: []byte{1, 2, 3}, +// BlockNumber: uint64(5), +// } - _, _ = json.Marshal(v) -} +// _, _ = json.Marshal(v) +// } -func MakeStateLog(num int) state.Log { - address := common.HexToAddress("0x0") - data := []byte{1, 2, 3} - number := uint64(num) - topics := make([]common.Hash, 3) - topics = append(topics, common.HexToHash("0x00")) - topics = append(topics, common.HexToHash("0x10")) - topics = append(topics, common.HexToHash("0x20")) - log := state.NewLog(address, topics, data, number) - return log -} +// func MakeStateLog(num int) state.Log { +// address := common.HexToAddress("0x0") +// data := []byte{1, 2, 3} +// number := uint64(num) +// topics := make([]common.Hash, 3) +// topics = append(topics, common.HexToHash("0x00")) +// topics = append(topics, common.HexToHash("0x10")) +// topics = append(topics, common.HexToHash("0x20")) +// log := state.NewLog(address, topics, data, number) +// return log +// } -func TestNewLogRes(t *testing.T) { - log := MakeStateLog(0) - _ = NewLogRes(log) -} +// func TestNewLogRes(t *testing.T) { +// log := MakeStateLog(0) +// _ = NewLogRes(log) +// } -func TestNewLogsRes(t *testing.T) { - logs := make([]state.Log, 3) - logs[0] = MakeStateLog(1) - logs[1] = MakeStateLog(2) - logs[2] = MakeStateLog(3) - _ = NewLogsRes(logs) -} +// func TestNewLogsRes(t *testing.T) { +// logs := make([]state.Log, 3) +// logs[0] = MakeStateLog(1) +// logs[1] = MakeStateLog(2) +// logs[2] = MakeStateLog(3) +// _ = NewLogsRes(logs) +// } From 40ea46620066bd7888b3f9a425fcd6201e0c7320 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Tue, 31 Mar 2015 22:40:12 +0200 Subject: [PATCH 15/50] Store and retrieve tx context metadata #608 Improving this in the future will allow for cleaning up a bit of legacy code. --- core/block_processor.go | 28 +++++++++++++++++++++++++--- rpc/api.go | 8 ++++++-- xeth/xeth.go | 23 ++++++++++++++++++++--- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/core/block_processor.go b/core/block_processor.go index e970ad06ef..ceb0ef8a7c 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -233,8 +233,9 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big sm.txpool.RemoveSet(block.Transactions()) } - for _, tx := range block.Transactions() { - putTx(sm.extraDb, tx) + // This puts transactions in a extra db for rpc + for i, tx := range block.Transactions() { + putTx(sm.extraDb, tx, block, i) } if uncle { @@ -358,11 +359,32 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro return state.Logs(), nil } -func putTx(db common.Database, tx *types.Transaction) { +func putTx(db common.Database, tx *types.Transaction, block *types.Block, i int) { rlpEnc, err := rlp.EncodeToBytes(tx) if err != nil { statelogger.Infoln("Failed encoding tx", err) return } db.Put(tx.Hash().Bytes(), rlpEnc) + + rlpEnc, err = rlp.EncodeToBytes(block.Hash().Bytes()) + if err != nil { + statelogger.Infoln("Failed encoding meta", err) + return + } + db.Put(append(tx.Hash().Bytes(), 0x0001), rlpEnc) + + rlpEnc, err = rlp.EncodeToBytes(block.Number().Bytes()) + if err != nil { + statelogger.Infoln("Failed encoding meta", err) + return + } + db.Put(append(tx.Hash().Bytes(), 0x0002), rlpEnc) + + rlpEnc, err = rlp.EncodeToBytes(i) + if err != nil { + statelogger.Infoln("Failed encoding meta", err) + return + } + db.Put(append(tx.Hash().Bytes(), 0x0003), rlpEnc) } diff --git a/rpc/api.go b/rpc/api.go index 3f5d33da6e..48039511e1 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -199,9 +199,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err args := new(HashIndexArgs) if err := json.Unmarshal(req.Params, &args); err != nil { } - tx := api.xeth().EthTransactionByHash(args.Hash) + tx, bhash, bnum, txi := api.xeth().EthTransactionByHash(args.Hash) if tx != nil { - *reply = NewTransactionRes(tx) + v := NewTransactionRes(tx) + v.BlockHash = newHexData(bhash) + v.BlockNumber = newHexNum(bnum) + v.TxIndex = newHexNum(txi) + *reply = v } case "eth_getTransactionByBlockHashAndIndex": args := new(HashIndexArgs) diff --git a/xeth/xeth.go b/xeth/xeth.go index 7e1548964e..fcc03b85f2 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -185,12 +185,29 @@ func (self *XEth) EthBlockByHash(strHash string) *types.Block { return block } -func (self *XEth) EthTransactionByHash(hash string) *types.Transaction { +func (self *XEth) EthTransactionByHash(hash string) (tx *types.Transaction, blhash common.Hash, blnum *big.Int, txi uint64) { data, _ := self.backend.ExtraDb().Get(common.FromHex(hash)) if len(data) != 0 { - return types.NewTransactionFromBytes(data) + tx = types.NewTransactionFromBytes(data) } - return nil + + // blockhash + data, _ = self.backend.ExtraDb().Get(append(common.FromHex(hash), 0x0001)) + if len(data) != 0 { + blhash = common.BytesToHash(data) + } + // blocknum + data, _ = self.backend.ExtraDb().Get(append(common.FromHex(hash), 0x0002)) + if len(data) != 0 { + blnum = common.Bytes2Big(data) + } + // txindex + data, _ = self.backend.ExtraDb().Get(append(common.FromHex(hash), 0x0003)) + if len(data) != 0 { + txi = common.BytesToNumber(data) + } + + return } func (self *XEth) BlockByNumber(num int64) *Block { From 25998cfc456876a5447e45877b7f843730bab7c1 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 09:11:23 +0200 Subject: [PATCH 16/50] Re-enabled response tests (needs improvement) --- rpc/responses_test.go | 157 +++++++++++++----------------------------- 1 file changed, 46 insertions(+), 111 deletions(-) diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 18598f0713..8c1e2873fc 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -1,123 +1,58 @@ package rpc import ( -// "encoding/json" -// "math/big" -// "testing" + "math/big" + "testing" -// "github.com/ethereum/go-ethereum/common" -// "github.com/ethereum/go-ethereum/core/state" -// "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" ) -// func TestNewBlockRes(t *testing.T) { -// parentHash := common.HexToHash("0x01") -// coinbase := common.HexToAddress("0x01") -// root := common.HexToHash("0x01") -// difficulty := common.Big1 -// nonce := uint64(1) -// extra := "" -// block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) +func TestNewBlockRes(t *testing.T) { + parentHash := common.HexToHash("0x01") + coinbase := common.HexToAddress("0x01") + root := common.HexToHash("0x01") + difficulty := common.Big1 + nonce := uint64(1) + extra := "" + block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) -// _ = NewBlockRes(block) -// } + _ = NewBlockRes(block) +} -// func TestBlockRes(t *testing.T) { -// v := &BlockRes{ -// BlockNumber: big.NewInt(0), -// BlockHash: common.HexToHash("0x0"), -// ParentHash: common.HexToHash("0x0"), -// Nonce: [8]byte{0, 0, 0, 0, 0, 0, 0, 0}, -// Sha3Uncles: common.HexToHash("0x0"), -// LogsBloom: types.BytesToBloom([]byte{0}), -// TransactionRoot: common.HexToHash("0x0"), -// StateRoot: common.HexToHash("0x0"), -// Miner: common.HexToAddress("0x0"), -// Difficulty: big.NewInt(0), -// TotalDifficulty: big.NewInt(0), -// Size: big.NewInt(0), -// ExtraData: []byte{}, -// GasLimit: big.NewInt(0), -// MinGasPrice: int64(0), -// GasUsed: big.NewInt(0), -// UnixTimestamp: int64(0), -// // Transactions []*TransactionRes `json:"transactions"` -// // Uncles []common.Hash `json:"uncles"` -// } +func TestNewTransactionRes(t *testing.T) { + to := common.HexToAddress("0x02") + amount := big.NewInt(1) + gasAmount := big.NewInt(1) + gasPrice := big.NewInt(1) + data := []byte{1, 2, 3} + tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data) -// _, _ = json.Marshal(v) + _ = NewTransactionRes(tx) +} -// // fmt.Println(string(j)) +func MakeStateLog(num int) state.Log { + address := common.HexToAddress("0x0") + data := []byte{1, 2, 3} + number := uint64(num) + topics := make([]common.Hash, 3) + topics = append(topics, common.HexToHash("0x00")) + topics = append(topics, common.HexToHash("0x10")) + topics = append(topics, common.HexToHash("0x20")) + log := state.NewLog(address, topics, data, number) + return log +} -// } +func TestNewLogRes(t *testing.T) { + log := MakeStateLog(0) + _ = NewLogRes(log) +} -// func TestTransactionRes(t *testing.T) { -// a := common.HexToAddress("0x0") -// v := &TransactionRes{ -// Hash: common.HexToHash("0x0"), -// Nonce: uint64(0), -// BlockHash: common.HexToHash("0x0"), -// BlockNumber: int64(0), -// TxIndex: int64(0), -// From: common.HexToAddress("0x0"), -// To: &a, -// Value: big.NewInt(0), -// Gas: big.NewInt(0), -// GasPrice: big.NewInt(0), -// Input: []byte{0}, -// } - -// _, _ = json.Marshal(v) -// } - -// func TestNewTransactionRes(t *testing.T) { -// to := common.HexToAddress("0x02") -// amount := big.NewInt(1) -// gasAmount := big.NewInt(1) -// gasPrice := big.NewInt(1) -// data := []byte{1, 2, 3} -// tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data) - -// _ = NewTransactionRes(tx) -// } - -// func TestLogRes(t *testing.T) { -// topics := make([]common.Hash, 3) -// topics = append(topics, common.HexToHash("0x00")) -// topics = append(topics, common.HexToHash("0x10")) -// topics = append(topics, common.HexToHash("0x20")) - -// v := &LogRes{ -// Topics: topics, -// Address: common.HexToAddress("0x0"), -// Data: []byte{1, 2, 3}, -// BlockNumber: uint64(5), -// } - -// _, _ = json.Marshal(v) -// } - -// func MakeStateLog(num int) state.Log { -// address := common.HexToAddress("0x0") -// data := []byte{1, 2, 3} -// number := uint64(num) -// topics := make([]common.Hash, 3) -// topics = append(topics, common.HexToHash("0x00")) -// topics = append(topics, common.HexToHash("0x10")) -// topics = append(topics, common.HexToHash("0x20")) -// log := state.NewLog(address, topics, data, number) -// return log -// } - -// func TestNewLogRes(t *testing.T) { -// log := MakeStateLog(0) -// _ = NewLogRes(log) -// } - -// func TestNewLogsRes(t *testing.T) { -// logs := make([]state.Log, 3) -// logs[0] = MakeStateLog(1) -// logs[1] = MakeStateLog(2) -// logs[2] = MakeStateLog(3) -// _ = NewLogsRes(logs) -// } +func TestNewLogsRes(t *testing.T) { + logs := make([]state.Log, 3) + logs[0] = MakeStateLog(1) + logs[1] = MakeStateLog(2) + logs[2] = MakeStateLog(3) + _ = NewLogsRes(logs) +} From d3e86f9208d775ee8020d5583d0aac8f3cfb52b2 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 10:51:46 +0200 Subject: [PATCH 17/50] Added gas generator defaults --- generators/default.json | 56 +++++++++++++++++++++++++++++++++++++ generators/defaults.go | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 generators/default.json create mode 100644 generators/defaults.go diff --git a/generators/default.json b/generators/default.json new file mode 100644 index 0000000000..181a9dd54a --- /dev/null +++ b/generators/default.json @@ -0,0 +1,56 @@ +{ + "genesisGasLimit": { "v": 1000000, "d": "Gas limit of the Genesis block." }, + "minGasLimit": { "v": 125000, "d": "Minimum the gas limit may ever be." }, + "gasLimitBoundDivisor": { "v": 1024, "d": "The bound divisor of the gas limit, used in update calculations." }, + "genesisDifficulty": { "v": 131072, "d": "Difficulty of the Genesis block." }, + "minimumDifficulty": { "v": 131072, "d": "The minimum that the difficulty may ever be." }, + "difficultyBoundDivisor": { "v": 2048, "d": "The bound divisor of the difficulty, used in the update calculations." }, + "durationLimit": { "v": 8, "d": "The decision boundary on the blocktime duration used to determine whether difficulty should go up or not." }, + "maximumExtraDataSize": { "v": 1024, "d": "Maximum size extra data may be after Genesis." }, + "epochDuration": { "v": 30000, "d": "Duration between proof-of-work epochs." }, + "stackLimit": { "v": 1024, "d": "Maximum size of VM stack allowed." }, + + "tierStepGas": { "v": [ 0, 2, 3, 5, 8, 10, 20 ], "d": "Once per operation, for a selection of them." }, + "expGas": { "v": 10, "d": "Once per EXP instuction." }, + "expByteGas": { "v": 10, "d": "Times ceil(log256(exponent)) for the EXP instruction." }, + + "sha3Gas": { "v": 30, "d": "Once per SHA3 operation." }, + "sha3WordGas": { "v": 6, "d": "Once per word of the SHA3 operation's data." }, + + "sloadGas": { "v": 50, "d": "Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added." }, + "sstoreSetGas": { "v": 20000, "d": "Once per SLOAD operation." }, + "sstoreResetGas": { "v": 5000, "d": "Once per SSTORE operation if the zeroness changes from zero." }, + "sstoreClearGas": { "v": 5000, "d": "Once per SSTORE operation if the zeroness doesn't change." }, + "sstoreRefundGas": { "v": 15000, "d": "Once per SSTORE operation if the zeroness changes to zero." }, + "jumpdestGas": { "v": 1, "d": "Refunded gas, once per SSTORE operation if the zeroness changes to zero." }, + + "logGas": { "v": 375, "d": "Per LOG* operation." }, + "logDataGas": { "v": 8, "d": "Per byte in a LOG* operation's data." }, + "logTopicGas": { "v": 375, "d": "Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas." }, + + "createGas": { "v": 32000, "d": "Once per CREATE operation & contract-creation transaction." }, + + "callGas": { "v": 40, "d": "Once per CALL operation & message call transaction." }, + "callStipend": { "v": 2300, "d": "Free gas given at beginning of call." }, + "callValueTransferGas": { "v": 9000, "d": "Paid for CALL when the value transfor is non-zero." }, + "callNewAccountGas": { "v": 25000, "d": "Paid for CALL when the destination address didn't exist prior." }, + + "suicideRefundGas": { "v": 24000, "d": "Refunded following a suicide operation." }, + "memoryGas": { "v": 3, "d": "Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL." }, + "quadCoeffDiv": { "v": 512, "d": "Divisor for the quadratic particle of the memory cost equation." }, + + "createDataGas": { "v": 200, "d": "" }, + "txGas": { "v": 21000, "d": "Per transaction. NOTE: Not payable on data of calls between transactions." }, + "txDataZeroGas": { "v": 4, "d": "Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions." }, + "txDataNonZeroGas": { "v": 68, "d": "Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions." }, + + "copyGas": { "v": 3, "d": "" }, + + "ecrecoverGas": { "v": 3000, "d": "" }, + "sha256Gas": { "v": 60, "d": "" }, + "sha256WordGas": { "v": 12, "d": "" }, + "ripemd160Gas": { "v": 600, "d": "" }, + "ripemd160WordGas": { "v": 120, "d": "" }, + "identityGas": { "v": 15, "d": "" }, + "identityWordGas": { "v": 3, "d": ""} +} diff --git a/generators/defaults.go b/generators/defaults.go new file mode 100644 index 0000000000..b0c71111cf --- /dev/null +++ b/generators/defaults.go @@ -0,0 +1,62 @@ +//go:generate go run defaults.go default.json defs.go + +package main //build !none + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "strings" +) + +func fatal(str string, v ...interface{}) { + fmt.Fprintf(os.Stderr, str, v...) + os.Exit(1) +} + +type setting struct { + Value int64 `json:"v"` + Comment string `json:"d"` +} + +func main() { + if len(os.Args) < 3 { + fatal("usage %s \n", os.Args[0]) + } + + content, err := ioutil.ReadFile(os.Args[1]) + if err != nil { + fatal("error reading file %v\n", err) + } + + m := make(map[string]setting) + json.Unmarshal(content, &m) + + filepath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "core", os.Args[2]) + output, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE, os.ModePerm /*0777*/) + if err != nil { + fatal("error opening file for writing %v\n", err) + } + + output.WriteString(`package core + +import "math/big" + +var ( +`) + + for name, setting := range m { + output.WriteString(fmt.Sprintf("%s=big.NewInt(%d) // %s\n", strings.Title(name), setting.Value, setting.Comment)) + } + + output.WriteString(")\n") + output.Close() + + cmd := exec.Command("gofmt", "-w", filepath) + if err := cmd.Run(); err != nil { + fatal("gofmt failed: %v\n", err) + } +} From 0a554a1f27ece4235d180373643482ceb57d90ca Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 10:53:32 +0200 Subject: [PATCH 18/50] Blocktest fixed, Execution fixed * Added new CreateAccount method which properly overwrites previous accounts (excluding balance) * Fixed block tests (100% success) --- cmd/geth/blocktest.go | 2 +- core/block_processor.go | 6 +++- core/execution.go | 17 ++++++++-- core/genesis.go | 2 +- core/state/statedb.go | 68 +++++++++++++++++++++++++--------------- core/state_transition.go | 9 +++--- core/vm/vm.go | 3 +- tests/blocktest.go | 13 ++++---- 8 files changed, 77 insertions(+), 43 deletions(-) diff --git a/cmd/geth/blocktest.go b/cmd/geth/blocktest.go index d9cdfa83f0..f0b6bb1a21 100644 --- a/cmd/geth/blocktest.go +++ b/cmd/geth/blocktest.go @@ -60,7 +60,7 @@ func runblocktest(ctx *cli.Context) { // insert the test blocks, which will execute all transactions chain := ethereum.ChainManager() if err := chain.InsertChain(test.Blocks); err != nil { - utils.Fatalf("Block Test load error: %v", err) + utils.Fatalf("Block Test load error: %v %T", err, err) } else { fmt.Println("Block Test chain loaded") } diff --git a/core/block_processor.go b/core/block_processor.go index e970ad06ef..8fbf760afa 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -326,8 +326,12 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren return ValidationError(fmt.Sprintf("%v", err)) } + num := new(big.Int).Add(big.NewInt(8), uncle.Number) + num.Sub(num, block.Number()) + r := new(big.Int) - r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16)) + r.Mul(BlockReward, num) + r.Div(r, big.NewInt(8)) statedb.AddBalance(uncle.Coinbase, r) diff --git a/core/execution.go b/core/execution.go index 24e085e6dd..93fb03eccb 100644 --- a/core/execution.go +++ b/core/execution.go @@ -50,16 +50,29 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm. } vsnapshot := env.State().Copy() + var createAccount bool if self.address == nil { // Generate a new address nonce := env.State().GetNonce(caller.Address()) - addr := crypto.CreateAddress(caller.Address(), nonce) env.State().SetNonce(caller.Address(), nonce+1) + + addr := crypto.CreateAddress(caller.Address(), nonce) + self.address = &addr + createAccount = true } snapshot := env.State().Copy() - from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(*self.address) + var ( + from = env.State().GetStateObject(caller.Address()) + to *state.StateObject + ) + if createAccount { + to = env.State().CreateAccount(*self.address) + } else { + to = env.State().GetOrNewStateObject(*self.address) + } + err = env.Transfer(from, to, self.value) if err != nil { env.State().Set(vsnapshot) diff --git a/core/genesis.go b/core/genesis.go index 716298231d..7958157a41 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -47,7 +47,7 @@ func GenesisBlock(db common.Database) *types.Block { statedb := state.New(genesis.Root(), db) for addr, account := range accounts { codedAddr := common.Hex2Bytes(addr) - accountState := statedb.GetAccount(common.BytesToAddress(codedAddr)) + accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr)) accountState.SetBalance(common.Big(account.Balance)) accountState.SetCode(common.FromHex(account.Code)) statedb.UpdateStateObject(accountState) diff --git a/core/state/statedb.go b/core/state/statedb.go index 6fcd39dbc1..2dc8239ef8 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -57,6 +57,10 @@ func (self *StateDB) Refund(address common.Address, gas *big.Int) { self.refund[addr].Add(self.refund[addr], gas) } +/* + * GETTERS + */ + // Retrieve the balance from the given address or 0 if object not found func (self *StateDB) GetBalance(addr common.Address) *big.Int { stateObject := self.GetStateObject(addr) @@ -67,13 +71,6 @@ func (self *StateDB) GetBalance(addr common.Address) *big.Int { return common.Big0 } -func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { - stateObject := self.GetStateObject(addr) - if stateObject != nil { - stateObject.AddBalance(amount) - } -} - func (self *StateDB) GetNonce(addr common.Address) uint64 { stateObject := self.GetStateObject(addr) if stateObject != nil { @@ -101,22 +98,41 @@ func (self *StateDB) GetState(a common.Address, b common.Hash) []byte { return nil } -func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { +func (self *StateDB) IsDeleted(addr common.Address) bool { stateObject := self.GetStateObject(addr) + if stateObject != nil { + return stateObject.remove + } + return false +} + +/* + * SETTERS + */ + +func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { + stateObject := self.GetOrNewStateObject(addr) + if stateObject != nil { + stateObject.AddBalance(amount) + } +} + +func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { + stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetNonce(nonce) } } func (self *StateDB) SetCode(addr common.Address, code []byte) { - stateObject := self.GetStateObject(addr) + stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetCode(code) } } func (self *StateDB) SetState(addr common.Address, key common.Hash, value interface{}) { - stateObject := self.GetStateObject(addr) + stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetState(key, common.NewValue(value)) } @@ -134,14 +150,6 @@ func (self *StateDB) Delete(addr common.Address) bool { return false } -func (self *StateDB) IsDeleted(addr common.Address) bool { - stateObject := self.GetStateObject(addr) - if stateObject != nil { - return stateObject.remove - } - return false -} - // // Setting, updating & deleting state object methods // @@ -194,16 +202,14 @@ func (self *StateDB) SetStateObject(object *StateObject) { func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject { stateObject := self.GetStateObject(addr) if stateObject == nil { - stateObject = self.NewStateObject(addr) + stateObject = self.CreateAccount(addr) } return stateObject } -// Create a state object whether it exist in the trie or not -func (self *StateDB) NewStateObject(addr common.Address) *StateObject { - //addr = common.Address(addr) - +// NewStateObject create a state object whether it exist in the trie or not +func (self *StateDB) newStateObject(addr common.Address) *StateObject { statelogger.Debugf("(+) %x\n", addr) stateObject := NewStateObject(addr, self.db) @@ -212,9 +218,19 @@ func (self *StateDB) NewStateObject(addr common.Address) *StateObject { return stateObject } -// Deprecated -func (self *StateDB) GetAccount(addr common.Address) *StateObject { - return self.GetOrNewStateObject(addr) +// Creates creates a new state object and takes ownership. This is different from "NewStateObject" +func (self *StateDB) CreateAccount(addr common.Address) *StateObject { + // Get previous (if any) + so := self.GetStateObject(addr) + // Create a new one + newSo := self.newStateObject(addr) + + // If it existed set the balance to the new account + if so != nil { + newSo.balance = so.balance + } + + return newSo } // diff --git a/core/state_transition.go b/core/state_transition.go index 10a49f8296..7616686dba 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -183,15 +183,16 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er } // Pay data gas - var dgas int64 + dgas := new(big.Int) for _, byt := range self.data { if byt != 0 { - dgas += vm.GasTxDataNonzeroByte.Int64() + dgas.Add(dgas, vm.GasTxDataNonzeroByte) } else { - dgas += vm.GasTxDataZeroByte.Int64() + dgas.Add(dgas, vm.GasTxDataZeroByte) } } - if err = self.UseGas(big.NewInt(dgas)); err != nil { + + if err = self.UseGas(dgas); err != nil { return nil, nil, InvalidTxError(err) } diff --git a/core/vm/vm.go b/core/vm/vm.go index 6c3dd240a0..59c64e8a3e 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -857,7 +857,8 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom) newTotalFee := new(big.Int).Add(linCoef, quadCoef) - gas.Add(gas, new(big.Int).Sub(newTotalFee, oldTotalFee)) + fee := new(big.Int).Sub(newTotalFee, oldTotalFee) + gas.Add(gas, fee) } } diff --git a/tests/blocktest.go b/tests/blocktest.go index d813ebeec8..fc62eda58d 100644 --- a/tests/blocktest.go +++ b/tests/blocktest.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/hex" "encoding/json" - "errors" "fmt" "io/ioutil" "math/big" @@ -69,7 +68,7 @@ type btBlock struct { BlockHeader *btHeader Rlp string Transactions []btTransaction - UncleHeaders []string + UncleHeaders []*btHeader } type BlockTest struct { @@ -106,13 +105,13 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) { balance, _ := new(big.Int).SetString(acct.Balance, 0) nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64) - obj := statedb.NewStateObject(common.HexToAddress(addrString)) + obj := statedb.CreateAccount(common.HexToAddress(addrString)) obj.SetCode(code) obj.SetBalance(balance) obj.SetNonce(nonce) - // for k, v := range acct.Storage { - // obj.SetState(k, v) - // } + for k, v := range acct.Storage { + statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.FromHex(v)) + } } // sync objects to trie statedb.Update(nil) @@ -120,7 +119,7 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) { statedb.Sync() if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) { - return nil, errors.New("computed state root does not match genesis block") + return nil, fmt.Errorf("computed state root does not match genesis block %x %x", t.Genesis.Root().Bytes()[:4], statedb.Root().Bytes()[:4]) } return statedb, nil } From 7b7392826d7b76fd4a0bd57baa7ca1224a19a3f6 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 11:38:06 +0200 Subject: [PATCH 19/50] Improved response tests Actually verifies output as by regex --- rpc/messages.go | 6 +- rpc/responses_test.go | 128 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 117 insertions(+), 17 deletions(-) diff --git a/rpc/messages.go b/rpc/messages.go index 1ad41654b2..42af53c58f 100644 --- a/rpc/messages.go +++ b/rpc/messages.go @@ -50,8 +50,12 @@ func newHexData(input interface{}) *hexdata { d.data = input.([]byte) case common.Hash: d.data = input.(common.Hash).Bytes() + case *common.Hash: + d.data = input.(*common.Hash).Bytes() case common.Address: d.data = input.(common.Address).Bytes() + case *common.Address: + d.data = input.(*common.Address).Bytes() case *big.Int: d.data = input.(*big.Int).Bytes() case int64: @@ -62,7 +66,7 @@ func newHexData(input interface{}) *hexdata { d.data = big.NewInt(int64(input.(int))).Bytes() case uint: d.data = big.NewInt(int64(input.(uint))).Bytes() - case string: + case string: // hexstring d.data = common.Big(input.(string)).Bytes() default: d.data = nil diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 8c1e2873fc..5c6c6a895b 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -1,7 +1,10 @@ package rpc import ( + "encoding/json" + "fmt" "math/big" + "regexp" "testing" "github.com/ethereum/go-ethereum/common" @@ -9,6 +12,15 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +const ( + reHash = `"0x[0-9a-f]{64}"` // 32 bytes + reHashOpt = `"(0x[0-9a-f]{64})"|null` // 32 bytes or null + reAddress = `"0x[0-9a-f]{40}"` // 20 bytes + reAddressOpt = `"0x[0-9a-f]{40}"|null` // 20 bytes or null + reNum = `"0x([1-9a-f][0-9a-f]{1,15})|0"` // must not have left-padded zeros + reData = `"0x[0-9a-f]*"` // can be "empty" +) + func TestNewBlockRes(t *testing.T) { parentHash := common.HexToHash("0x01") coinbase := common.HexToAddress("0x01") @@ -17,8 +29,35 @@ func TestNewBlockRes(t *testing.T) { nonce := uint64(1) extra := "" block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) + tests := map[string]string{ + "number": reNum, + "hash": reHash, + "parentHash": reHash, + "nonce": reNum, + "sha3Uncles": reHash, + "logsBloom": reData, + "transactionRoot": reHash, + "stateRoot": reHash, + "miner": reAddress, + "difficulty": `"0x1"`, + "totalDifficulty": reNum, + "size": reNum, + "extraData": reData, + "gasLimit": reNum, + // "minGasPrice": "0x", + "gasUsed": reNum, + "timestamp": reNum, + } - _ = NewBlockRes(block) + v := NewBlockRes(block) + j, _ := json.Marshal(v) + + for k, re := range tests { + match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j)) + if !match { + t.Error(fmt.Sprintf("%s output json does not match format %s. Got %s", k, re, j)) + } + } } func TestNewTransactionRes(t *testing.T) { @@ -29,10 +68,80 @@ func TestNewTransactionRes(t *testing.T) { data := []byte{1, 2, 3} tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data) - _ = NewTransactionRes(tx) + tests := map[string]string{ + "hash": reHash, + "nonce": reNum, + "blockHash": reHash, + "blockNum": reNum, + "transactionIndex": reNum, + "from": reAddress, + "to": reAddressOpt, + "value": reNum, + "gas": reNum, + "gasPrice": reNum, + "input": reData, + } + + v := NewTransactionRes(tx) + v.BlockHash = newHexData(common.HexToHash("0x030201")) + v.BlockNumber = newHexNum(5) + v.TxIndex = newHexNum(0) + j, _ := json.Marshal(v) + for k, re := range tests { + match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j)) + if !match { + t.Error(fmt.Sprintf("`%s` output json does not match format %s. Source %s", k, re, j)) + } + } + } -func MakeStateLog(num int) state.Log { +func TestNewLogRes(t *testing.T) { + log := makeStateLog(0) + tests := map[string]string{ + "address": reAddress, + // "topics": "[.*]" + "data": reData, + "blockNumber": reNum, + // "hash": reHash, + // "logIndex": reNum, + // "blockHash": reHash, + // "transactionHash": reHash, + "transactionIndex": reNum, + } + + v := NewLogRes(log) + j, _ := json.Marshal(v) + + for k, re := range tests { + match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j)) + if !match { + t.Error(fmt.Sprintf("`%s` output json does not match format %s. Got %s", k, re, j)) + } + } + +} + +func TestNewLogsRes(t *testing.T) { + logs := make([]state.Log, 3) + logs[0] = makeStateLog(1) + logs[1] = makeStateLog(2) + logs[2] = makeStateLog(3) + tests := map[string]string{} + + v := NewLogsRes(logs) + j, _ := json.Marshal(v) + + for k, re := range tests { + match, _ := regexp.MatchString(fmt.Sprintf(`[{.*"%s":%s.*}]`, k, re), string(j)) + if !match { + t.Error(fmt.Sprintf("%s output json does not match format %s. Got %s", k, re, j)) + } + } + +} + +func makeStateLog(num int) state.Log { address := common.HexToAddress("0x0") data := []byte{1, 2, 3} number := uint64(num) @@ -43,16 +152,3 @@ func MakeStateLog(num int) state.Log { log := state.NewLog(address, topics, data, number) return log } - -func TestNewLogRes(t *testing.T) { - log := MakeStateLog(0) - _ = NewLogRes(log) -} - -func TestNewLogsRes(t *testing.T) { - logs := make([]state.Log, 3) - logs[0] = MakeStateLog(1) - logs[1] = MakeStateLog(2) - logs[2] = MakeStateLog(3) - _ = NewLogsRes(logs) -} From f468364e4d3545d445ed5027539426900b440dd9 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 11:42:02 +0200 Subject: [PATCH 20/50] fixed tests --- cmd/evm/main.go | 4 ++-- core/state/state_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 4c6059794c..5eb753fa8d 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -61,8 +61,8 @@ func main() { db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) - sender := statedb.NewStateObject(common.StringToAddress("sender")) - receiver := statedb.NewStateObject(common.StringToAddress("receiver")) + sender := statedb.CreateAccount(common.StringToAddress("sender")) + receiver := statedb.CreateAccount(common.StringToAddress("receiver")) receiver.SetCode(common.Hex2Bytes(*code)) vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(*value)) diff --git a/core/state/state_test.go b/core/state/state_test.go index a3d3973de2..da597d773d 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -68,7 +68,7 @@ func TestNull(t *testing.T) { state := New(common.Hash{}, db) address := common.HexToAddress("0x823140710bf13990e4500136726d8b55") - state.NewStateObject(address) + state.CreateAccount(address) //value := common.FromHex("0x823140710bf13990e4500136726d8b55") value := make([]byte, 16) state.SetState(address, common.Hash{}, value) From b860b6769329137c24024c2330529d7b2078d89d Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 11:45:29 +0200 Subject: [PATCH 21/50] Remove extra type assetion --- rpc/messages.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/rpc/messages.go b/rpc/messages.go index 42af53c58f..f868c5f9b0 100644 --- a/rpc/messages.go +++ b/rpc/messages.go @@ -45,29 +45,29 @@ func (d *hexdata) UnmarshalJSON(b []byte) (err error) { func newHexData(input interface{}) *hexdata { d := new(hexdata) - switch input.(type) { + switch input := input.(type) { case []byte: - d.data = input.([]byte) + d.data = input case common.Hash: - d.data = input.(common.Hash).Bytes() + d.data = input.Bytes() case *common.Hash: - d.data = input.(*common.Hash).Bytes() + d.data = input.Bytes() case common.Address: - d.data = input.(common.Address).Bytes() + d.data = input.Bytes() case *common.Address: - d.data = input.(*common.Address).Bytes() + d.data = input.Bytes() case *big.Int: - d.data = input.(*big.Int).Bytes() + d.data = input.Bytes() case int64: - d.data = big.NewInt(input.(int64)).Bytes() + d.data = big.NewInt(input).Bytes() case uint64: - d.data = big.NewInt(int64(input.(uint64))).Bytes() + d.data = big.NewInt(int64(input)).Bytes() case int: - d.data = big.NewInt(int64(input.(int))).Bytes() + d.data = big.NewInt(int64(input)).Bytes() case uint: - d.data = big.NewInt(int64(input.(uint))).Bytes() + d.data = big.NewInt(int64(input)).Bytes() case string: // hexstring - d.data = common.Big(input.(string)).Bytes() + d.data = common.Big(input).Bytes() default: d.data = nil } From f2c6a937f31a82dc548eb723da442ab00af2f987 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 11:50:19 +0200 Subject: [PATCH 22/50] Protocol bump --- eth/protocol.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/protocol.go b/eth/protocol.go index b373c9889b..e32ea233b0 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -13,7 +13,7 @@ import ( ) const ( - ProtocolVersion = 59 + ProtocolVersion = 60 NetworkId = 0 ProtocolLength = uint64(8) ProtocolMaxMsgSize = 10 * 1024 * 1024 From 4e8f8cfab701bb6c4ad2b8cf166d642f408ca398 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 11:51:05 +0200 Subject: [PATCH 23/50] ethereum.js update --- cmd/mist/assets/ext/ethereum.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/mist/assets/ext/ethereum.js b/cmd/mist/assets/ext/ethereum.js index 17164bea8b..2536888f81 160000 --- a/cmd/mist/assets/ext/ethereum.js +++ b/cmd/mist/assets/ext/ethereum.js @@ -1 +1 @@ -Subproject commit 17164bea8b330d6a118b40d6fbe222ffb12a0e9f +Subproject commit 2536888f817a1a15b05dab4727d30f73d6763f07 From 86ba7432a965d9469ce1b4ccc2397ed2e08c9a3c Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 12:14:35 +0200 Subject: [PATCH 24/50] txMeta storage as struct --- core/block_processor.go | 30 ++++++++++++------------------ xeth/xeth.go | 27 ++++++++++++++------------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/core/block_processor.go b/core/block_processor.go index ceb0ef8a7c..c463bd0836 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -235,7 +235,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big // This puts transactions in a extra db for rpc for i, tx := range block.Transactions() { - putTx(sm.extraDb, tx, block, i) + putTx(sm.extraDb, tx, block, uint64(i)) } if uncle { @@ -359,7 +359,7 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro return state.Logs(), nil } -func putTx(db common.Database, tx *types.Transaction, block *types.Block, i int) { +func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint64) { rlpEnc, err := rlp.EncodeToBytes(tx) if err != nil { statelogger.Infoln("Failed encoding tx", err) @@ -367,24 +367,18 @@ func putTx(db common.Database, tx *types.Transaction, block *types.Block, i int) } db.Put(tx.Hash().Bytes(), rlpEnc) - rlpEnc, err = rlp.EncodeToBytes(block.Hash().Bytes()) + var txExtra struct { + BlockHash common.Hash + BlockIndex uint64 + Index uint64 + } + txExtra.BlockHash = block.Hash() + txExtra.BlockIndex = block.NumberU64() + txExtra.Index = i + rlpMeta, err := rlp.EncodeToBytes(txExtra) if err != nil { statelogger.Infoln("Failed encoding meta", err) return } - db.Put(append(tx.Hash().Bytes(), 0x0001), rlpEnc) - - rlpEnc, err = rlp.EncodeToBytes(block.Number().Bytes()) - if err != nil { - statelogger.Infoln("Failed encoding meta", err) - return - } - db.Put(append(tx.Hash().Bytes(), 0x0002), rlpEnc) - - rlpEnc, err = rlp.EncodeToBytes(i) - if err != nil { - statelogger.Infoln("Failed encoding meta", err) - return - } - db.Put(append(tx.Hash().Bytes(), 0x0003), rlpEnc) + db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) } diff --git a/xeth/xeth.go b/xeth/xeth.go index fcc03b85f2..33fda9b4be 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/event/filter" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/miner" + "github.com/ethereum/go-ethereum/rlp" ) var ( @@ -191,20 +192,20 @@ func (self *XEth) EthTransactionByHash(hash string) (tx *types.Transaction, blha tx = types.NewTransactionFromBytes(data) } - // blockhash - data, _ = self.backend.ExtraDb().Get(append(common.FromHex(hash), 0x0001)) - if len(data) != 0 { - blhash = common.BytesToHash(data) + // meta + var txExtra struct { + BlockHash common.Hash + BlockIndex int64 + Index uint64 } - // blocknum - data, _ = self.backend.ExtraDb().Get(append(common.FromHex(hash), 0x0002)) - if len(data) != 0 { - blnum = common.Bytes2Big(data) - } - // txindex - data, _ = self.backend.ExtraDb().Get(append(common.FromHex(hash), 0x0003)) - if len(data) != 0 { - txi = common.BytesToNumber(data) + + v, _ := self.backend.ExtraDb().Get(append(common.FromHex(hash), 0x0001)) + r := bytes.NewReader(v) + err := rlp.Decode(r, &txExtra) + if err == nil { + blhash = txExtra.BlockHash + blnum = big.NewInt(txExtra.BlockIndex) + txi = txExtra.Index } return From 02fb83782eab5d6ad394aca58daab77a9525d5ff Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 12:28:48 +0200 Subject: [PATCH 25/50] #612 rename eth_protocol method --- rpc/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/api.go b/rpc/api.go index 7f10f16e37..c046c22fed 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -54,7 +54,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err case "net_peerCount": v := api.xeth().PeerCount() *reply = common.ToHex(big.NewInt(int64(v)).Bytes()) - case "eth_version": + case "eth_protocolVersion": *reply = api.xeth().EthVersion() case "eth_coinbase": // TODO handling of empty coinbase due to lack of accounts From 6605d00d92c029a46f624d3f295758f62c3dddd4 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Wed, 1 Apr 2015 12:33:12 +0200 Subject: [PATCH 26/50] Frontier/513 --- xeth/xeth.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/xeth/xeth.go b/xeth/xeth.go index 7e1548964e..7f0c04a123 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -128,8 +128,8 @@ func cTopics(t [][]string) [][]common.Hash { return topics } -func (self *XEth) DefaultGas() *big.Int { return defaultGas } -func (self *XEth) DefaultGasPrice() *big.Int { return defaultGasPrice } +func (self *XEth) DefaultGas() *big.Int { return big.NewInt(defaultGas.Int64()) } +func (self *XEth) DefaultGasPrice() *big.Int { return big.NewInt(defaultGasPrice.Int64()) } func (self *XEth) RemoteMining() *miner.RemoteAgent { return self.agent } @@ -547,12 +547,13 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st value: common.Big(valueStr), data: common.FromHex(dataStr), } + if msg.gas.Cmp(big.NewInt(0)) == 0 { - msg.gas = defaultGas + msg.gas = self.DefaultGas() } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { - msg.gasPrice = defaultGasPrice + msg.gasPrice = self.DefaultGasPrice() } block := self.CurrentBlock() @@ -598,11 +599,11 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt // TODO: align default values to have the same type, e.g. not depend on // common.Value conversions later on if gas.Cmp(big.NewInt(0)) == 0 { - gas = defaultGas + gas = self.DefaultGas() } if price.Cmp(big.NewInt(0)) == 0 { - price = defaultGasPrice + price = self.DefaultGasPrice() } data = common.FromHex(codeStr) From 1559bd9e1bce8c5fcc947a1aee778da7446b251b Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Wed, 1 Apr 2015 13:15:21 +0200 Subject: [PATCH 27/50] changed big.Int instantiation --- xeth/xeth.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xeth/xeth.go b/xeth/xeth.go index 7f0c04a123..3f2f14352a 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -128,8 +128,8 @@ func cTopics(t [][]string) [][]common.Hash { return topics } -func (self *XEth) DefaultGas() *big.Int { return big.NewInt(defaultGas.Int64()) } -func (self *XEth) DefaultGasPrice() *big.Int { return big.NewInt(defaultGasPrice.Int64()) } +func (self *XEth) DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) } +func (self *XEth) DefaultGasPrice() *big.Int { return new(big.Int).Set(defaultGasPrice) } func (self *XEth) RemoteMining() *miner.RemoteAgent { return self.agent } From 88f2a96ca3224bf59cf5639ffc4efabe2fe1f87b Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 13:18:30 +0200 Subject: [PATCH 28/50] Set fullTx option in constructor --- rpc/api.go | 29 ++++++++++++----------------- rpc/responses.go | 5 ++++- rpc/responses_test.go | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index c046c22fed..660bb32513 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -113,7 +113,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return err } - block := NewBlockRes(api.xeth().EthBlockByHash(args.BlockHash)) + block := NewBlockRes(api.xeth().EthBlockByHash(args.BlockHash), false) *reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes()) case "eth_getBlockTransactionCountByNumber": args := new(GetBlockByNumberArgs) @@ -121,7 +121,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return err } - block := NewBlockRes(api.xeth().EthBlockByNumber(args.BlockNumber)) + block := NewBlockRes(api.xeth().EthBlockByNumber(args.BlockNumber), false) *reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes()) case "eth_getUncleCountByBlockHash": args := new(GetBlockByHashArgs) @@ -130,7 +130,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByHash(args.BlockHash) - br := NewBlockRes(block) + br := NewBlockRes(block, false) *reply = common.ToHex(big.NewInt(int64(len(br.Uncles))).Bytes()) case "eth_getUncleCountByBlockNumber": args := new(GetBlockByNumberArgs) @@ -139,7 +139,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByNumber(args.BlockNumber) - br := NewBlockRes(block) + br := NewBlockRes(block, false) *reply = common.ToHex(big.NewInt(int64(len(br.Uncles))).Bytes()) case "eth_getData", "eth_getCode": args := new(GetDataArgs) @@ -179,8 +179,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByHash(args.BlockHash) - br := NewBlockRes(block) - br.fullTx = args.IncludeTxs + br := NewBlockRes(block, true) *reply = br case "eth_getBlockByNumber": @@ -190,8 +189,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByNumber(args.BlockNumber) - br := NewBlockRes(block) - br.fullTx = args.IncludeTxs + br := NewBlockRes(block, true) *reply = br case "eth_getTransactionByHash": @@ -214,8 +212,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByHash(args.Hash) - br := NewBlockRes(block) - br.fullTx = true + br := NewBlockRes(block, true) if args.Index >= int64(len(br.Transactions)) || args.Index < 0 { return NewValidationError("Index", "does not exist") @@ -228,8 +225,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByNumber(args.BlockNumber) - v := NewBlockRes(block) - v.fullTx = true + v := NewBlockRes(block, true) if args.Index >= int64(len(v.Transactions)) || args.Index < 0 { return NewValidationError("Index", "does not exist") @@ -241,14 +237,14 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return err } - br := NewBlockRes(api.xeth().EthBlockByHash(args.Hash)) + br := NewBlockRes(api.xeth().EthBlockByHash(args.Hash), false) if args.Index >= int64(len(br.Uncles)) || args.Index < 0 { return NewValidationError("Index", "does not exist") } uhash := br.Uncles[args.Index] - uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String())) + uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String()), false) *reply = uncle case "eth_getUncleByBlockNumberAndIndex": @@ -258,15 +254,14 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByNumber(args.BlockNumber) - v := NewBlockRes(block) - v.fullTx = true + v := NewBlockRes(block, true) if args.Index >= int64(len(v.Uncles)) || args.Index < 0 { return NewValidationError("Index", "does not exist") } uhash := v.Uncles[args.Index] - uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String())) + uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String()), false) *reply = uncle case "eth_getCompilers": diff --git a/rpc/responses.go b/rpc/responses.go index 3e9293fbb1..9e1170c321 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -29,12 +29,15 @@ type BlockRes struct { Uncles []*hexdata `json:"uncles"` } -func NewBlockRes(block *types.Block) *BlockRes { +func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { + // TODO respect fullTx flag + if block == nil { return &BlockRes{} } res := new(BlockRes) + res.fullTx = fullTx res.BlockNumber = newHexNum(block.Number()) res.BlockHash = newHexData(block.Hash()) res.ParentHash = newHexData(block.ParentHash()) diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 5c6c6a895b..43924151a4 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -49,7 +49,7 @@ func TestNewBlockRes(t *testing.T) { "timestamp": reNum, } - v := NewBlockRes(block) + v := NewBlockRes(block, false) j, _ := json.Marshal(v) for k, re := range tests { From dbf17105f62da03972fa9350f76485f5cc7aaeb8 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 13:18:51 +0200 Subject: [PATCH 29/50] Build transaction context in BlockRes --- rpc/responses.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/rpc/responses.go b/rpc/responses.go index 9e1170c321..45a2fa18b2 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -55,11 +55,20 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { // res.MinGasPrice = res.GasUsed = newHexNum(block.GasUsed()) res.UnixTimestamp = newHexNum(block.Time()) - res.Transactions = NewTransactionsRes(block.Transactions()) + + res.Transactions = make([]*TransactionRes, len(block.Transactions())) + for i, tx := range block.Transactions() { + res.Transactions[i] = NewTransactionRes(tx) + res.Transactions[i].BlockHash = res.BlockHash + res.Transactions[i].BlockNumber = res.BlockNumber + res.Transactions[i].TxIndex = newHexNum(i) + } + res.Uncles = make([]*hexdata, len(block.Uncles())) for i, uncle := range block.Uncles() { res.Uncles[i] = newHexData(uncle.Hash()) } + return res } @@ -94,14 +103,6 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes { return v } -func NewTransactionsRes(txs []*types.Transaction) []*TransactionRes { - v := make([]*TransactionRes, len(txs)) - for i, tx := range txs { - v[i] = NewTransactionRes(tx) - } - return v -} - // type FilterLogRes struct { // Hash string `json:"hash"` // Address string `json:"address"` From e1be34bce1ddf662bca58a37a6f38fea63a2a70f Mon Sep 17 00:00:00 2001 From: zelig Date: Sat, 28 Mar 2015 00:48:37 +0000 Subject: [PATCH 30/50] eth: SEC-29 eth wire protocol decoding invalid message data crashes client - add validate method to types.Block - validate after Decode -> error - add tests for NewBlockMsg --- core/types/block.go | 20 ++++++++ eth/protocol.go | 9 ++-- eth/protocol_test.go | 117 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 124 insertions(+), 22 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index 5cdde44620..c04beae5a2 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -148,6 +148,26 @@ func NewBlockWithHeader(header *Header) *Block { return &Block{header: header} } +func (self *Block) Validate() error { + if self.header == nil { + return fmt.Errorf("header is nil") + } + // check *big.Int fields + if self.header.Difficulty == nil { + return fmt.Errorf("Difficulty undefined") + } + if self.header.GasLimit == nil { + return fmt.Errorf("GasLimit undefined") + } + if self.header.GasUsed == nil { + return fmt.Errorf("GasUsed undefined") + } + if self.header.Number == nil { + return fmt.Errorf("Number undefined") + } + return nil +} + func (self *Block) DecodeRLP(s *rlp.Stream) error { var eb extblock if err := s.Decode(&eb); err != nil { diff --git a/eth/protocol.go b/eth/protocol.go index e32ea233b0..0a3f67b62a 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -105,7 +105,7 @@ type getBlockHashesMsgData struct { type statusMsgData struct { ProtocolVersion uint32 NetworkId uint32 - TD *big.Int + TD big.Int CurrentBlock common.Hash GenesisBlock common.Hash } @@ -276,6 +276,9 @@ func (self *ethProtocol) handle() error { if err := msg.Decode(&request); err != nil { return self.protoError(ErrDecode, "%v: %v", msg, err) } + if err := request.Block.Validate(); err != nil { + return self.protoError(ErrDecode, "block validation %v: %v", msg, err) + } hash := request.Block.Hash() _, chainHead, _ := self.chainManager.Status() @@ -335,7 +338,7 @@ func (self *ethProtocol) handleStatus() error { return self.protoError(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, self.protocolVersion) } - _, suspended := self.blockPool.AddPeer(status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) + _, suspended := self.blockPool.AddPeer(&status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) if suspended { return self.protoError(ErrSuspendedPeer, "") } @@ -366,7 +369,7 @@ func (self *ethProtocol) sendStatus() error { return p2p.Send(self.rw, StatusMsg, &statusMsgData{ ProtocolVersion: uint32(self.protocolVersion), NetworkId: uint32(self.networkId), - TD: td, + TD: *td, CurrentBlock: currentBlock, GenesisBlock: genesisBlock, }) diff --git a/eth/protocol_test.go b/eth/protocol_test.go index 8ca6d1be61..7831e9bc6f 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -1,6 +1,7 @@ package eth import ( + "fmt" "log" "math/big" "os" @@ -63,6 +64,10 @@ func (self *testChainManager) GetBlockHashesFromHash(hash common.Hash, amount ui func (self *testChainManager) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) { if self.status != nil { td, currentBlock, genesisBlock = self.status() + } else { + td = common.Big1 + currentBlock = common.Hash{1} + genesisBlock = common.Hash{2} } return } @@ -163,14 +168,29 @@ func (self *ethProtocolTester) run() { self.quit <- err } +func (self *ethProtocolTester) handshake(t *testing.T, mock bool) { + td, currentBlock, genesis := self.chainManager.Status() + // first outgoing msg should be StatusMsg. + err := p2p.ExpectMsg(self, StatusMsg, &statusMsgData{ + ProtocolVersion: ProtocolVersion, + NetworkId: NetworkId, + TD: *td, + CurrentBlock: currentBlock, + GenesisBlock: genesis, + }) + if err != nil { + t.Fatalf("incorrect outgoing status: %v", err) + } + if mock { + go p2p.Send(self, StatusMsg, &statusMsgData{ProtocolVersion, NetworkId, *td, currentBlock, genesis}) + } +} + func TestStatusMsgErrors(t *testing.T) { logInit() eth := newEth(t) - td := common.Big1 - currentBlock := common.Hash{1} - genesis := common.Hash{2} - eth.chainManager.status = func() (*big.Int, common.Hash, common.Hash) { return td, currentBlock, genesis } go eth.run() + td, currentBlock, genesis := eth.chainManager.Status() tests := []struct { code uint64 @@ -182,31 +202,20 @@ func TestStatusMsgErrors(t *testing.T) { wantErrorCode: ErrNoStatusMsg, }, { - code: StatusMsg, data: statusMsgData{10, NetworkId, td, currentBlock, genesis}, + code: StatusMsg, data: statusMsgData{10, NetworkId, *td, currentBlock, genesis}, wantErrorCode: ErrProtocolVersionMismatch, }, { - code: StatusMsg, data: statusMsgData{ProtocolVersion, 999, td, currentBlock, genesis}, + code: StatusMsg, data: statusMsgData{ProtocolVersion, 999, *td, currentBlock, genesis}, wantErrorCode: ErrNetworkIdMismatch, }, { - code: StatusMsg, data: statusMsgData{ProtocolVersion, NetworkId, td, currentBlock, common.Hash{3}}, + code: StatusMsg, data: statusMsgData{ProtocolVersion, NetworkId, *td, currentBlock, common.Hash{3}}, wantErrorCode: ErrGenesisBlockMismatch, }, } for _, test := range tests { - // first outgoing msg should be StatusMsg. - err := p2p.ExpectMsg(eth, StatusMsg, &statusMsgData{ - ProtocolVersion: ProtocolVersion, - NetworkId: NetworkId, - TD: td, - CurrentBlock: currentBlock, - GenesisBlock: genesis, - }) - if err != nil { - t.Fatalf("incorrect outgoing status: %v", err) - } - + eth.handshake(t, false) // the send call might hang until reset because // the protocol might not read the payload. go p2p.Send(eth, test.code, test.data) @@ -216,3 +225,73 @@ func TestStatusMsgErrors(t *testing.T) { go eth.run() } } + +func TestNewBlockMsg(t *testing.T) { + logInit() + eth := newEth(t) + eth.blockPool.addBlock = func(block *types.Block, peerId string) (err error) { + fmt.Printf("Add Block: %v\n", block) + return + } + + var disconnected bool + eth.blockPool.removePeer = func(peerId string) { + fmt.Printf("peer <%s> is disconnected\n", peerId) + disconnected = true + } + + go eth.run() + + eth.handshake(t, true) + err := p2p.ExpectMsg(eth, TxMsg, []interface{}{}) + if err != nil { + t.Errorf("transactions expected, got %v", err) + } + + var tds = make(chan *big.Int) + eth.blockPool.addPeer = func(td *big.Int, currentBlock common.Hash, peerId string, requestHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool, suspended bool) { + tds <- td + return + } + + var delay = 1 * time.Second + // eth.reset() + block := types.NewBlock(common.Hash{1}, common.Address{1}, common.Hash{1}, common.Big1, 1, "extra") + + go p2p.Send(eth, NewBlockMsg, &newBlockMsgData{Block: block}) + timer := time.After(delay) + + select { + case td := <-tds: + if td.Cmp(common.Big0) != 0 { + t.Errorf("incorrect td %v, expected %v", td, common.Big0) + } + case <-timer: + t.Errorf("no td recorded after %v", delay) + return + case err := <-eth.quit: + t.Errorf("no error expected, got %v", err) + return + } + + go p2p.Send(eth, NewBlockMsg, &newBlockMsgData{block, common.Big2}) + timer = time.After(delay) + + select { + case td := <-tds: + if td.Cmp(common.Big2) != 0 { + t.Errorf("incorrect td %v, expected %v", td, common.Big2) + } + case <-timer: + t.Errorf("no td recorded after %v", delay) + return + case err := <-eth.quit: + t.Errorf("no error expected, got %v", err) + return + } + + go p2p.Send(eth, NewBlockMsg, []interface{}{}) + // Block.DecodeRLP: validation failed: header is nil + eth.checkError(ErrDecode, delay) + +} From d677190f3916c5bee276d9abba69814022ab967f Mon Sep 17 00:00:00 2001 From: zelig Date: Sat, 28 Mar 2015 01:54:23 +0000 Subject: [PATCH 31/50] add tests for valid blocks msg handling --- eth/protocol_test.go | 50 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/eth/protocol_test.go b/eth/protocol_test.go index 7831e9bc6f..d5ac217558 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -229,10 +229,6 @@ func TestStatusMsgErrors(t *testing.T) { func TestNewBlockMsg(t *testing.T) { logInit() eth := newEth(t) - eth.blockPool.addBlock = func(block *types.Block, peerId string) (err error) { - fmt.Printf("Add Block: %v\n", block) - return - } var disconnected bool eth.blockPool.removePeer = func(peerId string) { @@ -295,3 +291,49 @@ func TestNewBlockMsg(t *testing.T) { eth.checkError(ErrDecode, delay) } + +func TestBlockMsg(t *testing.T) { + logInit() + eth := newEth(t) + blocks := make(chan *types.Block) + eth.blockPool.addBlock = func(block *types.Block, peerId string) (err error) { + blocks <- block + return + } + + var disconnected bool + eth.blockPool.removePeer = func(peerId string) { + fmt.Printf("peer <%s> is disconnected\n", peerId) + disconnected = true + } + + go eth.run() + + eth.handshake(t, true) + err := p2p.ExpectMsg(eth, TxMsg, []interface{}{}) + if err != nil { + t.Errorf("transactions expected, got %v", err) + } + + var delay = 3 * time.Second + // eth.reset() + newblock := func(i int64) *types.Block { + return types.NewBlock(common.Hash{byte(i)}, common.Address{byte(i)}, common.Hash{byte(i)}, big.NewInt(i), uint64(i), string(i)) + } + go p2p.Send(eth, BlocksMsg, types.Blocks{newblock(0), newblock(1), newblock(2)}) + timer := time.After(delay) + for i := int64(0); i < 3; i++ { + select { + case block := <-blocks: + if (block.ParentHash() != common.Hash{byte(i)}) { + t.Errorf("incorrect block %v, expected %v", block.ParentHash(), common.Hash{byte(i)}) + } + case <-timer: + t.Errorf("no td recorded after %v", delay) + return + case err := <-eth.quit: + t.Errorf("no error expected, got %v", err) + return + } + } +} From 82da6bf4d213784cfc7ba45432f9f96c2d6b4d9d Mon Sep 17 00:00:00 2001 From: zelig Date: Mon, 30 Mar 2015 13:48:07 +0100 Subject: [PATCH 32/50] test for invalid rlp encoding of block in BlocksMsg - rename Validate -> ValidateFields not to confure consensus block validation - add nil transaction and nil uncle header validation - remove bigint field checks: rlp already decodes *big.Int to big.NewInt(0) - add test for nil header, nil transaction --- core/types/block.go | 27 ++++++++++++--------------- eth/protocol.go | 5 ++++- eth/protocol_test.go | 34 ++++++++++++++++++++++++++++------ 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index c04beae5a2..a40bac42c8 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -148,22 +148,19 @@ func NewBlockWithHeader(header *Header) *Block { return &Block{header: header} } -func (self *Block) Validate() error { +func (self *Block) ValidateFields() error { if self.header == nil { return fmt.Errorf("header is nil") } - // check *big.Int fields - if self.header.Difficulty == nil { - return fmt.Errorf("Difficulty undefined") + for i, transaction := range self.transactions { + if transaction == nil { + return fmt.Errorf("transaction %d is nil", i) + } } - if self.header.GasLimit == nil { - return fmt.Errorf("GasLimit undefined") - } - if self.header.GasUsed == nil { - return fmt.Errorf("GasUsed undefined") - } - if self.header.Number == nil { - return fmt.Errorf("Number undefined") + for i, uncle := range self.uncles { + if uncle == nil { + return fmt.Errorf("uncle %d is nil", i) + } } return nil } @@ -253,10 +250,10 @@ func (self *Block) AddReceipt(receipt *Receipt) { } func (self *Block) RlpData() interface{} { - return []interface{}{self.header, self.transactions, self.uncles} -} + // return []interface{}{self.header, self.transactions, self.uncles} + // } -func (self *Block) RlpDataForStorage() interface{} { + // func (self *Block) RlpDataForStorage() interface{} { return []interface{}{self.header, self.transactions, self.uncles, self.Td /* TODO receipts */} } diff --git a/eth/protocol.go b/eth/protocol.go index 0a3f67b62a..f0a749d337 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -268,6 +268,9 @@ func (self *ethProtocol) handle() error { return self.protoError(ErrDecode, "msg %v: %v", msg, err) } } + if err := block.ValidateFields(); err != nil { + return self.protoError(ErrDecode, "block validation %v: %v", msg, err) + } self.blockPool.AddBlock(&block, self.id) } @@ -276,7 +279,7 @@ func (self *ethProtocol) handle() error { if err := msg.Decode(&request); err != nil { return self.protoError(ErrDecode, "%v: %v", msg, err) } - if err := request.Block.Validate(); err != nil { + if err := request.Block.ValidateFields(); err != nil { return self.protoError(ErrDecode, "block validation %v: %v", msg, err) } hash := request.Block.Hash() diff --git a/eth/protocol_test.go b/eth/protocol_test.go index d5ac217558..6a8eedaddf 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -1,7 +1,6 @@ package eth import ( - "fmt" "log" "math/big" "os" @@ -227,12 +226,11 @@ func TestStatusMsgErrors(t *testing.T) { } func TestNewBlockMsg(t *testing.T) { - logInit() + // logInit() eth := newEth(t) var disconnected bool eth.blockPool.removePeer = func(peerId string) { - fmt.Printf("peer <%s> is disconnected\n", peerId) disconnected = true } @@ -293,7 +291,7 @@ func TestNewBlockMsg(t *testing.T) { } func TestBlockMsg(t *testing.T) { - logInit() + // logInit() eth := newEth(t) blocks := make(chan *types.Block) eth.blockPool.addBlock = func(block *types.Block, peerId string) (err error) { @@ -303,7 +301,6 @@ func TestBlockMsg(t *testing.T) { var disconnected bool eth.blockPool.removePeer = func(peerId string) { - fmt.Printf("peer <%s> is disconnected\n", peerId) disconnected = true } @@ -320,7 +317,9 @@ func TestBlockMsg(t *testing.T) { newblock := func(i int64) *types.Block { return types.NewBlock(common.Hash{byte(i)}, common.Address{byte(i)}, common.Hash{byte(i)}, big.NewInt(i), uint64(i), string(i)) } - go p2p.Send(eth, BlocksMsg, types.Blocks{newblock(0), newblock(1), newblock(2)}) + b := newblock(0) + b.Header().Difficulty = nil // check if nil as *big.Int decodes as 0 + go p2p.Send(eth, BlocksMsg, types.Blocks{b, newblock(1), newblock(2)}) timer := time.After(delay) for i := int64(0); i < 3; i++ { select { @@ -328,6 +327,9 @@ func TestBlockMsg(t *testing.T) { if (block.ParentHash() != common.Hash{byte(i)}) { t.Errorf("incorrect block %v, expected %v", block.ParentHash(), common.Hash{byte(i)}) } + if block.Difficulty().Cmp(big.NewInt(i)) != 0 { + t.Errorf("incorrect block %v, expected %v", block.Difficulty(), big.NewInt(i)) + } case <-timer: t.Errorf("no td recorded after %v", delay) return @@ -336,4 +338,24 @@ func TestBlockMsg(t *testing.T) { return } } + + go p2p.Send(eth, BlocksMsg, []interface{}{[]interface{}{}}) + eth.checkError(ErrDecode, delay) + if !disconnected { + t.Errorf("peer not disconnected after error") + } + + // test empty transaction + eth.reset() + go eth.run() + eth.handshake(t, true) + err = p2p.ExpectMsg(eth, TxMsg, []interface{}{}) + if err != nil { + t.Errorf("transactions expected, got %v", err) + } + b = newblock(0) + b.AddTransaction(nil) + go p2p.Send(eth, BlocksMsg, types.Blocks{b}) + eth.checkError(ErrDecode, delay) + } From 6ffea34d8bf19fb358c1a7f01e20bf25f1061c5e Mon Sep 17 00:00:00 2001 From: zelig Date: Mon, 30 Mar 2015 15:21:41 +0100 Subject: [PATCH 33/50] check TxMsg - add validation on TxMsg checking for nil - add test for nil transaction - add test for zero value transaction (no extra validation needed) --- core/types/block.go | 6 +++--- eth/protocol.go | 5 ++++- eth/protocol_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index a40bac42c8..d5cd8a21ea 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -250,10 +250,10 @@ func (self *Block) AddReceipt(receipt *Receipt) { } func (self *Block) RlpData() interface{} { - // return []interface{}{self.header, self.transactions, self.uncles} - // } + return []interface{}{self.header, self.transactions, self.uncles} +} - // func (self *Block) RlpDataForStorage() interface{} { +func (self *Block) RlpDataForStorage() interface{} { return []interface{}{self.header, self.transactions, self.uncles, self.Td /* TODO receipts */} } diff --git a/eth/protocol.go b/eth/protocol.go index f0a749d337..214eed875d 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -185,7 +185,10 @@ func (self *ethProtocol) handle() error { if err := msg.Decode(&txs); err != nil { return self.protoError(ErrDecode, "msg %v: %v", msg, err) } - for _, tx := range txs { + for i, tx := range txs { + if tx == nil { + return self.protoError(ErrDecode, "transaction %d is nil", i) + } jsonlogger.LogJson(&logger.EthTxReceived{ TxHash: tx.Hash().Hex(), RemoteId: self.peer.ID().String(), diff --git a/eth/protocol_test.go b/eth/protocol_test.go index 6a8eedaddf..2228fa0ecd 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -359,3 +359,42 @@ func TestBlockMsg(t *testing.T) { eth.checkError(ErrDecode, delay) } + +func TestTransactionsMsg(t *testing.T) { + logInit() + eth := newEth(t) + txs := make(chan *types.Transaction) + + eth.txPool.addTransactions = func(t []*types.Transaction) { + for _, tx := range t { + txs <- tx + } + } + go eth.run() + + eth.handshake(t, true) + err := p2p.ExpectMsg(eth, TxMsg, []interface{}{}) + if err != nil { + t.Errorf("transactions expected, got %v", err) + } + + var delay = 3 * time.Second + tx := &types.Transaction{} + + go p2p.Send(eth, TxMsg, []interface{}{tx, tx}) + timer := time.After(delay) + for i := int64(0); i < 2; i++ { + select { + case <-txs: + case <-timer: + return + case err := <-eth.quit: + t.Errorf("no error expected, got %v", err) + return + } + } + + go p2p.Send(eth, TxMsg, []interface{}{[]interface{}{}}) + eth.checkError(ErrDecode, delay) + +} From f56fc9cd9d13e88ee1a244ea590e249e324b8b84 Mon Sep 17 00:00:00 2001 From: zelig Date: Wed, 1 Apr 2015 12:36:49 +0100 Subject: [PATCH 34/50] change StatusMsgData.TD back to pointer type *big.Int --- eth/protocol.go | 6 +++--- eth/protocol_test.go | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/eth/protocol.go b/eth/protocol.go index 214eed875d..a0ab177cdc 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -105,7 +105,7 @@ type getBlockHashesMsgData struct { type statusMsgData struct { ProtocolVersion uint32 NetworkId uint32 - TD big.Int + TD *big.Int CurrentBlock common.Hash GenesisBlock common.Hash } @@ -344,7 +344,7 @@ func (self *ethProtocol) handleStatus() error { return self.protoError(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, self.protocolVersion) } - _, suspended := self.blockPool.AddPeer(&status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) + _, suspended := self.blockPool.AddPeer(status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) if suspended { return self.protoError(ErrSuspendedPeer, "") } @@ -375,7 +375,7 @@ func (self *ethProtocol) sendStatus() error { return p2p.Send(self.rw, StatusMsg, &statusMsgData{ ProtocolVersion: uint32(self.protocolVersion), NetworkId: uint32(self.networkId), - TD: *td, + TD: td, CurrentBlock: currentBlock, GenesisBlock: genesisBlock, }) diff --git a/eth/protocol_test.go b/eth/protocol_test.go index 2228fa0ecd..d3466326a6 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -173,7 +173,7 @@ func (self *ethProtocolTester) handshake(t *testing.T, mock bool) { err := p2p.ExpectMsg(self, StatusMsg, &statusMsgData{ ProtocolVersion: ProtocolVersion, NetworkId: NetworkId, - TD: *td, + TD: td, CurrentBlock: currentBlock, GenesisBlock: genesis, }) @@ -181,7 +181,7 @@ func (self *ethProtocolTester) handshake(t *testing.T, mock bool) { t.Fatalf("incorrect outgoing status: %v", err) } if mock { - go p2p.Send(self, StatusMsg, &statusMsgData{ProtocolVersion, NetworkId, *td, currentBlock, genesis}) + go p2p.Send(self, StatusMsg, &statusMsgData{ProtocolVersion, NetworkId, td, currentBlock, genesis}) } } @@ -201,15 +201,15 @@ func TestStatusMsgErrors(t *testing.T) { wantErrorCode: ErrNoStatusMsg, }, { - code: StatusMsg, data: statusMsgData{10, NetworkId, *td, currentBlock, genesis}, + code: StatusMsg, data: statusMsgData{10, NetworkId, td, currentBlock, genesis}, wantErrorCode: ErrProtocolVersionMismatch, }, { - code: StatusMsg, data: statusMsgData{ProtocolVersion, 999, *td, currentBlock, genesis}, + code: StatusMsg, data: statusMsgData{ProtocolVersion, 999, td, currentBlock, genesis}, wantErrorCode: ErrNetworkIdMismatch, }, { - code: StatusMsg, data: statusMsgData{ProtocolVersion, NetworkId, *td, currentBlock, common.Hash{3}}, + code: StatusMsg, data: statusMsgData{ProtocolVersion, NetworkId, td, currentBlock, common.Hash{3}}, wantErrorCode: ErrGenesisBlockMismatch, }, } From 101ea1a1e8e8f7b0592dbd06e4eca8432e2e2527 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 14:15:20 +0200 Subject: [PATCH 35/50] Make inner size before assinging. Closes #615 --- xeth/xeth.go | 1 + 1 file changed, 1 insertion(+) diff --git a/xeth/xeth.go b/xeth/xeth.go index 5a5a4650a2..5936c0fb2e 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -122,6 +122,7 @@ func cAddress(a []string) []common.Address { 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) } From 92928309b2f0e274a6103b21a650eb07e78f88ea Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 24 Mar 2015 15:36:11 +0100 Subject: [PATCH 36/50] p2p/discover: add version number to ping packet The primary motivation for doing this right now is that old PoC 8 nodes and newer PoC 9 nodes keep discovering each other, causing handshake failures. --- p2p/discover/udp.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go index 69e9f3c2e7..738a01fb7e 100644 --- a/p2p/discover/udp.go +++ b/p2p/discover/udp.go @@ -16,11 +16,14 @@ import ( var log = logger.NewLogger("P2P Discovery") +const Version = 3 + // Errors var ( errPacketTooSmall = errors.New("too small") errBadHash = errors.New("bad hash") errExpired = errors.New("expired") + errBadVersion = errors.New("version mismatch") errTimeout = errors.New("RPC timeout") errClosed = errors.New("socket closed") ) @@ -45,6 +48,7 @@ const ( // RPC request structures type ( ping struct { + Version uint // must match Version IP string // our IP Port uint16 // our port Expiration uint64 @@ -169,6 +173,7 @@ func (t *udp) ping(e *Node) error { // TODO: maybe check for ReplyTo field in callback to measure RTT errc := t.pending(e.ID, pongPacket, func(interface{}) bool { return true }) t.send(e, pingPacket, ping{ + Version: Version, IP: t.self.IP.String(), Port: uint16(t.self.TCPPort), Expiration: uint64(time.Now().Add(expiration).Unix()), @@ -371,6 +376,9 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er if expired(req.Expiration) { return errExpired } + if req.Version != Version { + return errBadVersion + } t.mutex.Lock() // Note: we're ignoring the provided IP address right now n := t.bumpOrAdd(fromID, from) From de7af720d6bb10b93d716fb0c6cf3ee0e51dc71a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 25 Mar 2015 16:45:53 +0100 Subject: [PATCH 37/50] p2p/discover: implement node bonding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This a fix for an attack vector where the discovery protocol could be used to amplify traffic in a DDOS attack. A malicious actor would send a findnode request with the IP address and UDP port of the target as the source address. The recipient of the findnode packet would then send a neighbors packet (which is 16x the size of findnode) to the victim. Our solution is to require a 'bond' with the sender of findnode. If no bond exists, the findnode packet is not processed. A bond between nodes α and β is created when α replies to a ping from β. This (initial) version of the bonding implementation might still be vulnerable against replay attacks during the expiration time window. We will add stricter source address validation later. --- p2p/discover/node.go | 43 +++- p2p/discover/table.go | 187 ++++++++++----- p2p/discover/table_test.go | 174 ++++++-------- p2p/discover/udp.go | 226 ++++++++++-------- p2p/discover/udp_test.go | 454 ++++++++++++++++++++++++------------- 5 files changed, 675 insertions(+), 409 deletions(-) diff --git a/p2p/discover/node.go b/p2p/discover/node.go index e1130e0b58..99cb549a59 100644 --- a/p2p/discover/node.go +++ b/p2p/discover/node.go @@ -13,6 +13,8 @@ import ( "net/url" "strconv" "strings" + "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/crypto" @@ -30,7 +32,8 @@ type Node struct { DiscPort int // UDP listening port for discovery protocol TCPPort int // TCP listening port for RLPx - active time.Time + // this must be set/read using atomic load and store. + activeStamp int64 } func newNode(id NodeID, addr *net.UDPAddr) *Node { @@ -39,7 +42,6 @@ func newNode(id NodeID, addr *net.UDPAddr) *Node { IP: addr.IP, DiscPort: addr.Port, TCPPort: addr.Port, - active: time.Now(), } } @@ -48,6 +50,20 @@ func (n *Node) isValid() bool { return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.TCPPort != 0 && n.DiscPort != 0 } +func (n *Node) bumpActive() { + stamp := time.Now().Unix() + atomic.StoreInt64(&n.activeStamp, stamp) +} + +func (n *Node) active() time.Time { + stamp := atomic.LoadInt64(&n.activeStamp) + return time.Unix(stamp, 0) +} + +func (n *Node) addr() *net.UDPAddr { + return &net.UDPAddr{IP: n.IP, Port: n.DiscPort} +} + // The string representation of a Node is a URL. // Please see ParseNode for a description of the format. func (n *Node) String() string { @@ -304,3 +320,26 @@ func randomID(a NodeID, n int) (b NodeID) { } return b } + +// nodeDB stores all nodes we know about. +type nodeDB struct { + mu sync.RWMutex + byID map[NodeID]*Node +} + +func (db *nodeDB) get(id NodeID) *Node { + db.mu.RLock() + defer db.mu.RUnlock() + return db.byID[id] +} + +func (db *nodeDB) add(id NodeID, addr *net.UDPAddr, tcpPort uint16) *Node { + db.mu.Lock() + defer db.mu.Unlock() + if db.byID == nil { + db.byID = make(map[NodeID]*Node) + } + n := &Node{ID: id, IP: addr.IP, DiscPort: addr.Port, TCPPort: int(tcpPort)} + db.byID[n.ID] = n + return n +} diff --git a/p2p/discover/table.go b/p2p/discover/table.go index 33b705a12b..842f55d9f3 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -14,9 +14,10 @@ import ( ) const ( - alpha = 3 // Kademlia concurrency factor - bucketSize = 16 // Kademlia bucket size - nBuckets = nodeIDBits + 1 // Number of buckets + alpha = 3 // Kademlia concurrency factor + bucketSize = 16 // Kademlia bucket size + nBuckets = nodeIDBits + 1 // Number of buckets + maxBondingPingPongs = 10 ) type Table struct { @@ -24,27 +25,50 @@ type Table struct { buckets [nBuckets]*bucket // index of known nodes by distance nursery []*Node // bootstrap nodes + bondmu sync.Mutex + bonding map[NodeID]*bondproc + bondslots chan struct{} // limits total number of active bonding processes + net transport self *Node // metadata of the local node + db *nodeDB +} + +type bondproc struct { + err error + n *Node + done chan struct{} } // transport is implemented by the UDP transport. // it is an interface so we can test without opening lots of UDP // sockets and without generating a private key. type transport interface { - ping(*Node) error - findnode(e *Node, target NodeID) ([]*Node, error) + ping(NodeID, *net.UDPAddr) error + waitping(NodeID) error + findnode(toid NodeID, addr *net.UDPAddr, target NodeID) ([]*Node, error) close() } // bucket contains nodes, ordered by their last activity. +// the entry that was most recently active is the last element +// in entries. type bucket struct { lastLookup time.Time entries []*Node } func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr) *Table { - tab := &Table{net: t, self: newNode(ourID, ourAddr)} + tab := &Table{ + net: t, + db: new(nodeDB), + self: newNode(ourID, ourAddr), + bonding: make(map[NodeID]*bondproc), + bondslots: make(chan struct{}, maxBondingPingPongs), + } + for i := 0; i < cap(tab.bondslots); i++ { + tab.bondslots <- struct{}{} + } for i := range tab.buckets { tab.buckets[i] = new(bucket) } @@ -107,8 +131,8 @@ func (tab *Table) Lookup(target NodeID) []*Node { asked[n.ID] = true pendingQueries++ go func() { - result, _ := tab.net.findnode(n, target) - reply <- result + r, _ := tab.net.findnode(n.ID, n.addr(), target) + reply <- tab.bondall(r) }() } } @@ -116,13 +140,11 @@ func (tab *Table) Lookup(target NodeID) []*Node { // we have asked all closest nodes, stop the search break } - // wait for the next reply for _, n := range <-reply { - cn := n - if !seen[n.ID] { + if n != nil && !seen[n.ID] { seen[n.ID] = true - result.push(cn, bucketSize) + result.push(n, bucketSize) } } pendingQueries-- @@ -145,8 +167,9 @@ func (tab *Table) refresh() { result := tab.Lookup(randomID(tab.self.ID, ld)) if len(result) == 0 { // bootstrap the table with a self lookup + all := tab.bondall(tab.nursery) tab.mutex.Lock() - tab.add(tab.nursery) + tab.add(all) tab.mutex.Unlock() tab.Lookup(tab.self.ID) // TODO: the Kademlia paper says that we're supposed to perform @@ -176,45 +199,105 @@ func (tab *Table) len() (n int) { return n } -// bumpOrAdd updates the activity timestamp for the given node and -// attempts to insert the node into a bucket. The returned Node might -// not be part of the table. The caller must hold tab.mutex. -func (tab *Table) bumpOrAdd(node NodeID, from *net.UDPAddr) (n *Node) { - b := tab.buckets[logdist(tab.self.ID, node)] - if n = b.bump(node); n == nil { - n = newNode(node, from) - if len(b.entries) == bucketSize { - tab.pingReplace(n, b) - } else { - b.entries = append(b.entries, n) +// bondall bonds with all given nodes concurrently and returns +// those nodes for which bonding has probably succeeded. +func (tab *Table) bondall(nodes []*Node) (result []*Node) { + rc := make(chan *Node, len(nodes)) + for i := range nodes { + go func(n *Node) { + nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCPPort)) + rc <- nn + }(nodes[i]) + } + for _ = range nodes { + if n := <-rc; n != nil { + result = append(result, n) } } - return n + return result } -func (tab *Table) pingReplace(n *Node, b *bucket) { - old := b.entries[bucketSize-1] - go func() { - if err := tab.net.ping(old); err == nil { - // it responded, we don't need to replace it. +// bond ensures the local node has a bond with the given remote node. +// It also attempts to insert the node into the table if bonding succeeds. +// The caller must not hold tab.mutex. +// +// A bond is must be established before sending findnode requests. +// Both sides must have completed a ping/pong exchange for a bond to +// exist. The total number of active bonding processes is limited in +// order to restrain network use. +// +// bond is meant to operate idempotently in that bonding with a remote +// node which still remembers a previously established bond will work. +// The remote node will simply not send a ping back, causing waitping +// to time out. +// +// If pinged is true, the remote node has just pinged us and one half +// of the process can be skipped. +func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) (*Node, error) { + var n *Node + if n = tab.db.get(id); n == nil { + tab.bondmu.Lock() + w := tab.bonding[id] + if w != nil { + // Wait for an existing bonding process to complete. + tab.bondmu.Unlock() + <-w.done + } else { + // Register a new bonding process. + w = &bondproc{done: make(chan struct{})} + tab.bonding[id] = w + tab.bondmu.Unlock() + // Do the ping/pong. The result goes into w. + tab.pingpong(w, pinged, id, addr, tcpPort) + // Unregister the process after it's done. + tab.bondmu.Lock() + delete(tab.bonding, id) + tab.bondmu.Unlock() + } + n = w.n + if w.err != nil { + return nil, w.err + } + } + tab.mutex.Lock() + defer tab.mutex.Unlock() + if b := tab.buckets[logdist(tab.self.ID, n.ID)]; !b.bump(n) { + tab.pingreplace(n, b) + } + return n, nil +} + +func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) { + <-tab.bondslots + defer func() { tab.bondslots <- struct{}{} }() + if w.err = tab.net.ping(id, addr); w.err != nil { + close(w.done) + return + } + if !pinged { + // Give the remote node a chance to ping us before we start + // sending findnode requests. If they still remember us, + // waitping will simply time out. + tab.net.waitping(id) + } + w.n = tab.db.add(id, addr, tcpPort) + close(w.done) +} + +func (tab *Table) pingreplace(new *Node, b *bucket) { + if len(b.entries) == bucketSize { + oldest := b.entries[bucketSize-1] + if err := tab.net.ping(oldest.ID, oldest.addr()); err == nil { + // The node responded, we don't need to replace it. return } - // it didn't respond, replace the node if it is still the oldest node. - tab.mutex.Lock() - if len(b.entries) > 0 && b.entries[len(b.entries)-1] == old { - // slide down other entries and put the new one in front. - // TODO: insert in correct position to keep the order - copy(b.entries[1:], b.entries) - b.entries[0] = n - } - tab.mutex.Unlock() - }() -} - -// bump updates the activity timestamp for the given node. -// The caller must hold tab.mutex. -func (tab *Table) bump(node NodeID) { - tab.buckets[logdist(tab.self.ID, node)].bump(node) + } else { + // Add a slot at the end so the last entry doesn't + // fall off when adding the new node. + b.entries = append(b.entries, nil) + } + copy(b.entries[1:], b.entries) + b.entries[0] = new } // add puts the entries into the table if their corresponding @@ -240,17 +323,17 @@ outer: } } -func (b *bucket) bump(id NodeID) *Node { - for i, n := range b.entries { - if n.ID == id { - n.active = time.Now() +func (b *bucket) bump(n *Node) bool { + for i := range b.entries { + if b.entries[i].ID == n.ID { + n.bumpActive() // move it to the front copy(b.entries[1:], b.entries[:i+1]) b.entries[0] = n - return n + return true } } - return nil + return false } // nodesByDistance is a list of nodes, ordered by diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go index 08faea68e9..95ec30bea4 100644 --- a/p2p/discover/table_test.go +++ b/p2p/discover/table_test.go @@ -2,79 +2,68 @@ package discover import ( "crypto/ecdsa" - "errors" "fmt" "math/rand" "net" "reflect" "testing" "testing/quick" - "time" "github.com/ethereum/go-ethereum/crypto" ) -func TestTable_bumpOrAddBucketAssign(t *testing.T) { - tab := newTable(nil, NodeID{}, &net.UDPAddr{}) - for i := 1; i < len(tab.buckets); i++ { - tab.bumpOrAdd(randomID(tab.self.ID, i), &net.UDPAddr{}) - } - for i, b := range tab.buckets { - if i > 0 && len(b.entries) != 1 { - t.Errorf("bucket %d has %d entries, want 1", i, len(b.entries)) +func TestTable_pingReplace(t *testing.T) { + doit := func(newNodeIsResponding, lastInBucketIsResponding bool) { + transport := newPingRecorder() + tab := newTable(transport, NodeID{}, &net.UDPAddr{}) + last := fillBucket(tab, 200) + pingSender := randomID(tab.self.ID, 200) + + // this gotPing should replace the last node + // if the last node is not responding. + transport.responding[last.ID] = lastInBucketIsResponding + transport.responding[pingSender] = newNodeIsResponding + tab.bond(true, pingSender, &net.UDPAddr{}, 0) + + // first ping goes to sender (bonding pingback) + if !transport.pinged[pingSender] { + t.Error("table did not ping back sender") + } + if newNodeIsResponding { + // second ping goes to oldest node in bucket + // to see whether it is still alive. + if !transport.pinged[last.ID] { + t.Error("table did not ping last node in bucket") + } + } + + tab.mutex.Lock() + defer tab.mutex.Unlock() + if l := len(tab.buckets[200].entries); l != bucketSize { + t.Errorf("wrong bucket size after gotPing: got %d, want %d", bucketSize, l) + } + + if lastInBucketIsResponding || !newNodeIsResponding { + if !contains(tab.buckets[200].entries, last.ID) { + t.Error("last entry was removed") + } + if contains(tab.buckets[200].entries, pingSender) { + t.Error("new entry was added") + } + } else { + if contains(tab.buckets[200].entries, last.ID) { + t.Error("last entry was not removed") + } + if !contains(tab.buckets[200].entries, pingSender) { + t.Error("new entry was not added") + } } } -} -func TestTable_bumpOrAddPingReplace(t *testing.T) { - pingC := make(pingC) - tab := newTable(pingC, NodeID{}, &net.UDPAddr{}) - last := fillBucket(tab, 200) - - // this bumpOrAdd should not replace the last node - // because the node replies to ping. - new := tab.bumpOrAdd(randomID(tab.self.ID, 200), &net.UDPAddr{}) - - pinged := <-pingC - if pinged != last.ID { - t.Fatalf("pinged wrong node: %v\nwant %v", pinged, last.ID) - } - - tab.mutex.Lock() - defer tab.mutex.Unlock() - if l := len(tab.buckets[200].entries); l != bucketSize { - t.Errorf("wrong bucket size after bumpOrAdd: got %d, want %d", bucketSize, l) - } - if !contains(tab.buckets[200].entries, last.ID) { - t.Error("last entry was removed") - } - if contains(tab.buckets[200].entries, new.ID) { - t.Error("new entry was added") - } -} - -func TestTable_bumpOrAddPingTimeout(t *testing.T) { - tab := newTable(pingC(nil), NodeID{}, &net.UDPAddr{}) - last := fillBucket(tab, 200) - - // this bumpOrAdd should replace the last node - // because the node does not reply to ping. - new := tab.bumpOrAdd(randomID(tab.self.ID, 200), &net.UDPAddr{}) - - // wait for async bucket update. damn. this needs to go away. - time.Sleep(2 * time.Millisecond) - - tab.mutex.Lock() - defer tab.mutex.Unlock() - if l := len(tab.buckets[200].entries); l != bucketSize { - t.Errorf("wrong bucket size after bumpOrAdd: got %d, want %d", bucketSize, l) - } - if contains(tab.buckets[200].entries, last.ID) { - t.Error("last entry was not removed") - } - if !contains(tab.buckets[200].entries, new.ID) { - t.Error("new entry was not added") - } + doit(true, true) + doit(false, true) + doit(false, true) + doit(false, false) } func fillBucket(tab *Table, ld int) (last *Node) { @@ -85,44 +74,27 @@ func fillBucket(tab *Table, ld int) (last *Node) { return b.entries[bucketSize-1] } -type pingC chan NodeID +type pingRecorder struct{ responding, pinged map[NodeID]bool } -func (t pingC) findnode(n *Node, target NodeID) ([]*Node, error) { +func newPingRecorder() *pingRecorder { + return &pingRecorder{make(map[NodeID]bool), make(map[NodeID]bool)} +} + +func (t *pingRecorder) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) { panic("findnode called on pingRecorder") } -func (t pingC) close() { +func (t *pingRecorder) close() { panic("close called on pingRecorder") } -func (t pingC) ping(n *Node) error { - if t == nil { - return errTimeout - } - t <- n.ID - return nil +func (t *pingRecorder) waitping(from NodeID) error { + return nil // remote always pings } - -func TestTable_bump(t *testing.T) { - tab := newTable(nil, NodeID{}, &net.UDPAddr{}) - - // add an old entry and two recent ones - oldactive := time.Now().Add(-2 * time.Minute) - old := &Node{ID: randomID(tab.self.ID, 200), active: oldactive} - others := []*Node{ - &Node{ID: randomID(tab.self.ID, 200), active: time.Now()}, - &Node{ID: randomID(tab.self.ID, 200), active: time.Now()}, - } - tab.add(append(others, old)) - if tab.buckets[200].entries[0] == old { - t.Fatal("old entry is at front of bucket") - } - - // bumping the old entry should move it to the front - tab.bump(old.ID) - if old.active == oldactive { - t.Error("activity timestamp not updated") - } - if tab.buckets[200].entries[0] != old { - t.Errorf("bumped entry did not move to the front of bucket") +func (t *pingRecorder) ping(toid NodeID, toaddr *net.UDPAddr) error { + t.pinged[toid] = true + if t.responding[toid] { + return nil + } else { + return errTimeout } } @@ -210,7 +182,7 @@ func TestTable_Lookup(t *testing.T) { t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results) } // seed table with initial node (otherwise lookup will terminate immediately) - tab.bumpOrAdd(randomID(target, 200), &net.UDPAddr{Port: 200}) + tab.add([]*Node{newNode(randomID(target, 200), &net.UDPAddr{Port: 200})}) results := tab.Lookup(target) t.Logf("results:") @@ -238,16 +210,16 @@ type findnodeOracle struct { target NodeID } -func (t findnodeOracle) findnode(n *Node, target NodeID) ([]*Node, error) { - t.t.Logf("findnode query at dist %d", n.DiscPort) +func (t findnodeOracle) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) { + t.t.Logf("findnode query at dist %d", toaddr.Port) // current log distance is encoded in port number var result []*Node - switch n.DiscPort { + switch toaddr.Port { case 0: panic("query to node at distance 0") default: // TODO: add more randomness to distances - next := n.DiscPort - 1 + next := toaddr.Port - 1 for i := 0; i < bucketSize; i++ { result = append(result, &Node{ID: randomID(t.target, next), DiscPort: next}) } @@ -255,11 +227,9 @@ func (t findnodeOracle) findnode(n *Node, target NodeID) ([]*Node, error) { return result, nil } -func (t findnodeOracle) close() {} - -func (t findnodeOracle) ping(n *Node) error { - return errors.New("ping is not supported by this transport") -} +func (t findnodeOracle) close() {} +func (t findnodeOracle) waitping(from NodeID) error { return nil } +func (t findnodeOracle) ping(toid NodeID, toaddr *net.UDPAddr) error { return nil } func hasDuplicates(slice []*Node) bool { seen := make(map[NodeID]bool) diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go index 738a01fb7e..e9ede13972 100644 --- a/p2p/discover/udp.go +++ b/p2p/discover/udp.go @@ -20,12 +20,14 @@ const Version = 3 // Errors var ( - errPacketTooSmall = errors.New("too small") - errBadHash = errors.New("bad hash") - errExpired = errors.New("expired") - errBadVersion = errors.New("version mismatch") - errTimeout = errors.New("RPC timeout") - errClosed = errors.New("socket closed") + errPacketTooSmall = errors.New("too small") + errBadHash = errors.New("bad hash") + errExpired = errors.New("expired") + errBadVersion = errors.New("version mismatch") + errUnsolicitedReply = errors.New("unsolicited reply") + errUnknownNode = errors.New("unknown node") + errTimeout = errors.New("RPC timeout") + errClosed = errors.New("socket closed") ) // Timeouts @@ -80,14 +82,27 @@ type rpcNode struct { ID NodeID } +type packet interface { + handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error +} + +type conn interface { + ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) + WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) + Close() error + LocalAddr() net.Addr +} + // udp implements the RPC protocol. type udp struct { - conn *net.UDPConn - priv *ecdsa.PrivateKey + conn conn + priv *ecdsa.PrivateKey + addpending chan *pending - replies chan reply - closing chan struct{} - nat nat.Interface + gotreply chan reply + + closing chan struct{} + nat nat.Interface *Table } @@ -124,6 +139,9 @@ type reply struct { from NodeID ptype byte data interface{} + // loop indicates whether there was + // a matching request by sending on this channel. + matched chan<- bool } // ListenUDP returns a new table that listens for UDP packets on laddr. @@ -136,15 +154,20 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface) (*Table if err != nil { return nil, err } + tab, _ := newUDP(priv, conn, natm) + log.Infoln("Listening,", tab.self) + return tab, nil +} + +func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface) (*Table, *udp) { udp := &udp{ - conn: conn, + conn: c, priv: priv, closing: make(chan struct{}), + gotreply: make(chan reply), addpending: make(chan *pending), - replies: make(chan reply), } - - realaddr := conn.LocalAddr().(*net.UDPAddr) + realaddr := c.LocalAddr().(*net.UDPAddr) if natm != nil { if !realaddr.IP.IsLoopback() { go nat.Map(natm, udp.closing, "udp", realaddr.Port, realaddr.Port, "ethereum discovery") @@ -155,11 +178,9 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface) (*Table } } udp.Table = newTable(udp, PubkeyID(&priv.PublicKey), realaddr) - go udp.loop() go udp.readLoop() - log.Infoln("Listening, ", udp.self) - return udp.Table, nil + return udp.Table, udp } func (t *udp) close() { @@ -169,10 +190,10 @@ func (t *udp) close() { } // ping sends a ping message to the given node and waits for a reply. -func (t *udp) ping(e *Node) error { +func (t *udp) ping(toid NodeID, toaddr *net.UDPAddr) error { // TODO: maybe check for ReplyTo field in callback to measure RTT - errc := t.pending(e.ID, pongPacket, func(interface{}) bool { return true }) - t.send(e, pingPacket, ping{ + errc := t.pending(toid, pongPacket, func(interface{}) bool { return true }) + t.send(toaddr, pingPacket, ping{ Version: Version, IP: t.self.IP.String(), Port: uint16(t.self.TCPPort), @@ -181,12 +202,16 @@ func (t *udp) ping(e *Node) error { return <-errc } +func (t *udp) waitping(from NodeID) error { + return <-t.pending(from, pingPacket, func(interface{}) bool { return true }) +} + // findnode sends a findnode request to the given node and waits until // the node has sent up to k neighbors. -func (t *udp) findnode(to *Node, target NodeID) ([]*Node, error) { +func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) { nodes := make([]*Node, 0, bucketSize) nreceived := 0 - errc := t.pending(to.ID, neighborsPacket, func(r interface{}) bool { + errc := t.pending(toid, neighborsPacket, func(r interface{}) bool { reply := r.(*neighbors) for _, n := range reply.Nodes { nreceived++ @@ -196,8 +221,7 @@ func (t *udp) findnode(to *Node, target NodeID) ([]*Node, error) { } return nreceived >= bucketSize }) - - t.send(to, findnodePacket, findnode{ + t.send(toaddr, findnodePacket, findnode{ Target: target, Expiration: uint64(time.Now().Add(expiration).Unix()), }) @@ -219,6 +243,17 @@ func (t *udp) pending(id NodeID, ptype byte, callback func(interface{}) bool) <- return ch } +func (t *udp) handleReply(from NodeID, ptype byte, req packet) bool { + matched := make(chan bool) + select { + case t.gotreply <- reply{from, ptype, req, matched}: + // loop will handle it + return <-matched + case <-t.closing: + return false + } +} + // loop runs in its own goroutin. it keeps track of // the refresh timer and the pending reply queue. func (t *udp) loop() { @@ -249,6 +284,7 @@ func (t *udp) loop() { for _, p := range pending { p.errc <- errClosed } + pending = nil return case p := <-t.addpending: @@ -256,18 +292,21 @@ func (t *udp) loop() { pending = append(pending, p) rearmTimeout() - case reply := <-t.replies: - // run matching callbacks, remove if they return false. + case r := <-t.gotreply: + var matched bool for i := 0; i < len(pending); i++ { - p := pending[i] - if reply.from == p.from && reply.ptype == p.ptype && p.callback(reply.data) { - p.errc <- nil - copy(pending[i:], pending[i+1:]) - pending = pending[:len(pending)-1] - i-- + if p := pending[i]; p.from == r.from && p.ptype == r.ptype { + matched = true + if p.callback(r.data) { + // callback indicates the request is done, remove it. + p.errc <- nil + copy(pending[i:], pending[i+1:]) + pending = pending[:len(pending)-1] + i-- + } } } - rearmTimeout() + r.matched <- matched case now := <-timeout.C: // notify and remove callbacks whose deadline is in the past. @@ -292,28 +331,11 @@ const ( var headSpace = make([]byte, headSize) -func (t *udp) send(to *Node, ptype byte, req interface{}) error { - b := new(bytes.Buffer) - b.Write(headSpace) - b.WriteByte(ptype) - if err := rlp.Encode(b, req); err != nil { - log.Errorln("error encoding packet:", err) - return err - } - - packet := b.Bytes() - sig, err := crypto.Sign(crypto.Sha3(packet[headSize:]), t.priv) +func (t *udp) send(toaddr *net.UDPAddr, ptype byte, req interface{}) error { + packet, err := encodePacket(t.priv, ptype, req) if err != nil { - log.Errorln("could not sign packet:", err) return err } - copy(packet[macSize:], sig) - // add the hash to the front. Note: this doesn't protect the - // packet in any way. Our public key will be part of this hash in - // the future. - copy(packet, crypto.Sha3(packet[macSize:])) - - toaddr := &net.UDPAddr{IP: to.IP, Port: to.DiscPort} log.DebugDetailf(">>> %v %T %v\n", toaddr, req, req) if _, err = t.conn.WriteToUDP(packet, toaddr); err != nil { log.DebugDetailln("UDP send failed:", err) @@ -321,6 +343,28 @@ func (t *udp) send(to *Node, ptype byte, req interface{}) error { return err } +func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte, error) { + b := new(bytes.Buffer) + b.Write(headSpace) + b.WriteByte(ptype) + if err := rlp.Encode(b, req); err != nil { + log.Errorln("error encoding packet:", err) + return nil, err + } + packet := b.Bytes() + sig, err := crypto.Sign(crypto.Sha3(packet[headSize:]), priv) + if err != nil { + log.Errorln("could not sign packet:", err) + return nil, err + } + copy(packet[macSize:], sig) + // add the hash to the front. Note: this doesn't protect the + // packet in any way. Our public key will be part of this hash in + // The future. + copy(packet, crypto.Sha3(packet[macSize:])) + return packet, nil +} + // readLoop runs in its own goroutine. it handles incoming UDP packets. func (t *udp) readLoop() { defer t.conn.Close() @@ -330,29 +374,34 @@ func (t *udp) readLoop() { if err != nil { return } - if err := t.packetIn(from, buf[:nbytes]); err != nil { + packet, fromID, hash, err := decodePacket(buf[:nbytes]) + if err != nil { log.Debugf("Bad packet from %v: %v\n", from, err) + continue } + log.DebugDetailf("<<< %v %T %v\n", from, packet, packet) + go func() { + if err := packet.handle(t, from, fromID, hash); err != nil { + log.Debugf("error handling %T from %v: %v", packet, from, err) + } + }() } } -func (t *udp) packetIn(from *net.UDPAddr, buf []byte) error { +func decodePacket(buf []byte) (packet, NodeID, []byte, error) { if len(buf) < headSize+1 { - return errPacketTooSmall + return nil, NodeID{}, nil, errPacketTooSmall } hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:] shouldhash := crypto.Sha3(buf[macSize:]) if !bytes.Equal(hash, shouldhash) { - return errBadHash + return nil, NodeID{}, nil, errBadHash } fromID, err := recoverNodeID(crypto.Sha3(buf[headSize:]), sig) if err != nil { - return err - } - - var req interface { - handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error + return nil, NodeID{}, hash, err } + var req packet switch ptype := sigdata[0]; ptype { case pingPacket: req = new(ping) @@ -363,13 +412,10 @@ func (t *udp) packetIn(from *net.UDPAddr, buf []byte) error { case neighborsPacket: req = new(neighbors) default: - return fmt.Errorf("unknown type: %d", ptype) + return nil, fromID, hash, fmt.Errorf("unknown type: %d", ptype) } - if err := rlp.Decode(bytes.NewReader(sigdata[1:]), req); err != nil { - return err - } - log.DebugDetailf("<<< %v %T %v\n", from, req, req) - return req.handle(t, from, fromID, hash) + err = rlp.Decode(bytes.NewReader(sigdata[1:]), req) + return req, fromID, hash, err } func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { @@ -379,18 +425,14 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er if req.Version != Version { return errBadVersion } - t.mutex.Lock() - // Note: we're ignoring the provided IP address right now - n := t.bumpOrAdd(fromID, from) - if req.Port != 0 { - n.TCPPort = int(req.Port) - } - t.mutex.Unlock() - - t.send(n, pongPacket, pong{ + t.send(from, pongPacket, pong{ ReplyTok: mac, Expiration: uint64(time.Now().Add(expiration).Unix()), }) + if !t.handleReply(fromID, pingPacket, req) { + // Note: we're ignoring the provided IP address right now + t.bond(true, fromID, from, req.Port) + } return nil } @@ -398,11 +440,9 @@ func (req *pong) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er if expired(req.Expiration) { return errExpired } - t.mutex.Lock() - t.bump(fromID) - t.mutex.Unlock() - - t.replies <- reply{fromID, pongPacket, req} + if !t.handleReply(fromID, pongPacket, req) { + return errUnsolicitedReply + } return nil } @@ -410,12 +450,21 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte if expired(req.Expiration) { return errExpired } + if t.db.get(fromID) == nil { + // No bond exists, we don't process the packet. This prevents + // an attack vector where the discovery protocol could be used + // to amplify traffic in a DDOS attack. A malicious actor + // would send a findnode request with the IP address and UDP + // port of the target as the source address. The recipient of + // the findnode packet would then send a neighbors packet + // (which is a much bigger packet than findnode) to the victim. + return errUnknownNode + } t.mutex.Lock() - e := t.bumpOrAdd(fromID, from) closest := t.closest(req.Target, bucketSize).entries t.mutex.Unlock() - t.send(e, neighborsPacket, neighbors{ + t.send(from, neighborsPacket, neighbors{ Nodes: closest, Expiration: uint64(time.Now().Add(expiration).Unix()), }) @@ -426,12 +475,9 @@ func (req *neighbors) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byt if expired(req.Expiration) { return errExpired } - t.mutex.Lock() - t.bump(fromID) - t.add(req.Nodes) - t.mutex.Unlock() - - t.replies <- reply{fromID, neighborsPacket, req} + if !t.handleReply(fromID, neighborsPacket, req) { + return errUnsolicitedReply + } return nil } diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go index 0a8ff63589..c6c4d78e3d 100644 --- a/p2p/discover/udp_test.go +++ b/p2p/discover/udp_test.go @@ -1,10 +1,18 @@ package discover import ( + "bytes" + "crypto/ecdsa" + "errors" "fmt" + "io" logpkg "log" "net" "os" + "path" + "reflect" + "runtime" + "sync" "testing" "time" @@ -15,22 +23,243 @@ func init() { logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel)) } -func TestUDP_ping(t *testing.T) { +type udpTest struct { + t *testing.T + pipe *dgramPipe + table *Table + udp *udp + sent [][]byte + localkey, remotekey *ecdsa.PrivateKey + remoteaddr *net.UDPAddr +} + +func newUDPTest(t *testing.T) *udpTest { + test := &udpTest{ + t: t, + pipe: newpipe(), + localkey: newkey(), + remotekey: newkey(), + remoteaddr: &net.UDPAddr{IP: net.IP{1, 2, 3, 4}, Port: 30303}, + } + test.table, test.udp = newUDP(test.localkey, test.pipe, nil) + return test +} + +// handles a packet as if it had been sent to the transport. +func (test *udpTest) packetIn(wantError error, ptype byte, data packet) error { + enc, err := encodePacket(test.remotekey, ptype, data) + if err != nil { + return test.errorf("packet (%d) encode error: %v", err) + } + test.sent = append(test.sent, enc) + err = data.handle(test.udp, test.remoteaddr, PubkeyID(&test.remotekey.PublicKey), enc[:macSize]) + if err != wantError { + return test.errorf("error mismatch: got %q, want %q", err, wantError) + } + return nil +} + +// waits for a packet to be sent by the transport. +// validate should have type func(*udpTest, X) error, where X is a packet type. +func (test *udpTest) waitPacketOut(validate interface{}) error { + dgram := test.pipe.waitPacketOut() + p, _, _, err := decodePacket(dgram) + if err != nil { + return test.errorf("sent packet decode error: %v", err) + } + fn := reflect.ValueOf(validate) + exptype := fn.Type().In(0) + if reflect.TypeOf(p) != exptype { + return test.errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype) + } + fn.Call([]reflect.Value{reflect.ValueOf(p)}) + return nil +} + +func (test *udpTest) errorf(format string, args ...interface{}) error { + _, file, line, ok := runtime.Caller(2) // errorf + waitPacketOut + if ok { + file = path.Base(file) + } else { + file = "???" + line = 1 + } + err := fmt.Errorf(format, args...) + fmt.Printf("\t%s:%d: %v\n", file, line, err) + test.t.Fail() + return err +} + +// shared test variables +var ( + futureExp = uint64(time.Now().Add(10 * time.Hour).Unix()) + testTarget = MustHexID("01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101") +) + +func TestUDP_packetErrors(t *testing.T) { + test := newUDPTest(t) + defer test.table.Close() + + test.packetIn(errExpired, pingPacket, &ping{IP: "foo", Port: 99, Version: Version}) + test.packetIn(errBadVersion, pingPacket, &ping{IP: "foo", Port: 99, Version: 99, Expiration: futureExp}) + test.packetIn(errUnsolicitedReply, pongPacket, &pong{ReplyTok: []byte{}, Expiration: futureExp}) + test.packetIn(errUnknownNode, findnodePacket, &findnode{Expiration: futureExp}) + test.packetIn(errUnsolicitedReply, neighborsPacket, &neighbors{Expiration: futureExp}) +} + +func TestUDP_pingTimeout(t *testing.T) { t.Parallel() + test := newUDPTest(t) + defer test.table.Close() - n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) - n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) - defer n1.Close() - defer n2.Close() + toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222} + toid := NodeID{1, 2, 3, 4} + if err := test.udp.ping(toid, toaddr); err != errTimeout { + t.Error("expected timeout error, got", err) + } +} - if err := n1.net.ping(n2.self); err != nil { - t.Fatalf("ping error: %v", err) +func TestUDP_findnodeTimeout(t *testing.T) { + t.Parallel() + test := newUDPTest(t) + defer test.table.Close() + + toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222} + toid := NodeID{1, 2, 3, 4} + target := NodeID{4, 5, 6, 7} + result, err := test.udp.findnode(toid, toaddr, target) + if err != errTimeout { + t.Error("expected timeout error, got", err) } - if find(n2, n1.self.ID) == nil { - t.Errorf("node 2 does not contain id of node 1") + if len(result) > 0 { + t.Error("expected empty result, got", result) } - if e := find(n1, n2.self.ID); e != nil { - t.Errorf("node 1 does contains id of node 2: %v", e) +} + +func TestUDP_findnode(t *testing.T) { + test := newUDPTest(t) + defer test.table.Close() + + // put a few nodes into the table. their exact + // distribution shouldn't matter much, altough we need to + // take care not to overflow any bucket. + target := testTarget + nodes := &nodesByDistance{target: target} + for i := 0; i < bucketSize; i++ { + nodes.push(&Node{ + IP: net.IP{1, 2, 3, byte(i)}, + DiscPort: i + 2, + TCPPort: i + 2, + ID: randomID(test.table.self.ID, i+2), + }, bucketSize) + } + test.table.add(nodes.entries) + + // ensure there's a bond with the test node, + // findnode won't be accepted otherwise. + test.table.db.add(PubkeyID(&test.remotekey.PublicKey), test.remoteaddr, 99) + + // check that closest neighbors are returned. + test.packetIn(nil, findnodePacket, &findnode{Target: testTarget, Expiration: futureExp}) + test.waitPacketOut(func(p *neighbors) { + expected := test.table.closest(testTarget, bucketSize) + if len(p.Nodes) != bucketSize { + t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize) + } + for i := range p.Nodes { + if p.Nodes[i].ID != expected.entries[i].ID { + t.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, p.Nodes[i], expected.entries[i]) + } + } + }) +} + +func TestUDP_findnodeMultiReply(t *testing.T) { + test := newUDPTest(t) + defer test.table.Close() + + // queue a pending findnode request + resultc, errc := make(chan []*Node), make(chan error) + go func() { + rid := PubkeyID(&test.remotekey.PublicKey) + ns, err := test.udp.findnode(rid, test.remoteaddr, testTarget) + if err != nil && len(ns) == 0 { + errc <- err + } else { + resultc <- ns + } + }() + + // wait for the findnode to be sent. + // after it is sent, the transport is waiting for a reply + test.waitPacketOut(func(p *findnode) { + if p.Target != testTarget { + t.Errorf("wrong target: got %v, want %v", p.Target, testTarget) + } + }) + + // send the reply as two packets. + list := []*Node{ + MustParseNode("enode://ba85011c70bcc5c04d8607d3a0ed29aa6179c092cbdda10d5d32684fb33ed01bd94f588ca8f91ac48318087dcb02eaf36773a7a453f0eedd6742af668097b29c@10.0.1.16:30303"), + MustParseNode("enode://81fa361d25f157cd421c60dcc28d8dac5ef6a89476633339c5df30287474520caca09627da18543d9079b5b288698b542d56167aa5c09111e55acdbbdf2ef799@10.0.1.16:30303"), + MustParseNode("enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301"), + MustParseNode("enode://1b5b4aa662d7cb44a7221bfba67302590b643028197a7d5214790f3bac7aaa4a3241be9e83c09cf1f6c69d007c634faae3dc1b1221793e8446c0b3a09de65960@10.0.1.16:30303"), + } + test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: list[:2]}) + test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: list[2:]}) + + // check that the sent neighbors are all returned by findnode + select { + case result := <-resultc: + if !reflect.DeepEqual(result, list) { + t.Errorf("neighbors mismatch:\n got: %v\n want: %v", result, list) + } + case err := <-errc: + t.Errorf("findnode error: %v", err) + case <-time.After(5 * time.Second): + t.Error("findnode did not return within 5 seconds") + } +} + +func TestUDP_successfulPing(t *testing.T) { + test := newUDPTest(t) + defer test.table.Close() + + done := make(chan struct{}) + go func() { + test.packetIn(nil, pingPacket, &ping{IP: "foo", Port: 99, Version: Version, Expiration: futureExp}) + close(done) + }() + + // the ping is replied to. + test.waitPacketOut(func(p *pong) { + pinghash := test.sent[0][:macSize] + if !bytes.Equal(p.ReplyTok, pinghash) { + t.Errorf("got ReplyTok %x, want %x", p.ReplyTok, pinghash) + } + }) + + // remote is unknown, the table pings back. + test.waitPacketOut(func(p *ping) error { return nil }) + test.packetIn(nil, pongPacket, &pong{Expiration: futureExp}) + + // ping should return shortly after getting the pong packet. + <-done + + // check that the node was added. + rid := PubkeyID(&test.remotekey.PublicKey) + rnode := find(test.table, rid) + if rnode == nil { + t.Fatalf("node %v not found in table", rid) + } + if !bytes.Equal(rnode.IP, test.remoteaddr.IP) { + t.Errorf("node has wrong IP: got %v, want: %v", rnode.IP, test.remoteaddr.IP) + } + if rnode.DiscPort != test.remoteaddr.Port { + t.Errorf("node has wrong Port: got %v, want: %v", rnode.DiscPort, test.remoteaddr.Port) + } + if rnode.TCPPort != 99 { + t.Errorf("node has wrong Port: got %v, want: %v", rnode.TCPPort, 99) } } @@ -45,167 +274,66 @@ func find(tab *Table, id NodeID) *Node { return nil } -func TestUDP_findnode(t *testing.T) { - t.Parallel() +// dgramPipe is a fake UDP socket. It queues all sent datagrams. +type dgramPipe struct { + mu *sync.Mutex + cond *sync.Cond + closing chan struct{} + closed bool + queue [][]byte +} - n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) - n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) - defer n1.Close() - defer n2.Close() - - // put a few nodes into n2. the exact distribution shouldn't - // matter much, altough we need to take care not to overflow - // any bucket. - target := randomID(n1.self.ID, 100) - nodes := &nodesByDistance{target: target} - for i := 0; i < bucketSize; i++ { - n2.add([]*Node{&Node{ - IP: net.IP{1, 2, 3, byte(i)}, - DiscPort: i + 2, - TCPPort: i + 2, - ID: randomID(n2.self.ID, i+2), - }}) - } - n2.add(nodes.entries) - n2.bumpOrAdd(n1.self.ID, &net.UDPAddr{IP: n1.self.IP, Port: n1.self.DiscPort}) - expected := n2.closest(target, bucketSize) - - err := runUDP(10, func() error { - result, _ := n1.net.findnode(n2.self, target) - if len(result) != bucketSize { - return fmt.Errorf("wrong number of results: got %d, want %d", len(result), bucketSize) - } - for i := range result { - if result[i].ID != expected.entries[i].ID { - return fmt.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, result[i], expected.entries[i]) - } - } - return nil - }) - if err != nil { - t.Error(err) +func newpipe() *dgramPipe { + mu := new(sync.Mutex) + return &dgramPipe{ + closing: make(chan struct{}), + cond: &sync.Cond{L: mu}, + mu: mu, } } -func TestUDP_replytimeout(t *testing.T) { - t.Parallel() - - // reserve a port so we don't talk to an existing service by accident - addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:0") - fd, err := net.ListenUDP("udp", addr) - if err != nil { - t.Fatal(err) - } - defer fd.Close() - - n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) - defer n1.Close() - n2 := n1.bumpOrAdd(randomID(n1.self.ID, 10), fd.LocalAddr().(*net.UDPAddr)) - - if err := n1.net.ping(n2); err != errTimeout { - t.Error("expected timeout error, got", err) - } - - if result, err := n1.net.findnode(n2, n1.self.ID); err != errTimeout { - t.Error("expected timeout error, got", err) - } else if len(result) > 0 { - t.Error("expected empty result, got", result) +// WriteToUDP queues a datagram. +func (c *dgramPipe) WriteToUDP(b []byte, to *net.UDPAddr) (n int, err error) { + msg := make([]byte, len(b)) + copy(msg, b) + c.mu.Lock() + defer c.mu.Unlock() + if c.closed { + return 0, errors.New("closed") } + c.queue = append(c.queue, msg) + c.cond.Signal() + return len(b), nil } -func TestUDP_findnodeMultiReply(t *testing.T) { - t.Parallel() - - n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) - n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) - udp2 := n2.net.(*udp) - defer n1.Close() - defer n2.Close() - - err := runUDP(10, func() error { - nodes := make([]*Node, bucketSize) - for i := range nodes { - nodes[i] = &Node{ - IP: net.IP{1, 2, 3, 4}, - DiscPort: i + 1, - TCPPort: i + 1, - ID: randomID(n2.self.ID, i+1), - } - } - - // ask N2 for neighbors. it will send an empty reply back. - // the request will wait for up to bucketSize replies. - resultc := make(chan []*Node) - errc := make(chan error) - go func() { - ns, err := n1.net.findnode(n2.self, n1.self.ID) - if err != nil { - errc <- err - } else { - resultc <- ns - } - }() - - // send a few more neighbors packets to N1. - // it should collect those. - for end := 0; end < len(nodes); { - off := end - if end = end + 5; end > len(nodes) { - end = len(nodes) - } - udp2.send(n1.self, neighborsPacket, neighbors{ - Nodes: nodes[off:end], - Expiration: uint64(time.Now().Add(10 * time.Second).Unix()), - }) - } - - // check that they are all returned. we cannot just check for - // equality because they might not be returned in the order they - // were sent. - var result []*Node - select { - case result = <-resultc: - case err := <-errc: - return err - } - if hasDuplicates(result) { - return fmt.Errorf("result slice contains duplicates") - } - if len(result) != len(nodes) { - return fmt.Errorf("wrong number of nodes returned: got %d, want %d", len(result), len(nodes)) - } - matched := make(map[NodeID]bool) - for _, n := range result { - for _, expn := range nodes { - if n.ID == expn.ID { // && bytes.Equal(n.Addr.IP, expn.Addr.IP) && n.Addr.Port == expn.Addr.Port { - matched[n.ID] = true - } - } - } - if len(matched) != len(nodes) { - return fmt.Errorf("wrong number of matching nodes: got %d, want %d", len(matched), len(nodes)) - } - return nil - }) - if err != nil { - t.Error(err) - } +// ReadFromUDP just hangs until the pipe is closed. +func (c *dgramPipe) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) { + <-c.closing + return 0, nil, io.EOF } -// runUDP runs a test n times and returns an error if the test failed -// in all n runs. This is necessary because UDP is unreliable even for -// connections on the local machine, causing test failures. -func runUDP(n int, test func() error) error { - errcount := 0 - errors := "" - for i := 0; i < n; i++ { - if err := test(); err != nil { - errors += fmt.Sprintf("\n#%d: %v", i, err) - errcount++ - } - } - if errcount == n { - return fmt.Errorf("failed on all %d iterations:%s", n, errors) +func (c *dgramPipe) Close() error { + c.mu.Lock() + defer c.mu.Unlock() + if !c.closed { + close(c.closing) + c.closed = true } return nil } + +func (c *dgramPipe) LocalAddr() net.Addr { + return &net.UDPAddr{} +} + +func (c *dgramPipe) waitPacketOut() []byte { + c.mu.Lock() + defer c.mu.Unlock() + for len(c.queue) == 0 { + c.cond.Wait() + } + p := c.queue[0] + copy(c.queue, c.queue[1:]) + c.queue = c.queue[:len(c.queue)-1] + return p +} From a77c431e378a3cfcddb4b33317319412799c96cb Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 30 Mar 2015 17:23:28 +0200 Subject: [PATCH 38/50] p2p/discover: fix off by one error causing buckets to contain duplicates --- p2p/discover/table.go | 2 +- p2p/discover/table_test.go | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/p2p/discover/table.go b/p2p/discover/table.go index 842f55d9f3..dbf86c0840 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -328,7 +328,7 @@ func (b *bucket) bump(n *Node) bool { if b.entries[i].ID == n.ID { n.bumpActive() // move it to the front - copy(b.entries[1:], b.entries[:i+1]) + copy(b.entries[1:], b.entries[:i]) b.entries[0] = n return true } diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go index 95ec30bea4..a98376bca3 100644 --- a/p2p/discover/table_test.go +++ b/p2p/discover/table_test.go @@ -66,6 +66,48 @@ func TestTable_pingReplace(t *testing.T) { doit(false, false) } +func TestBucket_bumpNoDuplicates(t *testing.T) { + t.Parallel() + cfg := &quick.Config{ + MaxCount: 1000, + Rand: quickrand, + Values: func(args []reflect.Value, rand *rand.Rand) { + // generate a random list of nodes. this will be the content of the bucket. + n := rand.Intn(bucketSize-1) + 1 + nodes := make([]*Node, n) + for i := range nodes { + nodes[i] = &Node{ID: randomID(NodeID{}, 200)} + } + args[0] = reflect.ValueOf(nodes) + // generate random bump positions. + bumps := make([]int, rand.Intn(100)) + for i := range bumps { + bumps[i] = rand.Intn(len(nodes)) + } + args[1] = reflect.ValueOf(bumps) + }, + } + + prop := func(nodes []*Node, bumps []int) (ok bool) { + b := &bucket{entries: make([]*Node, len(nodes))} + copy(b.entries, nodes) + for i, pos := range bumps { + b.bump(b.entries[pos]) + if hasDuplicates(b.entries) { + t.Logf("bucket has duplicates after %d/%d bumps:", i+1, len(bumps)) + for _, n := range b.entries { + t.Logf(" %p", n) + } + return false + } + } + return true + } + if err := quick.Check(prop, cfg); err != nil { + t.Error(err) + } +} + func fillBucket(tab *Table, ld int) (last *Node) { b := tab.buckets[ld] for len(b.entries) < bucketSize { From 76218959ab36828f340a113e3b3b7dffabb1f36a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 1 Apr 2015 16:59:14 +0200 Subject: [PATCH 39/50] eth: update cpp bootnode address --- eth/backend.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index b1fa68e729..cc4f807bff 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -32,8 +32,8 @@ var ( defaultBootNodes = []*discover.Node{ // ETH/DEV cmd/bootnode discover.MustParseNode("enode://09fbeec0d047e9a37e63f60f8618aa9df0e49271f3fadb2c070dc09e2099b95827b63a8b837c6fd01d0802d457dd83e3bd48bd3e6509f8209ed90dabbc30e3d3@52.16.188.185:30303"), - // ETH/DEV cpp-ethereum (poc-8.ethdev.com) - discover.MustParseNode("enode://4a44599974518ea5b0f14c31c4463692ac0329cb84851f3435e6d1b18ee4eae4aa495f846a0fa1219bd58035671881d44423876e57db2abd57254d0197da0ebe@5.1.83.226:30303"), + // ETH/DEV cpp-ethereum (poc-9.ethdev.com) + discover.MustParseNode("enode://487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a@5.1.83.226:30303"), } ) From 8e961df2830a57fadeafc2f74aca19a820b104cb Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 17:10:42 +0200 Subject: [PATCH 40/50] bumped network protocol --- eth/protocol.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/protocol.go b/eth/protocol.go index a0ab177cdc..844641d04f 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -14,7 +14,7 @@ import ( const ( ProtocolVersion = 60 - NetworkId = 0 + NetworkId = 3 ProtocolLength = uint64(8) ProtocolMaxMsgSize = 10 * 1024 * 1024 maxHashes = 256 From 216ea425e4579f95c01572d2da0d83890a05c162 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 17:36:56 +0200 Subject: [PATCH 41/50] corrected --- eth/protocol.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/protocol.go b/eth/protocol.go index 844641d04f..a0ab177cdc 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -14,7 +14,7 @@ import ( const ( ProtocolVersion = 60 - NetworkId = 3 + NetworkId = 0 ProtocolLength = uint64(8) ProtocolMaxMsgSize = 10 * 1024 * 1024 maxHashes = 256 From f801183b8bea24ce9988fbd06c2f17fedfc3587f Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 17:41:58 +0200 Subject: [PATCH 42/50] Squashed 'tests/files/' changes from 29da5ea..5f8a010 5f8a010 go fials 6f7924a add cppjit fail c21f368 update genesis test de7266b update js example test git-subtree-dir: tests/files git-subtree-split: 5f8a0103c0456f9467b402fde3db4bcde345d53b --- BasicTests/genesishashestest.json | 4 +- .../RandomTests/st201503261401CPPJIT.json | 71 +++++++++++++++++++ StateTests/RandomTests/st201504011535GO.json | 71 +++++++++++++++++++ StateTests/RandomTests/st201504011536GO.json | 71 +++++++++++++++++++ StateTests/stCallCreateCallCodeTest.json | 20 ++++-- 5 files changed, 231 insertions(+), 6 deletions(-) create mode 100644 StateTests/RandomTests/st201503261401CPPJIT.json create mode 100644 StateTests/RandomTests/st201504011535GO.json create mode 100644 StateTests/RandomTests/st201504011536GO.json diff --git a/BasicTests/genesishashestest.json b/BasicTests/genesishashestest.json index cff9691a17..4687cab9bf 100644 --- a/BasicTests/genesishashestest.json +++ b/BasicTests/genesishashestest.json @@ -1,5 +1,5 @@ { - "genesis_rlp_hex": "f90219f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080830f4240808080a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0", + "genesis_rlp_hex": "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0", "genesis_state_root": "9178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4e", - "genesis_hash": "b5d6d8402156c5c1dfadaa4b87c676b5bcadb17ef9bc8e939606daaa0d35f55d" + "genesis_hash": "fd4af92a79c7fc2fd8bf0d342f2e832e1d4f485c85b9152d2039e03bc604fdca" } diff --git a/StateTests/RandomTests/st201503261401CPPJIT.json b/StateTests/RandomTests/st201503261401CPPJIT.json new file mode 100644 index 0000000000..074fd18d2c --- /dev/null +++ b/StateTests/RandomTests/st201503261401CPPJIT.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "972201916", + "code" : "0x7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000019e7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c35036017f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b51916f2620a6e7d187a5560005155", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "912450255", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998115347875", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "24e7dcfb7ff0269a9000bedfeafad33c3ccc3610e3031c88bace245f3cbe64d2", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000019e7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c35036017f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b51916f2620a6e7d187a5560005155", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000019e7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c35036017f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b51916f2620a6e7d187a", + "gasLimit" : "0x3662e2a1", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "972201916" + } + } +} diff --git a/StateTests/RandomTests/st201504011535GO.json b/StateTests/RandomTests/st201504011535GO.json new file mode 100644 index 0000000000..449ca0407c --- /dev/null +++ b/StateTests/RandomTests/st201504011535GO.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x31417f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0315208a675944747f7430661519049a55", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "704316238", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999295683808", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "ddb8f27abb51685caa793be133df9db3912648c02498b74a0ae874294acce6f0", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x31417f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0315208a675944747f7430661519049a55", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x31417f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0315208a675944747f7430661519049a", + "gasLimit" : "0x29fb0320", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1758540724" + } + } +} diff --git a/StateTests/RandomTests/st201504011536GO.json b/StateTests/RandomTests/st201504011536GO.json new file mode 100644 index 0000000000..53b487063d --- /dev/null +++ b/StateTests/RandomTests/st201504011536GO.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x44207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000001145344846604627f5560005155", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "620442430", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999379557616", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "da70f5af0d1545ec9f0f0e28a55d3f2896bb3d64c71b4908f72ed26c345aafe4", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x44207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000001145344846604627f5560005155", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x44207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000001145344846604627f", + "gasLimit" : "0x24fb3310", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1561176030" + } + } +} diff --git a/StateTests/stCallCreateCallCodeTest.json b/StateTests/stCallCreateCallCodeTest.json index abed20ae00..04f9cc4344 100644 --- a/StateTests/stCallCreateCallCodeTest.json +++ b/StateTests/stCallCreateCallCodeTest.json @@ -868,7 +868,7 @@ } }, "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { - "balance" : "100000", + "balance" : "200000", "code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056", "nonce" : "0", "storage" : { @@ -880,17 +880,29 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999533644", + "balance" : "9999999533644", "code" : "0x", "nonce" : "1", "storage" : { } } }, - "postStateRoot" : "239c509594811741c8f3ed0a2d89abb00c0398098c80f88a82cebc153dec5c4b", + "postStateRoot" : "5500215cdbf8165ca47720ad088ae49c2441560cdf267f1c946ae7b9807cb1d4", "pre" : { + "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { + "balance" : "100000", + "code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056", + "nonce" : "0", + "storage" : { + "0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x01" : "0x42", + "0x02" : "0x23", + "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x05" : "0x54c98c81" + } + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", + "balance" : "10000000000000", "code" : "0x", "nonce" : "0", "storage" : { From 96cf776f8171c6d3aa4749a831ee73c3548545f1 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 17:45:38 +0200 Subject: [PATCH 43/50] Check stack for BALANCE. Closes #622 --- core/vm/gas.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vm/gas.go b/core/vm/gas.go index 2d5d7ae186..bfcf75149c 100644 --- a/core/vm/gas.go +++ b/core/vm/gas.go @@ -142,7 +142,7 @@ var _baseCheck = map[OpCode]req{ MSIZE: {0, GasQuickStep, true}, GAS: {0, GasQuickStep, true}, BLOCKHASH: {1, GasExtStep, true}, - BALANCE: {0, GasExtStep, true}, + BALANCE: {1, GasExtStep, true}, EXTCODESIZE: {1, GasExtStep, true}, EXTCODECOPY: {4, GasExtStep, false}, SLOAD: {1, GasStorageGet, true}, From 4e3ffbcf9bae7e44e45fd1b6e504b3645040d73c Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 17:50:19 +0200 Subject: [PATCH 44/50] Squashed 'tests/files/' changes from 5f8a010..ab81bf2 ab81bf2 go fail git-subtree-dir: tests/files git-subtree-split: ab81bf28d6157657b0a1c0d598785f1ed23fdbb1 --- StateTests/RandomTests/st201504011547GO.json | 71 ++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 StateTests/RandomTests/st201504011547GO.json diff --git a/StateTests/RandomTests/st201504011547GO.json b/StateTests/RandomTests/st201504011547GO.json new file mode 100644 index 0000000000..9e94ee7170 --- /dev/null +++ b/StateTests/RandomTests/st201504011547GO.json @@ -0,0 +1,71 @@ +{ + "randomStatetest" : { + "env" : { + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f0000000000000000000000000000000000000000000000000000000000000001207f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe406f", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1258533548", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999998741466498", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "postStateRoot" : "e1881131f80068947922f01c78464f93c46e6e11314d0deceb55809e594aec0a", + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x7f0000000000000000000000000000000000000000000000000000000000000001207f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe406f", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x7f0000000000000000000000000000000000000000000000000000000000000001207f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe406f", + "gasLimit" : "0x4b03b27e", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "781711523" + } + } +} From 516ec28544e0f9c76e18d82742d3ae58cfb59cc1 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 17:51:22 +0200 Subject: [PATCH 45/50] sha3 stack check --- core/vm/gas.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vm/gas.go b/core/vm/gas.go index bfcf75149c..976333a787 100644 --- a/core/vm/gas.go +++ b/core/vm/gas.go @@ -147,7 +147,7 @@ var _baseCheck = map[OpCode]req{ EXTCODECOPY: {4, GasExtStep, false}, SLOAD: {1, GasStorageGet, true}, SSTORE: {2, Zero, false}, - SHA3: {1, GasSha3Base, true}, + SHA3: {2, GasSha3Base, true}, CREATE: {3, GasCreate, true}, CALL: {7, GasCall, true}, CALLCODE: {7, GasCall, true}, From 344b3556ebd8c96f96d78ad2d9d386e6ed66ce0a Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 21:18:41 +0200 Subject: [PATCH 46/50] Fixed uncle rewards in miner The uncle rewards were changed in the block processor. This change will reflect those changes in the miner as well. --- core/block_processor.go | 40 +++++++++++++++++++++++----------------- miner/agent.go | 2 +- miner/worker.go | 5 +---- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/core/block_processor.go b/core/block_processor.go index f7f0cd1889..ec68dc6c94 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -210,10 +210,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big return } - // Accumulate static rewards; block reward, uncle's and uncle inclusion. - if err = sm.AccumulateRewards(state, block, parent); err != nil { + // Verify uncles + if err = sm.VerifyUncles(state, block, parent); err != nil { return } + // Accumulate static rewards; block reward, uncle's and uncle inclusion. + AccumulateRewards(state, block) // Commit state objects/accounts to a temporary trie (does not save) // used to calculate the state root. @@ -291,9 +293,27 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { return nil } -func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, parent *types.Block) error { +func AccumulateRewards(statedb *state.StateDB, block *types.Block) { reward := new(big.Int).Set(BlockReward) + for _, uncle := range block.Uncles() { + num := new(big.Int).Add(big.NewInt(8), uncle.Number) + num.Sub(num, block.Number()) + + r := new(big.Int) + r.Mul(BlockReward, num) + r.Div(r, big.NewInt(8)) + + statedb.AddBalance(uncle.Coinbase, r) + + reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32))) + } + + // Get the account associated with the coinbase + statedb.AddBalance(block.Header().Coinbase, reward) +} + +func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error { ancestors := set.New() uncles := set.New() ancestorHeaders := make(map[common.Hash]*types.Header) @@ -327,21 +347,8 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren return ValidationError(fmt.Sprintf("%v", err)) } - num := new(big.Int).Add(big.NewInt(8), uncle.Number) - num.Sub(num, block.Number()) - - r := new(big.Int) - r.Mul(BlockReward, num) - r.Div(r, big.NewInt(8)) - - statedb.AddBalance(uncle.Coinbase, r) - - reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32))) } - // Get the account associated with the coinbase - statedb.AddBalance(block.Header().Coinbase, reward) - return nil } @@ -358,7 +365,6 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro ) sm.TransitionState(state, parent, block, true) - sm.AccumulateRewards(state, block, parent) return state.Logs(), nil } diff --git a/miner/agent.go b/miner/agent.go index c650fa2f30..ad08e38418 100644 --- a/miner/agent.go +++ b/miner/agent.go @@ -60,7 +60,7 @@ out: } } - close(self.quitCurrentOp) + //close(self.quitCurrentOp) done: // Empty channel for { diff --git a/miner/worker.go b/miner/worker.go index e3680dea3f..d89519fb1f 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -270,7 +270,7 @@ gasLimit: self.current.block.SetUncles(uncles) - self.current.state.AddBalance(self.coinbase, core.BlockReward) + core.AccumulateRewards(self.current.state, self.current.block) self.current.state.Update(common.Big0) self.push() @@ -297,9 +297,6 @@ func (self *worker) commitUncle(uncle *types.Header) error { return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash())) } - self.current.state.AddBalance(uncle.Coinbase, uncleReward) - self.current.state.AddBalance(self.coinbase, inclusionReward) - return nil } From 4391c3821567b1f5718b39ed660afb6cf65eeba3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 23:22:03 +0200 Subject: [PATCH 47/50] Changed getters on account objects. Closes #610 * GetCode * GetNonce * GetStorage * GetBalance --- rpc/api.go | 5 +---- xeth/xeth.go | 10 ++++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index 660bb32513..80dd27afba 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -95,10 +95,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return err } - state := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address) - value := state.StorageString(args.Key) - - *reply = common.ToHex(value.Bytes()) + *reply = api.xethAtStateNum(args.BlockNumber).StorageAt(args.Address, args.Key) case "eth_getTransactionCount": args := new(GetTxCountArgs) if err := json.Unmarshal(req.Params, &args); err != nil { diff --git a/xeth/xeth.go b/xeth/xeth.go index 5936c0fb2e..0a813ec99c 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -308,21 +308,19 @@ func (self *XEth) NumberToHuman(balance string) string { } func (self *XEth) StorageAt(addr, storageAddr string) string { - storage := self.State().SafeGet(addr).StorageString(storageAddr) - - return common.ToHex(storage.Bytes()) + return common.ToHex(self.State().state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr))) } func (self *XEth) BalanceAt(addr string) string { - return self.State().SafeGet(addr).Balance().String() + return self.State().state.GetBalance(common.HexToAddress(addr)).String() } func (self *XEth) TxCountAt(address string) int { - return int(self.State().SafeGet(address).Nonce()) + return int(self.State().state.GetNonce(common.HexToAddress(address))) } func (self *XEth) CodeAt(address string) string { - return common.ToHex(self.State().SafeGet(address).Code()) + return common.ToHex(self.State().state.GetCode(common.HexToAddress(address))) } func (self *XEth) IsContract(address string) bool { From ab5c007376e36cde14cdb060ad4786f016c713d4 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 23:28:45 +0200 Subject: [PATCH 48/50] Updated ethereum.js --- jsre/ethereum_js.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go index 403c438bc8..fe15178fa3 100644 --- a/jsre/ethereum_js.go +++ b/jsre/ethereum_js.go @@ -1,3 +1,3 @@ package jsre -const Ethereum_JS = `require=function t(e,n,r){function o(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ay;y++)g.push(d(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(s),n.push(d(e.slice(0,s))),e=e.slice(s)):(n.push(d(e.slice(0,s))),e=e.slice(s))}),n},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:d,outputParser:h,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),i(r.toTwosComplement(t).round().toString(16),e)},u=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},s=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},c=function(t){return a(new n(t).times(new n(2).pow(128)))},l=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},f=function(t){return t=t||"0",l(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},p=function(t){return t=t||"0",new n(t,16)},m=function(t){return f(t).dividedBy(new n(2).pow(128))},d=function(t){return p(t).dividedBy(new n(2).pow(128))},h=function(t){return"0x"+t},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},y=function(t){return r.toAscii(t)},b=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:a,formatInputString:u,formatInputBool:s,formatInputReal:c,formatOutputInt:f,formatOutputUInt:p,formatOutputReal:m,formatOutputUReal:d,formatOutputHash:h,formatOutputBool:g,formatOutputString:y,formatOutputAddress:b}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},a=function(t){for(var e="",n=0;n1?(t[n[0]]||(t[n[0]]={}),t[n[0]][n[1]]=r):t[n[0]]=r})},g=function(t,e){e.forEach(function(e){var n=e.name.split("."),r={};r.get=function(){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.getter,outputFormatter:e.outputFormatter})},e.setter&&(r.set=function(t){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.setter,params:[t],inputFormatter:e.inputFormatter})}),r.enumerable=!e.newProperty,n.length>1?(t[n[0]]||(t[n[0]]={}),Object.defineProperty(t[n[0]],n[1],r)):Object.defineProperty(t,e.name,r)})},y=function(t,e,n,r){x.manager.startPolling({method:t,params:[e]},e,n,r)},b=function(t){x.manager.stopPolling(t)},v={startPolling:y.bind(null,"eth_getFilterChanges"),stopPolling:b},w={startPolling:y.bind(null,"shh_getFilterChanges"),stopPolling:b},x={version:{api:n.version},manager:f(),providers:{},setProvider:function(t){x.manager.setProvider(t)},reset:function(){x.manager.reset()},toHex:c.toHex,toAscii:c.toAscii,fromAscii:c.fromAscii,toDecimal:c.toDecimal,fromDecimal:c.fromDecimal,toBigNumber:c.toBigNumber,toWei:c.toWei,fromWei:c.fromWei,isAddress:c.isAddress,net:{},eth:{contractFromAbi:function(t){return console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=x.eth.contract(e,t);return n.address=e,n}},filter:function(t,e,n){return t._isEvent?t(e,n):s(t,v,l.outputLogFormatter)},watch:function(t,e,n){return console.warn("eth.watch() is deprecated please use eth.filter() instead."),this.filter(t,e,n)}},db:{},shh:{filter:function(t){return s(t,w,l.outputPostFormatter)},watch:function(t){return console.warn("shh.watch() is deprecated please use shh.filter() instead."),this.filter(t)}}};Object.defineProperty(x.eth,"defaultBlock",{get:function(){return p.ETH_DEFAULTBLOCK},set:function(t){return p.ETH_DEFAULTBLOCK=t,p.ETH_DEFAULTBLOCK}}),h(x,m),g(x,d),h(x.net,r.methods),g(x.net,r.properties),h(x.eth,o.methods),g(x.eth,o.properties),h(x.db,i.methods()),h(x.shh,a.methods()),h(v,u.eth()),h(w,u.shh()),e.exports=x},{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/db":10,"./web3/eth":11,"./web3/filter":13,"./web3/formatters":14,"./web3/net":17,"./web3/requestmanager":19,"./web3/shh":20,"./web3/watches":22}],9:[function(t,e){function n(t,e){t.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return c(n),l(n,t,e),f(n,t,e),p(n,t,e),n}var r=t("../web3"),o=t("../solidity/abi"),i=t("../utils/utils"),a=t("./event"),u=t("./signature"),s=function(t){r._currentContractAbi=t.abi,r._currentContractAddress=t.address,r._currentContractMethodName=t.method,r._currentContractMethodParams=t.params},c=function(t){t.call=function(e){return t._isTransaction=!1,t._options=e,t},t.sendTransaction=function(e){return t._isTransaction=!0,t._options=e,t},t.transact=function(e){return console.warn("myContract.transact() is deprecated please use myContract.sendTransaction() instead."),t.sendTransaction(e)},t._options={},["gas","gasPrice","value","from"].forEach(function(e){t[e]=function(n){return t._options[e]=n,t}})},l=function(t,e,n){var a=o.inputParser(e),c=o.outputParser(e);i.filterFunctions(e).forEach(function(o){var l=i.extractDisplayName(o.name),f=i.extractTypeName(o.name),p=function(){var i=Array.prototype.slice.call(arguments),p=u.functionSignatureFromAscii(o.name),m=a[l][f].apply(null,i),d=t._options||{};d.to=n,d.data=p+m;var h=t._isTransaction===!0||t._isTransaction!==!1&&!o.constant,g=d.collapse!==!1;if(t._options={},t._isTransaction=null,h)return s({abi:e,address:n,method:o.name,params:i}),void r.eth.sendTransaction(d);var y=r.eth.call(d),b=c[l][f](y);return g&&(1===b.length?b=b[0]:0===b.length&&(b=null)),b};void 0===t[l]&&(t[l]=p),t[l][f]=p})},f=function(t,e,n){t.address=n,t._onWatchEventResult=function(t){var n=event.getMatchingEvent(i.filterEvents(e)),r=a.outputParser(n);return r(t)},Object.defineProperty(t,"topics",{get:function(){return i.filterEvents(e).map(function(t){return u.eventSignatureFromAscii(t.name)})}})},p=function(t,e,n){i.filterEvents(e).forEach(function(e){var o=function(){var t=Array.prototype.slice.call(arguments),o=u.eventSignatureFromAscii(e.name),i=a.inputParser(n,o,e),s=i.apply(null,t),c=function(t){var n=a.outputParser(e);return n(t)};return r.eth.filter(s,void 0,void 0,c)};o._isEvent=!0;var s=i.extractDisplayName(e.name),c=i.extractTypeName(e.name);void 0===t[s]&&(t[s]=o),t[s][c]=o})},m=function(t){return t instanceof Array&&1===arguments.length?n.bind(null,t):(console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),new n(arguments[1],arguments[0]))};e.exports=m},{"../solidity/abi":1,"../utils/utils":6,"../web3":8,"./event":12,"./signature":21}],10:[function(t,e){var n=function(){return[{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"},{name:"putHex",call:"db_putHex"},{name:"getHex",call:"db_getHex"}]};e.exports={methods:n}},{}],11:[function(t,e){var n=t("./formatters"),r=t("../utils/utils"),o=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockByHash":"eth_getBlockByNumber"},i=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getTransactionByBlockHashAndIndex":"eth_getTransactionByBlockNumberAndIndex"},a=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleByBlockHashAndIndex":"eth_getUncleByBlockNumberAndIndex"},u=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockTransactionCountByHash":"eth_getBlockTransactionCountByNumber"},s=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleCountByBlockHash":"eth_getUncleCountByBlockNumber"},c=[{name:"getBalance",call:"eth_getBalance",addDefaultblock:2,outputFormatter:n.convertToBigNumber},{name:"getStorage",call:"eth_getStorage",addDefaultblock:2},{name:"getStorageAt",call:"eth_getStorageAt",addDefaultblock:3,inputFormatter:r.toHex},{name:"getCode",call:"eth_getCode",addDefaultblock:2},{name:"getBlock",call:o,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,function(t){return t?!0:!1}]},{name:"getUncle",call:a,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,r.toHex,function(t){return t?!0:!1}]},{name:"getCompilers",call:"eth_getCompilers"},{name:"getBlockTransactionCount",call:u,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getBlockUncleCount",call:s,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getTransaction",call:"eth_getTransactionByHash",outputFormatter:n.outputTransactionFormatter},{name:"getTransactionFromBlock",call:i,outputFormatter:n.outputTransactionFormatter,inputFormatter:r.toHex},{name:"getTransactionCount",call:"eth_getTransactionCount",addDefaultblock:2,outputFormatter:r.toDecimal},{name:"sendTransaction",call:"eth_sendTransaction",inputFormatter:n.inputTransactionFormatter},{name:"call",call:"eth_call",addDefaultblock:2,inputFormatter:n.inputCallFormatter},{name:"compile.solidity",call:"eth_compileSolidity"},{name:"compile.lll",call:"eth_compileLLL",inputFormatter:r.toHex},{name:"compile.serpent",call:"eth_compileSerpent",inputFormatter:r.toHex},{name:"flush",call:"eth_flush"},{name:"balanceAt",call:"eth_balanceAt",newMethod:"eth.getBalance"},{name:"stateAt",call:"eth_stateAt",newMethod:"eth.getStorageAt"},{name:"storageAt",call:"eth_storageAt",newMethod:"eth.getStorage"},{name:"countAt",call:"eth_countAt",newMethod:"eth.getTransactionCount"},{name:"codeAt",call:"eth_codeAt",newMethod:"eth.getCode"},{name:"transact",call:"eth_transact",newMethod:"eth.sendTransaction"},{name:"block",call:o,newMethod:"eth.getBlock"},{name:"transaction",call:i,newMethod:"eth.getTransaction"},{name:"uncle",call:a,newMethod:"eth.getUncle"},{name:"compilers",call:"eth_compilers",newMethod:"eth.getCompilers"},{name:"solidity",call:"eth_solidity",newMethod:"eth.compile.solidity"},{name:"lll",call:"eth_lll",newMethod:"eth.compile.lll"},{name:"serpent",call:"eth_serpent",newMethod:"eth.compile.serpent"},{name:"transactionCount",call:u,newMethod:"eth.getBlockTransactionCount"},{name:"uncleCount",call:s,newMethod:"eth.getBlockUncleCount"},{name:"logs",call:"eth_logs"}],l=[{name:"coinbase",getter:"eth_coinbase"},{name:"mining",getter:"eth_mining"},{name:"gasPrice",getter:"eth_gasPrice",outputFormatter:n.convertToBigNumber},{name:"accounts",getter:"eth_accounts"},{name:"blockNumber",getter:"eth_blockNumber",outputFormatter:r.toDecimal},{name:"listening",getter:"net_listening",setter:"eth_setListening",newProperty:"net.listening"},{name:"peerCount",getter:"net_peerCount",newProperty:"net.peerCount"},{name:"number",getter:"eth_number",newProperty:"eth.blockNumber"}];e.exports={methods:c,properties:l}},{"../utils/utils":6,"./formatters":14}],12:[function(t,e){var n=t("../solidity/abi"),r=t("../utils/utils"),o=t("./signature"),i=function(t,e){return t.filter(function(t){return t.indexed===e})},a=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},u=function(t,e){return Object.keys(e).map(function(r){var o=[a(i(t.inputs,!0),r)],u=e[r];return u instanceof Array?u.map(function(t){return n.formatInput(o,[t])}):"0x"+n.formatInput(o,[u])})},s=function(t,e,n){return function(r,o){var i=o||{};return i.address=t,i.topics=[],i.topics.push(e),r&&(i.topics=i.topics.concat(u(n,r))),i}},c=function(t,e,n){var r=e.slice(),o=n.slice();return t.reduce(function(t,e){var n;return n=e.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[e.name]=n,t},{})},l=function(t){return function(e){var o={event:r.extractDisplayName(t.name),number:e.number,hash:e.hash,args:{}};if(e.topics=e.topic,!e.topics)return o;var a=i(t.inputs,!0),u="0x"+e.topics.slice(1,e.topics.length).map(function(t){return t.slice(2)}).join(""),s=n.formatOutput(a,u),l=i(t.inputs,!1),f=n.formatOutput(l,e.data);return o.args=c(t.inputs,s,f),o}},f=function(t,e){for(var n=0;nv;v++)g.push(h(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(s),n.push(h(e.slice(0,s))),e=e.slice(s)):(n.push(h(e.slice(0,s))),e=e.slice(s))}),n},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:h,outputParser:d,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),i(r.toTwosComplement(t).round().toString(16),e)},u=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},s=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},c=function(t){return a(new n(t).times(new n(2).pow(128)))},l=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},f=function(t){return t=t||"0",l(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},p=function(t){return t=t||"0",new n(t,16)},m=function(t){return f(t).dividedBy(new n(2).pow(128))},h=function(t){return p(t).dividedBy(new n(2).pow(128))},d=function(t){return"0x"+t},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},v=function(t){return r.toAscii(t)},y=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:a,formatInputString:u,formatInputBool:s,formatInputReal:c,formatOutputInt:f,formatOutputUInt:p,formatOutputReal:m,formatOutputUReal:h,formatOutputHash:d,formatOutputBool:g,formatOutputString:v,formatOutputAddress:y}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},a=function(t){for(var e="",n=0;n1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},i.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},i.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return n.getInstance().sendAsync(t,function(n,r){t.callback(null,e.formatOutput(r))})}return this.formatOutput(n.getInstance().send(t))},e.exports=i},{"../utils/utils":6,"./errors":11,"./requestmanager":22}],19:[function(t,e){var n=t("../utils/utils"),r=t("./property"),o=[],i=[new r({name:"listening",getter:"net_listening"}),new r({name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal})];e.exports={methods:o,properties:i}},{"../utils/utils":6,"./property":20}],20:[function(t,e){var n=t("./requestmanager"),r=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};r.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},r.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},r.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},Object.defineProperty(t[n[0]],n[1],e)):Object.defineProperty(t,n[0],e)},r.prototype.get=function(){return this.formatOutput(n.getInstance().send({method:this.getter}))},r.prototype.set=function(t){return n.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=r},{"./requestmanager":22}],21:[function(t,e){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],22:[function(t,e){var n=t("./jsonrpc"),r=t("../utils/utils"),o=t("../utils/config"),i=t("./errors"),a=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};a.getInstance=function(){var t=new a;return t},a.prototype.send=function(t){if(!this.provider)return console.error(i.InvalidProvider),null;var e=n.getInstance().toPayload(t.method,t.params),r=this.provider.send(e);if(!n.getInstance().isValidResponse(r))throw i.InvalidResponse(r);return r.result},a.prototype.sendAsync=function(t,e){if(!this.provider)return e(i.InvalidProvider);var r=n.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(r,function(t,r){return t?e(t):n.getInstance().isValidResponse(r)?void e(null,r.result):e(i.InvalidResponse(r))})},a.prototype.setProvider=function(t){this.provider=t},a.prototype.startPolling=function(t,e,n,r){this.polls.push({data:t,id:e,callback:n,uninstall:r})},a.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},a.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},a.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(i.InvalidProvider);var t=n.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,o){if(!t){if(!r.isArray(o))throw i.InvalidResponse(o);o.map(function(t,n){return t.callback=e.polls[n].callback,t}).filter(function(t){var e=n.getInstance().isValidResponse(t);return e||t.callback(i.InvalidResponse(t)),e}).filter(function(t){return r.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=a},{"../utils/config":5,"../utils/utils":6,"./errors":11,"./jsonrpc":17}],23:[function(t,e){var n=t("./method"),r=t("./formatters"),o=new n({name:"post",call:"shh_post",params:1,inputFormatter:r.inputPostFormatter}),i=new n({name:"newIdentity",call:"shh_newIdentity",params:0}),a=new n({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new n({name:"newGroup",call:"shh_newGroup",params:0}),s=new n({name:"addToGroup",call:"shh_addToGroup",params:0}),c=[o,i,a,u,s];e.exports={methods:c}},{"./formatters":15,"./method":18}],24:[function(t,e){var n=t("../web3"),r=t("../utils/config"),o=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*r.ETH_SIGNATURE_LENGTH)},i=function(t){return n.sha3(n.fromAscii(t))};e.exports={functionSignatureFromAscii:o,eventSignatureFromAscii:i}},{"../utils/config":5,"../web3":8}],25:[function(t,e){var n=t("./method"),r=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new n({name:"newFilter",call:t,params:1}),r=new n({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new n({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new n({name:"poll",call:"eth_getFilterChanges",params:1});return[e,r,o,i]},o=function(){var t=new n({name:"newFilter",call:"shh_newFilter",params:1}),e=new n({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),r=new n({name:"getLogs",call:"shh_getMessages",params:1}),o=new n({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,r,o]};e.exports={eth:r,shh:o}},{"./method":18}],26:[function(){},{}],"bignumber.js":[function(t,e){"use strict";e.exports=BigNumber},{}],"ethereum.js":[function(t,e){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":8,"./lib/web3/contract":9,"./lib/web3/httpprovider":16,"./lib/web3/qtsync":21}]},{},["ethereum.js"]);` From c26c8d3a44cdd45994b6d99777d620565bab8f9c Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Thu, 2 Apr 2015 05:17:15 +0200 Subject: [PATCH 49/50] Read most protocol params from common/params.json * Add params package with exported variables generated from github.com/ethereum/common/blob/master/params.json * Use params package variables in applicable places * Add check for minimum gas limit in validation of block's gas limit * Remove common/params.json from go-ethereum to avoid outdated version of it --- core/block_processor.go | 11 ++++---- core/chain_manager.go | 14 ++++------ core/execution.go | 3 +- core/genesis.go | 8 ++---- core/state_transition.go | 9 +++--- core/vm/address.go | 15 +++++----- core/vm/common.go | 2 -- core/vm/errors.go | 3 +- core/vm/gas.go | 58 ++++++++------------------------------- core/vm/stack.go | 2 -- core/vm/vm.go | 43 +++++++++++++++-------------- core/vm/vm_jit.go | 4 +-- generators/default.json | 56 ------------------------------------- generators/defaults.go | 7 +++-- params/protocol_params.go | 54 ++++++++++++++++++++++++++++++++++++ 15 files changed, 126 insertions(+), 163 deletions(-) delete mode 100644 generators/default.json create mode 100755 params/protocol_params.go diff --git a/core/block_processor.go b/core/block_processor.go index f7f0cd1889..18667c4492 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/rlp" "gopkg.in/fatih/set.v0" @@ -252,7 +253,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big // an uncle or anything that isn't on the current block chain. // Validation validates easy over difficult (dagger takes longer time = difficult) func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { - if len(block.Extra) > 1024 { + if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 { return fmt.Errorf("Block extra data too long (%d)", len(block.Extra)) } @@ -261,13 +262,11 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) } - // TODO: use use minGasLimit and gasLimitBoundDivisor from - // https://github.com/ethereum/common/blob/master/params.json - // block.gasLimit - parent.gasLimit <= parent.gasLimit / 1024 + // block.gasLimit - parent.gasLimit <= parent.gasLimit / GasLimitBoundDivisor a := new(big.Int).Sub(block.GasLimit, parent.GasLimit) a.Abs(a) - b := new(big.Int).Div(parent.GasLimit, big.NewInt(1024)) - if !(a.Cmp(b) < 0) { + b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor) + if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) { return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b) } diff --git a/core/chain_manager.go b/core/chain_manager.go index f0d3fd4cf7..d97a94b062 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) @@ -32,18 +33,15 @@ type StateQuery interface { func CalcDifficulty(block, parent *types.Header) *big.Int { diff := new(big.Int) - diffBoundDiv := big.NewInt(2048) - min := big.NewInt(131072) - - adjust := new(big.Int).Div(parent.Difficulty, diffBoundDiv) - if (block.Time - parent.Time) < 8 { + adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor) + if big.NewInt(int64(block.Time)-int64(parent.Time)).Cmp(params.DurationLimit) < 0 { diff.Add(parent.Difficulty, adjust) } else { diff.Sub(parent.Difficulty, adjust) } - if diff.Cmp(min) < 0 { - return min + if diff.Cmp(params.MinimumDifficulty) < 0 { + return params.MinimumDifficulty } return diff @@ -76,7 +74,7 @@ func CalcGasLimit(parent, block *types.Block) *big.Int { result := new(big.Int).Add(previous, curInt) result.Div(result, big.NewInt(1024)) - return common.BigMax(GenesisGasLimit, result) + return common.BigMax(params.GenesisGasLimit, result) } type ChainManager struct { diff --git a/core/execution.go b/core/execution.go index 93fb03eccb..8134471d1d 100644 --- a/core/execution.go +++ b/core/execution.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" ) type Execution struct { @@ -43,7 +44,7 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm. env := self.env evm := self.evm - if env.Depth() == vm.MaxCallDepth { + if env.Depth() > int(params.CallCreateDepth.Int64()) { caller.ReturnGas(self.Gas, self.price) return nil, vm.DepthError{} diff --git a/core/genesis.go b/core/genesis.go index 7958157a41..13656c40cf 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -3,12 +3,12 @@ package core import ( "encoding/json" "fmt" - "math/big" "os" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" ) /* @@ -18,13 +18,11 @@ import ( var ZeroHash256 = make([]byte, 32) var ZeroHash160 = make([]byte, 20) var ZeroHash512 = make([]byte, 64) -var GenesisDiff = big.NewInt(131072) -var GenesisGasLimit = big.NewInt(3141592) func GenesisBlock(db common.Database) *types.Block { - genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, GenesisDiff, 42, "") + genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, params.GenesisDifficulty, 42, "") genesis.Header().Number = common.Big0 - genesis.Header().GasLimit = GenesisGasLimit + genesis.Header().GasLimit = params.GenesisGasLimit genesis.Header().GasUsed = common.Big0 genesis.Header().Time = 0 diff --git a/core/state_transition.go b/core/state_transition.go index 7616686dba..1994cabf63 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" ) const tryJit = false @@ -178,7 +179,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er ) // Transaction gas - if err = self.UseGas(vm.GasTx); err != nil { + if err = self.UseGas(params.TxGas); err != nil { return nil, nil, InvalidTxError(err) } @@ -186,9 +187,9 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er dgas := new(big.Int) for _, byt := range self.data { if byt != 0 { - dgas.Add(dgas, vm.GasTxDataNonzeroByte) + dgas.Add(dgas, params.TxDataNonZeroGas) } else { - dgas.Add(dgas, vm.GasTxDataZeroByte) + dgas.Add(dgas, params.TxDataZeroGas) } } @@ -202,7 +203,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er ret, err, ref = vmenv.Create(sender, self.msg.Data(), self.gas, self.gasPrice, self.value) if err == nil { dataGas := big.NewInt(int64(len(ret))) - dataGas.Mul(dataGas, vm.GasCreateByte) + dataGas.Mul(dataGas, params.CreateDataGas) if err := self.UseGas(dataGas); err == nil { ref.SetCode(ret) } else { diff --git a/core/vm/address.go b/core/vm/address.go index 0b3a95dd08..df801863fc 100644 --- a/core/vm/address.go +++ b/core/vm/address.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" ) type Address interface { @@ -27,28 +28,28 @@ func PrecompiledContracts() map[string]*PrecompiledAccount { return map[string]*PrecompiledAccount{ // ECRECOVER string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int { - return GasEcrecover + return params.EcrecoverGas }, ecrecoverFunc}, // SHA256 string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int { n := big.NewInt(int64(l+31) / 32) - n.Mul(n, GasSha256Word) - return n.Add(n, GasSha256Base) + n.Mul(n, params.Sha256WordGas) + return n.Add(n, params.Sha256Gas) }, sha256Func}, // RIPEMD160 string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int { n := big.NewInt(int64(l+31) / 32) - n.Mul(n, GasRipemdWord) - return n.Add(n, GasRipemdBase) + n.Mul(n, params.Ripemd160WordGas) + return n.Add(n, params.Ripemd160Gas) }, ripemd160Func}, string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int { n := big.NewInt(int64(l+31) / 32) - n.Mul(n, GasIdentityWord) + n.Mul(n, params.IdentityWordGas) - return n.Add(n, GasIdentityBase) + return n.Add(n, params.IdentityGas) }, memCpy}, } } diff --git a/core/vm/common.go b/core/vm/common.go index 5ff4e05f2d..0a93c3dd96 100644 --- a/core/vm/common.go +++ b/core/vm/common.go @@ -20,8 +20,6 @@ const ( JitVmTy MaxVmTy - MaxCallDepth = 1025 - LogTyPretty byte = 0x1 LogTyDiff byte = 0x2 ) diff --git a/core/vm/errors.go b/core/vm/errors.go index ab011bd624..fc3459de09 100644 --- a/core/vm/errors.go +++ b/core/vm/errors.go @@ -2,6 +2,7 @@ package vm import ( "fmt" + "github.com/ethereum/go-ethereum/params" "math/big" ) @@ -42,7 +43,7 @@ func IsStack(err error) bool { type DepthError struct{} func (self DepthError) Error() string { - return fmt.Sprintf("Max call depth exceeded (%d)", MaxCallDepth) + return fmt.Sprintf("Max call depth exceeded (%d)", params.CallCreateDepth) } func IsDepthErr(err error) bool { diff --git a/core/vm/gas.go b/core/vm/gas.go index 976333a787..f7abe63f8f 100644 --- a/core/vm/gas.go +++ b/core/vm/gas.go @@ -2,6 +2,7 @@ package vm import ( "fmt" + "github.com/ethereum/go-ethereum/params" "math/big" ) @@ -13,45 +14,10 @@ var ( GasSlowStep = big.NewInt(10) GasExtStep = big.NewInt(20) - GasStorageGet = big.NewInt(50) - GasStorageAdd = big.NewInt(20000) - GasStorageMod = big.NewInt(5000) - GasLogBase = big.NewInt(375) - GasLogTopic = big.NewInt(375) - GasLogByte = big.NewInt(8) - GasCreate = big.NewInt(32000) - GasCreateByte = big.NewInt(200) - GasCall = big.NewInt(40) - GasCallValueTransfer = big.NewInt(9000) - GasStipend = big.NewInt(2300) - GasCallNewAccount = big.NewInt(25000) - GasReturn = big.NewInt(0) - GasStop = big.NewInt(0) - GasJumpDest = big.NewInt(1) + GasReturn = big.NewInt(0) + GasStop = big.NewInt(0) - RefundStorage = big.NewInt(15000) - RefundSuicide = big.NewInt(24000) - - GasMemWord = big.NewInt(3) - GasQuadCoeffDenom = big.NewInt(512) - GasContractByte = big.NewInt(200) - GasTransaction = big.NewInt(21000) - GasTxDataNonzeroByte = big.NewInt(68) - GasTxDataZeroByte = big.NewInt(4) - GasTx = big.NewInt(21000) - GasExp = big.NewInt(10) - GasExpByte = big.NewInt(10) - - GasSha3Base = big.NewInt(30) - GasSha3Word = big.NewInt(6) - GasSha256Base = big.NewInt(60) - GasSha256Word = big.NewInt(12) - GasRipemdBase = big.NewInt(600) - GasRipemdWord = big.NewInt(12) - GasEcrecover = big.NewInt(3000) - GasIdentityBase = big.NewInt(15) - GasIdentityWord = big.NewInt(3) - GasCopyWord = big.NewInt(3) + GasContractByte = big.NewInt(200) ) func baseCheck(op OpCode, stack *stack, gas *big.Int) error { @@ -71,8 +37,8 @@ func baseCheck(op OpCode, stack *stack, gas *big.Int) error { return err } - if r.stackPush && len(stack.data)-r.stackPop+1 > 1024 { - return fmt.Errorf("stack limit reached (%d)", maxStack) + if r.stackPush && len(stack.data)-r.stackPop+1 > int(params.StackLimit.Int64()) { + return fmt.Errorf("stack limit reached (%d)", params.StackLimit.Int64()) } gas.Add(gas, r.gas) @@ -145,13 +111,13 @@ var _baseCheck = map[OpCode]req{ BALANCE: {1, GasExtStep, true}, EXTCODESIZE: {1, GasExtStep, true}, EXTCODECOPY: {4, GasExtStep, false}, - SLOAD: {1, GasStorageGet, true}, + SLOAD: {1, params.SloadGas, true}, SSTORE: {2, Zero, false}, - SHA3: {2, GasSha3Base, true}, - CREATE: {3, GasCreate, true}, - CALL: {7, GasCall, true}, - CALLCODE: {7, GasCall, true}, - JUMPDEST: {0, GasJumpDest, false}, + SHA3: {2, params.Sha3Gas, true}, + CREATE: {3, params.CreateGas, true}, + CALL: {7, params.CallGas, true}, + CALLCODE: {7, params.CallGas, true}, + JUMPDEST: {0, params.JumpdestGas, false}, SUICIDE: {1, Zero, false}, RETURN: {2, Zero, false}, PUSH1: {0, GasFastestStep, true}, diff --git a/core/vm/stack.go b/core/vm/stack.go index 1686377082..bb232d0b91 100644 --- a/core/vm/stack.go +++ b/core/vm/stack.go @@ -5,8 +5,6 @@ import ( "math/big" ) -const maxStack = 1024 - func newStack() *stack { return &stack{} } diff --git a/core/vm/vm.go b/core/vm/vm.go index 59c64e8a3e..6222ef8c24 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" ) type Vm struct { @@ -640,7 +641,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) { } else { // gas < len(ret) * CreateDataGas == NO_CODE dataGas := big.NewInt(int64(len(ret))) - dataGas.Mul(dataGas, GasCreateByte) + dataGas.Mul(dataGas, params.CreateDataGas) if context.UseGas(dataGas) { ref.SetCode(ret) } @@ -667,7 +668,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) { args := mem.Get(inOffset.Int64(), inSize.Int64()) if len(value.Bytes()) > 0 { - gas.Add(gas, GasStipend) + gas.Add(gas, params.CallStipend) } var ( @@ -759,13 +760,13 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1] - gas.Add(gas, GasLogBase) - gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic)) - gas.Add(gas, new(big.Int).Mul(mSize, GasLogByte)) + gas.Add(gas, params.LogGas) + gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas)) + gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas)) newMemSize = calcMemSize(mStart, mSize) case EXP: - gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), GasExpByte)) + gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas)) case SSTORE: err := stack.require(2) if err != nil { @@ -777,19 +778,19 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo val := statedb.GetState(context.Address(), common.BigToHash(x)) if len(val) == 0 && len(y.Bytes()) > 0 { // 0 => non 0 - g = GasStorageAdd + g = params.SstoreSetGas } else if len(val) > 0 && len(y.Bytes()) == 0 { - statedb.Refund(self.env.Origin(), RefundStorage) + statedb.Refund(self.env.Origin(), params.SstoreRefundGas) - g = GasStorageMod + g = params.SstoreClearGas } else { // non 0 => non 0 (or 0 => 0) - g = GasStorageMod + g = params.SstoreClearGas } gas.Set(g) case SUICIDE: if !statedb.IsDeleted(context.Address()) { - statedb.Refund(self.env.Origin(), RefundSuicide) + statedb.Refund(self.env.Origin(), params.SuicideRefundGas) } case MLOAD: newMemSize = calcMemSize(stack.peek(), u256(32)) @@ -803,22 +804,22 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) words := toWordSize(stack.data[stack.len()-2]) - gas.Add(gas, words.Mul(words, GasSha3Word)) + gas.Add(gas, words.Mul(words, params.Sha3WordGas)) case CALLDATACOPY: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3]) - gas.Add(gas, words.Mul(words, GasCopyWord)) + gas.Add(gas, words.Mul(words, params.CopyGas)) case CODECOPY: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3]) - gas.Add(gas, words.Mul(words, GasCopyWord)) + gas.Add(gas, words.Mul(words, params.CopyGas)) case EXTCODECOPY: newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4]) words := toWordSize(stack.data[stack.len()-4]) - gas.Add(gas, words.Mul(words, GasCopyWord)) + gas.Add(gas, words.Mul(words, params.CopyGas)) case CREATE: newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3]) @@ -827,12 +828,12 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo if op == CALL { if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil { - gas.Add(gas, GasCallNewAccount) + gas.Add(gas, params.CallNewAccountGas) } } if len(stack.data[stack.len()-3].Bytes()) > 0 { - gas.Add(gas, GasCallValueTransfer) + gas.Add(gas, params.CallValueTransferGas) } x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7]) @@ -848,13 +849,13 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { oldSize := toWordSize(big.NewInt(int64(mem.Len()))) pow := new(big.Int).Exp(oldSize, common.Big2, Zero) - linCoef := new(big.Int).Mul(oldSize, GasMemWord) - quadCoef := new(big.Int).Div(pow, GasQuadCoeffDenom) + linCoef := new(big.Int).Mul(oldSize, params.MemoryGas) + quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv) oldTotalFee := new(big.Int).Add(linCoef, quadCoef) pow.Exp(newMemSizeWords, common.Big2, Zero) - linCoef = new(big.Int).Mul(newMemSizeWords, GasMemWord) - quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom) + linCoef = new(big.Int).Mul(newMemSizeWords, params.MemoryGas) + quadCoef = new(big.Int).Div(pow, params.QuadCoeffDiv) newTotalFee := new(big.Int).Add(linCoef, quadCoef) fee := new(big.Int).Sub(newTotalFee, oldTotalFee) diff --git a/core/vm/vm_jit.go b/core/vm/vm_jit.go index 2b88d86202..991ade3186 100644 --- a/core/vm/vm_jit.go +++ b/core/vm/vm_jit.go @@ -18,8 +18,8 @@ import ( "bytes" "errors" "fmt" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/crypto" "math/big" "unsafe" ) @@ -330,7 +330,7 @@ func env_create(_vm unsafe.Pointer, _gas *int64, _value unsafe.Pointer, initData ret, suberr, ref := vm.env.Create(vm.me, nil, initData, gas, vm.price, value) if suberr == nil { dataGas := big.NewInt(int64(len(ret))) // TODO: Nto the best design. env.Create can do it, it has the reference to gas counter - dataGas.Mul(dataGas, GasCreateByte) + dataGas.Mul(dataGas, params.CreateDataGas) gas.Sub(gas, dataGas) *result = hash2llvm(ref.Address()) } diff --git a/generators/default.json b/generators/default.json deleted file mode 100644 index 181a9dd54a..0000000000 --- a/generators/default.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "genesisGasLimit": { "v": 1000000, "d": "Gas limit of the Genesis block." }, - "minGasLimit": { "v": 125000, "d": "Minimum the gas limit may ever be." }, - "gasLimitBoundDivisor": { "v": 1024, "d": "The bound divisor of the gas limit, used in update calculations." }, - "genesisDifficulty": { "v": 131072, "d": "Difficulty of the Genesis block." }, - "minimumDifficulty": { "v": 131072, "d": "The minimum that the difficulty may ever be." }, - "difficultyBoundDivisor": { "v": 2048, "d": "The bound divisor of the difficulty, used in the update calculations." }, - "durationLimit": { "v": 8, "d": "The decision boundary on the blocktime duration used to determine whether difficulty should go up or not." }, - "maximumExtraDataSize": { "v": 1024, "d": "Maximum size extra data may be after Genesis." }, - "epochDuration": { "v": 30000, "d": "Duration between proof-of-work epochs." }, - "stackLimit": { "v": 1024, "d": "Maximum size of VM stack allowed." }, - - "tierStepGas": { "v": [ 0, 2, 3, 5, 8, 10, 20 ], "d": "Once per operation, for a selection of them." }, - "expGas": { "v": 10, "d": "Once per EXP instuction." }, - "expByteGas": { "v": 10, "d": "Times ceil(log256(exponent)) for the EXP instruction." }, - - "sha3Gas": { "v": 30, "d": "Once per SHA3 operation." }, - "sha3WordGas": { "v": 6, "d": "Once per word of the SHA3 operation's data." }, - - "sloadGas": { "v": 50, "d": "Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added." }, - "sstoreSetGas": { "v": 20000, "d": "Once per SLOAD operation." }, - "sstoreResetGas": { "v": 5000, "d": "Once per SSTORE operation if the zeroness changes from zero." }, - "sstoreClearGas": { "v": 5000, "d": "Once per SSTORE operation if the zeroness doesn't change." }, - "sstoreRefundGas": { "v": 15000, "d": "Once per SSTORE operation if the zeroness changes to zero." }, - "jumpdestGas": { "v": 1, "d": "Refunded gas, once per SSTORE operation if the zeroness changes to zero." }, - - "logGas": { "v": 375, "d": "Per LOG* operation." }, - "logDataGas": { "v": 8, "d": "Per byte in a LOG* operation's data." }, - "logTopicGas": { "v": 375, "d": "Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas." }, - - "createGas": { "v": 32000, "d": "Once per CREATE operation & contract-creation transaction." }, - - "callGas": { "v": 40, "d": "Once per CALL operation & message call transaction." }, - "callStipend": { "v": 2300, "d": "Free gas given at beginning of call." }, - "callValueTransferGas": { "v": 9000, "d": "Paid for CALL when the value transfor is non-zero." }, - "callNewAccountGas": { "v": 25000, "d": "Paid for CALL when the destination address didn't exist prior." }, - - "suicideRefundGas": { "v": 24000, "d": "Refunded following a suicide operation." }, - "memoryGas": { "v": 3, "d": "Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL." }, - "quadCoeffDiv": { "v": 512, "d": "Divisor for the quadratic particle of the memory cost equation." }, - - "createDataGas": { "v": 200, "d": "" }, - "txGas": { "v": 21000, "d": "Per transaction. NOTE: Not payable on data of calls between transactions." }, - "txDataZeroGas": { "v": 4, "d": "Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions." }, - "txDataNonZeroGas": { "v": 68, "d": "Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions." }, - - "copyGas": { "v": 3, "d": "" }, - - "ecrecoverGas": { "v": 3000, "d": "" }, - "sha256Gas": { "v": 60, "d": "" }, - "sha256WordGas": { "v": 12, "d": "" }, - "ripemd160Gas": { "v": 600, "d": "" }, - "ripemd160WordGas": { "v": 120, "d": "" }, - "identityGas": { "v": 15, "d": "" }, - "identityWordGas": { "v": 3, "d": ""} -} diff --git a/generators/defaults.go b/generators/defaults.go index b0c71111cf..41d46729c5 100644 --- a/generators/defaults.go +++ b/generators/defaults.go @@ -35,13 +35,16 @@ func main() { m := make(map[string]setting) json.Unmarshal(content, &m) - filepath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "core", os.Args[2]) + filepath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "params", os.Args[2]) output, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE, os.ModePerm /*0777*/) if err != nil { fatal("error opening file for writing %v\n", err) } - output.WriteString(`package core + output.WriteString(`// DO NOT EDIT!!! +// AUTOGENERATED FROM generators/defaults.go + +package params import "math/big" diff --git a/params/protocol_params.go b/params/protocol_params.go new file mode 100755 index 0000000000..d0bc2f4ad8 --- /dev/null +++ b/params/protocol_params.go @@ -0,0 +1,54 @@ +// DO NOT EDIT!!! +// AUTOGENERATED FROM generators/defaults.go + +package params + +import "math/big" + +var ( + MaximumExtraDataSize = big.NewInt(1024) // Maximum size extra data may be after Genesis. + ExpByteGas = big.NewInt(10) // Times ceil(log256(exponent)) for the EXP instruction. + SloadGas = big.NewInt(50) // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added. + CallValueTransferGas = big.NewInt(9000) // Paid for CALL when the value transfor is non-zero. + CallNewAccountGas = big.NewInt(25000) // Paid for CALL when the destination address didn't exist prior. + TxGas = big.NewInt(21000) // Per transaction. NOTE: Not payable on data of calls between transactions. + TxDataZeroGas = big.NewInt(4) // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. + GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block. + DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. + QuadCoeffDiv = big.NewInt(512) // Divisor for the quadratic particle of the memory cost equation. + GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block. + DurationLimit = big.NewInt(8) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + SstoreSetGas = big.NewInt(20000) // Once per SLOAD operation. + LogDataGas = big.NewInt(8) // Per byte in a LOG* operation's data. + CallStipend = big.NewInt(2300) // Free gas given at beginning of call. + EcrecoverGas = big.NewInt(3000) // + Sha256WordGas = big.NewInt(12) // + MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be. + Sha3Gas = big.NewInt(30) // Once per SHA3 operation. + Sha256Gas = big.NewInt(60) // + IdentityWordGas = big.NewInt(3) // + Sha3WordGas = big.NewInt(6) // Once per word of the SHA3 operation's data. + SstoreResetGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness changes from zero. + SstoreClearGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness doesn't change. + SstoreRefundGas = big.NewInt(15000) // Once per SSTORE operation if the zeroness changes to zero. + JumpdestGas = big.NewInt(1) // Refunded gas, once per SSTORE operation if the zeroness changes to zero. + IdentityGas = big.NewInt(15) // + GasLimitBoundDivisor = big.NewInt(1024) // The bound divisor of the gas limit, used in update calculations. + EpochDuration = big.NewInt(30000) // Duration between proof-of-work epochs. + CallGas = big.NewInt(40) // Once per CALL operation & message call transaction. + CreateDataGas = big.NewInt(200) // + Ripemd160Gas = big.NewInt(600) // + Ripemd160WordGas = big.NewInt(120) // + MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. + CallCreateDepth = big.NewInt(1024) // Maximum depth of call/create stack. + ExpGas = big.NewInt(10) // Once per EXP instuction. + LogGas = big.NewInt(375) // Per LOG* operation. + CopyGas = big.NewInt(3) // + StackLimit = big.NewInt(1024) // Maximum size of VM stack allowed. + TierStepGas = big.NewInt(0) // Once per operation, for a selection of them. + LogTopicGas = big.NewInt(375) // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. + CreateGas = big.NewInt(32000) // Once per CREATE operation & contract-creation transaction. + SuicideRefundGas = big.NewInt(24000) // Refunded following a suicide operation. + MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. + TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. +) From b8124ec79182dbf90b28c8527f2440cea6473f1b Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 1 Apr 2015 23:58:26 +0200 Subject: [PATCH 50/50] Removed old (unused) argument --- core/block_processor.go | 4 ++-- core/chain_makers.go | 4 ++-- core/state/state_test.go | 2 +- core/state/statedb.go | 2 +- miner/worker.go | 2 +- tests/blocktest.go | 2 +- tests/helper/vm.go | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/block_processor.go b/core/block_processor.go index 0591fd26e3..97c8855361 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -84,7 +84,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated } // Update the state with pending changes - statedb.Update(nil) + statedb.Update() cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas)) receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative) @@ -220,7 +220,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big // Commit state objects/accounts to a temporary trie (does not save) // used to calculate the state root. - state.Update(common.Big0) + state.Update() if header.Root != state.Root() { err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return diff --git a/core/chain_makers.go b/core/chain_makers.go index d559b2a3ae..52cb367c50 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -5,10 +5,10 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/pow" - "github.com/ethereum/go-ethereum/core/state" ) // So we can generate blocks easily @@ -81,7 +81,7 @@ func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Datab cbase := state.GetOrNewStateObject(addr) cbase.SetGasPool(CalcGasLimit(parent, block)) cbase.AddBalance(BlockReward) - state.Update(common.Big0) + state.Update() block.SetRoot(state.Root()) return block } diff --git a/core/state/state_test.go b/core/state/state_test.go index da597d773d..09a65de54c 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -72,7 +72,7 @@ func TestNull(t *testing.T) { //value := common.FromHex("0x823140710bf13990e4500136726d8b55") value := make([]byte, 16) state.SetState(address, common.Hash{}, value) - state.Update(nil) + state.Update() state.Sync() value = state.GetState(address, common.Hash{}) } diff --git a/core/state/statedb.go b/core/state/statedb.go index 2dc8239ef8..e69bb34fe5 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -316,7 +316,7 @@ func (self *StateDB) Refunds() map[string]*big.Int { return self.refund } -func (self *StateDB) Update(gasUsed *big.Int) { +func (self *StateDB) Update() { self.refund = make(map[string]*big.Int) for _, stateObject := range self.stateObjects { diff --git a/miner/worker.go b/miner/worker.go index d89519fb1f..2ba3faed85 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -272,7 +272,7 @@ gasLimit: core.AccumulateRewards(self.current.state, self.current.block) - self.current.state.Update(common.Big0) + self.current.state.Update() self.push() } diff --git a/tests/blocktest.go b/tests/blocktest.go index fc62eda58d..1c4f1c2f25 100644 --- a/tests/blocktest.go +++ b/tests/blocktest.go @@ -114,7 +114,7 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) { } } // sync objects to trie - statedb.Update(nil) + statedb.Update() // sync trie to disk statedb.Sync() diff --git a/tests/helper/vm.go b/tests/helper/vm.go index 052ad6a6ed..9f62ada950 100644 --- a/tests/helper/vm.go +++ b/tests/helper/vm.go @@ -185,7 +185,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state. if core.IsNonceErr(err) || core.IsInvalidTxErr(err) { statedb.Set(snapshot) } - statedb.Update(vmenv.Gas) + statedb.Update() return ret, vmenv.logs, vmenv.Gas, err }