Merge branch 'develop' into bzz

This commit is contained in:
Daniel A. Nagy 2015-04-02 10:30:27 +02:00
commit b083b0329a
77 changed files with 4001 additions and 1051 deletions

4
Godeps/Godeps.json generated
View file

@ -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"

4
Godeps/_workspace/src/github.com/rs/cors/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,4 @@
language: go
go:
- 1.3
- 1.4

19
Godeps/_workspace/src/github.com/rs/cors/LICENSE generated vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2014 Olivier Poitrey <rs@dailymotion.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

84
Godeps/_workspace/src/github.com/rs/cors/README.md generated vendored Normal file
View file

@ -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).

37
Godeps/_workspace/src/github.com/rs/cors/bench_test.go generated vendored Normal file
View file

@ -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)
}
}

308
Godeps/_workspace/src/github.com/rs/cors/cors.go generated vendored Normal file
View file

@ -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
}

288
Godeps/_workspace/src/github.com/rs/cors/cors_test.go generated vendored Normal file
View file

@ -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": "",
})
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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()
}

View file

@ -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()
}

View file

@ -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")
}

View file

@ -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))
}

View file

@ -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))
}

27
Godeps/_workspace/src/github.com/rs/cors/utils.go generated vendored Normal file
View file

@ -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
}

28
Godeps/_workspace/src/github.com/rs/cors/utils_test.go generated vendored Normal file
View file

@ -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")
}
}

View file

@ -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))

View file

@ -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()
}

View file

@ -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")
}

View file

@ -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:

@ -1 +1 @@
Subproject commit 17164bea8b330d6a118b40d6fbe222ffb12a0e9f
Subproject commit 2536888f817a1a15b05dab4727d30f73d6763f07

View file

@ -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,

View file

@ -2,9 +2,6 @@ package utils
import (
"crypto/ecdsa"
"fmt"
"net"
"net/http"
"os"
"path"
"runtime"
@ -148,7 +145,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",
@ -255,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)
}

View file

@ -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"
@ -83,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)
@ -210,14 +211,16 @@ 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.
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
@ -233,8 +236,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, uint64(i))
}
if uncle {
@ -251,7 +255,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))
}
@ -260,10 +264,11 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
}
// block.gasLimit - parent.gasLimit <= parent.gasLimit / 1024
// block.gasLimit - parent.gasLimit <= parent.gasLimit / GasLimitBoundDivisor
a := new(big.Int).Sub(block.GasLimit, parent.GasLimit)
b := new(big.Int).Div(parent.GasLimit, big.NewInt(1024))
if a.Cmp(b) > 0 {
a.Abs(a)
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)
}
@ -287,9 +292,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)
@ -323,17 +346,8 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
return ValidationError(fmt.Sprintf("%v", err))
}
r := new(big.Int)
r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
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
}
@ -350,16 +364,30 @@ 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
}
func putTx(db common.Database, tx *types.Transaction) {
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)
return
}
db.Put(tx.Hash().Bytes(), rlpEnc)
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), rlpMeta)
}

View file

@ -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
}

View file

@ -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 {

View file

@ -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,23 +44,36 @@ 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{}
}
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)

View file

@ -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/types"
"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
@ -34,7 +32,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)
@ -44,8 +45,9 @@ 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)
}
statedb.Sync()

View file

@ -68,11 +68,11 @@ 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)
state.Update(nil)
state.Update()
state.Sync()
value = state.GetState(address, common.Hash{})
}

View file

@ -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
}
//
@ -300,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 {

View file

@ -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,20 +179,21 @@ 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)
}
// 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, params.TxDataNonZeroGas)
} else {
dgas += vm.GasTxDataZeroByte.Int64()
dgas.Add(dgas, params.TxDataZeroGas)
}
}
if err = self.UseGas(big.NewInt(dgas)); err != nil {
if err = self.UseGas(dgas); err != nil {
return nil, nil, InvalidTxError(err)
}
@ -201,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 {

View file

@ -148,6 +148,23 @@ func NewBlockWithHeader(header *Header) *Block {
return &Block{header: header}
}
func (self *Block) ValidateFields() error {
if self.header == nil {
return fmt.Errorf("header is nil")
}
for i, transaction := range self.transactions {
if transaction == nil {
return fmt.Errorf("transaction %d is nil", i)
}
}
for i, uncle := range self.uncles {
if uncle == nil {
return fmt.Errorf("uncle %d is nil", i)
}
}
return nil
}
func (self *Block) DecodeRLP(s *rlp.Stream) error {
var eb extblock
if err := s.Decode(&eb); err != nil {

View file

@ -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},
}
}

View file

@ -20,8 +20,6 @@ const (
JitVmTy
MaxVmTy
MaxCallDepth = 1025
LogTyPretty byte = 0x1
LogTyDiff byte = 0x2
)

View file

@ -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 {

View file

@ -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)
@ -142,16 +108,16 @@ 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},
SLOAD: {1, params.SloadGas, true},
SSTORE: {2, Zero, false},
SHA3: {1, 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},

View file

@ -5,8 +5,6 @@ import (
"math/big"
)
const maxStack = 1024
func newStack() *stack {
return &stack{}
}

View file

@ -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,16 +849,17 @@ 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)
gas.Add(gas, new(big.Int).Sub(newTotalFee, oldTotalFee))
fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
gas.Add(gas, fee)
}
}

View file

@ -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())
}

View file

@ -31,9 +31,9 @@ var (
defaultBootNodes = []*discover.Node{
// ETH/DEV cmd/bootnode
discover.MustParseNode("enode://6cdd090303f394a1cac34ecc9f7cda18127eafa2a3a06de39f6d920b0e583e062a7362097c7c65ee490a758b442acd5c80c6fce4b148c6a391e946b45131365b@54.169.166.226:30303"),
// ETH/DEV cpp-ethereum (poc-8.ethdev.com)
discover.MustParseNode("enode://4a44599974518ea5b0f14c31c4463692ac0329cb84851f3435e6d1b18ee4eae4aa495f846a0fa1219bd58035671881d44423876e57db2abd57254d0197da0ebe@5.1.83.226:30303"),
discover.MustParseNode("enode://09fbeec0d047e9a37e63f60f8618aa9df0e49271f3fadb2c070dc09e2099b95827b63a8b837c6fd01d0802d457dd83e3bd48bd3e6509f8209ed90dabbc30e3d3@52.16.188.185:30303"),
// ETH/DEV cpp-ethereum (poc-9.ethdev.com)
discover.MustParseNode("enode://487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a@5.1.83.226:30303"),
}
)

View file

@ -13,7 +13,7 @@ import (
)
const (
ProtocolVersion = 59
ProtocolVersion = 60
NetworkId = 0
ProtocolLength = uint64(8)
ProtocolMaxMsgSize = 10 * 1024 * 1024
@ -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(),
@ -268,6 +271,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,6 +282,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.ValidateFields(); err != nil {
return self.protoError(ErrDecode, "block validation %v: %v", msg, err)
}
hash := request.Block.Hash()
_, chainHead, _ := self.chainManager.Status()

View file

@ -63,6 +63,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 +167,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
@ -195,18 +214,7 @@ func TestStatusMsgErrors(t *testing.T) {
},
}
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 +224,177 @@ func TestStatusMsgErrors(t *testing.T) {
go eth.run()
}
}
func TestNewBlockMsg(t *testing.T) {
// logInit()
eth := newEth(t)
var disconnected bool
eth.blockPool.removePeer = func(peerId string) {
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)
}
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) {
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))
}
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 {
case block := <-blocks:
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
case err := <-eth.quit:
t.Errorf("no error expected, got %v", err)
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)
}
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)
}

65
generators/defaults.go Normal file
View file

@ -0,0 +1,65 @@
//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 <input> <output>\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", "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(`// DO NOT EDIT!!!
// AUTOGENERATED FROM generators/defaults.go
package params
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)
}
}

File diff suppressed because one or more lines are too long

View file

@ -60,7 +60,7 @@ out:
}
}
close(self.quitCurrentOp)
//close(self.quitCurrentOp)
done:
// Empty channel
for {

View file

@ -270,9 +270,9 @@ 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.current.state.Update()
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
}

View file

@ -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
}

View file

@ -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])
copy(b.entries[1:], b.entries[:i])
b.entries[0] = n
return n
return true
}
}
return nil
return false
}
// nodesByDistance is a list of nodes, ordered by

View file

@ -2,78 +2,109 @@ 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")
}
}
}
doit(true, true)
doit(false, true)
doit(false, true)
doit(false, false)
}
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)
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)
},
}
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)
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 !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")
if err := quick.Check(prop, cfg); err != nil {
t.Error(err)
}
}
@ -85,44 +116,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 +224,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 +252,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 +269,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)

View file

@ -16,13 +16,18 @@ 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")
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
@ -45,6 +50,7 @@ const (
// RPC request structures
type (
ping struct {
Version uint // must match Version
IP string // our IP
Port uint16 // our port
Expiration uint64
@ -76,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
}
@ -120,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.
@ -132,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")
@ -151,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() {
@ -165,10 +190,11 @@ 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),
Expiration: uint64(time.Now().Add(expiration).Unix()),
@ -176,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++
@ -191,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()),
})
@ -214,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() {
@ -244,6 +284,7 @@ func (t *udp) loop() {
for _, p := range pending {
p.errc <- errClosed
}
pending = nil
return
case p := <-t.addpending:
@ -251,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.
@ -287,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)
@ -316,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()
@ -325,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)
@ -358,31 +412,27 @@ 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 {
if expired(req.Expiration) {
return errExpired
}
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)
if req.Version != Version {
return errBadVersion
}
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
}
@ -390,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
}
@ -402,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()),
})
@ -418,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
}

View file

@ -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
}

54
params/protocol_params.go Executable file
View file

@ -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.
)

View file

@ -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
@ -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 {
@ -113,7 +110,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 +118,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 +127,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 +136,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)
@ -159,7 +156,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
}
@ -179,8 +176,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 +186,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":
@ -199,9 +194,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)
@ -210,10 +209,9 @@ 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 {
if args.Index >= int64(len(br.Transactions)) || args.Index < 0 {
return NewValidationError("Index", "does not exist")
}
*reply = br.Transactions[args.Index]
@ -224,10 +222,9 @@ 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 {
if args.Index >= int64(len(v.Transactions)) || args.Index < 0 {
return NewValidationError("Index", "does not exist")
}
*reply = v.Transactions[args.Index]
@ -237,14 +234,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 {
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.Hex()))
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String()), false)
*reply = uncle
case "eth_getUncleByBlockNumberAndIndex":
@ -254,15 +251,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 {
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.Hex()))
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.String()), false)
*reply = uncle
case "eth_getCompilers":

View file

@ -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

View file

@ -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)
}
}

View file

@ -2,12 +2,15 @@ package rpc
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/xeth"
"github.com/rs/cors"
)
var rpclogger = logger.NewLogger("RPC")
@ -17,13 +20,36 @@ 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
}
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
}
// JSONRPC returns a handler that implements the Ethereum JSON-RPC API.
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 {

View file

@ -19,8 +19,101 @@ package rpc
import (
"encoding/json"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
)
type hexdata struct {
data []byte
}
func (d *hexdata) String() string {
return "0x" + common.Bytes2Hex(d.data)
}
func (d *hexdata) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
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 := input.(type) {
case []byte:
d.data = input
case common.Hash:
d.data = input.Bytes()
case *common.Hash:
d.data = input.Bytes()
case common.Address:
d.data = input.Bytes()
case *common.Address:
d.data = input.Bytes()
case *big.Int:
d.data = input.Bytes()
case int64:
d.data = big.NewInt(input).Bytes()
case uint64:
d.data = big.NewInt(int64(input)).Bytes()
case int:
d.data = big.NewInt(int64(input)).Bytes()
case uint:
d.data = big.NewInt(int64(input)).Bytes()
case string: // hexstring
d.data = common.Big(input).Bytes()
default:
d.data = nil
}
return d
}
type hexnum struct {
data []byte
}
func (d *hexnum) String() string {
// 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 "0x" + out
}
func (d *hexnum) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
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 RpcConfig struct {
ListenAddress string
ListenPort uint
CorsDomain string
}
type InvalidTypeError struct {
method string
msg string

View file

@ -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,246 +8,149 @@ 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"`
Uncles []*hexdata `json:"uncles"`
}
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"`
Transactions []interface{} `json:"transactions"`
Uncles []string `json:"uncles"`
}
func NewBlockRes(block *types.Block, fullTx bool) *BlockRes {
// TODO respect fullTx flag
// 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.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] = tx.Hash.Hex()
}
}
ext.Uncles = make([]string, len(b.Uncles))
for i, v := range b.Uncles {
ext.Uncles[i] = v.Hex()
}
return json.Marshal(ext)
}
func NewBlockRes(block *types.Block) *BlockRes {
if block == nil {
return &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.fullTx = fullTx
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.GasUsed = newHexNum(block.GasUsed())
res.UnixTimestamp = newHexNum(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.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([]common.Hash, len(block.Uncles()))
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,omitempty"`
BlockNumber int64 `json:"blockNumber,omitempty"`
TxIndex int64 `json:"transactionIndex,omitempty"`
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 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"`
}
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)
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
}
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 *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.Number = 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 string `json:"address"`
Topics []string `json:"topics"`
Data string `json:"data"`
Number string `json:"number"`
}
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))
for i, v := range l.Topics {
ext.Topics[i] = v.Hex()
}
return json.Marshal(ext)
}
func NewLogsRes(logs state.Logs) (ls []LogRes) {
ls = make([]LogRes, len(logs))

View file

@ -2,7 +2,9 @@ package rpc
import (
"encoding/json"
"fmt"
"math/big"
"regexp"
"testing"
"github.com/ethereum/go-ethereum/common"
@ -10,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")
@ -18,56 +29,35 @@ func TestNewBlockRes(t *testing.T) {
nonce := uint64(1)
extra := ""
block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra)
_ = 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"`
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,
}
_, _ = json.Marshal(v)
v := NewBlockRes(block, false)
j, _ := json.Marshal(v)
// 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},
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))
}
}
_, _ = json.Marshal(v)
}
func TestNewTransactionRes(t *testing.T) {
@ -78,26 +68,80 @@ func TestNewTransactionRes(t *testing.T) {
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},
Number: uint64(5),
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))
}
}
_, _ = json.Marshal(v)
}
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)
@ -108,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)
}

View file

@ -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,21 +105,21 @@ 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)
statedb.Update()
// sync trie to disk
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
}

View file

@ -1,5 +1,5 @@
{
"genesis_rlp_hex": "f90219f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080830f4240808080a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0",
"genesis_rlp_hex": "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0",
"genesis_state_root": "9178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4e",
"genesis_hash": "b5d6d8402156c5c1dfadaa4b87c676b5bcadb17ef9bc8e939606daaa0d35f55d"
"genesis_hash": "fd4af92a79c7fc2fd8bf0d342f2e832e1d4f485c85b9152d2039e03bc604fdca"
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -847,6 +847,78 @@
"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" : "200000",
"code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056",
"nonce" : "0",
"storage" : {
"0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x01" : "0x42",
"0x02" : "0x23",
"0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x05" : "0x01"
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "9999999533644",
"code" : "0x",
"nonce" : "1",
"storage" : {
}
}
},
"postStateRoot" : "5500215cdbf8165ca47720ad088ae49c2441560cdf267f1c946ae7b9807cb1d4",
"pre" : {
"6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
"balance" : "100000",
"code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056",
"nonce" : "0",
"storage" : {
"0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x01" : "0x42",
"0x02" : "0x23",
"0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x05" : "0x54c98c81"
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10000000000000",
"code" : "0x",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" : {
"data" : "0x60406103ca600439600451602451336000819055506000600481905550816001819055508060028190555042600581905550336003819055505050610381806100496000396000f30060003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b505600000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000023",
"gasLimit" : "600000",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "",
"value" : "100000"
}
},
"createNameRegistratorendowmentTooHigh" : {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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
}

View file

@ -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 (
@ -121,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)
}
@ -128,8 +130,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 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 }
@ -185,12 +187,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
// meta
var txExtra struct {
BlockHash common.Hash
BlockIndex int64
Index uint64
}
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
}
func (self *XEth) BlockByNumber(num int64) *Block {
@ -289,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 {
@ -547,12 +564,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 +616,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)