mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 12:46:44 +00:00
Merge branch 'develop' into bzz
This commit is contained in:
commit
b083b0329a
77 changed files with 4001 additions and 1051 deletions
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
|
|
@ -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
4
Godeps/_workspace/src/github.com/rs/cors/.travis.yml
generated
vendored
Normal 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
19
Godeps/_workspace/src/github.com/rs/cors/LICENSE
generated
vendored
Normal 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
84
Godeps/_workspace/src/github.com/rs/cors/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# Go CORS handler [](https://godoc.org/github.com/rs/cors) [](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [](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
37
Godeps/_workspace/src/github.com/rs/cors/bench_test.go
generated
vendored
Normal 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
308
Godeps/_workspace/src/github.com/rs/cors/cors.go
generated
vendored
Normal 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
288
Godeps/_workspace/src/github.com/rs/cors/cors_test.go
generated
vendored
Normal 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": "",
|
||||
})
|
||||
}
|
||||
24
Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go
generated
vendored
Normal 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)
|
||||
}
|
||||
18
Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go
generated
vendored
Normal 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)
|
||||
}
|
||||
22
Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go
generated
vendored
Normal 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()
|
||||
}
|
||||
23
Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go
generated
vendored
Normal file
23
Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go
generated
vendored
Normal 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()
|
||||
}
|
||||
26
Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go
generated
vendored
Normal file
26
Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go
generated
vendored
Normal 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")
|
||||
}
|
||||
20
Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go
generated
vendored
Normal 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))
|
||||
}
|
||||
22
Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go
generated
vendored
Normal 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
27
Godeps/_workspace/src/github.com/rs/cors/utils.go
generated
vendored
Normal 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
28
Godeps/_workspace/src/github.com/rs/cors/utils_test.go
generated
vendored
Normal 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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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{})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ const (
|
|||
JitVmTy
|
||||
MaxVmTy
|
||||
|
||||
MaxCallDepth = 1025
|
||||
|
||||
LogTyPretty byte = 0x1
|
||||
LogTyDiff byte = 0x2
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
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},
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import (
|
|||
"math/big"
|
||||
)
|
||||
|
||||
const maxStack = 1024
|
||||
|
||||
func newStack() *stack {
|
||||
return &stack{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
65
generators/defaults.go
Normal 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
|
|
@ -60,7 +60,7 @@ out:
|
|||
}
|
||||
}
|
||||
|
||||
close(self.quitCurrentOp)
|
||||
//close(self.quitCurrentOp)
|
||||
done:
|
||||
// Empty channel
|
||||
for {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const (
|
|||
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
|
||||
}
|
||||
// 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
|
||||
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)
|
||||
}
|
||||
tab.mutex.Unlock()
|
||||
}()
|
||||
w.n = tab.db.add(id, addr, tcpPort)
|
||||
close(w.done)
|
||||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
}
|
||||
} 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
|
||||
|
|
|
|||
|
|
@ -2,79 +2,110 @@ 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_bumpOrAddPingReplace(t *testing.T) {
|
||||
pingC := make(pingC)
|
||||
tab := newTable(pingC, NodeID{}, &net.UDPAddr{})
|
||||
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 bumpOrAdd should not replace the last node
|
||||
// because the node replies to ping.
|
||||
new := tab.bumpOrAdd(randomID(tab.self.ID, 200), &net.UDPAddr{})
|
||||
// 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)
|
||||
|
||||
pinged := <-pingC
|
||||
if pinged != last.ID {
|
||||
t.Fatalf("pinged wrong node: %v\nwant %v", pinged, last.ID)
|
||||
// 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 bumpOrAdd: got %d, want %d", bucketSize, l)
|
||||
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, new.ID) {
|
||||
if contains(tab.buckets[200].entries, pingSender) {
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
if contains(tab.buckets[200].entries, last.ID) {
|
||||
t.Error("last entry was not removed")
|
||||
}
|
||||
if !contains(tab.buckets[200].entries, new.ID) {
|
||||
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 TestBucket_bumpNoDuplicates(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := &quick.Config{
|
||||
MaxCount: 1000,
|
||||
Rand: quickrand,
|
||||
Values: func(args []reflect.Value, rand *rand.Rand) {
|
||||
// generate a random list of nodes. this will be the content of the bucket.
|
||||
n := rand.Intn(bucketSize-1) + 1
|
||||
nodes := make([]*Node, n)
|
||||
for i := range nodes {
|
||||
nodes[i] = &Node{ID: randomID(NodeID{}, 200)}
|
||||
}
|
||||
args[0] = reflect.ValueOf(nodes)
|
||||
// generate random bump positions.
|
||||
bumps := make([]int, rand.Intn(100))
|
||||
for i := range bumps {
|
||||
bumps[i] = rand.Intn(len(nodes))
|
||||
}
|
||||
args[1] = reflect.ValueOf(bumps)
|
||||
},
|
||||
}
|
||||
|
||||
prop := func(nodes []*Node, bumps []int) (ok bool) {
|
||||
b := &bucket{entries: make([]*Node, len(nodes))}
|
||||
copy(b.entries, nodes)
|
||||
for i, pos := range bumps {
|
||||
b.bump(b.entries[pos])
|
||||
if hasDuplicates(b.entries) {
|
||||
t.Logf("bucket has duplicates after %d/%d bumps:", i+1, len(bumps))
|
||||
for _, n := range b.entries {
|
||||
t.Logf(" %p", n)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
if err := quick.Check(prop, cfg); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func fillBucket(tab *Table, ld int) (last *Node) {
|
||||
|
|
@ -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})
|
||||
}
|
||||
|
|
@ -256,10 +270,8 @@ func (t findnodeOracle) findnode(n *Node, target NodeID) ([]*Node, error) {
|
|||
}
|
||||
|
||||
func (t findnodeOracle) close() {}
|
||||
|
||||
func (t findnodeOracle) ping(n *Node) error {
|
||||
return errors.New("ping is not supported by this transport")
|
||||
}
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -16,11 +16,16 @@ import (
|
|||
|
||||
var log = logger.NewLogger("P2P Discovery")
|
||||
|
||||
const Version = 3
|
||||
|
||||
// Errors
|
||||
var (
|
||||
errPacketTooSmall = errors.New("too small")
|
||||
errBadHash = errors.New("bad hash")
|
||||
errExpired = errors.New("expired")
|
||||
errBadVersion = errors.New("version mismatch")
|
||||
errUnsolicitedReply = errors.New("unsolicited reply")
|
||||
errUnknownNode = errors.New("unknown node")
|
||||
errTimeout = errors.New("RPC timeout")
|
||||
errClosed = errors.New("socket closed")
|
||||
)
|
||||
|
|
@ -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,12 +82,25 @@ 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
|
||||
conn conn
|
||||
priv *ecdsa.PrivateKey
|
||||
|
||||
addpending chan *pending
|
||||
replies chan reply
|
||||
gotreply chan reply
|
||||
|
||||
closing chan struct{}
|
||||
nat nat.Interface
|
||||
|
||||
|
|
@ -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) {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
54
params/protocol_params.go
Executable 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.
|
||||
)
|
||||
54
rpc/api.go
54
rpc/api.go
|
|
@ -54,7 +54,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
case "net_peerCount":
|
||||
v := api.xeth().PeerCount()
|
||||
*reply = common.ToHex(big.NewInt(int64(v)).Bytes())
|
||||
case "eth_version":
|
||||
case "eth_protocolVersion":
|
||||
*reply = api.xeth().EthVersion()
|
||||
case "eth_coinbase":
|
||||
// TODO handling of empty coinbase due to lack of accounts
|
||||
|
|
@ -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":
|
||||
|
|
|
|||
87
rpc/args.go
87
rpc/args.go
|
|
@ -238,6 +238,93 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
type CallArgs struct {
|
||||
From string
|
||||
To string
|
||||
Value *big.Int
|
||||
Gas *big.Int
|
||||
GasPrice *big.Int
|
||||
Data string
|
||||
|
||||
BlockNumber int64
|
||||
}
|
||||
|
||||
func (args *CallArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
var obj []json.RawMessage
|
||||
var ext struct {
|
||||
From string
|
||||
To string
|
||||
Value interface{}
|
||||
Gas interface{}
|
||||
GasPrice interface{}
|
||||
Data string
|
||||
}
|
||||
|
||||
// Decode byte slice to array of RawMessages
|
||||
if err := json.Unmarshal(b, &obj); err != nil {
|
||||
return NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
// Check for sufficient params
|
||||
if len(obj) < 1 {
|
||||
return NewInsufficientParamsError(len(obj), 1)
|
||||
}
|
||||
|
||||
// Decode 0th RawMessage to temporary struct
|
||||
if err := json.Unmarshal(obj[0], &ext); err != nil {
|
||||
return NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
if len(ext.From) == 0 {
|
||||
return NewValidationError("from", "is required")
|
||||
}
|
||||
args.From = ext.From
|
||||
|
||||
if len(ext.To) == 0 {
|
||||
return NewValidationError("to", "is required")
|
||||
}
|
||||
args.To = ext.To
|
||||
|
||||
var num int64
|
||||
if ext.Value == nil {
|
||||
num = int64(0)
|
||||
} else {
|
||||
if err := numString(ext.Value, &num); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
args.Value = big.NewInt(num)
|
||||
|
||||
if ext.Gas == nil {
|
||||
num = int64(0)
|
||||
} else {
|
||||
if err := numString(ext.Gas, &num); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
args.Gas = big.NewInt(num)
|
||||
|
||||
if ext.GasPrice == nil {
|
||||
num = int64(0)
|
||||
} else {
|
||||
if err := numString(ext.GasPrice, &num); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
args.GasPrice = big.NewInt(num)
|
||||
|
||||
args.Data = ext.Data
|
||||
|
||||
// Check for optional BlockNumber param
|
||||
if len(obj) > 1 {
|
||||
if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetStorageArgs struct {
|
||||
Address string
|
||||
BlockNumber int64
|
||||
|
|
|
|||
277
rpc/args_test.go
277
rpc/args_test.go
|
|
@ -531,14 +531,275 @@ func TestNewTxArgsFromEmpty(t *testing.T) {
|
|||
input := `[{"to": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]`
|
||||
|
||||
args := new(NewTxArgs)
|
||||
err := json.Unmarshal([]byte(input), &args)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
t.Error("Expected error but didn't get one")
|
||||
case *ValidationError:
|
||||
break
|
||||
default:
|
||||
t.Errorf("Expected *rpc.ValidationError, but got %T with message `%s`", err, err.Error())
|
||||
str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgs(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": "0x76c0",
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
|
||||
"0x10"]`
|
||||
expected := new(CallArgs)
|
||||
expected.From = "0xb60e8dd61c5d32be8058bb8eb970870f07233155"
|
||||
expected.To = "0xd46e8dd67c5d32be8058bb8eb970870f072445675"
|
||||
expected.Gas = big.NewInt(30400)
|
||||
expected.GasPrice = big.NewInt(10000000000000)
|
||||
expected.Value = big.NewInt(10000000000000)
|
||||
expected.Data = "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
expected.BlockNumber = big.NewInt(16).Int64()
|
||||
|
||||
args := new(CallArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if expected.From != args.From {
|
||||
t.Errorf("From shoud be %#v but is %#v", expected.From, args.From)
|
||||
}
|
||||
|
||||
if expected.To != args.To {
|
||||
t.Errorf("To shoud be %#v but is %#v", expected.To, args.To)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
|
||||
t.Errorf("Gas shoud be %#v but is %#v", expected.Gas.Bytes(), args.Gas.Bytes())
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
|
||||
t.Errorf("GasPrice shoud be %#v but is %#v", expected.GasPrice, args.GasPrice)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
|
||||
t.Errorf("Value shoud be %#v but is %#v", expected.Value, args.Value)
|
||||
}
|
||||
|
||||
if expected.Data != args.Data {
|
||||
t.Errorf("Data shoud be %#v but is %#v", expected.Data, args.Data)
|
||||
}
|
||||
|
||||
if expected.BlockNumber != args.BlockNumber {
|
||||
t.Errorf("BlockNumber shoud be %#v but is %#v", expected.BlockNumber, args.BlockNumber)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsInt(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": 100,
|
||||
"gasPrice": 50,
|
||||
"value": 8765456789,
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
|
||||
5]`
|
||||
expected := new(CallArgs)
|
||||
expected.Gas = big.NewInt(100)
|
||||
expected.GasPrice = big.NewInt(50)
|
||||
expected.Value = big.NewInt(8765456789)
|
||||
expected.BlockNumber = int64(5)
|
||||
|
||||
args := new(CallArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
|
||||
t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
|
||||
t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
|
||||
t.Errorf("Value shoud be %v but is %v", expected.Value, args.Value)
|
||||
}
|
||||
|
||||
if expected.BlockNumber != args.BlockNumber {
|
||||
t.Errorf("BlockNumber shoud be %v but is %v", expected.BlockNumber, args.BlockNumber)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsBlockBool(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": "0x76c0",
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
|
||||
false]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsGasInvalid(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": false,
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsGaspriceInvalid(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": "0x76c0",
|
||||
"gasPrice": false,
|
||||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsValueInvalid(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": "0x76c0",
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"value": false,
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsGasMissing(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expected := new(CallArgs)
|
||||
expected.Gas = big.NewInt(0)
|
||||
|
||||
if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
|
||||
t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCallArgsBlockGaspriceMissing(t *testing.T) {
|
||||
input := `[{
|
||||
"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": "0x76c0",
|
||||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expected := new(CallArgs)
|
||||
expected.GasPrice = big.NewInt(0)
|
||||
|
||||
if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
|
||||
t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsValueMissing(t *testing.T) {
|
||||
input := `[{
|
||||
"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
|
||||
"gas": "0x76c0",
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expected := new(CallArgs)
|
||||
expected.Value = big.NewInt(int64(0))
|
||||
|
||||
if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
|
||||
t.Errorf("GasPrice shoud be %v but is %v", expected.Value, args.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsEmpty(t *testing.T) {
|
||||
input := `[]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsInvalid(t *testing.T) {
|
||||
input := `{}`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
func TestCallArgsNotStrings(t *testing.T) {
|
||||
input := `[{"from":6}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsFromEmpty(t *testing.T) {
|
||||
input := `[{"to": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallArgsToEmpty(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]`
|
||||
|
||||
args := new(CallArgs)
|
||||
str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
30
rpc/http.go
30
rpc/http.go
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
312
rpc/responses.go
312
rpc/responses.go
|
|
@ -1,11 +1,6 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
// "fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
|
@ -13,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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"genesis_rlp_hex": "f90219f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080830f4240808080a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0",
|
||||
"genesis_rlp_hex": "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0",
|
||||
"genesis_state_root": "9178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4e",
|
||||
"genesis_hash": "b5d6d8402156c5c1dfadaa4b87c676b5bcadb17ef9bc8e939606daaa0d35f55d"
|
||||
"genesis_hash": "fd4af92a79c7fc2fd8bf0d342f2e832e1d4f485c85b9152d2039e03bc604fdca"
|
||||
}
|
||||
|
|
|
|||
71
tests/files/StateTests/RandomTests/st201503261401CPPJIT.json
Normal file
71
tests/files/StateTests/RandomTests/st201503261401CPPJIT.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201503302200JS.json
Normal file
71
tests/files/StateTests/RandomTests/st201503302200JS.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201503302202JS.json
Normal file
71
tests/files/StateTests/RandomTests/st201503302202JS.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201503302206JS.json
Normal file
71
tests/files/StateTests/RandomTests/st201503302206JS.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201503302208JS.json
Normal file
71
tests/files/StateTests/RandomTests/st201503302208JS.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201503302210JS.json
Normal file
71
tests/files/StateTests/RandomTests/st201503302210JS.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201503302211JS.json
Normal file
71
tests/files/StateTests/RandomTests/st201503302211JS.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201504011535GO.json
Normal file
71
tests/files/StateTests/RandomTests/st201504011535GO.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201504011536GO.json
Normal file
71
tests/files/StateTests/RandomTests/st201504011536GO.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tests/files/StateTests/RandomTests/st201504011547GO.json
Normal file
71
tests/files/StateTests/RandomTests/st201504011547GO.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
48
xeth/xeth.go
48
xeth/xeth.go
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/event/filter"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue