aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Godeps/Godeps.json43
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/LICENSE22
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/README.md15
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/backup.go266
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/file.go219
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/fileinfo.go54
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/pipe.go398
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/privilege.go150
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/reparse.go124
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/sd.go96
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/syscall.go3
-rw-r--r--Godeps/_workspace/src/github.com/microsoft/go-winio/zsyscall.go492
-rw-r--r--Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go1
-rw-r--r--Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go4
-rw-r--r--Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go34
-rw-r--r--Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util/hash.go28
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/context/context.go295
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq.go19
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq_go14.go23
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp.go140
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/context/go17.go72
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/context/pre_go17.go300
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go3
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go5
-rw-r--r--Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/.gitignore22
-rw-r--r--Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/LICENSE.txt8
-rw-r--r--Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/README.md308
-rw-r--r--Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/doc.go50
-rwxr-xr-xGodeps/_workspace/src/gopkg.in/natefinch/npipe.v2/npipe_windows.go531
-rw-r--r--Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_386.go124
-rw-r--r--Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_amd64.go124
-rw-r--r--README.md195
-rw-r--r--accounts/abi/bind/backend.go27
-rw-r--r--accounts/abi/bind/backends/nil.go19
-rw-r--r--accounts/abi/bind/backends/remote.go159
-rw-r--r--accounts/abi/bind/backends/simulated.go20
-rw-r--r--accounts/abi/bind/base.go19
-rw-r--r--accounts/account_manager.go22
-rw-r--r--appveyor.yml24
-rw-r--r--circle.yml32
-rw-r--r--cmd/bootnode/main.go28
-rw-r--r--cmd/ethtest/main.go4
-rw-r--r--cmd/evm/main.go1
-rw-r--r--cmd/geth/accountcmd.go2
-rw-r--r--cmd/geth/consolecmd.go19
-rw-r--r--cmd/geth/dao_test.go232
-rw-r--r--cmd/geth/genesis_test.go107
-rw-r--r--cmd/geth/main.go22
-rw-r--r--cmd/geth/monitorcmd.go39
-rw-r--r--cmd/geth/usage.go2
-rw-r--r--cmd/utils/client.go55
-rw-r--r--cmd/utils/flags.go114
-rw-r--r--common/registrar/ethreg/api.go5
-rw-r--r--console/bridge.go174
-rw-r--r--console/console.go4
-rw-r--r--containers/docker/develop-alpine/Dockerfile13
-rw-r--r--containers/docker/master-alpine/Dockerfile12
-rw-r--r--core/bench_test.go2
-rw-r--r--core/block_validator.go8
-rw-r--r--core/blockchain.go7
-rw-r--r--core/blockchain_test.go16
-rw-r--r--core/chain_makers.go28
-rw-r--r--core/chain_makers_test.go2
-rw-r--r--core/chain_pow_test.go6
-rw-r--r--core/config.go7
-rw-r--r--core/dao.go74
-rw-r--r--core/dao_test.go404
-rw-r--r--core/database_util_test.go2
-rw-r--r--core/execution.go10
-rw-r--r--core/state/statedb.go8
-rw-r--r--core/state_processor.go76
-rw-r--r--core/state_transition.go7
-rw-r--r--core/types/transaction.go1
-rw-r--r--core/vm/environment.go5
-rw-r--r--core/vm/jit.go2
-rw-r--r--core/vm/jit_test.go9
-rw-r--r--core/vm/runtime/env.go2
-rw-r--r--core/vm/vm.go2
-rw-r--r--core/vm_env.go6
-rw-r--r--eth/api.go1549
-rw-r--r--eth/api_backend.go201
-rw-r--r--eth/backend.go266
-rw-r--r--eth/backend_test.go2
-rw-r--r--eth/bind.go58
-rw-r--r--eth/db_upgrade.go13
-rw-r--r--eth/downloader/downloader.go678
-rw-r--r--eth/downloader/downloader_test.go124
-rw-r--r--eth/downloader/metrics.go10
-rw-r--r--eth/downloader/peer.go50
-rw-r--r--eth/downloader/queue.go138
-rw-r--r--eth/downloader/types.go20
-rw-r--r--eth/fetcher/fetcher.go98
-rw-r--r--eth/fetcher/fetcher_test.go137
-rw-r--r--eth/fetcher/metrics.go3
-rw-r--r--eth/filters/api.go63
-rw-r--r--eth/filters/filter_system.go19
-rw-r--r--eth/filters/filter_test.go4
-rw-r--r--eth/gasprice/gasprice.go (renamed from eth/gasprice.go)57
-rw-r--r--eth/handler.go196
-rw-r--r--eth/handler_test.go228
-rw-r--r--eth/helper_test.go2
-rw-r--r--eth/metrics.go26
-rw-r--r--eth/peer.go50
-rw-r--r--eth/protocol.go50
-rw-r--r--eth/protocol_test.go3
-rw-r--r--ethdb/database.go6
-rw-r--r--internal/ethapi/api.go1548
-rw-r--r--internal/ethapi/backend.go119
-rw-r--r--internal/jsre/pretty.go2
-rw-r--r--internal/web3ext/web3ext.go4
-rw-r--r--miner/worker.go20
-rw-r--r--node/node.go6
-rw-r--r--node/node_test.go34
-rw-r--r--p2p/discover/database.go2
-rw-r--r--params/dao.go418
-rw-r--r--params/util.go4
-rw-r--r--release/release.go5
-rw-r--r--rpc/client.go740
-rw-r--r--rpc/client_context_go1.4.go60
-rw-r--r--rpc/client_context_go1.5.go61
-rw-r--r--rpc/client_context_go1.6.go55
-rw-r--r--rpc/client_context_go1.7.go51
-rw-r--r--rpc/client_example_test.go83
-rw-r--r--rpc/client_test.go489
-rw-r--r--rpc/errors.go63
-rw-r--r--rpc/http.go163
-rw-r--r--rpc/inproc.go49
-rw-r--r--rpc/ipc.go79
-rw-r--r--rpc/ipc_unix.go6
-rw-r--r--rpc/ipc_windows.go21
-rw-r--r--rpc/json.go77
-rw-r--r--rpc/notification.go2
-rw-r--r--rpc/notification_test.go45
-rw-r--r--rpc/server.go24
-rw-r--r--rpc/server_test.go14
-rw-r--r--rpc/types.go32
-rw-r--r--rpc/utils.go29
-rw-r--r--rpc/websocket.go160
-rw-r--r--tests/block_test.go60
-rw-r--r--tests/block_test_util.go16
-rw-r--r--tests/files/BlockchainTests/TestNetwork/bcTheDaoTest.json8599
-rw-r--r--tests/util.go4
-rw-r--r--tests/vm_test_util.go2
143 files changed, 16198 insertions, 7006 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 9b5b9a44f..edfa8ad1e 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -94,11 +94,6 @@
"Rev": "e882a96ec18dd43fa283187b66af74497c9101c0"
},
{
- "ImportPath": "github.com/microsoft/go-winio",
- "Comment": "v0.2.0",
- "Rev": "9e2895e5f6c3f16473b91d37fae6e89990a4520c"
- },
- {
"ImportPath": "github.com/nsf/termbox-go",
"Rev": "362329b0aa6447eadd52edd8d660ec1dff470295"
},
@@ -157,51 +152,51 @@
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/cache",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/comparer",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/errors",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/filter",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/iterator",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/journal",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/memdb",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/opt",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/storage",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/table",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/util",
- "Rev": "917f41c560270110ceb73c5b38be2a9127387071"
+ "Rev": "ab8b5dcf1042e818ab68e770d465112a899b668e"
},
{
"ImportPath": "golang.org/x/crypto/pbkdf2",
@@ -217,23 +212,23 @@
},
{
"ImportPath": "golang.org/x/net/context",
- "Rev": "8968c61983e8f51a91b8c0ef25bf739278c89634"
+ "Rev": "a728288923b47049b2ce791836767ffbe964a5bd"
},
{
"ImportPath": "golang.org/x/net/html",
- "Rev": "8968c61983e8f51a91b8c0ef25bf739278c89634"
+ "Rev": "a728288923b47049b2ce791836767ffbe964a5bd"
},
{
"ImportPath": "golang.org/x/net/html/atom",
- "Rev": "8968c61983e8f51a91b8c0ef25bf739278c89634"
+ "Rev": "a728288923b47049b2ce791836767ffbe964a5bd"
},
{
"ImportPath": "golang.org/x/net/html/charset",
- "Rev": "8968c61983e8f51a91b8c0ef25bf739278c89634"
+ "Rev": "a728288923b47049b2ce791836767ffbe964a5bd"
},
{
"ImportPath": "golang.org/x/net/websocket",
- "Rev": "8968c61983e8f51a91b8c0ef25bf739278c89634"
+ "Rev": "a728288923b47049b2ce791836767ffbe964a5bd"
},
{
"ImportPath": "golang.org/x/sys/unix",
@@ -321,6 +316,10 @@
"Rev": "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57"
},
{
+ "ImportPath": "gopkg.in/natefinch/npipe.v2",
+ "Rev": "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6"
+ },
+ {
"ImportPath": "gopkg.in/urfave/cli.v1",
"Comment": "v1.17.0",
"Rev": "01857ac33766ce0c93856370626f9799281c14f4"
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/LICENSE b/Godeps/_workspace/src/github.com/microsoft/go-winio/LICENSE
deleted file mode 100644
index b8b569d77..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Microsoft
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/README.md b/Godeps/_workspace/src/github.com/microsoft/go-winio/README.md
deleted file mode 100644
index 478862a8b..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# go-winio
-
-This repository contains utilities for efficiently performing Win32 IO operations in
-Go. Currently, this is focused on accessing named pipes and other file handles, and
-for using named pipes as a net transport.
-
-This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go
-to reuse the thread to schedule another goroutine. This limits support to Windows Vista and
-newer operating systems. This is similar to the implementation of network sockets in Go's net
-package.
-
-Please see the LICENSE file for licensing information.
-
-Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
-for another named pipe implementation.
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/backup.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/backup.go
deleted file mode 100644
index 864935175..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/backup.go
+++ /dev/null
@@ -1,266 +0,0 @@
-package winio
-
-import (
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "runtime"
- "syscall"
- "unicode/utf16"
-)
-
-//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
-//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite
-
-const (
- BackupData = uint32(iota + 1)
- BackupEaData
- BackupSecurity
- BackupAlternateData
- BackupLink
- BackupPropertyData
- BackupObjectId
- BackupReparseData
- BackupSparseBlock
- BackupTxfsData
-)
-
-const (
- StreamSparseAttributes = uint32(8)
-)
-
-const (
- WRITE_DAC = 0x40000
- WRITE_OWNER = 0x80000
- ACCESS_SYSTEM_SECURITY = 0x1000000
-)
-
-// BackupHeader represents a backup stream of a file.
-type BackupHeader struct {
- Id uint32 // The backup stream ID
- Attributes uint32 // Stream attributes
- Size int64 // The size of the stream in bytes
- Name string // The name of the stream (for BackupAlternateData only).
- Offset int64 // The offset of the stream in the file (for BackupSparseBlock only).
-}
-
-type win32StreamId struct {
- StreamId uint32
- Attributes uint32
- Size uint64
- NameSize uint32
-}
-
-// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series
-// of BackupHeader values.
-type BackupStreamReader struct {
- r io.Reader
- bytesLeft int64
-}
-
-// NewBackupStreamReader produces a BackupStreamReader from any io.Reader.
-func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
- return &BackupStreamReader{r, 0}
-}
-
-// Next returns the next backup stream and prepares for calls to Write(). It skips the remainder of the current stream if
-// it was not completely read.
-func (r *BackupStreamReader) Next() (*BackupHeader, error) {
- if r.bytesLeft > 0 {
- if _, err := io.Copy(ioutil.Discard, r); err != nil {
- return nil, err
- }
- }
- var wsi win32StreamId
- if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
- return nil, err
- }
- hdr := &BackupHeader{
- Id: wsi.StreamId,
- Attributes: wsi.Attributes,
- Size: int64(wsi.Size),
- }
- if wsi.NameSize != 0 {
- name := make([]uint16, int(wsi.NameSize/2))
- if err := binary.Read(r.r, binary.LittleEndian, name); err != nil {
- return nil, err
- }
- hdr.Name = syscall.UTF16ToString(name)
- }
- if wsi.StreamId == BackupSparseBlock {
- if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
- return nil, err
- }
- hdr.Size -= 8
- }
- r.bytesLeft = hdr.Size
- return hdr, nil
-}
-
-// Read reads from the current backup stream.
-func (r *BackupStreamReader) Read(b []byte) (int, error) {
- if r.bytesLeft == 0 {
- return 0, io.EOF
- }
- if int64(len(b)) > r.bytesLeft {
- b = b[:r.bytesLeft]
- }
- n, err := r.r.Read(b)
- r.bytesLeft -= int64(n)
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- } else if r.bytesLeft == 0 && err == nil {
- err = io.EOF
- }
- return n, err
-}
-
-// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API.
-type BackupStreamWriter struct {
- w io.Writer
- bytesLeft int64
-}
-
-// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer.
-func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter {
- return &BackupStreamWriter{w, 0}
-}
-
-// WriteHeader writes the next backup stream header and prepares for calls to Write().
-func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
- if w.bytesLeft != 0 {
- return fmt.Errorf("missing %d bytes", w.bytesLeft)
- }
- name := utf16.Encode([]rune(hdr.Name))
- wsi := win32StreamId{
- StreamId: hdr.Id,
- Attributes: hdr.Attributes,
- Size: uint64(hdr.Size),
- NameSize: uint32(len(name) * 2),
- }
- if hdr.Id == BackupSparseBlock {
- // Include space for the int64 block offset
- wsi.Size += 8
- }
- if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil {
- return err
- }
- if len(name) != 0 {
- if err := binary.Write(w.w, binary.LittleEndian, name); err != nil {
- return err
- }
- }
- if hdr.Id == BackupSparseBlock {
- if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil {
- return err
- }
- }
- w.bytesLeft = hdr.Size
- return nil
-}
-
-// Write writes to the current backup stream.
-func (w *BackupStreamWriter) Write(b []byte) (int, error) {
- if w.bytesLeft < int64(len(b)) {
- return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft)
- }
- n, err := w.w.Write(b)
- w.bytesLeft -= int64(n)
- return n, err
-}
-
-// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API.
-type BackupFileReader struct {
- f *os.File
- includeSecurity bool
- ctx uintptr
-}
-
-// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true,
-// Read will attempt to read the security descriptor of the file.
-func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader {
- r := &BackupFileReader{f, includeSecurity, 0}
- runtime.SetFinalizer(r, func(r *BackupFileReader) { r.Close() })
- return r
-}
-
-// Read reads a backup stream from the file by calling the Win32 API BackupRead().
-func (r *BackupFileReader) Read(b []byte) (int, error) {
- var bytesRead uint32
- err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
- if err != nil {
- return 0, &os.PathError{"BackupRead", r.f.Name(), err}
- }
- if bytesRead == 0 {
- return 0, io.EOF
- }
- return int(bytesRead), nil
-}
-
-// Close frees Win32 resources associated with the BackupFileReader. It does not close
-// the underlying file.
-func (r *BackupFileReader) Close() error {
- if r.ctx != 0 {
- backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
- r.ctx = 0
- }
- return nil
-}
-
-// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API.
-type BackupFileWriter struct {
- f *os.File
- includeSecurity bool
- ctx uintptr
-}
-
-// NewBackupFileWrtier returns a new BackupFileWriter from a file handle. If includeSecurity is true,
-// Write() will attempt to restore the security descriptor from the stream.
-func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
- w := &BackupFileWriter{f, includeSecurity, 0}
- runtime.SetFinalizer(w, func(w *BackupFileWriter) { w.Close() })
- return w
-}
-
-// Write restores a portion of the file using the provided backup stream.
-func (w *BackupFileWriter) Write(b []byte) (int, error) {
- var bytesWritten uint32
- err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
- if err != nil {
- return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
- }
- if int(bytesWritten) != len(b) {
- return int(bytesWritten), errors.New("not all bytes could be written")
- }
- return len(b), nil
-}
-
-// Close frees Win32 resources associated with the BackupFileWriter. It does not
-// close the underlying file.
-func (w *BackupFileWriter) Close() error {
- if w.ctx != 0 {
- backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
- w.ctx = 0
- }
- return nil
-}
-
-// OpenForBackup opens a file or directory, potentially skipping access checks if the backup
-// or restore privileges have been acquired.
-//
-// If the file opened was a directory, it cannot be used with Readdir().
-func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) {
- winPath, err := syscall.UTF16FromString(path)
- if err != nil {
- return nil, err
- }
- h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
- if err != nil {
- err = &os.PathError{Op: "open", Path: path, Err: err}
- return nil, err
- }
- return os.NewFile(uintptr(h), path), nil
-}
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/file.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/file.go
deleted file mode 100644
index fd16f0075..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/file.go
+++ /dev/null
@@ -1,219 +0,0 @@
-package winio
-
-import (
- "errors"
- "io"
- "runtime"
- "sync"
- "syscall"
- "time"
-)
-
-//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
-//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
-//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
-//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
-//sys timeBeginPeriod(period uint32) (n int32) = winmm.timeBeginPeriod
-
-const (
- cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
- cFILE_SKIP_SET_EVENT_ON_HANDLE = 2
-)
-
-var (
- ErrFileClosed = errors.New("file has already been closed")
- ErrTimeout = &timeoutError{}
-)
-
-type timeoutError struct{}
-
-func (e *timeoutError) Error() string { return "i/o timeout" }
-func (e *timeoutError) Timeout() bool { return true }
-func (e *timeoutError) Temporary() bool { return true }
-
-var ioInitOnce sync.Once
-var ioCompletionPort syscall.Handle
-
-// ioResult contains the result of an asynchronous IO operation
-type ioResult struct {
- bytes uint32
- err error
-}
-
-// ioOperation represents an outstanding asynchronous Win32 IO
-type ioOperation struct {
- o syscall.Overlapped
- ch chan ioResult
-}
-
-func initIo() {
- h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
- if err != nil {
- panic(err)
- }
- ioCompletionPort = h
- go ioCompletionProcessor(h)
-}
-
-// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall.
-// It takes ownership of this handle and will close it if it is garbage collected.
-type win32File struct {
- handle syscall.Handle
- wg sync.WaitGroup
- closing bool
- readDeadline time.Time
- writeDeadline time.Time
-}
-
-// makeWin32File makes a new win32File from an existing file handle
-func makeWin32File(h syscall.Handle) (*win32File, error) {
- f := &win32File{handle: h}
- ioInitOnce.Do(initIo)
- _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
- if err != nil {
- return nil, err
- }
- err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
- if err != nil {
- return nil, err
- }
- runtime.SetFinalizer(f, (*win32File).closeHandle)
- return f, nil
-}
-
-func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
- return makeWin32File(h)
-}
-
-// closeHandle closes the resources associated with a Win32 handle
-func (f *win32File) closeHandle() {
- if !f.closing {
- // cancel all IO and wait for it to complete
- f.closing = true
- cancelIoEx(f.handle, nil)
- f.wg.Wait()
- // at this point, no new IO can start
- syscall.Close(f.handle)
- f.handle = 0
- }
-}
-
-// Close closes a win32File.
-func (f *win32File) Close() error {
- f.closeHandle()
- runtime.SetFinalizer(f, nil)
- return nil
-}
-
-// prepareIo prepares for a new IO operation
-func (f *win32File) prepareIo() (*ioOperation, error) {
- f.wg.Add(1)
- if f.closing {
- return nil, ErrFileClosed
- }
- c := &ioOperation{}
- c.ch = make(chan ioResult)
- return c, nil
-}
-
-// ioCompletionProcessor processes completed async IOs forever
-func ioCompletionProcessor(h syscall.Handle) {
- // Set the timer resolution to 1. This fixes a performance regression in golang 1.6.
- timeBeginPeriod(1)
- for {
- var bytes uint32
- var key uintptr
- var op *ioOperation
- err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE)
- if op == nil {
- panic(err)
- }
- op.ch <- ioResult{bytes, err}
- }
-}
-
-// asyncIo processes the return value from ReadFile or WriteFile, blocking until
-// the operation has actually completed.
-func (f *win32File) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, err error) (int, error) {
- if err != syscall.ERROR_IO_PENDING {
- f.wg.Done()
- return int(bytes), err
- } else {
- var r ioResult
- wait := true
- timedout := false
- if f.closing {
- cancelIoEx(f.handle, &c.o)
- } else if !deadline.IsZero() {
- now := time.Now()
- if !deadline.After(now) {
- timedout = true
- } else {
- timeout := time.After(deadline.Sub(now))
- select {
- case r = <-c.ch:
- wait = false
- case <-timeout:
- timedout = true
- }
- }
- }
- if timedout {
- cancelIoEx(f.handle, &c.o)
- }
- if wait {
- r = <-c.ch
- }
- err = r.err
- if err == syscall.ERROR_OPERATION_ABORTED {
- if f.closing {
- err = ErrFileClosed
- } else if timedout {
- err = ErrTimeout
- }
- }
- f.wg.Done()
- return int(r.bytes), err
- }
-}
-
-// Read reads from a file handle.
-func (f *win32File) Read(b []byte) (int, error) {
- c, err := f.prepareIo()
- if err != nil {
- return 0, err
- }
- var bytes uint32
- err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
- n, err := f.asyncIo(c, f.readDeadline, bytes, err)
-
- // Handle EOF conditions.
- if err == nil && n == 0 && len(b) != 0 {
- return 0, io.EOF
- } else if err == syscall.ERROR_BROKEN_PIPE {
- return 0, io.EOF
- } else {
- return n, err
- }
-}
-
-// Write writes to a file handle.
-func (f *win32File) Write(b []byte) (int, error) {
- c, err := f.prepareIo()
- if err != nil {
- return 0, err
- }
- var bytes uint32
- err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
- return f.asyncIo(c, f.writeDeadline, bytes, err)
-}
-
-func (f *win32File) SetReadDeadline(t time.Time) error {
- f.readDeadline = t
- return nil
-}
-
-func (f *win32File) SetWriteDeadline(t time.Time) error {
- f.writeDeadline = t
- return nil
-}
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/fileinfo.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/fileinfo.go
deleted file mode 100644
index d5acb72d5..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/fileinfo.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package winio
-
-import (
- "os"
- "syscall"
- "unsafe"
-)
-
-//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx
-//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle
-
-const (
- fileBasicInfo = 0
- fileIDInfo = 0x12
-)
-
-// FileBasicInfo contains file access time and file attributes information.
-type FileBasicInfo struct {
- CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
- FileAttributes uintptr // includes padding
-}
-
-// GetFileBasicInfo retrieves times and attributes for a file.
-func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
- bi := &FileBasicInfo{}
- if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
- return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
- }
- return bi, nil
-}
-
-// SetFileBasicInfo sets times and attributes for a file.
-func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
- if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
- return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
- }
- return nil
-}
-
-// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
-// unique on a system.
-type FileIDInfo struct {
- VolumeSerialNumber uint64
- FileID [16]byte
-}
-
-// GetFileID retrieves the unique (volume, file ID) pair for a file.
-func GetFileID(f *os.File) (*FileIDInfo, error) {
- fileID := &FileIDInfo{}
- if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
- return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
- }
- return fileID, nil
-}
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/pipe.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/pipe.go
deleted file mode 100644
index 82db28306..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/pipe.go
+++ /dev/null
@@ -1,398 +0,0 @@
-package winio
-
-import (
- "errors"
- "io"
- "net"
- "os"
- "syscall"
- "time"
- "unsafe"
-)
-
-//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
-//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
-//sys createFile(name string, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
-//sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW
-//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
-//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
-
-type securityAttributes struct {
- Length uint32
- SecurityDescriptor *byte
- InheritHandle uint32
-}
-
-const (
- cERROR_PIPE_BUSY = syscall.Errno(231)
- cERROR_PIPE_CONNECTED = syscall.Errno(535)
- cERROR_SEM_TIMEOUT = syscall.Errno(121)
-
- cPIPE_ACCESS_DUPLEX = 0x3
- cFILE_FLAG_FIRST_PIPE_INSTANCE = 0x80000
- cSECURITY_SQOS_PRESENT = 0x100000
- cSECURITY_ANONYMOUS = 0
-
- cPIPE_REJECT_REMOTE_CLIENTS = 0x8
-
- cPIPE_UNLIMITED_INSTANCES = 255
-
- cNMPWAIT_USE_DEFAULT_WAIT = 0
- cNMPWAIT_NOWAIT = 1
-
- cPIPE_TYPE_MESSAGE = 4
-
- cPIPE_READMODE_MESSAGE = 2
-)
-
-var (
- // ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
- // This error should match net.errClosing since docker takes a dependency on its text.
- ErrPipeListenerClosed = errors.New("use of closed network connection")
-
- errPipeWriteClosed = errors.New("pipe has been closed for write")
-)
-
-type win32Pipe struct {
- *win32File
- path string
-}
-
-type win32MessageBytePipe struct {
- win32Pipe
- writeClosed bool
- readEOF bool
-}
-
-type pipeAddress string
-
-func (f *win32Pipe) LocalAddr() net.Addr {
- return pipeAddress(f.path)
-}
-
-func (f *win32Pipe) RemoteAddr() net.Addr {
- return pipeAddress(f.path)
-}
-
-func (f *win32Pipe) SetDeadline(t time.Time) error {
- f.SetReadDeadline(t)
- f.SetWriteDeadline(t)
- return nil
-}
-
-// CloseWrite closes the write side of a message pipe in byte mode.
-func (f *win32MessageBytePipe) CloseWrite() error {
- if f.writeClosed {
- return errPipeWriteClosed
- }
- _, err := f.win32File.Write(nil)
- if err != nil {
- return err
- }
- f.writeClosed = true
- return nil
-}
-
-// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since
-// they are used to implement CloseWrite().
-func (f *win32MessageBytePipe) Write(b []byte) (int, error) {
- if f.writeClosed {
- return 0, errPipeWriteClosed
- }
- if len(b) == 0 {
- return 0, nil
- }
- return f.win32File.Write(b)
-}
-
-// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message
-// mode pipe will return io.EOF, as will all subsequent reads.
-func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
- if f.readEOF {
- return 0, io.EOF
- }
- n, err := f.win32File.Read(b)
- if err == io.EOF {
- // If this was the result of a zero-byte read, then
- // it is possible that the read was due to a zero-size
- // message. Since we are simulating CloseWrite with a
- // zero-byte message, ensure that all future Read() calls
- // also return EOF.
- f.readEOF = true
- }
- return n, err
-}
-
-func (s pipeAddress) Network() string {
- return "pipe"
-}
-
-func (s pipeAddress) String() string {
- return string(s)
-}
-
-// DialPipe connects to a named pipe by path, timing out if the connection
-// takes longer than the specified duration. If timeout is nil, then the timeout
-// is the default timeout established by the pipe server.
-func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
- var absTimeout time.Time
- if timeout != nil {
- absTimeout = time.Now().Add(*timeout)
- }
- var err error
- var h syscall.Handle
- for {
- h, err = createFile(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
- if err != cERROR_PIPE_BUSY {
- break
- }
- now := time.Now()
- var ms uint32
- if absTimeout.IsZero() {
- ms = cNMPWAIT_USE_DEFAULT_WAIT
- } else if now.After(absTimeout) {
- ms = cNMPWAIT_NOWAIT
- } else {
- ms = uint32(absTimeout.Sub(now).Nanoseconds() / 1000 / 1000)
- }
- err = waitNamedPipe(path, ms)
- if err != nil {
- if err == cERROR_SEM_TIMEOUT {
- return nil, ErrTimeout
- }
- break
- }
- }
- if err != nil {
- return nil, &os.PathError{Op: "open", Path: path, Err: err}
- }
-
- var flags uint32
- err = getNamedPipeInfo(h, &flags, nil, nil, nil)
- if err != nil {
- return nil, err
- }
-
- var state uint32
- err = getNamedPipeHandleState(h, &state, nil, nil, nil, nil, 0)
- if err != nil {
- return nil, err
- }
-
- if state&cPIPE_READMODE_MESSAGE != 0 {
- return nil, &os.PathError{Op: "open", Path: path, Err: errors.New("message readmode pipes not supported")}
- }
-
- f, err := makeWin32File(h)
- if err != nil {
- syscall.Close(h)
- return nil, err
- }
-
- // If the pipe is in message mode, return a message byte pipe, which
- // supports CloseWrite().
- if flags&cPIPE_TYPE_MESSAGE != 0 {
- return &win32MessageBytePipe{
- win32Pipe: win32Pipe{win32File: f, path: path},
- }, nil
- }
- return &win32Pipe{win32File: f, path: path}, nil
-}
-
-type acceptResponse struct {
- f *win32File
- err error
-}
-
-type win32PipeListener struct {
- firstHandle syscall.Handle
- path string
- securityDescriptor []byte
- config PipeConfig
- acceptCh chan (chan acceptResponse)
- closeCh chan int
- doneCh chan int
-}
-
-func makeServerPipeHandle(path string, securityDescriptor []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
- var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED
- if first {
- flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE
- }
-
- var mode uint32 = cPIPE_REJECT_REMOTE_CLIENTS
- if c.MessageMode {
- mode |= cPIPE_TYPE_MESSAGE
- }
-
- var sa securityAttributes
- sa.Length = uint32(unsafe.Sizeof(sa))
- if securityDescriptor != nil {
- sa.SecurityDescriptor = &securityDescriptor[0]
- }
- h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, &sa)
- if err != nil {
- return 0, &os.PathError{Op: "open", Path: path, Err: err}
- }
- return h, nil
-}
-
-func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
- h, err := makeServerPipeHandle(l.path, l.securityDescriptor, &l.config, false)
- if err != nil {
- return nil, err
- }
- f, err := makeWin32File(h)
- if err != nil {
- syscall.Close(h)
- return nil, err
- }
- return f, nil
-}
-
-func (l *win32PipeListener) listenerRoutine() {
- closed := false
- for !closed {
- select {
- case <-l.closeCh:
- closed = true
- case responseCh := <-l.acceptCh:
- p, err := l.makeServerPipe()
- if err == nil {
- // Wait for the client to connect.
- ch := make(chan error)
- go func() {
- ch <- connectPipe(p)
- }()
- select {
- case err = <-ch:
- if err != nil {
- p.Close()
- p = nil
- }
- case <-l.closeCh:
- // Abort the connect request by closing the handle.
- p.Close()
- p = nil
- err = <-ch
- if err == nil || err == ErrFileClosed {
- err = ErrPipeListenerClosed
- }
- closed = true
- }
- }
- responseCh <- acceptResponse{p, err}
- }
- }
- syscall.Close(l.firstHandle)
- l.firstHandle = 0
- // Notify Close() and Accept() callers that the handle has been closed.
- close(l.doneCh)
-}
-
-// PipeConfig contain configuration for the pipe listener.
-type PipeConfig struct {
- // SecurityDescriptor contains a Windows security descriptor in SDDL format.
- SecurityDescriptor string
-
- // MessageMode determines whether the pipe is in byte or message mode. In either
- // case the pipe is read in byte mode by default. The only practical difference in
- // this implementation is that CloseWrite() is only supported for message mode pipes;
- // CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only
- // transferred to the reader (and returned as io.EOF in this implementation)
- // when the pipe is in message mode.
- MessageMode bool
-
- // InputBufferSize specifies the size the input buffer, in bytes.
- InputBufferSize int32
-
- // OutputBufferSize specifies the size the input buffer, in bytes.
- OutputBufferSize int32
-}
-
-// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe.
-// The pipe must not already exist.
-func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
- var (
- sd []byte
- err error
- )
- if c == nil {
- c = &PipeConfig{}
- }
- if c.SecurityDescriptor != "" {
- sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor)
- if err != nil {
- return nil, err
- }
- }
- h, err := makeServerPipeHandle(path, sd, c, true)
- if err != nil {
- return nil, err
- }
- // Immediately open and then close a client handle so that the named pipe is
- // created but not currently accepting connections.
- h2, err := createFile(path, 0, 0, nil, syscall.OPEN_EXISTING, cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
- if err != nil {
- syscall.Close(h)
- return nil, err
- }
- syscall.Close(h2)
- l := &win32PipeListener{
- firstHandle: h,
- path: path,
- securityDescriptor: sd,
- config: *c,
- acceptCh: make(chan (chan acceptResponse)),
- closeCh: make(chan int),
- doneCh: make(chan int),
- }
- go l.listenerRoutine()
- return l, nil
-}
-
-func connectPipe(p *win32File) error {
- c, err := p.prepareIo()
- if err != nil {
- return err
- }
- err = connectNamedPipe(p.handle, &c.o)
- _, err = p.asyncIo(c, time.Time{}, 0, err)
- if err != nil && err != cERROR_PIPE_CONNECTED {
- return err
- }
- return nil
-}
-
-func (l *win32PipeListener) Accept() (net.Conn, error) {
- ch := make(chan acceptResponse)
- select {
- case l.acceptCh <- ch:
- response := <-ch
- err := response.err
- if err != nil {
- return nil, err
- }
- if l.config.MessageMode {
- return &win32MessageBytePipe{
- win32Pipe: win32Pipe{win32File: response.f, path: l.path},
- }, nil
- }
- return &win32Pipe{win32File: response.f, path: l.path}, nil
- case <-l.doneCh:
- return nil, ErrPipeListenerClosed
- }
-}
-
-func (l *win32PipeListener) Close() error {
- select {
- case l.closeCh <- 1:
- <-l.doneCh
- case <-l.doneCh:
- }
- return nil
-}
-
-func (l *win32PipeListener) Addr() net.Addr {
- return pipeAddress(l.path)
-}
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/privilege.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/privilege.go
deleted file mode 100644
index 81f9af7b7..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/privilege.go
+++ /dev/null
@@ -1,150 +0,0 @@
-package winio
-
-import (
- "bytes"
- "encoding/binary"
- "fmt"
- "runtime"
- "syscall"
- "unicode/utf16"
-)
-
-//sys adjustTokenPrivileges(token syscall.Handle, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
-//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf
-//sys revertToSelf() (err error) = advapi32.RevertToSelf
-//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *syscall.Handle) (err error) = advapi32.OpenThreadToken
-//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread
-//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW
-//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
-//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
-
-const (
- SE_PRIVILEGE_ENABLED = 2
-
- ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
-
- SeBackupPrivilege = "SeBackupPrivilege"
- SeRestorePrivilege = "SeRestorePrivilege"
-)
-
-const (
- securityAnonymous = iota
- securityIdentification
- securityImpersonation
- securityDelegation
-)
-
-type PrivilegeError struct {
- privileges []uint64
-}
-
-func (e *PrivilegeError) Error() string {
- s := ""
- if len(e.privileges) > 1 {
- s = "Could not enable privileges "
- } else {
- s = "Could not enable privilege "
- }
- for i, p := range e.privileges {
- if i != 0 {
- s += ", "
- }
- s += `"`
- s += getPrivilegeName(p)
- s += `"`
- }
- return s
-}
-
-func RunWithPrivilege(name string, fn func() error) error {
- return RunWithPrivileges([]string{name}, fn)
-}
-
-func RunWithPrivileges(names []string, fn func() error) error {
- var privileges []uint64
- for _, name := range names {
- p := uint64(0)
- err := lookupPrivilegeValue("", name, &p)
- if err != nil {
- return err
- }
- privileges = append(privileges, p)
- }
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
- token, err := newThreadToken()
- if err != nil {
- return err
- }
- defer releaseThreadToken(token)
- err = adjustPrivileges(token, privileges)
- if err != nil {
- return err
- }
- return fn()
-}
-
-func adjustPrivileges(token syscall.Handle, privileges []uint64) error {
- var b bytes.Buffer
- binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
- for _, p := range privileges {
- binary.Write(&b, binary.LittleEndian, p)
- binary.Write(&b, binary.LittleEndian, uint32(SE_PRIVILEGE_ENABLED))
- }
- prevState := make([]byte, b.Len())
- reqSize := uint32(0)
- success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize)
- if !success {
- return err
- }
- if err == ERROR_NOT_ALL_ASSIGNED {
- return &PrivilegeError{privileges}
- }
- return nil
-}
-
-func getPrivilegeName(luid uint64) string {
- var nameBuffer [256]uint16
- bufSize := uint32(len(nameBuffer))
- err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize)
- if err != nil {
- return fmt.Sprintf("<unknown privilege %d>", luid)
- }
-
- var displayNameBuffer [256]uint16
- displayBufSize := uint32(len(displayNameBuffer))
- var langId uint32
- err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langId)
- if err != nil {
- return fmt.Sprintf("<unknown privilege %s>", utf16.Decode(nameBuffer[:bufSize]))
- }
-
- return string(utf16.Decode(displayNameBuffer[:displayBufSize]))
-}
-
-func newThreadToken() (syscall.Handle, error) {
- err := impersonateSelf(securityImpersonation)
- if err != nil {
- panic(err)
- return 0, err
- }
-
- var token syscall.Handle
- err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token)
- if err != nil {
- rerr := revertToSelf()
- if rerr != nil {
- panic(rerr)
- }
- return 0, err
- }
- return token, nil
-}
-
-func releaseThreadToken(h syscall.Handle) {
- err := revertToSelf()
- if err != nil {
- panic(err)
- }
- syscall.Close(h)
-}
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/reparse.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/reparse.go
deleted file mode 100644
index 96d7b9a87..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/reparse.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package winio
-
-import (
- "bytes"
- "encoding/binary"
- "fmt"
- "strings"
- "unicode/utf16"
- "unsafe"
-)
-
-const (
- reparseTagMountPoint = 0xA0000003
- reparseTagSymlink = 0xA000000C
-)
-
-type reparseDataBuffer struct {
- ReparseTag uint32
- ReparseDataLength uint16
- Reserved uint16
- SubstituteNameOffset uint16
- SubstituteNameLength uint16
- PrintNameOffset uint16
- PrintNameLength uint16
-}
-
-// ReparsePoint describes a Win32 symlink or mount point.
-type ReparsePoint struct {
- Target string
- IsMountPoint bool
-}
-
-// UnsupportedReparsePointError is returned when trying to decode a non-symlink or
-// mount point reparse point.
-type UnsupportedReparsePointError struct {
- Tag uint32
-}
-
-func (e *UnsupportedReparsePointError) Error() string {
- return fmt.Sprintf("unsupported reparse point %x", e.Tag)
-}
-
-// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink
-// or a mount point.
-func DecodeReparsePoint(b []byte) (*ReparsePoint, error) {
- isMountPoint := false
- tag := binary.LittleEndian.Uint32(b[0:4])
- switch tag {
- case reparseTagMountPoint:
- isMountPoint = true
- case reparseTagSymlink:
- default:
- return nil, &UnsupportedReparsePointError{tag}
- }
- nameOffset := 16 + binary.LittleEndian.Uint16(b[12:14])
- if !isMountPoint {
- nameOffset += 4
- }
- nameLength := binary.LittleEndian.Uint16(b[14:16])
- name := make([]uint16, nameLength/2)
- err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name)
- if err != nil {
- return nil, err
- }
- return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil
-}
-
-func isDriveLetter(c byte) bool {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-}
-
-// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or
-// mount point.
-func EncodeReparsePoint(rp *ReparsePoint) []byte {
- // Generate an NT path and determine if this is a relative path.
- var ntTarget string
- relative := false
- if strings.HasPrefix(rp.Target, `\\?\`) {
- ntTarget = rp.Target
- } else if strings.HasPrefix(rp.Target, `\\`) {
- ntTarget = `\??\UNC\` + rp.Target[2:]
- } else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' {
- ntTarget = `\??\` + rp.Target
- } else {
- ntTarget = rp.Target
- relative = true
- }
-
- // The paths must be NUL-terminated even though they are counted strings.
- target16 := utf16.Encode([]rune(rp.Target + "\x00"))
- ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00"))
-
- size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8
- size += len(ntTarget16)*2 + len(target16)*2
-
- tag := uint32(reparseTagMountPoint)
- if !rp.IsMountPoint {
- tag = reparseTagSymlink
- size += 4 // Add room for symlink flags
- }
-
- data := reparseDataBuffer{
- ReparseTag: tag,
- ReparseDataLength: uint16(size),
- SubstituteNameOffset: 0,
- SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2),
- PrintNameOffset: uint16(len(ntTarget16) * 2),
- PrintNameLength: uint16((len(target16) - 1) * 2),
- }
-
- var b bytes.Buffer
- binary.Write(&b, binary.LittleEndian, &data)
- if !rp.IsMountPoint {
- flags := uint32(0)
- if relative {
- flags |= 1
- }
- binary.Write(&b, binary.LittleEndian, flags)
- }
-
- binary.Write(&b, binary.LittleEndian, ntTarget16)
- binary.Write(&b, binary.LittleEndian, target16)
- return b.Bytes()
-}
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/sd.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/sd.go
deleted file mode 100644
index 60ab56ce7..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/sd.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package winio
-
-import (
- "syscall"
- "unsafe"
-)
-
-//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
-//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
-//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
-//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
-//sys localFree(mem uintptr) = LocalFree
-//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
-
-const (
- cERROR_NONE_MAPPED = syscall.Errno(1332)
-)
-
-type AccountLookupError struct {
- Name string
- Err error
-}
-
-func (e *AccountLookupError) Error() string {
- if e.Name == "" {
- return "lookup account: empty account name specified"
- }
- var s string
- switch e.Err {
- case cERROR_NONE_MAPPED:
- s = "not found"
- default:
- s = e.Err.Error()
- }
- return "lookup account " + e.Name + ": " + s
-}
-
-type SddlConversionError struct {
- Sddl string
- Err error
-}
-
-func (e *SddlConversionError) Error() string {
- return "convert " + e.Sddl + ": " + e.Err.Error()
-}
-
-// LookupSidByName looks up the SID of an account by name
-func LookupSidByName(name string) (sid string, err error) {
- if name == "" {
- return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
- }
-
- var sidSize, sidNameUse, refDomainSize uint32
- err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
- if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
- return "", &AccountLookupError{name, err}
- }
- sidBuffer := make([]byte, sidSize)
- refDomainBuffer := make([]uint16, refDomainSize)
- err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
- if err != nil {
- return "", &AccountLookupError{name, err}
- }
- var strBuffer *uint16
- err = convertSidToStringSid(&sidBuffer[0], &strBuffer)
- if err != nil {
- return "", &AccountLookupError{name, err}
- }
- sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
- localFree(uintptr(unsafe.Pointer(strBuffer)))
- return sid, nil
-}
-
-func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
- var sdBuffer uintptr
- err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
- if err != nil {
- return nil, &SddlConversionError{sddl, err}
- }
- defer localFree(sdBuffer)
- sd := make([]byte, getSecurityDescriptorLength(sdBuffer))
- copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)])
- return sd, nil
-}
-
-func SecurityDescriptorToSddl(sd []byte) (string, error) {
- var sddl *uint16
- // The returned string length seems to including an aribtrary number of terminating NULs.
- // Don't use it.
- err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
- if err != nil {
- return "", err
- }
- defer localFree(uintptr(unsafe.Pointer(sddl)))
- return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil
-}
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/syscall.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/syscall.go
deleted file mode 100644
index 96fdff7b4..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/syscall.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package winio
-
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go
diff --git a/Godeps/_workspace/src/github.com/microsoft/go-winio/zsyscall.go b/Godeps/_workspace/src/github.com/microsoft/go-winio/zsyscall.go
deleted file mode 100644
index 74b6e97a6..000000000
--- a/Godeps/_workspace/src/github.com/microsoft/go-winio/zsyscall.go
+++ /dev/null
@@ -1,492 +0,0 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
-
-package winio
-
-import "unsafe"
-import "syscall"
-
-var _ unsafe.Pointer
-
-var (
- modkernel32 = syscall.NewLazyDLL("kernel32.dll")
- modwinmm = syscall.NewLazyDLL("winmm.dll")
- modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
-
- procCancelIoEx = modkernel32.NewProc("CancelIoEx")
- procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
- procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
- procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
- proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod")
- procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
- procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
- procCreateFileW = modkernel32.NewProc("CreateFileW")
- procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
- procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
- procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
- procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
- procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
- procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
- procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
- procLocalFree = modkernel32.NewProc("LocalFree")
- procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
- procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx")
- procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
- procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
- procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
- procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
- procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
- procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
- procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
- procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
- procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
- procBackupRead = modkernel32.NewProc("BackupRead")
- procBackupWrite = modkernel32.NewProc("BackupWrite")
-)
-
-func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
- r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
- newport = syscall.Handle(r0)
- if newport == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
- r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func timeBeginPeriod(period uint32) (n int32) {
- r0, _, _ := syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0)
- n = int32(r0)
- return
-}
-
-func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
- r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(name)
- if err != nil {
- return
- }
- return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
-}
-
-func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
- handle = syscall.Handle(r0)
- if handle == syscall.InvalidHandle {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func createFile(name string, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(name)
- if err != nil {
- return
- }
- return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
-}
-
-func _createFile(name *uint16, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
- handle = syscall.Handle(r0)
- if handle == syscall.InvalidHandle {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func waitNamedPipe(name string, timeout uint32) (err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(name)
- if err != nil {
- return
- }
- return _waitNamedPipe(_p0, timeout)
-}
-
-func _waitNamedPipe(name *uint16, timeout uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
- r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(accountName)
- if err != nil {
- return
- }
- return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
-}
-
-func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
- r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func convertSidToStringSid(sid *byte, str **uint16) (err error) {
- r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(str)
- if err != nil {
- return
- }
- return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size)
-}
-
-func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func localFree(mem uintptr) {
- syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
- return
-}
-
-func getSecurityDescriptorLength(sd uintptr) (len uint32) {
- r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
- len = uint32(r0)
- return
-}
-
-func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func adjustTokenPrivileges(token syscall.Handle, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
- var _p0 uint32
- if releaseAll {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
- success = r0 != 0
- if true {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func impersonateSelf(level uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func revertToSelf() (err error) {
- r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *syscall.Handle) (err error) {
- var _p0 uint32
- if openAsSelf {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func getCurrentThread() (h syscall.Handle) {
- r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
- h = syscall.Handle(r0)
- return
-}
-
-func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(systemName)
- if err != nil {
- return
- }
- var _p1 *uint16
- _p1, err = syscall.UTF16PtrFromString(name)
- if err != nil {
- return
- }
- return _lookupPrivilegeValue(_p0, _p1, luid)
-}
-
-func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) {
- r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(systemName)
- if err != nil {
- return
- }
- return _lookupPrivilegeName(_p0, luid, buffer, size)
-}
-
-func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
- var _p0 *uint16
- _p0, err = syscall.UTF16PtrFromString(systemName)
- if err != nil {
- return
- }
- return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId)
-}
-
-func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
- var _p0 *byte
- if len(b) > 0 {
- _p0 = &b[0]
- }
- var _p1 uint32
- if abort {
- _p1 = 1
- } else {
- _p1 = 0
- }
- var _p2 uint32
- if processSecurity {
- _p2 = 1
- } else {
- _p2 = 0
- }
- r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
- var _p0 *byte
- if len(b) > 0 {
- _p0 = &b[0]
- }
- var _p1 uint32
- if abort {
- _p1 = 1
- } else {
- _p1 = 0
- }
- var _p2 uint32
- if processSecurity {
- _p2 = 1
- } else {
- _p2 = 0
- }
- r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
index 652fa4124..501006717 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
@@ -158,6 +158,7 @@ func (b *Batch) append(p *Batch) {
b.grow(len(p.data) - batchHdrLen)
b.data = append(b.data, p.data[batchHdrLen:]...)
b.rLen += p.rLen
+ b.bLen += p.bLen
}
if p.sync {
b.sync = true
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go
index 9664e64d0..659f00dc6 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go
@@ -172,7 +172,7 @@ func (db *DB) compactionTransact(name string, t compactionTransactInterface) {
disableBackoff = db.s.o.GetDisableCompactionBackoff()
)
for n := 0; ; n++ {
- // Check wether the DB is closed.
+ // Check whether the DB is closed.
if db.isClosed() {
db.logf("%s exiting", name)
db.compactionExitTransact()
@@ -688,7 +688,7 @@ func (db *DB) compTrigger(compC chan<- cCmd) {
}
}
-// This will trigger auto compation and/or wait for all compaction to be done.
+// This will trigger auto compaction and/or wait for all compaction to be done.
func (db *DB) compTriggerWait(compC chan<- cCmd) (err error) {
ch := make(chan error)
defer close(ch)
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go
new file mode 100644
index 000000000..5545aeef2
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go
@@ -0,0 +1,34 @@
+// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// +build nacl
+
+package storage
+
+import (
+ "os"
+ "syscall"
+)
+
+func newFileLock(path string, readOnly bool) (fl fileLock, err error) {
+ return nil, syscall.ENOTSUP
+}
+
+func setFileLock(f *os.File, readOnly, lock bool) error {
+ return syscall.ENOTSUP
+}
+
+func rename(oldpath, newpath string) error {
+ return syscall.ENOTSUP
+}
+
+func isErrInvalid(err error) bool {
+ return false
+}
+
+func syncDir(name string) error {
+ return syscall.ENOTSUP
+}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util/hash.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util/hash.go
index 54903660f..7f3fa4e2c 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util/hash.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util/hash.go
@@ -7,38 +7,38 @@
package util
import (
- "bytes"
"encoding/binary"
)
// Hash return hash of the given data.
func Hash(data []byte, seed uint32) uint32 {
// Similar to murmur hash
- var m uint32 = 0xc6a4a793
- var r uint32 = 24
- h := seed ^ (uint32(len(data)) * m)
+ const (
+ m = uint32(0xc6a4a793)
+ r = uint32(24)
+ )
+ var (
+ h = seed ^ (uint32(len(data)) * m)
+ i int
+ )
- buf := bytes.NewBuffer(data)
- for buf.Len() >= 4 {
- var w uint32
- binary.Read(buf, binary.LittleEndian, &w)
- h += w
+ for n := len(data) - len(data)%4; i < n; i += 4 {
+ h += binary.LittleEndian.Uint32(data[i:])
h *= m
h ^= (h >> 16)
}
- rest := buf.Bytes()
- switch len(rest) {
+ switch len(data) - i {
default:
panic("not reached")
case 3:
- h += uint32(rest[2]) << 16
+ h += uint32(data[i+2]) << 16
fallthrough
case 2:
- h += uint32(rest[1]) << 8
+ h += uint32(data[i+1]) << 8
fallthrough
case 1:
- h += uint32(rest[0])
+ h += uint32(data[i])
h *= m
h ^= (h >> r)
case 0:
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/context.go b/Godeps/_workspace/src/golang.org/x/net/context/context.go
index 11bd8d34e..ea1a7cd53 100644
--- a/Godeps/_workspace/src/golang.org/x/net/context/context.go
+++ b/Godeps/_workspace/src/golang.org/x/net/context/context.go
@@ -36,12 +36,7 @@
// Contexts.
package context
-import (
- "errors"
- "fmt"
- "sync"
- "time"
-)
+import "time"
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
@@ -66,7 +61,7 @@ type Context interface {
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
- // func Stream(ctx context.Context, out <-chan Value) error {
+ // func Stream(ctx context.Context, out chan<- Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
@@ -138,48 +133,6 @@ type Context interface {
Value(key interface{}) interface{}
}
-// Canceled is the error returned by Context.Err when the context is canceled.
-var Canceled = errors.New("context canceled")
-
-// DeadlineExceeded is the error returned by Context.Err when the context's
-// deadline passes.
-var DeadlineExceeded = errors.New("context deadline exceeded")
-
-// An emptyCtx is never canceled, has no values, and has no deadline. It is not
-// struct{}, since vars of this type must have distinct addresses.
-type emptyCtx int
-
-func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
- return
-}
-
-func (*emptyCtx) Done() <-chan struct{} {
- return nil
-}
-
-func (*emptyCtx) Err() error {
- return nil
-}
-
-func (*emptyCtx) Value(key interface{}) interface{} {
- return nil
-}
-
-func (e *emptyCtx) String() string {
- switch e {
- case background:
- return "context.Background"
- case todo:
- return "context.TODO"
- }
- return "unknown empty Context"
-}
-
-var (
- background = new(emptyCtx)
- todo = new(emptyCtx)
-)
-
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
@@ -201,247 +154,3 @@ func TODO() Context {
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc func()
-
-// WithCancel returns a copy of parent with a new Done channel. The returned
-// context's Done channel is closed when the returned cancel function is called
-// or when the parent context's Done channel is closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
- c := newCancelCtx(parent)
- propagateCancel(parent, &c)
- return &c, func() { c.cancel(true, Canceled) }
-}
-
-// newCancelCtx returns an initialized cancelCtx.
-func newCancelCtx(parent Context) cancelCtx {
- return cancelCtx{
- Context: parent,
- done: make(chan struct{}),
- }
-}
-
-// propagateCancel arranges for child to be canceled when parent is.
-func propagateCancel(parent Context, child canceler) {
- if parent.Done() == nil {
- return // parent is never canceled
- }
- if p, ok := parentCancelCtx(parent); ok {
- p.mu.Lock()
- if p.err != nil {
- // parent has already been canceled
- child.cancel(false, p.err)
- } else {
- if p.children == nil {
- p.children = make(map[canceler]bool)
- }
- p.children[child] = true
- }
- p.mu.Unlock()
- } else {
- go func() {
- select {
- case <-parent.Done():
- child.cancel(false, parent.Err())
- case <-child.Done():
- }
- }()
- }
-}
-
-// parentCancelCtx follows a chain of parent references until it finds a
-// *cancelCtx. This function understands how each of the concrete types in this
-// package represents its parent.
-func parentCancelCtx(parent Context) (*cancelCtx, bool) {
- for {
- switch c := parent.(type) {
- case *cancelCtx:
- return c, true
- case *timerCtx:
- return &c.cancelCtx, true
- case *valueCtx:
- parent = c.Context
- default:
- return nil, false
- }
- }
-}
-
-// removeChild removes a context from its parent.
-func removeChild(parent Context, child canceler) {
- p, ok := parentCancelCtx(parent)
- if !ok {
- return
- }
- p.mu.Lock()
- if p.children != nil {
- delete(p.children, child)
- }
- p.mu.Unlock()
-}
-
-// A canceler is a context type that can be canceled directly. The
-// implementations are *cancelCtx and *timerCtx.
-type canceler interface {
- cancel(removeFromParent bool, err error)
- Done() <-chan struct{}
-}
-
-// A cancelCtx can be canceled. When canceled, it also cancels any children
-// that implement canceler.
-type cancelCtx struct {
- Context
-
- done chan struct{} // closed by the first cancel call.
-
- mu sync.Mutex
- children map[canceler]bool // set to nil by the first cancel call
- err error // set to non-nil by the first cancel call
-}
-
-func (c *cancelCtx) Done() <-chan struct{} {
- return c.done
-}
-
-func (c *cancelCtx) Err() error {
- c.mu.Lock()
- defer c.mu.Unlock()
- return c.err
-}
-
-func (c *cancelCtx) String() string {
- return fmt.Sprintf("%v.WithCancel", c.Context)
-}
-
-// cancel closes c.done, cancels each of c's children, and, if
-// removeFromParent is true, removes c from its parent's children.
-func (c *cancelCtx) cancel(removeFromParent bool, err error) {
- if err == nil {
- panic("context: internal error: missing cancel error")
- }
- c.mu.Lock()
- if c.err != nil {
- c.mu.Unlock()
- return // already canceled
- }
- c.err = err
- close(c.done)
- for child := range c.children {
- // NOTE: acquiring the child's lock while holding parent's lock.
- child.cancel(false, err)
- }
- c.children = nil
- c.mu.Unlock()
-
- if removeFromParent {
- removeChild(c.Context, c)
- }
-}
-
-// WithDeadline returns a copy of the parent context with the deadline adjusted
-// to be no later than d. If the parent's deadline is already earlier than d,
-// WithDeadline(parent, d) is semantically equivalent to parent. The returned
-// context's Done channel is closed when the deadline expires, when the returned
-// cancel function is called, or when the parent context's Done channel is
-// closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
- if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
- // The current deadline is already sooner than the new one.
- return WithCancel(parent)
- }
- c := &timerCtx{
- cancelCtx: newCancelCtx(parent),
- deadline: deadline,
- }
- propagateCancel(parent, c)
- d := deadline.Sub(time.Now())
- if d <= 0 {
- c.cancel(true, DeadlineExceeded) // deadline has already passed
- return c, func() { c.cancel(true, Canceled) }
- }
- c.mu.Lock()
- defer c.mu.Unlock()
- if c.err == nil {
- c.timer = time.AfterFunc(d, func() {
- c.cancel(true, DeadlineExceeded)
- })
- }
- return c, func() { c.cancel(true, Canceled) }
-}
-
-// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
-// implement Done and Err. It implements cancel by stopping its timer then
-// delegating to cancelCtx.cancel.
-type timerCtx struct {
- cancelCtx
- timer *time.Timer // Under cancelCtx.mu.
-
- deadline time.Time
-}
-
-func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
- return c.deadline, true
-}
-
-func (c *timerCtx) String() string {
- return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
-}
-
-func (c *timerCtx) cancel(removeFromParent bool, err error) {
- c.cancelCtx.cancel(false, err)
- if removeFromParent {
- // Remove this timerCtx from its parent cancelCtx's children.
- removeChild(c.cancelCtx.Context, c)
- }
- c.mu.Lock()
- if c.timer != nil {
- c.timer.Stop()
- c.timer = nil
- }
- c.mu.Unlock()
-}
-
-// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete:
-//
-// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
-// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
-// defer cancel() // releases resources if slowOperation completes before timeout elapses
-// return slowOperation(ctx)
-// }
-func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
- return WithDeadline(parent, time.Now().Add(timeout))
-}
-
-// WithValue returns a copy of parent in which the value associated with key is
-// val.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-func WithValue(parent Context, key interface{}, val interface{}) Context {
- return &valueCtx{parent, key, val}
-}
-
-// A valueCtx carries a key-value pair. It implements Value for that key and
-// delegates all other calls to the embedded Context.
-type valueCtx struct {
- Context
- key, val interface{}
-}
-
-func (c *valueCtx) String() string {
- return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
-}
-
-func (c *valueCtx) Value(key interface{}) interface{} {
- if c.key == key {
- return c.val
- }
- return c.Context.Value(key)
-}
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq.go b/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq.go
deleted file mode 100644
index e3170e333..000000000
--- a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.5
-
-package ctxhttp
-
-import "net/http"
-
-func canceler(client *http.Client, req *http.Request) func() {
- // TODO(djd): Respect any existing value of req.Cancel.
- ch := make(chan struct{})
- req.Cancel = ch
-
- return func() {
- close(ch)
- }
-}
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq_go14.go b/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq_go14.go
deleted file mode 100644
index 56bcbadb8..000000000
--- a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq_go14.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.5
-
-package ctxhttp
-
-import "net/http"
-
-type requestCanceler interface {
- CancelRequest(*http.Request)
-}
-
-func canceler(client *http.Client, req *http.Request) func() {
- rc, ok := client.Transport.(requestCanceler)
- if !ok {
- return func() {}
- }
- return func() {
- rc.CancelRequest(req)
- }
-}
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp.go b/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp.go
deleted file mode 100644
index 26a5e19ac..000000000
--- a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
-package ctxhttp
-
-import (
- "io"
- "net/http"
- "net/url"
- "strings"
-
- "golang.org/x/net/context"
-)
-
-func nop() {}
-
-var (
- testHookContextDoneBeforeHeaders = nop
- testHookDoReturned = nop
- testHookDidBodyClose = nop
-)
-
-// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
-// If the client is nil, http.DefaultClient is used.
-// If the context is canceled or times out, ctx.Err() will be returned.
-func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
- if client == nil {
- client = http.DefaultClient
- }
-
- // Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go.
- cancel := canceler(client, req)
-
- type responseAndError struct {
- resp *http.Response
- err error
- }
- result := make(chan responseAndError, 1)
-
- go func() {
- resp, err := client.Do(req)
- testHookDoReturned()
- result <- responseAndError{resp, err}
- }()
-
- var resp *http.Response
-
- select {
- case <-ctx.Done():
- testHookContextDoneBeforeHeaders()
- cancel()
- // Clean up after the goroutine calling client.Do:
- go func() {
- if r := <-result; r.resp != nil {
- testHookDidBodyClose()
- r.resp.Body.Close()
- }
- }()
- return nil, ctx.Err()
- case r := <-result:
- var err error
- resp, err = r.resp, r.err
- if err != nil {
- return resp, err
- }
- }
-
- c := make(chan struct{})
- go func() {
- select {
- case <-ctx.Done():
- cancel()
- case <-c:
- // The response's Body is closed.
- }
- }()
- resp.Body = &notifyingReader{resp.Body, c}
-
- return resp, nil
-}
-
-// Get issues a GET request via the Do function.
-func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, err
- }
- return Do(ctx, client, req)
-}
-
-// Head issues a HEAD request via the Do function.
-func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
- req, err := http.NewRequest("HEAD", url, nil)
- if err != nil {
- return nil, err
- }
- return Do(ctx, client, req)
-}
-
-// Post issues a POST request via the Do function.
-func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
- req, err := http.NewRequest("POST", url, body)
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", bodyType)
- return Do(ctx, client, req)
-}
-
-// PostForm issues a POST request via the Do function.
-func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
- return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
-}
-
-// notifyingReader is an io.ReadCloser that closes the notify channel after
-// Close is called or a Read fails on the underlying ReadCloser.
-type notifyingReader struct {
- io.ReadCloser
- notify chan<- struct{}
-}
-
-func (r *notifyingReader) Read(p []byte) (int, error) {
- n, err := r.ReadCloser.Read(p)
- if err != nil && r.notify != nil {
- close(r.notify)
- r.notify = nil
- }
- return n, err
-}
-
-func (r *notifyingReader) Close() error {
- err := r.ReadCloser.Close()
- if r.notify != nil {
- close(r.notify)
- r.notify = nil
- }
- return err
-}
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/go17.go b/Godeps/_workspace/src/golang.org/x/net/context/go17.go
new file mode 100644
index 000000000..f8cda19ad
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/context/go17.go
@@ -0,0 +1,72 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+package context
+
+import (
+ "context" // standard library's context, as of Go 1.7
+ "time"
+)
+
+var (
+ todo = context.TODO()
+ background = context.Background()
+)
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = context.Canceled
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = context.DeadlineExceeded
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ ctx, f := context.WithCancel(parent)
+ return ctx, CancelFunc(f)
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ ctx, f := context.WithDeadline(parent, deadline)
+ return ctx, CancelFunc(f)
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return context.WithValue(parent, key, val)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/pre_go17.go b/Godeps/_workspace/src/golang.org/x/net/context/pre_go17.go
new file mode 100644
index 000000000..5a30acabd
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/context/pre_go17.go
@@ -0,0 +1,300 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package context
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+)
+
+// An emptyCtx is never canceled, has no values, and has no deadline. It is not
+// struct{}, since vars of this type must have distinct addresses.
+type emptyCtx int
+
+func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
+ return
+}
+
+func (*emptyCtx) Done() <-chan struct{} {
+ return nil
+}
+
+func (*emptyCtx) Err() error {
+ return nil
+}
+
+func (*emptyCtx) Value(key interface{}) interface{} {
+ return nil
+}
+
+func (e *emptyCtx) String() string {
+ switch e {
+ case background:
+ return "context.Background"
+ case todo:
+ return "context.TODO"
+ }
+ return "unknown empty Context"
+}
+
+var (
+ background = new(emptyCtx)
+ todo = new(emptyCtx)
+)
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = errors.New("context canceled")
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = errors.New("context deadline exceeded")
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ c := newCancelCtx(parent)
+ propagateCancel(parent, c)
+ return c, func() { c.cancel(true, Canceled) }
+}
+
+// newCancelCtx returns an initialized cancelCtx.
+func newCancelCtx(parent Context) *cancelCtx {
+ return &cancelCtx{
+ Context: parent,
+ done: make(chan struct{}),
+ }
+}
+
+// propagateCancel arranges for child to be canceled when parent is.
+func propagateCancel(parent Context, child canceler) {
+ if parent.Done() == nil {
+ return // parent is never canceled
+ }
+ if p, ok := parentCancelCtx(parent); ok {
+ p.mu.Lock()
+ if p.err != nil {
+ // parent has already been canceled
+ child.cancel(false, p.err)
+ } else {
+ if p.children == nil {
+ p.children = make(map[canceler]bool)
+ }
+ p.children[child] = true
+ }
+ p.mu.Unlock()
+ } else {
+ go func() {
+ select {
+ case <-parent.Done():
+ child.cancel(false, parent.Err())
+ case <-child.Done():
+ }
+ }()
+ }
+}
+
+// parentCancelCtx follows a chain of parent references until it finds a
+// *cancelCtx. This function understands how each of the concrete types in this
+// package represents its parent.
+func parentCancelCtx(parent Context) (*cancelCtx, bool) {
+ for {
+ switch c := parent.(type) {
+ case *cancelCtx:
+ return c, true
+ case *timerCtx:
+ return c.cancelCtx, true
+ case *valueCtx:
+ parent = c.Context
+ default:
+ return nil, false
+ }
+ }
+}
+
+// removeChild removes a context from its parent.
+func removeChild(parent Context, child canceler) {
+ p, ok := parentCancelCtx(parent)
+ if !ok {
+ return
+ }
+ p.mu.Lock()
+ if p.children != nil {
+ delete(p.children, child)
+ }
+ p.mu.Unlock()
+}
+
+// A canceler is a context type that can be canceled directly. The
+// implementations are *cancelCtx and *timerCtx.
+type canceler interface {
+ cancel(removeFromParent bool, err error)
+ Done() <-chan struct{}
+}
+
+// A cancelCtx can be canceled. When canceled, it also cancels any children
+// that implement canceler.
+type cancelCtx struct {
+ Context
+
+ done chan struct{} // closed by the first cancel call.
+
+ mu sync.Mutex
+ children map[canceler]bool // set to nil by the first cancel call
+ err error // set to non-nil by the first cancel call
+}
+
+func (c *cancelCtx) Done() <-chan struct{} {
+ return c.done
+}
+
+func (c *cancelCtx) Err() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.err
+}
+
+func (c *cancelCtx) String() string {
+ return fmt.Sprintf("%v.WithCancel", c.Context)
+}
+
+// cancel closes c.done, cancels each of c's children, and, if
+// removeFromParent is true, removes c from its parent's children.
+func (c *cancelCtx) cancel(removeFromParent bool, err error) {
+ if err == nil {
+ panic("context: internal error: missing cancel error")
+ }
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return // already canceled
+ }
+ c.err = err
+ close(c.done)
+ for child := range c.children {
+ // NOTE: acquiring the child's lock while holding parent's lock.
+ child.cancel(false, err)
+ }
+ c.children = nil
+ c.mu.Unlock()
+
+ if removeFromParent {
+ removeChild(c.Context, c)
+ }
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
+ // The current deadline is already sooner than the new one.
+ return WithCancel(parent)
+ }
+ c := &timerCtx{
+ cancelCtx: newCancelCtx(parent),
+ deadline: deadline,
+ }
+ propagateCancel(parent, c)
+ d := deadline.Sub(time.Now())
+ if d <= 0 {
+ c.cancel(true, DeadlineExceeded) // deadline has already passed
+ return c, func() { c.cancel(true, Canceled) }
+ }
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.err == nil {
+ c.timer = time.AfterFunc(d, func() {
+ c.cancel(true, DeadlineExceeded)
+ })
+ }
+ return c, func() { c.cancel(true, Canceled) }
+}
+
+// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
+// implement Done and Err. It implements cancel by stopping its timer then
+// delegating to cancelCtx.cancel.
+type timerCtx struct {
+ *cancelCtx
+ timer *time.Timer // Under cancelCtx.mu.
+
+ deadline time.Time
+}
+
+func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
+ return c.deadline, true
+}
+
+func (c *timerCtx) String() string {
+ return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
+}
+
+func (c *timerCtx) cancel(removeFromParent bool, err error) {
+ c.cancelCtx.cancel(false, err)
+ if removeFromParent {
+ // Remove this timerCtx from its parent cancelCtx's children.
+ removeChild(c.cancelCtx.Context, c)
+ }
+ c.mu.Lock()
+ if c.timer != nil {
+ c.timer.Stop()
+ c.timer = nil
+ }
+ c.mu.Unlock()
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return &valueCtx{parent, key, val}
+}
+
+// A valueCtx carries a key-value pair. It implements Value for that key and
+// delegates all other calls to the embedded Context.
+type valueCtx struct {
+ Context
+ key, val interface{}
+}
+
+func (c *valueCtx) String() string {
+ return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
+}
+
+func (c *valueCtx) Value(key interface{}) interface{} {
+ if c.key == key {
+ return c.val
+ }
+ return c.Context.Value(key)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go
index 60bbc8418..8cffdd16c 100644
--- a/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go
@@ -81,9 +81,6 @@ type hybiFrameReader struct {
func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
n, err = frame.reader.Read(msg)
- if err != nil {
- return 0, err
- }
if frame.header.MaskingKey != nil {
for i := 0; i < n; i++ {
msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
diff --git a/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go
index da0dd964c..9f9b9a52d 100644
--- a/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go
@@ -144,6 +144,8 @@ type frameHandler interface {
}
// Conn represents a WebSocket connection.
+//
+// Multiple goroutines may invoke methods on a Conn simultaneously.
type Conn struct {
config *Config
request *http.Request
@@ -207,9 +209,6 @@ func (ws *Conn) Write(msg []byte) (n int, err error) {
}
n, err = w.Write(msg)
w.Close()
- if err != nil {
- return n, err
- }
return n, err
}
diff --git a/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/.gitignore b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/.gitignore
new file mode 100644
index 000000000..00268614f
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/.gitignore
@@ -0,0 +1,22 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
diff --git a/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/LICENSE.txt b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/LICENSE.txt
new file mode 100644
index 000000000..a4a11046c
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/LICENSE.txt
@@ -0,0 +1,8 @@
+The MIT License (MIT)
+Copyright (c) 2013 npipe authors
+
+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. \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/README.md b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/README.md
new file mode 100644
index 000000000..420a4d16c
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/README.md
@@ -0,0 +1,308 @@
+npipe [![Build status](https://ci.appveyor.com/api/projects/status/00vuepirsot29qwi)](https://ci.appveyor.com/project/natefinch/npipe) [![GoDoc](https://godoc.org/gopkg.in/natefinch/npipe.v2?status.svg)](https://godoc.org/gopkg.in/natefinch/npipe.v2)
+=====
+Package npipe provides a pure Go wrapper around Windows named pipes.
+
+Windows named pipe documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365780
+
+Note that the code lives at https://github.com/natefinch/npipe (v2 branch)
+but should be imported as gopkg.in/natefinch/npipe.v2 (the package name is
+still npipe).
+
+npipe provides an interface based on stdlib's net package, with Dial, Listen,
+and Accept functions, as well as associated implementations of net.Conn and
+net.Listener. It supports rpc over the connection.
+
+### Notes
+* Deadlines for reading/writing to the connection are only functional in Windows Vista/Server 2008 and above, due to limitations with the Windows API.
+
+* The pipes support byte mode only (no support for message mode)
+
+### Examples
+The Dial function connects a client to a named pipe:
+
+
+ conn, err := npipe.Dial(`\\.\pipe\mypipename`)
+ if err != nil {
+ <handle error>
+ }
+ fmt.Fprintf(conn, "Hi server!\n")
+ msg, err := bufio.NewReader(conn).ReadString('\n')
+ ...
+
+The Listen function creates servers:
+
+
+ ln, err := npipe.Listen(`\\.\pipe\mypipename`)
+ if err != nil {
+ // handle error
+ }
+ for {
+ conn, err := ln.Accept()
+ if err != nil {
+ // handle error
+ continue
+ }
+ go handleConnection(conn)
+ }
+
+
+
+
+
+## Variables
+``` go
+var ErrClosed = PipeError{"Pipe has been closed.", false}
+```
+ErrClosed is the error returned by PipeListener.Accept when Close is called
+on the PipeListener.
+
+
+
+## type PipeAddr
+``` go
+type PipeAddr string
+```
+PipeAddr represents the address of a named pipe.
+
+
+
+
+
+
+
+
+
+
+
+### func (PipeAddr) Network
+``` go
+func (a PipeAddr) Network() string
+```
+Network returns the address's network name, "pipe".
+
+
+
+### func (PipeAddr) String
+``` go
+func (a PipeAddr) String() string
+```
+String returns the address of the pipe
+
+
+
+## type PipeConn
+``` go
+type PipeConn struct {
+ // contains filtered or unexported fields
+}
+```
+PipeConn is the implementation of the net.Conn interface for named pipe connections.
+
+
+
+
+
+
+
+
+
+### func Dial
+``` go
+func Dial(address string) (*PipeConn, error)
+```
+Dial connects to a named pipe with the given address. If the specified pipe is not available,
+it will wait indefinitely for the pipe to become available.
+
+The address must be of the form \\.\\pipe\<name> for local pipes and \\<computer>\pipe\<name>
+for remote pipes.
+
+Dial will return a PipeError if you pass in a badly formatted pipe name.
+
+Examples:
+
+
+ // local pipe
+ conn, err := Dial(`\\.\pipe\mypipename`)
+
+ // remote pipe
+ conn, err := Dial(`\\othercomp\pipe\mypipename`)
+
+
+### func DialTimeout
+``` go
+func DialTimeout(address string, timeout time.Duration) (*PipeConn, error)
+```
+DialTimeout acts like Dial, but will time out after the duration of timeout
+
+
+
+
+### func (\*PipeConn) Close
+``` go
+func (c *PipeConn) Close() error
+```
+Close closes the connection.
+
+
+
+### func (\*PipeConn) LocalAddr
+``` go
+func (c *PipeConn) LocalAddr() net.Addr
+```
+LocalAddr returns the local network address.
+
+
+
+### func (\*PipeConn) Read
+``` go
+func (c *PipeConn) Read(b []byte) (int, error)
+```
+Read implements the net.Conn Read method.
+
+
+
+### func (\*PipeConn) RemoteAddr
+``` go
+func (c *PipeConn) RemoteAddr() net.Addr
+```
+RemoteAddr returns the remote network address.
+
+
+
+### func (\*PipeConn) SetDeadline
+``` go
+func (c *PipeConn) SetDeadline(t time.Time) error
+```
+SetDeadline implements the net.Conn SetDeadline method.
+Note that timeouts are only supported on Windows Vista/Server 2008 and above
+
+
+
+### func (\*PipeConn) SetReadDeadline
+``` go
+func (c *PipeConn) SetReadDeadline(t time.Time) error
+```
+SetReadDeadline implements the net.Conn SetReadDeadline method.
+Note that timeouts are only supported on Windows Vista/Server 2008 and above
+
+
+
+### func (\*PipeConn) SetWriteDeadline
+``` go
+func (c *PipeConn) SetWriteDeadline(t time.Time) error
+```
+SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+Note that timeouts are only supported on Windows Vista/Server 2008 and above
+
+
+
+### func (\*PipeConn) Write
+``` go
+func (c *PipeConn) Write(b []byte) (int, error)
+```
+Write implements the net.Conn Write method.
+
+
+
+## type PipeError
+``` go
+type PipeError struct {
+ // contains filtered or unexported fields
+}
+```
+PipeError is an error related to a call to a pipe
+
+
+
+
+
+
+
+
+
+
+
+### func (PipeError) Error
+``` go
+func (e PipeError) Error() string
+```
+Error implements the error interface
+
+
+
+### func (PipeError) Temporary
+``` go
+func (e PipeError) Temporary() bool
+```
+Temporary implements net.AddrError.Temporary()
+
+
+
+### func (PipeError) Timeout
+``` go
+func (e PipeError) Timeout() bool
+```
+Timeout implements net.AddrError.Timeout()
+
+
+
+## type PipeListener
+``` go
+type PipeListener struct {
+ // contains filtered or unexported fields
+}
+```
+PipeListener is a named pipe listener. Clients should typically
+use variables of type net.Listener instead of assuming named pipe.
+
+
+
+
+
+
+
+
+
+### func Listen
+``` go
+func Listen(address string) (*PipeListener, error)
+```
+Listen returns a new PipeListener that will listen on a pipe with the given
+address. The address must be of the form \\.\pipe\<name>
+
+Listen will return a PipeError for an incorrectly formatted pipe name.
+
+
+
+
+### func (\*PipeListener) Accept
+``` go
+func (l *PipeListener) Accept() (net.Conn, error)
+```
+Accept implements the Accept method in the net.Listener interface; it
+waits for the next call and returns a generic net.Conn.
+
+
+
+### func (\*PipeListener) AcceptPipe
+``` go
+func (l *PipeListener) AcceptPipe() (*PipeConn, error)
+```
+AcceptPipe accepts the next incoming call and returns the new connection.
+
+
+
+### func (\*PipeListener) Addr
+``` go
+func (l *PipeListener) Addr() net.Addr
+```
+Addr returns the listener's network address, a PipeAddr.
+
+
+
+### func (\*PipeListener) Close
+``` go
+func (l *PipeListener) Close() error
+```
+Close stops listening on the address.
+Already Accepted connections are not closed.
diff --git a/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/doc.go b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/doc.go
new file mode 100644
index 000000000..3445773b4
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/doc.go
@@ -0,0 +1,50 @@
+// Copyright 2013 Nate Finch. All rights reserved.
+// Use of this source code is governed by an MIT-style
+// license that can be found in the LICENSE file.
+
+// Package npipe provides a pure Go wrapper around Windows named pipes.
+//
+// !! Note, this package is Windows-only. There is no code to compile on linux.
+//
+// Windows named pipe documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365780
+//
+// Note that the code lives at https://github.com/natefinch/npipe (v2 branch)
+// but should be imported as gopkg.in/natefinch/npipe.v2 (the package name is
+// still npipe).
+//
+// npipe provides an interface based on stdlib's net package, with Dial, Listen,
+// and Accept functions, as well as associated implementations of net.Conn and
+// net.Listener. It supports rpc over the connection.
+//
+// Notes
+//
+// * Deadlines for reading/writing to the connection are only functional in Windows Vista/Server 2008 and above, due to limitations with the Windows API.
+//
+// * The pipes support byte mode only (no support for message mode)
+//
+// Examples
+//
+// The Dial function connects a client to a named pipe:
+// conn, err := npipe.Dial(`\\.\pipe\mypipename`)
+// if err != nil {
+// <handle error>
+// }
+// fmt.Fprintf(conn, "Hi server!\n")
+// msg, err := bufio.NewReader(conn).ReadString('\n')
+// ...
+//
+// The Listen function creates servers:
+//
+// ln, err := npipe.Listen(`\\.\pipe\mypipename`)
+// if err != nil {
+// // handle error
+// }
+// for {
+// conn, err := ln.Accept()
+// if err != nil {
+// // handle error
+// continue
+// }
+// go handleConnection(conn)
+// }
+package npipe
diff --git a/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/npipe_windows.go b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/npipe_windows.go
new file mode 100755
index 000000000..5e7cf13ee
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/npipe_windows.go
@@ -0,0 +1,531 @@
+package npipe
+
+//sys createNamedPipe(name *uint16, openMode uint32, pipeMode uint32, maxInstances uint32, outBufSize uint32, inBufSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
+//sys connectNamedPipe(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) = ConnectNamedPipe
+//sys disconnectNamedPipe(handle syscall.Handle) (err error) = DisconnectNamedPipe
+//sys waitNamedPipe(name *uint16, timeout uint32) (err error) = WaitNamedPipeW
+//sys createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateEventW
+//sys getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, transferred *uint32, wait bool) (err error) = GetOverlappedResult
+//sys cancelIoEx(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) = CancelIoEx
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "sync"
+ "syscall"
+ "time"
+)
+
+const (
+ // openMode
+ pipe_access_duplex = 0x3
+ pipe_access_inbound = 0x1
+ pipe_access_outbound = 0x2
+
+ // openMode write flags
+ file_flag_first_pipe_instance = 0x00080000
+ file_flag_write_through = 0x80000000
+ file_flag_overlapped = 0x40000000
+
+ // openMode ACL flags
+ write_dac = 0x00040000
+ write_owner = 0x00080000
+ access_system_security = 0x01000000
+
+ // pipeMode
+ pipe_type_byte = 0x0
+ pipe_type_message = 0x4
+
+ // pipeMode read mode flags
+ pipe_readmode_byte = 0x0
+ pipe_readmode_message = 0x2
+
+ // pipeMode wait mode flags
+ pipe_wait = 0x0
+ pipe_nowait = 0x1
+
+ // pipeMode remote-client mode flags
+ pipe_accept_remote_clients = 0x0
+ pipe_reject_remote_clients = 0x8
+
+ pipe_unlimited_instances = 255
+
+ nmpwait_wait_forever = 0xFFFFFFFF
+
+ // the two not-an-errors below occur if a client connects to the pipe between
+ // the server's CreateNamedPipe and ConnectNamedPipe calls.
+ error_no_data syscall.Errno = 0xE8
+ error_pipe_connected syscall.Errno = 0x217
+ error_pipe_busy syscall.Errno = 0xE7
+ error_sem_timeout syscall.Errno = 0x79
+
+ error_bad_pathname syscall.Errno = 0xA1
+ error_invalid_name syscall.Errno = 0x7B
+
+ error_io_incomplete syscall.Errno = 0x3e4
+)
+
+var _ net.Conn = (*PipeConn)(nil)
+var _ net.Listener = (*PipeListener)(nil)
+
+// ErrClosed is the error returned by PipeListener.Accept when Close is called
+// on the PipeListener.
+var ErrClosed = PipeError{"Pipe has been closed.", false}
+
+// PipeError is an error related to a call to a pipe
+type PipeError struct {
+ msg string
+ timeout bool
+}
+
+// Error implements the error interface
+func (e PipeError) Error() string {
+ return e.msg
+}
+
+// Timeout implements net.AddrError.Timeout()
+func (e PipeError) Timeout() bool {
+ return e.timeout
+}
+
+// Temporary implements net.AddrError.Temporary()
+func (e PipeError) Temporary() bool {
+ return false
+}
+
+// Dial connects to a named pipe with the given address. If the specified pipe is not available,
+// it will wait indefinitely for the pipe to become available.
+//
+// The address must be of the form \\.\\pipe\<name> for local pipes and \\<computer>\pipe\<name>
+// for remote pipes.
+//
+// Dial will return a PipeError if you pass in a badly formatted pipe name.
+//
+// Examples:
+// // local pipe
+// conn, err := Dial(`\\.\pipe\mypipename`)
+//
+// // remote pipe
+// conn, err := Dial(`\\othercomp\pipe\mypipename`)
+func Dial(address string) (*PipeConn, error) {
+ for {
+ conn, err := dial(address, nmpwait_wait_forever)
+ if err == nil {
+ return conn, nil
+ }
+ if isPipeNotReady(err) {
+ <-time.After(100 * time.Millisecond)
+ continue
+ }
+ return nil, err
+ }
+}
+
+// DialTimeout acts like Dial, but will time out after the duration of timeout
+func DialTimeout(address string, timeout time.Duration) (*PipeConn, error) {
+ deadline := time.Now().Add(timeout)
+
+ now := time.Now()
+ for now.Before(deadline) {
+ millis := uint32(deadline.Sub(now) / time.Millisecond)
+ conn, err := dial(address, millis)
+ if err == nil {
+ return conn, nil
+ }
+ if err == error_sem_timeout {
+ // This is WaitNamedPipe's timeout error, so we know we're done
+ return nil, PipeError{fmt.Sprintf(
+ "Timed out waiting for pipe '%s' to come available", address), true}
+ }
+ if isPipeNotReady(err) {
+ left := deadline.Sub(time.Now())
+ retry := 100 * time.Millisecond
+ if left > retry {
+ <-time.After(retry)
+ } else {
+ <-time.After(left - time.Millisecond)
+ }
+ now = time.Now()
+ continue
+ }
+ return nil, err
+ }
+ return nil, PipeError{fmt.Sprintf(
+ "Timed out waiting for pipe '%s' to come available", address), true}
+}
+
+// isPipeNotReady checks the error to see if it indicates the pipe is not ready
+func isPipeNotReady(err error) bool {
+ // Pipe Busy means another client just grabbed the open pipe end,
+ // and the server hasn't made a new one yet.
+ // File Not Found means the server hasn't created the pipe yet.
+ // Neither is a fatal error.
+
+ return err == syscall.ERROR_FILE_NOT_FOUND || err == error_pipe_busy
+}
+
+// newOverlapped creates a structure used to track asynchronous
+// I/O requests that have been issued.
+func newOverlapped() (*syscall.Overlapped, error) {
+ event, err := createEvent(nil, true, true, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &syscall.Overlapped{HEvent: event}, nil
+}
+
+// waitForCompletion waits for an asynchronous I/O request referred to by overlapped to complete.
+// This function returns the number of bytes transferred by the operation and an error code if
+// applicable (nil otherwise).
+func waitForCompletion(handle syscall.Handle, overlapped *syscall.Overlapped) (uint32, error) {
+ _, err := syscall.WaitForSingleObject(overlapped.HEvent, syscall.INFINITE)
+ if err != nil {
+ return 0, err
+ }
+ var transferred uint32
+ err = getOverlappedResult(handle, overlapped, &transferred, true)
+ return transferred, err
+}
+
+// dial is a helper to initiate a connection to a named pipe that has been started by a server.
+// The timeout is only enforced if the pipe server has already created the pipe, otherwise
+// this function will return immediately.
+func dial(address string, timeout uint32) (*PipeConn, error) {
+ name, err := syscall.UTF16PtrFromString(string(address))
+ if err != nil {
+ return nil, err
+ }
+ // If at least one instance of the pipe has been created, this function
+ // will wait timeout milliseconds for it to become available.
+ // It will return immediately regardless of timeout, if no instances
+ // of the named pipe have been created yet.
+ // If this returns with no error, there is a pipe available.
+ if err := waitNamedPipe(name, timeout); err != nil {
+ if err == error_bad_pathname {
+ // badly formatted pipe name
+ return nil, badAddr(address)
+ }
+ return nil, err
+ }
+ pathp, err := syscall.UTF16PtrFromString(address)
+ if err != nil {
+ return nil, err
+ }
+ handle, err := syscall.CreateFile(pathp, syscall.GENERIC_READ|syscall.GENERIC_WRITE,
+ uint32(syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE), nil, syscall.OPEN_EXISTING,
+ syscall.FILE_FLAG_OVERLAPPED, 0)
+ if err != nil {
+ return nil, err
+ }
+ return &PipeConn{handle: handle, addr: PipeAddr(address)}, nil
+}
+
+// Listen returns a new PipeListener that will listen on a pipe with the given
+// address. The address must be of the form \\.\pipe\<name>
+//
+// Listen will return a PipeError for an incorrectly formatted pipe name.
+func Listen(address string) (*PipeListener, error) {
+ handle, err := createPipe(address, true)
+ if err == error_invalid_name {
+ return nil, badAddr(address)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ return &PipeListener{
+ addr: PipeAddr(address),
+ handle: handle,
+ }, nil
+}
+
+// PipeListener is a named pipe listener. Clients should typically
+// use variables of type net.Listener instead of assuming named pipe.
+type PipeListener struct {
+ mu sync.Mutex
+
+ addr PipeAddr
+ handle syscall.Handle
+ closed bool
+
+ // acceptHandle contains the current handle waiting for
+ // an incoming connection or nil.
+ acceptHandle syscall.Handle
+ // acceptOverlapped is set before waiting on a connection.
+ // If not waiting, it is nil.
+ acceptOverlapped *syscall.Overlapped
+}
+
+// Accept implements the Accept method in the net.Listener interface; it
+// waits for the next call and returns a generic net.Conn.
+func (l *PipeListener) Accept() (net.Conn, error) {
+ c, err := l.AcceptPipe()
+ for err == error_no_data {
+ // Ignore clients that connect and immediately disconnect.
+ c, err = l.AcceptPipe()
+ }
+ if err != nil {
+ return nil, err
+ }
+ return c, nil
+}
+
+// AcceptPipe accepts the next incoming call and returns the new connection.
+// It might return an error if a client connected and immediately cancelled
+// the connection.
+func (l *PipeListener) AcceptPipe() (*PipeConn, error) {
+ if l == nil {
+ return nil, syscall.EINVAL
+ }
+
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ if l.addr == "" || l.closed {
+ return nil, syscall.EINVAL
+ }
+
+ // the first time we call accept, the handle will have been created by the Listen
+ // call. This is to prevent race conditions where the client thinks the server
+ // isn't listening because it hasn't actually called create yet. After the first time, we'll
+ // have to create a new handle each time
+ handle := l.handle
+ if handle == 0 {
+ var err error
+ handle, err = createPipe(string(l.addr), false)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ l.handle = 0
+ }
+
+ overlapped, err := newOverlapped()
+ if err != nil {
+ return nil, err
+ }
+ defer syscall.CloseHandle(overlapped.HEvent)
+ err = connectNamedPipe(handle, overlapped)
+ if err == nil || err == error_pipe_connected {
+ return &PipeConn{handle: handle, addr: l.addr}, nil
+ }
+
+ if err == error_io_incomplete || err == syscall.ERROR_IO_PENDING {
+ l.acceptOverlapped = overlapped
+ l.acceptHandle = handle
+ // unlock here so close can function correctly while we wait (we'll
+ // get relocked via the defer below, before the original defer
+ // unlock happens.)
+ l.mu.Unlock()
+ defer func() {
+ l.mu.Lock()
+ l.acceptOverlapped = nil
+ l.acceptHandle = 0
+ // unlock is via defer above.
+ }()
+ _, err = waitForCompletion(handle, overlapped)
+ }
+ if err == syscall.ERROR_OPERATION_ABORTED {
+ // Return error compatible to net.Listener.Accept() in case the
+ // listener was closed.
+ return nil, ErrClosed
+ }
+ if err != nil {
+ return nil, err
+ }
+ return &PipeConn{handle: handle, addr: l.addr}, nil
+}
+
+// Close stops listening on the address.
+// Already Accepted connections are not closed.
+func (l *PipeListener) Close() error {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ if l.closed {
+ return nil
+ }
+ l.closed = true
+ if l.handle != 0 {
+ err := disconnectNamedPipe(l.handle)
+ if err != nil {
+ return err
+ }
+ err = syscall.CloseHandle(l.handle)
+ if err != nil {
+ return err
+ }
+ l.handle = 0
+ }
+ if l.acceptOverlapped != nil && l.acceptHandle != 0 {
+ // Cancel the pending IO. This call does not block, so it is safe
+ // to hold onto the mutex above.
+ if err := cancelIoEx(l.acceptHandle, l.acceptOverlapped); err != nil {
+ return err
+ }
+ err := syscall.CloseHandle(l.acceptOverlapped.HEvent)
+ if err != nil {
+ return err
+ }
+ l.acceptOverlapped.HEvent = 0
+ err = syscall.CloseHandle(l.acceptHandle)
+ if err != nil {
+ return err
+ }
+ l.acceptHandle = 0
+ }
+ return nil
+}
+
+// Addr returns the listener's network address, a PipeAddr.
+func (l *PipeListener) Addr() net.Addr { return l.addr }
+
+// PipeConn is the implementation of the net.Conn interface for named pipe connections.
+type PipeConn struct {
+ handle syscall.Handle
+ addr PipeAddr
+
+ // these aren't actually used yet
+ readDeadline *time.Time
+ writeDeadline *time.Time
+}
+
+type iodata struct {
+ n uint32
+ err error
+}
+
+// completeRequest looks at iodata to see if a request is pending. If so, it waits for it to either complete or to
+// abort due to hitting the specified deadline. Deadline may be set to nil to wait forever. If no request is pending,
+// the content of iodata is returned.
+func (c *PipeConn) completeRequest(data iodata, deadline *time.Time, overlapped *syscall.Overlapped) (int, error) {
+ if data.err == error_io_incomplete || data.err == syscall.ERROR_IO_PENDING {
+ var timer <-chan time.Time
+ if deadline != nil {
+ if timeDiff := deadline.Sub(time.Now()); timeDiff > 0 {
+ timer = time.After(timeDiff)
+ }
+ }
+ done := make(chan iodata)
+ go func() {
+ n, err := waitForCompletion(c.handle, overlapped)
+ done <- iodata{n, err}
+ }()
+ select {
+ case data = <-done:
+ case <-timer:
+ syscall.CancelIoEx(c.handle, overlapped)
+ data = iodata{0, timeout(c.addr.String())}
+ }
+ }
+ // Windows will produce ERROR_BROKEN_PIPE upon closing
+ // a handle on the other end of a connection. Go RPC
+ // expects an io.EOF error in this case.
+ if data.err == syscall.ERROR_BROKEN_PIPE {
+ data.err = io.EOF
+ }
+ return int(data.n), data.err
+}
+
+// Read implements the net.Conn Read method.
+func (c *PipeConn) Read(b []byte) (int, error) {
+ // Use ReadFile() rather than Read() because the latter
+ // contains a workaround that eats ERROR_BROKEN_PIPE.
+ overlapped, err := newOverlapped()
+ if err != nil {
+ return 0, err
+ }
+ defer syscall.CloseHandle(overlapped.HEvent)
+ var n uint32
+ err = syscall.ReadFile(c.handle, b, &n, overlapped)
+ return c.completeRequest(iodata{n, err}, c.readDeadline, overlapped)
+}
+
+// Write implements the net.Conn Write method.
+func (c *PipeConn) Write(b []byte) (int, error) {
+ overlapped, err := newOverlapped()
+ if err != nil {
+ return 0, err
+ }
+ defer syscall.CloseHandle(overlapped.HEvent)
+ var n uint32
+ err = syscall.WriteFile(c.handle, b, &n, overlapped)
+ return c.completeRequest(iodata{n, err}, c.writeDeadline, overlapped)
+}
+
+// Close closes the connection.
+func (c *PipeConn) Close() error {
+ return syscall.CloseHandle(c.handle)
+}
+
+// LocalAddr returns the local network address.
+func (c *PipeConn) LocalAddr() net.Addr {
+ return c.addr
+}
+
+// RemoteAddr returns the remote network address.
+func (c *PipeConn) RemoteAddr() net.Addr {
+ // not sure what to do here, we don't have remote addr....
+ return c.addr
+}
+
+// SetDeadline implements the net.Conn SetDeadline method.
+// Note that timeouts are only supported on Windows Vista/Server 2008 and above
+func (c *PipeConn) SetDeadline(t time.Time) error {
+ c.SetReadDeadline(t)
+ c.SetWriteDeadline(t)
+ return nil
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+// Note that timeouts are only supported on Windows Vista/Server 2008 and above
+func (c *PipeConn) SetReadDeadline(t time.Time) error {
+ c.readDeadline = &t
+ return nil
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+// Note that timeouts are only supported on Windows Vista/Server 2008 and above
+func (c *PipeConn) SetWriteDeadline(t time.Time) error {
+ c.writeDeadline = &t
+ return nil
+}
+
+// PipeAddr represents the address of a named pipe.
+type PipeAddr string
+
+// Network returns the address's network name, "pipe".
+func (a PipeAddr) Network() string { return "pipe" }
+
+// String returns the address of the pipe
+func (a PipeAddr) String() string {
+ return string(a)
+}
+
+// createPipe is a helper function to make sure we always create pipes
+// with the same arguments, since subsequent calls to create pipe need
+// to use the same arguments as the first one. If first is set, fail
+// if the pipe already exists.
+func createPipe(address string, first bool) (syscall.Handle, error) {
+ n, err := syscall.UTF16PtrFromString(address)
+ if err != nil {
+ return 0, err
+ }
+ mode := uint32(pipe_access_duplex | syscall.FILE_FLAG_OVERLAPPED)
+ if first {
+ mode |= file_flag_first_pipe_instance
+ }
+ return createNamedPipe(n,
+ mode,
+ pipe_type_byte,
+ pipe_unlimited_instances,
+ 512, 512, 0, nil)
+}
+
+func badAddr(addr string) PipeError {
+ return PipeError{fmt.Sprintf("Invalid pipe address '%s'.", addr), false}
+}
+func timeout(addr string) PipeError {
+ return PipeError{fmt.Sprintf("Pipe IO timed out waiting for '%s'", addr), true}
+}
diff --git a/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_386.go b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_386.go
new file mode 100644
index 000000000..c283e6cf9
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_386.go
@@ -0,0 +1,124 @@
+// +build windows
+// go build mksyscall_windows.go && ./mksyscall_windows npipe_windows.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package npipe
+
+import "unsafe"
+import "syscall"
+
+var (
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+
+ procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
+ procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
+ procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe")
+ procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
+ procCreateEventW = modkernel32.NewProc("CreateEventW")
+ procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
+ procCancelIoEx = modkernel32.NewProc("CancelIoEx")
+)
+
+func createNamedPipe(name *uint16, openMode uint32, pipeMode uint32, maxInstances uint32, outBufSize uint32, inBufSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
+ r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(openMode), uintptr(pipeMode), uintptr(maxInstances), uintptr(outBufSize), uintptr(inBufSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
+ handle = syscall.Handle(r0)
+ if handle == syscall.InvalidHandle {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func cancelIoEx(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) {
+ r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func connectNamedPipe(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) {
+ r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func disconnectNamedPipe(handle syscall.Handle) (err error) {
+ r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(handle), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func waitNamedPipe(name *uint16, timeout uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) {
+ var _p0 uint32
+ if manualReset {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ var _p1 uint32
+ if initialState {
+ _p1 = 1
+ } else {
+ _p1 = 0
+ }
+ r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(sa)), uintptr(_p0), uintptr(_p1), uintptr(unsafe.Pointer(name)), 0, 0)
+ handle = syscall.Handle(r0)
+ if handle == syscall.InvalidHandle {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, transferred *uint32, wait bool) (err error) {
+ var _p0 uint32
+ if wait {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transferred)), uintptr(_p0), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
diff --git a/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_amd64.go b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_amd64.go
new file mode 100644
index 000000000..c283e6cf9
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/natefinch/npipe.v2/znpipe_windows_amd64.go
@@ -0,0 +1,124 @@
+// +build windows
+// go build mksyscall_windows.go && ./mksyscall_windows npipe_windows.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package npipe
+
+import "unsafe"
+import "syscall"
+
+var (
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+
+ procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
+ procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
+ procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe")
+ procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
+ procCreateEventW = modkernel32.NewProc("CreateEventW")
+ procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
+ procCancelIoEx = modkernel32.NewProc("CancelIoEx")
+)
+
+func createNamedPipe(name *uint16, openMode uint32, pipeMode uint32, maxInstances uint32, outBufSize uint32, inBufSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
+ r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(openMode), uintptr(pipeMode), uintptr(maxInstances), uintptr(outBufSize), uintptr(inBufSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
+ handle = syscall.Handle(r0)
+ if handle == syscall.InvalidHandle {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func cancelIoEx(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) {
+ r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func connectNamedPipe(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) {
+ r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func disconnectNamedPipe(handle syscall.Handle) (err error) {
+ r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(handle), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func waitNamedPipe(name *uint16, timeout uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) {
+ var _p0 uint32
+ if manualReset {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ var _p1 uint32
+ if initialState {
+ _p1 = 1
+ } else {
+ _p1 = 0
+ }
+ r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(sa)), uintptr(_p0), uintptr(_p1), uintptr(unsafe.Pointer(name)), 0, 0)
+ handle = syscall.Handle(r0)
+ if handle == syscall.InvalidHandle {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, transferred *uint32, wait bool) (err error) {
+ var _p0 uint32
+ if wait {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transferred)), uintptr(_p0), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
diff --git a/README.md b/README.md
index 95c7a3615..94474dce3 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/6874
## Automated development builds
-The following builds are build automatically by our build servers after each push to the [develop](https://github.com/ethereum/go-ethereum/tree/develop) branch.
+The following builds are built automatically by our build servers after each push to the [develop](https://github.com/ethereum/go-ethereum/tree/develop) branch.
* [Docker](https://registry.hub.docker.com/u/ethereum/client-go/)
* [OS X](http://build.ethdev.com/builds/OSX%20Go%20develop%20branch/Mist-OSX-latest.dmg)
@@ -50,10 +50,201 @@ The go-ethereum project comes with several wrappers/executables found in the `cm
| `abigen` | Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) with expanded functionality if the contract bytecode is also available. However it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) wiki page for details. |
| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. |
| `disasm` | Bytecode disassembler to convert EVM (Ethereum Virtual Machine) bytecode into more user friendly assembly-like opcodes (e.g. `echo "6001" | disasm`). For details on the individual opcodes, please see pages 22-30 of the [Ethereum Yellow Paper](http://gavwood.com/paper.pdf). |
-| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow insolated, fine graned debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug`). |
+| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow insolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug`). |
| `gethrpctest` | Developer utility tool to support our [ethereum/rpc-test](https://github.com/ethereum/rpc-tests) test suite which validates baseline conformity to the [Ethereum JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) specs. Please see the [test suite's readme](https://github.com/ethereum/rpc-tests/blob/master/README.md) for details. |
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://github.com/ethereum/wiki/wiki/RLP)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
+## Running geth
+
+Going through all the possible command line flags is out of scope here (please consult our
+[CLI Wiki page](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)), but we've
+enumerated a few common parameter combos to get you up to speed quickly on how you can run your
+own Geth instance.
+
+### Full node on the main Ethereum network
+
+By far the most common scenario is people wanting to simply interact with the Ethereum network:
+create accounts; transfer funds; deploy and interact with contracts. For this particular use-case
+the user doesn't care about years-old historical data, so we can fast-sync quickly to the current
+state of the network. To do so:
+
+```
+$ geth --fast --cache=512 console
+```
+
+This command will:
+
+ * Start geth in fast sync mode (`--fast`), causing it to download more data in exchange for avoiding
+ processing the entire history of the Ethereum network, which is very CPU intensive.
+ * Bump the memory allowance of the database to 512MB (`--cache=512`), which can help significantly in
+ sync times especially for HDD users. This flag is optional and you can set it as high or as low as
+ you'd like, though we'd recommend the 512MB - 2GB range.
+ * Start up Geth's built-in interactive [JavaScript console](https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console),
+ (via the trailing `console` subcommand) through which you can invoke all official [`web3` methods](https://github.com/ethereum/wiki/wiki/JavaScript-API)
+ as well as Geth's own [management APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs).
+ This too is optional and if you leave it out you can always attach to an already running Geth instance
+ with `geth --attach`.
+
+### Full node on the Ethereum test network
+
+Transitioning towards developers, if you'd like to play around with creating Ethereum contracts, you
+almost certainly would like to do that without any real money involved until you get the hang of the
+entire system. In other words, instead of attaching to the main network, you want to join the **test**
+network with your node, which is fully equivalent to the main network, but with play-Ether only.
+
+```
+$ geth --testnet --fast --cache=512 console
+```
+
+The `--fast`, `--cache` flags and `console` subcommand have the exact same meaning as above and they
+are equially useful on the testnet too. Please see above for their explanations if you've skipped to
+here.
+
+Specifying the `--testnet` flag however will reconfigure your Geth instance a bit:
+
+ * Instead of using the default data directory (`~/.ethereum` on Linux for example), Geth will nest
+ itself one level deeper into a `testnet` subfolder (`~/.ethereum/testnet` on Linux).
+ * Instead of connecting the main Ethereum network, the client will connect to the test network,
+ which uses different P2P bootnodes, different network IDs and genesis states.
+
+*Note: Although there are some internal protective measures to prevent transactions from crossing
+over between the main network and test network (different starting nonces), you should make sure to
+always use separate accounts for play-money and real-money. Unless you manually move accounts, Geth
+will by default correctly separate the two networks and will not make any accounts available between
+them.*
+
+### Programatically interfacing Geth nodes
+
+As a developer, sooner rather than later you'll want to start interacting with Geth and the Ethereum
+network via your own programs and not manually through the console. To aid this, Geth has built in
+support for a JSON-RPC based APIs ([standard APIs](https://github.com/ethereum/wiki/wiki/JSON-RPC) and
+[Geth specific APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs)). These can be
+exposed via HTTP, WebSockets and IPC (unix sockets on unix based platroms, and named pipes on Windows).
+
+The IPC interface is enabled by default and exposes all the APIs supported by Geth, whereas the HTTP
+and WS interfaces need to manually be enabled and only expose a subset of APIs due to security reasons.
+These can be turned on/off and configured as you'd expect.
+
+HTTP based JSON-RPC API options:
+
+ * `--rpc` Enable the HTTP-RPC server
+ * `--rpcaddr` HTTP-RPC server listening interface (default: "localhost")
+ * `--rpcport` HTTP-RPC server listening port (default: 8545)
+ * `--rpcapi` API's offered over the HTTP-RPC interface (default: "eth,net,web3")
+ * `--rpccorsdomain` Comma separated list of domains from which to accept cross origin requests (browser enforced)
+ * `--ws` Enable the WS-RPC server
+ * `--wsaddr` WS-RPC server listening interface (default: "localhost")
+ * `--wsport` WS-RPC server listening port (default: 8546)
+ * `--wsapi` API's offered over the WS-RPC interface (default: "eth,net,web3")
+ * `--wsorigins` Origins from which to accept websockets requests
+ * `--ipcdisable` Disable the IPC-RPC server
+ * `--ipcapi` API's offered over the IPC-RPC interface (default: "admin,debug,eth,miner,net,personal,shh,txpool,web3")
+ * `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it)
+
+You'll need to use your own programming environments' capabilities (libraries, tools, etc) to connect
+via HTTP, WS or IPC to a Geth node configured with the above flags and you'll need to speak [JSON-RPC](http://www.jsonrpc.org/specification)
+on all transports. You can reuse the same connection for multiple requests!
+
+**Note: Please understand the security implications of opening up an HTTP/WS based transport before
+doing so! Hackers on the internet are actively trying to subvert Ethereum nodes with exposed APIs!
+Further, all browser tabs can access locally running webservers, so malicious webpages could try to
+subvert locally available APIs!**
+
+### Operating a private network
+
+Maintaining your own private network is more involved as a lot of configurations taken for granted in
+the official networks need to be manually set up.
+
+#### Defining the private genesis state
+
+First, you'll need to create the genesis state of your networks, which all nodes need to be aware of
+and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`):
+
+```json
+{
+ "alloc" : {},
+ "coinbase" : "0x0000000000000000000000000000000000000000",
+ "difficulty" : "0x20000",
+ "extraData" : "",
+ "gasLimit" : "0x2fefd8",
+ "nonce" : "0x0000000000000042",
+ "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp" : "0x00"
+}
+```
+
+The above fields should be fine for most purposes, although we'd recommend changing the `nonce` to
+some random value so you prevent unknown remote nodes from being able to connect to you. If you'd
+like to pre-fund some accounts for easier testing, you can populate the `alloc` field with account
+configs:
+
+```json
+"alloc": {
+ "0x0000000000000000000000000000000000000001": {"balance": "111111111"},
+ "0x0000000000000000000000000000000000000002": {"balance": "222222222"}
+}
+```
+
+With the genesis state defined in the above JSON file, you'll need to initialize **every** Geth node
+with it prior to starting it up to ensure all blockchain parameters are correctly set:
+
+```
+$ geth init path/to/genesis.json
+```
+
+#### Creating the rendezvous point
+
+With all nodes that you want to run initialized to the desired genesis state, you'll need to start a
+bootstrap node that others can use to find each other in your network and/or over the internet. The
+clean way is to configure and run a dedicated bootnode:
+
+```
+$ bootnode --genkey=boot.key
+$ bootnode --nodekey=boot.key
+```
+
+With the bootnode online, it will display an [`enode` URL](https://github.com/ethereum/wiki/wiki/enode-url-format)
+that other nodes can use to connect to it and exchange peer information. Make sure to replace the
+displayed IP address information (most probably `[::]`) with your externally accessible IP to get the
+actual `enode` URL.
+
+*Note: You could also use a full fledged Geth node as a bootnode, but it's the less recommended way.*
+
+#### Starting up your member nodes
+
+With the bootnode operational and externally reachable (you can try `telnet <ip> <port>` to ensure
+it's indeed reachable), start every subsequent Geth node pointed to the bootnode for peer discovery
+via the `--bootnodes` flag. It will probably also be desirable to keep the data directory of your
+private network separated, so do also specify a custom `--datadir` flag.
+
+```
+$ geth --datadir=path/to/custom/data/folder --bootnodes=<bootnode-enode-url-from-above>
+```
+
+*Note: Since your network will be completely cut off from the main and test networks, you'll also
+need to configure a miner to process transactions and create new blocks for you.*
+
+#### Running a private miner
+
+Mining on the public Ethereum network is a complex task as it's only feasible using GPUs, requiring
+an OpenCL or CUDA enabled `ethminer` instance. For information on such a setup, please consult the
+[EtherMining subreddit](https://www.reddit.com/r/EtherMining/) and the [Genoil miner](https://github.com/Genoil/cpp-ethereum)
+repository.
+
+In a private network setting however, a single CPU miner instance is more than enough for practical
+purposes as it can produce a stable stream of blocks at the correct intervals without needing heavy
+resources (consider running on a single thread, no need for multiple ones either). To start a Geth
+instance for mining, run it with all your usual flags, extended by:
+
+```
+$ geth <usual-flags> --mine --minerthreads=1 --etherbase=0x0000000000000000000000000000000000000000
+```
+
+Which will start mining bocks and transactions on a single CPU thread, crediting all proceedings to
+the account specified by `--etherbase`. You can further tune the mining by changing the default gas
+limit blocks converge to (`--targetgaslimit`) and the price transactions are accepted at (`--gasprice`).
+
## Contribution
Thank you for considering to help out with the source code! We welcome contributions from
diff --git a/accounts/abi/bind/backend.go b/accounts/abi/bind/backend.go
index 65806aef4..bec742c29 100644
--- a/accounts/abi/bind/backend.go
+++ b/accounts/abi/bind/backend.go
@@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "golang.org/x/net/context"
)
// ErrNoCode is returned by call and transact operations for which the requested
@@ -35,12 +36,12 @@ type ContractCaller interface {
// HasCode checks if the contract at the given address has any code associated
// with it or not. This is needed to differentiate between contract internal
// errors and the local chain being out of sync.
- HasCode(contract common.Address, pending bool) (bool, error)
+ HasCode(ctx context.Context, contract common.Address, pending bool) (bool, error)
// ContractCall executes an Ethereum contract call with the specified data as
// the input. The pending flag requests execution against the pending block, not
// the stable head of the chain.
- ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error)
+ ContractCall(ctx context.Context, contract common.Address, data []byte, pending bool) ([]byte, error)
}
// ContractTransactor defines the methods needed to allow operating with contract
@@ -50,26 +51,26 @@ type ContractCaller interface {
type ContractTransactor interface {
// PendingAccountNonce retrieves the current pending nonce associated with an
// account.
- PendingAccountNonce(account common.Address) (uint64, error)
+ PendingAccountNonce(ctx context.Context, account common.Address) (uint64, error)
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
// execution of a transaction.
- SuggestGasPrice() (*big.Int, error)
+ SuggestGasPrice(ctx context.Context) (*big.Int, error)
// HasCode checks if the contract at the given address has any code associated
// with it or not. This is needed to differentiate between contract internal
// errors and the local chain being out of sync.
- HasCode(contract common.Address, pending bool) (bool, error)
+ HasCode(ctx context.Context, contract common.Address, pending bool) (bool, error)
// EstimateGasLimit tries to estimate the gas needed to execute a specific
// transaction based on the current pending state of the backend blockchain.
// There is no guarantee that this is the true gas limit requirement as other
// transactions may be added or removed by miners, but it should provide a basis
// for setting a reasonable default.
- EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error)
+ EstimateGasLimit(ctx context.Context, sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error)
// SendTransaction injects the transaction into the pending pool for execution.
- SendTransaction(tx *types.Transaction) error
+ SendTransaction(ctx context.Context, tx *types.Transaction) error
}
// ContractBackend defines the methods needed to allow operating with contract
@@ -84,28 +85,28 @@ type ContractBackend interface {
// HasCode checks if the contract at the given address has any code associated
// with it or not. This is needed to differentiate between contract internal
// errors and the local chain being out of sync.
- HasCode(contract common.Address, pending bool) (bool, error)
+ HasCode(ctx context.Context, contract common.Address, pending bool) (bool, error)
// ContractCall executes an Ethereum contract call with the specified data as
// the input. The pending flag requests execution against the pending block, not
// the stable head of the chain.
- ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error)
+ ContractCall(ctx context.Context, contract common.Address, data []byte, pending bool) ([]byte, error)
// PendingAccountNonce retrieves the current pending nonce associated with an
// account.
- PendingAccountNonce(account common.Address) (uint64, error)
+ PendingAccountNonce(ctx context.Context, account common.Address) (uint64, error)
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
// execution of a transaction.
- SuggestGasPrice() (*big.Int, error)
+ SuggestGasPrice(ctx context.Context) (*big.Int, error)
// EstimateGasLimit tries to estimate the gas needed to execute a specific
// transaction based on the current pending state of the backend blockchain.
// There is no guarantee that this is the true gas limit requirement as other
// transactions may be added or removed by miners, but it should provide a basis
// for setting a reasonable default.
- EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error)
+ EstimateGasLimit(ctx context.Context, sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error)
// SendTransaction injects the transaction into the pending pool for execution.
- SendTransaction(tx *types.Transaction) error
+ SendTransaction(ctx context.Context, tx *types.Transaction) error
}
diff --git a/accounts/abi/bind/backends/nil.go b/accounts/abi/bind/backends/nil.go
index f10bb61ac..54b222f1f 100644
--- a/accounts/abi/bind/backends/nil.go
+++ b/accounts/abi/bind/backends/nil.go
@@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "golang.org/x/net/context"
)
// This nil assignment ensures compile time that nilBackend implements bind.ContractBackend.
@@ -32,16 +33,22 @@ var _ bind.ContractBackend = (*nilBackend)(nil)
// wrappers without calling any methods on them.
type nilBackend struct{}
-func (*nilBackend) ContractCall(common.Address, []byte, bool) ([]byte, error) {
+func (*nilBackend) ContractCall(context.Context, common.Address, []byte, bool) ([]byte, error) {
panic("not implemented")
}
-func (*nilBackend) EstimateGasLimit(common.Address, *common.Address, *big.Int, []byte) (*big.Int, error) {
+func (*nilBackend) EstimateGasLimit(context.Context, common.Address, *common.Address, *big.Int, []byte) (*big.Int, error) {
+ panic("not implemented")
+}
+func (*nilBackend) HasCode(context.Context, common.Address, bool) (bool, error) {
+ panic("not implemented")
+}
+func (*nilBackend) SuggestGasPrice(context.Context) (*big.Int, error) { panic("not implemented") }
+func (*nilBackend) PendingAccountNonce(context.Context, common.Address) (uint64, error) {
+ panic("not implemented")
+}
+func (*nilBackend) SendTransaction(context.Context, *types.Transaction) error {
panic("not implemented")
}
-func (*nilBackend) HasCode(common.Address, bool) (bool, error) { panic("not implemented") }
-func (*nilBackend) SuggestGasPrice() (*big.Int, error) { panic("not implemented") }
-func (*nilBackend) PendingAccountNonce(common.Address) (uint64, error) { panic("not implemented") }
-func (*nilBackend) SendTransaction(*types.Transaction) error { panic("not implemented") }
// NewNilBackend creates a new binding backend that can be used for instantiation
// but will panic on any invocation. Its sole purpose is to help testing.
diff --git a/accounts/abi/bind/backends/remote.go b/accounts/abi/bind/backends/remote.go
index d903cbc8f..58edd791a 100644
--- a/accounts/abi/bind/backends/remote.go
+++ b/accounts/abi/bind/backends/remote.go
@@ -17,17 +17,14 @@
package backends
import (
- "encoding/json"
- "fmt"
"math/big"
- "sync"
- "sync/atomic"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
+ "golang.org/x/net/context"
)
// This nil assignment ensures compile time that rpcBackend implements bind.ContractBackend.
@@ -36,105 +33,34 @@ var _ bind.ContractBackend = (*rpcBackend)(nil)
// rpcBackend implements bind.ContractBackend, and acts as the data provider to
// Ethereum contracts bound to Go structs. It uses an RPC connection to delegate
// all its functionality.
-//
-// Note: The current implementation is a blocking one. This should be replaced
-// by a proper async version when a real RPC client is created.
type rpcBackend struct {
- client rpc.Client // RPC client connection to interact with an API server
- autoid uint32 // ID number to use for the next API request
- lock sync.Mutex // Singleton access until we get to request multiplexing
+ client *rpc.Client // RPC client connection to interact with an API server
}
// NewRPCBackend creates a new binding backend to an RPC provider that can be
// used to interact with remote contracts.
-func NewRPCBackend(client rpc.Client) bind.ContractBackend {
- return &rpcBackend{
- client: client,
- }
-}
-
-// request is a JSON RPC request package assembled internally from the client
-// method calls.
-type request struct {
- JSONRPC string `json:"jsonrpc"` // Version of the JSON RPC protocol, always set to 2.0
- ID int `json:"id"` // Auto incrementing ID number for this request
- Method string `json:"method"` // Remote procedure name to invoke on the server
- Params []interface{} `json:"params"` // List of parameters to pass through (keep types simple)
-}
-
-// response is a JSON RPC response package sent back from the API server.
-type response struct {
- JSONRPC string `json:"jsonrpc"` // Version of the JSON RPC protocol, always set to 2.0
- ID int `json:"id"` // Auto incrementing ID number for this request
- Error *failure `json:"error"` // Any error returned by the remote side
- Result json.RawMessage `json:"result"` // Whatever the remote side sends us in reply
-}
-
-// failure is a JSON RPC response error field sent back from the API server.
-type failure struct {
- Code int `json:"code"` // JSON RPC error code associated with the failure
- Message string `json:"message"` // Specific error message of the failure
-}
-
-// request forwards an API request to the RPC server, and parses the response.
-//
-// This is currently painfully non-concurrent, but it will have to do until we
-// find the time for niceties like this :P
-func (b *rpcBackend) request(method string, params []interface{}) (json.RawMessage, error) {
- b.lock.Lock()
- defer b.lock.Unlock()
-
- // Ugly hack to serialize an empty list properly
- if params == nil {
- params = []interface{}{}
- }
- // Assemble the request object
- req := &request{
- JSONRPC: "2.0",
- ID: int(atomic.AddUint32(&b.autoid, 1)),
- Method: method,
- Params: params,
- }
- if err := b.client.Send(req); err != nil {
- return nil, err
- }
- res := new(response)
- if err := b.client.Recv(res); err != nil {
- return nil, err
- }
- if res.Error != nil {
- if res.Error.Message == bind.ErrNoCode.Error() {
- return nil, bind.ErrNoCode
- }
- return nil, fmt.Errorf("remote error: %s", res.Error.Message)
- }
- return res.Result, nil
+func NewRPCBackend(client *rpc.Client) bind.ContractBackend {
+ return &rpcBackend{client: client}
}
// HasCode implements ContractVerifier.HasCode by retrieving any code associated
// with the contract from the remote node, and checking its size.
-func (b *rpcBackend) HasCode(contract common.Address, pending bool) (bool, error) {
- // Execute the RPC code retrieval
+func (b *rpcBackend) HasCode(ctx context.Context, contract common.Address, pending bool) (bool, error) {
block := "latest"
if pending {
block = "pending"
}
- res, err := b.request("eth_getCode", []interface{}{contract.Hex(), block})
- if err != nil {
- return false, err
- }
var hex string
- if err := json.Unmarshal(res, &hex); err != nil {
+ err := b.client.CallContext(ctx, &hex, "eth_getCode", contract, block)
+ if err != nil {
return false, err
}
- // Convert the response back to a Go byte slice and return
return len(common.FromHex(hex)) > 0, nil
}
// ContractCall implements ContractCaller.ContractCall, delegating the execution of
// a contract call to the remote node, returning the reply to for local processing.
-func (b *rpcBackend) ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error) {
- // Pack up the request into an RPC argument
+func (b *rpcBackend) ContractCall(ctx context.Context, contract common.Address, data []byte, pending bool) ([]byte, error) {
args := struct {
To common.Address `json:"to"`
Data string `json:"data"`
@@ -142,63 +68,43 @@ func (b *rpcBackend) ContractCall(contract common.Address, data []byte, pending
To: contract,
Data: common.ToHex(data),
}
- // Execute the RPC call and retrieve the response
block := "latest"
if pending {
block = "pending"
}
- res, err := b.request("eth_call", []interface{}{args, block})
- if err != nil {
- return nil, err
- }
var hex string
- if err := json.Unmarshal(res, &hex); err != nil {
+ err := b.client.CallContext(ctx, &hex, "eth_call", args, block)
+ if err != nil {
return nil, err
}
- // Convert the response back to a Go byte slice and return
return common.FromHex(hex), nil
+
}
// PendingAccountNonce implements ContractTransactor.PendingAccountNonce, delegating
// the current account nonce retrieval to the remote node.
-func (b *rpcBackend) PendingAccountNonce(account common.Address) (uint64, error) {
- res, err := b.request("eth_getTransactionCount", []interface{}{account.Hex(), "pending"})
+func (b *rpcBackend) PendingAccountNonce(ctx context.Context, account common.Address) (uint64, error) {
+ var hex rpc.HexNumber
+ err := b.client.CallContext(ctx, &hex, "eth_getTransactionCount", account.Hex(), "pending")
if err != nil {
return 0, err
}
- var hex string
- if err := json.Unmarshal(res, &hex); err != nil {
- return 0, err
- }
- nonce, ok := new(big.Int).SetString(hex, 0)
- if !ok {
- return 0, fmt.Errorf("invalid nonce hex: %s", hex)
- }
- return nonce.Uint64(), nil
+ return hex.Uint64(), nil
}
// SuggestGasPrice implements ContractTransactor.SuggestGasPrice, delegating the
// gas price oracle request to the remote node.
-func (b *rpcBackend) SuggestGasPrice() (*big.Int, error) {
- res, err := b.request("eth_gasPrice", nil)
- if err != nil {
- return nil, err
- }
- var hex string
- if err := json.Unmarshal(res, &hex); err != nil {
+func (b *rpcBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
+ var hex rpc.HexNumber
+ if err := b.client.CallContext(ctx, &hex, "eth_gasPrice"); err != nil {
return nil, err
}
- price, ok := new(big.Int).SetString(hex, 0)
- if !ok {
- return nil, fmt.Errorf("invalid price hex: %s", hex)
- }
- return price, nil
+ return (*big.Int)(&hex), nil
}
// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, delegating
// the gas estimation to the remote node.
-func (b *rpcBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
- // Pack up the request into an RPC argument
+func (b *rpcBackend) EstimateGasLimit(ctx context.Context, sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
args := struct {
From common.Address `json:"from"`
To *common.Address `json:"to"`
@@ -211,35 +117,20 @@ func (b *rpcBackend) EstimateGasLimit(sender common.Address, contract *common.Ad
Value: rpc.NewHexNumber(value),
}
// Execute the RPC call and retrieve the response
- res, err := b.request("eth_estimateGas", []interface{}{args})
+ var hex rpc.HexNumber
+ err := b.client.CallContext(ctx, &hex, "eth_estimateGas", args)
if err != nil {
return nil, err
}
- var hex string
- if err := json.Unmarshal(res, &hex); err != nil {
- return nil, err
- }
- estimate, ok := new(big.Int).SetString(hex, 0)
- if !ok {
- return nil, fmt.Errorf("invalid estimate hex: %s", hex)
- }
- return estimate, nil
+ return (*big.Int)(&hex), nil
}
// SendTransaction implements ContractTransactor.SendTransaction, delegating the
// raw transaction injection to the remote node.
-func (b *rpcBackend) SendTransaction(tx *types.Transaction) error {
+func (b *rpcBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
data, err := rlp.EncodeToBytes(tx)
if err != nil {
return err
}
- res, err := b.request("eth_sendRawTransaction", []interface{}{common.ToHex(data)})
- if err != nil {
- return err
- }
- var hex string
- if err := json.Unmarshal(res, &hex); err != nil {
- return err
- }
- return nil
+ return b.client.CallContext(ctx, nil, "eth_sendRawTransaction", common.ToHex(data))
}
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 54b1ce603..687a31bf1 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
+ "golang.org/x/net/context"
)
// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
@@ -72,7 +73,7 @@ func (b *SimulatedBackend) Commit() {
// Rollback aborts all pending transactions, reverting to the last committed state.
func (b *SimulatedBackend) Rollback() {
- blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
+ blocks, _ := core.GenerateChain(nil, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)
@@ -80,7 +81,7 @@ func (b *SimulatedBackend) Rollback() {
// HasCode implements ContractVerifier.HasCode, checking whether there is any
// code associated with a certain account in the blockchain.
-func (b *SimulatedBackend) HasCode(contract common.Address, pending bool) (bool, error) {
+func (b *SimulatedBackend) HasCode(ctx context.Context, contract common.Address, pending bool) (bool, error) {
if pending {
return len(b.pendingState.GetCode(contract)) > 0, nil
}
@@ -90,7 +91,7 @@ func (b *SimulatedBackend) HasCode(contract common.Address, pending bool) (bool,
// ContractCall implements ContractCaller.ContractCall, executing the specified
// contract with the given input data.
-func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error) {
+func (b *SimulatedBackend) ContractCall(ctx context.Context, contract common.Address, data []byte, pending bool) ([]byte, error) {
// Create a copy of the current state db to screw around with
var (
block *types.Block
@@ -129,20 +130,20 @@ func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pe
// PendingAccountNonce implements ContractTransactor.PendingAccountNonce, retrieving
// the nonce currently pending for the account.
-func (b *SimulatedBackend) PendingAccountNonce(account common.Address) (uint64, error) {
+func (b *SimulatedBackend) PendingAccountNonce(ctx context.Context, account common.Address) (uint64, error) {
return b.pendingState.GetOrNewStateObject(account).Nonce(), nil
}
// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
// chain doens't have miners, we just return a gas price of 1 for any call.
-func (b *SimulatedBackend) SuggestGasPrice() (*big.Int, error) {
+func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
return big.NewInt(1), nil
}
// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, executing the
// requested code against the currently pending block/state and returning the used
// gas.
-func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
+func (b *SimulatedBackend) EstimateGasLimit(ctx context.Context, sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
// Create a copy of the currently pending state db to screw around with
var (
block = b.pendingBlock
@@ -177,8 +178,8 @@ func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *com
// SendTransaction implements ContractTransactor.SendTransaction, delegating the raw
// transaction injection to the remote node.
-func (b *SimulatedBackend) SendTransaction(tx *types.Transaction) error {
- blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
+func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
+ blocks, _ := core.GenerateChain(nil, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
for _, tx := range b.pendingBlock.Transactions() {
block.AddTx(tx)
}
@@ -202,7 +203,8 @@ type callmsg struct {
func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
func (m callmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
-func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
+func (m callmsg) Nonce() uint64 { return 0 }
+func (m callmsg) CheckNonce() bool { return false }
func (m callmsg) To() *common.Address { return m.to }
func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
func (m callmsg) Gas() *big.Int { return m.gasLimit }
diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go
index 75e8d5bc8..80948d3f1 100644
--- a/accounts/abi/bind/base.go
+++ b/accounts/abi/bind/base.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "golang.org/x/net/context"
)
// SignerFn is a signer function callback when a contract requires a method to
@@ -35,6 +36,8 @@ type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, erro
// CallOpts is the collection of options to fine tune a contract call request.
type CallOpts struct {
Pending bool // Whether to operate on the pending state or the last known one
+
+ Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
// TransactOpts is the collection of authorization data required to create a
@@ -47,6 +50,8 @@ type TransactOpts struct {
Value *big.Int // Funds to transfer along along the transaction (nil = 0 = no funds)
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
GasLimit *big.Int // Gas limit to set for the transaction execution (nil = estimate + 10%)
+
+ Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
// BoundContract is the base wrapper object that reflects a contract on the
@@ -102,7 +107,7 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
}
// Make sure we have a contract to operate on, and bail out otherwise
if (opts.Pending && atomic.LoadUint32(&c.pendingHasCode) == 0) || (!opts.Pending && atomic.LoadUint32(&c.latestHasCode) == 0) {
- if code, err := c.caller.HasCode(c.address, opts.Pending); err != nil {
+ if code, err := c.caller.HasCode(opts.Context, c.address, opts.Pending); err != nil {
return err
} else if !code {
return ErrNoCode
@@ -118,7 +123,7 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
if err != nil {
return err
}
- output, err := c.caller.ContractCall(c.address, input, opts.Pending)
+ output, err := c.caller.ContractCall(opts.Context, c.address, input, opts.Pending)
if err != nil {
return err
}
@@ -153,7 +158,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
nonce := uint64(0)
if opts.Nonce == nil {
- nonce, err = c.transactor.PendingAccountNonce(opts.From)
+ nonce, err = c.transactor.PendingAccountNonce(opts.Context, opts.From)
if err != nil {
return nil, fmt.Errorf("failed to retrieve account nonce: %v", err)
}
@@ -163,7 +168,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
// Figure out the gas allowance and gas price values
gasPrice := opts.GasPrice
if gasPrice == nil {
- gasPrice, err = c.transactor.SuggestGasPrice()
+ gasPrice, err = c.transactor.SuggestGasPrice(opts.Context)
if err != nil {
return nil, fmt.Errorf("failed to suggest gas price: %v", err)
}
@@ -172,7 +177,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if gasLimit == nil {
// Gas estimation cannot succeed without code for method invocations
if contract != nil && atomic.LoadUint32(&c.pendingHasCode) == 0 {
- if code, err := c.transactor.HasCode(c.address, true); err != nil {
+ if code, err := c.transactor.HasCode(opts.Context, c.address, true); err != nil {
return nil, err
} else if !code {
return nil, ErrNoCode
@@ -180,7 +185,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
atomic.StoreUint32(&c.pendingHasCode, 1)
}
// If the contract surely has code (or code is not needed), estimate the transaction
- gasLimit, err = c.transactor.EstimateGasLimit(opts.From, contract, value, input)
+ gasLimit, err = c.transactor.EstimateGasLimit(opts.Context, opts.From, contract, value, input)
if err != nil {
return nil, fmt.Errorf("failed to exstimate gas needed: %v", err)
}
@@ -199,7 +204,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if err != nil {
return nil, err
}
- if err := c.transactor.SendTransaction(signedTx); err != nil {
+ if err := c.transactor.SendTransaction(opts.Context, signedTx); err != nil {
return nil, err
}
return signedTx, nil
diff --git a/accounts/account_manager.go b/accounts/account_manager.go
index bfb7556d6..982a2ca6e 100644
--- a/accounts/account_manager.go
+++ b/accounts/account_manager.go
@@ -34,6 +34,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/rpc"
)
var (
@@ -340,3 +342,23 @@ func zeroKey(k *ecdsa.PrivateKey) {
b[i] = 0
}
}
+
+// APIs implements node.Service
+func (am *Manager) APIs() []rpc.API {
+ return nil
+}
+
+// Protocols implements node.Service
+func (am *Manager) Protocols() []p2p.Protocol {
+ return nil
+}
+
+// Start implements node.Service
+func (am *Manager) Start(srvr *p2p.Server) error {
+ return nil
+}
+
+// Stop implements node.Service
+func (am *Manager) Stop() error {
+ return nil
+}
diff --git a/appveyor.yml b/appveyor.yml
index 89d3dfe3d..0b1c919d8 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -6,26 +6,28 @@ clone_depth: 5
version: "{branch}.{build}"
environment:
global:
+ # Go stuff
GOPATH: c:\gopath
-
-# cache choco package files so we don't hit sourceforge all
-# the time.
-cache:
- - c:\cache
+ GO: c:\go\bin\go
+ GOROOT: c:\go
+ CC: C:\msys64\mingw64\bin\gcc.exe
+ # MSYS2 stuff
+ MSYS2_ARCH: x86_64
+ MSYSTEM: MINGW64
+ PATH: C:\msys64\mingw64\bin\;%PATH%
install:
- - cmd: choco install --cache c:\cache golang mingw | find /v "Extracting "
- - refreshenv
- - cd c:\gopath\src\github.com\ethereum\go-ethereum
+ - "%GO% version"
+ - "%CC% --version"
build_script:
- - go run build\ci.go install
+ - "%GO% run build\\ci.go install"
test_script:
- - go run build\ci.go test -vet -coverage
+ - "%GO% run build\\ci.go test -vet -coverage"
after_build:
- - go run build\ci.go archive -type zip
+ - "%GO% run build\\ci.go archive -type zip"
artifacts:
- path: geth-*.zip
diff --git a/circle.yml b/circle.yml
new file mode 100644
index 000000000..39ff5d83c
--- /dev/null
+++ b/circle.yml
@@ -0,0 +1,32 @@
+machine:
+ services:
+ - docker
+
+dependencies:
+ cache_directories:
+ - "~/.ethash" # Cache the ethash DAG generated by hive for consecutive builds
+ - "~/.docker" # Cache all docker images manually to avoid lengthy rebuilds
+ override:
+ # Restore all previously cached docker images
+ - mkdir -p ~/.docker
+ - for img in `ls ~/.docker`; do docker load -i ~/.docker/$img; done
+
+ # Pull in and hive, restore cached ethash DAGs and do a dry run
+ - go get -u github.com/karalabe/hive
+ - (cd ~/.go_workspace/src/github.com/karalabe/hive && mkdir -p workspace/ethash/ ~/.ethash)
+ - (cd ~/.go_workspace/src/github.com/karalabe/hive && cp -r ~/.ethash/. workspace/ethash/)
+ - (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=NONE --test=. --sim=. --loglevel=6)
+
+ # Cache all the docker images and the ethash DAGs
+ - for img in `docker images | grep -v "^<none>" | tail -n +2 | awk '{print $1}'`; do docker save $img > ~/.docker/`echo $img | tr '/' ':'`.tar; done
+ - cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/ethash/. ~/.ethash
+
+test:
+ override:
+ # Build Geth and move into a known folder
+ - make geth
+ - cp ./build/bin/geth $HOME/geth
+
+ # Run hive and move all generated logs into the public artifacts folder
+ - (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=go-ethereum:local --override=$HOME/geth --test=. --sim=.)
+ - cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/logs/* $CIRCLE_ARTIFACTS
diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go
index 7d3f9fdb3..40d3cdc17 100644
--- a/cmd/bootnode/main.go
+++ b/cmd/bootnode/main.go
@@ -20,6 +20,7 @@ package main
import (
"crypto/ecdsa"
"flag"
+ "fmt"
"os"
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -32,7 +33,8 @@ import (
func main() {
var (
listenAddr = flag.String("addr", ":30301", "listen address")
- genKey = flag.String("genkey", "", "generate a node key and quit")
+ genKey = flag.String("genkey", "", "generate a node key")
+ writeAddr = flag.Bool("writeaddress", false, "write out the node's pubkey hash and quit")
nodeKeyFile = flag.String("nodekey", "", "private key filename")
nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)")
natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
@@ -45,22 +47,19 @@ func main() {
glog.SetToStderr(true)
flag.Parse()
- if *genKey != "" {
- key, err := crypto.GenerateKey()
- if err != nil {
- utils.Fatalf("could not generate key: %v", err)
- }
- if err := crypto.SaveECDSA(*genKey, key); err != nil {
- utils.Fatalf("%v", err)
- }
- os.Exit(0)
- }
-
natm, err := nat.Parse(*natdesc)
if err != nil {
utils.Fatalf("-nat: %v", err)
}
switch {
+ case *genKey != "":
+ nodeKey, err = crypto.GenerateKey()
+ if err != nil {
+ utils.Fatalf("could not generate key: %v", err)
+ }
+ if err = crypto.SaveECDSA(*genKey, nodeKey); err != nil {
+ utils.Fatalf("%v", err)
+ }
case *nodeKeyFile == "" && *nodeKeyHex == "":
utils.Fatalf("Use -nodekey or -nodekeyhex to specify a private key")
case *nodeKeyFile != "" && *nodeKeyHex != "":
@@ -75,6 +74,11 @@ func main() {
}
}
+ if *writeAddr {
+ fmt.Printf("%v\n", discover.PubkeyID(&nodeKey.PublicKey))
+ os.Exit(0)
+ }
+
if _, err := discover.ListenUDP(nodeKey, *listenAddr, natm, ""); err != nil {
utils.Fatalf("%v", err)
}
diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go
index e0ad0a7ea..71465fb55 100644
--- a/cmd/ethtest/main.go
+++ b/cmd/ethtest/main.go
@@ -74,9 +74,9 @@ func runTestWithReader(test string, r io.Reader) error {
var err error
switch strings.ToLower(test) {
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
- err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, r, skipTests)
+ err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, r, skipTests)
case "st", "state", "statetest", "statetests":
- rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock}
+ rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true}
err = tests.RunStateTestWithReader(rs, r, skipTests)
case "tx", "transactiontest", "transactiontests":
err = tests.RunTransactionTestsWithReader(r, skipTests)
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index ba7d8d8a8..aa48f6ede 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -220,7 +220,6 @@ type ruleSet struct{}
func (ruleSet) IsHomestead(*big.Int) bool { return true }
-func (self *VMEnv) MarkCodeHash(common.Hash) {}
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Db() vm.Database { return self.state }
diff --git a/cmd/geth/accountcmd.go b/cmd/geth/accountcmd.go
index 1415240eb..7fea16a25 100644
--- a/cmd/geth/accountcmd.go
+++ b/cmd/geth/accountcmd.go
@@ -316,7 +316,7 @@ func accountImport(ctx *cli.Context) error {
}
key, err := crypto.LoadECDSA(keyfile)
if err != nil {
- utils.Fatalf("keyfile must be given as argument")
+ utils.Fatalf("Failed to load the private key: %v", err)
}
accman := utils.MakeAccountManager(ctx)
passphrase := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))
diff --git a/cmd/geth/consolecmd.go b/cmd/geth/consolecmd.go
index 257050a62..8d53809ce 100644
--- a/cmd/geth/consolecmd.go
+++ b/cmd/geth/consolecmd.go
@@ -19,9 +19,12 @@ package main
import (
"os"
"os/signal"
+ "strings"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/console"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/rpc"
"gopkg.in/urfave/cli.v1"
)
@@ -99,7 +102,7 @@ func localConsole(ctx *cli.Context) error {
// console to it.
func remoteConsole(ctx *cli.Context) error {
// Attach to a remotely running geth instance and start the JavaScript console
- client, err := utils.NewRemoteRPCClient(ctx)
+ client, err := dialRPC(ctx.Args().First())
if err != nil {
utils.Fatalf("Unable to attach to remote geth: %v", err)
}
@@ -127,6 +130,20 @@ func remoteConsole(ctx *cli.Context) error {
return nil
}
+// dialRPC returns a RPC client which connects to the given endpoint.
+// The check for empty endpoint implements the defaulting logic
+// for "geth attach" and "geth monitor" with no argument.
+func dialRPC(endpoint string) (*rpc.Client, error) {
+ if endpoint == "" {
+ endpoint = node.DefaultIPCEndpoint()
+ } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
+ // Backwards compatibility with geth < 1.5 which required
+ // these prefixes.
+ endpoint = endpoint[4:]
+ }
+ return rpc.Dial(endpoint)
+}
+
// ephemeralConsole starts a new geth node, attaches an ephemeral JavaScript
// console to it, and each of the files specified as arguments and tears the
// everything down.
diff --git a/cmd/geth/dao_test.go b/cmd/geth/dao_test.go
new file mode 100644
index 000000000..7058fb385
--- /dev/null
+++ b/cmd/geth/dao_test.go
@@ -0,0 +1,232 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+package main
+
+import (
+ "io/ioutil"
+ "math/big"
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// Genesis block for nodes which don't care about the DAO fork (i.e. not configured)
+var daoOldGenesis = `{
+ "alloc" : {},
+ "coinbase" : "0x0000000000000000000000000000000000000000",
+ "difficulty" : "0x20000",
+ "extraData" : "",
+ "gasLimit" : "0x2fefd8",
+ "nonce" : "0x0000000000000042",
+ "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp" : "0x00",
+ "config" : {}
+}`
+
+// Genesis block for nodes which actively oppose the DAO fork
+var daoNoForkGenesis = `{
+ "alloc" : {},
+ "coinbase" : "0x0000000000000000000000000000000000000000",
+ "difficulty" : "0x20000",
+ "extraData" : "",
+ "gasLimit" : "0x2fefd8",
+ "nonce" : "0x0000000000000042",
+ "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp" : "0x00",
+ "config" : {
+ "daoForkBlock" : 314,
+ "daoForkSupport" : false
+ }
+}`
+
+// Genesis block for nodes which actively support the DAO fork
+var daoProForkGenesis = `{
+ "alloc" : {},
+ "coinbase" : "0x0000000000000000000000000000000000000000",
+ "difficulty" : "0x20000",
+ "extraData" : "",
+ "gasLimit" : "0x2fefd8",
+ "nonce" : "0x0000000000000042",
+ "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp" : "0x00",
+ "config" : {
+ "daoForkBlock" : 314,
+ "daoForkSupport" : true
+ }
+}`
+
+var daoGenesisHash = common.HexToHash("5e1fc79cb4ffa4739177b5408045cd5d51c6cf766133f23f7cd72ee1f8d790e0")
+var daoGenesisForkBlock = big.NewInt(314)
+
+// Tests that the DAO hard-fork number and the nodes support/opposition is correctly
+// set in the database after various initialization procedures and invocations.
+func TestDAODefaultMainnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, "", [][2]bool{{false, false}}, params.MainNetDAOForkBlock, true)
+}
+func TestDAOSupportMainnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, "", [][2]bool{{true, false}}, params.MainNetDAOForkBlock, true)
+}
+func TestDAOOpposeMainnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, "", [][2]bool{{false, true}}, params.MainNetDAOForkBlock, false)
+}
+func TestDAOSwitchToSupportMainnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, "", [][2]bool{{false, true}, {true, false}}, params.MainNetDAOForkBlock, true)
+}
+func TestDAOSwitchToOpposeMainnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, "", [][2]bool{{true, false}, {false, true}}, params.MainNetDAOForkBlock, false)
+}
+func TestDAODefaultTestnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, true, "", [][2]bool{{false, false}}, params.TestNetDAOForkBlock, true)
+}
+func TestDAOSupportTestnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, true, "", [][2]bool{{true, false}}, params.TestNetDAOForkBlock, true)
+}
+func TestDAOOpposeTestnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, true, "", [][2]bool{{false, true}}, params.TestNetDAOForkBlock, false)
+}
+func TestDAOSwitchToSupportTestnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, true, "", [][2]bool{{false, true}, {true, false}}, params.TestNetDAOForkBlock, true)
+}
+func TestDAOSwitchToOpposeTestnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, true, "", [][2]bool{{true, false}, {false, true}}, params.TestNetDAOForkBlock, false)
+}
+func TestDAOInitOldPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{}, nil, false)
+}
+func TestDAODefaultOldPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{false, false}}, params.MainNetDAOForkBlock, true)
+}
+func TestDAOSupportOldPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{true, false}}, params.MainNetDAOForkBlock, true)
+}
+func TestDAOOpposeOldPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{false, true}}, params.MainNetDAOForkBlock, false)
+}
+func TestDAOSwitchToSupportOldPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{false, true}, {true, false}}, params.MainNetDAOForkBlock, true)
+}
+func TestDAOSwitchToOpposeOldPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{true, false}, {false, true}}, params.MainNetDAOForkBlock, false)
+}
+func TestDAOInitNoForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoNoForkGenesis, [][2]bool{}, daoGenesisForkBlock, false)
+}
+func TestDAODefaultNoForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoNoForkGenesis, [][2]bool{{false, false}}, daoGenesisForkBlock, false)
+}
+func TestDAOSupportNoForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoNoForkGenesis, [][2]bool{{true, false}}, daoGenesisForkBlock, true)
+}
+func TestDAOOpposeNoForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoNoForkGenesis, [][2]bool{{false, true}}, daoGenesisForkBlock, false)
+}
+func TestDAOSwitchToSupportNoForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoNoForkGenesis, [][2]bool{{false, true}, {true, false}}, daoGenesisForkBlock, true)
+}
+func TestDAOSwitchToOpposeNoForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoNoForkGenesis, [][2]bool{{true, false}, {false, true}}, daoGenesisForkBlock, false)
+}
+func TestDAOInitProForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoProForkGenesis, [][2]bool{}, daoGenesisForkBlock, true)
+}
+func TestDAODefaultProForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoProForkGenesis, [][2]bool{{false, false}}, daoGenesisForkBlock, true)
+}
+func TestDAOSupportProForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoProForkGenesis, [][2]bool{{true, false}}, daoGenesisForkBlock, true)
+}
+func TestDAOOpposeProForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoProForkGenesis, [][2]bool{{false, true}}, daoGenesisForkBlock, false)
+}
+func TestDAOSwitchToSupportProForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoProForkGenesis, [][2]bool{{false, true}, {true, false}}, daoGenesisForkBlock, true)
+}
+func TestDAOSwitchToOpposeProForkPrivnet(t *testing.T) {
+ testDAOForkBlockNewChain(t, false, daoProForkGenesis, [][2]bool{{true, false}, {false, true}}, daoGenesisForkBlock, false)
+}
+
+func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes [][2]bool, expectBlock *big.Int, expectVote bool) {
+ // Create a temporary data directory to use and inspect later
+ datadir := tmpdir(t)
+ defer os.RemoveAll(datadir)
+
+ // Start a Geth instance with the requested flags set and immediately terminate
+ if genesis != "" {
+ json := filepath.Join(datadir, "genesis.json")
+ if err := ioutil.WriteFile(json, []byte(genesis), 0600); err != nil {
+ t.Fatalf("failed to write genesis file: %v", err)
+ }
+ runGeth(t, "--datadir", datadir, "init", json).cmd.Wait()
+ }
+ for _, vote := range votes {
+ args := []string{"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir}
+ if testnet {
+ args = append(args, "--testnet")
+ }
+ if vote[0] {
+ args = append(args, "--support-dao-fork")
+ }
+ if vote[1] {
+ args = append(args, "--oppose-dao-fork")
+ }
+ geth := runGeth(t, append(args, []string{"--exec", "2+2", "console"}...)...)
+ geth.cmd.Wait()
+ }
+ // Retrieve the DAO config flag from the database
+ path := filepath.Join(datadir, "chaindata")
+ if testnet && genesis == "" {
+ path = filepath.Join(datadir, "testnet", "chaindata")
+ }
+ db, err := ethdb.NewLDBDatabase(path, 0, 0)
+ if err != nil {
+ t.Fatalf("failed to open test database: %v", err)
+ }
+ defer db.Close()
+
+ genesisHash := common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
+ if testnet {
+ genesisHash = common.HexToHash("0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303")
+ }
+ if genesis != "" {
+ genesisHash = daoGenesisHash
+ }
+ config, err := core.GetChainConfig(db, genesisHash)
+ if err != nil {
+ t.Fatalf("failed to retrieve chain config: %v", err)
+ }
+ // Validate the DAO hard-fork block number against the expected value
+ if config.DAOForkBlock == nil {
+ if expectBlock != nil {
+ t.Errorf("dao hard-fork block mismatch: have nil, want %v", expectBlock)
+ }
+ } else if expectBlock == nil {
+ t.Errorf("dao hard-fork block mismatch: have %v, want nil", config.DAOForkBlock)
+ } else if config.DAOForkBlock.Cmp(expectBlock) != 0 {
+ t.Errorf("dao hard-fork block mismatch: have %v, want %v", config.DAOForkBlock, expectBlock)
+ }
+ if config.DAOForkSupport != expectVote {
+ t.Errorf("dao hard-fork support mismatch: have %v, want %v", config.DAOForkSupport, expectVote)
+ }
+}
diff --git a/cmd/geth/genesis_test.go b/cmd/geth/genesis_test.go
new file mode 100644
index 000000000..4f8b1642e
--- /dev/null
+++ b/cmd/geth/genesis_test.go
@@ -0,0 +1,107 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+package main
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+var customGenesisTests = []struct {
+ genesis string
+ query string
+ result string
+}{
+ // Plain genesis file without anything extra
+ {
+ genesis: `{
+ "alloc" : {},
+ "coinbase" : "0x0000000000000000000000000000000000000000",
+ "difficulty" : "0x20000",
+ "extraData" : "",
+ "gasLimit" : "0x2fefd8",
+ "nonce" : "0x0000000000000042",
+ "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp" : "0x00"
+ }`,
+ query: "eth.getBlock(0).nonce",
+ result: "0x0000000000000042",
+ },
+ // Genesis file with an empty chain configuration (ensure missing fields work)
+ {
+ genesis: `{
+ "alloc" : {},
+ "coinbase" : "0x0000000000000000000000000000000000000000",
+ "difficulty" : "0x20000",
+ "extraData" : "",
+ "gasLimit" : "0x2fefd8",
+ "nonce" : "0x0000000000000042",
+ "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp" : "0x00",
+ "config" : {}
+ }`,
+ query: "eth.getBlock(0).nonce",
+ result: "0x0000000000000042",
+ },
+ // Genesis file with specific chain configurations
+ {
+ genesis: `{
+ "alloc" : {},
+ "coinbase" : "0x0000000000000000000000000000000000000000",
+ "difficulty" : "0x20000",
+ "extraData" : "",
+ "gasLimit" : "0x2fefd8",
+ "nonce" : "0x0000000000000042",
+ "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp" : "0x00",
+ "config" : {
+ "homesteadBlock" : 314,
+ "daoForkBlock" : 141,
+ "daoForkSupport" : true
+ },
+ }`,
+ query: "eth.getBlock(0).nonce",
+ result: "0x0000000000000042",
+ },
+}
+
+// Tests that initializing Geth with a custom genesis block and chain definitions
+// work properly.
+func TestCustomGenesis(t *testing.T) {
+ for i, tt := range customGenesisTests {
+ // Create a temporary data directory to use and inspect later
+ datadir := tmpdir(t)
+ defer os.RemoveAll(datadir)
+
+ // Initialize the data directory with the custom genesis block
+ json := filepath.Join(datadir, "genesis.json")
+ if err := ioutil.WriteFile(json, []byte(tt.genesis), 0600); err != nil {
+ t.Fatalf("test %d: failed to write genesis file: %v", i, err)
+ }
+ runGeth(t, "--datadir", datadir, "init", json).cmd.Wait()
+
+ // Query the custom genesis block
+ geth := runGeth(t, "--datadir", datadir, "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--exec", tt.query, "console")
+ geth.expectRegexp(tt.result)
+ geth.expectExit()
+ }
+}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 95aad3bea..5f1157b90 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -29,6 +29,7 @@ import (
"time"
"github.com/ethereum/ethash"
+ "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console"
@@ -149,7 +150,6 @@ participating.
utils.IdentityFlag,
utils.UnlockedAccountFlag,
utils.PasswordFileFlag,
- utils.GenesisFileFlag,
utils.BootnodesFlag,
utils.DataDirFlag,
utils.KeyStoreDirFlag,
@@ -164,12 +164,13 @@ participating.
utils.MaxPendingPeersFlag,
utils.EtherbaseFlag,
utils.GasPriceFlag,
+ utils.SupportDAOFork,
+ utils.OpposeDAOFork,
utils.MinerThreadsFlag,
utils.MiningEnabledFlag,
utils.MiningGPUFlag,
utils.AutoDAGFlag,
utils.TargetGasLimitFlag,
- utils.DAOSoftForkFlag,
utils.NATFlag,
utils.NatspecEnabledFlag,
utils.NoDiscoverFlag,
@@ -225,12 +226,6 @@ participating.
eth.EnableBadBlockReporting = true
utils.SetupNetwork(ctx)
-
- // Deprecation warning.
- if ctx.GlobalIsSet(utils.GenesisFileFlag.Name) {
- common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'")
- }
-
return nil
}
@@ -310,15 +305,16 @@ func initGenesis(ctx *cli.Context) error {
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode(ctx *cli.Context, stack *node.Node) {
+ // Report geth version
+ glog.V(logger.Info).Infof("instance: Geth/%s/%s/%s\n", verString, runtime.Version(), runtime.GOOS)
// Start up the node itself
utils.StartNode(stack)
// Unlock any account specifically requested
- var ethereum *eth.Ethereum
- if err := stack.Service(&ethereum); err != nil {
+ var accman *accounts.Manager
+ if err := stack.Service(&accman); err != nil {
utils.Fatalf("ethereum service not running: %v", err)
}
- accman := ethereum.AccountManager()
passwords := utils.MakePasswordList(ctx)
accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
@@ -329,6 +325,10 @@ func startNode(ctx *cli.Context, stack *node.Node) {
}
// Start auxiliary services if enabled
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
+ var ethereum *eth.Ethereum
+ if err := stack.Service(&ethereum); err != nil {
+ utils.Fatalf("ethereum service not running: %v", err)
+ }
if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
utils.Fatalf("Failed to start mining: %v", err)
}
diff --git a/cmd/geth/monitorcmd.go b/cmd/geth/monitorcmd.go
index 11fdca89c..d1490dce2 100644
--- a/cmd/geth/monitorcmd.go
+++ b/cmd/geth/monitorcmd.go
@@ -21,11 +21,10 @@ import (
"math"
"reflect"
"runtime"
+ "sort"
"strings"
"time"
- "sort"
-
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
@@ -36,7 +35,7 @@ import (
var (
monitorCommandAttachFlag = cli.StringFlag{
Name: "attach",
- Value: "ipc:" + node.DefaultIPCEndpoint(),
+ Value: node.DefaultIPCEndpoint(),
Usage: "API endpoint to attach to",
}
monitorCommandRowsFlag = cli.IntFlag{
@@ -69,12 +68,12 @@ to display multiple metrics simultaneously.
// monitor starts a terminal UI based monitoring tool for the requested metrics.
func monitor(ctx *cli.Context) error {
var (
- client rpc.Client
+ client *rpc.Client
err error
)
// Attach to an Ethereum node over IPC or RPC
endpoint := ctx.String(monitorCommandAttachFlag.Name)
- if client, err = utils.NewRemoteRPCClientFromString(endpoint); err != nil {
+ if client, err = dialRPC(endpoint); err != nil {
utils.Fatalf("Unable to attach to geth node: %v", err)
}
defer client.Close()
@@ -159,30 +158,10 @@ func monitor(ctx *cli.Context) error {
// retrieveMetrics contacts the attached geth node and retrieves the entire set
// of collected system metrics.
-func retrieveMetrics(client rpc.Client) (map[string]interface{}, error) {
- req := map[string]interface{}{
- "id": new(int64),
- "method": "debug_metrics",
- "jsonrpc": "2.0",
- "params": []interface{}{true},
- }
-
- if err := client.Send(req); err != nil {
- return nil, err
- }
-
- var res rpc.JSONSuccessResponse
- if err := client.Recv(&res); err != nil {
- return nil, err
- }
-
- if res.Result != nil {
- if mets, ok := res.Result.(map[string]interface{}); ok {
- return mets, nil
- }
- }
-
- return nil, fmt.Errorf("unable to retrieve metrics")
+func retrieveMetrics(client *rpc.Client) (map[string]interface{}, error) {
+ var metrics map[string]interface{}
+ err := client.Call(&metrics, "debug_metrics", true)
+ return metrics, err
}
// resolveMetrics takes a list of input metric patterns, and resolves each to one
@@ -270,7 +249,7 @@ func fetchMetric(metrics map[string]interface{}, metric string) float64 {
// refreshCharts retrieves a next batch of metrics, and inserts all the new
// values into the active datasets and charts
-func refreshCharts(client rpc.Client, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
+func refreshCharts(client *rpc.Client, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
values, err := retrieveMetrics(client)
for i, metric := range metrics {
if len(data) < 512 {
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index 10bc56b97..eb897d2b5 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -68,7 +68,6 @@ var AppHelpFlagGroups = []flagGroup{
utils.OlympicFlag,
utils.TestNetFlag,
utils.DevModeFlag,
- utils.GenesisFileFlag,
utils.IdentityFlag,
utils.FastSyncFlag,
utils.LightKDFFlag,
@@ -128,7 +127,6 @@ var AppHelpFlagGroups = []flagGroup{
utils.TargetGasLimitFlag,
utils.GasPriceFlag,
utils.ExtraDataFlag,
- utils.DAOSoftForkFlag,
},
},
{
diff --git a/cmd/utils/client.go b/cmd/utils/client.go
deleted file mode 100644
index cc9647580..000000000
--- a/cmd/utils/client.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
-
-package utils
-
-import (
- "fmt"
- "strings"
-
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/rpc"
- "gopkg.in/urfave/cli.v1"
-)
-
-// NewRemoteRPCClient returns a RPC client which connects to a running geth instance.
-// Depending on the given context this can either be a IPC or a HTTP client.
-func NewRemoteRPCClient(ctx *cli.Context) (rpc.Client, error) {
- if ctx.Args().Present() {
- endpoint := ctx.Args().First()
- return NewRemoteRPCClientFromString(endpoint)
- }
- // use IPC by default
- return rpc.NewIPCClient(node.DefaultIPCEndpoint())
-}
-
-// NewRemoteRPCClientFromString returns a RPC client which connects to the given
-// endpoint. It must start with either `ipc:` or `rpc:` (HTTP).
-func NewRemoteRPCClientFromString(endpoint string) (rpc.Client, error) {
- if strings.HasPrefix(endpoint, "ipc:") {
- return rpc.NewIPCClient(endpoint[4:])
- }
- if strings.HasPrefix(endpoint, "rpc:") {
- return rpc.NewHTTPClient(endpoint[4:])
- }
- if strings.HasPrefix(endpoint, "http://") {
- return rpc.NewHTTPClient(endpoint)
- }
- if strings.HasPrefix(endpoint, "ws:") {
- return rpc.NewWSClient(endpoint)
- }
- return nil, fmt.Errorf("invalid endpoint")
-}
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index d8001e348..de379f84f 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -126,10 +126,6 @@ var (
Name: "dev",
Usage: "Developer mode: pre-configured private network with several debugging flags",
}
- GenesisFileFlag = cli.StringFlag{
- Name: "genesis",
- Usage: "Insert/overwrite the genesis block (JSON format)",
- }
IdentityFlag = cli.StringFlag{
Name: "identity",
Usage: "Custom node name",
@@ -161,6 +157,15 @@ var (
Name: "lightkdf",
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
}
+ // Fork settings
+ SupportDAOFork = cli.BoolFlag{
+ Name: "support-dao-fork",
+ Usage: "Updates the chain rules to support the DAO hard-fork",
+ }
+ OpposeDAOFork = cli.BoolFlag{
+ Name: "oppose-dao-fork",
+ Usage: "Updates the chain rules to oppose the DAO hard-fork",
+ }
// Miner settings
// TODO: refactor CPU vs GPU mining flags
MiningEnabledFlag = cli.BoolFlag{
@@ -181,10 +186,6 @@ var (
Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
Value: params.GenesisGasLimit.String(),
}
- DAOSoftForkFlag = cli.BoolFlag{
- Name: "dao-soft-fork",
- Usage: "Vote for the DAO soft-fork, temporarilly decreasing the gas limits",
- }
AutoDAGFlag = cli.BoolFlag{
Name: "autodag",
Usage: "Enable automatic DAG pregeneration",
@@ -538,20 +539,6 @@ func MakeWSRpcHost(ctx *cli.Context) string {
return ctx.GlobalString(WSListenAddrFlag.Name)
}
-// MakeGenesisBlock loads up a genesis block from an input file specified in the
-// command line, or returns the empty string if none set.
-func MakeGenesisBlock(ctx *cli.Context) string {
- genesis := ctx.GlobalString(GenesisFileFlag.Name)
- if genesis == "" {
- return ""
- }
- data, err := ioutil.ReadFile(genesis)
- if err != nil {
- Fatalf("Failed to load custom genesis file: %v", err)
- }
- return string(data)
-}
-
// MakeDatabaseHandles raises out the number of allowed file handles per process
// for Geth and returns half of the allowance to assign to the database.
func MakeDatabaseHandles() int {
@@ -681,9 +668,6 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
// Configure the Ethereum service
accman := MakeAccountManager(ctx)
- // Handle some miner strategies arrising from the DAO fiasco
- core.DAOSoftFork = ctx.GlobalBool(DAOSoftForkFlag.Name)
-
// initialise new random number generator
rand := rand.New(rand.NewSource(time.Now().UnixNano()))
// get enabled jit flag
@@ -696,7 +680,6 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
ethConf := &eth.Config{
ChainConfig: MustMakeChainConfig(ctx),
- Genesis: MakeGenesisBlock(ctx),
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
@@ -729,17 +712,13 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
ethConf.NetworkId = 1
}
- if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
- ethConf.Genesis = core.OlympicGenesisBlock()
- }
+ ethConf.Genesis = core.OlympicGenesisBlock()
case ctx.GlobalBool(TestNetFlag.Name):
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
ethConf.NetworkId = 2
}
- if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
- ethConf.Genesis = core.TestNetGenesisBlock()
- }
+ ethConf.Genesis = core.TestNetGenesisBlock()
state.StartingNonce = 1048576 // (2**20)
case ctx.GlobalBool(DevModeFlag.Name):
@@ -754,9 +733,7 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
stackConf.ListenAddr = ":0"
}
// Override the Ethereum protocol configs
- if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
- ethConf.Genesis = core.OlympicGenesisBlock()
- }
+ ethConf.Genesis = core.OlympicGenesisBlock()
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
ethConf.GasPrice = new(big.Int)
}
@@ -770,6 +747,13 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
if err != nil {
Fatalf("Failed to create the protocol stack: %v", err)
}
+
+ if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
+ return accman, nil
+ }); err != nil {
+ Fatalf("Failed to register the account manager service: %v", err)
+ }
+
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return eth.New(ctx, ethConf)
}); err != nil {
@@ -813,24 +797,62 @@ func MustMakeChainConfig(ctx *cli.Context) *core.ChainConfig {
// MustMakeChainConfigFromDb reads the chain configuration from the given database.
func MustMakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfig {
- genesis := core.GetBlock(db, core.GetCanonicalHash(db, 0), 0)
+ // If the chain is already initialized, use any existing chain configs
+ config := new(core.ChainConfig)
+ genesis := core.GetBlock(db, core.GetCanonicalHash(db, 0), 0)
if genesis != nil {
- // Existing genesis block, use stored config if available.
storedConfig, err := core.GetChainConfig(db, genesis.Hash())
- if err == nil {
- return storedConfig
- } else if err != core.ChainConfigNotFoundErr {
+ switch err {
+ case nil:
+ config = storedConfig
+ case core.ChainConfigNotFoundErr:
+ // No configs found, use empty, will populate below
+ default:
Fatalf("Could not make chain configuration: %v", err)
}
}
- var homesteadBlockNo *big.Int
- if ctx.GlobalBool(TestNetFlag.Name) {
- homesteadBlockNo = params.TestNetHomesteadBlock
- } else {
- homesteadBlockNo = params.MainNetHomesteadBlock
+ // Set any missing fields due to them being unset or system upgrade
+ if config.HomesteadBlock == nil {
+ if ctx.GlobalBool(TestNetFlag.Name) {
+ config.HomesteadBlock = params.TestNetHomesteadBlock
+ } else {
+ config.HomesteadBlock = params.MainNetHomesteadBlock
+ }
}
- return &core.ChainConfig{HomesteadBlock: homesteadBlockNo}
+ if config.DAOForkBlock == nil {
+ if ctx.GlobalBool(TestNetFlag.Name) {
+ config.DAOForkBlock = params.TestNetDAOForkBlock
+ } else {
+ config.DAOForkBlock = params.MainNetDAOForkBlock
+ }
+ config.DAOForkSupport = true
+ }
+ // Force override any existing configs if explicitly requested
+ switch {
+ case ctx.GlobalBool(SupportDAOFork.Name):
+ config.DAOForkSupport = true
+ case ctx.GlobalBool(OpposeDAOFork.Name):
+ config.DAOForkSupport = false
+ }
+ // Temporarilly display a proper message so the user knows which fork its on
+ if !ctx.GlobalBool(TestNetFlag.Name) && (genesis == nil || genesis.Hash() == common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")) {
+ choice := "SUPPORT"
+ if !config.DAOForkSupport {
+ choice = "OPPOSE"
+ }
+ current := fmt.Sprintf("Geth is currently configured to %s the DAO hard-fork!", choice)
+ howtoswap := fmt.Sprintf("You can change your choice prior to block #%v with --support-dao-fork or --oppose-dao-fork.", config.DAOForkBlock)
+ howtosync := fmt.Sprintf("After the hard-fork block #%v passed, changing chains requires a resync from scratch!", config.DAOForkBlock)
+ separator := strings.Repeat("-", len(howtoswap))
+
+ glog.V(logger.Warn).Info(separator)
+ glog.V(logger.Warn).Info(current)
+ glog.V(logger.Warn).Info(howtoswap)
+ glog.V(logger.Warn).Info(howtosync)
+ glog.V(logger.Warn).Info(separator)
+ }
+ return config
}
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
diff --git a/common/registrar/ethreg/api.go b/common/registrar/ethreg/api.go
index 6d77a9385..6dd0ef46f 100644
--- a/common/registrar/ethreg/api.go
+++ b/common/registrar/ethreg/api.go
@@ -128,7 +128,10 @@ func (m callmsg) FromFrontier() (common.Address, error) {
return m.from.Address(), nil
}
func (m callmsg) Nonce() uint64 {
- return m.from.Nonce()
+ return 0
+}
+func (m callmsg) CheckNonce() bool {
+ return false
}
func (m callmsg) To() *common.Address {
return m.to
diff --git a/console/bridge.go b/console/bridge.go
index b23e06837..06cb41d80 100644
--- a/console/bridge.go
+++ b/console/bridge.go
@@ -31,13 +31,13 @@ import (
// bridge is a collection of JavaScript utility methods to bride the .js runtime
// environment and the Go RPC connection backing the remote method calls.
type bridge struct {
- client rpc.Client // RPC client to execute Ethereum requests through
+ client *rpc.Client // RPC client to execute Ethereum requests through
prompter UserPrompter // Input prompter to allow interactive user feedback
printer io.Writer // Output writer to serialize any display strings to
}
// newBridge creates a new JavaScript wrapper around an RPC client.
-func newBridge(client rpc.Client, prompter UserPrompter, printer io.Writer) *bridge {
+func newBridge(client *rpc.Client, prompter UserPrompter, printer io.Writer) *bridge {
return &bridge{
client: client,
prompter: prompter,
@@ -188,88 +188,86 @@ func (b *bridge) SleepBlocks(call otto.FunctionCall) (response otto.Value) {
return otto.FalseValue()
}
-// Send will serialize the first argument, send it to the node and returns the response.
+type jsonrpcCall struct {
+ Id int64
+ Method string
+ Params []interface{}
+}
+
+// Send implements the web3 provider "send" method.
func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) {
- // Ensure that we've got a batch request (array) or a single request (object)
- arg := call.Argument(0).Object()
- if arg == nil || (arg.Class() != "Array" && arg.Class() != "Object") {
- throwJSException("request must be an object or array")
- }
- // Convert the otto VM arguments to Go values
- data, err := call.Otto.Call("JSON.stringify", nil, arg)
+ // Remarshal the request into a Go value.
+ JSON, _ := call.Otto.Object("JSON")
+ reqVal, err := JSON.Call("stringify", call.Argument(0))
if err != nil {
throwJSException(err.Error())
}
- reqjson, err := data.ToString()
- if err != nil {
- throwJSException(err.Error())
- }
-
var (
- reqs []rpc.JSONRequest
- batch = true
+ rawReq = []byte(reqVal.String())
+ reqs []jsonrpcCall
+ batch bool
)
- if err = json.Unmarshal([]byte(reqjson), &reqs); err != nil {
- // single request?
- reqs = make([]rpc.JSONRequest, 1)
- if err = json.Unmarshal([]byte(reqjson), &reqs[0]); err != nil {
- throwJSException("invalid request")
- }
+ if rawReq[0] == '[' {
+ batch = true
+ json.Unmarshal(rawReq, &reqs)
+ } else {
batch = false
+ reqs = make([]jsonrpcCall, 1)
+ json.Unmarshal(rawReq, &reqs[0])
}
- // Iteratively execute the requests
- call.Otto.Set("response_len", len(reqs))
- call.Otto.Run("var ret_response = new Array(response_len);")
- for i, req := range reqs {
- // Execute the RPC request and parse the reply
- if err = b.client.Send(&req); err != nil {
- return newErrorResponse(call, -32603, err.Error(), req.Id)
- }
- result := make(map[string]interface{})
- if err = b.client.Recv(&result); err != nil {
- return newErrorResponse(call, -32603, err.Error(), req.Id)
+ // Execute the requests.
+ resps, _ := call.Otto.Object("new Array()")
+ for _, req := range reqs {
+ resp, _ := call.Otto.Object(`({"jsonrpc":"2.0"})`)
+ resp.Set("id", req.Id)
+ var result json.RawMessage
+ err = b.client.Call(&result, req.Method, req.Params...)
+ switch err := err.(type) {
+ case nil:
+ if result == nil {
+ // Special case null because it is decoded as an empty
+ // raw message for some reason.
+ resp.Set("result", otto.NullValue())
+ } else {
+ resultVal, err := JSON.Call("parse", string(result))
+ if err != nil {
+ resp = newErrorResponse(call, -32603, err.Error(), &req.Id).Object()
+ } else {
+ resp.Set("result", resultVal)
+ }
+ }
+ case rpc.Error:
+ resp.Set("error", map[string]interface{}{
+ "code": err.ErrorCode(),
+ "message": err.Error(),
+ })
+ default:
+ resp = newErrorResponse(call, -32603, err.Error(), &req.Id).Object()
}
- // Feed the reply back into the JavaScript runtime environment
- id, _ := result["id"]
- jsonver, _ := result["jsonrpc"]
-
- call.Otto.Set("ret_id", id)
- call.Otto.Set("ret_jsonrpc", jsonver)
- call.Otto.Set("response_idx", i)
+ resps.Call("push", resp)
+ }
- if res, ok := result["result"]; ok {
- payload, _ := json.Marshal(res)
- call.Otto.Set("ret_result", string(payload))
- response, err = call.Otto.Run(`
- ret_response[response_idx] = { jsonrpc: ret_jsonrpc, id: ret_id, result: JSON.parse(ret_result) };
- `)
- continue
- }
- if res, ok := result["error"]; ok {
- payload, _ := json.Marshal(res)
- call.Otto.Set("ret_result", string(payload))
- response, err = call.Otto.Run(`
- ret_response[response_idx] = { jsonrpc: ret_jsonrpc, id: ret_id, error: JSON.parse(ret_result) };
- `)
- continue
- }
- return newErrorResponse(call, -32603, fmt.Sprintf("Invalid response"), new(int64))
+ // Return the responses either to the callback (if supplied)
+ // or directly as the return value.
+ if batch {
+ response = resps.Value()
+ } else {
+ response, _ = resps.Get("0")
}
- // Convert single requests back from batch ones
- if !batch {
- call.Otto.Run("ret_response = ret_response[0];")
+ if fn := call.Argument(1).Object(); fn != nil && fn.Class() == "function" {
+ fn.Call("apply", response)
+ return otto.UndefinedValue()
}
- // Execute any registered callbacks
- if call.Argument(1).IsObject() {
- call.Otto.Set("callback", call.Argument(1))
- call.Otto.Run(`
- if (Object.prototype.toString.call(callback) == '[object Function]') {
- callback(null, ret_response);
- }
- `)
- }
- return
+ return response
+}
+
+func newErrorResponse(call otto.FunctionCall, code int, msg string, id interface{}) otto.Value {
+ // Bundle the error into a JSON RPC call response
+ m := map[string]interface{}{"version": "2.0", "id": id, "error": map[string]interface{}{"code": code, msg: msg}}
+ res, _ := json.Marshal(m)
+ val, _ := call.Otto.Run("(" + string(res) + ")")
+ return val
}
// throwJSException panics on an otto.Value. The Otto VM will recover from the
@@ -281,37 +279,3 @@ func throwJSException(msg interface{}) otto.Value {
}
panic(val)
}
-
-// newErrorResponse creates a JSON RPC error response for a specific request id,
-// containing the specified error code and error message. Beside returning the
-// error to the caller, it also sets the ret_error and ret_response JavaScript
-// variables.
-func newErrorResponse(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) {
- // Bundle the error into a JSON RPC call response
- res := rpc.JSONErrResponse{
- Version: rpc.JSONRPCVersion,
- Id: id,
- Error: rpc.JSONError{
- Code: code,
- Message: msg,
- },
- }
- // Serialize the error response into JavaScript variables
- errObj, err := json.Marshal(res.Error)
- if err != nil {
- glog.V(logger.Error).Infof("Failed to serialize JSON RPC error: %v", err)
- }
- resObj, err := json.Marshal(res)
- if err != nil {
- glog.V(logger.Error).Infof("Failed to serialize JSON RPC error response: %v", err)
- }
-
- if _, err = call.Otto.Run("ret_error = " + string(errObj)); err != nil {
- glog.V(logger.Error).Infof("Failed to set `ret_error` to the occurred error: %v", err)
- }
- resVal, err := call.Otto.Run("ret_response = " + string(resObj))
- if err != nil {
- glog.V(logger.Error).Infof("Failed to set `ret_response` to the JSON RPC response: %v", err)
- }
- return resVal
-}
diff --git a/console/console.go b/console/console.go
index 00d1fea1d..f224f0c2e 100644
--- a/console/console.go
+++ b/console/console.go
@@ -52,7 +52,7 @@ const DefaultPrompt = "> "
type Config struct {
DataDir string // Data directory to store the console history at
DocRoot string // Filesystem path from where to load JavaScript files from
- Client rpc.Client // RPC client to execute Ethereum requests through
+ Client *rpc.Client // RPC client to execute Ethereum requests through
Prompt string // Input prompt prefix string (defaults to DefaultPrompt)
Prompter UserPrompter // Input prompter to allow interactive user feedback (defaults to TerminalPrompter)
Printer io.Writer // Output writer to serialize any display strings to (defaults to os.Stdout)
@@ -63,7 +63,7 @@ type Config struct {
// JavaScript console attached to a running node via an external or in-process RPC
// client.
type Console struct {
- client rpc.Client // RPC client to execute Ethereum requests through
+ client *rpc.Client // RPC client to execute Ethereum requests through
jsre *jsre.JSRE // JavaScript runtime environment running the interpreter
prompt string // Input prompt prefix string
prompter UserPrompter // Input prompter to allow interactive user feedback
diff --git a/containers/docker/develop-alpine/Dockerfile b/containers/docker/develop-alpine/Dockerfile
index 6b00bf253..f3247d178 100644
--- a/containers/docker/develop-alpine/Dockerfile
+++ b/containers/docker/develop-alpine/Dockerfile
@@ -1,12 +1,11 @@
-FROM alpine:3.3
+FROM alpine:3.4
RUN \
- apk add --update go git make gcc musl-dev && \
- git clone https://github.com/ethereum/go-ethereum && \
- (cd go-ethereum && git checkout develop) && \
- (cd go-ethereum && make geth) && \
- cp go-ethereum/build/bin/geth /geth && \
- apk del go git make gcc musl-dev && \
+ apk add --update go git make gcc musl-dev && \
+ git clone --depth 1 --branch develop https://github.com/ethereum/go-ethereum && \
+ (cd go-ethereum && make geth) && \
+ cp go-ethereum/build/bin/geth /geth && \
+ apk del go git make gcc musl-dev && \
rm -rf /go-ethereum && rm -rf /var/cache/apk/*
EXPOSE 8545
diff --git a/containers/docker/master-alpine/Dockerfile b/containers/docker/master-alpine/Dockerfile
index 11d4159a3..3393c4337 100644
--- a/containers/docker/master-alpine/Dockerfile
+++ b/containers/docker/master-alpine/Dockerfile
@@ -1,11 +1,11 @@
-FROM alpine:3.3
+FROM alpine:3.4
RUN \
- apk add --update go git make gcc musl-dev gmp-dev gmp && \
- git clone https://github.com/ethereum/go-ethereum && \
- (cd go-ethereum && make geth) && \
- cp go-ethereum/build/bin/geth /geth && \
- apk del go git make gcc musl-dev gmp-dev && \
+ apk add --update go git make gcc musl-dev && \
+ git clone --depth 1 https://github.com/ethereum/go-ethereum && \
+ (cd go-ethereum && make geth) && \
+ cp go-ethereum/build/bin/geth /geth && \
+ apk del go git make gcc musl-dev && \
rm -rf /go-ethereum && rm -rf /var/cache/apk/*
EXPOSE 8545
diff --git a/core/bench_test.go b/core/bench_test.go
index c6029499a..344e7e3c5 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -163,7 +163,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Generate a chain of b.N blocks using the supplied block
// generator function.
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds})
- chain, _ := GenerateChain(genesis, db, b.N, gen)
+ chain, _ := GenerateChain(nil, genesis, db, b.N, gen)
// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
diff --git a/core/block_validator.go b/core/block_validator.go
index f056d9e3d..e5bc6178b 100644
--- a/core/block_validator.go
+++ b/core/block_validator.go
@@ -247,7 +247,8 @@ func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, pare
return &BlockNonceErr{header.Number, header.Hash(), header.Nonce.Uint64()}
}
}
- return nil
+ // If all checks passed, validate the extra-data field for hard forks
+ return ValidateDAOHeaderExtraData(config, header)
}
// CalcDifficulty is the difficulty adjustment algorithm. It returns
@@ -371,10 +372,5 @@ func CalcGasLimit(parent *types.Block) *big.Int {
gl.Add(parent.GasLimit(), decay)
gl.Set(common.BigMin(gl, params.TargetGasLimit))
}
- // Temporary special case: if DAO rupture is requested, cap the gas limit
- if DAOSoftFork && parent.NumberU64() <= ruptureBlock && gl.Cmp(ruptureTarget) > 0 {
- gl.Sub(parent.GasLimit(), decay)
- gl.Set(common.BigMax(gl, ruptureTarget))
- }
return gl
}
diff --git a/core/blockchain.go b/core/blockchain.go
index 95bada5ee..950804d40 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -771,14 +771,13 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
if ptd == nil {
return NonStatTy, ParentError(block.ParentHash())
}
-
- localTd := self.GetTd(self.currentBlock.Hash(), self.currentBlock.NumberU64())
- externTd := new(big.Int).Add(block.Difficulty(), ptd)
-
// Make sure no inconsistent state is leaked during insertion
self.mu.Lock()
defer self.mu.Unlock()
+ localTd := self.GetTd(self.currentBlock.Hash(), self.currentBlock.NumberU64())
+ externTd := new(big.Int).Add(block.Difficulty(), ptd)
+
// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index a26fe4a1b..c3e4d352d 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -712,7 +712,7 @@ func TestFastVsFullChains(t *testing.T) {
funds = big.NewInt(1000000000)
genesis = GenesisBlockForTesting(gendb, address, funds)
)
- blocks, receipts := GenerateChain(genesis, gendb, 1024, func(i int, block *BlockGen) {
+ blocks, receipts := GenerateChain(nil, genesis, gendb, 1024, func(i int, block *BlockGen) {
block.SetCoinbase(common.Address{0x00})
// If the block number is multiple of 3, send a few bonus transactions to the miner
@@ -795,7 +795,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
genesis = GenesisBlockForTesting(gendb, address, funds)
)
height := uint64(1024)
- blocks, receipts := GenerateChain(genesis, gendb, int(height), nil)
+ blocks, receipts := GenerateChain(nil, genesis, gendb, int(height), nil)
// Configure a subchain to roll back
remove := []common.Hash{}
@@ -895,7 +895,7 @@ func TestChainTxReorgs(t *testing.T) {
// - futureAdd: transaction added after the reorg has already finished
var pastAdd, freshAdd, futureAdd *types.Transaction
- chain, _ := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {
+ chain, _ := GenerateChain(nil, genesis, db, 3, func(i int, gen *BlockGen) {
switch i {
case 0:
pastDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
@@ -920,7 +920,7 @@ func TestChainTxReorgs(t *testing.T) {
}
// overwrite the old chain
- chain, _ = GenerateChain(genesis, db, 5, func(i int, gen *BlockGen) {
+ chain, _ = GenerateChain(nil, genesis, db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
pastAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
@@ -990,7 +990,7 @@ func TestLogReorgs(t *testing.T) {
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
subs := evmux.Subscribe(RemovedLogsEvent{})
- chain, _ := GenerateChain(genesis, db, 2, func(i int, gen *BlockGen) {
+ chain, _ := GenerateChain(nil, genesis, db, 2, func(i int, gen *BlockGen) {
if i == 1 {
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code).SignECDSA(key1)
if err != nil {
@@ -1003,7 +1003,7 @@ func TestLogReorgs(t *testing.T) {
t.Fatalf("failed to insert chain: %v", err)
}
- chain, _ = GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {})
+ chain, _ = GenerateChain(nil, genesis, db, 3, func(i int, gen *BlockGen) {})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert forked chain: %v", err)
}
@@ -1025,12 +1025,12 @@ func TestReorgSideEvent(t *testing.T) {
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
- chain, _ := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {})
+ chain, _ := GenerateChain(nil, genesis, db, 3, func(i int, gen *BlockGen) {})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert chain: %v", err)
}
- replacementBlocks, _ := GenerateChain(genesis, db, 4, func(i int, gen *BlockGen) {
+ replacementBlocks, _ := GenerateChain(nil, genesis, db, 4, func(i int, gen *BlockGen) {
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(key1)
if i == 2 {
gen.OffsetTime(-1)
diff --git a/core/chain_makers.go b/core/chain_makers.go
index ef0ac66d1..0b9a5f75d 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
)
@@ -35,7 +36,11 @@ import (
// MakeChainConfig returns a new ChainConfig with the ethereum default chain settings.
func MakeChainConfig() *ChainConfig {
- return &ChainConfig{HomesteadBlock: big.NewInt(0)}
+ return &ChainConfig{
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ }
}
// FakePow is a non-validating proof of work implementation.
@@ -173,10 +178,27 @@ func (b *BlockGen) OffsetTime(seconds int64) {
// Blocks created by GenerateChain do not contain valid proof of work
// values. Inserting them into BlockChain requires use of FakePow or
// a similar non-validating proof of work implementation.
-func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
+func GenerateChain(config *ChainConfig, parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) {
b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb}
+
+ // Mutate the state and block according to any hard-fork specs
+ if config == nil {
+ config = MakeChainConfig()
+ }
+ if daoBlock := config.DAOForkBlock; daoBlock != nil {
+ limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
+ if h.Number.Cmp(daoBlock) >= 0 && h.Number.Cmp(limit) < 0 {
+ if config.DAOForkSupport {
+ h.Extra = common.CopyBytes(params.DAOForkBlockExtra)
+ }
+ }
+ }
+ if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(h.Number) == 0 {
+ ApplyDAOHardFork(statedb)
+ }
+ // Execute any user modifications to the block and finalize it
if gen != nil {
gen(i, b)
}
@@ -261,7 +283,7 @@ func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) [
// makeBlockChain creates a deterministic chain of blocks rooted at parent.
func makeBlockChain(parent *types.Block, n int, db ethdb.Database, seed int) []*types.Block {
- blocks, _ := GenerateChain(parent, db, n, func(i int, b *BlockGen) {
+ blocks, _ := GenerateChain(nil, parent, db, n, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
})
return blocks
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index 32c3efe8d..f52b09ad9 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -47,7 +47,7 @@ func ExampleGenerateChain() {
// This call generates a chain of 5 blocks. The function runs for
// each block and adds different features to gen based on the
// block index.
- chain, _ := GenerateChain(genesis, db, 5, func(i int, gen *BlockGen) {
+ chain, _ := GenerateChain(nil, genesis, db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
// In block 1, addr1 sends addr2 some ether.
diff --git a/core/chain_pow_test.go b/core/chain_pow_test.go
index d2b0bd144..2e26c8211 100644
--- a/core/chain_pow_test.go
+++ b/core/chain_pow_test.go
@@ -60,7 +60,7 @@ func TestPowVerification(t *testing.T) {
var (
testdb, _ = ethdb.NewMemDatabase()
genesis = GenesisBlockForTesting(testdb, common.Address{}, new(big.Int))
- blocks, _ = GenerateChain(genesis, testdb, 8, nil)
+ blocks, _ = GenerateChain(nil, genesis, testdb, 8, nil)
)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@@ -115,7 +115,7 @@ func testPowConcurrentVerification(t *testing.T, threads int) {
var (
testdb, _ = ethdb.NewMemDatabase()
genesis = GenesisBlockForTesting(testdb, common.Address{}, new(big.Int))
- blocks, _ = GenerateChain(genesis, testdb, 8, nil)
+ blocks, _ = GenerateChain(nil, genesis, testdb, 8, nil)
)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@@ -186,7 +186,7 @@ func testPowConcurrentAbortion(t *testing.T, threads int) {
var (
testdb, _ = ethdb.NewMemDatabase()
genesis = GenesisBlockForTesting(testdb, common.Address{}, new(big.Int))
- blocks, _ = GenerateChain(genesis, testdb, 1024, nil)
+ blocks, _ = GenerateChain(nil, genesis, testdb, 1024, nil)
)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
diff --git a/core/config.go b/core/config.go
index 81ca76aa3..c0d065a57 100644
--- a/core/config.go
+++ b/core/config.go
@@ -31,16 +31,17 @@ var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general conf
// that any network, identified by its genesis block, can have its own
// set of configuration options.
type ChainConfig struct {
- HomesteadBlock *big.Int // homestead switch block
+ HomesteadBlock *big.Int `json:"homesteadBlock"` // Homestead switch block (nil = no fork, 0 = already homestead)
+ DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork)
+ DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork
VmConfig vm.Config `json:"-"`
}
// IsHomestead returns whether num is either equal to the homestead block or greater.
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
- if num == nil {
+ if c.HomesteadBlock == nil || num == nil {
return false
}
-
return num.Cmp(c.HomesteadBlock) >= 0
}
diff --git a/core/dao.go b/core/dao.go
new file mode 100644
index 000000000..e315c9884
--- /dev/null
+++ b/core/dao.go
@@ -0,0 +1,74 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package core
+
+import (
+ "bytes"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// ValidateDAOHeaderExtraData validates the extra-data field of a block header to
+// ensure it conforms to DAO hard-fork rules.
+//
+// DAO hard-fork extension to the header validity:
+// a) if the node is no-fork, do not accept blocks in the [fork, fork+10) range
+// with the fork specific extra-data set
+// b) if the node is pro-fork, require blocks in the specific range to have the
+// unique extra-data set.
+func ValidateDAOHeaderExtraData(config *ChainConfig, header *types.Header) error {
+ // Short circuit validation if the node doesn't care about the DAO fork
+ if config.DAOForkBlock == nil {
+ return nil
+ }
+ // Make sure the block is within the fork's modified extra-data range
+ limit := new(big.Int).Add(config.DAOForkBlock, params.DAOForkExtraRange)
+ if header.Number.Cmp(config.DAOForkBlock) < 0 || header.Number.Cmp(limit) >= 0 {
+ return nil
+ }
+ // Depending whether we support or oppose the fork, validate the extra-data contents
+ if config.DAOForkSupport {
+ if bytes.Compare(header.Extra, params.DAOForkBlockExtra) != 0 {
+ return ValidationError("DAO pro-fork bad block extra-data: 0x%x", header.Extra)
+ }
+ } else {
+ if bytes.Compare(header.Extra, params.DAOForkBlockExtra) == 0 {
+ return ValidationError("DAO no-fork bad block extra-data: 0x%x", header.Extra)
+ }
+ }
+ // All ok, header has the same extra-data we expect
+ return nil
+}
+
+// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
+// rules, transferring all balances of a set of DAO accounts to a single refund
+// contract.
+func ApplyDAOHardFork(statedb *state.StateDB) {
+ // Retrieve the contract to refund balances into
+ refund := statedb.GetOrNewStateObject(params.DAORefundContract)
+
+ // Move every DAO account and extra-balance account funds into the refund contract
+ for _, addr := range params.DAODrainList {
+ if account := statedb.GetStateObject(addr); account != nil {
+ refund.AddBalance(account.Balance())
+ account.SetBalance(new(big.Int))
+ }
+ }
+}
diff --git a/core/dao_test.go b/core/dao_test.go
index 12fa2ddd7..0830b1231 100644
--- a/core/dao_test.go
+++ b/core/dao_test.go
@@ -20,339 +20,113 @@ import (
"math/big"
"testing"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
)
-// Some weird dependency for deploying a DAO instance.
-var creatorDeployCode = common.FromHex("606060405261339c806100126000396000f3606060405260e060020a6000350463e2faf0448114601a575b005b6097600435602435604435606435600084308585853360606132e8806100b48339018087600160a060020a0316815260200186600160a060020a0316815260200185815260200184815260200183815260200182600160a060020a031681526020019650505050505050604051809103906000f095945050505050565b60408051600160a060020a03929092168252519081900360200190f3606060405260405160c0806132e88339610120604052905160805160a051925160e0516101005193949293828282600f829055601083905560118054610100830261010060a860020a031990911617905560405130906001906101bc806103378339600160a060020a039390931692019182526020820152604080519182900301906000f060128054600160a060020a031916919091179055505060038054600160a060020a03199081168917909155600e80549091168717905550600c84905560405130906000906101bc806104f38339018083600160a060020a0316815260200182815260200192505050604051809103906000f060405160078054600160a060020a0319169290921790915530906000906101bc806106af8339018083600160a060020a0316815260200182815260200192505050604051809103906000f060088054600160a060020a031916919091179055600754600160a060020a0316600014156101c357610002565b50505030600160a060020a03908116600090815260046020526040808220805460ff19908116600190811790925560035490941683529120805490921617905550505050505050612a7d8061086b6000396000f35b600854600160a060020a0316600014156101dc57610002565b4260025560056001908155600080548282558290801582901161016e57600e0281600e02836000526020600020918201910161016e919061023e565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b80821115610333578054600160a060020a03191681556000600182810182905560028381018054848255909281161561010002600019011604601f81901061030557505b506000600383018190556004838101805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220610218929091028101905b808211156103335760008082556001820181815560028301919091556003919091018054600160a060020a03191690556102d0565b601f01602090049060005260206000209081019061028291905b80821115610333576000815560010161031f565b50905660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b92915050566060604052361561020e5760e060020a6000350463013cf08b811461022c578063095ea7b3146103ea5780630c3b7b961461045e5780630e70820314610467578063149acf9a1461047957806318160ddd1461048b5780631f2dc5ef1461049457806321b5b8dd146104b4578063234693d3146104c6578063237e94921461052c57806323b872dd1461058d57806334145808146105c057806339d1f908146105c95780634b6753bc146105e15780634df6d6cc146105ea5780634e10c3ee14610605578063590e1ae314610618578063612e45a314610629578063643f7cdd146106c8578063674ed066146106e05780636837ff1e146106e957806370a0823114610733578063749f98891461075957806378524b2e1461077257806381f03fcb1461079f57806382661dc4146107b757806382bf6464146107d85780638b15a605146107ea5780638d7af473146107f357806396d7f3f514610802578063a1da2fb91461080b578063a3912ec814610825578063a9059cbb14610830578063b7bc2c8414610860578063baac53001461086c578063c9d27afe146108d0578063cc9ae3f6146108e6578063cdef91d0146108fa578063dbde198814610912578063dd62ed3e14610937578063e33734fd1461096b578063e59621951461097f578063e66f53b714610997578063eceb2945146109a9578063f8c80d2614610a08578063fbac395114610a1f575b610a4d600f546000906234bc0001421015610a5f57610a6733610873565b610a6d60043560008054829081101561000257508052600e027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5678101547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5698201547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5668301547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564840154600080516020612a5d8339815191528501547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56a8601547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5688701547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c8801547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56d8901547f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5708a0154600160a060020a039586169a96997f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565979097019860ff888116986101009004811697959691959116939291168c565b610a4d600435602435600160a060020a03338116600081815260156020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b610a4d60105481565b610b64600754600160a060020a031681565b610b64600e54600160a060020a031681565b610a4d60165481565b610a4d5b60004262127500600f6000505403111561267757506014610a6a565b610b64601254600160a060020a031681565b610b64600435600060006000508281548110156100025750508080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b600e83020180548290811015610002575081526020902060030154600160a060020a0316610754565b60408051602060248035600481810135601f8101859004850286018501909652858552610a4d958135959194604494929390920191819084018382808284375094965050505050505060006000600060006000600034111561140f57610002565b610a4d6004356024356044355b60115460009060ff1680156105b05750600f5442115b801561220b575061220984610a26565b610a4d60065481565b610a4d5b600d5430600160a060020a03163103610a6a565b610a4d600f5481565b610a4d60043560046020526000908152604090205460ff1681565b610a4d60043560243560006121ed6108ea565b610b8160003411156124b557610002565b604080516020604435600481810135601f8101849004840285018401909552848452610a4d948135946024803595939460649492939101918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505060a43591505060006000610b833361073a565b610a4d60043560096020526000908152604090205481565b610a4d60015481565b610b8160043530600160a060020a031633600160a060020a03161415806107295750600160a060020a03811660009081526004602052604090205460ff16155b15611ee757611ee4565b610a4d6004355b600160a060020a0381166000908152601460205260409020545b919050565b610a4d600435602435600060003411156122bb57610002565b610a4d60006301dfe200420360026000505410156123375750426002908155600180549091028155610a6a565b610a4d600435600a6020526000908152604090205481565b610a4d6004356024356000600060006000600060003411156118cb57610002565b610b64600854600160a060020a031681565b610a4d600c5481565b610a4d60005460001901610a6a565b610a4d60025481565b610a4d6004356000600060006000341115611f1857610002565b610a4d5b6001610a6a565b610a4d6004356024355b60115460009060ff1680156108505750600f5442115b80156121a457506121a233610a26565b610a4d60115460ff1681565b610a4d6004355b60006000600f600050544210801561088b5750600034115b80156108c357506011546101009004600160a060020a0316600014806108c35750601154600160a060020a0333811661010090920416145b156121e8576123b5610498565b610a4d600435602435600060006111b43361073a565b610a4d5b6000600034111561219957610002565b610a4d60043560056020526000908152604090205481565b610a4d6004356024356044356000612251845b6000600060003411156126ad57610002565b610a4d600435602435600160a060020a03828116600090815260156020908152604080832093851683529290522054610458565b610b81600435600034111561226757610002565b610a4d600435600b6020526000908152604090205481565b610b64600354600160a060020a031681565b604080516020606435600481810135601f8101849004840285018401909552848452610a4d9481359460248035956044359560849492019190819084018382808284375094965050505050505060006000600034111561112557610002565b610b646011546101009004600160a060020a031681565b610a4d6004355b600160a060020a0381166000908152600b6020526040812054819081141561233f576123af565b60408051918252519081900360200190f35b610a67610829565b90505b90565b604051808d600160a060020a031681526020018c8152602001806020018b81526020018a815260200189815260200188815260200187815260200186815260200185815260200184815260200183600160a060020a0316815260200182810382528c818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610b4a5780601f10610b1f57610100808354040283529160200191610b4a565b820191906000526020600020905b815481529060010190602001808311610b2d57829003601f168201915b50509d505050505050505050505050505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b005b60001415610b9057610002565b828015610bda5750866000141580610baa57508451600014155b80610bc25750600354600160a060020a038981169116145b80610bcd5750600034115b80610bda575062093a8084105b15610be457610002565b82158015610c045750610bf688610c1e565b1580610c0457506212750084105b15610cc057610002565b835461158390600160a060020a03165b600160a060020a03811660009081526004602052604081205460ff1680610cb35750601254600160a060020a03908116908316148015610cb35750601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051516006541190505b156128a257506001610754565b6249d400841115610cd057610002565b60115460ff161580610ce35750600f5442105b80610cf85750600c5434108015610cf8575082155b15610d0257610002565b428442011015610d1157610002565b30600160a060020a031633600160a060020a03161415610d3057610002565b6000805460018101808355909190828015829011610d6757600e0281600e028360005260206000209182019101610d679190610e2c565b505060008054929450918491508110156100025750808052600e8302600080516020612a5d8339815191520190508054600160a060020a031916891781556001818101899055875160028084018054600082815260209081902096975091959481161561010002600019011691909104601f908101829004840193918b0190839010610f2457805160ff19168380011785555b50610f54929150610f0c565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b80821115610f20578054600160a060020a03191681556000600182810182905560028084018054848255909281161561010002600019011604601f819010610ef257505b506000600383018190556004808401805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220610e06929091028101905b80821115610f2057600080825560018201818155600283019190915560039091018054600160a060020a0319169055610ebe565b601f016020900490600052602060002090810190610e7091905b80821115610f205760008155600101610f0c565b5090565b82800160010185558215610dfa579182015b82811115610dfa578251826000505591602001919060010190610f36565b50508787866040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160050160005081905550834201816003016000508190555060018160040160006101000a81548160ff02191690830217905550828160070160006101000a81548160ff02191690830217905550821561103a5760088101805460018101808355909190828015829011611035576004028160040283600052602060002091820191016110359190610ebe565b505050505b600d8082018054600160a060020a031916331790553460068301819055815401905560408051600160a060020a038a16815260208181018a9052918101859052608060608201818152895191830191909152885185937f5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f938d938d938a938e93929160a084019185810191908190849082908590600090600490601f850104600f02600301f150905090810190601f16801561110a5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a2509695505050505050565b6000805487908110156100025750808052600e8702600080516020612a5d83398151915201905090508484846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020816005016000505414915050949350505050565b600014156111c157610002565b60003411156111cf57610002565b6000805485908110156100025750600160a060020a0333168152600e85027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e8101602052604090912054600080516020612a5d83398151915291909101915060ff16806112485750600c810160205260406000205460ff165b80611257575060038101544210155b1561126157610002565b82156112a757600160a060020a0333166000908152601460209081526040808320546009850180549091019055600b84019091529020805460ff191660011790556112e3565b600160a060020a033316600090815260146020908152604080832054600a850180549091019055600c84019091529020805460ff191660011790555b600160a060020a0333166000908152600b6020526040812054141561130f576040600020849055611383565b600160a060020a0333166000908152600b60205260408120548154811015610002579080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566600e90910201546003820154111561138357600160a060020a0333166000908152600b602052604090208490555b604080518481529051600160a060020a0333169186917f86abfce99b7dd908bec0169288797f85049ec73cbe046ed9de818fab3a497ae09181900360200190a35092915050565b6040805186815260208101839052815189927fdfc78bdca8e3e0b18c16c5c99323c6cb9eb5e00afde190b4e7273f5158702b07928290030190a25b5050505092915050565b6000805488908110156100025750808052600e8802600080516020612a5d833981519152019050600781015490945060ff1661144e57620d2f00611453565b622398805b600485015490935060ff16801561146f57506003840154830142115b1561147d5761151f8761152e565b60038401544210806114945750600484015460ff16155b8061151557508360000160009054906101000a9004600160a060020a03168460010160005054876040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020846005016000505414155b15610c0e57610002565b611405565b426002555b6113ca875b6000600060005082815481101561000257908052600e02600080516020612a5d833981519152018150600481015490915060ff161561157557600d80546006830154900390555b600401805460ff1916905550565b1580156115945750600484015460ff165b156115a2576115ae8761152e565b600191506115df6105cd565b604051600d8501546006860154600160a060020a0391909116916000919082818181858883f1935050505050611405565b600185015411156115ef57600091505b50600a8301546009840154865191019060049010801590611634575085600081518110156100025790602001015160f860020a900460f860020a02606860f860020a02145b8015611664575085600181518110156100025790602001015160f860020a900460f860020a02603760f860020a02145b8015611694575085600281518110156100025790602001015160f860020a900460f860020a0260ff60f860020a02145b80156116c4575085600381518110156100025790602001015160f860020a900460f860020a02601e60f860020a02145b80156116f3575030600160a060020a03166000908152600560205260409020546116f09061170b6105cd565b81105b156116fd57600091505b600184015461172e9061170d565b015b30600160a060020a03166000908152600560205260408120546128aa6105cd565b811015801561174557506009840154600a85015490115b801561174e5750815b1561178957604051600d8501546006860154600160a060020a0391909116916000919082818181858883f19350505050151561179757610002565b60018401546118709061170d565b42600255604051600185015485548851600160a060020a03919091169289918190602084810191908190849082908590600090600490601f850104600f02600301f150905090810190601f1680156118035780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f192505050151561182757610002565b60048401805461ff0019166101001790556001848101805430600160a060020a031660009081526005602052604090208054919091019055546006805490910190559450611529565b811015801561188757506009840154600a85015410155b80611890575081155b1561152957604051600d8501546006860154600160a060020a0391909116916000919082818181858883f19350505050151561152457610002565b6118d43361073a565b600014156118e157610002565b60008054889081101561000257508052600e87027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566810154600080516020612a5d83398151915291909101945042108061194357506003840154622398800142115b8061195c57508354600160a060020a0390811690871614155b8061196c5750600784015460ff16155b806119925750600160a060020a0333166000908152600b8501602052604090205460ff16155b806119b55750600160a060020a0333166000908152600b60205260409020548714155b156119bf57610002565b600884018054600090811015610002579081526020812060030154600160a060020a03161415611b2b57611c1586604051600090600160a060020a038316907f9046fefd66f538ab35263248a44217dcb70e2eb2cd136629e141b8b8f9f03b60908390a260408051600e547fe2faf044000000000000000000000000000000000000000000000000000000008252600160a060020a03858116600484015260248301859052604483018590526223988042016064840152925192169163e2faf04491608480820192602092909190829003018187876161da5a03f1156100025750506040515191506107549050565b6008850180546000908110156100025781815260208082209390935530600160a060020a031681526005909252604082205481549092908110156100025790815260208120905060020155601654600885018054600090811015610002579081526020812090506001015560048401805461ff0019166101001790555b60088401805460009081101561000257815482825260208220600101549291908110156100025790815260208120905054600160a060020a033316600090815260146020526040812054600888018054939091029390930495509081101561000257908152602081209050604080516003909201547fbaac5300000000000000000000000000000000000000000000000000000000008352600160a060020a033381166004850152915191169163baac5300918691602480820192602092909190829003018185886185025a03f11561000257505060405151600014159150611c91905057610002565b60088501805460009081101561000257818152602081206003018054600160a060020a03191690931790925580549091908110156100025790815260208120905060030154600160a060020a031660001415611c7057610002565b600d5430600160a060020a0316311015611c8957610002565b611aae6105cd565b60088401805460009081101561000257815482825260208220600101549291908110156100025790815260208120905060020154600160a060020a0333811660009081526014602090815260408083205430909416835260058083528184205460099093529083205460088b018054969095029690960497509487020494508593929091908290811015610002575260208120815060030154600160a060020a03908116825260208281019390935260409182016000908120805490950190945530168352600590915290205482901015611d6b57610002565b30600160a060020a031660009081526005602052604081208054849003905560088501805483926009929091829081101561000257508152602080822060030154600160a060020a0390811683529290526040808220805494909401909355309091168152205481901015611ddf57610002565b30600160a060020a039081166000908152600960209081526040808320805486900390553393909316808352601482528383205484519081529351929390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3611e5233610925565b50600160a060020a0333166000908152601460209081526040808320805460168054919091039055839055600a90915281205560019450611405565b30600160a060020a03908116600081815260056020908152604080832080549587168085528285208054979097019096558484528390556009909152808220805494835290822080549490940190935590815290555b50565b604051600160a060020a0382811691309091163190600081818185876185025a03f1925050501515611e8e57610002565b600160a060020a0333818116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f028352935196995091969195929091169363d2cc718f93600483810194919391929183900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a031681526020019081526020016000206000505402041015611fba57610002565b600160a060020a03338116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f02835293519296909593169363d2cc718f93600483810194929383900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a03168152602001908152602001600020600050540204039050831561210957600860009054906101000a9004600160a060020a0316600160a060020a0316630221038a83600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a031660048201526024810186905290516044808301935060209282900301816000876161da5a03f115610002575050604051511515905061217157610002565b6040805160085460e160020a63011081c5028252600160a060020a038581166004840152602483018590529251921691630221038a9160448082019260209290919082900301816000876161da5a03f115610002575050604051511515905061217157610002565b600160a060020a03331660009081526009602052604090208054909101905550600192915050565b610a6733610925565b155b80156121bf57506121bf3384845b6000600061283b8561073a565b80156121db57506121db8383600060003411156128cc57610002565b156121e857506001610458565b610002565b15156121f857610002565b612202838361083a565b9050610458565b155b801561221d575061221d8484846121b2565b801561223a575061223a8484846000600034111561297157610002565b156121e85750600161224a565b90505b9392505050565b151561225c57610002565b61224784848461059a565b30600160a060020a031633600160a060020a03161415806122ac575030600160a060020a03166000908152600560205260409020546064906122a76105cd565b010481115b156122b657610002565b600c55565b600354600160a060020a039081163391909116146122d857610002565b600160a060020a038316600081815260046020908152604091829020805460ff191686179055815185815291517f73ad2a153c8b67991df9459024950b318a609782cee8c7eeda47b905f9baa91f9281900390910190a2506001610458565b506000610a6a565b600160a060020a0383166000908152600b6020526040812054815481101561000257818052600e02600080516020612a5d83398151915201905060038101549091504211156123aa57600160a060020a0383166000908152600b6020526040812081905591506123af565b600191505b50919050565b604051601254601434908102939093049350600160a060020a03169183900390600081818185876185025a03f150505050600160a060020a038316600081815260146020908152604080832080548601905560168054860190556013825291829020805434019055815184815291517fdbccb92686efceafb9bb7e0394df7f58f71b954061b81afb57109bf247d3d75a9281900390910190a260105460165410801590612465575060115460ff16155b156123aa576011805460ff1916600117905560165460408051918252517ff381a3e2428fdda36615919e8d9c35878d9eb0cf85ac6edf575088e80e4c147e9181900360200190a1600191506123af565b600f54421180156124c9575060115460ff16155b15612675576040805160125460e060020a63d2cc718f0282529151600160a060020a039290921691630221038a913091849163d2cc718f91600480830192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a039490941660048201526024810193909352516044838101936020935082900301816000876161da5a03f11561000257505060408051600160a060020a03331660008181526013602052928320549093509181818185876185025a03f192505050156126755760406000818120600160a060020a0333169182905260136020908152835191548252925191927fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d92918290030190a26014600050600033600160a060020a0316815260200190815260200160002060005054601660008282825054039250508190555060006014600050600033600160a060020a031681526020019081526020016000206000508190555060006013600050600033600160a060020a03168152602001908152602001600020600050819055505b565b4262054600600f600050540311156126a5576201518062127500600f60005054034203046014019050610a6a565b50601e610a6a565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f11561000257505060405151905061271b8661073a565b0204101561272857610002565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f1156100025750506040515190506127968661073a565b0204039050600760009054906101000a9004600160a060020a0316600160a060020a0316630221038a84836040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061281457610002565b600160a060020a0383166000908152600a60205260409020805482019055600191506123af565b600160a060020a0386166000908152600a602052604090205480850291909104915081111561286957610002565b600160a060020a038581166000908152600a60205260408082208054859003905591861681522080548201905560019150509392505050565b506000610754565b0160030260166000505483020460016000505460166000505404019050610754565b600160a060020a0333166000908152601460205260409020548290108015906128f55750600082115b1561296957600160a060020a03338116600081815260146020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610458565b506000610458565b600160a060020a0384166000908152601460205260409020548290108015906129ba57506015602090815260406000818120600160a060020a0333168252909252902054829010155b80156129c65750600082115b15612a5557600160a060020a0383811660008181526014602090815260408083208054880190558885168084528184208054899003905560158352818420339690961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a350600161224a565b50600061224a56290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
-
-// EVM deploy bytecode of the DAO to simulate blocking.
-var daoDeployCode = common.FromHex("606060405260405160c0806132c88339610120604052905160805160a051925160e0516101005193949293828282600f829055601083905560118054610100830261010060a860020a031990911617905560405130906001906101bc8061033e8339600160a060020a03909316908301526101408201526040519081900361016001906000f060128054600160a060020a031916919091179055505060038054600160a060020a03199081168917909155600e80549091168717905550600c84905560405130906000906101bc806104fa8339018083600160a060020a0316815260200182815260200192505050604051809103906000f0600760006101000a815481600160a060020a03021916908302179055503060006040516101bc806106b68339018083600160a060020a0316815260200182815260200192505050604051809103906000f060088054600160a060020a031916919091179055600754600160a060020a03166000141561017557610002565b600854600160a060020a03166000141561018e57610002565b426002556005600190815560008054828255829080158290116101ca57600e0281600e0283600052602060002091820191016101ca9190610245565b50505030600160a060020a03908116600090815260046020526040808220805460ff19908116600190811790925560035490941683529120805490921617905550505050505050612a56806108726000396000f35b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561033a578054600160a060020a03191681556000600182810182905560028381018054848255909281161561010002600019011604601f81901061030c57505b506000600383018190556004838101805461ffff19169055600584018290556006840182905560078401805460ff19169055600884018054838255908352602090922061021f929091028101905b8082111561033a5760008082556001820181815560028301919091556003919091018054600160a060020a03191690556102d7565b601f01602090049060005260206000209081019061028991905b8082111561033a5760008155600101610326565b50905660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b92915050566060604052361561020e5760e060020a6000350463013cf08b8114610247578063095ea7b3146102d05780630c3b7b96146103455780630e7082031461034e578063149acf9a1461036057806318160ddd146103725780631f2dc5ef1461037b57806321b5b8dd1461039b578063237e9492146103ad57806323b872dd1461040e5780632632bf2014610441578063341458081461047257806339d1f9081461047b5780634b6753bc146104935780634df6d6cc1461049c5780634e10c3ee146104b7578063590e1ae3146104ca578063612e45a3146104db578063643f7cdd1461057a578063674ed066146105925780636837ff1e1461059b57806370a08231146105e5578063749f98891461060b57806378524b2e1461062457806381f03fcb1461067e57806382661dc41461069657806382bf6464146106b75780638b15a605146106c95780638d7af473146106d257806396d7f3f5146106e1578063a1da2fb9146106ea578063a3912ec814610704578063a9059cbb1461070f578063b7bc2c841461073f578063baac53001461074b578063be7c29c1146107b1578063c9d27afe14610817578063cc9ae3f61461082d578063cdef91d014610841578063dbde198814610859578063dd62ed3e1461087e578063e33734fd146108b2578063e5962195146108c6578063e66f53b7146108de578063eceb2945146108f0578063f8c80d261461094f575b610966600f546000906234bc000142108015610239575060125433600160a060020a03908116911614155b156109785761098033610752565b6109866004356000805482908110156100025750808052600e8202600080516020612a3683398151915201905060038101546004820154600683015460018401548454600786015460058701546009880154600a890154600d8a0154600160a060020a039586169b509599600201989760ff81811698610100909204811697949691951693168c565b61096660043560243533600160a060020a03908116600081815260156020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b61096660105481565b610a7d600754600160a060020a031681565b610a7d600e54600160a060020a031681565b61096660165481565b6109665b60004262127500600f60005054031115610de557506014610983565b610a7d601254600160a060020a031681565b60408051602060248035600481810135601f810185900485028601850190965285855261096695813595919460449492939092019181908401838280828437509496505050505050506000600060006000600060003411156116a857610002565b6109666004356024356044355b60115460009060ff1680156104315750600f5442115b80156124e957506124e78461044b565b6109666000610980335b600160a060020a0381166000908152600b602052604081205481908114156129cb57610b99565b61096660065481565b6109665b600d5430600160a060020a03163103610983565b610966600f5481565b61096660043560046020526000908152604090205460ff1681565b61096660043560243560006124cb610831565b610a9a6000341115610ba457610002565b604080516020604435600481810135601f8101849004840285018401909552848452610966948135946024803595939460649492939101918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505060a435915050600060006110c1336105ec565b61096660043560096020526000908152604090205481565b61096660015481565b610a9a60043530600160a060020a031633600160a060020a03161415806105db5750600160a060020a03811660009081526004602052604090205460ff16155b156121cb576121c8565b6109666004355b600160a060020a0381166000908152601460205260409020545b919050565b6109666004356024356000600034111561259957610002565b610966600062e6b680420360026000505410806106505750600354600160a060020a0390811633909116145b80156106645750600254621274ff19420190105b156126145750426002908155600180549091028155610983565b610966600435600a6020526000908152604090205481565b610966600435602435600060006000600060006000341115611ba157610002565b610a7d600854600160a060020a031681565b610966600c5481565b61096660005460001901610983565b61096660025481565b61096660043560006000600060003411156121fc57610002565b6109665b6001610983565b6109666004356024355b60115460009060ff16801561072f5750600f5442115b801561248757506124853361044b565b61096660115460ff1681565b6109666004355b60006000600f600050544210801561076a5750600034115b80156107a457506011546101009004600160a060020a0316600014806107a457506011546101009004600160a060020a0390811633909116145b15610b9f57610a9c61037f565b610a7d600435600060006000508281548110156100025750508080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b600e83020180548290811015610002575081526020902060030154600160a060020a0316610606565b61096660043560243560006000610e1b336105ec565b6109665b6000600034111561247c57610002565b61096660043560056020526000908152604090205481565b610966600435602435604435600061252f845b6000600060003411156127ac57610002565b610966600435602435600160a060020a0382811660009081526015602090815260408083209385168352929052205461033f565b610a9a600435600034111561254557610002565b610966600435600b6020526000908152604090205481565b610a7d600354600160a060020a031681565b604080516020606435600481810135601f81018490048402850184019095528484526109669481359460248035956044359560849492019190819084018382808284375094965050505050505060006000600034111561103257610002565b610a7d6011546101009004600160a060020a031681565b60408051918252519081900360200190f35b610980610708565b90505b90565b604051808d600160a060020a031681526020018c8152602001806020018b81526020018a815260200189815260200188815260200187815260200186815260200185815260200184815260200183600160a060020a0316815260200182810382528c818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610a635780601f10610a3857610100808354040283529160200191610a63565b820191906000526020600020905b815481529060010190602001808311610a4657829003601f168201915b50509d505050505050505050505050505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b005b604051601254601434908102939093049350600160a060020a03169183900390600081818185876185025a03f150505050600160a060020a038316600081815260146020908152604080832080548601905560168054860190556013825291829020805434019055815184815291517fdbccb92686efceafb9bb7e0394df7f58f71b954061b81afb57109bf247d3d75a9281900390910190a260105460165410801590610b4c575060115460ff16155b15610b94576011805460ff1916600117905560165460408051918252517ff381a3e2428fdda36615919e8d9c35878d9eb0cf85ac6edf575088e80e4c147e9181900360200190a15b600191505b50919050565b610002565b600f5442118015610bb8575060115460ff16155b15610de357601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040516012549051600160a060020a039190911631109050610cc9576040805160125460e060020a63d2cc718f0282529151600160a060020a039290921691630221038a913091849163d2cc718f91600482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a039490941660048201526024810193909352516044838101936020935082900301816000876161da5a03f115610002575050505b33600160a060020a0316600081815260136020526040808220549051909181818185876185025a03f19250505015610de35733600160a060020a03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d6013600050600033600160a060020a03168152602001908152602001600020600050546040518082815260200191505060405180910390a26014600050600033600160a060020a0316815260200190815260200160002060005054601660008282825054039250508190555060006014600050600033600160a060020a031681526020019081526020016000206000508190555060006013600050600033600160a060020a03168152602001908152602001600020600050819055505b565b4262054600600f60005054031115610e13576201518062127500600f60005054034203046014019050610983565b50601e610983565b60001415610e2857610002565b6000341115610e3657610002565b6000805485908110156100025750600160a060020a03331681527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e600e8602908101602052604090912054600080516020612a3683398151915291909101915060ff1680610eb05750600c810160205260406000205460ff165b80610ebf575060038101544210155b15610ec957610002565b8215610f0f5733600160a060020a03166000908152601460209081526040808320546009850180549091019055600b84019091529020805460ff19166001179055610f4b565b33600160a060020a0316600090815260146020908152604080832054600a850180549091019055600c84019091529020805460ff191660011790555b33600160a060020a03166000908152600b60205260408120541415610f77576040600020849055610feb565b33600160a060020a03166000908152600b60205260408120548154811015610002579080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566600e909102015460038201541115610feb5733600160a060020a03166000908152600b602052604090208490555b60408051848152905133600160a060020a03169186917f86abfce99b7dd908bec0169288797f85049ec73cbe046ed9de818fab3a497ae09181900360200190a35092915050565b6000805487908110156100025750808052600e8702600080516020612a3683398151915201905090508484846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020816005016000505414915050949350505050565b600014156110ce57610002565b82801561111857508660001415806110e857508451600014155b806111005750600354600160a060020a038981169116145b8061110b5750600034115b80611118575062093a8084105b1561112257610002565b8215801561114257506111348861115c565b158061114257506212750084105b156111fe57610002565b83546118e590600160a060020a03165b600160a060020a03811660009081526004602052604081205460ff16806111f15750601254600160a060020a039081169083161480156111f15750601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051516006541190505b156129a157506001610606565b6249d40084111561120e57610002565b60115460ff1615806112215750600f5442105b806112365750600c5434108015611236575082155b1561124057610002565b42844201101561124f57610002565b30600160a060020a031633600160a060020a0316141561126e57610002565b60008054600181018083559091908280158290116112a557600e0281600e0283600052602060002091820191016112a5919061136a565b505060008054929450918491508110156100025750808052600e8302600080516020612a368339815191520190508054600160a060020a031916891781556001818101899055875160028084018054600082815260209081902096975091959481161561010002600019011691909104601f908101829004840193918b019083901061146257805160ff19168380011785555b5061149292915061144a565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561145e578054600160a060020a03191681556000600182810182905560028084018054848255909281161561010002600019011604601f81901061143057505b506000600383018190556004808401805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220611344929091028101905b8082111561145e57600080825560018201818155600283019190915560039091018054600160a060020a03191690556113fc565b601f0160209004906000526020600020908101906113ae91905b8082111561145e576000815560010161144a565b5090565b82800160010185558215611338579182015b82811115611338578251826000505591602001919060010190611474565b50508787866040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160050160005081905550834201816003016000508190555060018160040160006101000a81548160ff02191690830217905550828160070160006101000a81548160ff02191690830217905550821561157857600881018054600181018083559091908280158290116115735760040281600402836000526020600020918201910161157391906113fc565b505050505b600d8082018054600160a060020a031916331790553460068301819055815401905560408051600160a060020a038a16815260208181018a9052918101859052608060608201818152895191830191909152885185937f5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f938d938d938a938e93929160a084019185810191908190849082908590600090600490601f850104600f02600301f150905090810190601f1680156116485780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a2509695505050505050565b6040805186815260208101839052815189927fdfc78bdca8e3e0b18c16c5c99323c6cb9eb5e00afde190b4e7273f5158702b07928290030190a25b5050505092915050565b6000805488908110156100025750808052600e8802600080516020612a36833981519152019050600781015490945060ff166116e757620d2f006116ec565b622398805b600485015490935060ff16801561170857506003840154830142115b15611716576117b887611890565b600384015442108061172d5750600484015460ff16155b806117ae57508360000160009054906101000a9004600160a060020a03168460010160005054876040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020846005016000505414155b1561114c57610002565b61169e565b60048401805461ff001916610100179055835460019550600160a060020a03908116309091161480159061180157508354600754600160a060020a03908116911614155b801561181d57506008548454600160a060020a03908116911614155b801561183957508354601254600160a060020a03908116911614155b801561185557506003548454600160a060020a03908116911614155b1561188b5760018401805430600160a060020a031660009081526005602052604090208054919091019055546006805490910190555b611663875b6000600060005082815481101561000257908052600e02600080516020612a36833981519152018150600481015490915060ff16156118d757600d80546006830154900390555b600401805460ff1916905550565b15156118f45761190087611890565b6001915061193161047f565b604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050505061169e565b6001850154111561194157600091505b50600a8301546009840154865191019060049010801590611986575085600081518110156100025790602001015160f860020a900460f860020a02606860f860020a02145b80156119b6575085600181518110156100025790602001015160f860020a900460f860020a02603760f860020a02145b80156119e6575085600281518110156100025790602001015160f860020a900460f860020a0260ff60f860020a02145b8015611a16575085600381518110156100025790602001015160f860020a900460f860020a02601e60f860020a02145b8015611a45575030600160a060020a0316600090815260056020526040902054611a4290611a5d61047f565b81105b15611a4f57600091505b6001840154611a8090611a5f565b015b30600160a060020a03166000908152600560205260408120546129a961047f565b8110611ad457604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050501515611abc57610002565b4260025560165460059004811115611ad45760056001555b6001840154611ae290611a5f565b8110158015611af85750600a8401546009850154115b8015611b015750815b1561188b578360000160009054906101000a9004600160a060020a0316600160a060020a0316846001016000505487604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611b7d5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f19250505015156117bd57610002565b611baa336105ec565b60001415611bb757610002565b60008054889081101561000257508052600e87027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566810154600080516020612a36833981519152919091019450421080611c1957506003840154622398800142115b80611c3257508354600160a060020a0390811690871614155b80611c425750600784015460ff16155b80611c68575033600160a060020a03166000908152600b8501602052604090205460ff16155b80611c9c575033600160a060020a03166000908152600b60205260409020548714801590611c9c5750604060009081205414155b15611ca657610002565b600884018054600090811015610002579081526020812060030154600160a060020a03161415611e1257611efc86604051600090600160a060020a038316907f9046fefd66f538ab35263248a44217dcb70e2eb2cd136629e141b8b8f9f03b60908390a260408051600e547fe2faf044000000000000000000000000000000000000000000000000000000008252600160a060020a03858116600484015260248301859052604483018590526223988042016064840152925192169163e2faf04491608480820192602092909190829003018187876161da5a03f1156100025750506040515191506106069050565b6008850180546000908110156100025781815260208082209390935530600160a060020a031681526005909252604082205481549092908110156100025790815260208120905060020155601654600885018054600090811015610002579081526020812090506001015560048401805461ff0019166101001790555b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090505433600160a060020a031660009081526014602052604081205460088801805493909102939093049550908110156100025790815260208120905060030154604080517fbaac530000000000000000000000000000000000000000000000000000000000815233600160a060020a0390811660048301529151929091169163baac53009186916024808301926020929190829003018185886185025a03f11561000257505060405151600014159150611f78905057610002565b60088501805460009081101561000257818152602081206003018054600160a060020a03191690931790925580549091908110156100025790815260208120905060030154600160a060020a031660001415611f5757610002565b600d5430600160a060020a0316311015611f7057610002565b611d9561047f565b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090506002015433600160a060020a0390811660009081526014602090815260408083205430909416835260058083528184205460099093529083205460088b018054969095029690960497509487020494508593929091908290811015610002575260208120815060030154600160a060020a0390811682526020828101939093526040918201600090812080549095019094553016835260059091529020548290101561205357610002565b30600160a060020a031660009081526005602052604081208054849003905560088501805483926009929091829081101561000257508152602080822060030154600160a060020a039081168352929052604080822080549094019093553090911681522054819010156120c657610002565b30600160a060020a0390811660009081526009602090815260408083208054869003905533909316808352601482528383205484519081529351929390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a36121383361086c565b5033600160a060020a03166000908152601460209081526040808320805460168054919091039055839055600a9091528120556001945061169e565b30600160a060020a0390811660008181526005602090815260408083208054958716808552828520805490970190965584845283905560099091528082208054948352908220805490940190935590815290555b50565b604051600160a060020a0382811691309091163190600081818185876185025a03f192505050151561217457610002565b33600160a060020a03818116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f028352935197995091969195929092169363d2cc718f936004848101949193929183900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a03168152602001908152602001600020600050540204101561229d57610002565b600160a060020a03338116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f02835293519296909593169363d2cc718f93600483810194929383900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a0316815260200190815260200160002060005054020403905083156123ec57600860009054906101000a9004600160a060020a0316600160a060020a0316630221038a83600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a031660048201526024810186905290516044808301935060209282900301816000876161da5a03f115610002575050604051511515905061245457610002565b6040805160085460e160020a63011081c5028252600160a060020a038581166004840152602483018590529251921691630221038a9160448082019260209290919082900301816000876161da5a03f115610002575050604051511515905061245457610002565b600160a060020a03331660009081526009602052604090208054909101905550600192915050565b6109803361086c565b155b80156124a257506124a23384845b6000600061293a856105ec565b80156124be57506124be83836000600034111561261c57610002565b15610b9f5750600161033f565b15156124d657610002565b6124e08383610719565b905061033f565b155b80156124fb57506124fb848484612495565b80156125185750612518848484600060003411156126c157610002565b15610b9f57506001612528565b90505b9392505050565b151561253a57610002565b61252584848461041b565b30600160a060020a031633600160a060020a031614158061258a575030600160a060020a031660009081526005602052604090205460649061258561047f565b010481115b1561259457610002565b600c55565b600354600160a060020a0390811633909116146125b557610002565b600160a060020a038316600081815260046020908152604091829020805460ff191686179055815185815291517f73ad2a153c8b67991df9459024950b318a609782cee8c7eeda47b905f9baa91f9281900390910190a250600161033f565b506000610983565b33600160a060020a03166000908152601460205260409020548290108015906126455750600082115b156126b957600160a060020a03338116600081815260146020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161033f565b50600061033f565b600160a060020a03841660009081526014602052604090205482901080159061270a5750601560209081526040600081812033600160a060020a03168252909252902054829010155b80156127165750600082115b156127a457600160a060020a03838116600081815260146020908152604080832080548801905588851680845281842080548990039055601583528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001612528565b506000612528565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f11561000257505060405151905061281a866105ec565b0204101561282757610002565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f115610002575050604051519050612895866105ec565b0204039050600760009054906101000a9004600160a060020a0316600160a060020a0316630221038a84836040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061291357610002565b600160a060020a0383166000908152600a6020526040902080548201905560019150610b99565b600160a060020a0386166000908152600a602052604090205480850291909104915081111561296857610002565b600160a060020a038581166000908152600a60205260408082208054859003905591861681522080548201905560019150509392505050565b506000610606565b0160030260166000505483020460016000505460166000505404019050610606565b600160a060020a0383166000908152600b6020526040812054815481101561000257818052600e02600080516020612a368339815191520190506003810154909150421115610b9457600160a060020a0383166000908152600b602052604081208190559150610b9956290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
-
-// Proxy contract to whitelist interaction with:
-//
-// contract Proxy {
-// address _dao;
-//
-// function Proxy(address dao) {
-// _dao = dao;
-// }
-// function() {
-// if (msg.value > 0) {
-// _dao.call.value(msg.value)();
-// } else {
-// _dao.call(bytes4(sha3("refund()")));
-// }
-// }
-// }
-var proxyDeployCode = common.FromHex("606060405260405160208060dd83395060806040525160008054600160a060020a031916821790555060a98060346000396000f360606040523615600a575b60486000341115604a576000805473ffffffffffffffffffffffffffffffffffffffff1690349060609081818185876185025a03f1925050505060a7565b005b600080547f590e1ae300000000000000000000000000000000000000000000000000000000606090815273ffffffffffffffffffffffffffffffffffffffff9091169163590e1ae3916064919060048183876161da5a03f1505050505b56")
-
-// Tests that unannimous votes are handled correctly (i.e. the simple case).
-func TestDAOForkUnanimousFail(t *testing.T) { testDAOUnanimousFork(t, false) }
-func TestDAOForkUnanimousPass(t *testing.T) { testDAOUnanimousFork(t, true) }
-
-func testDAOUnanimousFork(t *testing.T, pass bool) {
- // Reduce the test size to avoid wasting too much time
- defer func(old uint64) { ruptureBlock = old }(ruptureBlock)
- ruptureBlock = 128
-
- defer func(old int) { ruptureCacheLimit = old }(ruptureCacheLimit)
- ruptureCacheLimit = 256
-
- // Depending on the tested outcome, set a high or a low gas limit
- defer func(old *big.Int) { params.GenesisGasLimit = old }(params.GenesisGasLimit)
- defer func(old *big.Int) { params.TargetGasLimit = old }(params.TargetGasLimit)
- if pass {
- params.GenesisGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(-10))
- params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(-10))
- } else {
- params.GenesisGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(10))
- params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(10))
- }
- // Create a test chain with a DAO instance deployed and attempt to transact with it
- var (
- slockit, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
- black, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- white, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
- slockitAddr = crypto.PubkeyToAddress(slockit.PublicKey)
- blackAddr = crypto.PubkeyToAddress(black.PublicKey)
- whiteAddr = crypto.PubkeyToAddress(white.PublicKey)
- creatorAddr common.Address
- daoAddr common.Address
- blackProxy common.Address
- whiteProxy common.Address
- db, _ = ethdb.NewMemDatabase()
- )
- genesis := WriteGenesisBlockForTesting(db,
- GenesisAccount{slockitAddr, big.NewInt(1000000)},
- GenesisAccount{blackAddr, big.NewInt(1000000)},
- GenesisAccount{whiteAddr, big.NewInt(1000000)},
- )
- length := int(ruptureBlock) + 2*ruptureCacheLimit
- chain, _ := GenerateChain(genesis, db, length, func(i int, gen *BlockGen) {
- switch i {
- case 0:
- // Deploy the DAO creator in the first block
- tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(1), params.GenesisGasLimit, new(big.Int), creatorDeployCode).SignECDSA(slockit)
- gen.AddTx(tx)
- creatorAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
-
- case 1:
- // Deploy the DAO in the second block
- var args []byte
- args = append(args, common.LeftPadBytes(slockitAddr.Bytes(), 32)...) // curator
- args = append(args, common.LeftPadBytes(creatorAddr.Bytes(), 32)...) // daoCreator
- args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // proposalDeposit
- args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // minTokensToCreate
- args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // closingTime
- args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // privateCreation
-
- tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(0), params.GenesisGasLimit, new(big.Int), append(daoDeployCode, args...)).SignECDSA(slockit)
- gen.AddTx(tx)
- daoAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
-
- case 2:
- // Deploy the black and white hat proxy contracts
- tx, _ := types.NewContractCreation(gen.TxNonce(blackAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(black)
- gen.AddTx(tx)
- blackProxy = crypto.CreateAddress(blackAddr, tx.Nonce())
-
- tx, _ = types.NewContractCreation(gen.TxNonce(whiteAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(white)
- gen.AddTx(tx)
- whiteProxy = crypto.CreateAddress(whiteAddr, tx.Nonce())
-
- ruptureWhitelist[whiteProxy] = true
-
- case 3:
- // Fund the DAO with some funds, but not enough for successful creation
- tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(white)
- gen.AddTx(tx)
-
- tx, _ = types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(black)
- gen.AddTx(tx)
-
- case length - 2:
- // DAO creation failed by this time and forks are in effect; try retrieving whitelisted funds
- tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(white)
- gen.AddTx(tx)
-
- case length - 1:
- // DAO creation failed by this time and forks are in effect; try retrieving blacklisted funds
- tx, _ := types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(black)
- gen.AddTx(tx)
+// Tests that DAO-fork enabled clients can properly filter out fork-commencing
+// blocks based on their extradata fields.
+func TestDAOForkRangeExtradata(t *testing.T) {
+ forkBlock := big.NewInt(32)
+
+ // Generate a common prefix for both pro-forkers and non-forkers
+ db, _ := ethdb.NewMemDatabase()
+ genesis := WriteGenesisBlockForTesting(db)
+ prefix, _ := GenerateChain(nil, genesis, db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
+
+ // Create the concurrent, conflicting two nodes
+ proDb, _ := ethdb.NewMemDatabase()
+ WriteGenesisBlockForTesting(proDb)
+ proConf := &ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
+ proBc, _ := NewBlockChain(proDb, proConf, new(FakePow), new(event.TypeMux))
+
+ conDb, _ := ethdb.NewMemDatabase()
+ WriteGenesisBlockForTesting(conDb)
+ conConf := &ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
+ conBc, _ := NewBlockChain(conDb, conConf, new(FakePow), new(event.TypeMux))
+
+ if _, err := proBc.InsertChain(prefix); err != nil {
+ t.Fatalf("pro-fork: failed to import chain prefix: %v", err)
+ }
+ if _, err := conBc.InsertChain(prefix); err != nil {
+ t.Fatalf("con-fork: failed to import chain prefix: %v", err)
+ }
+ // Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
+ for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
+ // Create a pro-fork block, and try to feed into the no-fork chain
+ db, _ = ethdb.NewMemDatabase()
+ WriteGenesisBlockForTesting(db)
+ bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux))
+
+ blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
+ for j := 0; j < len(blocks)/2; j++ {
+ blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
}
- })
- defer delete(ruptureWhitelist, whiteProxy) // This can't be done in the aboge generator sadly
-
- // Import the chain. This runs all block validation rules.
- bc, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, new(event.TypeMux))
- n, err := bc.InsertChain(chain)
-
- // The chain should either succeed (no votes), or fail on the black address
- if !pass {
- if err != nil {
- t.Errorf("block %d rejected on non forked chain: %v", n, err)
+ if _, err := bc.InsertChain(blocks); err != nil {
+ t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
}
- } else {
- if n != length-1 || err != blockedCodeHashErr {
- t.Errorf("failure mismatch: have %d:%v, want %d:%v", n, err, length-1, blockedCodeHashErr)
+ blocks, _ = GenerateChain(proConf, conBc.CurrentBlock(), db, 1, func(i int, gen *BlockGen) {})
+ if _, err := conBc.InsertChain(blocks); err == nil {
+ t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0])
}
- }
- // Verify account balances to make sure transactions executd properly, not just the test is bugged
- state, _ := bc.State()
- if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
- t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
- }
- if !pass {
- if state.GetBalance(blackProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund (fork refused)
- t.Errorf("black proxy balance mismatch: have %v, want 3", state.GetBalance(blackProxy))
- }
- if state.GetBalance(daoAddr).Cmp(big.NewInt(0)) != 0 { // all refunded (fork refused)
- t.Errorf("dao balance mismatch: have %v, want 0", state.GetBalance(daoAddr))
+ // Create a proper no-fork block for the contra-forker
+ blocks, _ = GenerateChain(conConf, conBc.CurrentBlock(), db, 1, func(i int, gen *BlockGen) {})
+ if _, err := conBc.InsertChain(blocks); err != nil {
+ t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
}
- } else {
- if state.GetBalance(blackProxy).Cmp(big.NewInt(1)) != 0 { // 1 init (refund refused due to fork)
- t.Errorf("black proxy balance mismatch: have %v, want 1", state.GetBalance(blackProxy))
+ // Create a no-fork block, and try to feed into the pro-fork chain
+ db, _ = ethdb.NewMemDatabase()
+ WriteGenesisBlockForTesting(db)
+ bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux))
+
+ blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
+ for j := 0; j < len(blocks)/2; j++ {
+ blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
}
- if state.GetBalance(daoAddr).Cmp(big.NewInt(2)) != 0 { // 2 from black (refund refused due to fork)
- t.Errorf("dao balance mismatch: have %v, want 2", state.GetBalance(daoAddr))
+ if _, err := bc.InsertChain(blocks); err != nil {
+ t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
}
- }
-}
-
-// Tests the unique corner case where miners don't cleanly decide on the outcome
-// of the vote, rather
-func TestDAOForkRaceyResolution(t *testing.T) {
- // Reduce the test size to avoid wasting too much time
- defer func(old uint64) { ruptureBlock = old }(ruptureBlock)
- ruptureBlock = 128
-
- defer func(old int) { ruptureCacheLimit = old }(ruptureCacheLimit)
- ruptureCacheLimit = 256
-
- // Set up the parameters of the test chain
- var (
- slockit, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
- black, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- white, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
- slockitAddr = crypto.PubkeyToAddress(slockit.PublicKey)
- blackAddr = crypto.PubkeyToAddress(black.PublicKey)
- whiteAddr = crypto.PubkeyToAddress(white.PublicKey)
- creatorAddr common.Address
- daoAddr common.Address
- blackProxy common.Address
- whiteProxy common.Address
- db, _ = ethdb.NewMemDatabase()
- )
- defer func(old *big.Int) { params.GenesisGasLimit = old }(params.GenesisGasLimit)
- params.GenesisGasLimit = ruptureThreshold
-
- genesis := WriteGenesisBlockForTesting(db,
- GenesisAccount{slockitAddr, big.NewInt(1000000)},
- GenesisAccount{blackAddr, big.NewInt(1000000)},
- GenesisAccount{whiteAddr, big.NewInt(1000000)},
- )
- // Generate a chain where the outcome for the fork proposal is pass
- defer func(old *big.Int) { params.TargetGasLimit = old }(params.TargetGasLimit)
- params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(-10))
-
- length := int(ruptureBlock) + 2*ruptureCacheLimit
- chainPass, _ := GenerateChain(genesis, db, length, func(i int, gen *BlockGen) {
- switch i {
- case 0:
- // Deploy the DAO creator in the first block
- tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(1), big.NewInt(3999980), new(big.Int), creatorDeployCode).SignECDSA(slockit)
- gen.AddTx(tx)
- creatorAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
-
- case 1:
- // Deploy the DAO in the second block
- var args []byte
- args = append(args, common.LeftPadBytes(slockitAddr.Bytes(), 32)...) // curator
- args = append(args, common.LeftPadBytes(creatorAddr.Bytes(), 32)...) // daoCreator
- args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // proposalDeposit
- args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // minTokensToCreate
- args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // closingTime
- args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // privateCreation
-
- tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(0), big.NewInt(3999980), new(big.Int), append(daoDeployCode, args...)).SignECDSA(slockit)
- gen.AddTx(tx)
- daoAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
-
- case 2:
- // Deploy the black and white hat proxy contracts
- tx, _ := types.NewContractCreation(gen.TxNonce(blackAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(black)
- gen.AddTx(tx)
- blackProxy = crypto.CreateAddress(blackAddr, tx.Nonce())
-
- tx, _ = types.NewContractCreation(gen.TxNonce(whiteAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(white)
- gen.AddTx(tx)
- whiteProxy = crypto.CreateAddress(whiteAddr, tx.Nonce())
-
- ruptureWhitelist[whiteProxy] = true
-
- case 3:
- // Fund the DAO with some funds, but not enough for successful creation
- tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(white)
- gen.AddTx(tx)
-
- tx, _ = types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(black)
- gen.AddTx(tx)
-
- case length - 2:
- // DAO creation failed by this time and forks are in effect; try retrieving whitelisted funds
- tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(white)
- gen.AddTx(tx)
-
- case length - 1:
- // DAO creation failed by this time and forks are in effect; try retrieving blacklisted funds
- tx, _ := types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(black)
- gen.AddTx(tx)
+ blocks, _ = GenerateChain(conConf, proBc.CurrentBlock(), db, 1, func(i int, gen *BlockGen) {})
+ if _, err := proBc.InsertChain(blocks); err == nil {
+ t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0])
}
- })
- // Generate a chain to work around the last bad block above
- chainPassCont, _ := GenerateChain(chainPass[len(chainPass)-2], db, 3, func(i int, gen *BlockGen) {})
-
- // Generate a fork of the chain where the outcome of the fork proposal is fail
- params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(10))
- chainFail, _ := GenerateChain(chainPass[4], db, length-4, func(i int, gen *BlockGen) { // Start fro block #4 to reuse previous creation code
- switch i {
- case length - 4 - 2:
- // DAO creation failed by this time and forks are in effect; try retrieving whitelisted funds
- tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(white)
- gen.AddTx(tx)
-
- case length - 4 - 1:
- // DAO creation failed by this time and forks are in effect; try retrieving blacklisted funds
- tx, _ := types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(black)
- gen.AddTx(tx)
+ // Create a proper pro-fork block for the pro-forker
+ blocks, _ = GenerateChain(proConf, proBc.CurrentBlock(), db, 1, func(i int, gen *BlockGen) {})
+ if _, err := proBc.InsertChain(blocks); err != nil {
+ t.Fatalf("pro-fork chain didn't accepted pro-fork block: %v", err)
}
- })
- defer delete(ruptureWhitelist, whiteProxy) // This can't be done in the aboge generator sadly
-
- // Import the chain where the vote passed
- bc, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, new(event.TypeMux))
-
- if n, err := bc.InsertChain(chainPass); n != length-1 || err != blockedCodeHashErr {
- t.Fatalf("forked chain error mismatch: have %v/%v, want %v/%v", n, err, length-1, blockedCodeHashErr)
- }
- state, _ := bc.State()
- if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
- t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
- }
- if state.GetBalance(blackProxy).Cmp(big.NewInt(1)) != 0 { // 1 init (no refund on the passing chain)
- t.Errorf("black proxy balance mismatch: have %v, want 1", state.GetBalance(blackProxy))
- }
- if state.GetBalance(daoAddr).Cmp(big.NewInt(2)) != 0 { // 2 from black (refund refused due to fork)
- t.Errorf("dao balance mismatch: have %v, want 2", state.GetBalance(daoAddr))
- }
- // Import the chain where the vote failed (longer than the passing with 1 block (dropped from the passing))
- if _, err := bc.InsertChain(chainFail); err != nil {
- t.Fatalf("failed to import non-forked chain: %v", err)
- }
- state, _ = bc.State()
- if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
- t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
}
- if state.GetBalance(blackProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund (fork refused)
- t.Errorf("black proxy balance mismatch: have %v, want 3", state.GetBalance(blackProxy))
- }
- if state.GetBalance(daoAddr).Cmp(big.NewInt(0)) != 0 { // all refunded (fork refused)
- t.Errorf("dao balance mismatch: have %v, want 0", state.GetBalance(daoAddr))
- }
- // Try to import a bad block on theforked chain to make sure no cache screwes up
- if _, err := bc.InsertChain(chainPass[len(chainPass)-2:]); err != blockedCodeHashErr {
- t.Fatalf("forked chain error mismatch: have %v, want %v", err, blockedCodeHashErr)
- }
- // The balances must still be that of the failed chain
- state, _ = bc.State()
- if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
- t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
- }
- if state.GetBalance(blackProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund (fork refused)
- t.Errorf("black proxy balance mismatch: have %v, want 3", state.GetBalance(blackProxy))
+ // Verify that contra-forkers accept pro-fork extra-datas after forking finishes
+ db, _ = ethdb.NewMemDatabase()
+ WriteGenesisBlockForTesting(db)
+ bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux))
+
+ blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
+ for j := 0; j < len(blocks)/2; j++ {
+ blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
}
- if state.GetBalance(daoAddr).Cmp(big.NewInt(0)) != 0 { // all refunded (fork refused)
- t.Errorf("dao balance mismatch: have %v, want 0", state.GetBalance(daoAddr))
+ if _, err := bc.InsertChain(blocks); err != nil {
+ t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
}
- // Overrule the passing chain with fresh blocks
- if _, err := bc.InsertChain(chainPassCont); err != nil {
- t.Fatalf("failed to import forked chain continuation: %v", err)
+ blocks, _ = GenerateChain(proConf, conBc.CurrentBlock(), db, 1, func(i int, gen *BlockGen) {})
+ if _, err := conBc.InsertChain(blocks); err != nil {
+ t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
}
- // Balances must be switched over to the forked version
- state, _ = bc.State()
- if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
- t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
+ // Verify that pro-forkers accept contra-fork extra-datas after forking finishes
+ db, _ = ethdb.NewMemDatabase()
+ WriteGenesisBlockForTesting(db)
+ bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux))
+
+ blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
+ for j := 0; j < len(blocks)/2; j++ {
+ blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
}
- if state.GetBalance(blackProxy).Cmp(big.NewInt(1)) != 0 { // 1 init (no refund on the passing chain)
- t.Errorf("black proxy balance mismatch: have %v, want 1", state.GetBalance(blackProxy))
+ if _, err := bc.InsertChain(blocks); err != nil {
+ t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
}
- if state.GetBalance(daoAddr).Cmp(big.NewInt(2)) != 0 { // 2 from black (refund refused due to fork)
- t.Errorf("dao balance mismatch: have %v, want 2", state.GetBalance(daoAddr))
+ blocks, _ = GenerateChain(conConf, proBc.CurrentBlock(), db, 1, func(i int, gen *BlockGen) {})
+ if _, err := proBc.InsertChain(blocks); err != nil {
+ t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err)
}
}
diff --git a/core/database_util_test.go b/core/database_util_test.go
index 6c19f78c8..280270ac8 100644
--- a/core/database_util_test.go
+++ b/core/database_util_test.go
@@ -561,7 +561,7 @@ func TestMipmapChain(t *testing.T) {
defer db.Close()
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr, big.NewInt(1000000)})
- chain, receipts := GenerateChain(genesis, db, 1010, func(i int, gen *BlockGen) {
+ chain, receipts := GenerateChain(nil, genesis, db, 1010, func(i int, gen *BlockGen) {
var receipts types.Receipts
switch i {
case 1:
diff --git a/core/execution.go b/core/execution.go
index d2008bc3e..82143443c 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -84,10 +84,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
address = &addr
createAccount = true
}
- // Mark all contracts doing outbound value transfers to allow DAO filtering.
- if value.Cmp(common.Big0) > 0 {
- env.MarkCodeHash(env.Db().GetCodeHash(caller.Address()))
- }
+
snapshotPreTransfer := env.MakeSnapshot()
var (
from = env.Db().GetAccount(caller.Address())
@@ -146,10 +143,7 @@ func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toA
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, vm.DepthError
}
- // Mark all contracts doing outbound value transfers to allow DAO filtering.
- if value.Cmp(common.Big0) > 0 {
- env.MarkCodeHash(env.Db().GetCodeHash(caller.Address()))
- }
+
snapshot := env.MakeSnapshot()
var to vm.Account
diff --git a/core/state/statedb.go b/core/state/statedb.go
index be1960f9e..3e25e0c16 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -161,14 +161,6 @@ func (self *StateDB) GetCode(addr common.Address) []byte {
return nil
}
-func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
- stateObject := self.GetStateObject(addr)
- if stateObject != nil {
- return common.BytesToHash(stateObject.codeHash)
- }
- return common.Hash{}
-}
-
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
stateObject := self.GetStateObject(a)
if stateObject != nil {
diff --git a/core/state_processor.go b/core/state_processor.go
index 6e8bb0144..fd8e9762e 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -17,10 +17,8 @@
package core
import (
- "errors"
"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/core/vm"
@@ -30,25 +28,8 @@ import (
)
var (
- big8 = big.NewInt(8)
- big32 = big.NewInt(32)
- blockedCodeHashErr = errors.New("core: blocked code-hash found during execution")
-
- // DAO attack chain rupture mechanism
- DAOSoftFork bool // Flag whether to vote for DAO rupture
-
- ruptureBlock = uint64(1800000) // Block number of the voted soft fork
- ruptureTarget = big.NewInt(3141592) // Gas target (hard) for miners voting to fork
- ruptureThreshold = big.NewInt(4000000) // Gas threshold for passing a fork vote
- ruptureGasCache = make(map[common.Hash]*big.Int) // Amount of gas in the point of rupture
- ruptureCodeHashes = map[common.Hash]struct{}{
- common.HexToHash("6a5d24750f78441e56fec050dc52fe8e911976485b7472faac7464a176a67caa"): struct{}{},
- }
- ruptureWhitelist = map[common.Address]bool{
- common.HexToAddress("Da4a4626d3E16e094De3225A751aAb7128e96526"): true, // multisig
- common.HexToAddress("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334"): true, // attack contract
- }
- ruptureCacheLimit = 30000 // 1 epoch, 0.5 per possible fork
+ big8 = big.NewInt(8)
+ big32 = big.NewInt(32)
)
// StateProcessor is a basic Processor, which takes care of transitioning
@@ -84,7 +65,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
allLogs vm.Logs
gp = new(GasPool).AddGas(block.GasLimit())
)
-
+ // Mutate the the block and state according to any hard-fork specs
+ if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
+ ApplyDAOHardFork(statedb)
+ }
+ // Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
statedb.StartRecord(tx.Hash(), block.Hash(), i)
receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
@@ -105,56 +90,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// ApplyTransactions returns the generated receipts and vm logs during the
// execution of the state transition phase.
func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
- env := NewEnv(statedb, config, bc, tx, header, cfg)
- _, gas, err := ApplyMessage(env, tx, gp)
+ _, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), tx, gp)
if err != nil {
return nil, nil, nil, err
}
- // Check whether the DAO needs to be blocked or not
- if bc != nil { // Test chain maker uses nil to construct the potential chain
- blockRuptureCodes := false
-
- if number := header.Number.Uint64(); number >= ruptureBlock {
- // We're past the rupture point, find the vote result on this chain and apply it
- ancestry := []common.Hash{header.Hash(), header.ParentHash}
- for _, ok := ruptureGasCache[ancestry[len(ancestry)-1]]; !ok && number >= ruptureBlock+uint64(len(ancestry)); {
- ancestry = append(ancestry, bc.GetHeaderByHash(ancestry[len(ancestry)-1]).ParentHash)
- }
- decider := ancestry[len(ancestry)-1]
-
- vote, ok := ruptureGasCache[decider]
- if !ok {
- // We've reached the rupture point, retrieve the vote
- vote = bc.GetHeaderByHash(decider).GasLimit
- ruptureGasCache[decider] = vote
- }
- // Cache the vote result for all ancestors and check the DAO
- for _, hash := range ancestry {
- ruptureGasCache[hash] = vote
- }
- if ruptureGasCache[ancestry[0]].Cmp(ruptureThreshold) <= 0 {
- blockRuptureCodes = true
- }
- // Make sure we don't OOM long run due to too many votes caching up
- for len(ruptureGasCache) > ruptureCacheLimit {
- for hash, _ := range ruptureGasCache {
- delete(ruptureGasCache, hash)
- break
- }
- }
- }
- // Verify if the DAO soft fork kicks in
- if blockRuptureCodes {
- if recipient := tx.To(); recipient == nil || !ruptureWhitelist[*recipient] {
- for hash, _ := range env.GetMarkedCodeHashes() {
- if _, blocked := ruptureCodeHashes[hash]; blocked {
- return nil, nil, nil, blockedCodeHashErr
- }
- }
- }
- }
- }
// Update the state with pending changes
usedGas.Add(usedGas, gas)
receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas)
diff --git a/core/state_transition.go b/core/state_transition.go
index c8160424b..9e6b2f567 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -71,6 +71,7 @@ type Message interface {
Value() *big.Int
Nonce() uint64
+ CheckNonce() bool
Data() []byte
}
@@ -208,8 +209,10 @@ func (self *StateTransition) preCheck() (err error) {
}
// Make sure this transaction's nonce is correct
- if n := self.state.GetNonce(sender.Address()); n != msg.Nonce() {
- return NonceError(msg.Nonce(), n)
+ if msg.CheckNonce() {
+ if n := self.state.GetNonce(sender.Address()); n != msg.Nonce() {
+ return NonceError(msg.Nonce(), n)
+ }
}
// Pre-pay gas
diff --git a/core/types/transaction.go b/core/types/transaction.go
index b99d3a716..c71c98aa7 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -113,6 +113,7 @@ func (tx *Transaction) Gas() *big.Int { return new(big.Int).Set(tx.data.Gas
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) }
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
+func (tx *Transaction) CheckNonce() bool { return true }
func (tx *Transaction) To() *common.Address {
if tx.data.Recipient == nil {
diff --git a/core/vm/environment.go b/core/vm/environment.go
index 37817be9e..664887454 100644
--- a/core/vm/environment.go
+++ b/core/vm/environment.go
@@ -73,8 +73,8 @@ type Environment interface {
DelegateCall(me ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error)
// Create a new contract
Create(me ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error)
- // Mark the code hash that was executed
- MarkCodeHash(hash common.Hash)
+
+ StructLogs() []StructLog
}
// Vm is the basic interface for an implementation of the EVM.
@@ -98,7 +98,6 @@ type Database interface {
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
- GetCodeHash(common.Address) common.Hash
AddRefund(*big.Int)
GetRefund() *big.Int
diff --git a/core/vm/jit.go b/core/vm/jit.go
index f56d7c1af..e2374df42 100644
--- a/core/vm/jit.go
+++ b/core/vm/jit.go
@@ -421,7 +421,7 @@ func jitCalculateGasAndSize(env Environment, contract *Contract, instr instructi
g = params.SstoreClearGas
} else {
- g = params.SstoreClearGas
+ g = params.SstoreResetGas
}
gas.Set(g)
case SUICIDE:
diff --git a/core/vm/jit_test.go b/core/vm/jit_test.go
index a9ddd48a5..403c15a8d 100644
--- a/core/vm/jit_test.go
+++ b/core/vm/jit_test.go
@@ -175,11 +175,10 @@ func NewEnv(noJit, forceJit bool) *Env {
return env
}
-func (self *Env) MarkCodeHash(common.Hash) {}
-func (self *Env) RuleSet() RuleSet { return ruleSet{new(big.Int)} }
-func (self *Env) Vm() Vm { return self.evm }
-func (self *Env) Origin() common.Address { return common.Address{} }
-func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
+func (self *Env) RuleSet() RuleSet { return ruleSet{new(big.Int)} }
+func (self *Env) Vm() Vm { return self.evm }
+func (self *Env) Origin() common.Address { return common.Address{} }
+func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
func (self *Env) AddStructLog(log StructLog) {
}
func (self *Env) StructLogs() []StructLog {
diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go
index 94adb0287..d8c98e545 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/runtime/env.go
@@ -79,8 +79,6 @@ func (self *Env) AddStructLog(log vm.StructLog) {
self.logs = append(self.logs, log)
}
-func (self *Env) MarkCodeHash(hash common.Hash) {}
-
func (self *Env) RuleSet() vm.RuleSet { return self.ruleSet }
func (self *Env) Vm() vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return self.origin }
diff --git a/core/vm/vm.go b/core/vm/vm.go
index 0f93715d6..52e782b23 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -306,7 +306,7 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
g = params.SstoreClearGas
} else {
// non 0 => non 0 (or 0 => 0)
- g = params.SstoreClearGas
+ g = params.SstoreResetGas
}
gas.Set(g)
case SUICIDE:
diff --git a/core/vm_env.go b/core/vm_env.go
index a034c428e..599672382 100644
--- a/core/vm_env.go
+++ b/core/vm_env.go
@@ -47,8 +47,6 @@ type VMEnv struct {
depth int // Current execution depth
msg Message // Message appliod
- codeHashes map[common.Hash]struct{} // code hashes collected during execution
-
header *types.Header // Header information
chain *BlockChain // Blockchain handle
logs []vm.StructLog // Logs for the custom structured logger
@@ -58,7 +56,6 @@ type VMEnv struct {
func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, msg Message, header *types.Header, cfg vm.Config) *VMEnv {
env := &VMEnv{
chainConfig: chainConfig,
- codeHashes: make(map[common.Hash]struct{}),
chain: chain,
state: state,
header: header,
@@ -75,9 +72,6 @@ func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, m
return env
}
-func (self *VMEnv) MarkCodeHash(hash common.Hash) { self.codeHashes[hash] = struct{}{} }
-func (self *VMEnv) GetMarkedCodeHashes() map[common.Hash]struct{} { return self.codeHashes }
-
func (self *VMEnv) RuleSet() vm.RuleSet { return self.chainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
diff --git a/eth/api.go b/eth/api.go
index 9f5f2e677..3b7abb69a 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -18,8 +18,6 @@ package eth
import (
"bytes"
- "encoding/hex"
- "encoding/json"
"errors"
"fmt"
"io"
@@ -27,111 +25,30 @@ import (
"math/big"
"os"
"runtime"
- "strings"
- "sync"
- "time"
"github.com/ethereum/ethash"
- "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/miner"
- "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/syndtr/goleveldb/leveldb"
- "golang.org/x/net/context"
)
-const defaultGas = uint64(90000)
-
-// blockByNumber is a commonly used helper function which retrieves and returns
-// the block for the given block number, capable of handling two special blocks:
-// rpc.LatestBlockNumber and rpc.PendingBlockNumber. It returns nil when no block
-// could be found.
-func blockByNumber(m *miner.Miner, bc *core.BlockChain, blockNr rpc.BlockNumber) *types.Block {
- // Pending block is only known by the miner
- if blockNr == rpc.PendingBlockNumber {
- block, _ := m.Pending()
- return block
- }
- // Otherwise resolve and return the block
- if blockNr == rpc.LatestBlockNumber {
- return bc.CurrentBlock()
- }
- return bc.GetBlockByNumber(uint64(blockNr))
-}
-
-// stateAndBlockByNumber is a commonly used helper function which retrieves and
-// returns the state and containing block for the given block number, capable of
-// handling two special states: rpc.LatestBlockNumber and rpc.PendingBlockNumber.
-// It returns nil when no block or state could be found.
-func stateAndBlockByNumber(m *miner.Miner, bc *core.BlockChain, blockNr rpc.BlockNumber, chainDb ethdb.Database) (*state.StateDB, *types.Block, error) {
- // Pending state is only known by the miner
- if blockNr == rpc.PendingBlockNumber {
- block, state := m.Pending()
- return state, block, nil
- }
- // Otherwise resolve the block number and return its state
- block := blockByNumber(m, bc, blockNr)
- if block == nil {
- return nil, nil, nil
- }
- stateDb, err := state.New(block.Root(), chainDb)
- return stateDb, block, err
-}
-
-// PublicEthereumAPI provides an API to access Ethereum related information.
-// It offers only methods that operate on public data that is freely available to anyone.
+// PublicEthereumAPI provides an API to access Ethereum full node-related
+// information.
type PublicEthereumAPI struct {
- e *Ethereum
- gpo *GasPriceOracle
+ e *Ethereum
}
-// NewPublicEthereumAPI creates a new Ethereum protocol API.
+// NewPublicEthereumAPI creates a new Etheruem protocol API for full nodes.
func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI {
- return &PublicEthereumAPI{
- e: e,
- gpo: e.gpo,
- }
-}
-
-// GasPrice returns a suggestion for a gas price.
-func (s *PublicEthereumAPI) GasPrice() *big.Int {
- return s.gpo.SuggestPrice()
-}
-
-// GetCompilers returns the collection of available smart contract compilers
-func (s *PublicEthereumAPI) GetCompilers() ([]string, error) {
- solc, err := s.e.Solc()
- if err == nil && solc != nil {
- return []string{"Solidity"}, nil
- }
-
- return []string{}, nil
-}
-
-// CompileSolidity compiles the given solidity source
-func (s *PublicEthereumAPI) CompileSolidity(source string) (map[string]*compiler.Contract, error) {
- solc, err := s.e.Solc()
- if err != nil {
- return nil, err
- }
-
- if solc == nil {
- return nil, errors.New("solc (solidity compiler) not found")
- }
-
- return solc.Compile(source)
+ return &PublicEthereumAPI{e}
}
// Etherbase is the address that mining rewards will be send to
@@ -144,40 +61,11 @@ func (s *PublicEthereumAPI) Coinbase() (common.Address, error) {
return s.Etherbase()
}
-// ProtocolVersion returns the current Ethereum protocol version this node supports
-func (s *PublicEthereumAPI) ProtocolVersion() *rpc.HexNumber {
- return rpc.NewHexNumber(s.e.EthVersion())
-}
-
// Hashrate returns the POW hashrate
func (s *PublicEthereumAPI) Hashrate() *rpc.HexNumber {
return rpc.NewHexNumber(s.e.Miner().HashRate())
}
-// Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not
-// yet received the latest block headers from its pears. In case it is synchronizing:
-// - startingBlock: block number this node started to synchronise from
-// - currentBlock: block number this node is currently importing
-// - highestBlock: block number of the highest block header this node has received from peers
-// - pulledStates: number of state entries processed until now
-// - knownStates: number of known state entries that still need to be pulled
-func (s *PublicEthereumAPI) Syncing() (interface{}, error) {
- origin, current, height, pulled, known := s.e.Downloader().Progress()
-
- // Return not syncing if the synchronisation already completed
- if current >= height {
- return false, nil
- }
- // Otherwise gather the block sync stats
- return map[string]interface{}{
- "startingBlock": rpc.NewHexNumber(origin),
- "currentBlock": rpc.NewHexNumber(current),
- "highestBlock": rpc.NewHexNumber(height),
- "pulledStates": rpc.NewHexNumber(pulled),
- "knownStates": rpc.NewHexNumber(known),
- }, nil
-}
-
// PublicMinerAPI provides an API to control the miner.
// It offers only methods that operate on data that pose no security risk when it is publicly accessible.
type PublicMinerAPI struct {
@@ -303,1197 +191,18 @@ func (s *PrivateMinerAPI) MakeDAG(blockNr rpc.BlockNumber) (bool, error) {
return true, nil
}
-// PublicTxPoolAPI offers and API for the transaction pool. It only operates on data that is non confidential.
-type PublicTxPoolAPI struct {
- e *Ethereum
-}
-
-// NewPublicTxPoolAPI creates a new tx pool service that gives information about the transaction pool.
-func NewPublicTxPoolAPI(e *Ethereum) *PublicTxPoolAPI {
- return &PublicTxPoolAPI{e}
-}
-
-// Content returns the transactions contained within the transaction pool.
-func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string][]*RPCTransaction {
- content := map[string]map[string]map[string][]*RPCTransaction{
- "pending": make(map[string]map[string][]*RPCTransaction),
- "queued": make(map[string]map[string][]*RPCTransaction),
- }
- pending, queue := s.e.TxPool().Content()
-
- // Flatten the pending transactions
- for account, batches := range pending {
- dump := make(map[string][]*RPCTransaction)
- for nonce, txs := range batches {
- nonce := fmt.Sprintf("%d", nonce)
- for _, tx := range txs {
- dump[nonce] = append(dump[nonce], newRPCPendingTransaction(tx))
- }
- }
- content["pending"][account.Hex()] = dump
- }
- // Flatten the queued transactions
- for account, batches := range queue {
- dump := make(map[string][]*RPCTransaction)
- for nonce, txs := range batches {
- nonce := fmt.Sprintf("%d", nonce)
- for _, tx := range txs {
- dump[nonce] = append(dump[nonce], newRPCPendingTransaction(tx))
- }
- }
- content["queued"][account.Hex()] = dump
- }
- return content
-}
-
-// Status returns the number of pending and queued transaction in the pool.
-func (s *PublicTxPoolAPI) Status() map[string]*rpc.HexNumber {
- pending, queue := s.e.TxPool().Stats()
- return map[string]*rpc.HexNumber{
- "pending": rpc.NewHexNumber(pending),
- "queued": rpc.NewHexNumber(queue),
- }
-}
-
-// Inspect retrieves the content of the transaction pool and flattens it into an
-// easily inspectable list.
-func (s *PublicTxPoolAPI) Inspect() map[string]map[string]map[string][]string {
- content := map[string]map[string]map[string][]string{
- "pending": make(map[string]map[string][]string),
- "queued": make(map[string]map[string][]string),
- }
- pending, queue := s.e.TxPool().Content()
-
- // Define a formatter to flatten a transaction into a string
- var format = func(tx *types.Transaction) string {
- if to := tx.To(); to != nil {
- return fmt.Sprintf("%s: %v wei + %v × %v gas", tx.To().Hex(), tx.Value(), tx.Gas(), tx.GasPrice())
- }
- return fmt.Sprintf("contract creation: %v wei + %v × %v gas", tx.Value(), tx.Gas(), tx.GasPrice())
- }
- // Flatten the pending transactions
- for account, batches := range pending {
- dump := make(map[string][]string)
- for nonce, txs := range batches {
- nonce := fmt.Sprintf("%d", nonce)
- for _, tx := range txs {
- dump[nonce] = append(dump[nonce], format(tx))
- }
- }
- content["pending"][account.Hex()] = dump
- }
- // Flatten the queued transactions
- for account, batches := range queue {
- dump := make(map[string][]string)
- for nonce, txs := range batches {
- nonce := fmt.Sprintf("%d", nonce)
- for _, tx := range txs {
- dump[nonce] = append(dump[nonce], format(tx))
- }
- }
- content["queued"][account.Hex()] = dump
- }
- return content
-}
-
-// PublicAccountAPI provides an API to access accounts managed by this node.
-// It offers only methods that can retrieve accounts.
-type PublicAccountAPI struct {
- am *accounts.Manager
-}
-
-// NewPublicAccountAPI creates a new PublicAccountAPI.
-func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI {
- return &PublicAccountAPI{am: am}
-}
-
-// Accounts returns the collection of accounts this node manages
-func (s *PublicAccountAPI) Accounts() []accounts.Account {
- return s.am.Accounts()
-}
-
-// PrivateAccountAPI provides an API to access accounts managed by this node.
-// It offers methods to create, (un)lock en list accounts. Some methods accept
-// passwords and are therefore considered private by default.
-type PrivateAccountAPI struct {
- am *accounts.Manager
- txPool *core.TxPool
- txMu *sync.Mutex
- gpo *GasPriceOracle
-}
-
-// NewPrivateAccountAPI create a new PrivateAccountAPI.
-func NewPrivateAccountAPI(e *Ethereum) *PrivateAccountAPI {
- return &PrivateAccountAPI{
- am: e.accountManager,
- txPool: e.txPool,
- txMu: &e.txMu,
- gpo: e.gpo,
- }
-}
-
-// ListAccounts will return a list of addresses for accounts this node manages.
-func (s *PrivateAccountAPI) ListAccounts() []common.Address {
- accounts := s.am.Accounts()
- addresses := make([]common.Address, len(accounts))
- for i, acc := range accounts {
- addresses[i] = acc.Address
- }
- return addresses
-}
-
-// NewAccount will create a new account and returns the address for the new account.
-func (s *PrivateAccountAPI) NewAccount(password string) (common.Address, error) {
- acc, err := s.am.NewAccount(password)
- if err == nil {
- return acc.Address, nil
- }
- return common.Address{}, err
-}
-
-// ImportRawKey stores the given hex encoded ECDSA key into the key directory,
-// encrypting it with the passphrase.
-func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) {
- hexkey, err := hex.DecodeString(privkey)
- if err != nil {
- return common.Address{}, err
- }
-
- acc, err := s.am.ImportECDSA(crypto.ToECDSA(hexkey), password)
- return acc.Address, err
-}
-
-// UnlockAccount will unlock the account associated with the given address with
-// the given password for duration seconds. If duration is nil it will use a
-// default of 300 seconds. It returns an indication if the account was unlocked.
-func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *rpc.HexNumber) (bool, error) {
- if duration == nil {
- duration = rpc.NewHexNumber(300)
- }
- a := accounts.Account{Address: addr}
- d := time.Duration(duration.Int64()) * time.Second
- if err := s.am.TimedUnlock(a, password, d); err != nil {
- return false, err
- }
- return true, nil
-}
-
-// LockAccount will lock the account associated with the given address when it's unlocked.
-func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
- return s.am.Lock(addr) == nil
-}
-
-// SignAndSendTransaction will create a transaction from the given arguments and
-// tries to sign it with the key associated with args.To. If the given passwd isn't
-// able to decrypt the key it fails.
-func (s *PrivateAccountAPI) SignAndSendTransaction(args SendTxArgs, passwd string) (common.Hash, error) {
- args = prepareSendTxArgs(args, s.gpo)
-
- s.txMu.Lock()
- defer s.txMu.Unlock()
-
- if args.Nonce == nil {
- args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From))
- }
-
- var tx *types.Transaction
- if args.To == nil {
- tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
- } else {
- tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
- }
-
- signature, err := s.am.SignWithPassphrase(args.From, passwd, tx.SigHash().Bytes())
- if err != nil {
- return common.Hash{}, err
- }
-
- return submitTransaction(s.txPool, tx, signature)
-}
-
-// PublicBlockChainAPI provides an API to access the Ethereum blockchain.
-// It offers only methods that operate on public data that is freely available to anyone.
-type PublicBlockChainAPI struct {
- config *core.ChainConfig
- bc *core.BlockChain
- chainDb ethdb.Database
- eventMux *event.TypeMux
- muNewBlockSubscriptions sync.Mutex // protects newBlocksSubscriptions
- newBlockSubscriptions map[string]func(core.ChainEvent) error // callbacks for new block subscriptions
- am *accounts.Manager
- miner *miner.Miner
- gpo *GasPriceOracle
-}
-
-// NewPublicBlockChainAPI creates a new Etheruem blockchain API.
-func NewPublicBlockChainAPI(config *core.ChainConfig, bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, gpo *GasPriceOracle, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI {
- api := &PublicBlockChainAPI{
- config: config,
- bc: bc,
- miner: m,
- chainDb: chainDb,
- eventMux: eventMux,
- am: am,
- newBlockSubscriptions: make(map[string]func(core.ChainEvent) error),
- gpo: gpo,
- }
-
- go api.subscriptionLoop()
-
- return api
-}
-
-// subscriptionLoop reads events from the global event mux and creates notifications for the matched subscriptions.
-func (s *PublicBlockChainAPI) subscriptionLoop() {
- sub := s.eventMux.Subscribe(core.ChainEvent{})
- for event := range sub.Chan() {
- if chainEvent, ok := event.Data.(core.ChainEvent); ok {
- s.muNewBlockSubscriptions.Lock()
- for id, notifyOf := range s.newBlockSubscriptions {
- if notifyOf(chainEvent) == rpc.ErrNotificationNotFound {
- delete(s.newBlockSubscriptions, id)
- }
- }
- s.muNewBlockSubscriptions.Unlock()
- }
- }
-}
-
-// BlockNumber returns the block number of the chain head.
-func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
- return s.bc.CurrentHeader().Number
-}
-
-// GetBalance returns the amount of wei for the given address in the state of the
-// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
-// block numbers are also allowed.
-func (s *PublicBlockChainAPI) GetBalance(address common.Address, blockNr rpc.BlockNumber) (*big.Int, error) {
- state, _, err := stateAndBlockByNumber(s.miner, s.bc, blockNr, s.chainDb)
- if state == nil || err != nil {
- return nil, err
- }
- return state.GetBalance(address), nil
-}
-
-// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
-// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
-func (s *PublicBlockChainAPI) GetBlockByNumber(blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
- if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
- response, err := s.rpcOutputBlock(block, true, fullTx)
- if err == nil && blockNr == rpc.PendingBlockNumber {
- // Pending blocks need to nil out a few fields
- for _, field := range []string{"hash", "nonce", "logsBloom", "miner"} {
- response[field] = nil
- }
- }
- return response, err
- }
- return nil, nil
-}
-
-// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
-// detail, otherwise only the transaction hash is returned.
-func (s *PublicBlockChainAPI) GetBlockByHash(blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
- if block := s.bc.GetBlockByHash(blockHash); block != nil {
- return s.rpcOutputBlock(block, true, fullTx)
- }
- return nil, nil
-}
-
-// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
-// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
-func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(blockNr rpc.BlockNumber, index rpc.HexNumber) (map[string]interface{}, error) {
- if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
- uncles := block.Uncles()
- if index.Int() < 0 || index.Int() >= len(uncles) {
- glog.V(logger.Debug).Infof("uncle block on index %d not found for block #%d", index.Int(), blockNr)
- return nil, nil
- }
- block = types.NewBlockWithHeader(uncles[index.Int()])
- return s.rpcOutputBlock(block, false, false)
- }
- return nil, nil
-}
-
-// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true
-// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
-func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(blockHash common.Hash, index rpc.HexNumber) (map[string]interface{}, error) {
- if block := s.bc.GetBlockByHash(blockHash); block != nil {
- uncles := block.Uncles()
- if index.Int() < 0 || index.Int() >= len(uncles) {
- glog.V(logger.Debug).Infof("uncle block on index %d not found for block %s", index.Int(), blockHash.Hex())
- return nil, nil
- }
- block = types.NewBlockWithHeader(uncles[index.Int()])
- return s.rpcOutputBlock(block, false, false)
- }
- return nil, nil
-}
-
-// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
-func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(blockNr rpc.BlockNumber) *rpc.HexNumber {
- if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
- return rpc.NewHexNumber(len(block.Uncles()))
- }
- return nil
-}
-
-// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
-func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(blockHash common.Hash) *rpc.HexNumber {
- if block := s.bc.GetBlockByHash(blockHash); block != nil {
- return rpc.NewHexNumber(len(block.Uncles()))
- }
- return nil
-}
-
-// NewBlocksArgs allows the user to specify if the returned block should include transactions and in which format.
-type NewBlocksArgs struct {
- IncludeTransactions bool `json:"includeTransactions"`
- TransactionDetails bool `json:"transactionDetails"`
-}
-
-// NewBlocks triggers a new block event each time a block is appended to the chain. It accepts an argument which allows
-// the caller to specify whether the output should contain transactions and in what format.
-func (s *PublicBlockChainAPI) NewBlocks(ctx context.Context, args NewBlocksArgs) (rpc.Subscription, error) {
- notifier, supported := rpc.NotifierFromContext(ctx)
- if !supported {
- return nil, rpc.ErrNotificationsUnsupported
- }
-
- // create a subscription that will remove itself when unsubscribed/cancelled
- subscription, err := notifier.NewSubscription(func(subId string) {
- s.muNewBlockSubscriptions.Lock()
- delete(s.newBlockSubscriptions, subId)
- s.muNewBlockSubscriptions.Unlock()
- })
-
- if err != nil {
- return nil, err
- }
-
- // add a callback that is called on chain events which will format the block and notify the client
- s.muNewBlockSubscriptions.Lock()
- s.newBlockSubscriptions[subscription.ID()] = func(e core.ChainEvent) error {
- notification, err := s.rpcOutputBlock(e.Block, args.IncludeTransactions, args.TransactionDetails)
- if err == nil {
- return subscription.Notify(notification)
- }
- glog.V(logger.Warn).Info("unable to format block %v\n", err)
- return nil
- }
- s.muNewBlockSubscriptions.Unlock()
- return subscription, nil
-}
-
-// GetCode returns the code stored at the given address in the state for the given block number.
-func (s *PublicBlockChainAPI) GetCode(address common.Address, blockNr rpc.BlockNumber) (string, error) {
- state, _, err := stateAndBlockByNumber(s.miner, s.bc, blockNr, s.chainDb)
- if state == nil || err != nil {
- return "", err
- }
- res := state.GetCode(address)
- if len(res) == 0 { // backwards compatibility
- return "0x", nil
- }
- return common.ToHex(res), nil
-}
-
-// GetStorageAt returns the storage from the state at the given address, key and
-// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
-// numbers are also allowed.
-func (s *PublicBlockChainAPI) GetStorageAt(address common.Address, key string, blockNr rpc.BlockNumber) (string, error) {
- state, _, err := stateAndBlockByNumber(s.miner, s.bc, blockNr, s.chainDb)
- if state == nil || err != nil {
- return "0x", err
- }
- return state.GetState(address, common.HexToHash(key)).Hex(), nil
-}
-
-// callmsg is the message type used for call transactions.
-type callmsg struct {
- from *state.StateObject
- to *common.Address
- gas, gasPrice *big.Int
- value *big.Int
- data []byte
-}
-
-// accessor boilerplate to implement core.Message
-func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
-func (m callmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
-func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
-func (m callmsg) To() *common.Address { return m.to }
-func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
-func (m callmsg) Gas() *big.Int { return m.gas }
-func (m callmsg) Value() *big.Int { return m.value }
-func (m callmsg) Data() []byte { return m.data }
-
-// CallArgs represents the arguments for a call.
-type CallArgs struct {
- From common.Address `json:"from"`
- To *common.Address `json:"to"`
- Gas *rpc.HexNumber `json:"gas"`
- GasPrice *rpc.HexNumber `json:"gasPrice"`
- Value rpc.HexNumber `json:"value"`
- Data string `json:"data"`
-}
-
-func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) {
- // Fetch the state associated with the block number
- stateDb, block, err := stateAndBlockByNumber(s.miner, s.bc, blockNr, s.chainDb)
- if stateDb == nil || err != nil {
- return "0x", nil, err
- }
- stateDb = stateDb.Copy()
-
- // Retrieve the account state object to interact with
- var from *state.StateObject
- if args.From == (common.Address{}) {
- accounts := s.am.Accounts()
- if len(accounts) == 0 {
- from = stateDb.GetOrNewStateObject(common.Address{})
- } else {
- from = stateDb.GetOrNewStateObject(accounts[0].Address)
- }
- } else {
- from = stateDb.GetOrNewStateObject(args.From)
- }
- from.SetBalance(common.MaxBig)
-
- // Assemble the CALL invocation
- msg := callmsg{
- from: from,
- to: args.To,
- gas: args.Gas.BigInt(),
- gasPrice: args.GasPrice.BigInt(),
- value: args.Value.BigInt(),
- data: common.FromHex(args.Data),
- }
- if msg.gas == nil {
- msg.gas = big.NewInt(50000000)
- }
- if msg.gasPrice == nil {
- msg.gasPrice = s.gpo.SuggestPrice()
- }
-
- // Execute the call and return
- vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), s.config.VmConfig)
- gp := new(core.GasPool).AddGas(common.MaxBig)
-
- res, requiredGas, _, err := core.NewStateTransition(vmenv, msg, gp).TransitionDb()
- if len(res) == 0 { // backwards compatibility
- return "0x", requiredGas, err
- }
- return common.ToHex(res), requiredGas, err
-}
-
-// Call executes the given transaction on the state for the given block number.
-// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
-func (s *PublicBlockChainAPI) Call(args CallArgs, blockNr rpc.BlockNumber) (string, error) {
- result, _, err := s.doCall(args, blockNr)
- return result, err
-}
-
-// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
-func (s *PublicBlockChainAPI) EstimateGas(args CallArgs) (*rpc.HexNumber, error) {
- _, gas, err := s.doCall(args, rpc.PendingBlockNumber)
- return rpc.NewHexNumber(gas), err
-}
-
-// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
-// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
-// transaction hashes.
-func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
- fields := map[string]interface{}{
- "number": rpc.NewHexNumber(b.Number()),
- "hash": b.Hash(),
- "parentHash": b.ParentHash(),
- "nonce": b.Header().Nonce,
- "sha3Uncles": b.UncleHash(),
- "logsBloom": b.Bloom(),
- "stateRoot": b.Root(),
- "miner": b.Coinbase(),
- "difficulty": rpc.NewHexNumber(b.Difficulty()),
- "totalDifficulty": rpc.NewHexNumber(s.bc.GetTd(b.Hash(), b.NumberU64())),
- "extraData": fmt.Sprintf("0x%x", b.Extra()),
- "size": rpc.NewHexNumber(b.Size().Int64()),
- "gasLimit": rpc.NewHexNumber(b.GasLimit()),
- "gasUsed": rpc.NewHexNumber(b.GasUsed()),
- "timestamp": rpc.NewHexNumber(b.Time()),
- "transactionsRoot": b.TxHash(),
- "receiptRoot": b.ReceiptHash(),
- }
-
- if inclTx {
- formatTx := func(tx *types.Transaction) (interface{}, error) {
- return tx.Hash(), nil
- }
-
- if fullTx {
- formatTx = func(tx *types.Transaction) (interface{}, error) {
- return newRPCTransaction(b, tx.Hash())
- }
- }
-
- txs := b.Transactions()
- transactions := make([]interface{}, len(txs))
- var err error
- for i, tx := range b.Transactions() {
- if transactions[i], err = formatTx(tx); err != nil {
- return nil, err
- }
- }
- fields["transactions"] = transactions
- }
-
- uncles := b.Uncles()
- uncleHashes := make([]common.Hash, len(uncles))
- for i, uncle := range uncles {
- uncleHashes[i] = uncle.Hash()
- }
- fields["uncles"] = uncleHashes
-
- return fields, nil
-}
-
-// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
-type RPCTransaction struct {
- BlockHash common.Hash `json:"blockHash"`
- BlockNumber *rpc.HexNumber `json:"blockNumber"`
- From common.Address `json:"from"`
- Gas *rpc.HexNumber `json:"gas"`
- GasPrice *rpc.HexNumber `json:"gasPrice"`
- Hash common.Hash `json:"hash"`
- Input string `json:"input"`
- Nonce *rpc.HexNumber `json:"nonce"`
- To *common.Address `json:"to"`
- TransactionIndex *rpc.HexNumber `json:"transactionIndex"`
- Value *rpc.HexNumber `json:"value"`
-}
-
-// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
-func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction {
- from, _ := tx.FromFrontier()
-
- return &RPCTransaction{
- From: from,
- Gas: rpc.NewHexNumber(tx.Gas()),
- GasPrice: rpc.NewHexNumber(tx.GasPrice()),
- Hash: tx.Hash(),
- Input: fmt.Sprintf("0x%x", tx.Data()),
- Nonce: rpc.NewHexNumber(tx.Nonce()),
- To: tx.To(),
- Value: rpc.NewHexNumber(tx.Value()),
- }
-}
-
-// newRPCTransaction returns a transaction that will serialize to the RPC representation.
-func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransaction, error) {
- if txIndex >= 0 && txIndex < len(b.Transactions()) {
- tx := b.Transactions()[txIndex]
- from, err := tx.FromFrontier()
- if err != nil {
- return nil, err
- }
-
- return &RPCTransaction{
- BlockHash: b.Hash(),
- BlockNumber: rpc.NewHexNumber(b.Number()),
- From: from,
- Gas: rpc.NewHexNumber(tx.Gas()),
- GasPrice: rpc.NewHexNumber(tx.GasPrice()),
- Hash: tx.Hash(),
- Input: fmt.Sprintf("0x%x", tx.Data()),
- Nonce: rpc.NewHexNumber(tx.Nonce()),
- To: tx.To(),
- TransactionIndex: rpc.NewHexNumber(txIndex),
- Value: rpc.NewHexNumber(tx.Value()),
- }, nil
- }
-
- return nil, nil
-}
-
-// newRPCTransaction returns a transaction that will serialize to the RPC representation.
-func newRPCTransaction(b *types.Block, txHash common.Hash) (*RPCTransaction, error) {
- for idx, tx := range b.Transactions() {
- if tx.Hash() == txHash {
- return newRPCTransactionFromBlockIndex(b, idx)
- }
- }
-
- return nil, nil
-}
-
-// PublicTransactionPoolAPI exposes methods for the RPC interface
-type PublicTransactionPoolAPI struct {
- eventMux *event.TypeMux
- chainDb ethdb.Database
- gpo *GasPriceOracle
- bc *core.BlockChain
- miner *miner.Miner
- am *accounts.Manager
- txPool *core.TxPool
- txMu *sync.Mutex
- muPendingTxSubs sync.Mutex
- pendingTxSubs map[string]rpc.Subscription
-}
-
-// NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool.
-func NewPublicTransactionPoolAPI(e *Ethereum) *PublicTransactionPoolAPI {
- api := &PublicTransactionPoolAPI{
- eventMux: e.eventMux,
- gpo: e.gpo,
- chainDb: e.chainDb,
- bc: e.blockchain,
- am: e.accountManager,
- txPool: e.txPool,
- txMu: &e.txMu,
- miner: e.miner,
- pendingTxSubs: make(map[string]rpc.Subscription),
- }
- go api.subscriptionLoop()
-
- return api
-}
-
-// subscriptionLoop listens for events on the global event mux and creates notifications for subscriptions.
-func (s *PublicTransactionPoolAPI) subscriptionLoop() {
- sub := s.eventMux.Subscribe(core.TxPreEvent{})
- for event := range sub.Chan() {
- tx := event.Data.(core.TxPreEvent)
- if from, err := tx.Tx.FromFrontier(); err == nil {
- if s.am.HasAddress(from) {
- s.muPendingTxSubs.Lock()
- for id, sub := range s.pendingTxSubs {
- if sub.Notify(tx.Tx.Hash()) == rpc.ErrNotificationNotFound {
- delete(s.pendingTxSubs, id)
- }
- }
- s.muPendingTxSubs.Unlock()
- }
- }
- }
-}
-
-func getTransaction(chainDb ethdb.Database, txPool *core.TxPool, txHash common.Hash) (*types.Transaction, bool, error) {
- txData, err := chainDb.Get(txHash.Bytes())
- isPending := false
- tx := new(types.Transaction)
-
- if err == nil && len(txData) > 0 {
- if err := rlp.DecodeBytes(txData, tx); err != nil {
- return nil, isPending, err
- }
- } else {
- // pending transaction?
- tx = txPool.GetTransaction(txHash)
- isPending = true
- }
-
- return tx, isPending, nil
-}
-
-// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
-func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(blockNr rpc.BlockNumber) *rpc.HexNumber {
- if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
- return rpc.NewHexNumber(len(block.Transactions()))
- }
- return nil
-}
-
-// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
-func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(blockHash common.Hash) *rpc.HexNumber {
- if block := s.bc.GetBlockByHash(blockHash); block != nil {
- return rpc.NewHexNumber(len(block.Transactions()))
- }
- return nil
-}
-
-// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
-func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(blockNr rpc.BlockNumber, index rpc.HexNumber) (*RPCTransaction, error) {
- if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
- return newRPCTransactionFromBlockIndex(block, index.Int())
- }
- return nil, nil
-}
-
-// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
-func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(blockHash common.Hash, index rpc.HexNumber) (*RPCTransaction, error) {
- if block := s.bc.GetBlockByHash(blockHash); block != nil {
- return newRPCTransactionFromBlockIndex(block, index.Int())
- }
- return nil, nil
-}
-
-// GetTransactionCount returns the number of transactions the given address has sent for the given block number
-func (s *PublicTransactionPoolAPI) GetTransactionCount(address common.Address, blockNr rpc.BlockNumber) (*rpc.HexNumber, error) {
- state, _, err := stateAndBlockByNumber(s.miner, s.bc, blockNr, s.chainDb)
- if state == nil || err != nil {
- return nil, err
- }
- return rpc.NewHexNumber(state.GetNonce(address)), nil
-}
-
-// getTransactionBlockData fetches the meta data for the given transaction from the chain database. This is useful to
-// retrieve block information for a hash. It returns the block hash, block index and transaction index.
-func getTransactionBlockData(chainDb ethdb.Database, txHash common.Hash) (common.Hash, uint64, uint64, error) {
- var txBlock struct {
- BlockHash common.Hash
- BlockIndex uint64
- Index uint64
- }
-
- blockData, err := chainDb.Get(append(txHash.Bytes(), 0x0001))
- if err != nil {
- return common.Hash{}, uint64(0), uint64(0), err
- }
-
- reader := bytes.NewReader(blockData)
- if err = rlp.Decode(reader, &txBlock); err != nil {
- return common.Hash{}, uint64(0), uint64(0), err
- }
-
- return txBlock.BlockHash, txBlock.BlockIndex, txBlock.Index, nil
-}
-
-// GetTransactionByHash returns the transaction for the given hash
-func (s *PublicTransactionPoolAPI) GetTransactionByHash(txHash common.Hash) (*RPCTransaction, error) {
- var tx *types.Transaction
- var isPending bool
- var err error
-
- if tx, isPending, err = getTransaction(s.chainDb, s.txPool, txHash); err != nil {
- glog.V(logger.Debug).Infof("%v\n", err)
- return nil, nil
- } else if tx == nil {
- return nil, nil
- }
-
- if isPending {
- return newRPCPendingTransaction(tx), nil
- }
-
- blockHash, _, _, err := getTransactionBlockData(s.chainDb, txHash)
- if err != nil {
- glog.V(logger.Debug).Infof("%v\n", err)
- return nil, nil
- }
-
- if block := s.bc.GetBlockByHash(blockHash); block != nil {
- return newRPCTransaction(block, txHash)
- }
-
- return nil, nil
-}
-
-// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
-func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (map[string]interface{}, error) {
- receipt := core.GetReceipt(s.chainDb, txHash)
- if receipt == nil {
- glog.V(logger.Debug).Infof("receipt not found for transaction %s", txHash.Hex())
- return nil, nil
- }
-
- tx, _, err := getTransaction(s.chainDb, s.txPool, txHash)
- if err != nil {
- glog.V(logger.Debug).Infof("%v\n", err)
- return nil, nil
- }
-
- txBlock, blockIndex, index, err := getTransactionBlockData(s.chainDb, txHash)
- if err != nil {
- glog.V(logger.Debug).Infof("%v\n", err)
- return nil, nil
- }
-
- from, err := tx.FromFrontier()
- if err != nil {
- glog.V(logger.Debug).Infof("%v\n", err)
- return nil, nil
- }
-
- fields := map[string]interface{}{
- "root": common.Bytes2Hex(receipt.PostState),
- "blockHash": txBlock,
- "blockNumber": rpc.NewHexNumber(blockIndex),
- "transactionHash": txHash,
- "transactionIndex": rpc.NewHexNumber(index),
- "from": from,
- "to": tx.To(),
- "gasUsed": rpc.NewHexNumber(receipt.GasUsed),
- "cumulativeGasUsed": rpc.NewHexNumber(receipt.CumulativeGasUsed),
- "contractAddress": nil,
- "logs": receipt.Logs,
- }
-
- if receipt.Logs == nil {
- fields["logs"] = []vm.Logs{}
- }
-
- // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
- if bytes.Compare(receipt.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 {
- fields["contractAddress"] = receipt.ContractAddress
- }
-
- return fields, nil
-}
-
-// sign is a helper function that signs a transaction with the private key of the given address.
-func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
- signature, err := s.am.Sign(addr, tx.SigHash().Bytes())
- if err != nil {
- return nil, err
- }
- return tx.WithSignature(signature)
-}
-
-// SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool.
-type SendTxArgs struct {
- From common.Address `json:"from"`
- To *common.Address `json:"to"`
- Gas *rpc.HexNumber `json:"gas"`
- GasPrice *rpc.HexNumber `json:"gasPrice"`
- Value *rpc.HexNumber `json:"value"`
- Data string `json:"data"`
- Nonce *rpc.HexNumber `json:"nonce"`
-}
-
-// prepareSendTxArgs is a helper function that fills in default values for unspecified tx fields.
-func prepareSendTxArgs(args SendTxArgs, gpo *GasPriceOracle) SendTxArgs {
- if args.Gas == nil {
- args.Gas = rpc.NewHexNumber(defaultGas)
- }
- if args.GasPrice == nil {
- args.GasPrice = rpc.NewHexNumber(gpo.SuggestPrice())
- }
- if args.Value == nil {
- args.Value = rpc.NewHexNumber(0)
- }
- return args
-}
-
-// submitTransaction is a helper function that submits tx to txPool and creates a log entry.
-func submitTransaction(txPool *core.TxPool, tx *types.Transaction, signature []byte) (common.Hash, error) {
- signedTx, err := tx.WithSignature(signature)
- if err != nil {
- return common.Hash{}, err
- }
-
- txPool.SetLocal(signedTx)
- if err := txPool.Add(signedTx); err != nil {
- return common.Hash{}, err
- }
-
- if signedTx.To() == nil {
- from, _ := signedTx.From()
- addr := crypto.CreateAddress(from, signedTx.Nonce())
- glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
- } else {
- glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
- }
-
- return signedTx.Hash(), nil
-}
-
-// SendTransaction creates a transaction for the given argument, sign it and submit it to the
-// transaction pool.
-func (s *PublicTransactionPoolAPI) SendTransaction(args SendTxArgs) (common.Hash, error) {
- args = prepareSendTxArgs(args, s.gpo)
-
- s.txMu.Lock()
- defer s.txMu.Unlock()
-
- if args.Nonce == nil {
- args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From))
- }
-
- var tx *types.Transaction
- if args.To == nil {
- tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
- } else {
- tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
- }
-
- signature, err := s.am.Sign(args.From, tx.SigHash().Bytes())
- if err != nil {
- return common.Hash{}, err
- }
-
- return submitTransaction(s.txPool, tx, signature)
-}
-
-// SendRawTransaction will add the signed transaction to the transaction pool.
-// The sender is responsible for signing the transaction and using the correct nonce.
-func (s *PublicTransactionPoolAPI) SendRawTransaction(encodedTx string) (string, error) {
- tx := new(types.Transaction)
- if err := rlp.DecodeBytes(common.FromHex(encodedTx), tx); err != nil {
- return "", err
- }
-
- s.txPool.SetLocal(tx)
- if err := s.txPool.Add(tx); err != nil {
- return "", err
- }
-
- if tx.To() == nil {
- from, err := tx.FromFrontier()
- if err != nil {
- return "", err
- }
- addr := crypto.CreateAddress(from, tx.Nonce())
- glog.V(logger.Info).Infof("Tx(%x) created: %x\n", tx.Hash(), addr)
- } else {
- glog.V(logger.Info).Infof("Tx(%x) to: %x\n", tx.Hash(), tx.To())
- }
-
- return tx.Hash().Hex(), nil
-}
-
-// Sign signs the given hash using the key that matches the address. The key must be
-// unlocked in order to sign the hash.
-func (s *PublicTransactionPoolAPI) Sign(addr common.Address, hash common.Hash) (string, error) {
- signature, error := s.am.Sign(addr, hash[:])
- return common.ToHex(signature), error
-}
-
-// SignTransactionArgs represents the arguments to sign a transaction.
-type SignTransactionArgs struct {
- From common.Address
- To *common.Address
- Nonce *rpc.HexNumber
- Value *rpc.HexNumber
- Gas *rpc.HexNumber
- GasPrice *rpc.HexNumber
- Data string
-
- BlockNumber int64
-}
-
-// Tx is a helper object for argument and return values
-type Tx struct {
- tx *types.Transaction
-
- To *common.Address `json:"to"`
- From common.Address `json:"from"`
- Nonce *rpc.HexNumber `json:"nonce"`
- Value *rpc.HexNumber `json:"value"`
- Data string `json:"data"`
- GasLimit *rpc.HexNumber `json:"gas"`
- GasPrice *rpc.HexNumber `json:"gasPrice"`
- Hash common.Hash `json:"hash"`
-}
-
-// UnmarshalJSON parses JSON data into tx.
-func (tx *Tx) UnmarshalJSON(b []byte) (err error) {
- req := struct {
- To *common.Address `json:"to"`
- From common.Address `json:"from"`
- Nonce *rpc.HexNumber `json:"nonce"`
- Value *rpc.HexNumber `json:"value"`
- Data string `json:"data"`
- GasLimit *rpc.HexNumber `json:"gas"`
- GasPrice *rpc.HexNumber `json:"gasPrice"`
- Hash common.Hash `json:"hash"`
- }{}
-
- if err := json.Unmarshal(b, &req); err != nil {
- return err
- }
-
- tx.To = req.To
- tx.From = req.From
- tx.Nonce = req.Nonce
- tx.Value = req.Value
- tx.Data = req.Data
- tx.GasLimit = req.GasLimit
- tx.GasPrice = req.GasPrice
- tx.Hash = req.Hash
-
- data := common.Hex2Bytes(tx.Data)
-
- if tx.Nonce == nil {
- return fmt.Errorf("need nonce")
- }
- if tx.Value == nil {
- tx.Value = rpc.NewHexNumber(0)
- }
- if tx.GasLimit == nil {
- tx.GasLimit = rpc.NewHexNumber(0)
- }
- if tx.GasPrice == nil {
- tx.GasPrice = rpc.NewHexNumber(int64(50000000000))
- }
-
- if req.To == nil {
- tx.tx = types.NewContractCreation(tx.Nonce.Uint64(), tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
- } else {
- tx.tx = types.NewTransaction(tx.Nonce.Uint64(), *tx.To, tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
- }
-
- return nil
-}
-
-// SignTransactionResult represents a RLP encoded signed transaction.
-type SignTransactionResult struct {
- Raw string `json:"raw"`
- Tx *Tx `json:"tx"`
-}
-
-func newTx(t *types.Transaction) *Tx {
- from, _ := t.FromFrontier()
- return &Tx{
- tx: t,
- To: t.To(),
- From: from,
- Value: rpc.NewHexNumber(t.Value()),
- Nonce: rpc.NewHexNumber(t.Nonce()),
- Data: "0x" + common.Bytes2Hex(t.Data()),
- GasLimit: rpc.NewHexNumber(t.Gas()),
- GasPrice: rpc.NewHexNumber(t.GasPrice()),
- Hash: t.Hash(),
- }
-}
-
-// SignTransaction will sign the given transaction with the from account.
-// The node needs to have the private key of the account corresponding with
-// the given from address and it needs to be unlocked.
-func (s *PublicTransactionPoolAPI) SignTransaction(args SignTransactionArgs) (*SignTransactionResult, error) {
- if args.Gas == nil {
- args.Gas = rpc.NewHexNumber(defaultGas)
- }
- if args.GasPrice == nil {
- args.GasPrice = rpc.NewHexNumber(s.gpo.SuggestPrice())
- }
- if args.Value == nil {
- args.Value = rpc.NewHexNumber(0)
- }
-
- s.txMu.Lock()
- defer s.txMu.Unlock()
-
- if args.Nonce == nil {
- args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From))
- }
-
- var tx *types.Transaction
- if args.To == nil {
- tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
- } else {
- tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
- }
-
- signedTx, err := s.sign(args.From, tx)
- if err != nil {
- return nil, err
- }
-
- data, err := rlp.EncodeToBytes(signedTx)
- if err != nil {
- return nil, err
- }
-
- return &SignTransactionResult{"0x" + common.Bytes2Hex(data), newTx(signedTx)}, nil
-}
-
-// PendingTransactions returns the transactions that are in the transaction pool and have a from address that is one of
-// the accounts this node manages.
-func (s *PublicTransactionPoolAPI) PendingTransactions() []*RPCTransaction {
- pending := s.txPool.GetTransactions()
- transactions := make([]*RPCTransaction, 0, len(pending))
- for _, tx := range pending {
- from, _ := tx.FromFrontier()
- if s.am.HasAddress(from) {
- transactions = append(transactions, newRPCPendingTransaction(tx))
- }
- }
- return transactions
-}
-
-// NewPendingTransactions creates a subscription that is triggered each time a transaction enters the transaction pool
-// and is send from one of the transactions this nodes manages.
-func (s *PublicTransactionPoolAPI) NewPendingTransactions(ctx context.Context) (rpc.Subscription, error) {
- notifier, supported := rpc.NotifierFromContext(ctx)
- if !supported {
- return nil, rpc.ErrNotificationsUnsupported
- }
-
- subscription, err := notifier.NewSubscription(func(id string) {
- s.muPendingTxSubs.Lock()
- delete(s.pendingTxSubs, id)
- s.muPendingTxSubs.Unlock()
- })
-
- if err != nil {
- return nil, err
- }
-
- s.muPendingTxSubs.Lock()
- s.pendingTxSubs[subscription.ID()] = subscription
- s.muPendingTxSubs.Unlock()
-
- return subscription, nil
-}
-
-// Resend accepts an existing transaction and a new gas price and limit. It will remove the given transaction from the
-// pool and reinsert it with the new gas price and limit.
-func (s *PublicTransactionPoolAPI) Resend(tx Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) {
-
- pending := s.txPool.GetTransactions()
- for _, p := range pending {
- if pFrom, err := p.FromFrontier(); err == nil && pFrom == tx.From && p.SigHash() == tx.tx.SigHash() {
- if gasPrice == nil {
- gasPrice = rpc.NewHexNumber(tx.tx.GasPrice())
- }
- if gasLimit == nil {
- gasLimit = rpc.NewHexNumber(tx.tx.Gas())
- }
-
- var newTx *types.Transaction
- if tx.tx.To() == nil {
- newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data())
- } else {
- newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data())
- }
-
- signedTx, err := s.sign(tx.From, newTx)
- if err != nil {
- return common.Hash{}, err
- }
-
- s.txPool.RemoveTx(tx.Hash)
- if err = s.txPool.Add(signedTx); err != nil {
- return common.Hash{}, err
- }
-
- return signedTx.Hash(), nil
- }
- }
-
- return common.Hash{}, fmt.Errorf("Transaction %#x not found", tx.Hash)
-}
-
-// PrivateAdminAPI is the collection of Etheruem APIs exposed over the private
-// admin endpoint.
+// PrivateAdminAPI is the collection of Etheruem full node-related APIs
+// exposed over the private admin endpoint.
type PrivateAdminAPI struct {
eth *Ethereum
}
-// NewPrivateAdminAPI creates a new API definition for the private admin methods
-// of the Ethereum service.
+// NewPrivateAdminAPI creates a new API definition for the full node private
+// admin methods of the Ethereum service.
func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI {
return &PrivateAdminAPI{eth: eth}
}
-// SetSolc sets the Solidity compiler path to be used by the node.
-func (api *PrivateAdminAPI) SetSolc(path string) (string, error) {
- solc, err := api.eth.SetSolc(path)
- if err != nil {
- return "", err
- }
- return solc.Info(), nil
-}
-
// ExportChain exports the current blockchain into a local file.
func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
// Make sure we can create the file to export into
@@ -1562,14 +271,14 @@ func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
return true, nil
}
-// PublicDebugAPI is the collection of Etheruem APIs exposed over the public
-// debugging endpoint.
+// PublicDebugAPI is the collection of Etheruem full node APIs exposed
+// over the public debugging endpoint.
type PublicDebugAPI struct {
eth *Ethereum
}
-// NewPublicDebugAPI creates a new API definition for the public debug methods
-// of the Ethereum service.
+// NewPublicDebugAPI creates a new API definition for the full node-
+// related public debug methods of the Ethereum service.
func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI {
return &PublicDebugAPI{eth: eth}
}
@@ -1587,76 +296,25 @@ func (api *PublicDebugAPI) DumpBlock(number uint64) (state.World, error) {
return stateDb.RawDump(), nil
}
-// GetBlockRlp retrieves the RLP encoded for of a single block.
-func (api *PublicDebugAPI) GetBlockRlp(number uint64) (string, error) {
- block := api.eth.BlockChain().GetBlockByNumber(number)
- if block == nil {
- return "", fmt.Errorf("block #%d not found", number)
- }
- encoded, err := rlp.EncodeToBytes(block)
- if err != nil {
- return "", err
- }
- return fmt.Sprintf("%x", encoded), nil
-}
-
-// PrintBlock retrieves a block and returns its pretty printed form.
-func (api *PublicDebugAPI) PrintBlock(number uint64) (string, error) {
- block := api.eth.BlockChain().GetBlockByNumber(number)
- if block == nil {
- return "", fmt.Errorf("block #%d not found", number)
- }
- return fmt.Sprintf("%s", block), nil
-}
-
-// SeedHash retrieves the seed hash of a block.
-func (api *PublicDebugAPI) SeedHash(number uint64) (string, error) {
- block := api.eth.BlockChain().GetBlockByNumber(number)
- if block == nil {
- return "", fmt.Errorf("block #%d not found", number)
- }
- hash, err := ethash.GetSeedHash(number)
- if err != nil {
- return "", err
- }
- return fmt.Sprintf("0x%x", hash), nil
-}
-
-// PrivateDebugAPI is the collection of Etheruem APIs exposed over the private
-// debugging endpoint.
+// PrivateDebugAPI is the collection of Etheruem full node APIs exposed over
+// the private debugging endpoint.
type PrivateDebugAPI struct {
config *core.ChainConfig
eth *Ethereum
}
-// NewPrivateDebugAPI creates a new API definition for the private debug methods
-// of the Ethereum service.
+// NewPrivateDebugAPI creates a new API definition for the full node-related
+// private debug methods of the Ethereum service.
func NewPrivateDebugAPI(config *core.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
return &PrivateDebugAPI{config: config, eth: eth}
}
-// ChaindbProperty returns leveldb properties of the chain database.
-func (api *PrivateDebugAPI) ChaindbProperty(property string) (string, error) {
- ldb, ok := api.eth.chainDb.(interface {
- LDB() *leveldb.DB
- })
- if !ok {
- return "", fmt.Errorf("chaindbProperty does not work for memory databases")
- }
- if property == "" {
- property = "leveldb.stats"
- } else if !strings.HasPrefix(property, "leveldb.") {
- property = "leveldb." + property
- }
- return ldb.LDB().GetProperty(property)
-}
-
// BlockTraceResult is the returned value when replaying a block to check for
// consensus results and full VM trace logs for all included transactions.
type BlockTraceResult struct {
- Validated bool `json:"validated"`
- StructLogs []structLogRes `json:"structLogs"`
- Error string `json:"error"`
+ Validated bool `json:"validated"`
+ StructLogs []ethapi.StructLogRes `json:"structLogs"`
+ Error string `json:"error"`
}
// TraceBlock processes the given block's RLP but does not import the block in to
@@ -1671,7 +329,7 @@ func (api *PrivateDebugAPI) TraceBlock(blockRlp []byte, config *vm.Config) Block
validated, logs, err := api.traceBlock(&block, config)
return BlockTraceResult{
Validated: validated,
- StructLogs: formatLogs(logs),
+ StructLogs: ethapi.FormatLogs(logs),
Error: formatError(err),
}
}
@@ -1697,7 +355,7 @@ func (api *PrivateDebugAPI) TraceBlockByNumber(number uint64, config *vm.Config)
validated, logs, err := api.traceBlock(block, config)
return BlockTraceResult{
Validated: validated,
- StructLogs: formatLogs(logs),
+ StructLogs: ethapi.FormatLogs(logs),
Error: formatError(err),
}
}
@@ -1713,7 +371,7 @@ func (api *PrivateDebugAPI) TraceBlockByHash(hash common.Hash, config *vm.Config
validated, logs, err := api.traceBlock(block, config)
return BlockTraceResult{
Validated: validated,
- StructLogs: formatLogs(logs),
+ StructLogs: ethapi.FormatLogs(logs),
Error: formatError(err),
}
}
@@ -1763,63 +421,25 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, config *vm.Config) (b
return true, collector.traces, nil
}
-// SetHead rewinds the head of the blockchain to a previous block.
-func (api *PrivateDebugAPI) SetHead(number uint64) {
- api.eth.BlockChain().SetHead(number)
-}
-
-// ExecutionResult groups all structured logs emitted by the EVM
-// while replaying a transaction in debug mode as well as the amount of
-// gas used and the return value
-type ExecutionResult struct {
- Gas *big.Int `json:"gas"`
- ReturnValue string `json:"returnValue"`
- StructLogs []structLogRes `json:"structLogs"`
-}
-
-// structLogRes stores a structured log emitted by the EVM while replaying a
-// transaction in debug mode
-type structLogRes struct {
- Pc uint64 `json:"pc"`
- Op string `json:"op"`
- Gas *big.Int `json:"gas"`
- GasCost *big.Int `json:"gasCost"`
- Depth int `json:"depth"`
- Error string `json:"error"`
- Stack []string `json:"stack"`
- Memory []string `json:"memory"`
- Storage map[string]string `json:"storage"`
+// callmsg is the message type used for call transations.
+type callmsg struct {
+ addr common.Address
+ to *common.Address
+ gas, gasPrice *big.Int
+ value *big.Int
+ data []byte
}
-// formatLogs formats EVM returned structured logs for json output
-func formatLogs(structLogs []vm.StructLog) []structLogRes {
- formattedStructLogs := make([]structLogRes, len(structLogs))
- for index, trace := range structLogs {
- formattedStructLogs[index] = structLogRes{
- Pc: trace.Pc,
- Op: trace.Op.String(),
- Gas: trace.Gas,
- GasCost: trace.GasCost,
- Depth: trace.Depth,
- Error: formatError(trace.Err),
- Stack: make([]string, len(trace.Stack)),
- Storage: make(map[string]string),
- }
-
- for i, stackValue := range trace.Stack {
- formattedStructLogs[index].Stack[i] = fmt.Sprintf("%x", common.LeftPadBytes(stackValue.Bytes(), 32))
- }
-
- for i := 0; i+32 <= len(trace.Memory); i += 32 {
- formattedStructLogs[index].Memory = append(formattedStructLogs[index].Memory, fmt.Sprintf("%x", trace.Memory[i:i+32]))
- }
-
- for i, storageValue := range trace.Storage {
- formattedStructLogs[index].Storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue)
- }
- }
- return formattedStructLogs
-}
+// accessor boilerplate to implement core.Message
+func (m callmsg) From() (common.Address, error) { return m.addr, nil }
+func (m callmsg) FromFrontier() (common.Address, error) { return m.addr, nil }
+func (m callmsg) Nonce() uint64 { return 0 }
+func (m callmsg) CheckNonce() bool { return false }
+func (m callmsg) To() *common.Address { return m.to }
+func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
+func (m callmsg) Gas() *big.Int { return m.gas }
+func (m callmsg) Value() *big.Int { return m.value }
+func (m callmsg) Data() []byte { return m.data }
// formatError formats a Go error into either an empty string or the data content
// of the error itself.
@@ -1832,7 +452,7 @@ func formatError(err error) string {
// TraceTransaction returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
-func (api *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger *vm.LogConfig) (*ExecutionResult, error) {
+func (api *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger *vm.LogConfig) (*ethapi.ExecutionResult, error) {
if logger == nil {
logger = new(vm.LogConfig)
}
@@ -1862,7 +482,7 @@ func (api *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger *vm.LogC
return nil, fmt.Errorf("sender retrieval failed: %v", err)
}
msg := callmsg{
- from: stateDb.GetOrNewStateObject(from),
+ addr: from,
to: tx.To(),
gas: tx.Gas(),
gasPrice: tx.GasPrice(),
@@ -1885,90 +505,11 @@ func (api *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger *vm.LogC
if err != nil {
return nil, fmt.Errorf("tracing failed: %v", err)
}
- return &ExecutionResult{
+ return &ethapi.ExecutionResult{
Gas: gas,
ReturnValue: fmt.Sprintf("%x", ret),
- StructLogs: formatLogs(vmenv.StructLogs()),
+ StructLogs: ethapi.FormatLogs(vmenv.StructLogs()),
}, nil
}
return nil, errors.New("database inconsistency")
}
-
-// TraceCall executes a call and returns the amount of gas, created logs and optionally returned values.
-func (s *PublicBlockChainAPI) TraceCall(args CallArgs, blockNr rpc.BlockNumber) (*ExecutionResult, error) {
- // Fetch the state associated with the block number
- stateDb, block, err := stateAndBlockByNumber(s.miner, s.bc, blockNr, s.chainDb)
- if stateDb == nil || err != nil {
- return nil, err
- }
- stateDb = stateDb.Copy()
-
- // Retrieve the account state object to interact with
- var from *state.StateObject
- if args.From == (common.Address{}) {
- accounts := s.am.Accounts()
- if len(accounts) == 0 {
- from = stateDb.GetOrNewStateObject(common.Address{})
- } else {
- from = stateDb.GetOrNewStateObject(accounts[0].Address)
- }
- } else {
- from = stateDb.GetOrNewStateObject(args.From)
- }
- from.SetBalance(common.MaxBig)
-
- // Assemble the CALL invocation
- msg := callmsg{
- from: from,
- to: args.To,
- gas: args.Gas.BigInt(),
- gasPrice: args.GasPrice.BigInt(),
- value: args.Value.BigInt(),
- data: common.FromHex(args.Data),
- }
- if msg.gas.Cmp(common.Big0) == 0 {
- msg.gas = big.NewInt(50000000)
- }
- if msg.gasPrice.Cmp(common.Big0) == 0 {
- msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
- }
-
- // Execute the call and return
- vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), vm.Config{
- Debug: true,
- })
- gp := new(core.GasPool).AddGas(common.MaxBig)
-
- ret, gas, err := core.ApplyMessage(vmenv, msg, gp)
- return &ExecutionResult{
- Gas: gas,
- ReturnValue: fmt.Sprintf("%x", ret),
- StructLogs: formatLogs(vmenv.StructLogs()),
- }, nil
-}
-
-// PublicNetAPI offers network related RPC methods
-type PublicNetAPI struct {
- net *p2p.Server
- networkVersion int
-}
-
-// NewPublicNetAPI creates a new net API instance.
-func NewPublicNetAPI(net *p2p.Server, networkVersion int) *PublicNetAPI {
- return &PublicNetAPI{net, networkVersion}
-}
-
-// Listening returns an indication if the node is listening for network connections.
-func (s *PublicNetAPI) Listening() bool {
- return true // always listening
-}
-
-// PeerCount returns the number of connected peers
-func (s *PublicNetAPI) PeerCount() *rpc.HexNumber {
- return rpc.NewHexNumber(s.net.PeerCount())
-}
-
-// Version returns the current ethereum protocol version.
-func (s *PublicNetAPI) Version() string {
- return fmt.Sprintf("%d", s.networkVersion)
-}
diff --git a/eth/api_backend.go b/eth/api_backend.go
new file mode 100644
index 000000000..efcdb3361
--- /dev/null
+++ b/eth/api_backend.go
@@ -0,0 +1,201 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+package eth
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/eth/gasprice"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ rpc "github.com/ethereum/go-ethereum/rpc"
+ "golang.org/x/net/context"
+)
+
+// EthApiBackend implements ethapi.Backend for full nodes
+type EthApiBackend struct {
+ eth *Ethereum
+ gpo *gasprice.GasPriceOracle
+}
+
+func (b *EthApiBackend) SetHead(number uint64) {
+ b.eth.blockchain.SetHead(number)
+}
+
+func (b *EthApiBackend) HeaderByNumber(blockNr rpc.BlockNumber) *types.Header {
+ // Pending block is only known by the miner
+ if blockNr == rpc.PendingBlockNumber {
+ block, _ := b.eth.miner.Pending()
+ return block.Header()
+ }
+ // Otherwise resolve and return the block
+ if blockNr == rpc.LatestBlockNumber {
+ return b.eth.blockchain.CurrentBlock().Header()
+ }
+ return b.eth.blockchain.GetHeaderByNumber(uint64(blockNr))
+}
+
+func (b *EthApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
+ // Pending block is only known by the miner
+ if blockNr == rpc.PendingBlockNumber {
+ block, _ := b.eth.miner.Pending()
+ return block, nil
+ }
+ // Otherwise resolve and return the block
+ if blockNr == rpc.LatestBlockNumber {
+ return b.eth.blockchain.CurrentBlock(), nil
+ }
+ return b.eth.blockchain.GetBlockByNumber(uint64(blockNr)), nil
+}
+
+func (b *EthApiBackend) StateAndHeaderByNumber(blockNr rpc.BlockNumber) (ethapi.State, *types.Header, error) {
+ // Pending state is only known by the miner
+ if blockNr == rpc.PendingBlockNumber {
+ block, state := b.eth.miner.Pending()
+ return EthApiState{state}, block.Header(), nil
+ }
+ // Otherwise resolve the block number and return its state
+ header := b.HeaderByNumber(blockNr)
+ if header == nil {
+ return nil, nil, nil
+ }
+ stateDb, err := state.New(header.Root, b.eth.chainDb)
+ return EthApiState{stateDb}, header, err
+}
+
+func (b *EthApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {
+ return b.eth.blockchain.GetBlockByHash(blockHash), nil
+}
+
+func (b *EthApiBackend) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) {
+ return core.GetBlockReceipts(b.eth.chainDb, blockHash, core.GetBlockNumber(b.eth.chainDb, blockHash)), nil
+}
+
+func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int {
+ return b.eth.blockchain.GetTdByHash(blockHash)
+}
+
+func (b *EthApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header) (vm.Environment, func() error, error) {
+ stateDb := state.(EthApiState).state.Copy()
+ addr, _ := msg.From()
+ from := stateDb.GetOrNewStateObject(addr)
+ from.SetBalance(common.MaxBig)
+ vmError := func() error { return nil }
+ return core.NewEnv(stateDb, b.eth.chainConfig, b.eth.blockchain, msg, header, b.eth.chainConfig.VmConfig), vmError, nil
+}
+
+func (b *EthApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
+ b.eth.txMu.Lock()
+ defer b.eth.txMu.Unlock()
+
+ b.eth.txPool.SetLocal(signedTx)
+ return b.eth.txPool.Add(signedTx)
+}
+
+func (b *EthApiBackend) RemoveTx(txHash common.Hash) {
+ b.eth.txMu.Lock()
+ defer b.eth.txMu.Unlock()
+
+ b.eth.txPool.RemoveTx(txHash)
+}
+
+func (b *EthApiBackend) GetPoolTransactions() types.Transactions {
+ b.eth.txMu.Lock()
+ defer b.eth.txMu.Unlock()
+
+ return b.eth.txPool.GetTransactions()
+}
+
+func (b *EthApiBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction {
+ b.eth.txMu.Lock()
+ defer b.eth.txMu.Unlock()
+
+ return b.eth.txPool.GetTransaction(txHash)
+}
+
+func (b *EthApiBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
+ b.eth.txMu.Lock()
+ defer b.eth.txMu.Unlock()
+
+ return b.eth.txPool.State().GetNonce(addr), nil
+}
+
+func (b *EthApiBackend) Stats() (pending int, queued int) {
+ b.eth.txMu.Lock()
+ defer b.eth.txMu.Unlock()
+
+ return b.eth.txPool.Stats()
+}
+
+func (b *EthApiBackend) TxPoolContent() (map[common.Address]map[uint64][]*types.Transaction, map[common.Address]map[uint64][]*types.Transaction) {
+ b.eth.txMu.Lock()
+ defer b.eth.txMu.Unlock()
+
+ return b.eth.TxPool().Content()
+}
+
+func (b *EthApiBackend) Downloader() *downloader.Downloader {
+ return b.eth.Downloader()
+}
+
+func (b *EthApiBackend) ProtocolVersion() int {
+ return b.eth.EthVersion()
+}
+
+func (b *EthApiBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
+ return b.gpo.SuggestPrice(), nil
+}
+
+func (b *EthApiBackend) ChainDb() ethdb.Database {
+ return b.eth.ChainDb()
+}
+
+func (b *EthApiBackend) EventMux() *event.TypeMux {
+ return b.eth.EventMux()
+}
+
+func (b *EthApiBackend) AccountManager() *accounts.Manager {
+ return b.eth.AccountManager()
+}
+
+type EthApiState struct {
+ state *state.StateDB
+}
+
+func (s EthApiState) GetBalance(ctx context.Context, addr common.Address) (*big.Int, error) {
+ return s.state.GetBalance(addr), nil
+}
+
+func (s EthApiState) GetCode(ctx context.Context, addr common.Address) ([]byte, error) {
+ return s.state.GetCode(addr), nil
+}
+
+func (s EthApiState) GetState(ctx context.Context, a common.Address, b common.Hash) (common.Hash, error) {
+ return s.state.GetState(a, b), nil
+}
+
+func (s EthApiState) GetNonce(ctx context.Context, addr common.Address) (uint64, error) {
+ return s.state.GetNonce(addr), nil
+}
diff --git a/eth/backend.go b/eth/backend.go
index 006523484..c8a9af6ee 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -39,8 +39,10 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/filters"
+ "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/miner"
@@ -101,95 +103,86 @@ type Config struct {
TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
}
+// Ethereum implements the Ethereum full node service.
type Ethereum struct {
- chainConfig *core.ChainConfig
+ chainConfig *core.ChainConfig
+ // Channel for shutting down the service
shutdownChan chan bool // Channel for shutting down the ethereum
stopDbUpgrade func() // stop chain db sequential key upgrade
-
- // DB interfaces
- chainDb ethdb.Database // Block chain database
- dappDb ethdb.Database // Dapp database
-
// Handlers
txPool *core.TxPool
txMu sync.Mutex
blockchain *core.BlockChain
- accountManager *accounts.Manager
- pow *ethash.Ethash
protocolManager *ProtocolManager
- SolcPath string
- solc *compiler.Solidity
- gpo *GasPriceOracle
+ // DB interfaces
+ chainDb ethdb.Database // Block chain database
+ dappDb ethdb.Database // Dapp database
- GpoMinGasPrice *big.Int
- GpoMaxGasPrice *big.Int
- GpoFullBlockRatio int
- GpobaseStepDown int
- GpobaseStepUp int
- GpobaseCorrectionFactor int
+ eventMux *event.TypeMux
+ pow *ethash.Ethash
+ httpclient *httpclient.HTTPClient
+ accountManager *accounts.Manager
- httpclient *httpclient.HTTPClient
+ apiBackend *EthApiBackend
- eventMux *event.TypeMux
- miner *miner.Miner
+ miner *miner.Miner
+ Mining bool
+ MinerThreads int
+ AutoDAG bool
+ autodagquit chan bool
+ etherbase common.Address
+ solcPath string
+ solc *compiler.Solidity
- Mining bool
- MinerThreads int
NatSpec bool
- AutoDAG bool
PowTest bool
- autodagquit chan bool
- etherbase common.Address
netVersionId int
- netRPCService *PublicNetAPI
+ netRPCService *ethapi.PublicNetAPI
}
+// New creates a new Ethereum object (including the
+// initialisation of the common Ethereum object)
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
- // Open the chain database and perform any upgrades needed
- chainDb, err := ctx.OpenDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles)
+ chainDb, dappDb, err := CreateDBs(ctx, config)
if err != nil {
return nil, err
}
- if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
- db.Meter("eth/db/chaindata/")
- }
- if err := upgradeChainDatabase(chainDb); err != nil {
- return nil, err
- }
- if err := addMipmapBloomBins(chainDb); err != nil {
+ stopDbUpgrade := upgradeSequentialKeys(chainDb)
+ if err := SetupGenesisBlock(&chainDb, config); err != nil {
return nil, err
}
- stopDbUpgrade := upgradeSequentialKeys(chainDb)
-
- dappDb, err := ctx.OpenDatabase("dapp", config.DatabaseCache, config.DatabaseHandles)
+ pow, err := CreatePoW(config)
if err != nil {
return nil, err
}
- if db, ok := dappDb.(*ethdb.LDBDatabase); ok {
- db.Meter("eth/db/dapp/")
- }
- glog.V(logger.Info).Infof("Protocol Versions: %v, Network Id: %v", ProtocolVersions, config.NetworkId)
- // Load up any custom genesis block if requested
- if len(config.Genesis) > 0 {
- block, err := core.WriteGenesisBlock(chainDb, strings.NewReader(config.Genesis))
- if err != nil {
- return nil, err
- }
- glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
+ eth := &Ethereum{
+ chainDb: chainDb,
+ dappDb: dappDb,
+ eventMux: ctx.EventMux,
+ accountManager: config.AccountManager,
+ pow: pow,
+ shutdownChan: make(chan bool),
+ stopDbUpgrade: stopDbUpgrade,
+ httpclient: httpclient.New(config.DocRoot),
+ netVersionId: config.NetworkId,
+ NatSpec: config.NatSpec,
+ PowTest: config.PowTest,
+ etherbase: config.Etherbase,
+ MinerThreads: config.MinerThreads,
+ AutoDAG: config.AutoDAG,
+ solcPath: config.SolcPath,
}
- // Load up a test setup if directly injected
- if config.TestGenesisState != nil {
- chainDb = config.TestGenesisState
+ if err := upgradeChainDatabase(chainDb); err != nil {
+ return nil, err
}
- if config.TestGenesisBlock != nil {
- core.WriteTd(chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64(), config.TestGenesisBlock.Difficulty())
- core.WriteBlock(chainDb, config.TestGenesisBlock)
- core.WriteCanonicalHash(chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64())
- core.WriteHeadBlockHash(chainDb, config.TestGenesisBlock.Hash())
+ if err := addMipmapBloomBins(chainDb); err != nil {
+ return nil, err
}
+ glog.V(logger.Info).Infof("Protocol Versions: %v, Network Id: %v", ProtocolVersions, config.NetworkId)
+
if !config.SkipBcVersionCheck {
bcVersion := core.GetBlockChainVersion(chainDb)
if bcVersion != config.BlockChainVersion && bcVersion != 0 {
@@ -197,44 +190,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
core.WriteBlockChainVersion(chainDb, config.BlockChainVersion)
}
- glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion)
-
- eth := &Ethereum{
- shutdownChan: make(chan bool),
- stopDbUpgrade: stopDbUpgrade,
- chainDb: chainDb,
- dappDb: dappDb,
- eventMux: ctx.EventMux,
- accountManager: config.AccountManager,
- etherbase: config.Etherbase,
- netVersionId: config.NetworkId,
- NatSpec: config.NatSpec,
- MinerThreads: config.MinerThreads,
- SolcPath: config.SolcPath,
- AutoDAG: config.AutoDAG,
- PowTest: config.PowTest,
- GpoMinGasPrice: config.GpoMinGasPrice,
- GpoMaxGasPrice: config.GpoMaxGasPrice,
- GpoFullBlockRatio: config.GpoFullBlockRatio,
- GpobaseStepDown: config.GpobaseStepDown,
- GpobaseStepUp: config.GpobaseStepUp,
- GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
- httpclient: httpclient.New(config.DocRoot),
- }
- switch {
- case config.PowTest:
- glog.V(logger.Info).Infof("ethash used in test mode")
- eth.pow, err = ethash.NewForTesting()
- if err != nil {
- return nil, err
- }
- case config.PowShared:
- glog.V(logger.Info).Infof("ethash used in shared mode")
- eth.pow = ethash.NewShared()
-
- default:
- eth.pow = ethash.New()
- }
// load the genesis block or write a new one if no genesis
// block is prenent in the database.
@@ -250,6 +205,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if config.ChainConfig == nil {
return nil, errors.New("missing chain config")
}
+ core.WriteChainConfig(chainDb, genesis.Hash(), config.ChainConfig)
+
eth.chainConfig = config.ChainConfig
eth.chainConfig.VmConfig = vm.Config{
EnableJit: config.EnableJit,
@@ -263,8 +220,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
return nil, err
}
- eth.gpo = NewGasPriceOracle(eth)
-
newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
eth.txPool = newPool
@@ -275,13 +230,83 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
eth.miner.SetGasPrice(config.GasPrice)
eth.miner.SetExtra(config.ExtraData)
+ gpoParams := &gasprice.GpoParams{
+ GpoMinGasPrice: config.GpoMinGasPrice,
+ GpoMaxGasPrice: config.GpoMaxGasPrice,
+ GpoFullBlockRatio: config.GpoFullBlockRatio,
+ GpobaseStepDown: config.GpobaseStepDown,
+ GpobaseStepUp: config.GpobaseStepUp,
+ GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
+ }
+ gpo := gasprice.NewGasPriceOracle(eth.blockchain, chainDb, eth.eventMux, gpoParams)
+ eth.apiBackend = &EthApiBackend{eth, gpo}
+
return eth, nil
}
+// CreateDBs creates the chain and dapp databases for an Ethereum service
+func CreateDBs(ctx *node.ServiceContext, config *Config) (chainDb, dappDb ethdb.Database, err error) {
+ // Open the chain database and perform any upgrades needed
+ chainDb, err = ctx.OpenDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles)
+ if err != nil {
+ return nil, nil, err
+ }
+ if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
+ db.Meter("eth/db/chaindata/")
+ }
+
+ dappDb, err = ctx.OpenDatabase("dapp", config.DatabaseCache, config.DatabaseHandles)
+ if err != nil {
+ return nil, nil, err
+ }
+ if db, ok := dappDb.(*ethdb.LDBDatabase); ok {
+ db.Meter("eth/db/dapp/")
+ }
+ return
+}
+
+// SetupGenesisBlock initializes the genesis block for an Ethereum service
+func SetupGenesisBlock(chainDb *ethdb.Database, config *Config) error {
+ // Load up any custom genesis block if requested
+ if len(config.Genesis) > 0 {
+ block, err := core.WriteGenesisBlock(*chainDb, strings.NewReader(config.Genesis))
+ if err != nil {
+ return err
+ }
+ glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
+ }
+ // Load up a test setup if directly injected
+ if config.TestGenesisState != nil {
+ *chainDb = config.TestGenesisState
+ }
+ if config.TestGenesisBlock != nil {
+ core.WriteTd(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64(), config.TestGenesisBlock.Difficulty())
+ core.WriteBlock(*chainDb, config.TestGenesisBlock)
+ core.WriteCanonicalHash(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64())
+ core.WriteHeadBlockHash(*chainDb, config.TestGenesisBlock.Hash())
+ }
+ return nil
+}
+
+// CreatePoW creates the required type of PoW instance for an Ethereum service
+func CreatePoW(config *Config) (*ethash.Ethash, error) {
+ switch {
+ case config.PowTest:
+ glog.V(logger.Info).Infof("ethash used in test mode")
+ return ethash.NewForTesting()
+ case config.PowShared:
+ glog.V(logger.Info).Infof("ethash used in shared mode")
+ return ethash.NewShared(), nil
+
+ default:
+ return ethash.New(), nil
+ }
+}
+
// APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func (s *Ethereum) APIs() []rpc.API {
- return []rpc.API{
+ return append(ethapi.GetAPIs(s.apiBackend, &s.solcPath, &s.solc), []rpc.API{
{
Namespace: "eth",
Version: "1.0",
@@ -290,26 +315,6 @@ func (s *Ethereum) APIs() []rpc.API {
}, {
Namespace: "eth",
Version: "1.0",
- Service: NewPublicAccountAPI(s.accountManager),
- Public: true,
- }, {
- Namespace: "personal",
- Version: "1.0",
- Service: NewPrivateAccountAPI(s),
- Public: false,
- }, {
- Namespace: "eth",
- Version: "1.0",
- Service: NewPublicBlockChainAPI(s.chainConfig, s.blockchain, s.miner, s.chainDb, s.gpo, s.eventMux, s.accountManager),
- Public: true,
- }, {
- Namespace: "eth",
- Version: "1.0",
- Service: NewPublicTransactionPoolAPI(s),
- Public: true,
- }, {
- Namespace: "eth",
- Version: "1.0",
Service: NewPublicMinerAPI(s),
Public: true,
}, {
@@ -323,11 +328,6 @@ func (s *Ethereum) APIs() []rpc.API {
Service: NewPrivateMinerAPI(s),
Public: false,
}, {
- Namespace: "txpool",
- Version: "1.0",
- Service: NewPublicTxPoolAPI(s),
- Public: true,
- }, {
Namespace: "eth",
Version: "1.0",
Service: filters.NewPublicFilterAPI(s.chainDb, s.eventMux),
@@ -355,7 +355,7 @@ func (s *Ethereum) APIs() []rpc.API {
Version: "1.0",
Service: ethreg.NewPrivateRegistarAPI(s.chainConfig, s.blockchain, s.chainDb, s.txPool, s.accountManager),
},
- }
+ }...)
}
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
@@ -388,6 +388,7 @@ func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
+func (s *Ethereum) Pow() *ethash.Ethash { return s.pow }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
func (s *Ethereum) DappDb() ethdb.Database { return s.dappDb }
func (s *Ethereum) IsListening() bool { return true } // Always listening
@@ -404,11 +405,11 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
func (s *Ethereum) Start(srvr *p2p.Server) error {
+ s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion())
if s.AutoDAG {
s.StartAutoDAG()
}
s.protocolManager.Start()
- s.netRPCService = NewPublicNetAPI(srvr, s.NetVersion())
return nil
}
@@ -507,21 +508,6 @@ func (self *Ethereum) HTTPClient() *httpclient.HTTPClient {
return self.httpclient
}
-func (self *Ethereum) Solc() (*compiler.Solidity, error) {
- var err error
- if self.solc == nil {
- self.solc, err = compiler.New(self.SolcPath)
- }
- return self.solc, err
-}
-
-// set in js console via admin interface or wrapper from cli flags
-func (self *Ethereum) SetSolc(solcPath string) (*compiler.Solidity, error) {
- self.SolcPath = solcPath
- self.solc = nil
- return self.Solc()
-}
-
// dagFiles(epoch) returns the two alternative DAG filenames (not a path)
// 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
func dagFiles(epoch uint64) (string, string) {
diff --git a/eth/backend_test.go b/eth/backend_test.go
index cb94adbf0..105d71080 100644
--- a/eth/backend_test.go
+++ b/eth/backend_test.go
@@ -32,7 +32,7 @@ func TestMipmapUpgrade(t *testing.T) {
addr := common.BytesToAddress([]byte("jeff"))
genesis := core.WriteGenesisBlockForTesting(db)
- chain, receipts := core.GenerateChain(genesis, db, 10, func(i int, gen *core.BlockGen) {
+ chain, receipts := core.GenerateChain(nil, genesis, db, 10, func(i int, gen *core.BlockGen) {
var receipts types.Receipts
switch i {
case 1:
diff --git a/eth/bind.go b/eth/bind.go
index fb7f29f60..c1366464f 100644
--- a/eth/bind.go
+++ b/eth/bind.go
@@ -21,8 +21,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
+ "golang.org/x/net/context"
)
// ContractBackend implements bind.ContractBackend with direct calls to Ethereum
@@ -33,38 +35,44 @@ import (
// object. These should be rewritten to internal Go method calls when the Go API
// is refactored to support a clean library use.
type ContractBackend struct {
- eapi *PublicEthereumAPI // Wrapper around the Ethereum object to access metadata
- bcapi *PublicBlockChainAPI // Wrapper around the blockchain to access chain data
- txapi *PublicTransactionPoolAPI // Wrapper around the transaction pool to access transaction data
+ eapi *ethapi.PublicEthereumAPI // Wrapper around the Ethereum object to access metadata
+ bcapi *ethapi.PublicBlockChainAPI // Wrapper around the blockchain to access chain data
+ txapi *ethapi.PublicTransactionPoolAPI // Wrapper around the transaction pool to access transaction data
}
// NewContractBackend creates a new native contract backend using an existing
// Etheruem object.
func NewContractBackend(eth *Ethereum) *ContractBackend {
return &ContractBackend{
- eapi: NewPublicEthereumAPI(eth),
- bcapi: NewPublicBlockChainAPI(eth.chainConfig, eth.blockchain, eth.miner, eth.chainDb, eth.gpo, eth.eventMux, eth.accountManager),
- txapi: NewPublicTransactionPoolAPI(eth),
+ eapi: ethapi.NewPublicEthereumAPI(eth.apiBackend, nil, nil),
+ bcapi: ethapi.NewPublicBlockChainAPI(eth.apiBackend),
+ txapi: ethapi.NewPublicTransactionPoolAPI(eth.apiBackend),
}
}
// HasCode implements bind.ContractVerifier.HasCode by retrieving any code associated
// with the contract from the local API, and checking its size.
-func (b *ContractBackend) HasCode(contract common.Address, pending bool) (bool, error) {
+func (b *ContractBackend) HasCode(ctx context.Context, contract common.Address, pending bool) (bool, error) {
+ if ctx == nil {
+ ctx = context.Background()
+ }
block := rpc.LatestBlockNumber
if pending {
block = rpc.PendingBlockNumber
}
- out, err := b.bcapi.GetCode(contract, block)
+ out, err := b.bcapi.GetCode(ctx, contract, block)
return len(common.FromHex(out)) > 0, err
}
// ContractCall implements bind.ContractCaller executing an Ethereum contract
// call with the specified data as the input. The pending flag requests execution
// against the pending block, not the stable head of the chain.
-func (b *ContractBackend) ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error) {
+func (b *ContractBackend) ContractCall(ctx context.Context, contract common.Address, data []byte, pending bool) ([]byte, error) {
+ if ctx == nil {
+ ctx = context.Background()
+ }
// Convert the input args to the API spec
- args := CallArgs{
+ args := ethapi.CallArgs{
To: &contract,
Data: common.ToHex(data),
}
@@ -73,21 +81,27 @@ func (b *ContractBackend) ContractCall(contract common.Address, data []byte, pen
block = rpc.PendingBlockNumber
}
// Execute the call and convert the output back to Go types
- out, err := b.bcapi.Call(args, block)
+ out, err := b.bcapi.Call(ctx, args, block)
return common.FromHex(out), err
}
// PendingAccountNonce implements bind.ContractTransactor retrieving the current
// pending nonce associated with an account.
-func (b *ContractBackend) PendingAccountNonce(account common.Address) (uint64, error) {
- out, err := b.txapi.GetTransactionCount(account, rpc.PendingBlockNumber)
+func (b *ContractBackend) PendingAccountNonce(ctx context.Context, account common.Address) (uint64, error) {
+ if ctx == nil {
+ ctx = context.Background()
+ }
+ out, err := b.txapi.GetTransactionCount(ctx, account, rpc.PendingBlockNumber)
return out.Uint64(), err
}
// SuggestGasPrice implements bind.ContractTransactor retrieving the currently
// suggested gas price to allow a timely execution of a transaction.
-func (b *ContractBackend) SuggestGasPrice() (*big.Int, error) {
- return b.eapi.GasPrice(), nil
+func (b *ContractBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
+ if ctx == nil {
+ ctx = context.Background()
+ }
+ return b.eapi.GasPrice(ctx)
}
// EstimateGasLimit implements bind.ContractTransactor triing to estimate the gas
@@ -95,8 +109,11 @@ func (b *ContractBackend) SuggestGasPrice() (*big.Int, error) {
// the backend blockchain. There is no guarantee that this is the true gas limit
// requirement as other transactions may be added or removed by miners, but it
// should provide a basis for setting a reasonable default.
-func (b *ContractBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
- out, err := b.bcapi.EstimateGas(CallArgs{
+func (b *ContractBackend) EstimateGasLimit(ctx context.Context, sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
+ if ctx == nil {
+ ctx = context.Background()
+ }
+ out, err := b.bcapi.EstimateGas(ctx, ethapi.CallArgs{
From: sender,
To: contract,
Value: *rpc.NewHexNumber(value),
@@ -107,8 +124,11 @@ func (b *ContractBackend) EstimateGasLimit(sender common.Address, contract *comm
// SendTransaction implements bind.ContractTransactor injects the transaction
// into the pending pool for execution.
-func (b *ContractBackend) SendTransaction(tx *types.Transaction) error {
+func (b *ContractBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
+ if ctx == nil {
+ ctx = context.Background()
+ }
raw, _ := rlp.EncodeToBytes(tx)
- _, err := b.txapi.SendRawTransaction(common.ToHex(raw))
+ _, err := b.txapi.SendRawTransaction(ctx, common.ToHex(raw))
return err
}
diff --git a/eth/db_upgrade.go b/eth/db_upgrade.go
index 12de60fe7..172bb0954 100644
--- a/eth/db_upgrade.go
+++ b/eth/db_upgrade.go
@@ -93,6 +93,9 @@ func upgradeSequentialKeys(db ethdb.Database) (stopFn func()) {
func upgradeSequentialCanonicalNumbers(db ethdb.Database, stopFn func() bool) (error, bool) {
prefix := []byte("block-num-")
it := db.(*ethdb.LDBDatabase).NewIterator()
+ defer func() {
+ it.Release()
+ }()
it.Seek(prefix)
cnt := 0
for bytes.HasPrefix(it.Key(), prefix) {
@@ -100,6 +103,9 @@ func upgradeSequentialCanonicalNumbers(db ethdb.Database, stopFn func() bool) (e
if len(keyPtr) < 20 {
cnt++
if cnt%100000 == 0 {
+ it.Release()
+ it = db.(*ethdb.LDBDatabase).NewIterator()
+ it.Seek(keyPtr)
glog.V(logger.Info).Infof("converting %d canonical numbers...", cnt)
}
number := big.NewInt(0).SetBytes(keyPtr[10:]).Uint64()
@@ -130,6 +136,9 @@ func upgradeSequentialCanonicalNumbers(db ethdb.Database, stopFn func() bool) (e
func upgradeSequentialBlocks(db ethdb.Database, stopFn func() bool) (error, bool) {
prefix := []byte("block-")
it := db.(*ethdb.LDBDatabase).NewIterator()
+ defer func() {
+ it.Release()
+ }()
it.Seek(prefix)
cnt := 0
for bytes.HasPrefix(it.Key(), prefix) {
@@ -137,6 +146,9 @@ func upgradeSequentialBlocks(db ethdb.Database, stopFn func() bool) (error, bool
if len(keyPtr) >= 38 {
cnt++
if cnt%10000 == 0 {
+ it.Release()
+ it = db.(*ethdb.LDBDatabase).NewIterator()
+ it.Seek(keyPtr)
glog.V(logger.Info).Infof("converting %d blocks...", cnt)
}
// convert header, body, td and block receipts
@@ -175,6 +187,7 @@ func upgradeSequentialBlocks(db ethdb.Database, stopFn func() bool) (error, bool
func upgradeSequentialOrphanedReceipts(db ethdb.Database, stopFn func() bool) (error, bool) {
prefix := []byte("receipts-block-")
it := db.(*ethdb.LDBDatabase).NewIterator()
+ defer it.Release()
it.Seek(prefix)
cnt := 0
for bytes.HasPrefix(it.Key(), prefix) {
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 92124cfeb..aee21122a 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -48,23 +48,17 @@ var (
MaxReceiptFetch = 256 // Amount of transaction receipts to allow fetching per request
MaxStateFetch = 384 // Amount of node state values to allow fetching per request
- MaxForkAncestry = 3 * params.EpochDuration.Uint64() // Maximum chain reorganisation
-
- hashTTL = 3 * time.Second // [eth/61] Time it takes for a hash request to time out
- blockTargetRTT = 3 * time.Second / 2 // [eth/61] Target time for completing a block retrieval request
- blockTTL = 3 * blockTargetRTT // [eth/61] Maximum time allowance before a block request is considered expired
-
- rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests
- rttMaxEstimate = 20 * time.Second // Maximum rount-trip time to target for download requests
- rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value
- ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion
- ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts
+ MaxForkAncestry = 3 * params.EpochDuration.Uint64() // Maximum chain reorganisation
+ rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests
+ rttMaxEstimate = 20 * time.Second // Maximum rount-trip time to target for download requests
+ rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value
+ ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion
+ ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts
qosTuningPeers = 5 // Number of peers to tune based on (best peers)
qosConfidenceCap = 10 // Number of peers above which not to modify RTT confidence
qosTuningImpact = 0.25 // Impact that a new tuning target has on the previous value
- maxQueuedHashes = 32 * 1024 // [eth/61] Maximum number of hashes to queue for import (DOS protection)
maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection)
maxHeadersProcess = 2048 // Number of header download results to import at once into the chain
maxResultsProcess = 2048 // Number of content download results to import at once into the chain
@@ -84,16 +78,13 @@ var (
errStallingPeer = errors.New("peer is stalling")
errNoPeers = errors.New("no peers to keep download active")
errTimeout = errors.New("timeout")
- errEmptyHashSet = errors.New("empty hash set by peer")
errEmptyHeaderSet = errors.New("empty header set by peer")
errPeersUnavailable = errors.New("no peers available or all tried for download")
- errAlreadyInPool = errors.New("hash already in pool")
errInvalidAncestor = errors.New("retrieved ancestor is invalid")
errInvalidChain = errors.New("retrieved hash chain is invalid")
errInvalidBlock = errors.New("retrieved block is invalid")
errInvalidBody = errors.New("retrieved block body is invalid")
errInvalidReceipt = errors.New("retrieved receipt is invalid")
- errCancelHashFetch = errors.New("hash download canceled (requested)")
errCancelBlockFetch = errors.New("block download canceled (requested)")
errCancelHeaderFetch = errors.New("block header download canceled (requested)")
errCancelBodyFetch = errors.New("block body download canceled (requested)")
@@ -102,6 +93,7 @@ var (
errCancelHeaderProcessing = errors.New("header processing canceled (requested)")
errCancelContentProcessing = errors.New("content processing canceled (requested)")
errNoSyncActive = errors.New("no sync active")
+ errTooOld = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)")
)
type Downloader struct {
@@ -146,13 +138,10 @@ type Downloader struct {
// Channels
newPeerCh chan *peer
- hashCh chan dataPack // [eth/61] Channel receiving inbound hashes
- blockCh chan dataPack // [eth/61] Channel receiving inbound blocks
headerCh chan dataPack // [eth/62] Channel receiving inbound block headers
bodyCh chan dataPack // [eth/62] Channel receiving inbound block bodies
receiptCh chan dataPack // [eth/63] Channel receiving inbound receipts
stateCh chan dataPack // [eth/63] Channel receiving inbound node state data
- blockWakeCh chan bool // [eth/61] Channel to signal the block fetcher of new tasks
bodyWakeCh chan bool // [eth/62] Channel to signal the block body fetcher of new tasks
receiptWakeCh chan bool // [eth/63] Channel to signal the receipt fetcher of new tasks
stateWakeCh chan bool // [eth/63] Channel to signal the state fetcher of new tasks
@@ -199,13 +188,10 @@ func New(stateDb ethdb.Database, mux *event.TypeMux, hasHeader headerCheckFn, ha
rollback: rollback,
dropPeer: dropPeer,
newPeerCh: make(chan *peer, 1),
- hashCh: make(chan dataPack, 1),
- blockCh: make(chan dataPack, 1),
headerCh: make(chan dataPack, 1),
bodyCh: make(chan dataPack, 1),
receiptCh: make(chan dataPack, 1),
stateCh: make(chan dataPack, 1),
- blockWakeCh: make(chan bool, 1),
bodyWakeCh: make(chan bool, 1),
receiptWakeCh: make(chan bool, 1),
stateWakeCh: make(chan bool, 1),
@@ -251,12 +237,11 @@ func (d *Downloader) Synchronising() bool {
// RegisterPeer injects a new download peer into the set of block source to be
// used for fetching hashes and blocks from.
func (d *Downloader) RegisterPeer(id string, version int, head common.Hash,
- getRelHashes relativeHashFetcherFn, getAbsHashes absoluteHashFetcherFn, getBlocks blockFetcherFn, // eth/61 callbacks, remove when upgrading
getRelHeaders relativeHeaderFetcherFn, getAbsHeaders absoluteHeaderFetcherFn, getBlockBodies blockBodyFetcherFn,
getReceipts receiptFetcherFn, getNodeData stateFetcherFn) error {
glog.V(logger.Detail).Infoln("Registering peer", id)
- if err := d.peers.Register(newPeer(id, version, head, getRelHashes, getAbsHashes, getBlocks, getRelHeaders, getAbsHeaders, getBlockBodies, getReceipts, getNodeData)); err != nil {
+ if err := d.peers.Register(newPeer(id, version, head, getRelHeaders, getAbsHeaders, getBlockBodies, getReceipts, getNodeData)); err != nil {
glog.V(logger.Error).Infoln("Register failed:", err)
return err
}
@@ -291,7 +276,9 @@ func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode
case errBusy:
glog.V(logger.Detail).Infof("Synchronisation already in progress")
- case errTimeout, errBadPeer, errStallingPeer, errEmptyHashSet, errEmptyHeaderSet, errPeersUnavailable, errInvalidAncestor, errInvalidChain:
+ case errTimeout, errBadPeer, errStallingPeer,
+ errEmptyHeaderSet, errPeersUnavailable, errTooOld,
+ errInvalidAncestor, errInvalidChain:
glog.V(logger.Debug).Infof("Removing peer %v: %v", id, err)
d.dropPeer(id)
@@ -323,13 +310,13 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode
d.queue.Reset()
d.peers.Reset()
- for _, ch := range []chan bool{d.blockWakeCh, d.bodyWakeCh, d.receiptWakeCh, d.stateWakeCh} {
+ for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh, d.stateWakeCh} {
select {
case <-ch:
default:
}
}
- for _, ch := range []chan dataPack{d.hashCh, d.blockCh, d.headerCh, d.bodyCh, d.receiptCh, d.stateCh} {
+ for _, ch := range []chan dataPack{d.headerCh, d.bodyCh, d.receiptCh, d.stateCh} {
for empty := false; !empty; {
select {
case <-ch:
@@ -377,105 +364,73 @@ func (d *Downloader) syncWithPeer(p *peer, hash common.Hash, td *big.Int) (err e
d.mux.Post(DoneEvent{})
}
}()
+ if p.version < 62 {
+ return errTooOld
+ }
glog.V(logger.Debug).Infof("Synchronising with the network using: %s [eth/%d]", p.id, p.version)
defer func(start time.Time) {
glog.V(logger.Debug).Infof("Synchronisation terminated after %v", time.Since(start))
}(time.Now())
- switch {
- case p.version == 61:
- // Look up the sync boundaries: the common ancestor and the target block
- latest, err := d.fetchHeight61(p)
- if err != nil {
- return err
- }
- origin, err := d.findAncestor61(p, latest)
- if err != nil {
- return err
- }
- d.syncStatsLock.Lock()
- if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin {
- d.syncStatsChainOrigin = origin
- }
- d.syncStatsChainHeight = latest
- d.syncStatsLock.Unlock()
+ // Look up the sync boundaries: the common ancestor and the target block
+ latest, err := d.fetchHeight(p)
+ if err != nil {
+ return err
+ }
+ height := latest.Number.Uint64()
- // Initiate the sync using a concurrent hash and block retrieval algorithm
- d.queue.Prepare(origin+1, d.mode, 0, nil)
- if d.syncInitHook != nil {
- d.syncInitHook(origin, latest)
- }
- return d.spawnSync(origin+1,
- func() error { return d.fetchHashes61(p, td, origin+1) },
- func() error { return d.fetchBlocks61(origin + 1) },
- )
-
- case p.version >= 62:
- // Look up the sync boundaries: the common ancestor and the target block
- latest, err := d.fetchHeight(p)
- if err != nil {
- return err
- }
- height := latest.Number.Uint64()
+ origin, err := d.findAncestor(p, height)
+ if err != nil {
+ return err
+ }
+ d.syncStatsLock.Lock()
+ if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin {
+ d.syncStatsChainOrigin = origin
+ }
+ d.syncStatsChainHeight = height
+ d.syncStatsLock.Unlock()
- origin, err := d.findAncestor(p, height)
- if err != nil {
- return err
- }
- d.syncStatsLock.Lock()
- if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin {
- d.syncStatsChainOrigin = origin
- }
- d.syncStatsChainHeight = height
- d.syncStatsLock.Unlock()
-
- // Initiate the sync using a concurrent header and content retrieval algorithm
- pivot := uint64(0)
- switch d.mode {
- case LightSync:
- pivot = height
- case FastSync:
- // Calculate the new fast/slow sync pivot point
- if d.fsPivotLock == nil {
- pivotOffset, err := rand.Int(rand.Reader, big.NewInt(int64(fsPivotInterval)))
- if err != nil {
- panic(fmt.Sprintf("Failed to access crypto random source: %v", err))
- }
- if height > uint64(fsMinFullBlocks)+pivotOffset.Uint64() {
- pivot = height - uint64(fsMinFullBlocks) - pivotOffset.Uint64()
- }
- } else {
- // Pivot point locked in, use this and do not pick a new one!
- pivot = d.fsPivotLock.Number.Uint64()
+ // Initiate the sync using a concurrent header and content retrieval algorithm
+ pivot := uint64(0)
+ switch d.mode {
+ case LightSync:
+ pivot = height
+ case FastSync:
+ // Calculate the new fast/slow sync pivot point
+ if d.fsPivotLock == nil {
+ pivotOffset, err := rand.Int(rand.Reader, big.NewInt(int64(fsPivotInterval)))
+ if err != nil {
+ panic(fmt.Sprintf("Failed to access crypto random source: %v", err))
}
- // If the point is below the origin, move origin back to ensure state download
- if pivot < origin {
- if pivot > 0 {
- origin = pivot - 1
- } else {
- origin = 0
- }
+ if height > uint64(fsMinFullBlocks)+pivotOffset.Uint64() {
+ pivot = height - uint64(fsMinFullBlocks) - pivotOffset.Uint64()
}
- glog.V(logger.Debug).Infof("Fast syncing until pivot block #%d", pivot)
+ } else {
+ // Pivot point locked in, use this and do not pick a new one!
+ pivot = d.fsPivotLock.Number.Uint64()
}
- d.queue.Prepare(origin+1, d.mode, pivot, latest)
- if d.syncInitHook != nil {
- d.syncInitHook(origin, height)
+ // If the point is below the origin, move origin back to ensure state download
+ if pivot < origin {
+ if pivot > 0 {
+ origin = pivot - 1
+ } else {
+ origin = 0
+ }
}
- return d.spawnSync(origin+1,
- func() error { return d.fetchHeaders(p, origin+1) }, // Headers are always retrieved
- func() error { return d.processHeaders(origin+1, td) }, // Headers are always retrieved
- func() error { return d.fetchBodies(origin + 1) }, // Bodies are retrieved during normal and fast sync
- func() error { return d.fetchReceipts(origin + 1) }, // Receipts are retrieved during fast sync
- func() error { return d.fetchNodeData() }, // Node state data is retrieved during fast sync
- )
-
- default:
- // Something very wrong, stop right here
- glog.V(logger.Error).Infof("Unsupported eth protocol: %d", p.version)
- return errBadPeer
+ glog.V(logger.Debug).Infof("Fast syncing until pivot block #%d", pivot)
+ }
+ d.queue.Prepare(origin+1, d.mode, pivot, latest)
+ if d.syncInitHook != nil {
+ d.syncInitHook(origin, height)
}
+ return d.spawnSync(origin+1,
+ func() error { return d.fetchHeaders(p, origin+1) }, // Headers are always retrieved
+ func() error { return d.processHeaders(origin+1, td) }, // Headers are always retrieved
+ func() error { return d.fetchBodies(origin + 1) }, // Bodies are retrieved during normal and fast sync
+ func() error { return d.fetchReceipts(origin + 1) }, // Receipts are retrieved during fast sync
+ func() error { return d.fetchNodeData() }, // Node state data is retrieved during fast sync
+ )
}
// spawnSync runs d.process and all given fetcher functions to completion in
@@ -540,452 +495,6 @@ func (d *Downloader) Terminate() {
d.cancel()
}
-// fetchHeight61 retrieves the head block of the remote peer to aid in estimating
-// the total time a pending synchronisation would take.
-func (d *Downloader) fetchHeight61(p *peer) (uint64, error) {
- glog.V(logger.Debug).Infof("%v: retrieving remote chain height", p)
-
- // Request the advertised remote head block and wait for the response
- go p.getBlocks([]common.Hash{p.head})
-
- timeout := time.After(hashTTL)
- for {
- select {
- case <-d.cancelCh:
- return 0, errCancelBlockFetch
-
- case packet := <-d.blockCh:
- // Discard anything not from the origin peer
- if packet.PeerId() != p.id {
- glog.V(logger.Debug).Infof("Received blocks from incorrect peer(%s)", packet.PeerId())
- break
- }
- // Make sure the peer actually gave something valid
- blocks := packet.(*blockPack).blocks
- if len(blocks) != 1 {
- glog.V(logger.Debug).Infof("%v: invalid number of head blocks: %d != 1", p, len(blocks))
- return 0, errBadPeer
- }
- return blocks[0].NumberU64(), nil
-
- case <-timeout:
- glog.V(logger.Debug).Infof("%v: head block timeout", p)
- return 0, errTimeout
-
- case <-d.hashCh:
- // Out of bounds hashes received, ignore them
-
- case <-d.headerCh:
- case <-d.bodyCh:
- case <-d.stateCh:
- case <-d.receiptCh:
- // Ignore eth/{62,63} packets because this is eth/61.
- // These can arrive as a late delivery from a previous sync.
- }
- }
-}
-
-// findAncestor61 tries to locate the common ancestor block of the local chain and
-// a remote peers blockchain. In the general case when our node was in sync and
-// on the correct chain, checking the top N blocks should already get us a match.
-// In the rare scenario when we ended up on a long reorganisation (i.e. none of
-// the head blocks match), we do a binary search to find the common ancestor.
-func (d *Downloader) findAncestor61(p *peer, height uint64) (uint64, error) {
- glog.V(logger.Debug).Infof("%v: looking for common ancestor", p)
-
- // Figure out the valid ancestor range to prevent rewrite attacks
- floor, ceil := int64(-1), d.headBlock().NumberU64()
- if ceil >= MaxForkAncestry {
- floor = int64(ceil - MaxForkAncestry)
- }
- // Request the topmost blocks to short circuit binary ancestor lookup
- head := ceil
- if head > height {
- head = height
- }
- from := int64(head) - int64(MaxHashFetch) + 1
- if from < 0 {
- from = 0
- }
- go p.getAbsHashes(uint64(from), MaxHashFetch)
-
- // Wait for the remote response to the head fetch
- number, hash := uint64(0), common.Hash{}
- timeout := time.After(hashTTL)
-
- for finished := false; !finished; {
- select {
- case <-d.cancelCh:
- return 0, errCancelHashFetch
-
- case packet := <-d.hashCh:
- // Discard anything not from the origin peer
- if packet.PeerId() != p.id {
- glog.V(logger.Debug).Infof("Received hashes from incorrect peer(%s)", packet.PeerId())
- break
- }
- // Make sure the peer actually gave something valid
- hashes := packet.(*hashPack).hashes
- if len(hashes) == 0 {
- glog.V(logger.Debug).Infof("%v: empty head hash set", p)
- return 0, errEmptyHashSet
- }
- // Check if a common ancestor was found
- finished = true
- for i := len(hashes) - 1; i >= 0; i-- {
- // Skip any headers that underflow/overflow our requested set
- header := d.getHeader(hashes[i])
- if header == nil || header.Number.Int64() < from || header.Number.Uint64() > head {
- continue
- }
- // Otherwise check if we already know the header or not
- if d.hasBlockAndState(hashes[i]) {
- number, hash = header.Number.Uint64(), header.Hash()
- break
- }
- }
-
- case <-timeout:
- glog.V(logger.Debug).Infof("%v: head hash timeout", p)
- return 0, errTimeout
-
- case <-d.blockCh:
- // Out of bounds blocks received, ignore them
-
- case <-d.headerCh:
- case <-d.bodyCh:
- case <-d.stateCh:
- case <-d.receiptCh:
- // Ignore eth/{62,63} packets because this is eth/61.
- // These can arrive as a late delivery from a previous sync.
- }
- }
- // If the head fetch already found an ancestor, return
- if !common.EmptyHash(hash) {
- if int64(number) <= floor {
- glog.V(logger.Warn).Infof("%v: potential rewrite attack: #%d [%x…] <= #%d limit", p, number, hash[:4], floor)
- return 0, errInvalidAncestor
- }
- glog.V(logger.Debug).Infof("%v: common ancestor: #%d [%x…]", p, number, hash[:4])
- return number, nil
- }
- // Ancestor not found, we need to binary search over our chain
- start, end := uint64(0), head
- if floor > 0 {
- start = uint64(floor)
- }
- for start+1 < end {
- // Split our chain interval in two, and request the hash to cross check
- check := (start + end) / 2
-
- timeout := time.After(hashTTL)
- go p.getAbsHashes(uint64(check), 1)
-
- // Wait until a reply arrives to this request
- for arrived := false; !arrived; {
- select {
- case <-d.cancelCh:
- return 0, errCancelHashFetch
-
- case packet := <-d.hashCh:
- // Discard anything not from the origin peer
- if packet.PeerId() != p.id {
- glog.V(logger.Debug).Infof("Received hashes from incorrect peer(%s)", packet.PeerId())
- break
- }
- // Make sure the peer actually gave something valid
- hashes := packet.(*hashPack).hashes
- if len(hashes) != 1 {
- glog.V(logger.Debug).Infof("%v: invalid search hash set (%d)", p, len(hashes))
- return 0, errBadPeer
- }
- arrived = true
-
- // Modify the search interval based on the response
- if !d.hasBlockAndState(hashes[0]) {
- end = check
- break
- }
- block := d.getBlock(hashes[0]) // this doesn't check state, hence the above explicit check
- if block.NumberU64() != check {
- glog.V(logger.Debug).Infof("%v: non requested hash #%d [%x…], instead of #%d", p, block.NumberU64(), block.Hash().Bytes()[:4], check)
- return 0, errBadPeer
- }
- start = check
-
- case <-timeout:
- glog.V(logger.Debug).Infof("%v: search hash timeout", p)
- return 0, errTimeout
-
- case <-d.blockCh:
- // Out of bounds blocks received, ignore them
-
- case <-d.headerCh:
- case <-d.bodyCh:
- case <-d.stateCh:
- case <-d.receiptCh:
- // Ignore eth/{62,63} packets because this is eth/61.
- // These can arrive as a late delivery from a previous sync.
- }
- }
- }
- // Ensure valid ancestry and return
- if int64(start) <= floor {
- glog.V(logger.Warn).Infof("%v: potential rewrite attack: #%d [%x…] <= #%d limit", p, start, hash[:4], floor)
- return 0, errInvalidAncestor
- }
- glog.V(logger.Debug).Infof("%v: common ancestor: #%d [%x…]", p, start, hash[:4])
- return start, nil
-}
-
-// fetchHashes61 keeps retrieving hashes from the requested number, until no more
-// are returned, potentially throttling on the way.
-func (d *Downloader) fetchHashes61(p *peer, td *big.Int, from uint64) error {
- glog.V(logger.Debug).Infof("%v: downloading hashes from #%d", p, from)
-
- // Create a timeout timer, and the associated hash fetcher
- request := time.Now() // time of the last fetch request
- timeout := time.NewTimer(0) // timer to dump a non-responsive active peer
- <-timeout.C // timeout channel should be initially empty
- defer timeout.Stop()
-
- getHashes := func(from uint64) {
- glog.V(logger.Detail).Infof("%v: fetching %d hashes from #%d", p, MaxHashFetch, from)
-
- request = time.Now()
- timeout.Reset(hashTTL)
- go p.getAbsHashes(from, MaxHashFetch)
- }
- // Start pulling hashes, until all are exhausted
- getHashes(from)
- gotHashes := false
-
- for {
- select {
- case <-d.cancelCh:
- return errCancelHashFetch
-
- case packet := <-d.hashCh:
- // Make sure the active peer is giving us the hashes
- if packet.PeerId() != p.id {
- glog.V(logger.Debug).Infof("Received hashes from incorrect peer(%s)", packet.PeerId())
- break
- }
- hashReqTimer.UpdateSince(request)
- timeout.Stop()
-
- // If no more hashes are inbound, notify the block fetcher and return
- if packet.Items() == 0 {
- glog.V(logger.Debug).Infof("%v: no available hashes", p)
-
- select {
- case d.blockWakeCh <- false:
- case <-d.cancelCh:
- }
- // If no hashes were retrieved at all, the peer violated it's TD promise that it had a
- // better chain compared to ours. The only exception is if it's promised blocks were
- // already imported by other means (e.g. fetcher):
- //
- // R <remote peer>, L <local node>: Both at block 10
- // R: Mine block 11, and propagate it to L
- // L: Queue block 11 for import
- // L: Notice that R's head and TD increased compared to ours, start sync
- // L: Import of block 11 finishes
- // L: Sync begins, and finds common ancestor at 11
- // L: Request new hashes up from 11 (R's TD was higher, it must have something)
- // R: Nothing to give
- if !gotHashes && td.Cmp(d.getTd(d.headBlock().Hash())) > 0 {
- return errStallingPeer
- }
- return nil
- }
- gotHashes = true
- hashes := packet.(*hashPack).hashes
-
- // Otherwise insert all the new hashes, aborting in case of junk
- glog.V(logger.Detail).Infof("%v: scheduling %d hashes from #%d", p, len(hashes), from)
-
- inserts := d.queue.Schedule61(hashes, true)
- if len(inserts) != len(hashes) {
- glog.V(logger.Debug).Infof("%v: stale hashes", p)
- return errBadPeer
- }
- // Notify the block fetcher of new hashes, but stop if queue is full
- if d.queue.PendingBlocks() < maxQueuedHashes {
- // We still have hashes to fetch, send continuation wake signal (potential)
- select {
- case d.blockWakeCh <- true:
- default:
- }
- } else {
- // Hash limit reached, send a termination wake signal (enforced)
- select {
- case d.blockWakeCh <- false:
- case <-d.cancelCh:
- }
- return nil
- }
- // Queue not yet full, fetch the next batch
- from += uint64(len(hashes))
- getHashes(from)
-
- case <-timeout.C:
- glog.V(logger.Debug).Infof("%v: hash request timed out", p)
- hashTimeoutMeter.Mark(1)
- return errTimeout
-
- case <-d.headerCh:
- case <-d.bodyCh:
- case <-d.stateCh:
- case <-d.receiptCh:
- // Ignore eth/{62,63} packets because this is eth/61.
- // These can arrive as a late delivery from a previous sync.
- }
- }
-}
-
-// fetchBlocks61 iteratively downloads the scheduled hashes, taking any available
-// peers, reserving a chunk of blocks for each, waiting for delivery and also
-// periodically checking for timeouts.
-func (d *Downloader) fetchBlocks61(from uint64) error {
- glog.V(logger.Debug).Infof("Downloading blocks from #%d", from)
- defer glog.V(logger.Debug).Infof("Block download terminated")
-
- // Create a timeout timer for scheduling expiration tasks
- ticker := time.NewTicker(100 * time.Millisecond)
- defer ticker.Stop()
-
- update := make(chan struct{}, 1)
-
- // Fetch blocks until the hash fetcher's done
- finished := false
- for {
- select {
- case <-d.cancelCh:
- return errCancelBlockFetch
-
- case packet := <-d.blockCh:
- // If the peer was previously banned and failed to deliver it's pack
- // in a reasonable time frame, ignore it's message.
- if peer := d.peers.Peer(packet.PeerId()); peer != nil {
- blocks := packet.(*blockPack).blocks
-
- // Deliver the received chunk of blocks and check chain validity
- accepted, err := d.queue.DeliverBlocks(peer.id, blocks)
- if err == errInvalidChain {
- return err
- }
- // Unless a peer delivered something completely else than requested (usually
- // caused by a timed out request which came through in the end), set it to
- // idle. If the delivery's stale, the peer should have already been idled.
- if err != errStaleDelivery {
- peer.SetBlocksIdle(accepted)
- }
- // Issue a log to the user to see what's going on
- switch {
- case err == nil && len(blocks) == 0:
- glog.V(logger.Detail).Infof("%s: no blocks delivered", peer)
- case err == nil:
- glog.V(logger.Detail).Infof("%s: delivered %d blocks", peer, len(blocks))
- default:
- glog.V(logger.Detail).Infof("%s: delivery failed: %v", peer, err)
- }
- }
- // Blocks arrived, try to update the progress
- select {
- case update <- struct{}{}:
- default:
- }
-
- case cont := <-d.blockWakeCh:
- // The hash fetcher sent a continuation flag, check if it's done
- if !cont {
- finished = true
- }
- // Hashes arrive, try to update the progress
- select {
- case update <- struct{}{}:
- default:
- }
-
- case <-ticker.C:
- // Sanity check update the progress
- select {
- case update <- struct{}{}:
- default:
- }
-
- case <-update:
- // Short circuit if we lost all our peers
- if d.peers.Len() == 0 {
- return errNoPeers
- }
- // Check for block request timeouts and demote the responsible peers
- for pid, fails := range d.queue.ExpireBlocks(blockTTL) {
- if peer := d.peers.Peer(pid); peer != nil {
- if fails > 1 {
- glog.V(logger.Detail).Infof("%s: block delivery timeout", peer)
- peer.SetBlocksIdle(0)
- } else {
- glog.V(logger.Debug).Infof("%s: stalling block delivery, dropping", peer)
- d.dropPeer(pid)
- }
- }
- }
- // If there's nothing more to fetch, wait or terminate
- if d.queue.PendingBlocks() == 0 {
- if !d.queue.InFlightBlocks() && finished {
- glog.V(logger.Debug).Infof("Block fetching completed")
- return nil
- }
- break
- }
- // Send a download request to all idle peers, until throttled
- throttled := false
- idles, total := d.peers.BlockIdlePeers()
-
- for _, peer := range idles {
- // Short circuit if throttling activated
- if d.queue.ShouldThrottleBlocks() {
- throttled = true
- break
- }
- // Reserve a chunk of hashes for a peer. A nil can mean either that
- // no more hashes are available, or that the peer is known not to
- // have them.
- request := d.queue.ReserveBlocks(peer, peer.BlockCapacity(blockTargetRTT))
- if request == nil {
- continue
- }
- if glog.V(logger.Detail) {
- glog.Infof("%s: requesting %d blocks", peer, len(request.Hashes))
- }
- // Fetch the chunk and make sure any errors return the hashes to the queue
- if err := peer.Fetch61(request); err != nil {
- // Although we could try and make an attempt to fix this, this error really
- // means that we've double allocated a fetch task to a peer. If that is the
- // case, the internal state of the downloader and the queue is very wrong so
- // better hard crash and note the error instead of silently accumulating into
- // a much bigger issue.
- panic(fmt.Sprintf("%v: fetch assignment failed", peer))
- }
- }
- // Make sure that we have peers available for fetching. If all peers have been tried
- // and all failed throw an error
- if !throttled && !d.queue.InFlightBlocks() && len(idles) == total {
- return errPeersUnavailable
- }
-
- case <-d.headerCh:
- case <-d.bodyCh:
- case <-d.stateCh:
- case <-d.receiptCh:
- // Ignore eth/{62,63} packets because this is eth/61.
- // These can arrive as a late delivery from a previous sync.
- }
- }
-}
-
// fetchHeight retrieves the head header of the remote peer to aid in estimating
// the total time a pending synchronisation would take.
func (d *Downloader) fetchHeight(p *peer) (*types.Header, error) {
@@ -1022,11 +531,6 @@ func (d *Downloader) fetchHeight(p *peer) (*types.Header, error) {
case <-d.stateCh:
case <-d.receiptCh:
// Out of bounds delivery, ignore
-
- case <-d.hashCh:
- case <-d.blockCh:
- // Ignore eth/61 packets because this is eth/62+.
- // These can arrive as a late delivery from a previous sync.
}
}
}
@@ -1067,7 +571,7 @@ func (d *Downloader) findAncestor(p *peer, height uint64) (uint64, error) {
for finished := false; !finished; {
select {
case <-d.cancelCh:
- return 0, errCancelHashFetch
+ return 0, errCancelHeaderFetch
case packet := <-d.headerCh:
// Discard anything not from the origin peer
@@ -1114,11 +618,6 @@ func (d *Downloader) findAncestor(p *peer, height uint64) (uint64, error) {
case <-d.stateCh:
case <-d.receiptCh:
// Out of bounds delivery, ignore
-
- case <-d.hashCh:
- case <-d.blockCh:
- // Ignore eth/61 packets because this is eth/62+.
- // These can arrive as a late delivery from a previous sync.
}
}
// If the head fetch already found an ancestor, return
@@ -1146,7 +645,7 @@ func (d *Downloader) findAncestor(p *peer, height uint64) (uint64, error) {
for arrived := false; !arrived; {
select {
case <-d.cancelCh:
- return 0, errCancelHashFetch
+ return 0, errCancelHeaderFetch
case packer := <-d.headerCh:
// Discard anything not from the origin peer
@@ -1182,11 +681,6 @@ func (d *Downloader) findAncestor(p *peer, height uint64) (uint64, error) {
case <-d.stateCh:
case <-d.receiptCh:
// Out of bounds delivery, ignore
-
- case <-d.hashCh:
- case <-d.blockCh:
- // Ignore eth/61 packets because this is eth/62+.
- // These can arrive as a late delivery from a previous sync.
}
}
}
@@ -1305,11 +799,6 @@ func (d *Downloader) fetchHeaders(p *peer, from uint64) error {
case <-d.cancelCh:
}
return errBadPeer
-
- case <-d.hashCh:
- case <-d.blockCh:
- // Ignore eth/61 packets because this is eth/62+.
- // These can arrive as a late delivery from a previous sync.
}
}
}
@@ -1555,7 +1044,14 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv
// Check for fetch request timeouts and demote the responsible peers
for pid, fails := range expire() {
if peer := d.peers.Peer(pid); peer != nil {
- if fails > 1 {
+ // If a lot of retrieval elements expired, we might have overestimated the remote peer or perhaps
+ // ourselves. Only reset to minimal throughput but don't drop just yet. If even the minimal times
+ // out that sync wise we need to get rid of the peer.
+ //
+ // The reason the minimum threshold is 2 is because the downloader tries to estimate the bandwidth
+ // and latency of a peer separately, which requires pushing the measures capacity a bit and seeing
+ // how response times reacts, to it always requests one more than the minimum (i.e. min 2).
+ if fails > 2 {
glog.V(logger.Detail).Infof("%s: %s delivery timeout", peer, strings.ToLower(kind))
setIdle(peer, 0)
} else {
@@ -1623,11 +1119,6 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv
if !progressed && !throttled && !running && len(idles) == total && pending() > 0 {
return errPeersUnavailable
}
-
- case <-d.hashCh:
- case <-d.blockCh:
- // Ignore eth/61 packets because this is eth/62+.
- // These can arrive as a late delivery from a previous sync.
}
}
}
@@ -1859,7 +1350,7 @@ func (d *Downloader) processContent() error {
}
if err != nil {
glog.V(logger.Debug).Infof("Result #%d [%x…] processing failed: %v", results[index].Header.Number, results[index].Header.Hash().Bytes()[:4], err)
- return err
+ return errInvalidChain
}
// Shift the results to the next batch
results = results[items:]
@@ -1867,19 +1358,6 @@ func (d *Downloader) processContent() error {
}
}
-// DeliverHashes injects a new batch of hashes received from a remote node into
-// the download schedule. This is usually invoked through the BlockHashesMsg by
-// the protocol handler.
-func (d *Downloader) DeliverHashes(id string, hashes []common.Hash) (err error) {
- return d.deliver(id, d.hashCh, &hashPack{id, hashes}, hashInMeter, hashDropMeter)
-}
-
-// DeliverBlocks injects a new batch of blocks received from a remote node.
-// This is usually invoked through the BlocksMsg by the protocol handler.
-func (d *Downloader) DeliverBlocks(id string, blocks []*types.Block) (err error) {
- return d.deliver(id, d.blockCh, &blockPack{id, blocks}, blockInMeter, blockDropMeter)
-}
-
// DeliverHeaders injects a new batch of block headers received from a remote
// node into the download schedule.
func (d *Downloader) DeliverHeaders(id string, headers []*types.Header) (err error) {
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index e9e051ded..4ca28091c 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -55,7 +55,7 @@ func init() {
// reassembly.
func makeChain(n int, seed byte, parent *types.Block, parentReceipts types.Receipts, heavy bool) ([]common.Hash, map[common.Hash]*types.Header, map[common.Hash]*types.Block, map[common.Hash]types.Receipts) {
// Generate the block chain
- blocks, receipts := core.GenerateChain(parent, testdb, n, func(i int, block *core.BlockGen) {
+ blocks, receipts := core.GenerateChain(nil, parent, testdb, n, func(i int, block *core.BlockGen) {
block.SetCoinbase(common.Address{seed})
// If a heavy chain is requested, delay blocks to raise difficulty
@@ -399,14 +399,12 @@ func (dl *downloadTester) newSlowPeer(id string, version int, hashes []common.Ha
var err error
switch version {
- case 61:
- err = dl.downloader.RegisterPeer(id, version, hashes[0], dl.peerGetRelHashesFn(id, delay), dl.peerGetAbsHashesFn(id, delay), dl.peerGetBlocksFn(id, delay), nil, nil, nil, nil, nil)
case 62:
- err = dl.downloader.RegisterPeer(id, version, hashes[0], nil, nil, nil, dl.peerGetRelHeadersFn(id, delay), dl.peerGetAbsHeadersFn(id, delay), dl.peerGetBodiesFn(id, delay), nil, nil)
+ err = dl.downloader.RegisterPeer(id, version, hashes[0], dl.peerGetRelHeadersFn(id, delay), dl.peerGetAbsHeadersFn(id, delay), dl.peerGetBodiesFn(id, delay), nil, nil)
case 63:
- err = dl.downloader.RegisterPeer(id, version, hashes[0], nil, nil, nil, dl.peerGetRelHeadersFn(id, delay), dl.peerGetAbsHeadersFn(id, delay), dl.peerGetBodiesFn(id, delay), dl.peerGetReceiptsFn(id, delay), dl.peerGetNodeDataFn(id, delay))
+ err = dl.downloader.RegisterPeer(id, version, hashes[0], dl.peerGetRelHeadersFn(id, delay), dl.peerGetAbsHeadersFn(id, delay), dl.peerGetBodiesFn(id, delay), dl.peerGetReceiptsFn(id, delay), dl.peerGetNodeDataFn(id, delay))
case 64:
- err = dl.downloader.RegisterPeer(id, version, hashes[0], nil, nil, nil, dl.peerGetRelHeadersFn(id, delay), dl.peerGetAbsHeadersFn(id, delay), dl.peerGetBodiesFn(id, delay), dl.peerGetReceiptsFn(id, delay), dl.peerGetNodeDataFn(id, delay))
+ err = dl.downloader.RegisterPeer(id, version, hashes[0], dl.peerGetRelHeadersFn(id, delay), dl.peerGetAbsHeadersFn(id, delay), dl.peerGetBodiesFn(id, delay), dl.peerGetReceiptsFn(id, delay), dl.peerGetNodeDataFn(id, delay))
}
if err == nil {
// Assign the owned hashes, headers and blocks to the peer (deep copy)
@@ -465,86 +463,6 @@ func (dl *downloadTester) dropPeer(id string) {
dl.downloader.UnregisterPeer(id)
}
-// peerGetRelHashesFn constructs a GetHashes function associated with a specific
-// peer in the download tester. The returned function can be used to retrieve
-// batches of hashes from the particularly requested peer.
-func (dl *downloadTester) peerGetRelHashesFn(id string, delay time.Duration) func(head common.Hash) error {
- return func(head common.Hash) error {
- time.Sleep(delay)
-
- dl.lock.RLock()
- defer dl.lock.RUnlock()
-
- // Gather the next batch of hashes
- hashes := dl.peerHashes[id]
- result := make([]common.Hash, 0, MaxHashFetch)
- for i, hash := range hashes {
- if hash == head {
- i++
- for len(result) < cap(result) && i < len(hashes) {
- result = append(result, hashes[i])
- i++
- }
- break
- }
- }
- // Delay delivery a bit to allow attacks to unfold
- go func() {
- time.Sleep(time.Millisecond)
- dl.downloader.DeliverHashes(id, result)
- }()
- return nil
- }
-}
-
-// peerGetAbsHashesFn constructs a GetHashesFromNumber function associated with
-// a particular peer in the download tester. The returned function can be used to
-// retrieve batches of hashes from the particularly requested peer.
-func (dl *downloadTester) peerGetAbsHashesFn(id string, delay time.Duration) func(uint64, int) error {
- return func(head uint64, count int) error {
- time.Sleep(delay)
-
- dl.lock.RLock()
- defer dl.lock.RUnlock()
-
- // Gather the next batch of hashes
- hashes := dl.peerHashes[id]
- result := make([]common.Hash, 0, count)
- for i := 0; i < count && len(hashes)-int(head)-1-i >= 0; i++ {
- result = append(result, hashes[len(hashes)-int(head)-1-i])
- }
- // Delay delivery a bit to allow attacks to unfold
- go func() {
- time.Sleep(time.Millisecond)
- dl.downloader.DeliverHashes(id, result)
- }()
- return nil
- }
-}
-
-// peerGetBlocksFn constructs a getBlocks function associated with a particular
-// peer in the download tester. The returned function can be used to retrieve
-// batches of blocks from the particularly requested peer.
-func (dl *downloadTester) peerGetBlocksFn(id string, delay time.Duration) func([]common.Hash) error {
- return func(hashes []common.Hash) error {
- time.Sleep(delay)
-
- dl.lock.RLock()
- defer dl.lock.RUnlock()
-
- blocks := dl.peerBlocks[id]
- result := make([]*types.Block, 0, len(hashes))
- for _, hash := range hashes {
- if block, ok := blocks[hash]; ok {
- result = append(result, block)
- }
- }
- go dl.downloader.DeliverBlocks(id, result)
-
- return nil
- }
-}
-
// peerGetRelHeadersFn constructs a GetBlockHeaders function based on a hashed
// origin; associated with a particular peer in the download tester. The returned
// function can be used to retrieve batches of headers from the particular peer.
@@ -730,7 +648,6 @@ func assertOwnForkedChain(t *testing.T, tester *downloadTester, common int, leng
// Tests that simple synchronization against a canonical chain works correctly.
// In this test common ancestor lookup should be short circuited and not require
// binary searching.
-func TestCanonicalSynchronisation61(t *testing.T) { testCanonicalSynchronisation(t, 61, FullSync) }
func TestCanonicalSynchronisation62(t *testing.T) { testCanonicalSynchronisation(t, 62, FullSync) }
func TestCanonicalSynchronisation63Full(t *testing.T) { testCanonicalSynchronisation(t, 63, FullSync) }
func TestCanonicalSynchronisation63Fast(t *testing.T) { testCanonicalSynchronisation(t, 63, FastSync) }
@@ -759,7 +676,6 @@ func testCanonicalSynchronisation(t *testing.T, protocol int, mode SyncMode) {
// Tests that if a large batch of blocks are being downloaded, it is throttled
// until the cached blocks are retrieved.
-func TestThrottling61(t *testing.T) { testThrottling(t, 61, FullSync) }
func TestThrottling62(t *testing.T) { testThrottling(t, 62, FullSync) }
func TestThrottling63Full(t *testing.T) { testThrottling(t, 63, FullSync) }
func TestThrottling63Fast(t *testing.T) { testThrottling(t, 63, FastSync) }
@@ -845,7 +761,6 @@ func testThrottling(t *testing.T, protocol int, mode SyncMode) {
// Tests that simple synchronization against a forked chain works correctly. In
// this test common ancestor lookup should *not* be short circuited, and a full
// binary search should be executed.
-func TestForkedSync61(t *testing.T) { testForkedSync(t, 61, FullSync) }
func TestForkedSync62(t *testing.T) { testForkedSync(t, 62, FullSync) }
func TestForkedSync63Full(t *testing.T) { testForkedSync(t, 63, FullSync) }
func TestForkedSync63Fast(t *testing.T) { testForkedSync(t, 63, FastSync) }
@@ -881,7 +796,6 @@ func testForkedSync(t *testing.T, protocol int, mode SyncMode) {
// Tests that synchronising against a much shorter but much heavyer fork works
// corrently and is not dropped.
-func TestHeavyForkedSync61(t *testing.T) { testHeavyForkedSync(t, 61, FullSync) }
func TestHeavyForkedSync62(t *testing.T) { testHeavyForkedSync(t, 62, FullSync) }
func TestHeavyForkedSync63Full(t *testing.T) { testHeavyForkedSync(t, 63, FullSync) }
func TestHeavyForkedSync63Fast(t *testing.T) { testHeavyForkedSync(t, 63, FastSync) }
@@ -915,24 +829,9 @@ func testHeavyForkedSync(t *testing.T, protocol int, mode SyncMode) {
assertOwnForkedChain(t, tester, common+1, []int{common + fork + 1, common + fork/2 + 1})
}
-// Tests that an inactive downloader will not accept incoming hashes and blocks.
-func TestInactiveDownloader61(t *testing.T) {
- t.Parallel()
- tester := newTester()
-
- // Check that neither hashes nor blocks are accepted
- if err := tester.downloader.DeliverHashes("bad peer", []common.Hash{}); err != errNoSyncActive {
- t.Errorf("error mismatch: have %v, want %v", err, errNoSyncActive)
- }
- if err := tester.downloader.DeliverBlocks("bad peer", []*types.Block{}); err != errNoSyncActive {
- t.Errorf("error mismatch: have %v, want %v", err, errNoSyncActive)
- }
-}
-
// Tests that chain forks are contained within a certain interval of the current
// chain head, ensuring that malicious peers cannot waste resources by feeding
// long dead chains.
-func TestBoundedForkedSync61(t *testing.T) { testBoundedForkedSync(t, 61, FullSync) }
func TestBoundedForkedSync62(t *testing.T) { testBoundedForkedSync(t, 62, FullSync) }
func TestBoundedForkedSync63Full(t *testing.T) { testBoundedForkedSync(t, 63, FullSync) }
func TestBoundedForkedSync63Fast(t *testing.T) { testBoundedForkedSync(t, 63, FastSync) }
@@ -968,7 +867,6 @@ func testBoundedForkedSync(t *testing.T, protocol int, mode SyncMode) {
// Tests that chain forks are contained within a certain interval of the current
// chain head for short but heavy forks too. These are a bit special because they
// take different ancestor lookup paths.
-func TestBoundedHeavyForkedSync61(t *testing.T) { testBoundedHeavyForkedSync(t, 61, FullSync) }
func TestBoundedHeavyForkedSync62(t *testing.T) { testBoundedHeavyForkedSync(t, 62, FullSync) }
func TestBoundedHeavyForkedSync63Full(t *testing.T) { testBoundedHeavyForkedSync(t, 63, FullSync) }
func TestBoundedHeavyForkedSync63Fast(t *testing.T) { testBoundedHeavyForkedSync(t, 63, FastSync) }
@@ -1039,7 +937,6 @@ func TestInactiveDownloader63(t *testing.T) {
}
// Tests that a canceled download wipes all previously accumulated state.
-func TestCancel61(t *testing.T) { testCancel(t, 61, FullSync) }
func TestCancel62(t *testing.T) { testCancel(t, 62, FullSync) }
func TestCancel63Full(t *testing.T) { testCancel(t, 63, FullSync) }
func TestCancel63Fast(t *testing.T) { testCancel(t, 63, FastSync) }
@@ -1081,7 +978,6 @@ func testCancel(t *testing.T, protocol int, mode SyncMode) {
}
// Tests that synchronisation from multiple peers works as intended (multi thread sanity test).
-func TestMultiSynchronisation61(t *testing.T) { testMultiSynchronisation(t, 61, FullSync) }
func TestMultiSynchronisation62(t *testing.T) { testMultiSynchronisation(t, 62, FullSync) }
func TestMultiSynchronisation63Full(t *testing.T) { testMultiSynchronisation(t, 63, FullSync) }
func TestMultiSynchronisation63Fast(t *testing.T) { testMultiSynchronisation(t, 63, FastSync) }
@@ -1112,7 +1008,6 @@ func testMultiSynchronisation(t *testing.T, protocol int, mode SyncMode) {
// Tests that synchronisations behave well in multi-version protocol environments
// and not wreak havoc on other nodes in the network.
-func TestMultiProtoSynchronisation61(t *testing.T) { testMultiProtoSync(t, 61, FullSync) }
func TestMultiProtoSynchronisation62(t *testing.T) { testMultiProtoSync(t, 62, FullSync) }
func TestMultiProtoSynchronisation63Full(t *testing.T) { testMultiProtoSync(t, 63, FullSync) }
func TestMultiProtoSynchronisation63Fast(t *testing.T) { testMultiProtoSync(t, 63, FastSync) }
@@ -1131,7 +1026,6 @@ func testMultiProtoSync(t *testing.T, protocol int, mode SyncMode) {
tester := newTester()
defer tester.terminate()
- tester.newPeer("peer 61", 61, hashes, nil, blocks, nil)
tester.newPeer("peer 62", 62, hashes, headers, blocks, nil)
tester.newPeer("peer 63", 63, hashes, headers, blocks, receipts)
tester.newPeer("peer 64", 64, hashes, headers, blocks, receipts)
@@ -1143,7 +1037,7 @@ func testMultiProtoSync(t *testing.T, protocol int, mode SyncMode) {
assertOwnChain(t, tester, targetBlocks+1)
// Check that no peers have been dropped off
- for _, version := range []int{61, 62, 63, 64} {
+ for _, version := range []int{62, 63, 64} {
peer := fmt.Sprintf("peer %d", version)
if _, ok := tester.peerHashes[peer]; !ok {
t.Errorf("%s dropped", peer)
@@ -1368,7 +1262,6 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) {
// Tests that a peer advertising an high TD doesn't get to stall the downloader
// afterwards by not sending any useful hashes.
-func TestHighTDStarvationAttack61(t *testing.T) { testHighTDStarvationAttack(t, 61, FullSync) }
func TestHighTDStarvationAttack62(t *testing.T) { testHighTDStarvationAttack(t, 62, FullSync) }
func TestHighTDStarvationAttack63Full(t *testing.T) { testHighTDStarvationAttack(t, 63, FullSync) }
func TestHighTDStarvationAttack63Fast(t *testing.T) { testHighTDStarvationAttack(t, 63, FastSync) }
@@ -1391,7 +1284,6 @@ func testHighTDStarvationAttack(t *testing.T, protocol int, mode SyncMode) {
}
// Tests that misbehaving peers are disconnected, whilst behaving ones are not.
-func TestBlockHeaderAttackerDropping61(t *testing.T) { testBlockHeaderAttackerDropping(t, 61) }
func TestBlockHeaderAttackerDropping62(t *testing.T) { testBlockHeaderAttackerDropping(t, 62) }
func TestBlockHeaderAttackerDropping63(t *testing.T) { testBlockHeaderAttackerDropping(t, 63) }
func TestBlockHeaderAttackerDropping64(t *testing.T) { testBlockHeaderAttackerDropping(t, 64) }
@@ -1409,7 +1301,6 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol int) {
{errStallingPeer, true}, // Peer was detected to be stalling, drop it
{errNoPeers, false}, // No peers to download from, soft race, no issue
{errTimeout, true}, // No hashes received in due time, drop the peer
- {errEmptyHashSet, true}, // No hashes were returned as a response, drop as it's a dead end
{errEmptyHeaderSet, true}, // No headers were returned as a response, drop as it's a dead end
{errPeersUnavailable, true}, // Nobody had the advertised blocks, drop the advertiser
{errInvalidAncestor, true}, // Agreed upon ancestor is not acceptable, drop the chain rewriter
@@ -1417,7 +1308,6 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol int) {
{errInvalidBlock, false}, // A bad peer was detected, but not the sync origin
{errInvalidBody, false}, // A bad peer was detected, but not the sync origin
{errInvalidReceipt, false}, // A bad peer was detected, but not the sync origin
- {errCancelHashFetch, false}, // Synchronisation was canceled, origin may be innocent, don't drop
{errCancelBlockFetch, false}, // Synchronisation was canceled, origin may be innocent, don't drop
{errCancelHeaderFetch, false}, // Synchronisation was canceled, origin may be innocent, don't drop
{errCancelBodyFetch, false}, // Synchronisation was canceled, origin may be innocent, don't drop
@@ -1450,7 +1340,6 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol int) {
// Tests that synchronisation progress (origin block number, current block number
// and highest block number) is tracked and updated correctly.
-func TestSyncProgress61(t *testing.T) { testSyncProgress(t, 61, FullSync) }
func TestSyncProgress62(t *testing.T) { testSyncProgress(t, 62, FullSync) }
func TestSyncProgress63Full(t *testing.T) { testSyncProgress(t, 63, FullSync) }
func TestSyncProgress63Fast(t *testing.T) { testSyncProgress(t, 63, FastSync) }
@@ -1524,7 +1413,6 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
// Tests that synchronisation progress (origin block number and highest block
// number) is tracked and updated correctly in case of a fork (or manual head
// revertal).
-func TestForkedSyncProgress61(t *testing.T) { testForkedSyncProgress(t, 61, FullSync) }
func TestForkedSyncProgress62(t *testing.T) { testForkedSyncProgress(t, 62, FullSync) }
func TestForkedSyncProgress63Full(t *testing.T) { testForkedSyncProgress(t, 63, FullSync) }
func TestForkedSyncProgress63Fast(t *testing.T) { testForkedSyncProgress(t, 63, FastSync) }
@@ -1601,7 +1489,6 @@ func testForkedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
// Tests that if synchronisation is aborted due to some failure, then the progress
// origin is not updated in the next sync cycle, as it should be considered the
// continuation of the previous sync and not a new instance.
-func TestFailedSyncProgress61(t *testing.T) { testFailedSyncProgress(t, 61, FullSync) }
func TestFailedSyncProgress62(t *testing.T) { testFailedSyncProgress(t, 62, FullSync) }
func TestFailedSyncProgress63Full(t *testing.T) { testFailedSyncProgress(t, 63, FullSync) }
func TestFailedSyncProgress63Fast(t *testing.T) { testFailedSyncProgress(t, 63, FastSync) }
@@ -1679,7 +1566,6 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
// Tests that if an attacker fakes a chain height, after the attack is detected,
// the progress height is successfully reduced at the next sync invocation.
-func TestFakedSyncProgress61(t *testing.T) { testFakedSyncProgress(t, 61, FullSync) }
func TestFakedSyncProgress62(t *testing.T) { testFakedSyncProgress(t, 62, FullSync) }
func TestFakedSyncProgress63Full(t *testing.T) { testFakedSyncProgress(t, 63, FullSync) }
func TestFakedSyncProgress63Fast(t *testing.T) { testFakedSyncProgress(t, 63, FastSync) }
diff --git a/eth/downloader/metrics.go b/eth/downloader/metrics.go
index d6fcfa25c..0d76c7dfd 100644
--- a/eth/downloader/metrics.go
+++ b/eth/downloader/metrics.go
@@ -23,16 +23,6 @@ import (
)
var (
- hashInMeter = metrics.NewMeter("eth/downloader/hashes/in")
- hashReqTimer = metrics.NewTimer("eth/downloader/hashes/req")
- hashDropMeter = metrics.NewMeter("eth/downloader/hashes/drop")
- hashTimeoutMeter = metrics.NewMeter("eth/downloader/hashes/timeout")
-
- blockInMeter = metrics.NewMeter("eth/downloader/blocks/in")
- blockReqTimer = metrics.NewTimer("eth/downloader/blocks/req")
- blockDropMeter = metrics.NewMeter("eth/downloader/blocks/drop")
- blockTimeoutMeter = metrics.NewMeter("eth/downloader/blocks/timeout")
-
headerInMeter = metrics.NewMeter("eth/downloader/headers/in")
headerReqTimer = metrics.NewTimer("eth/downloader/headers/req")
headerDropMeter = metrics.NewMeter("eth/downloader/headers/drop")
diff --git a/eth/downloader/peer.go b/eth/downloader/peer.go
index 94d44fca4..c2b7a52d0 100644
--- a/eth/downloader/peer.go
+++ b/eth/downloader/peer.go
@@ -37,11 +37,6 @@ const (
measurementImpact = 0.1 // The impact a single measurement has on a peer's final throughput value.
)
-// Hash and block fetchers belonging to eth/61 and below
-type relativeHashFetcherFn func(common.Hash) error
-type absoluteHashFetcherFn func(uint64, int) error
-type blockFetcherFn func([]common.Hash) error
-
// Block header and body fetchers belonging to eth/62 and above
type relativeHeaderFetcherFn func(common.Hash, int, int, bool) error
type absoluteHeaderFetcherFn func(uint64, int, int, bool) error
@@ -79,10 +74,6 @@ type peer struct {
lacking map[common.Hash]struct{} // Set of hashes not to request (didn't have previously)
- getRelHashes relativeHashFetcherFn // [eth/61] Method to retrieve a batch of hashes from an origin hash
- getAbsHashes absoluteHashFetcherFn // [eth/61] Method to retrieve a batch of hashes from an absolute position
- getBlocks blockFetcherFn // [eth/61] Method to retrieve a batch of blocks
-
getRelHeaders relativeHeaderFetcherFn // [eth/62] Method to retrieve a batch of headers from an origin hash
getAbsHeaders absoluteHeaderFetcherFn // [eth/62] Method to retrieve a batch of headers from an absolute position
getBlockBodies blockBodyFetcherFn // [eth/62] Method to retrieve a batch of block bodies
@@ -97,7 +88,6 @@ type peer struct {
// newPeer create a new downloader peer, with specific hash and block retrieval
// mechanisms.
func newPeer(id string, version int, head common.Hash,
- getRelHashes relativeHashFetcherFn, getAbsHashes absoluteHashFetcherFn, getBlocks blockFetcherFn, // eth/61 callbacks, remove when upgrading
getRelHeaders relativeHeaderFetcherFn, getAbsHeaders absoluteHeaderFetcherFn, getBlockBodies blockBodyFetcherFn,
getReceipts receiptFetcherFn, getNodeData stateFetcherFn) *peer {
return &peer{
@@ -105,10 +95,6 @@ func newPeer(id string, version int, head common.Hash,
head: head,
lacking: make(map[common.Hash]struct{}),
- getRelHashes: getRelHashes,
- getAbsHashes: getAbsHashes,
- getBlocks: getBlocks,
-
getRelHeaders: getRelHeaders,
getAbsHeaders: getAbsHeaders,
getBlockBodies: getBlockBodies,
@@ -138,28 +124,6 @@ func (p *peer) Reset() {
p.lacking = make(map[common.Hash]struct{})
}
-// Fetch61 sends a block retrieval request to the remote peer.
-func (p *peer) Fetch61(request *fetchRequest) error {
- // Sanity check the protocol version
- if p.version != 61 {
- panic(fmt.Sprintf("block fetch [eth/61] requested on eth/%d", p.version))
- }
- // Short circuit if the peer is already fetching
- if !atomic.CompareAndSwapInt32(&p.blockIdle, 0, 1) {
- return errAlreadyFetching
- }
- p.blockStarted = time.Now()
-
- // Convert the hash set to a retrievable slice
- hashes := make([]common.Hash, 0, len(request.Hashes))
- for hash, _ := range request.Hashes {
- hashes = append(hashes, hash)
- }
- go p.getBlocks(hashes)
-
- return nil
-}
-
// FetchHeaders sends a header retrieval request to the remote peer.
func (p *peer) FetchHeaders(from uint64, count int) error {
// Sanity check the protocol version
@@ -481,20 +445,6 @@ func (ps *peerSet) AllPeers() []*peer {
return list
}
-// BlockIdlePeers retrieves a flat list of all the currently idle peers within the
-// active peer set, ordered by their reputation.
-func (ps *peerSet) BlockIdlePeers() ([]*peer, int) {
- idle := func(p *peer) bool {
- return atomic.LoadInt32(&p.blockIdle) == 0
- }
- throughput := func(p *peer) float64 {
- p.lock.RLock()
- defer p.lock.RUnlock()
- return p.blockThroughput
- }
- return ps.idlePeers(61, 61, idle, throughput)
-}
-
// HeaderIdlePeers retrieves a flat list of all the currently header-idle peers
// within the active peer set, ordered by their reputation.
func (ps *peerSet) HeaderIdlePeers() ([]*peer, int) {
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index 01897af6d..fd239f7e4 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -45,7 +45,6 @@ var (
var (
errNoFetchesPending = errors.New("no fetches pending")
- errStateSyncPending = errors.New("state trie sync already scheduled")
errStaleDelivery = errors.New("stale delivery")
)
@@ -74,10 +73,6 @@ type queue struct {
mode SyncMode // Synchronisation mode to decide on the block parts to schedule for fetching
fastSyncPivot uint64 // Block number where the fast sync pivots into archive synchronisation mode
- hashPool map[common.Hash]int // [eth/61] Pending hashes, mapping to their insertion index (priority)
- hashQueue *prque.Prque // [eth/61] Priority queue of the block hashes to fetch
- hashCounter int // [eth/61] Counter indexing the added hashes to ensure retrieval order
-
headerHead common.Hash // [eth/62] Hash of the last queued header to verify order
// Headers are "special", they download in batches, supported by a skeleton chain
@@ -85,7 +80,6 @@ type queue struct {
headerTaskQueue *prque.Prque // [eth/62] Priority queue of the skeleton indexes to fetch the filling headers for
headerPeerMiss map[string]map[uint64]struct{} // [eth/62] Set of per-peer header batches known to be unavailable
headerPendPool map[string]*fetchRequest // [eth/62] Currently pending header retrieval operations
- headerDonePool map[uint64]struct{} // [eth/62] Set of the completed header fetches
headerResults []*types.Header // [eth/62] Result cache accumulating the completed headers
headerProced int // [eth/62] Number of headers already processed from the results
headerOffset uint64 // [eth/62] Number of the first header in the result cache
@@ -124,8 +118,6 @@ type queue struct {
func newQueue(stateDb ethdb.Database) *queue {
lock := new(sync.Mutex)
return &queue{
- hashPool: make(map[common.Hash]int),
- hashQueue: prque.New(),
headerPendPool: make(map[string]*fetchRequest),
headerContCh: make(chan bool),
blockTaskPool: make(map[common.Hash]*types.Header),
@@ -158,10 +150,6 @@ func (q *queue) Reset() {
q.mode = FullSync
q.fastSyncPivot = 0
- q.hashPool = make(map[common.Hash]int)
- q.hashQueue.Reset()
- q.hashCounter = 0
-
q.headerHead = common.Hash{}
q.headerPendPool = make(map[string]*fetchRequest)
@@ -208,7 +196,7 @@ func (q *queue) PendingBlocks() int {
q.lock.Lock()
defer q.lock.Unlock()
- return q.hashQueue.Size() + q.blockTaskQueue.Size()
+ return q.blockTaskQueue.Size()
}
// PendingReceipts retrieves the number of block receipts pending for retrieval.
@@ -272,7 +260,7 @@ func (q *queue) Idle() bool {
q.lock.Lock()
defer q.lock.Unlock()
- queued := q.hashQueue.Size() + q.blockTaskQueue.Size() + q.receiptTaskQueue.Size() + q.stateTaskQueue.Size()
+ queued := q.blockTaskQueue.Size() + q.receiptTaskQueue.Size() + q.stateTaskQueue.Size()
pending := len(q.blockPendPool) + len(q.receiptPendPool) + len(q.statePendPool)
cached := len(q.blockDonePool) + len(q.receiptDonePool)
@@ -323,34 +311,6 @@ func (q *queue) ShouldThrottleReceipts() bool {
return pending >= len(q.resultCache)-len(q.receiptDonePool)
}
-// Schedule61 adds a set of hashes for the download queue for scheduling, returning
-// the new hashes encountered.
-func (q *queue) Schedule61(hashes []common.Hash, fifo bool) []common.Hash {
- q.lock.Lock()
- defer q.lock.Unlock()
-
- // Insert all the hashes prioritised in the arrival order
- inserts := make([]common.Hash, 0, len(hashes))
- for _, hash := range hashes {
- // Skip anything we already have
- if old, ok := q.hashPool[hash]; ok {
- glog.V(logger.Warn).Infof("Hash %x already scheduled at index %v", hash, old)
- continue
- }
- // Update the counters and insert the hash
- q.hashCounter = q.hashCounter + 1
- inserts = append(inserts, hash)
-
- q.hashPool[hash] = q.hashCounter
- if fifo {
- q.hashQueue.Push(hash, -float32(q.hashCounter)) // Lowest gets schedules first
- } else {
- q.hashQueue.Push(hash, float32(q.hashCounter)) // Highest gets schedules first
- }
- }
- return inserts
-}
-
// ScheduleSkeleton adds a batch of header retrieval tasks to the queue to fill
// up an already retrieved header skeleton.
func (q *queue) ScheduleSkeleton(from uint64, skeleton []*types.Header) {
@@ -550,15 +510,6 @@ func (q *queue) ReserveHeaders(p *peer, count int) *fetchRequest {
return request
}
-// ReserveBlocks reserves a set of block hashes for the given peer, skipping any
-// previously failed download.
-func (q *queue) ReserveBlocks(p *peer, count int) *fetchRequest {
- q.lock.Lock()
- defer q.lock.Unlock()
-
- return q.reserveHashes(p, count, q.hashQueue, nil, q.blockPendPool, len(q.resultCache)-len(q.blockDonePool))
-}
-
// ReserveNodeData reserves a set of node data hashes for the given peer, skipping
// any previously failed download.
func (q *queue) ReserveNodeData(p *peer, count int) *fetchRequest {
@@ -753,11 +704,6 @@ func (q *queue) CancelHeaders(request *fetchRequest) {
q.cancel(request, q.headerTaskQueue, q.headerPendPool)
}
-// CancelBlocks aborts a fetch request, returning all pending hashes to the queue.
-func (q *queue) CancelBlocks(request *fetchRequest) {
- q.cancel(request, q.hashQueue, q.blockPendPool)
-}
-
// CancelBodies aborts a body fetch request, returning all pending headers to the
// task queue.
func (q *queue) CancelBodies(request *fetchRequest) {
@@ -801,9 +747,6 @@ func (q *queue) Revoke(peerId string) {
defer q.lock.Unlock()
if request, ok := q.blockPendPool[peerId]; ok {
- for hash, index := range request.Hashes {
- q.hashQueue.Push(hash, float32(index))
- }
for _, header := range request.Headers {
q.blockTaskQueue.Push(header, -float32(header.Number.Uint64()))
}
@@ -832,15 +775,6 @@ func (q *queue) ExpireHeaders(timeout time.Duration) map[string]int {
return q.expire(timeout, q.headerPendPool, q.headerTaskQueue, headerTimeoutMeter)
}
-// ExpireBlocks checks for in flight requests that exceeded a timeout allowance,
-// canceling them and returning the responsible peers for penalisation.
-func (q *queue) ExpireBlocks(timeout time.Duration) map[string]int {
- q.lock.Lock()
- defer q.lock.Unlock()
-
- return q.expire(timeout, q.blockPendPool, q.hashQueue, blockTimeoutMeter)
-}
-
// ExpireBodies checks for in flight block body requests that exceeded a timeout
// allowance, canceling them and returning the responsible peers for penalisation.
func (q *queue) ExpireBodies(timeout time.Duration) map[string]int {
@@ -907,74 +841,6 @@ func (q *queue) expire(timeout time.Duration, pendPool map[string]*fetchRequest,
return expiries
}
-// DeliverBlocks injects a block retrieval response into the download queue. The
-// method returns the number of blocks accepted from the delivery and also wakes
-// any threads waiting for data delivery.
-func (q *queue) DeliverBlocks(id string, blocks []*types.Block) (int, error) {
- q.lock.Lock()
- defer q.lock.Unlock()
-
- // Short circuit if the blocks were never requested
- request := q.blockPendPool[id]
- if request == nil {
- return 0, errNoFetchesPending
- }
- blockReqTimer.UpdateSince(request.Time)
- delete(q.blockPendPool, id)
-
- // If no blocks were retrieved, mark them as unavailable for the origin peer
- if len(blocks) == 0 {
- for hash, _ := range request.Hashes {
- request.Peer.MarkLacking(hash)
- }
- }
- // Iterate over the downloaded blocks and add each of them
- accepted, errs := 0, make([]error, 0)
- for _, block := range blocks {
- // Skip any blocks that were not requested
- hash := block.Hash()
- if _, ok := request.Hashes[hash]; !ok {
- errs = append(errs, fmt.Errorf("non-requested block %x", hash))
- continue
- }
- // Reconstruct the next result if contents match up
- index := int(block.Number().Int64() - int64(q.resultOffset))
- if index >= len(q.resultCache) || index < 0 {
- errs = []error{errInvalidChain}
- break
- }
- q.resultCache[index] = &fetchResult{
- Header: block.Header(),
- Transactions: block.Transactions(),
- Uncles: block.Uncles(),
- }
- q.blockDonePool[block.Hash()] = struct{}{}
-
- delete(request.Hashes, hash)
- delete(q.hashPool, hash)
- accepted++
- }
- // Return all failed or missing fetches to the queue
- for hash, index := range request.Hashes {
- q.hashQueue.Push(hash, float32(index))
- }
- // Wake up WaitResults
- if accepted > 0 {
- q.active.Signal()
- }
- // If none of the blocks were good, it's a stale delivery
- switch {
- case len(errs) == 0:
- return accepted, nil
- case len(errs) == 1 && (errs[0] == errInvalidChain || errs[0] == errInvalidBlock):
- return accepted, errs[0]
- case len(errs) == len(blocks):
- return accepted, errStaleDelivery
- default:
- return accepted, fmt.Errorf("multiple failures: %v", errs)
- }
-}
-
// DeliverHeaders injects a header retrieval response into the header results
// cache. This method either accepts all headers it received, or none of them
// if they do not map correctly to the skeleton.
diff --git a/eth/downloader/types.go b/eth/downloader/types.go
index b67fff1f8..e10510486 100644
--- a/eth/downloader/types.go
+++ b/eth/downloader/types.go
@@ -73,26 +73,6 @@ type dataPack interface {
Stats() string
}
-// hashPack is a batch of block hashes returned by a peer (eth/61).
-type hashPack struct {
- peerId string
- hashes []common.Hash
-}
-
-func (p *hashPack) PeerId() string { return p.peerId }
-func (p *hashPack) Items() int { return len(p.hashes) }
-func (p *hashPack) Stats() string { return fmt.Sprintf("%d", len(p.hashes)) }
-
-// blockPack is a batch of blocks returned by a peer (eth/61).
-type blockPack struct {
- peerId string
- blocks []*types.Block
-}
-
-func (p *blockPack) PeerId() string { return p.peerId }
-func (p *blockPack) Items() int { return len(p.blocks) }
-func (p *blockPack) Stats() string { return fmt.Sprintf("%d", len(p.blocks)) }
-
// headerPack is a batch of block headers returned by a peer.
type headerPack struct {
peerId string
diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go
index 9300717c3..bd235bb9e 100644
--- a/eth/fetcher/fetcher.go
+++ b/eth/fetcher/fetcher.go
@@ -48,9 +48,6 @@ var (
// blockRetrievalFn is a callback type for retrieving a block from the local chain.
type blockRetrievalFn func(common.Hash) *types.Block
-// blockRequesterFn is a callback type for sending a block retrieval request.
-type blockRequesterFn func([]common.Hash) error
-
// headerRequesterFn is a callback type for sending a header retrieval request.
type headerRequesterFn func(common.Hash) error
@@ -82,7 +79,6 @@ type announce struct {
origin string // Identifier of the peer originating the notification
- fetch61 blockRequesterFn // [eth/61] Fetcher function to retrieve an announced block
fetchHeader headerRequesterFn // [eth/62] Fetcher function to retrieve the header of an announced block
fetchBodies bodyRequesterFn // [eth/62] Fetcher function to retrieve the body of an announced block
}
@@ -191,14 +187,12 @@ func (f *Fetcher) Stop() {
// Notify announces the fetcher of the potential availability of a new block in
// the network.
func (f *Fetcher) Notify(peer string, hash common.Hash, number uint64, time time.Time,
- blockFetcher blockRequesterFn, // eth/61 specific whole block fetcher
headerFetcher headerRequesterFn, bodyFetcher bodyRequesterFn) error {
block := &announce{
hash: hash,
number: number,
time: time,
origin: peer,
- fetch61: blockFetcher,
fetchHeader: headerFetcher,
fetchBodies: bodyFetcher,
}
@@ -224,34 +218,6 @@ func (f *Fetcher) Enqueue(peer string, block *types.Block) error {
}
}
-// FilterBlocks extracts all the blocks that were explicitly requested by the fetcher,
-// returning those that should be handled differently.
-func (f *Fetcher) FilterBlocks(blocks types.Blocks) types.Blocks {
- glog.V(logger.Detail).Infof("[eth/61] filtering %d blocks", len(blocks))
-
- // Send the filter channel to the fetcher
- filter := make(chan []*types.Block)
-
- select {
- case f.blockFilter <- filter:
- case <-f.quit:
- return nil
- }
- // Request the filtering of the block list
- select {
- case filter <- blocks:
- case <-f.quit:
- return nil
- }
- // Retrieve the blocks remaining after filtering
- select {
- case blocks := <-filter:
- return blocks
- case <-f.quit:
- return nil
- }
-}
-
// FilterHeaders extracts all the headers that were explicitly requested by the fetcher,
// returning those that should be handled differently.
func (f *Fetcher) FilterHeaders(headers []*types.Header, time time.Time) []*types.Header {
@@ -413,7 +379,7 @@ func (f *Fetcher) loop() {
}
}
}
- // Send out all block (eth/61) or header (eth/62) requests
+ // Send out all block header requests
for peer, hashes := range request {
if glog.V(logger.Detail) && len(hashes) > 0 {
list := "["
@@ -421,29 +387,17 @@ func (f *Fetcher) loop() {
list += fmt.Sprintf("%x…, ", hash[:4])
}
list = list[:len(list)-2] + "]"
-
- if f.fetching[hashes[0]].fetch61 != nil {
- glog.V(logger.Detail).Infof("[eth/61] Peer %s: fetching blocks %s", peer, list)
- } else {
- glog.V(logger.Detail).Infof("[eth/62] Peer %s: fetching headers %s", peer, list)
- }
+ glog.V(logger.Detail).Infof("[eth/62] Peer %s: fetching headers %s", peer, list)
}
// Create a closure of the fetch and schedule in on a new thread
- fetchBlocks, fetchHeader, hashes := f.fetching[hashes[0]].fetch61, f.fetching[hashes[0]].fetchHeader, hashes
+ fetchHeader, hashes := f.fetching[hashes[0]].fetchHeader, hashes
go func() {
if f.fetchingHook != nil {
f.fetchingHook(hashes)
}
- if fetchBlocks != nil {
- // Use old eth/61 protocol to retrieve whole blocks
- blockFetchMeter.Mark(int64(len(hashes)))
- fetchBlocks(hashes)
- } else {
- // Use new eth/62 protocol to retrieve headers first
- for _, hash := range hashes {
- headerFetchMeter.Mark(1)
- fetchHeader(hash) // Suboptimal, but protocol doesn't allow batch header retrievals
- }
+ for _, hash := range hashes {
+ headerFetchMeter.Mark(1)
+ fetchHeader(hash) // Suboptimal, but protocol doesn't allow batch header retrievals
}
}()
}
@@ -486,46 +440,6 @@ func (f *Fetcher) loop() {
// Schedule the next fetch if blocks are still pending
f.rescheduleComplete(completeTimer)
- case filter := <-f.blockFilter:
- // Blocks arrived, extract any explicit fetches, return all else
- var blocks types.Blocks
- select {
- case blocks = <-filter:
- case <-f.quit:
- return
- }
- blockFilterInMeter.Mark(int64(len(blocks)))
-
- explicit, download := []*types.Block{}, []*types.Block{}
- for _, block := range blocks {
- hash := block.Hash()
-
- // Filter explicitly requested blocks from hash announcements
- if f.fetching[hash] != nil && f.queued[hash] == nil {
- // Discard if already imported by other means
- if f.getBlock(hash) == nil {
- explicit = append(explicit, block)
- } else {
- f.forgetHash(hash)
- }
- } else {
- download = append(download, block)
- }
- }
-
- blockFilterOutMeter.Mark(int64(len(download)))
- select {
- case filter <- download:
- case <-f.quit:
- return
- }
- // Schedule the retrieved blocks for ordered import
- for _, block := range explicit {
- if announce := f.fetching[block.Hash()]; announce != nil {
- f.enqueue(announce.origin, block)
- }
- }
-
case filter := <-f.headerFilter:
// Headers arrived from a remote peer. Extract those that were explicitly
// requested by the fetcher, and return everything else so it's delivered
diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go
index 2404c8cfa..ad955a577 100644
--- a/eth/fetcher/fetcher_test.go
+++ b/eth/fetcher/fetcher_test.go
@@ -45,7 +45,7 @@ var (
// contains a transaction and every 5th an uncle to allow testing correct block
// reassembly.
func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block) {
- blocks, _ := core.GenerateChain(parent, testdb, n, func(i int, block *core.BlockGen) {
+ blocks, _ := core.GenerateChain(nil, parent, testdb, n, func(i int, block *core.BlockGen) {
block.SetCoinbase(common.Address{seed})
// If the block number is multiple of 3, send a bonus transaction to the miner
@@ -151,28 +151,6 @@ func (f *fetcherTester) dropPeer(peer string) {
f.drops[peer] = true
}
-// makeBlockFetcher retrieves a block fetcher associated with a simulated peer.
-func (f *fetcherTester) makeBlockFetcher(blocks map[common.Hash]*types.Block) blockRequesterFn {
- closure := make(map[common.Hash]*types.Block)
- for hash, block := range blocks {
- closure[hash] = block
- }
- // Create a function that returns blocks from the closure
- return func(hashes []common.Hash) error {
- // Gather the blocks to return
- blocks := make([]*types.Block, 0, len(hashes))
- for _, hash := range hashes {
- if block, ok := closure[hash]; ok {
- blocks = append(blocks, block)
- }
- }
- // Return on a new thread
- go f.fetcher.FilterBlocks(blocks)
-
- return nil
- }
-}
-
// makeHeaderFetcher retrieves a block header fetcher associated with a simulated peer.
func (f *fetcherTester) makeHeaderFetcher(blocks map[common.Hash]*types.Block, drift time.Duration) headerRequesterFn {
closure := make(map[common.Hash]*types.Block)
@@ -293,7 +271,6 @@ func verifyImportDone(t *testing.T, imported chan *types.Block) {
// Tests that a fetcher accepts block announcements and initiates retrievals for
// them, successfully importing into the local chain.
-func TestSequentialAnnouncements61(t *testing.T) { testSequentialAnnouncements(t, 61) }
func TestSequentialAnnouncements62(t *testing.T) { testSequentialAnnouncements(t, 62) }
func TestSequentialAnnouncements63(t *testing.T) { testSequentialAnnouncements(t, 63) }
func TestSequentialAnnouncements64(t *testing.T) { testSequentialAnnouncements(t, 64) }
@@ -304,7 +281,6 @@ func testSequentialAnnouncements(t *testing.T, protocol int) {
hashes, blocks := makeChain(targetBlocks, 0, genesis)
tester := newTester()
- blockFetcher := tester.makeBlockFetcher(blocks)
headerFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
bodyFetcher := tester.makeBodyFetcher(blocks, 0)
@@ -313,11 +289,7 @@ func testSequentialAnnouncements(t *testing.T, protocol int) {
tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
for i := len(hashes) - 2; i >= 0; i-- {
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[i], 0, time.Now().Add(-arriveTimeout), blockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
- }
+ tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
verifyImportEvent(t, imported, true)
}
verifyImportDone(t, imported)
@@ -325,7 +297,6 @@ func testSequentialAnnouncements(t *testing.T, protocol int) {
// Tests that if blocks are announced by multiple peers (or even the same buggy
// peer), they will only get downloaded at most once.
-func TestConcurrentAnnouncements61(t *testing.T) { testConcurrentAnnouncements(t, 61) }
func TestConcurrentAnnouncements62(t *testing.T) { testConcurrentAnnouncements(t, 62) }
func TestConcurrentAnnouncements63(t *testing.T) { testConcurrentAnnouncements(t, 63) }
func TestConcurrentAnnouncements64(t *testing.T) { testConcurrentAnnouncements(t, 64) }
@@ -337,15 +308,10 @@ func testConcurrentAnnouncements(t *testing.T, protocol int) {
// Assemble a tester with a built in counter for the requests
tester := newTester()
- blockFetcher := tester.makeBlockFetcher(blocks)
headerFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
bodyFetcher := tester.makeBodyFetcher(blocks, 0)
counter := uint32(0)
- blockWrapper := func(hashes []common.Hash) error {
- atomic.AddUint32(&counter, uint32(len(hashes)))
- return blockFetcher(hashes)
- }
headerWrapper := func(hash common.Hash) error {
atomic.AddUint32(&counter, 1)
return headerFetcher(hash)
@@ -355,15 +321,9 @@ func testConcurrentAnnouncements(t *testing.T, protocol int) {
tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
for i := len(hashes) - 2; i >= 0; i-- {
- if protocol < 62 {
- tester.fetcher.Notify("first", hashes[i], 0, time.Now().Add(-arriveTimeout), blockWrapper, nil, nil)
- tester.fetcher.Notify("second", hashes[i], 0, time.Now().Add(-arriveTimeout+time.Millisecond), blockWrapper, nil, nil)
- tester.fetcher.Notify("second", hashes[i], 0, time.Now().Add(-arriveTimeout-time.Millisecond), blockWrapper, nil, nil)
- } else {
- tester.fetcher.Notify("first", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), nil, headerWrapper, bodyFetcher)
- tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout+time.Millisecond), nil, headerWrapper, bodyFetcher)
- tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout-time.Millisecond), nil, headerWrapper, bodyFetcher)
- }
+ tester.fetcher.Notify("first", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerWrapper, bodyFetcher)
+ tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout+time.Millisecond), headerWrapper, bodyFetcher)
+ tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout-time.Millisecond), headerWrapper, bodyFetcher)
verifyImportEvent(t, imported, true)
}
verifyImportDone(t, imported)
@@ -376,7 +336,6 @@ func testConcurrentAnnouncements(t *testing.T, protocol int) {
// Tests that announcements arriving while a previous is being fetched still
// results in a valid import.
-func TestOverlappingAnnouncements61(t *testing.T) { testOverlappingAnnouncements(t, 61) }
func TestOverlappingAnnouncements62(t *testing.T) { testOverlappingAnnouncements(t, 62) }
func TestOverlappingAnnouncements63(t *testing.T) { testOverlappingAnnouncements(t, 63) }
func TestOverlappingAnnouncements64(t *testing.T) { testOverlappingAnnouncements(t, 64) }
@@ -387,7 +346,6 @@ func testOverlappingAnnouncements(t *testing.T, protocol int) {
hashes, blocks := makeChain(targetBlocks, 0, genesis)
tester := newTester()
- blockFetcher := tester.makeBlockFetcher(blocks)
headerFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
bodyFetcher := tester.makeBodyFetcher(blocks, 0)
@@ -400,11 +358,7 @@ func testOverlappingAnnouncements(t *testing.T, protocol int) {
tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
for i := len(hashes) - 2; i >= 0; i-- {
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[i], 0, time.Now().Add(-arriveTimeout), blockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
- }
+ tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
select {
case <-imported:
case <-time.After(time.Second):
@@ -416,7 +370,6 @@ func testOverlappingAnnouncements(t *testing.T, protocol int) {
}
// Tests that announces already being retrieved will not be duplicated.
-func TestPendingDeduplication61(t *testing.T) { testPendingDeduplication(t, 61) }
func TestPendingDeduplication62(t *testing.T) { testPendingDeduplication(t, 62) }
func TestPendingDeduplication63(t *testing.T) { testPendingDeduplication(t, 63) }
func TestPendingDeduplication64(t *testing.T) { testPendingDeduplication(t, 64) }
@@ -427,22 +380,11 @@ func testPendingDeduplication(t *testing.T, protocol int) {
// Assemble a tester with a built in counter and delayed fetcher
tester := newTester()
- blockFetcher := tester.makeBlockFetcher(blocks)
headerFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
bodyFetcher := tester.makeBodyFetcher(blocks, 0)
delay := 50 * time.Millisecond
counter := uint32(0)
- blockWrapper := func(hashes []common.Hash) error {
- atomic.AddUint32(&counter, uint32(len(hashes)))
-
- // Simulate a long running fetch
- go func() {
- time.Sleep(delay)
- blockFetcher(hashes)
- }()
- return nil
- }
headerWrapper := func(hash common.Hash) error {
atomic.AddUint32(&counter, 1)
@@ -455,11 +397,7 @@ func testPendingDeduplication(t *testing.T, protocol int) {
}
// Announce the same block many times until it's fetched (wait for any pending ops)
for tester.getBlock(hashes[0]) == nil {
- if protocol < 62 {
- tester.fetcher.Notify("repeater", hashes[0], 0, time.Now().Add(-arriveTimeout), blockWrapper, nil, nil)
- } else {
- tester.fetcher.Notify("repeater", hashes[0], 1, time.Now().Add(-arriveTimeout), nil, headerWrapper, bodyFetcher)
- }
+ tester.fetcher.Notify("repeater", hashes[0], 1, time.Now().Add(-arriveTimeout), headerWrapper, bodyFetcher)
time.Sleep(time.Millisecond)
}
time.Sleep(delay)
@@ -475,7 +413,6 @@ func testPendingDeduplication(t *testing.T, protocol int) {
// Tests that announcements retrieved in a random order are cached and eventually
// imported when all the gaps are filled in.
-func TestRandomArrivalImport61(t *testing.T) { testRandomArrivalImport(t, 61) }
func TestRandomArrivalImport62(t *testing.T) { testRandomArrivalImport(t, 62) }
func TestRandomArrivalImport63(t *testing.T) { testRandomArrivalImport(t, 63) }
func TestRandomArrivalImport64(t *testing.T) { testRandomArrivalImport(t, 64) }
@@ -487,7 +424,6 @@ func testRandomArrivalImport(t *testing.T, protocol int) {
skip := targetBlocks / 2
tester := newTester()
- blockFetcher := tester.makeBlockFetcher(blocks)
headerFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
bodyFetcher := tester.makeBodyFetcher(blocks, 0)
@@ -497,26 +433,17 @@ func testRandomArrivalImport(t *testing.T, protocol int) {
for i := len(hashes) - 1; i >= 0; i-- {
if i != skip {
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[i], 0, time.Now().Add(-arriveTimeout), blockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
- }
+ tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
time.Sleep(time.Millisecond)
}
}
// Finally announce the skipped entry and check full import
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[skip], 0, time.Now().Add(-arriveTimeout), blockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[skip], uint64(len(hashes)-skip-1), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
- }
+ tester.fetcher.Notify("valid", hashes[skip], uint64(len(hashes)-skip-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
verifyImportCount(t, imported, len(hashes)-1)
}
// Tests that direct block enqueues (due to block propagation vs. hash announce)
// are correctly schedule, filling and import queue gaps.
-func TestQueueGapFill61(t *testing.T) { testQueueGapFill(t, 61) }
func TestQueueGapFill62(t *testing.T) { testQueueGapFill(t, 62) }
func TestQueueGapFill63(t *testing.T) { testQueueGapFill(t, 63) }
func TestQueueGapFill64(t *testing.T) { testQueueGapFill(t, 64) }
@@ -528,7 +455,6 @@ func testQueueGapFill(t *testing.T, protocol int) {
skip := targetBlocks / 2
tester := newTester()
- blockFetcher := tester.makeBlockFetcher(blocks)
headerFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
bodyFetcher := tester.makeBodyFetcher(blocks, 0)
@@ -538,11 +464,7 @@ func testQueueGapFill(t *testing.T, protocol int) {
for i := len(hashes) - 1; i >= 0; i-- {
if i != skip {
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[i], 0, time.Now().Add(-arriveTimeout), blockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
- }
+ tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
time.Sleep(time.Millisecond)
}
}
@@ -553,7 +475,6 @@ func testQueueGapFill(t *testing.T, protocol int) {
// Tests that blocks arriving from various sources (multiple propagations, hash
// announces, etc) do not get scheduled for import multiple times.
-func TestImportDeduplication61(t *testing.T) { testImportDeduplication(t, 61) }
func TestImportDeduplication62(t *testing.T) { testImportDeduplication(t, 62) }
func TestImportDeduplication63(t *testing.T) { testImportDeduplication(t, 63) }
func TestImportDeduplication64(t *testing.T) { testImportDeduplication(t, 64) }
@@ -564,7 +485,6 @@ func testImportDeduplication(t *testing.T, protocol int) {
// Create the tester and wrap the importer with a counter
tester := newTester()
- blockFetcher := tester.makeBlockFetcher(blocks)
headerFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
bodyFetcher := tester.makeBodyFetcher(blocks, 0)
@@ -580,11 +500,7 @@ func testImportDeduplication(t *testing.T, protocol int) {
tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
// Announce the duplicating block, wait for retrieval, and also propagate directly
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[0], 0, time.Now().Add(-arriveTimeout), blockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[0], 1, time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
- }
+ tester.fetcher.Notify("valid", hashes[0], 1, time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
<-fetching
tester.fetcher.Enqueue("valid", blocks[hashes[0]])
@@ -660,14 +576,14 @@ func testDistantAnnouncementDiscarding(t *testing.T, protocol int) {
tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- struct{}{} }
// Ensure that a block with a lower number than the threshold is discarded
- tester.fetcher.Notify("lower", hashes[low], blocks[hashes[low]].NumberU64(), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
+ tester.fetcher.Notify("lower", hashes[low], blocks[hashes[low]].NumberU64(), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
select {
case <-time.After(50 * time.Millisecond):
case <-fetching:
t.Fatalf("fetcher requested stale header")
}
// Ensure that a block with a higher number than the threshold is discarded
- tester.fetcher.Notify("higher", hashes[high], blocks[hashes[high]].NumberU64(), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
+ tester.fetcher.Notify("higher", hashes[high], blocks[hashes[high]].NumberU64(), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
select {
case <-time.After(50 * time.Millisecond):
case <-fetching:
@@ -693,7 +609,7 @@ func testInvalidNumberAnnouncement(t *testing.T, protocol int) {
tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
// Announce a block with a bad number, check for immediate drop
- tester.fetcher.Notify("bad", hashes[0], 2, time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
+ tester.fetcher.Notify("bad", hashes[0], 2, time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
verifyImportEvent(t, imported, false)
tester.lock.RLock()
@@ -704,7 +620,7 @@ func testInvalidNumberAnnouncement(t *testing.T, protocol int) {
t.Fatalf("peer with invalid numbered announcement not dropped")
}
// Make sure a good announcement passes without a drop
- tester.fetcher.Notify("good", hashes[0], 1, time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
+ tester.fetcher.Notify("good", hashes[0], 1, time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
verifyImportEvent(t, imported, true)
tester.lock.RLock()
@@ -743,7 +659,7 @@ func testEmptyBlockShortCircuit(t *testing.T, protocol int) {
// Iteratively announce blocks until all are imported
for i := len(hashes) - 2; i >= 0; i-- {
- tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), nil, headerFetcher, bodyFetcher)
+ tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
// All announces should fetch the header
verifyFetchingEvent(t, fetching, true)
@@ -760,7 +676,6 @@ func testEmptyBlockShortCircuit(t *testing.T, protocol int) {
// Tests that a peer is unable to use unbounded memory with sending infinite
// block announcements to a node, but that even in the face of such an attack,
// the fetcher remains operational.
-func TestHashMemoryExhaustionAttack61(t *testing.T) { testHashMemoryExhaustionAttack(t, 61) }
func TestHashMemoryExhaustionAttack62(t *testing.T) { testHashMemoryExhaustionAttack(t, 62) }
func TestHashMemoryExhaustionAttack63(t *testing.T) { testHashMemoryExhaustionAttack(t, 63) }
func TestHashMemoryExhaustionAttack64(t *testing.T) { testHashMemoryExhaustionAttack(t, 64) }
@@ -781,29 +696,19 @@ func testHashMemoryExhaustionAttack(t *testing.T, protocol int) {
// Create a valid chain and an infinite junk chain
targetBlocks := hashLimit + 2*maxQueueDist
hashes, blocks := makeChain(targetBlocks, 0, genesis)
- validBlockFetcher := tester.makeBlockFetcher(blocks)
validHeaderFetcher := tester.makeHeaderFetcher(blocks, -gatherSlack)
validBodyFetcher := tester.makeBodyFetcher(blocks, 0)
attack, _ := makeChain(targetBlocks, 0, unknownBlock)
- attackerBlockFetcher := tester.makeBlockFetcher(nil)
attackerHeaderFetcher := tester.makeHeaderFetcher(nil, -gatherSlack)
attackerBodyFetcher := tester.makeBodyFetcher(nil, 0)
// Feed the tester a huge hashset from the attacker, and a limited from the valid peer
for i := 0; i < len(attack); i++ {
if i < maxQueueDist {
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[len(hashes)-2-i], 0, time.Now(), validBlockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[len(hashes)-2-i], uint64(i+1), time.Now(), nil, validHeaderFetcher, validBodyFetcher)
- }
- }
- if protocol < 62 {
- tester.fetcher.Notify("attacker", attack[i], 0, time.Now(), attackerBlockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("attacker", attack[i], 1 /* don't distance drop */, time.Now(), nil, attackerHeaderFetcher, attackerBodyFetcher)
+ tester.fetcher.Notify("valid", hashes[len(hashes)-2-i], uint64(i+1), time.Now(), validHeaderFetcher, validBodyFetcher)
}
+ tester.fetcher.Notify("attacker", attack[i], 1 /* don't distance drop */, time.Now(), attackerHeaderFetcher, attackerBodyFetcher)
}
if count := atomic.LoadInt32(&announces); count != hashLimit+maxQueueDist {
t.Fatalf("queued announce count mismatch: have %d, want %d", count, hashLimit+maxQueueDist)
@@ -813,11 +718,7 @@ func testHashMemoryExhaustionAttack(t *testing.T, protocol int) {
// Feed the remaining valid hashes to ensure DOS protection state remains clean
for i := len(hashes) - maxQueueDist - 2; i >= 0; i-- {
- if protocol < 62 {
- tester.fetcher.Notify("valid", hashes[i], 0, time.Now().Add(-arriveTimeout), validBlockFetcher, nil, nil)
- } else {
- tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), nil, validHeaderFetcher, validBodyFetcher)
- }
+ tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), validHeaderFetcher, validBodyFetcher)
verifyImportEvent(t, imported, true)
}
verifyImportDone(t, imported)
diff --git a/eth/fetcher/metrics.go b/eth/fetcher/metrics.go
index b82d3ca01..1ed8075bf 100644
--- a/eth/fetcher/metrics.go
+++ b/eth/fetcher/metrics.go
@@ -33,12 +33,9 @@ var (
propBroadcastDropMeter = metrics.NewMeter("eth/fetcher/prop/broadcasts/drop")
propBroadcastDOSMeter = metrics.NewMeter("eth/fetcher/prop/broadcasts/dos")
- blockFetchMeter = metrics.NewMeter("eth/fetcher/fetch/blocks")
headerFetchMeter = metrics.NewMeter("eth/fetcher/fetch/headers")
bodyFetchMeter = metrics.NewMeter("eth/fetcher/fetch/bodies")
- blockFilterInMeter = metrics.NewMeter("eth/fetcher/filter/blocks/in")
- blockFilterOutMeter = metrics.NewMeter("eth/fetcher/filter/blocks/out")
headerFilterInMeter = metrics.NewMeter("eth/fetcher/filter/headers/in")
headerFilterOutMeter = metrics.NewMeter("eth/fetcher/filter/headers/out")
bodyFilterInMeter = metrics.NewMeter("eth/fetcher/filter/bodies/in")
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 393019f8b..65c5b9380 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -68,8 +68,6 @@ type PublicFilterAPI struct {
transactionMu sync.RWMutex
transactionQueue map[int]*hashQueue
-
- transactMu sync.Mutex
}
// NewPublicFilterAPI returns a new PublicFilterAPI instance.
@@ -100,6 +98,7 @@ done:
for {
select {
case <-timer.C:
+ s.filterManager.Lock() // lock order like filterLoop()
s.logMu.Lock()
for id, filter := range s.logQueue {
if time.Since(filter.timeout) > filterTickerTime {
@@ -126,6 +125,7 @@ done:
}
}
s.transactionMu.Unlock()
+ s.filterManager.Unlock()
case <-s.quit:
break done
}
@@ -135,19 +135,24 @@ done:
// NewBlockFilter create a new filter that returns blocks that are included into the canonical chain.
func (s *PublicFilterAPI) NewBlockFilter() (string, error) {
+ // protect filterManager.Add() and setting of filter fields
+ s.filterManager.Lock()
+ defer s.filterManager.Unlock()
+
externalId, err := newFilterId()
if err != nil {
return "", err
}
- s.blockMu.Lock()
filter := New(s.chainDb)
id, err := s.filterManager.Add(filter, ChainFilter)
if err != nil {
return "", err
}
+ s.blockMu.Lock()
s.blockQueue[id] = &hashQueue{timeout: time.Now()}
+ s.blockMu.Unlock()
filter.BlockCallback = func(block *types.Block, logs vm.Logs) {
s.blockMu.Lock()
@@ -158,8 +163,6 @@ func (s *PublicFilterAPI) NewBlockFilter() (string, error) {
}
}
- defer s.blockMu.Unlock()
-
s.filterMapMu.Lock()
s.filterMapping[externalId] = id
s.filterMapMu.Unlock()
@@ -169,21 +172,24 @@ func (s *PublicFilterAPI) NewBlockFilter() (string, error) {
// NewPendingTransactionFilter creates a filter that returns new pending transactions.
func (s *PublicFilterAPI) NewPendingTransactionFilter() (string, error) {
+ // protect filterManager.Add() and setting of filter fields
+ s.filterManager.Lock()
+ defer s.filterManager.Unlock()
+
externalId, err := newFilterId()
if err != nil {
return "", err
}
- s.transactionMu.Lock()
- defer s.transactionMu.Unlock()
-
filter := New(s.chainDb)
id, err := s.filterManager.Add(filter, PendingTxFilter)
if err != nil {
return "", err
}
+ s.transactionMu.Lock()
s.transactionQueue[id] = &hashQueue{timeout: time.Now()}
+ s.transactionMu.Unlock()
filter.TransactionCallback = func(tx *types.Transaction) {
s.transactionMu.Lock()
@@ -203,8 +209,9 @@ func (s *PublicFilterAPI) NewPendingTransactionFilter() (string, error) {
// newLogFilter creates a new log filter.
func (s *PublicFilterAPI) newLogFilter(earliest, latest int64, addresses []common.Address, topics [][]common.Hash, callback func(log *vm.Log, removed bool)) (int, error) {
- s.logMu.Lock()
- defer s.logMu.Unlock()
+ // protect filterManager.Add() and setting of filter fields
+ s.filterManager.Lock()
+ defer s.filterManager.Unlock()
filter := New(s.chainDb)
id, err := s.filterManager.Add(filter, LogFilter)
@@ -212,7 +219,9 @@ func (s *PublicFilterAPI) newLogFilter(earliest, latest int64, addresses []commo
return 0, err
}
+ s.logMu.Lock()
s.logQueue[id] = &logQueue{timeout: time.Now()}
+ s.logMu.Unlock()
filter.SetBeginBlock(earliest)
filter.SetEndBlock(latest)
@@ -443,35 +452,43 @@ func (s *PublicFilterAPI) GetLogs(args NewFilterArgs) []vmlog {
// UninstallFilter removes the filter with the given filter id.
func (s *PublicFilterAPI) UninstallFilter(filterId string) bool {
- s.filterMapMu.Lock()
- defer s.filterMapMu.Unlock()
+ s.filterManager.Lock()
+ defer s.filterManager.Unlock()
+ s.filterMapMu.Lock()
id, ok := s.filterMapping[filterId]
if !ok {
+ s.filterMapMu.Unlock()
return false
}
-
- defer s.filterManager.Remove(id)
delete(s.filterMapping, filterId)
+ s.filterMapMu.Unlock()
+ s.filterManager.Remove(id)
+
+ s.logMu.Lock()
if _, ok := s.logQueue[id]; ok {
- s.logMu.Lock()
- defer s.logMu.Unlock()
delete(s.logQueue, id)
+ s.logMu.Unlock()
return true
}
+ s.logMu.Unlock()
+
+ s.blockMu.Lock()
if _, ok := s.blockQueue[id]; ok {
- s.blockMu.Lock()
- defer s.blockMu.Unlock()
delete(s.blockQueue, id)
+ s.blockMu.Unlock()
return true
}
+ s.blockMu.Unlock()
+
+ s.transactionMu.Lock()
if _, ok := s.transactionQueue[id]; ok {
- s.transactionMu.Lock()
- defer s.transactionMu.Unlock()
delete(s.transactionQueue, id)
+ s.transactionMu.Unlock()
return true
}
+ s.transactionMu.Unlock()
return false
}
@@ -525,7 +542,9 @@ func (s *PublicFilterAPI) logFilterChanged(id int) []vmlog {
// GetFilterLogs returns the logs for the filter with the given id.
func (s *PublicFilterAPI) GetFilterLogs(filterId string) []vmlog {
+ s.filterMapMu.RLock()
id, ok := s.filterMapping[filterId]
+ s.filterMapMu.RUnlock()
if !ok {
return toRPCLogs(nil, false)
}
@@ -540,9 +559,9 @@ func (s *PublicFilterAPI) GetFilterLogs(filterId string) []vmlog {
// GetFilterChanges returns the logs for the filter with the given id since last time is was called.
// This can be used for polling.
func (s *PublicFilterAPI) GetFilterChanges(filterId string) interface{} {
- s.filterMapMu.Lock()
+ s.filterMapMu.RLock()
id, ok := s.filterMapping[filterId]
- s.filterMapMu.Unlock()
+ s.filterMapMu.RUnlock()
if !ok { // filter not found
return []interface{}{}
diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go
index 4343dfa21..256464213 100644
--- a/eth/filters/filter_system.go
+++ b/eth/filters/filter_system.go
@@ -82,11 +82,20 @@ func (fs *FilterSystem) Stop() {
fs.sub.Unsubscribe()
}
-// Add adds a filter to the filter manager
-func (fs *FilterSystem) Add(filter *Filter, filterType FilterType) (int, error) {
+// Acquire filter system maps lock, required to force lock acquisition
+// sequence with filterMu acquired first to avoid deadlocks by callbacks
+func (fs *FilterSystem) Lock() {
fs.filterMu.Lock()
- defer fs.filterMu.Unlock()
+}
+
+// Release filter system maps lock
+func (fs *FilterSystem) Unlock() {
+ fs.filterMu.Unlock()
+}
+// Add adds a filter to the filter manager
+// Expects filterMu to be locked.
+func (fs *FilterSystem) Add(filter *Filter, filterType FilterType) (int, error) {
id := fs.filterId
filter.created = time.Now()
@@ -110,10 +119,8 @@ func (fs *FilterSystem) Add(filter *Filter, filterType FilterType) (int, error)
}
// Remove removes a filter by filter id
+// Expects filterMu to be locked.
func (fs *FilterSystem) Remove(id int) {
- fs.filterMu.Lock()
- defer fs.filterMu.Unlock()
-
delete(fs.chainFilters, id)
delete(fs.pendingTxFilters, id)
delete(fs.logFilters, id)
diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go
index a95adfce7..7b714f5d5 100644
--- a/eth/filters/filter_test.go
+++ b/eth/filters/filter_test.go
@@ -57,7 +57,7 @@ func BenchmarkMipmaps(b *testing.B) {
defer db.Close()
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000)})
- chain, receipts := core.GenerateChain(genesis, db, 100010, func(i int, gen *core.BlockGen) {
+ chain, receipts := core.GenerateChain(nil, genesis, db, 100010, func(i int, gen *core.BlockGen) {
var receipts types.Receipts
switch i {
case 2403:
@@ -133,7 +133,7 @@ func TestFilters(t *testing.T) {
defer db.Close()
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr, Balance: big.NewInt(1000000)})
- chain, receipts := core.GenerateChain(genesis, db, 1000, func(i int, gen *core.BlockGen) {
+ chain, receipts := core.GenerateChain(nil, genesis, db, 1000, func(i int, gen *core.BlockGen) {
var receipts types.Receipts
switch i {
case 1:
diff --git a/eth/gasprice.go b/eth/gasprice/gasprice.go
index ef203f8fe..eb2df4a96 100644
--- a/eth/gasprice.go
+++ b/eth/gasprice/gasprice.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package eth
+package gasprice
import (
"math/big"
@@ -23,6 +23,8 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
@@ -39,10 +41,22 @@ type blockPriceInfo struct {
baseGasPrice *big.Int
}
+type GpoParams struct {
+ GpoMinGasPrice *big.Int
+ GpoMaxGasPrice *big.Int
+ GpoFullBlockRatio int
+ GpobaseStepDown int
+ GpobaseStepUp int
+ GpobaseCorrectionFactor int
+}
+
// GasPriceOracle recommends gas prices based on the content of recent
// blocks.
type GasPriceOracle struct {
- eth *Ethereum
+ chain *core.BlockChain
+ db ethdb.Database
+ evmux *event.TypeMux
+ params *GpoParams
initOnce sync.Once
minPrice *big.Int
lastBaseMutex sync.Mutex
@@ -55,17 +69,20 @@ type GasPriceOracle struct {
}
// NewGasPriceOracle returns a new oracle.
-func NewGasPriceOracle(eth *Ethereum) *GasPriceOracle {
- minprice := eth.GpoMinGasPrice
+func NewGasPriceOracle(chain *core.BlockChain, db ethdb.Database, evmux *event.TypeMux, params *GpoParams) *GasPriceOracle {
+ minprice := params.GpoMinGasPrice
if minprice == nil {
minprice = big.NewInt(gpoDefaultMinGasPrice)
}
minbase := new(big.Int).Mul(minprice, big.NewInt(100))
- if eth.GpobaseCorrectionFactor > 0 {
- minbase = minbase.Div(minbase, big.NewInt(int64(eth.GpobaseCorrectionFactor)))
+ if params.GpobaseCorrectionFactor > 0 {
+ minbase = minbase.Div(minbase, big.NewInt(int64(params.GpobaseCorrectionFactor)))
}
return &GasPriceOracle{
- eth: eth,
+ chain: chain,
+ db: db,
+ evmux: evmux,
+ params: params,
blocks: make(map[uint64]*blockPriceInfo),
minBase: minbase,
minPrice: minprice,
@@ -75,14 +92,14 @@ func NewGasPriceOracle(eth *Ethereum) *GasPriceOracle {
func (gpo *GasPriceOracle) init() {
gpo.initOnce.Do(func() {
- gpo.processPastBlocks(gpo.eth.BlockChain())
+ gpo.processPastBlocks()
go gpo.listenLoop()
})
}
-func (self *GasPriceOracle) processPastBlocks(chain *core.BlockChain) {
+func (self *GasPriceOracle) processPastBlocks() {
last := int64(-1)
- cblock := chain.CurrentBlock()
+ cblock := self.chain.CurrentBlock()
if cblock != nil {
last = int64(cblock.NumberU64())
}
@@ -92,7 +109,7 @@ func (self *GasPriceOracle) processPastBlocks(chain *core.BlockChain) {
}
self.firstProcessed = uint64(first)
for i := first; i <= last; i++ {
- block := chain.GetBlockByNumber(uint64(i))
+ block := self.chain.GetBlockByNumber(uint64(i))
if block != nil {
self.processBlock(block)
}
@@ -101,7 +118,7 @@ func (self *GasPriceOracle) processPastBlocks(chain *core.BlockChain) {
}
func (self *GasPriceOracle) listenLoop() {
- events := self.eth.EventMux().Subscribe(core.ChainEvent{}, core.ChainSplitEvent{})
+ events := self.evmux.Subscribe(core.ChainEvent{}, core.ChainSplitEvent{})
defer events.Unsubscribe()
for event := range events.Chan() {
@@ -136,9 +153,9 @@ func (self *GasPriceOracle) processBlock(block *types.Block) {
}
if lastBase.Cmp(lp) < 0 {
- corr = self.eth.GpobaseStepUp
+ corr = self.params.GpobaseStepUp
} else {
- corr = -self.eth.GpobaseStepDown
+ corr = -self.params.GpobaseStepDown
}
crand := int64(corr * (900 + rand.Intn(201)))
@@ -159,14 +176,14 @@ func (self *GasPriceOracle) processBlock(block *types.Block) {
self.lastBase = newBase
self.lastBaseMutex.Unlock()
- glog.V(logger.Detail).Infof("Processed block #%v, base price is %v\n", block.NumberU64(), newBase.Int64())
+ glog.V(logger.Detail).Infof("Processed block #%v, base price is %v\n", i, newBase.Int64())
}
// returns the lowers possible price with which a tx was or could have been included
func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int {
gasUsed := big.NewInt(0)
- receipts := core.GetBlockReceipts(self.eth.ChainDb(), block.Hash(), block.NumberU64())
+ receipts := core.GetBlockReceipts(self.db, block.Hash(), block.NumberU64())
if len(receipts) > 0 {
if cgu := receipts[len(receipts)-1].CumulativeGasUsed; cgu != nil {
gasUsed = receipts[len(receipts)-1].CumulativeGasUsed
@@ -174,7 +191,7 @@ func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int {
}
if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.GasLimit(),
- big.NewInt(int64(self.eth.GpoFullBlockRatio)))) < 0 {
+ big.NewInt(int64(self.params.GpoFullBlockRatio)))) < 0 {
// block is not full, could have posted a tx with MinGasPrice
return big.NewInt(0)
}
@@ -201,12 +218,12 @@ func (self *GasPriceOracle) SuggestPrice() *big.Int {
price := new(big.Int).Set(self.lastBase)
self.lastBaseMutex.Unlock()
- price.Mul(price, big.NewInt(int64(self.eth.GpobaseCorrectionFactor)))
+ price.Mul(price, big.NewInt(int64(self.params.GpobaseCorrectionFactor)))
price.Div(price, big.NewInt(100))
if price.Cmp(self.minPrice) < 0 {
price.Set(self.minPrice)
- } else if self.eth.GpoMaxGasPrice != nil && price.Cmp(self.eth.GpoMaxGasPrice) > 0 {
- price.Set(self.eth.GpoMaxGasPrice)
+ } else if self.params.GpoMaxGasPrice != nil && price.Cmp(self.params.GpoMaxGasPrice) > 0 {
+ price.Set(self.params.GpoMaxGasPrice)
}
return price
}
diff --git a/eth/handler.go b/eth/handler.go
index 47a36cc0b..9ad430976 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -45,6 +45,10 @@ const (
estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header
)
+var (
+ daoChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the DAO handshake challenge
+)
+
// errIncompatibleConfig is returned if the requested protocols and configs are
// not compatible (low protocol version restrictions and high requirements).
var errIncompatibleConfig = errors.New("incompatible configuration")
@@ -53,18 +57,16 @@ func errResp(code errCode, format string, v ...interface{}) error {
return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
}
-type hashFetcherFn func(common.Hash) error
-type blockFetcherFn func([]common.Hash) error
-
type ProtocolManager struct {
networkId int
fastSync uint32 // Flag whether fast sync is enabled (gets disabled if we already have blocks)
synced uint32 // Flag whether we're considered synchronised (enables transaction processing)
- txpool txPool
- blockchain *core.BlockChain
- chaindb ethdb.Database
+ txpool txPool
+ blockchain *core.BlockChain
+ chaindb ethdb.Database
+ chainconfig *core.ChainConfig
downloader *downloader.Downloader
fetcher *fetcher.Fetcher
@@ -99,6 +101,7 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int,
txpool: txpool,
blockchain: blockchain,
chaindb: chaindb,
+ chainconfig: config,
peers: newPeerSet(),
newPeerCh: make(chan *peer),
noMorePeers: make(chan struct{}),
@@ -269,15 +272,36 @@ func (pm *ProtocolManager) handle(p *peer) error {
defer pm.removePeer(p.id)
// Register the peer in the downloader. If the downloader considers it banned, we disconnect
- if err := pm.downloader.RegisterPeer(p.id, p.version, p.Head(),
- p.RequestHashes, p.RequestHashesFromNumber, p.RequestBlocks, p.RequestHeadersByHash,
- p.RequestHeadersByNumber, p.RequestBodies, p.RequestReceipts, p.RequestNodeData); err != nil {
+ err := pm.downloader.RegisterPeer(p.id, p.version, p.Head(),
+ p.RequestHeadersByHash, p.RequestHeadersByNumber,
+ p.RequestBodies, p.RequestReceipts, p.RequestNodeData,
+ )
+ if err != nil {
return err
}
// Propagate existing transactions. new transactions appearing
// after this will be sent via broadcasts.
pm.syncTransactions(p)
+ // If we're DAO hard-fork aware, validate any remote peer with regard to the hard-fork
+ if daoBlock := pm.chainconfig.DAOForkBlock; daoBlock != nil {
+ // Request the peer's DAO fork header for extra-data validation
+ if err := p.RequestHeadersByNumber(daoBlock.Uint64(), 1, 0, false); err != nil {
+ return err
+ }
+ // Start a timer to disconnect if the peer doesn't reply in time
+ p.forkDrop = time.AfterFunc(daoChallengeTimeout, func() {
+ glog.V(logger.Warn).Infof("%v: timed out DAO fork-check, dropping", p)
+ pm.removePeer(p.id)
+ })
+ // Make sure it's cleaned up if the peer dies off
+ defer func() {
+ if p.forkDrop != nil {
+ p.forkDrop.Stop()
+ p.forkDrop = nil
+ }
+ }()
+ }
// main loop. handle incoming messages.
for {
if err := pm.handleMsg(p); err != nil {
@@ -306,108 +330,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
// Status messages should never arrive after the handshake
return errResp(ErrExtraStatusMsg, "uncontrolled status message")
- case p.version < eth62 && msg.Code == GetBlockHashesMsg:
- // Retrieve the number of hashes to return and from which origin hash
- var request getBlockHashesData
- if err := msg.Decode(&request); err != nil {
- return errResp(ErrDecode, "%v: %v", msg, err)
- }
- if request.Amount > uint64(downloader.MaxHashFetch) {
- request.Amount = uint64(downloader.MaxHashFetch)
- }
- // Retrieve the hashes from the block chain and return them
- hashes := pm.blockchain.GetBlockHashesFromHash(request.Hash, request.Amount)
- if len(hashes) == 0 {
- glog.V(logger.Debug).Infof("invalid block hash %x", request.Hash.Bytes()[:4])
- }
- return p.SendBlockHashes(hashes)
-
- case p.version < eth62 && msg.Code == GetBlockHashesFromNumberMsg:
- // Retrieve and decode the number of hashes to return and from which origin number
- var request getBlockHashesFromNumberData
- if err := msg.Decode(&request); err != nil {
- return errResp(ErrDecode, "%v: %v", msg, err)
- }
- if request.Amount > uint64(downloader.MaxHashFetch) {
- request.Amount = uint64(downloader.MaxHashFetch)
- }
- // Calculate the last block that should be retrieved, and short circuit if unavailable
- last := pm.blockchain.GetBlockByNumber(request.Number + request.Amount - 1)
- if last == nil {
- last = pm.blockchain.CurrentBlock()
- request.Amount = last.NumberU64() - request.Number + 1
- }
- if last.NumberU64() < request.Number {
- return p.SendBlockHashes(nil)
- }
- // Retrieve the hashes from the last block backwards, reverse and return
- hashes := []common.Hash{last.Hash()}
- hashes = append(hashes, pm.blockchain.GetBlockHashesFromHash(last.Hash(), request.Amount-1)...)
-
- for i := 0; i < len(hashes)/2; i++ {
- hashes[i], hashes[len(hashes)-1-i] = hashes[len(hashes)-1-i], hashes[i]
- }
- return p.SendBlockHashes(hashes)
-
- case p.version < eth62 && msg.Code == BlockHashesMsg:
- // A batch of hashes arrived to one of our previous requests
- var hashes []common.Hash
- if err := msg.Decode(&hashes); err != nil {
- break
- }
- // Deliver them all to the downloader for queuing
- err := pm.downloader.DeliverHashes(p.id, hashes)
- if err != nil {
- glog.V(logger.Debug).Infoln(err)
- }
-
- case p.version < eth62 && msg.Code == GetBlocksMsg:
- // Decode the retrieval message
- msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size))
- if _, err := msgStream.List(); err != nil {
- return err
- }
- // Gather blocks until the fetch or network limits is reached
- var (
- hash common.Hash
- bytes common.StorageSize
- blocks []*types.Block
- )
- for len(blocks) < downloader.MaxBlockFetch && bytes < softResponseLimit {
- //Retrieve the hash of the next block
- err := msgStream.Decode(&hash)
- if err == rlp.EOL {
- break
- } else if err != nil {
- return errResp(ErrDecode, "msg %v: %v", msg, err)
- }
- // Retrieve the requested block, stopping if enough was found
- if block := pm.blockchain.GetBlockByHash(hash); block != nil {
- blocks = append(blocks, block)
- bytes += block.Size()
- }
- }
- return p.SendBlocks(blocks)
-
- case p.version < eth62 && msg.Code == BlocksMsg:
- // Decode the arrived block message
- var blocks []*types.Block
- if err := msg.Decode(&blocks); err != nil {
- glog.V(logger.Detail).Infoln("Decode error", err)
- blocks = nil
- }
- // Update the receive timestamp of each block
- for _, block := range blocks {
- block.ReceivedAt = msg.ReceivedAt
- block.ReceivedFrom = p
- }
- // Filter out any explicitly requested blocks, deliver the rest to the downloader
- if blocks := pm.fetcher.FilterBlocks(blocks); len(blocks) > 0 {
- pm.downloader.DeliverBlocks(p.id, blocks)
- }
-
// Block header query, collect the requested headers and reply
- case p.version >= eth62 && msg.Code == GetBlockHeadersMsg:
+ case msg.Code == GetBlockHeadersMsg:
// Decode the complex header query
var query getBlockHeadersData
if err := msg.Decode(&query); err != nil {
@@ -475,15 +399,49 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
return p.SendBlockHeaders(headers)
- case p.version >= eth62 && msg.Code == BlockHeadersMsg:
+ case msg.Code == BlockHeadersMsg:
// A batch of headers arrived to one of our previous requests
var headers []*types.Header
if err := msg.Decode(&headers); err != nil {
return errResp(ErrDecode, "msg %v: %v", msg, err)
}
+ // If no headers were received, but we're expending a DAO fork check, maybe it's that
+ if len(headers) == 0 && p.forkDrop != nil {
+ // Possibly an empty reply to the fork header checks, sanity check TDs
+ verifyDAO := true
+
+ // If we already have a DAO header, we can check the peer's TD against it. If
+ // the peer's ahead of this, it too must have a reply to the DAO check
+ if daoHeader := pm.blockchain.GetHeaderByNumber(pm.chainconfig.DAOForkBlock.Uint64()); daoHeader != nil {
+ if p.Td().Cmp(pm.blockchain.GetTd(daoHeader.Hash(), daoHeader.Number.Uint64())) >= 0 {
+ verifyDAO = false
+ }
+ }
+ // If we're seemingly on the same chain, disable the drop timer
+ if verifyDAO {
+ glog.V(logger.Debug).Infof("%v: seems to be on the same side of the DAO fork", p)
+ p.forkDrop.Stop()
+ p.forkDrop = nil
+ return nil
+ }
+ }
// Filter out any explicitly requested headers, deliver the rest to the downloader
filter := len(headers) == 1
if filter {
+ // If it's a potential DAO fork check, validate against the rules
+ if p.forkDrop != nil && pm.chainconfig.DAOForkBlock.Cmp(headers[0].Number) == 0 {
+ // Disable the fork drop timer
+ p.forkDrop.Stop()
+ p.forkDrop = nil
+
+ // Validate the header and either drop the peer or continue
+ if err := core.ValidateDAOHeaderExtraData(pm.chainconfig, headers[0]); err != nil {
+ glog.V(logger.Debug).Infof("%v: verified to be on the other side of the DAO fork, dropping", p)
+ return err
+ }
+ glog.V(logger.Debug).Infof("%v: verified to be on the same side of the DAO fork", p)
+ }
+ // Irrelevant of the fork checks, send the header to the fetcher just in case
headers = pm.fetcher.FilterHeaders(headers, time.Now())
}
if len(headers) > 0 || !filter {
@@ -493,7 +451,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
}
- case p.version >= eth62 && msg.Code == GetBlockBodiesMsg:
+ case msg.Code == GetBlockBodiesMsg:
// Decode the retrieval message
msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size))
if _, err := msgStream.List(); err != nil {
@@ -520,7 +478,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
return p.SendBlockBodiesRLP(bodies)
- case p.version >= eth62 && msg.Code == BlockBodiesMsg:
+ case msg.Code == BlockBodiesMsg:
// A batch of block bodies arrived to one of our previous requests
var request blockBodiesData
if err := msg.Decode(&request); err != nil {
@@ -671,11 +629,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
}
for _, block := range unknown {
- if p.version < eth62 {
- pm.fetcher.Notify(p.id, block.Hash, block.Number, time.Now(), p.RequestBlocks, nil, nil)
- } else {
- pm.fetcher.Notify(p.id, block.Hash, block.Number, time.Now(), nil, p.RequestOneHeader, p.RequestBodies)
- }
+ pm.fetcher.Notify(p.id, block.Hash, block.Number, time.Now(), p.RequestOneHeader, p.RequestBodies)
}
case msg.Code == NewBlockMsg:
@@ -757,11 +711,7 @@ func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) {
// Otherwise if the block is indeed in out own chain, announce it
if pm.blockchain.HasBlock(hash) {
for _, peer := range peers {
- if peer.version < eth62 {
- peer.SendNewBlockHashes61([]common.Hash{hash})
- } else {
- peer.SendNewBlockHashes([]common.Hash{hash}, []uint64{block.NumberU64()})
- }
+ peer.SendNewBlockHashes([]common.Hash{hash}, []uint64{block.NumberU64()})
}
glog.V(logger.Detail).Infof("announced block %x to %d peers in %v", hash[:4], len(peers), time.Since(block.ReceivedAt))
}
diff --git a/eth/handler_test.go b/eth/handler_test.go
index 8418c28b2..91989cb8f 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -20,6 +20,7 @@ import (
"math/big"
"math/rand"
"testing"
+ "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@@ -28,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
)
@@ -61,160 +63,6 @@ func TestProtocolCompatibility(t *testing.T) {
}
}
-// Tests that hashes can be retrieved from a remote chain by hashes in reverse
-// order.
-func TestGetBlockHashes61(t *testing.T) { testGetBlockHashes(t, 61) }
-
-func testGetBlockHashes(t *testing.T, protocol int) {
- pm := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil, nil)
- peer, _ := newTestPeer("peer", protocol, pm, true)
- defer peer.close()
-
- // Create a batch of tests for various scenarios
- limit := downloader.MaxHashFetch
- tests := []struct {
- origin common.Hash
- number int
- result int
- }{
- {common.Hash{}, 1, 0}, // Make sure non existent hashes don't return results
- {pm.blockchain.Genesis().Hash(), 1, 0}, // There are no hashes to retrieve up from the genesis
- {pm.blockchain.GetBlockByNumber(5).Hash(), 5, 5}, // All the hashes including the genesis requested
- {pm.blockchain.GetBlockByNumber(5).Hash(), 10, 5}, // More hashes than available till the genesis requested
- {pm.blockchain.GetBlockByNumber(100).Hash(), 10, 10}, // All hashes available from the middle of the chain
- {pm.blockchain.CurrentBlock().Hash(), 10, 10}, // All hashes available from the head of the chain
- {pm.blockchain.CurrentBlock().Hash(), limit, limit}, // Request the maximum allowed hash count
- {pm.blockchain.CurrentBlock().Hash(), limit + 1, limit}, // Request more than the maximum allowed hash count
- }
- // Run each of the tests and verify the results against the chain
- for i, tt := range tests {
- // Assemble the hash response we would like to receive
- resp := make([]common.Hash, tt.result)
- if len(resp) > 0 {
- from := pm.blockchain.GetBlockByHash(tt.origin).NumberU64() - 1
- for j := 0; j < len(resp); j++ {
- resp[j] = pm.blockchain.GetBlockByNumber(uint64(int(from) - j)).Hash()
- }
- }
- // Send the hash request and verify the response
- p2p.Send(peer.app, 0x03, getBlockHashesData{tt.origin, uint64(tt.number)})
- if err := p2p.ExpectMsg(peer.app, 0x04, resp); err != nil {
- t.Errorf("test %d: block hashes mismatch: %v", i, err)
- }
- }
-}
-
-// Tests that hashes can be retrieved from a remote chain by numbers in forward
-// order.
-func TestGetBlockHashesFromNumber61(t *testing.T) { testGetBlockHashesFromNumber(t, 61) }
-
-func testGetBlockHashesFromNumber(t *testing.T, protocol int) {
- pm := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil, nil)
- peer, _ := newTestPeer("peer", protocol, pm, true)
- defer peer.close()
-
- // Create a batch of tests for various scenarios
- limit := downloader.MaxHashFetch
- tests := []struct {
- origin uint64
- number int
- result int
- }{
- {pm.blockchain.CurrentBlock().NumberU64() + 1, 1, 0}, // Out of bounds requests should return empty
- {pm.blockchain.CurrentBlock().NumberU64(), 1, 1}, // Make sure the head hash can be retrieved
- {pm.blockchain.CurrentBlock().NumberU64() - 4, 5, 5}, // All hashes, including the head hash requested
- {pm.blockchain.CurrentBlock().NumberU64() - 4, 10, 5}, // More hashes requested than available till the head
- {pm.blockchain.CurrentBlock().NumberU64() - 100, 10, 10}, // All hashes available from the middle of the chain
- {0, 10, 10}, // All hashes available from the root of the chain
- {0, limit, limit}, // Request the maximum allowed hash count
- {0, limit + 1, limit}, // Request more than the maximum allowed hash count
- {0, 1, 1}, // Make sure the genesis hash can be retrieved
- }
- // Run each of the tests and verify the results against the chain
- for i, tt := range tests {
- // Assemble the hash response we would like to receive
- resp := make([]common.Hash, tt.result)
- for j := 0; j < len(resp); j++ {
- resp[j] = pm.blockchain.GetBlockByNumber(tt.origin + uint64(j)).Hash()
- }
- // Send the hash request and verify the response
- p2p.Send(peer.app, 0x08, getBlockHashesFromNumberData{tt.origin, uint64(tt.number)})
- if err := p2p.ExpectMsg(peer.app, 0x04, resp); err != nil {
- t.Errorf("test %d: block hashes mismatch: %v", i, err)
- }
- }
-}
-
-// Tests that blocks can be retrieved from a remote chain based on their hashes.
-func TestGetBlocks61(t *testing.T) { testGetBlocks(t, 61) }
-
-func testGetBlocks(t *testing.T, protocol int) {
- pm := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil, nil)
- peer, _ := newTestPeer("peer", protocol, pm, true)
- defer peer.close()
-
- // Create a batch of tests for various scenarios
- limit := downloader.MaxBlockFetch
- tests := []struct {
- random int // Number of blocks to fetch randomly from the chain
- explicit []common.Hash // Explicitly requested blocks
- available []bool // Availability of explicitly requested blocks
- expected int // Total number of existing blocks to expect
- }{
- {1, nil, nil, 1}, // A single random block should be retrievable
- {10, nil, nil, 10}, // Multiple random blocks should be retrievable
- {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable
- {limit + 1, nil, nil, limit}, // No more than the possible block count should be returned
- {0, []common.Hash{pm.blockchain.Genesis().Hash()}, []bool{true}, 1}, // The genesis block should be retrievable
- {0, []common.Hash{pm.blockchain.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable
- {0, []common.Hash{common.Hash{}}, []bool{false}, 0}, // A non existent block should not be returned
-
- // Existing and non-existing blocks interleaved should not cause problems
- {0, []common.Hash{
- common.Hash{},
- pm.blockchain.GetBlockByNumber(1).Hash(),
- common.Hash{},
- pm.blockchain.GetBlockByNumber(10).Hash(),
- common.Hash{},
- pm.blockchain.GetBlockByNumber(100).Hash(),
- common.Hash{},
- }, []bool{false, true, false, true, false, true, false}, 3},
- }
- // Run each of the tests and verify the results against the chain
- for i, tt := range tests {
- // Collect the hashes to request, and the response to expect
- hashes, seen := []common.Hash{}, make(map[int64]bool)
- blocks := []*types.Block{}
-
- for j := 0; j < tt.random; j++ {
- for {
- num := rand.Int63n(int64(pm.blockchain.CurrentBlock().NumberU64()))
- if !seen[num] {
- seen[num] = true
-
- block := pm.blockchain.GetBlockByNumber(uint64(num))
- hashes = append(hashes, block.Hash())
- if len(blocks) < tt.expected {
- blocks = append(blocks, block)
- }
- break
- }
- }
- }
- for j, hash := range tt.explicit {
- hashes = append(hashes, hash)
- if tt.available[j] && len(blocks) < tt.expected {
- blocks = append(blocks, pm.blockchain.GetBlockByHash(hash))
- }
- }
- // Send the hash request and verify the response
- p2p.Send(peer.app, 0x05, hashes)
- if err := p2p.ExpectMsg(peer.app, 0x06, blocks); err != nil {
- t.Errorf("test %d: blocks mismatch: %v", i, err)
- }
- }
-}
-
// Tests that block headers can be retrieved from a remote chain based on user queries.
func TestGetBlockHeaders62(t *testing.T) { testGetBlockHeaders(t, 62) }
func TestGetBlockHeaders63(t *testing.T) { testGetBlockHeaders(t, 63) }
@@ -580,3 +428,75 @@ func testGetReceipt(t *testing.T, protocol int) {
t.Errorf("receipts mismatch: %v", err)
}
}
+
+// Tests that post eth protocol handshake, DAO fork-enabled clients also execute
+// a DAO "challenge" verifying each others' DAO fork headers to ensure they're on
+// compatible chains.
+func TestDAOChallengeNoVsNo(t *testing.T) { testDAOChallenge(t, false, false, false) }
+func TestDAOChallengeNoVsPro(t *testing.T) { testDAOChallenge(t, false, true, false) }
+func TestDAOChallengeProVsNo(t *testing.T) { testDAOChallenge(t, true, false, false) }
+func TestDAOChallengeProVsPro(t *testing.T) { testDAOChallenge(t, true, true, false) }
+func TestDAOChallengeNoVsTimeout(t *testing.T) { testDAOChallenge(t, false, false, true) }
+func TestDAOChallengeProVsTimeout(t *testing.T) { testDAOChallenge(t, true, true, true) }
+
+func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool) {
+ // Reduce the DAO handshake challenge timeout
+ if timeout {
+ defer func(old time.Duration) { daoChallengeTimeout = old }(daoChallengeTimeout)
+ daoChallengeTimeout = 500 * time.Millisecond
+ }
+ // Create a DAO aware protocol manager
+ var (
+ evmux = new(event.TypeMux)
+ pow = new(core.FakePow)
+ db, _ = ethdb.NewMemDatabase()
+ genesis = core.WriteGenesisBlockForTesting(db)
+ config = &core.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
+ blockchain, _ = core.NewBlockChain(db, config, pow, evmux)
+ )
+ pm, err := NewProtocolManager(config, false, NetworkId, evmux, new(testTxPool), pow, blockchain, db)
+ if err != nil {
+ t.Fatalf("failed to start test protocol manager: %v", err)
+ }
+ pm.Start()
+ defer pm.Stop()
+
+ // Connect a new peer and check that we receive the DAO challenge
+ peer, _ := newTestPeer("peer", eth63, pm, true)
+ defer peer.close()
+
+ challenge := &getBlockHeadersData{
+ Origin: hashOrNumber{Number: config.DAOForkBlock.Uint64()},
+ Amount: 1,
+ Skip: 0,
+ Reverse: false,
+ }
+ if err := p2p.ExpectMsg(peer.app, GetBlockHeadersMsg, challenge); err != nil {
+ t.Fatalf("challenge mismatch: %v", err)
+ }
+ // Create a block to reply to the challenge if no timeout is simualted
+ if !timeout {
+ blocks, _ := core.GenerateChain(nil, genesis, db, 1, func(i int, block *core.BlockGen) {
+ if remoteForked {
+ block.SetExtra(params.DAOForkBlockExtra)
+ }
+ })
+ if err := p2p.Send(peer.app, BlockHeadersMsg, []*types.Header{blocks[0].Header()}); err != nil {
+ t.Fatalf("failed to answer challenge: %v", err)
+ }
+ time.Sleep(100 * time.Millisecond) // Sleep to avoid the verification racing with the drops
+ } else {
+ // Otherwise wait until the test timeout passes
+ time.Sleep(daoChallengeTimeout + 500*time.Millisecond)
+ }
+ // Verify that depending on fork side, the remote peer is maintained or dropped
+ if localForked == remoteForked && !timeout {
+ if peers := pm.peers.Len(); peers != 1 {
+ t.Fatalf("peer count mismatch: have %d, want %d", peers, 1)
+ }
+ } else {
+ if peers := pm.peers.Len(); peers != 0 {
+ t.Fatalf("peer count mismatch: have %d, want %d", peers, 0)
+ }
+ }
+}
diff --git a/eth/helper_test.go b/eth/helper_test.go
index dacb1593f..28ff69b17 100644
--- a/eth/helper_test.go
+++ b/eth/helper_test.go
@@ -56,7 +56,7 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core
chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux)
)
- chain, _ := core.GenerateChain(genesis, db, blocks, generator)
+ chain, _ := core.GenerateChain(nil, genesis, db, blocks, generator)
if _, err := blockchain.InsertChain(chain); err != nil {
panic(err)
}
diff --git a/eth/metrics.go b/eth/metrics.go
index e1a89d3a9..5fa2597d4 100644
--- a/eth/metrics.go
+++ b/eth/metrics.go
@@ -34,14 +34,6 @@ var (
propBlockInTrafficMeter = metrics.NewMeter("eth/prop/blocks/in/traffic")
propBlockOutPacketsMeter = metrics.NewMeter("eth/prop/blocks/out/packets")
propBlockOutTrafficMeter = metrics.NewMeter("eth/prop/blocks/out/traffic")
- reqHashInPacketsMeter = metrics.NewMeter("eth/req/hashes/in/packets")
- reqHashInTrafficMeter = metrics.NewMeter("eth/req/hashes/in/traffic")
- reqHashOutPacketsMeter = metrics.NewMeter("eth/req/hashes/out/packets")
- reqHashOutTrafficMeter = metrics.NewMeter("eth/req/hashes/out/traffic")
- reqBlockInPacketsMeter = metrics.NewMeter("eth/req/blocks/in/packets")
- reqBlockInTrafficMeter = metrics.NewMeter("eth/req/blocks/in/traffic")
- reqBlockOutPacketsMeter = metrics.NewMeter("eth/req/blocks/out/packets")
- reqBlockOutTrafficMeter = metrics.NewMeter("eth/req/blocks/out/traffic")
reqHeaderInPacketsMeter = metrics.NewMeter("eth/req/headers/in/packets")
reqHeaderInTrafficMeter = metrics.NewMeter("eth/req/headers/in/traffic")
reqHeaderOutPacketsMeter = metrics.NewMeter("eth/req/headers/out/packets")
@@ -95,14 +87,9 @@ func (rw *meteredMsgReadWriter) ReadMsg() (p2p.Msg, error) {
// Account for the data traffic
packets, traffic := miscInPacketsMeter, miscInTrafficMeter
switch {
- case rw.version < eth62 && msg.Code == BlockHashesMsg:
- packets, traffic = reqHashInPacketsMeter, reqHashInTrafficMeter
- case rw.version < eth62 && msg.Code == BlocksMsg:
- packets, traffic = reqBlockInPacketsMeter, reqBlockInTrafficMeter
-
- case rw.version >= eth62 && msg.Code == BlockHeadersMsg:
+ case msg.Code == BlockHeadersMsg:
packets, traffic = reqHeaderInPacketsMeter, reqHeaderInTrafficMeter
- case rw.version >= eth62 && msg.Code == BlockBodiesMsg:
+ case msg.Code == BlockBodiesMsg:
packets, traffic = reqBodyInPacketsMeter, reqBodyInTrafficMeter
case rw.version >= eth63 && msg.Code == NodeDataMsg:
@@ -127,14 +114,9 @@ func (rw *meteredMsgReadWriter) WriteMsg(msg p2p.Msg) error {
// Account for the data traffic
packets, traffic := miscOutPacketsMeter, miscOutTrafficMeter
switch {
- case rw.version < eth62 && msg.Code == BlockHashesMsg:
- packets, traffic = reqHashOutPacketsMeter, reqHashOutTrafficMeter
- case rw.version < eth62 && msg.Code == BlocksMsg:
- packets, traffic = reqBlockOutPacketsMeter, reqBlockOutTrafficMeter
-
- case rw.version >= eth62 && msg.Code == BlockHeadersMsg:
+ case msg.Code == BlockHeadersMsg:
packets, traffic = reqHeaderOutPacketsMeter, reqHeaderOutTrafficMeter
- case rw.version >= eth62 && msg.Code == BlockBodiesMsg:
+ case msg.Code == BlockBodiesMsg:
packets, traffic = reqBodyOutPacketsMeter, reqBodyOutTrafficMeter
case rw.version >= eth63 && msg.Code == NodeDataMsg:
diff --git a/eth/peer.go b/eth/peer.go
index 8eb41b0f9..c8c207ecb 100644
--- a/eth/peer.go
+++ b/eth/peer.go
@@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p"
@@ -59,10 +58,12 @@ type peer struct {
*p2p.Peer
rw p2p.MsgReadWriter
- version int // Protocol version negotiated
- head common.Hash
- td *big.Int
- lock sync.RWMutex
+ version int // Protocol version negotiated
+ forkDrop *time.Timer // Timed connection dropper if forks aren't validated in time
+
+ head common.Hash
+ td *big.Int
+ lock sync.RWMutex
knownTxs *set.Set // Set of transaction hashes known to be known by this peer
knownBlocks *set.Set // Set of block hashes known to be known by this peer
@@ -152,25 +153,6 @@ func (p *peer) SendTransactions(txs types.Transactions) error {
return p2p.Send(p.rw, TxMsg, txs)
}
-// SendBlockHashes sends a batch of known hashes to the remote peer.
-func (p *peer) SendBlockHashes(hashes []common.Hash) error {
- return p2p.Send(p.rw, BlockHashesMsg, hashes)
-}
-
-// SendBlocks sends a batch of blocks to the remote peer.
-func (p *peer) SendBlocks(blocks []*types.Block) error {
- return p2p.Send(p.rw, BlocksMsg, blocks)
-}
-
-// SendNewBlockHashes61 announces the availability of a number of blocks through
-// a hash notification.
-func (p *peer) SendNewBlockHashes61(hashes []common.Hash) error {
- for _, hash := range hashes {
- p.knownBlocks.Add(hash)
- }
- return p2p.Send(p.rw, NewBlockHashesMsg, hashes)
-}
-
// SendNewBlockHashes announces the availability of a number of blocks through
// a hash notification.
func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error {
@@ -219,26 +201,6 @@ func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error {
return p2p.Send(p.rw, ReceiptsMsg, receipts)
}
-// RequestHashes fetches a batch of hashes from a peer, starting at from, going
-// towards the genesis block.
-func (p *peer) RequestHashes(from common.Hash) error {
- glog.V(logger.Debug).Infof("%v fetching hashes (%d) from %x...", p, downloader.MaxHashFetch, from[:4])
- return p2p.Send(p.rw, GetBlockHashesMsg, getBlockHashesData{from, uint64(downloader.MaxHashFetch)})
-}
-
-// RequestHashesFromNumber fetches a batch of hashes from a peer, starting at
-// the requested block number, going upwards towards the genesis block.
-func (p *peer) RequestHashesFromNumber(from uint64, count int) error {
- glog.V(logger.Debug).Infof("%v fetching hashes (%d) from #%d...", p, count, from)
- return p2p.Send(p.rw, GetBlockHashesFromNumberMsg, getBlockHashesFromNumberData{from, uint64(count)})
-}
-
-// RequestBlocks fetches a batch of blocks corresponding to the specified hashes.
-func (p *peer) RequestBlocks(hashes []common.Hash) error {
- glog.V(logger.Debug).Infof("%v fetching %v blocks", p, len(hashes))
- return p2p.Send(p.rw, GetBlocksMsg, hashes)
-}
-
// RequestHeaders is a wrapper around the header query functions to fetch a
// single header. It is used solely by the fetcher.
func (p *peer) RequestOneHeader(hash common.Hash) error {
diff --git a/eth/protocol.go b/eth/protocol.go
index 808ac0601..69b3be578 100644
--- a/eth/protocol.go
+++ b/eth/protocol.go
@@ -28,7 +28,6 @@ import (
// Constants to match up protocol versions and messages
const (
- eth61 = 61
eth62 = 62
eth63 = 63
)
@@ -37,10 +36,10 @@ const (
var ProtocolName = "eth"
// Supported versions of the eth protocol (first is primary).
-var ProtocolVersions = []uint{eth63, eth62, eth61}
+var ProtocolVersions = []uint{eth63, eth62}
// Number of implemented message corresponding to different protocol versions.
-var ProtocolLengths = []uint64{17, 8, 9}
+var ProtocolLengths = []uint64{17, 8}
const (
NetworkId = 1
@@ -49,26 +48,15 @@ const (
// eth protocol message codes
const (
- // Protocol messages belonging to eth/61
- StatusMsg = 0x00
- NewBlockHashesMsg = 0x01
- TxMsg = 0x02
- GetBlockHashesMsg = 0x03
- BlockHashesMsg = 0x04
- GetBlocksMsg = 0x05
- BlocksMsg = 0x06
- NewBlockMsg = 0x07
- GetBlockHashesFromNumberMsg = 0x08
-
- // Protocol messages belonging to eth/62 (new protocol from scratch)
- // StatusMsg = 0x00 (uncomment after eth/61 deprecation)
- // NewBlockHashesMsg = 0x01 (uncomment after eth/61 deprecation)
- // TxMsg = 0x02 (uncomment after eth/61 deprecation)
+ // Protocol messages belonging to eth/62
+ StatusMsg = 0x00
+ NewBlockHashesMsg = 0x01
+ TxMsg = 0x02
GetBlockHeadersMsg = 0x03
BlockHeadersMsg = 0x04
GetBlockBodiesMsg = 0x05
BlockBodiesMsg = 0x06
- // NewBlockMsg = 0x07 (uncomment after eth/61 deprecation)
+ NewBlockMsg = 0x07
// Protocol messages belonging to eth/63
GetNodeDataMsg = 0x0d
@@ -117,12 +105,6 @@ type txPool interface {
GetTransactions() types.Transactions
}
-type chainManager interface {
- GetBlockHashesFromHash(hash common.Hash, amount uint64) (hashes []common.Hash)
- GetBlock(hash common.Hash) (block *types.Block)
- Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
-}
-
// statusData is the network packet for the status message.
type statusData struct {
ProtocolVersion uint32
@@ -138,19 +120,6 @@ type newBlockHashesData []struct {
Number uint64 // Number of one particular block being announced
}
-// getBlockHashesData is the network packet for the hash based hash retrieval.
-type getBlockHashesData struct {
- Hash common.Hash
- Amount uint64
-}
-
-// getBlockHashesFromNumberData is the network packet for the number based hash
-// retrieval.
-type getBlockHashesFromNumberData struct {
- Number uint64
- Amount uint64
-}
-
// getBlockHeadersData represents a block header query.
type getBlockHeadersData struct {
Origin hashOrNumber // Block from which to retrieve headers
@@ -209,8 +178,3 @@ type blockBody struct {
// blockBodiesData is the network packet for block content distribution.
type blockBodiesData []*blockBody
-
-// nodeDataData is the network response packet for a node data retrieval.
-type nodeDataData []struct {
- Value []byte
-}
diff --git a/eth/protocol_test.go b/eth/protocol_test.go
index f860d0a35..4633344da 100644
--- a/eth/protocol_test.go
+++ b/eth/protocol_test.go
@@ -37,7 +37,6 @@ func init() {
var testAccount, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
// Tests that handshake failures are detected and reported correctly.
-func TestStatusMsgErrors61(t *testing.T) { testStatusMsgErrors(t, 61) }
func TestStatusMsgErrors62(t *testing.T) { testStatusMsgErrors(t, 62) }
func TestStatusMsgErrors63(t *testing.T) { testStatusMsgErrors(t, 63) }
@@ -90,7 +89,6 @@ func testStatusMsgErrors(t *testing.T, protocol int) {
}
// This test checks that received transactions are added to the local pool.
-func TestRecvTransactions61(t *testing.T) { testRecvTransactions(t, 61) }
func TestRecvTransactions62(t *testing.T) { testRecvTransactions(t, 62) }
func TestRecvTransactions63(t *testing.T) { testRecvTransactions(t, 63) }
@@ -119,7 +117,6 @@ func testRecvTransactions(t *testing.T, protocol int) {
}
// This test checks that pending transactions are sent.
-func TestSendTransactions61(t *testing.T) { testSendTransactions(t, 61) }
func TestSendTransactions62(t *testing.T) { testSendTransactions(t, 62) }
func TestSendTransactions63(t *testing.T) { testSendTransactions(t, 63) }
diff --git a/ethdb/database.go b/ethdb/database.go
index dffb42e2b..29da4a197 100644
--- a/ethdb/database.go
+++ b/ethdb/database.go
@@ -36,14 +36,14 @@ import (
var OpenFileLimit = 64
-// cacheRatio specifies how the total alloted cache is distributed between the
+// cacheRatio specifies how the total allotted cache is distributed between the
// various system databases.
var cacheRatio = map[string]float64{
"dapp": 0.0,
"chaindata": 1.0,
}
-// handleRatio specifies how the total alloted file descriptors is distributed
+// handleRatio specifies how the total allotted file descriptors is distributed
// between the various system databases.
var handleRatio = map[string]float64{
"dapp": 0.0,
@@ -79,7 +79,7 @@ func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) {
if handles < 16 {
handles = 16
}
- glog.V(logger.Info).Infof("Alloted %dMB cache and %d file handles to %s", cache, handles, file)
+ glog.V(logger.Info).Infof("Allotted %dMB cache and %d file handles to %s", cache, handles, file)
// Open the db and recover any potential corruptions
db, err := leveldb.OpenFile(file, &opt.Options{
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
new file mode 100644
index 000000000..88bacc45b
--- /dev/null
+++ b/internal/ethapi/api.go
@@ -0,0 +1,1548 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package ethapi
+
+import (
+ "bytes"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math/big"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/ethereum/ethash"
+ "github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/compiler"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/rpc"
+ "github.com/syndtr/goleveldb/leveldb"
+ "golang.org/x/net/context"
+)
+
+const defaultGas = uint64(90000)
+
+// PublicEthereumAPI provides an API to access Ethereum related information.
+// It offers only methods that operate on public data that is freely available to anyone.
+type PublicEthereumAPI struct {
+ b Backend
+ solcPath *string
+ solc **compiler.Solidity
+}
+
+// NewPublicEthereumAPI creates a new Etheruem protocol API.
+func NewPublicEthereumAPI(b Backend, solcPath *string, solc **compiler.Solidity) *PublicEthereumAPI {
+ return &PublicEthereumAPI{b, solcPath, solc}
+}
+
+// GasPrice returns a suggestion for a gas price.
+func (s *PublicEthereumAPI) GasPrice(ctx context.Context) (*big.Int, error) {
+ return s.b.SuggestPrice(ctx)
+}
+
+func (s *PublicEthereumAPI) getSolc() (*compiler.Solidity, error) {
+ var err error
+ solc := *s.solc
+ if solc == nil {
+ solc, err = compiler.New(*s.solcPath)
+ }
+ return solc, err
+}
+
+// GetCompilers returns the collection of available smart contract compilers
+func (s *PublicEthereumAPI) GetCompilers() ([]string, error) {
+ solc, err := s.getSolc()
+ if err == nil && solc != nil {
+ return []string{"Solidity"}, nil
+ }
+
+ return []string{}, nil
+}
+
+// CompileSolidity compiles the given solidity source
+func (s *PublicEthereumAPI) CompileSolidity(source string) (map[string]*compiler.Contract, error) {
+ solc, err := s.getSolc()
+ if err != nil {
+ return nil, err
+ }
+
+ if solc == nil {
+ return nil, errors.New("solc (solidity compiler) not found")
+ }
+
+ return solc.Compile(source)
+}
+
+// ProtocolVersion returns the current Ethereum protocol version this node supports
+func (s *PublicEthereumAPI) ProtocolVersion() *rpc.HexNumber {
+ return rpc.NewHexNumber(s.b.ProtocolVersion())
+}
+
+// Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not
+// yet received the latest block headers from its pears. In case it is synchronizing:
+// - startingBlock: block number this node started to synchronise from
+// - currentBlock: block number this node is currently importing
+// - highestBlock: block number of the highest block header this node has received from peers
+// - pulledStates: number of state entries processed until now
+// - knownStates: number of known state entries that still need to be pulled
+func (s *PublicEthereumAPI) Syncing() (interface{}, error) {
+ origin, current, height, pulled, known := s.b.Downloader().Progress()
+
+ // Return not syncing if the synchronisation already completed
+ if current >= height {
+ return false, nil
+ }
+ // Otherwise gather the block sync stats
+ return map[string]interface{}{
+ "startingBlock": rpc.NewHexNumber(origin),
+ "currentBlock": rpc.NewHexNumber(current),
+ "highestBlock": rpc.NewHexNumber(height),
+ "pulledStates": rpc.NewHexNumber(pulled),
+ "knownStates": rpc.NewHexNumber(known),
+ }, nil
+}
+
+// PublicTxPoolAPI offers and API for the transaction pool. It only operates on data that is non confidential.
+type PublicTxPoolAPI struct {
+ b Backend
+}
+
+// NewPublicTxPoolAPI creates a new tx pool service that gives information about the transaction pool.
+func NewPublicTxPoolAPI(b Backend) *PublicTxPoolAPI {
+ return &PublicTxPoolAPI{b}
+}
+
+// Content returns the transactions contained within the transaction pool.
+func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string][]*RPCTransaction {
+ content := map[string]map[string]map[string][]*RPCTransaction{
+ "pending": make(map[string]map[string][]*RPCTransaction),
+ "queued": make(map[string]map[string][]*RPCTransaction),
+ }
+ pending, queue := s.b.TxPoolContent()
+
+ // Flatten the pending transactions
+ for account, batches := range pending {
+ dump := make(map[string][]*RPCTransaction)
+ for nonce, txs := range batches {
+ nonce := fmt.Sprintf("%d", nonce)
+ for _, tx := range txs {
+ dump[nonce] = append(dump[nonce], newRPCPendingTransaction(tx))
+ }
+ }
+ content["pending"][account.Hex()] = dump
+ }
+ // Flatten the queued transactions
+ for account, batches := range queue {
+ dump := make(map[string][]*RPCTransaction)
+ for nonce, txs := range batches {
+ nonce := fmt.Sprintf("%d", nonce)
+ for _, tx := range txs {
+ dump[nonce] = append(dump[nonce], newRPCPendingTransaction(tx))
+ }
+ }
+ content["queued"][account.Hex()] = dump
+ }
+ return content
+}
+
+// Status returns the number of pending and queued transaction in the pool.
+func (s *PublicTxPoolAPI) Status() map[string]*rpc.HexNumber {
+ pending, queue := s.b.Stats()
+ return map[string]*rpc.HexNumber{
+ "pending": rpc.NewHexNumber(pending),
+ "queued": rpc.NewHexNumber(queue),
+ }
+}
+
+// Inspect retrieves the content of the transaction pool and flattens it into an
+// easily inspectable list.
+func (s *PublicTxPoolAPI) Inspect() map[string]map[string]map[string][]string {
+ content := map[string]map[string]map[string][]string{
+ "pending": make(map[string]map[string][]string),
+ "queued": make(map[string]map[string][]string),
+ }
+ pending, queue := s.b.TxPoolContent()
+
+ // Define a formatter to flatten a transaction into a string
+ var format = func(tx *types.Transaction) string {
+ if to := tx.To(); to != nil {
+ return fmt.Sprintf("%s: %v wei + %v × %v gas", tx.To().Hex(), tx.Value(), tx.Gas(), tx.GasPrice())
+ }
+ return fmt.Sprintf("contract creation: %v wei + %v × %v gas", tx.Value(), tx.Gas(), tx.GasPrice())
+ }
+ // Flatten the pending transactions
+ for account, batches := range pending {
+ dump := make(map[string][]string)
+ for nonce, txs := range batches {
+ nonce := fmt.Sprintf("%d", nonce)
+ for _, tx := range txs {
+ dump[nonce] = append(dump[nonce], format(tx))
+ }
+ }
+ content["pending"][account.Hex()] = dump
+ }
+ // Flatten the queued transactions
+ for account, batches := range queue {
+ dump := make(map[string][]string)
+ for nonce, txs := range batches {
+ nonce := fmt.Sprintf("%d", nonce)
+ for _, tx := range txs {
+ dump[nonce] = append(dump[nonce], format(tx))
+ }
+ }
+ content["queued"][account.Hex()] = dump
+ }
+ return content
+}
+
+// PublicAccountAPI provides an API to access accounts managed by this node.
+// It offers only methods that can retrieve accounts.
+type PublicAccountAPI struct {
+ am *accounts.Manager
+}
+
+// NewPublicAccountAPI creates a new PublicAccountAPI.
+func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI {
+ return &PublicAccountAPI{am: am}
+}
+
+// Accounts returns the collection of accounts this node manages
+func (s *PublicAccountAPI) Accounts() []accounts.Account {
+ return s.am.Accounts()
+}
+
+// PrivateAccountAPI provides an API to access accounts managed by this node.
+// It offers methods to create, (un)lock en list accounts. Some methods accept
+// passwords and are therefore considered private by default.
+type PrivateAccountAPI struct {
+ am *accounts.Manager
+ b Backend
+}
+
+// NewPrivateAccountAPI create a new PrivateAccountAPI.
+func NewPrivateAccountAPI(b Backend) *PrivateAccountAPI {
+ return &PrivateAccountAPI{
+ am: b.AccountManager(),
+ b: b,
+ }
+}
+
+// ListAccounts will return a list of addresses for accounts this node manages.
+func (s *PrivateAccountAPI) ListAccounts() []common.Address {
+ accounts := s.am.Accounts()
+ addresses := make([]common.Address, len(accounts))
+ for i, acc := range accounts {
+ addresses[i] = acc.Address
+ }
+ return addresses
+}
+
+// NewAccount will create a new account and returns the address for the new account.
+func (s *PrivateAccountAPI) NewAccount(password string) (common.Address, error) {
+ acc, err := s.am.NewAccount(password)
+ if err == nil {
+ return acc.Address, nil
+ }
+ return common.Address{}, err
+}
+
+// ImportRawKey stores the given hex encoded ECDSA key into the key directory,
+// encrypting it with the passphrase.
+func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) {
+ hexkey, err := hex.DecodeString(privkey)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ acc, err := s.am.ImportECDSA(crypto.ToECDSA(hexkey), password)
+ return acc.Address, err
+}
+
+// UnlockAccount will unlock the account associated with the given address with
+// the given password for duration seconds. If duration is nil it will use a
+// default of 300 seconds. It returns an indication if the account was unlocked.
+func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *rpc.HexNumber) (bool, error) {
+ if duration == nil {
+ duration = rpc.NewHexNumber(300)
+ }
+ a := accounts.Account{Address: addr}
+ d := time.Duration(duration.Int64()) * time.Second
+ if err := s.am.TimedUnlock(a, password, d); err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
+// LockAccount will lock the account associated with the given address when it's unlocked.
+func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
+ return s.am.Lock(addr) == nil
+}
+
+// SendTransaction will create a transaction from the given arguments and
+// tries to sign it with the key associated with args.To. If the given passwd isn't
+// able to decrypt the key it fails.
+func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
+ var err error
+ args, err = prepareSendTxArgs(ctx, args, s.b)
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ if args.Nonce == nil {
+ nonce, err := s.b.GetPoolNonce(ctx, args.From)
+ if err != nil {
+ return common.Hash{}, err
+ }
+ args.Nonce = rpc.NewHexNumber(nonce)
+ }
+
+ var tx *types.Transaction
+ if args.To == nil {
+ tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
+ } else {
+ tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
+ }
+
+ signature, err := s.am.SignWithPassphrase(args.From, passwd, tx.SigHash().Bytes())
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ return submitTransaction(ctx, s.b, tx, signature)
+}
+
+// SignAndSendTransaction was renamed to SendTransaction. This method is deprecated
+// and will be removed in the future. It primary goal is to give clients time to update.
+func (s *PrivateAccountAPI) SignAndSendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
+ return s.SendTransaction(ctx, args, passwd)
+}
+
+// PublicBlockChainAPI provides an API to access the Ethereum blockchain.
+// It offers only methods that operate on public data that is freely available to anyone.
+type PublicBlockChainAPI struct {
+ b Backend
+ muNewBlockSubscriptions sync.Mutex // protects newBlocksSubscriptions
+ newBlockSubscriptions map[string]func(core.ChainEvent) error // callbacks for new block subscriptions
+}
+
+// NewPublicBlockChainAPI creates a new Etheruem blockchain API.
+func NewPublicBlockChainAPI(b Backend) *PublicBlockChainAPI {
+ api := &PublicBlockChainAPI{
+ b: b,
+ newBlockSubscriptions: make(map[string]func(core.ChainEvent) error),
+ }
+
+ go api.subscriptionLoop()
+
+ return api
+}
+
+// subscriptionLoop reads events from the global event mux and creates notifications for the matched subscriptions.
+func (s *PublicBlockChainAPI) subscriptionLoop() {
+ sub := s.b.EventMux().Subscribe(core.ChainEvent{})
+ for event := range sub.Chan() {
+ if chainEvent, ok := event.Data.(core.ChainEvent); ok {
+ s.muNewBlockSubscriptions.Lock()
+ for id, notifyOf := range s.newBlockSubscriptions {
+ if notifyOf(chainEvent) == rpc.ErrNotificationNotFound {
+ delete(s.newBlockSubscriptions, id)
+ }
+ }
+ s.muNewBlockSubscriptions.Unlock()
+ }
+ }
+}
+
+// BlockNumber returns the block number of the chain head.
+func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
+ return s.b.HeaderByNumber(rpc.LatestBlockNumber).Number
+}
+
+// GetBalance returns the amount of wei for the given address in the state of the
+// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
+// block numbers are also allowed.
+func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*big.Int, error) {
+ state, _, err := s.b.StateAndHeaderByNumber(blockNr)
+ if state == nil || err != nil {
+ return nil, err
+ }
+
+ return state.GetBalance(ctx, address)
+}
+
+// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
+// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
+func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
+ block, err := s.b.BlockByNumber(ctx, blockNr)
+ if block != nil {
+ response, err := s.rpcOutputBlock(block, true, fullTx)
+ if err == nil && blockNr == rpc.PendingBlockNumber {
+ // Pending blocks need to nil out a few fields
+ for _, field := range []string{"hash", "nonce", "logsBloom", "miner"} {
+ response[field] = nil
+ }
+ }
+ return response, err
+ }
+ return nil, err
+}
+
+// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
+// detail, otherwise only the transaction hash is returned.
+func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
+ block, err := s.b.GetBlock(ctx, blockHash)
+ if block != nil {
+ return s.rpcOutputBlock(block, true, fullTx)
+ }
+ return nil, err
+}
+
+// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
+// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
+func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index rpc.HexNumber) (map[string]interface{}, error) {
+ block, err := s.b.BlockByNumber(ctx, blockNr)
+ if block != nil {
+ uncles := block.Uncles()
+ if index.Int() < 0 || index.Int() >= len(uncles) {
+ glog.V(logger.Debug).Infof("uncle block on index %d not found for block #%d", index.Int(), blockNr)
+ return nil, nil
+ }
+ block = types.NewBlockWithHeader(uncles[index.Int()])
+ return s.rpcOutputBlock(block, false, false)
+ }
+ return nil, err
+}
+
+// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true
+// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
+func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index rpc.HexNumber) (map[string]interface{}, error) {
+ block, err := s.b.GetBlock(ctx, blockHash)
+ if block != nil {
+ uncles := block.Uncles()
+ if index.Int() < 0 || index.Int() >= len(uncles) {
+ glog.V(logger.Debug).Infof("uncle block on index %d not found for block %s", index.Int(), blockHash.Hex())
+ return nil, nil
+ }
+ block = types.NewBlockWithHeader(uncles[index.Int()])
+ return s.rpcOutputBlock(block, false, false)
+ }
+ return nil, err
+}
+
+// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
+func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *rpc.HexNumber {
+ if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
+ return rpc.NewHexNumber(len(block.Uncles()))
+ }
+ return nil
+}
+
+// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
+func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *rpc.HexNumber {
+ if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
+ return rpc.NewHexNumber(len(block.Uncles()))
+ }
+ return nil
+}
+
+// NewBlocksArgs allows the user to specify if the returned block should include transactions and in which format.
+type NewBlocksArgs struct {
+ IncludeTransactions bool `json:"includeTransactions"`
+ TransactionDetails bool `json:"transactionDetails"`
+}
+
+// NewBlocks triggers a new block event each time a block is appended to the chain. It accepts an argument which allows
+// the caller to specify whether the output should contain transactions and in what format.
+func (s *PublicBlockChainAPI) NewBlocks(ctx context.Context, args NewBlocksArgs) (rpc.Subscription, error) {
+ notifier, supported := rpc.NotifierFromContext(ctx)
+ if !supported {
+ return nil, rpc.ErrNotificationsUnsupported
+ }
+
+ // create a subscription that will remove itself when unsubscribed/cancelled
+ subscription, err := notifier.NewSubscription(func(subId string) {
+ s.muNewBlockSubscriptions.Lock()
+ delete(s.newBlockSubscriptions, subId)
+ s.muNewBlockSubscriptions.Unlock()
+ })
+
+ if err != nil {
+ return nil, err
+ }
+
+ // add a callback that is called on chain events which will format the block and notify the client
+ s.muNewBlockSubscriptions.Lock()
+ s.newBlockSubscriptions[subscription.ID()] = func(e core.ChainEvent) error {
+ notification, err := s.rpcOutputBlock(e.Block, args.IncludeTransactions, args.TransactionDetails)
+ if err == nil {
+ return subscription.Notify(notification)
+ }
+ glog.V(logger.Warn).Info("unable to format block %v\n", err)
+ return nil
+ }
+ s.muNewBlockSubscriptions.Unlock()
+ return subscription, nil
+}
+
+// GetCode returns the code stored at the given address in the state for the given block number.
+func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (string, error) {
+ state, _, err := s.b.StateAndHeaderByNumber(blockNr)
+ if state == nil || err != nil {
+ return "", err
+ }
+ res, err := state.GetCode(ctx, address)
+ if len(res) == 0 || err != nil { // backwards compatibility
+ return "0x", err
+ }
+ return common.ToHex(res), nil
+}
+
+// GetStorageAt returns the storage from the state at the given address, key and
+// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
+// numbers are also allowed.
+func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNr rpc.BlockNumber) (string, error) {
+ state, _, err := s.b.StateAndHeaderByNumber(blockNr)
+ if state == nil || err != nil {
+ return "0x", err
+ }
+ res, err := state.GetState(ctx, address, common.HexToHash(key))
+ if err != nil {
+ return "0x", err
+ }
+ return res.Hex(), nil
+}
+
+// callmsg is the message type used for call transations.
+type callmsg struct {
+ addr common.Address
+ to *common.Address
+ gas, gasPrice *big.Int
+ value *big.Int
+ data []byte
+}
+
+// accessor boilerplate to implement core.Message
+func (m callmsg) From() (common.Address, error) { return m.addr, nil }
+func (m callmsg) FromFrontier() (common.Address, error) { return m.addr, nil }
+func (m callmsg) Nonce() uint64 { return 0 }
+func (m callmsg) CheckNonce() bool { return false }
+func (m callmsg) To() *common.Address { return m.to }
+func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
+func (m callmsg) Gas() *big.Int { return m.gas }
+func (m callmsg) Value() *big.Int { return m.value }
+func (m callmsg) Data() []byte { return m.data }
+
+// CallArgs represents the arguments for a call.
+type CallArgs struct {
+ From common.Address `json:"from"`
+ To *common.Address `json:"to"`
+ Gas rpc.HexNumber `json:"gas"`
+ GasPrice rpc.HexNumber `json:"gasPrice"`
+ Value rpc.HexNumber `json:"value"`
+ Data string `json:"data"`
+}
+
+func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) {
+ state, header, err := s.b.StateAndHeaderByNumber(blockNr)
+ if state == nil || err != nil {
+ return "0x", common.Big0, err
+ }
+
+ // Set the account address to interact with
+ var addr common.Address
+ if args.From == (common.Address{}) {
+ accounts := s.b.AccountManager().Accounts()
+ if len(accounts) == 0 {
+ addr = common.Address{}
+ } else {
+ addr = accounts[0].Address
+ }
+ } else {
+ addr = args.From
+ }
+
+ // Assemble the CALL invocation
+ msg := callmsg{
+ addr: addr,
+ to: args.To,
+ gas: args.Gas.BigInt(),
+ gasPrice: args.GasPrice.BigInt(),
+ value: args.Value.BigInt(),
+ data: common.FromHex(args.Data),
+ }
+
+ if msg.gas.Cmp(common.Big0) == 0 {
+ msg.gas = big.NewInt(50000000)
+ }
+
+ if msg.gasPrice.Cmp(common.Big0) == 0 {
+ msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
+ }
+
+ // Execute the call and return
+ vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header)
+ if err != nil {
+ return "0x", common.Big0, err
+ }
+ gp := new(core.GasPool).AddGas(common.MaxBig)
+ res, gas, err := core.ApplyMessage(vmenv, msg, gp)
+ if err := vmError(); err != nil {
+ return "0x", common.Big0, err
+ }
+ if len(res) == 0 { // backwards compatability
+ return "0x", gas, err
+ }
+ return common.ToHex(res), gas, err
+}
+
+// Call executes the given transaction on the state for the given block number.
+// It doesn't make and changes in the state/blockchain and is usefull to execute and retrieve values.
+func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (string, error) {
+ result, _, err := s.doCall(ctx, args, blockNr)
+ return result, err
+}
+
+// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
+func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*rpc.HexNumber, error) {
+ _, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber)
+ return rpc.NewHexNumber(gas), err
+}
+
+// ExecutionResult groups all structured logs emitted by the EVM
+// while replaying a transaction in debug mode as well as the amount of
+// gas used and the return value
+type ExecutionResult struct {
+ Gas *big.Int `json:"gas"`
+ ReturnValue string `json:"returnValue"`
+ StructLogs []StructLogRes `json:"structLogs"`
+}
+
+// StructLogRes stores a structured log emitted by the EVM while replaying a
+// transaction in debug mode
+type StructLogRes struct {
+ Pc uint64 `json:"pc"`
+ Op string `json:"op"`
+ Gas *big.Int `json:"gas"`
+ GasCost *big.Int `json:"gasCost"`
+ Depth int `json:"depth"`
+ Error error `json:"error"`
+ Stack []string `json:"stack"`
+ Memory []string `json:"memory"`
+ Storage map[string]string `json:"storage"`
+}
+
+// formatLogs formats EVM returned structured logs for json output
+func FormatLogs(structLogs []vm.StructLog) []StructLogRes {
+ formattedStructLogs := make([]StructLogRes, len(structLogs))
+ for index, trace := range structLogs {
+ formattedStructLogs[index] = StructLogRes{
+ Pc: trace.Pc,
+ Op: trace.Op.String(),
+ Gas: trace.Gas,
+ GasCost: trace.GasCost,
+ Depth: trace.Depth,
+ Error: trace.Err,
+ Stack: make([]string, len(trace.Stack)),
+ Storage: make(map[string]string),
+ }
+
+ for i, stackValue := range trace.Stack {
+ formattedStructLogs[index].Stack[i] = fmt.Sprintf("%x", common.LeftPadBytes(stackValue.Bytes(), 32))
+ }
+
+ for i := 0; i+32 <= len(trace.Memory); i += 32 {
+ formattedStructLogs[index].Memory = append(formattedStructLogs[index].Memory, fmt.Sprintf("%x", trace.Memory[i:i+32]))
+ }
+
+ for i, storageValue := range trace.Storage {
+ formattedStructLogs[index].Storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue)
+ }
+ }
+ return formattedStructLogs
+}
+
+// TraceCall executes a call and returns the amount of gas, created logs and optionally returned values.
+func (s *PublicBlockChainAPI) TraceCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (*ExecutionResult, error) {
+ state, header, err := s.b.StateAndHeaderByNumber(blockNr)
+ if state == nil || err != nil {
+ return nil, err
+ }
+
+ var addr common.Address
+ if args.From == (common.Address{}) {
+ accounts := s.b.AccountManager().Accounts()
+ if len(accounts) == 0 {
+ addr = common.Address{}
+ } else {
+ addr = accounts[0].Address
+ }
+ } else {
+ addr = args.From
+ }
+
+ // Assemble the CALL invocation
+ msg := callmsg{
+ addr: addr,
+ to: args.To,
+ gas: args.Gas.BigInt(),
+ gasPrice: args.GasPrice.BigInt(),
+ value: args.Value.BigInt(),
+ data: common.FromHex(args.Data),
+ }
+
+ if msg.gas.Cmp(common.Big0) == 0 {
+ msg.gas = big.NewInt(50000000)
+ }
+
+ if msg.gasPrice.Cmp(common.Big0) == 0 {
+ msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
+ }
+
+ // Execute the call and return
+ vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header)
+ if err != nil {
+ return nil, err
+ }
+ gp := new(core.GasPool).AddGas(common.MaxBig)
+ ret, gas, err := core.ApplyMessage(vmenv, msg, gp)
+ if err := vmError(); err != nil {
+ return nil, err
+ }
+ return &ExecutionResult{
+ Gas: gas,
+ ReturnValue: fmt.Sprintf("%x", ret),
+ StructLogs: FormatLogs(vmenv.StructLogs()),
+ }, nil
+}
+
+// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
+// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
+// transaction hashes.
+func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
+ fields := map[string]interface{}{
+ "number": rpc.NewHexNumber(b.Number()),
+ "hash": b.Hash(),
+ "parentHash": b.ParentHash(),
+ "nonce": b.Header().Nonce,
+ "sha3Uncles": b.UncleHash(),
+ "logsBloom": b.Bloom(),
+ "stateRoot": b.Root(),
+ "miner": b.Coinbase(),
+ "difficulty": rpc.NewHexNumber(b.Difficulty()),
+ "totalDifficulty": rpc.NewHexNumber(s.b.GetTd(b.Hash())),
+ "extraData": fmt.Sprintf("0x%x", b.Extra()),
+ "size": rpc.NewHexNumber(b.Size().Int64()),
+ "gasLimit": rpc.NewHexNumber(b.GasLimit()),
+ "gasUsed": rpc.NewHexNumber(b.GasUsed()),
+ "timestamp": rpc.NewHexNumber(b.Time()),
+ "transactionsRoot": b.TxHash(),
+ "receiptRoot": b.ReceiptHash(),
+ }
+
+ if inclTx {
+ formatTx := func(tx *types.Transaction) (interface{}, error) {
+ return tx.Hash(), nil
+ }
+
+ if fullTx {
+ formatTx = func(tx *types.Transaction) (interface{}, error) {
+ return newRPCTransaction(b, tx.Hash())
+ }
+ }
+
+ txs := b.Transactions()
+ transactions := make([]interface{}, len(txs))
+ var err error
+ for i, tx := range b.Transactions() {
+ if transactions[i], err = formatTx(tx); err != nil {
+ return nil, err
+ }
+ }
+ fields["transactions"] = transactions
+ }
+
+ uncles := b.Uncles()
+ uncleHashes := make([]common.Hash, len(uncles))
+ for i, uncle := range uncles {
+ uncleHashes[i] = uncle.Hash()
+ }
+ fields["uncles"] = uncleHashes
+
+ return fields, nil
+}
+
+// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
+type RPCTransaction struct {
+ BlockHash common.Hash `json:"blockHash"`
+ BlockNumber *rpc.HexNumber `json:"blockNumber"`
+ From common.Address `json:"from"`
+ Gas *rpc.HexNumber `json:"gas"`
+ GasPrice *rpc.HexNumber `json:"gasPrice"`
+ Hash common.Hash `json:"hash"`
+ Input string `json:"input"`
+ Nonce *rpc.HexNumber `json:"nonce"`
+ To *common.Address `json:"to"`
+ TransactionIndex *rpc.HexNumber `json:"transactionIndex"`
+ Value *rpc.HexNumber `json:"value"`
+}
+
+// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
+func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction {
+ from, _ := tx.FromFrontier()
+
+ return &RPCTransaction{
+ From: from,
+ Gas: rpc.NewHexNumber(tx.Gas()),
+ GasPrice: rpc.NewHexNumber(tx.GasPrice()),
+ Hash: tx.Hash(),
+ Input: fmt.Sprintf("0x%x", tx.Data()),
+ Nonce: rpc.NewHexNumber(tx.Nonce()),
+ To: tx.To(),
+ Value: rpc.NewHexNumber(tx.Value()),
+ }
+}
+
+// newRPCTransaction returns a transaction that will serialize to the RPC representation.
+func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransaction, error) {
+ if txIndex >= 0 && txIndex < len(b.Transactions()) {
+ tx := b.Transactions()[txIndex]
+ from, err := tx.FromFrontier()
+ if err != nil {
+ return nil, err
+ }
+
+ return &RPCTransaction{
+ BlockHash: b.Hash(),
+ BlockNumber: rpc.NewHexNumber(b.Number()),
+ From: from,
+ Gas: rpc.NewHexNumber(tx.Gas()),
+ GasPrice: rpc.NewHexNumber(tx.GasPrice()),
+ Hash: tx.Hash(),
+ Input: fmt.Sprintf("0x%x", tx.Data()),
+ Nonce: rpc.NewHexNumber(tx.Nonce()),
+ To: tx.To(),
+ TransactionIndex: rpc.NewHexNumber(txIndex),
+ Value: rpc.NewHexNumber(tx.Value()),
+ }, nil
+ }
+
+ return nil, nil
+}
+
+// newRPCTransaction returns a transaction that will serialize to the RPC representation.
+func newRPCTransaction(b *types.Block, txHash common.Hash) (*RPCTransaction, error) {
+ for idx, tx := range b.Transactions() {
+ if tx.Hash() == txHash {
+ return newRPCTransactionFromBlockIndex(b, idx)
+ }
+ }
+
+ return nil, nil
+}
+
+// PublicTransactionPoolAPI exposes methods for the RPC interface
+type PublicTransactionPoolAPI struct {
+ b Backend
+ muPendingTxSubs sync.Mutex
+ pendingTxSubs map[string]rpc.Subscription
+}
+
+// NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool.
+func NewPublicTransactionPoolAPI(b Backend) *PublicTransactionPoolAPI {
+ api := &PublicTransactionPoolAPI{
+ b: b,
+ pendingTxSubs: make(map[string]rpc.Subscription),
+ }
+
+ go api.subscriptionLoop()
+
+ return api
+}
+
+// subscriptionLoop listens for events on the global event mux and creates notifications for subscriptions.
+func (s *PublicTransactionPoolAPI) subscriptionLoop() {
+ sub := s.b.EventMux().Subscribe(core.TxPreEvent{})
+ for event := range sub.Chan() {
+ tx := event.Data.(core.TxPreEvent)
+ if from, err := tx.Tx.FromFrontier(); err == nil {
+ if s.b.AccountManager().HasAddress(from) {
+ s.muPendingTxSubs.Lock()
+ for id, sub := range s.pendingTxSubs {
+ if sub.Notify(tx.Tx.Hash()) == rpc.ErrNotificationNotFound {
+ delete(s.pendingTxSubs, id)
+ }
+ }
+ s.muPendingTxSubs.Unlock()
+ }
+ }
+ }
+}
+
+func getTransaction(chainDb ethdb.Database, b Backend, txHash common.Hash) (*types.Transaction, bool, error) {
+ txData, err := chainDb.Get(txHash.Bytes())
+ isPending := false
+ tx := new(types.Transaction)
+
+ if err == nil && len(txData) > 0 {
+ if err := rlp.DecodeBytes(txData, tx); err != nil {
+ return nil, isPending, err
+ }
+ } else {
+ // pending transaction?
+ tx = b.GetPoolTransaction(txHash)
+ isPending = true
+ }
+
+ return tx, isPending, nil
+}
+
+// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
+func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *rpc.HexNumber {
+ if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
+ return rpc.NewHexNumber(len(block.Transactions()))
+ }
+ return nil
+}
+
+// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
+func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *rpc.HexNumber {
+ if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
+ return rpc.NewHexNumber(len(block.Transactions()))
+ }
+ return nil
+}
+
+// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
+func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index rpc.HexNumber) (*RPCTransaction, error) {
+ if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
+ return newRPCTransactionFromBlockIndex(block, index.Int())
+ }
+ return nil, nil
+}
+
+// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
+func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index rpc.HexNumber) (*RPCTransaction, error) {
+ if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
+ return newRPCTransactionFromBlockIndex(block, index.Int())
+ }
+ return nil, nil
+}
+
+// GetTransactionCount returns the number of transactions the given address has sent for the given block number
+func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*rpc.HexNumber, error) {
+ state, _, err := s.b.StateAndHeaderByNumber(blockNr)
+ if state == nil || err != nil {
+ return nil, err
+ }
+ nonce, err := state.GetNonce(ctx, address)
+ if err != nil {
+ return nil, err
+ }
+ return rpc.NewHexNumber(nonce), nil
+}
+
+// getTransactionBlockData fetches the meta data for the given transaction from the chain database. This is useful to
+// retrieve block information for a hash. It returns the block hash, block index and transaction index.
+func getTransactionBlockData(chainDb ethdb.Database, txHash common.Hash) (common.Hash, uint64, uint64, error) {
+ var txBlock struct {
+ BlockHash common.Hash
+ BlockIndex uint64
+ Index uint64
+ }
+
+ blockData, err := chainDb.Get(append(txHash.Bytes(), 0x0001))
+ if err != nil {
+ return common.Hash{}, uint64(0), uint64(0), err
+ }
+
+ reader := bytes.NewReader(blockData)
+ if err = rlp.Decode(reader, &txBlock); err != nil {
+ return common.Hash{}, uint64(0), uint64(0), err
+ }
+
+ return txBlock.BlockHash, txBlock.BlockIndex, txBlock.Index, nil
+}
+
+// GetTransactionByHash returns the transaction for the given hash
+func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, txHash common.Hash) (*RPCTransaction, error) {
+ var tx *types.Transaction
+ var isPending bool
+ var err error
+
+ if tx, isPending, err = getTransaction(s.b.ChainDb(), s.b, txHash); err != nil {
+ glog.V(logger.Debug).Infof("%v\n", err)
+ return nil, nil
+ } else if tx == nil {
+ return nil, nil
+ }
+
+ if isPending {
+ return newRPCPendingTransaction(tx), nil
+ }
+
+ blockHash, _, _, err := getTransactionBlockData(s.b.ChainDb(), txHash)
+ if err != nil {
+ glog.V(logger.Debug).Infof("%v\n", err)
+ return nil, nil
+ }
+
+ if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
+ return newRPCTransaction(block, txHash)
+ }
+
+ return nil, nil
+}
+
+// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
+func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (map[string]interface{}, error) {
+ receipt := core.GetReceipt(s.b.ChainDb(), txHash)
+ if receipt == nil {
+ glog.V(logger.Debug).Infof("receipt not found for transaction %s", txHash.Hex())
+ return nil, nil
+ }
+
+ tx, _, err := getTransaction(s.b.ChainDb(), s.b, txHash)
+ if err != nil {
+ glog.V(logger.Debug).Infof("%v\n", err)
+ return nil, nil
+ }
+
+ txBlock, blockIndex, index, err := getTransactionBlockData(s.b.ChainDb(), txHash)
+ if err != nil {
+ glog.V(logger.Debug).Infof("%v\n", err)
+ return nil, nil
+ }
+
+ from, err := tx.FromFrontier()
+ if err != nil {
+ glog.V(logger.Debug).Infof("%v\n", err)
+ return nil, nil
+ }
+
+ fields := map[string]interface{}{
+ "root": common.Bytes2Hex(receipt.PostState),
+ "blockHash": txBlock,
+ "blockNumber": rpc.NewHexNumber(blockIndex),
+ "transactionHash": txHash,
+ "transactionIndex": rpc.NewHexNumber(index),
+ "from": from,
+ "to": tx.To(),
+ "gasUsed": rpc.NewHexNumber(receipt.GasUsed),
+ "cumulativeGasUsed": rpc.NewHexNumber(receipt.CumulativeGasUsed),
+ "contractAddress": nil,
+ "logs": receipt.Logs,
+ }
+
+ if receipt.Logs == nil {
+ fields["logs"] = []vm.Logs{}
+ }
+
+ // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
+ if bytes.Compare(receipt.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 {
+ fields["contractAddress"] = receipt.ContractAddress
+ }
+
+ return fields, nil
+}
+
+// sign is a helper function that signs a transaction with the private key of the given address.
+func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
+ signature, err := s.b.AccountManager().Sign(addr, tx.SigHash().Bytes())
+ if err != nil {
+ return nil, err
+ }
+ return tx.WithSignature(signature)
+}
+
+// SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool.
+type SendTxArgs struct {
+ From common.Address `json:"from"`
+ To *common.Address `json:"to"`
+ Gas *rpc.HexNumber `json:"gas"`
+ GasPrice *rpc.HexNumber `json:"gasPrice"`
+ Value *rpc.HexNumber `json:"value"`
+ Data string `json:"data"`
+ Nonce *rpc.HexNumber `json:"nonce"`
+}
+
+// prepareSendTxArgs is a helper function that fills in default values for unspecified tx fields.
+func prepareSendTxArgs(ctx context.Context, args SendTxArgs, b Backend) (SendTxArgs, error) {
+ if args.Gas == nil {
+ args.Gas = rpc.NewHexNumber(defaultGas)
+ }
+ if args.GasPrice == nil {
+ price, err := b.SuggestPrice(ctx)
+ if err != nil {
+ return args, err
+ }
+ args.GasPrice = rpc.NewHexNumber(price)
+ }
+ if args.Value == nil {
+ args.Value = rpc.NewHexNumber(0)
+ }
+ return args, nil
+}
+
+// submitTransaction is a helper function that submits tx to txPool and creates a log entry.
+func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, signature []byte) (common.Hash, error) {
+ signedTx, err := tx.WithSignature(signature)
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ if err := b.SendTx(ctx, signedTx); err != nil {
+ return common.Hash{}, err
+ }
+
+ if signedTx.To() == nil {
+ from, _ := signedTx.From()
+ addr := crypto.CreateAddress(from, signedTx.Nonce())
+ glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
+ } else {
+ glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
+ }
+
+ return signedTx.Hash(), nil
+}
+
+// SendTransaction creates a transaction for the given argument, sign it and submit it to the
+// transaction pool.
+func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
+ var err error
+ args, err = prepareSendTxArgs(ctx, args, s.b)
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ if args.Nonce == nil {
+ nonce, err := s.b.GetPoolNonce(ctx, args.From)
+ if err != nil {
+ return common.Hash{}, err
+ }
+ args.Nonce = rpc.NewHexNumber(nonce)
+ }
+
+ var tx *types.Transaction
+ if args.To == nil {
+ tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
+ } else {
+ tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
+ }
+
+ signature, err := s.b.AccountManager().Sign(args.From, tx.SigHash().Bytes())
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ return submitTransaction(ctx, s.b, tx, signature)
+}
+
+// SendRawTransaction will add the signed transaction to the transaction pool.
+// The sender is responsible for signing the transaction and using the correct nonce.
+func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx string) (string, error) {
+ tx := new(types.Transaction)
+ if err := rlp.DecodeBytes(common.FromHex(encodedTx), tx); err != nil {
+ return "", err
+ }
+
+ if err := s.b.SendTx(ctx, tx); err != nil {
+ return "", err
+ }
+
+ if tx.To() == nil {
+ from, err := tx.FromFrontier()
+ if err != nil {
+ return "", err
+ }
+ addr := crypto.CreateAddress(from, tx.Nonce())
+ glog.V(logger.Info).Infof("Tx(%x) created: %x\n", tx.Hash(), addr)
+ } else {
+ glog.V(logger.Info).Infof("Tx(%x) to: %x\n", tx.Hash(), tx.To())
+ }
+
+ return tx.Hash().Hex(), nil
+}
+
+// Sign signs the given hash using the key that matches the address. The key must be
+// unlocked in order to sign the hash.
+func (s *PublicTransactionPoolAPI) Sign(addr common.Address, hash common.Hash) (string, error) {
+ signature, error := s.b.AccountManager().Sign(addr, hash[:])
+ return common.ToHex(signature), error
+}
+
+// SignTransactionArgs represents the arguments to sign a transaction.
+type SignTransactionArgs struct {
+ From common.Address
+ To *common.Address
+ Nonce *rpc.HexNumber
+ Value *rpc.HexNumber
+ Gas *rpc.HexNumber
+ GasPrice *rpc.HexNumber
+ Data string
+
+ BlockNumber int64
+}
+
+// Tx is a helper object for argument and return values
+type Tx struct {
+ tx *types.Transaction
+
+ To *common.Address `json:"to"`
+ From common.Address `json:"from"`
+ Nonce *rpc.HexNumber `json:"nonce"`
+ Value *rpc.HexNumber `json:"value"`
+ Data string `json:"data"`
+ GasLimit *rpc.HexNumber `json:"gas"`
+ GasPrice *rpc.HexNumber `json:"gasPrice"`
+ Hash common.Hash `json:"hash"`
+}
+
+// UnmarshalJSON parses JSON data into tx.
+func (tx *Tx) UnmarshalJSON(b []byte) (err error) {
+ req := struct {
+ To *common.Address `json:"to"`
+ From common.Address `json:"from"`
+ Nonce *rpc.HexNumber `json:"nonce"`
+ Value *rpc.HexNumber `json:"value"`
+ Data string `json:"data"`
+ GasLimit *rpc.HexNumber `json:"gas"`
+ GasPrice *rpc.HexNumber `json:"gasPrice"`
+ Hash common.Hash `json:"hash"`
+ }{}
+
+ if err := json.Unmarshal(b, &req); err != nil {
+ return err
+ }
+
+ tx.To = req.To
+ tx.From = req.From
+ tx.Nonce = req.Nonce
+ tx.Value = req.Value
+ tx.Data = req.Data
+ tx.GasLimit = req.GasLimit
+ tx.GasPrice = req.GasPrice
+ tx.Hash = req.Hash
+
+ data := common.Hex2Bytes(tx.Data)
+
+ if tx.Nonce == nil {
+ return fmt.Errorf("need nonce")
+ }
+ if tx.Value == nil {
+ tx.Value = rpc.NewHexNumber(0)
+ }
+ if tx.GasLimit == nil {
+ tx.GasLimit = rpc.NewHexNumber(0)
+ }
+ if tx.GasPrice == nil {
+ tx.GasPrice = rpc.NewHexNumber(int64(50000000000))
+ }
+
+ if req.To == nil {
+ tx.tx = types.NewContractCreation(tx.Nonce.Uint64(), tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
+ } else {
+ tx.tx = types.NewTransaction(tx.Nonce.Uint64(), *tx.To, tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
+ }
+
+ return nil
+}
+
+// SignTransactionResult represents a RLP encoded signed transaction.
+type SignTransactionResult struct {
+ Raw string `json:"raw"`
+ Tx *Tx `json:"tx"`
+}
+
+func newTx(t *types.Transaction) *Tx {
+ from, _ := t.FromFrontier()
+ return &Tx{
+ tx: t,
+ To: t.To(),
+ From: from,
+ Value: rpc.NewHexNumber(t.Value()),
+ Nonce: rpc.NewHexNumber(t.Nonce()),
+ Data: "0x" + common.Bytes2Hex(t.Data()),
+ GasLimit: rpc.NewHexNumber(t.Gas()),
+ GasPrice: rpc.NewHexNumber(t.GasPrice()),
+ Hash: t.Hash(),
+ }
+}
+
+// SignTransaction will sign the given transaction with the from account.
+// The node needs to have the private key of the account corresponding with
+// the given from address and it needs to be unlocked.
+func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SignTransactionArgs) (*SignTransactionResult, error) {
+ if args.Gas == nil {
+ args.Gas = rpc.NewHexNumber(defaultGas)
+ }
+ if args.GasPrice == nil {
+ price, err := s.b.SuggestPrice(ctx)
+ if err != nil {
+ return nil, err
+ }
+ args.GasPrice = rpc.NewHexNumber(price)
+ }
+ if args.Value == nil {
+ args.Value = rpc.NewHexNumber(0)
+ }
+
+ if args.Nonce == nil {
+ nonce, err := s.b.GetPoolNonce(ctx, args.From)
+ if err != nil {
+ return nil, err
+ }
+ args.Nonce = rpc.NewHexNumber(nonce)
+ }
+
+ var tx *types.Transaction
+ if args.To == nil {
+ tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
+ } else {
+ tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
+ }
+
+ signedTx, err := s.sign(args.From, tx)
+ if err != nil {
+ return nil, err
+ }
+
+ data, err := rlp.EncodeToBytes(signedTx)
+ if err != nil {
+ return nil, err
+ }
+
+ return &SignTransactionResult{"0x" + common.Bytes2Hex(data), newTx(signedTx)}, nil
+}
+
+// PendingTransactions returns the transactions that are in the transaction pool and have a from address that is one of
+// the accounts this node manages.
+func (s *PublicTransactionPoolAPI) PendingTransactions() []*RPCTransaction {
+ pending := s.b.GetPoolTransactions()
+ transactions := make([]*RPCTransaction, 0, len(pending))
+ for _, tx := range pending {
+ from, _ := tx.FromFrontier()
+ if s.b.AccountManager().HasAddress(from) {
+ transactions = append(transactions, newRPCPendingTransaction(tx))
+ }
+ }
+ return transactions
+}
+
+// NewPendingTransactions creates a subscription that is triggered each time a transaction enters the transaction pool
+// and is send from one of the transactions this nodes manages.
+func (s *PublicTransactionPoolAPI) NewPendingTransactions(ctx context.Context) (rpc.Subscription, error) {
+ notifier, supported := rpc.NotifierFromContext(ctx)
+ if !supported {
+ return nil, rpc.ErrNotificationsUnsupported
+ }
+
+ subscription, err := notifier.NewSubscription(func(id string) {
+ s.muPendingTxSubs.Lock()
+ delete(s.pendingTxSubs, id)
+ s.muPendingTxSubs.Unlock()
+ })
+
+ if err != nil {
+ return nil, err
+ }
+
+ s.muPendingTxSubs.Lock()
+ s.pendingTxSubs[subscription.ID()] = subscription
+ s.muPendingTxSubs.Unlock()
+
+ return subscription, nil
+}
+
+// Resend accepts an existing transaction and a new gas price and limit. It will remove the given transaction from the
+// pool and reinsert it with the new gas price and limit.
+func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx *Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) {
+
+ pending := s.b.GetPoolTransactions()
+ for _, p := range pending {
+ if pFrom, err := p.FromFrontier(); err == nil && pFrom == tx.From && p.SigHash() == tx.tx.SigHash() {
+ if gasPrice == nil {
+ gasPrice = rpc.NewHexNumber(tx.tx.GasPrice())
+ }
+ if gasLimit == nil {
+ gasLimit = rpc.NewHexNumber(tx.tx.Gas())
+ }
+
+ var newTx *types.Transaction
+ if tx.tx.To() == nil {
+ newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data())
+ } else {
+ newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data())
+ }
+
+ signedTx, err := s.sign(tx.From, newTx)
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ s.b.RemoveTx(tx.Hash)
+ if err = s.b.SendTx(ctx, signedTx); err != nil {
+ return common.Hash{}, err
+ }
+
+ return signedTx.Hash(), nil
+ }
+ }
+
+ return common.Hash{}, fmt.Errorf("Transaction %#x not found", tx.Hash)
+}
+
+// PrivateAdminAPI is the collection of Etheruem APIs exposed over the private
+// admin endpoint.
+type PrivateAdminAPI struct {
+ b Backend
+ solcPath *string
+ solc **compiler.Solidity
+}
+
+// NewPrivateAdminAPI creates a new API definition for the private admin methods
+// of the Ethereum service.
+func NewPrivateAdminAPI(b Backend, solcPath *string, solc **compiler.Solidity) *PrivateAdminAPI {
+ return &PrivateAdminAPI{b, solcPath, solc}
+}
+
+// SetSolc sets the Solidity compiler path to be used by the node.
+func (api *PrivateAdminAPI) SetSolc(path string) (string, error) {
+ var err error
+ *api.solcPath = path
+ *api.solc, err = compiler.New(path)
+ if err != nil {
+ return "", err
+ }
+ return (*api.solc).Info(), nil
+}
+
+// PublicDebugAPI is the collection of Etheruem APIs exposed over the public
+// debugging endpoint.
+type PublicDebugAPI struct {
+ b Backend
+}
+
+// NewPublicDebugAPI creates a new API definition for the public debug methods
+// of the Ethereum service.
+func NewPublicDebugAPI(b Backend) *PublicDebugAPI {
+ return &PublicDebugAPI{b: b}
+}
+
+// GetBlockRlp retrieves the RLP encoded for of a single block.
+func (api *PublicDebugAPI) GetBlockRlp(ctx context.Context, number uint64) (string, error) {
+ block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number))
+ if block == nil {
+ return "", fmt.Errorf("block #%d not found", number)
+ }
+ encoded, err := rlp.EncodeToBytes(block)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%x", encoded), nil
+}
+
+// PrintBlock retrieves a block and returns its pretty printed form.
+func (api *PublicDebugAPI) PrintBlock(ctx context.Context, number uint64) (string, error) {
+ block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number))
+ if block == nil {
+ return "", fmt.Errorf("block #%d not found", number)
+ }
+ return fmt.Sprintf("%s", block), nil
+}
+
+// SeedHash retrieves the seed hash of a block.
+func (api *PublicDebugAPI) SeedHash(ctx context.Context, number uint64) (string, error) {
+ block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number))
+ if block == nil {
+ return "", fmt.Errorf("block #%d not found", number)
+ }
+ hash, err := ethash.GetSeedHash(number)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("0x%x", hash), nil
+}
+
+// PrivateDebugAPI is the collection of Etheruem APIs exposed over the private
+// debugging endpoint.
+type PrivateDebugAPI struct {
+ b Backend
+}
+
+// NewPrivateDebugAPI creates a new API definition for the private debug methods
+// of the Ethereum service.
+func NewPrivateDebugAPI(b Backend) *PrivateDebugAPI {
+ return &PrivateDebugAPI{b: b}
+}
+
+// ChaindbProperty returns leveldb properties of the chain database.
+func (api *PrivateDebugAPI) ChaindbProperty(property string) (string, error) {
+ ldb, ok := api.b.ChainDb().(interface {
+ LDB() *leveldb.DB
+ })
+ if !ok {
+ return "", fmt.Errorf("chaindbProperty does not work for memory databases")
+ }
+ if property == "" {
+ property = "leveldb.stats"
+ } else if !strings.HasPrefix(property, "leveldb.") {
+ property = "leveldb." + property
+ }
+ return ldb.LDB().GetProperty(property)
+}
+
+// SetHead rewinds the head of the blockchain to a previous block.
+func (api *PrivateDebugAPI) SetHead(number uint64) {
+ api.b.SetHead(number)
+}
+
+// PublicNetAPI offers network related RPC methods
+type PublicNetAPI struct {
+ net *p2p.Server
+ networkVersion int
+}
+
+// NewPublicNetAPI creates a new net API instance.
+func NewPublicNetAPI(net *p2p.Server, networkVersion int) *PublicNetAPI {
+ return &PublicNetAPI{net, networkVersion}
+}
+
+// Listening returns an indication if the node is listening for network connections.
+func (s *PublicNetAPI) Listening() bool {
+ return true // always listening
+}
+
+// PeerCount returns the number of connected peers
+func (s *PublicNetAPI) PeerCount() *rpc.HexNumber {
+ return rpc.NewHexNumber(s.net.PeerCount())
+}
+
+// Version returns the current ethereum protocol version.
+func (s *PublicNetAPI) Version() string {
+ return fmt.Sprintf("%d", s.networkVersion)
+}
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
new file mode 100644
index 000000000..d112a6aef
--- /dev/null
+++ b/internal/ethapi/backend.go
@@ -0,0 +1,119 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// Package ethapi implements the general Ethereum API functions.
+package ethapi
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/compiler"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/rpc"
+ "golang.org/x/net/context"
+)
+
+// Backend interface provides the common API services (that are provided by
+// both full and light clients) with access to necessary functions.
+type Backend interface {
+ // general Ethereum API
+ Downloader() *downloader.Downloader
+ ProtocolVersion() int
+ SuggestPrice(ctx context.Context) (*big.Int, error)
+ ChainDb() ethdb.Database
+ EventMux() *event.TypeMux
+ AccountManager() *accounts.Manager
+ // BlockChain API
+ SetHead(number uint64)
+ HeaderByNumber(blockNr rpc.BlockNumber) *types.Header
+ BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error)
+ StateAndHeaderByNumber(blockNr rpc.BlockNumber) (State, *types.Header, error)
+ GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error)
+ GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
+ GetTd(blockHash common.Hash) *big.Int
+ GetVMEnv(ctx context.Context, msg core.Message, state State, header *types.Header) (vm.Environment, func() error, error)
+ // TxPool API
+ SendTx(ctx context.Context, signedTx *types.Transaction) error
+ RemoveTx(txHash common.Hash)
+ GetPoolTransactions() types.Transactions
+ GetPoolTransaction(txHash common.Hash) *types.Transaction
+ GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
+ Stats() (pending int, queued int)
+ TxPoolContent() (map[common.Address]map[uint64][]*types.Transaction, map[common.Address]map[uint64][]*types.Transaction)
+}
+
+type State interface {
+ GetBalance(ctx context.Context, addr common.Address) (*big.Int, error)
+ GetCode(ctx context.Context, addr common.Address) ([]byte, error)
+ GetState(ctx context.Context, a common.Address, b common.Hash) (common.Hash, error)
+ GetNonce(ctx context.Context, addr common.Address) (uint64, error)
+}
+
+func GetAPIs(apiBackend Backend, solcPath *string, solc **compiler.Solidity) []rpc.API {
+ return []rpc.API{
+ {
+ Namespace: "eth",
+ Version: "1.0",
+ Service: NewPublicEthereumAPI(apiBackend, solcPath, solc),
+ Public: true,
+ }, {
+ Namespace: "eth",
+ Version: "1.0",
+ Service: NewPublicBlockChainAPI(apiBackend),
+ Public: true,
+ }, {
+ Namespace: "eth",
+ Version: "1.0",
+ Service: NewPublicTransactionPoolAPI(apiBackend),
+ Public: true,
+ }, {
+ Namespace: "txpool",
+ Version: "1.0",
+ Service: NewPublicTxPoolAPI(apiBackend),
+ Public: true,
+ }, {
+ Namespace: "admin",
+ Version: "1.0",
+ Service: NewPrivateAdminAPI(apiBackend, solcPath, solc),
+ }, {
+ Namespace: "debug",
+ Version: "1.0",
+ Service: NewPublicDebugAPI(apiBackend),
+ Public: true,
+ }, {
+ Namespace: "debug",
+ Version: "1.0",
+ Service: NewPrivateDebugAPI(apiBackend),
+ }, {
+ Namespace: "eth",
+ Version: "1.0",
+ Service: NewPublicAccountAPI(apiBackend.AccountManager()),
+ Public: true,
+ }, {
+ Namespace: "personal",
+ Version: "1.0",
+ Service: NewPrivateAccountAPI(apiBackend),
+ Public: false,
+ },
+ }
+}
diff --git a/internal/jsre/pretty.go b/internal/jsre/pretty.go
index 30d8660ff..f32e16243 100644
--- a/internal/jsre/pretty.go
+++ b/internal/jsre/pretty.go
@@ -116,7 +116,7 @@ func (ctx ppctx) printValue(v otto.Value, level int, inArray bool) {
func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) {
switch obj.Class() {
- case "Array":
+ case "Array", "GoArray":
lv, _ := obj.Get("length")
len, _ := lv.ToInteger()
if len == 0 {
diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go
index d45ce6581..e76e15177 100644
--- a/internal/web3ext/web3ext.go
+++ b/internal/web3ext/web3ext.go
@@ -423,8 +423,8 @@ web3._extend({
params: 2
}),
new web3._extend.Method({
- name: 'signAndSendTransaction',
- call: 'personal_signAndSendTransaction',
+ name: 'sendTransaction',
+ call: 'personal_sendTransaction',
params: 2,
inputFormatter: [web3._extend.formatters.inputTransactionFormatter, null]
})
diff --git a/miner/worker.go b/miner/worker.go
index 09cf6b6aa..dfda6d898 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -17,6 +17,7 @@
package miner
import (
+ "bytes"
"fmt"
"math/big"
"sync"
@@ -33,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"gopkg.in/fatih/set.v0"
)
@@ -468,7 +470,19 @@ func (self *worker) commitNewWork() {
Extra: self.extra,
Time: big.NewInt(tstamp),
}
-
+ // If we are care about TheDAO hard-fork check whether to override the extra-data or not
+ if daoBlock := self.config.DAOForkBlock; daoBlock != nil {
+ // Check whether the block is among the fork extra-override range
+ limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
+ if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 {
+ // Depending whether we support or oppose the fork, override differently
+ if self.config.DAOForkSupport {
+ header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
+ } else if bytes.Compare(header.Extra, params.DAOForkBlockExtra) == 0 {
+ header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data
+ }
+ }
+ }
previous := self.current
// Could potentially happen if starting to mine in an odd state.
err := self.makeCurrent(parent, header)
@@ -476,7 +490,11 @@ func (self *worker) commitNewWork() {
glog.V(logger.Info).Infoln("Could not create new env for mining, retrying on next block.")
return
}
+ // Create the current work task and check any fork transitions needed
work := self.current
+ if self.config.DAOForkSupport && self.config.DAOForkBlock != nil && self.config.DAOForkBlock.Cmp(header.Number) == 0 {
+ core.ApplyDAOHardFork(work.state)
+ }
/* //approach 1
transactions := self.eth.TxPool().GetTransactions()
diff --git a/node/node.go b/node/node.go
index 1f517a027..ac8a7e8f0 100644
--- a/node/node.go
+++ b/node/node.go
@@ -505,16 +505,14 @@ func (n *Node) Restart() error {
}
// Attach creates an RPC client attached to an in-process API handler.
-func (n *Node) Attach() (rpc.Client, error) {
+func (n *Node) Attach() (*rpc.Client, error) {
n.lock.RLock()
defer n.lock.RUnlock()
- // Short circuit if the node's not running
if n.server == nil {
return nil, ErrNodeStopped
}
- // Otherwise attach to the API and return
- return rpc.NewInProcRPCClient(n.inprocHandler), nil
+ return rpc.DialInProc(n.inprocHandler), nil
}
// Server retrieves the currently running P2P network layer. This method is meant
diff --git a/node/node_test.go b/node/node_test.go
index 372fc6b10..d9b26453b 100644
--- a/node/node_test.go
+++ b/node/node_test.go
@@ -507,21 +507,27 @@ func TestAPIGather(t *testing.T) {
}
// Register a batch of services with some configured APIs
calls := make(chan string, 1)
-
+ makeAPI := func(result string) *OneMethodApi {
+ return &OneMethodApi{fun: func() { calls <- result }}
+ }
services := map[string]struct {
APIs []rpc.API
Maker InstrumentingWrapper
}{
- "Zero APIs": {[]rpc.API{}, InstrumentedServiceMakerA},
- "Single API": {[]rpc.API{
- {"single", "1", &OneMethodApi{fun: func() { calls <- "single.v1" }}, true},
- }, InstrumentedServiceMakerB},
- "Many APIs": {[]rpc.API{
- {"multi", "1", &OneMethodApi{fun: func() { calls <- "multi.v1" }}, true},
- {"multi.v2", "2", &OneMethodApi{fun: func() { calls <- "multi.v2" }}, true},
- {"multi.v2.nested", "2", &OneMethodApi{fun: func() { calls <- "multi.v2.nested" }}, true},
- }, InstrumentedServiceMakerC},
+ "Zero APIs": {
+ []rpc.API{}, InstrumentedServiceMakerA},
+ "Single API": {
+ []rpc.API{
+ {Namespace: "single", Version: "1", Service: makeAPI("single.v1"), Public: true},
+ }, InstrumentedServiceMakerB},
+ "Many APIs": {
+ []rpc.API{
+ {Namespace: "multi", Version: "1", Service: makeAPI("multi.v1"), Public: true},
+ {Namespace: "multi.v2", Version: "2", Service: makeAPI("multi.v2"), Public: true},
+ {Namespace: "multi.v2.nested", Version: "2", Service: makeAPI("multi.v2.nested"), Public: true},
+ }, InstrumentedServiceMakerC},
}
+
for id, config := range services {
config := config
constructor := func(*ServiceContext) (Service, error) {
@@ -554,12 +560,8 @@ func TestAPIGather(t *testing.T) {
{"multi.v2.nested_theOneMethod", "multi.v2.nested"},
}
for i, test := range tests {
- if err := client.Send(rpc.JSONRequest{Id: []byte("1"), Version: "2.0", Method: test.Method}); err != nil {
- t.Fatalf("test %d: failed to send API request: %v", i, err)
- }
- reply := new(rpc.JSONSuccessResponse)
- if err := client.Recv(reply); err != nil {
- t.Fatalf("test %d: failed to read API reply: %v", i, err)
+ if err := client.Call(nil, test.Method); err != nil {
+ t.Errorf("test %d: API request failed: %v", i, err)
}
select {
case result := <-calls:
diff --git a/p2p/discover/database.go b/p2p/discover/database.go
index 6d448515d..d6ea507bb 100644
--- a/p2p/discover/database.go
+++ b/p2p/discover/database.go
@@ -243,7 +243,7 @@ func (db *nodeDB) expirer() {
}
// expireNodes iterates over the database and deletes all nodes that have not
-// been seen (i.e. received a pong from) for some alloted time.
+// been seen (i.e. received a pong from) for some allotted time.
func (db *nodeDB) expireNodes() error {
threshold := time.Now().Add(-nodeDBNodeExpiration)
diff --git a/params/dao.go b/params/dao.go
new file mode 100644
index 000000000..3e2a68cc9
--- /dev/null
+++ b/params/dao.go
@@ -0,0 +1,418 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package params
+
+import (
+ "encoding/json"
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// TestNetDAOForkBlock is the block number where the DAO hard-fork commences on
+// the Ethereum test network. It's enforced nil since it was decided not to do a
+// testnet transition.
+var TestNetDAOForkBlock *big.Int
+
+// MainNetDAOForkBlock is the block number where the DAO hard-fork commences on
+// the Ethereum main network.
+var MainNetDAOForkBlock = big.NewInt(1920000)
+
+// DAOForkBlockExtra is the block header extra-data field to set for the DAO fork
+// point and a number of consecutive blocks to allow fast/light syncers to correctly
+// pick the side they want ("dao-hard-fork").
+var DAOForkBlockExtra = common.FromHex("0x64616f2d686172642d666f726b")
+
+// DAOForkExtraRange is the number of consecutive blocks from the DAO fork point
+// to override the extra-data in to prevent no-fork attacks.
+var DAOForkExtraRange = big.NewInt(10)
+
+// DAORefundContract is the address of the refund contract to send DAO balances to.
+var DAORefundContract = common.HexToAddress("0xbf4ed7b27f1d666546e30d74d50d173d20bca754")
+
+// DAODrainList is the list of accounts whose full balances will be moved into a
+// refund contract at the beginning of the dao-fork block.
+var DAODrainList []common.Address
+
+func init() {
+ // Parse the list of DAO accounts to drain
+ var list []map[string]string
+ if err := json.Unmarshal([]byte(daoDrainListJSON), &list); err != nil {
+ panic(fmt.Errorf("Failed to parse DAO drain list: %v", err))
+ }
+ // Collect all the accounts that need draining
+ for _, dao := range list {
+ DAODrainList = append(DAODrainList, common.HexToAddress(dao["address"]))
+ DAODrainList = append(DAODrainList, common.HexToAddress(dao["extraBalanceAccount"]))
+ }
+}
+
+// daoDrainListJSON is the JSON encoded list of accounts whose full balances will
+// be moved into a refund contract at the beginning of the dao-fork block.
+const daoDrainListJSON = `
+[
+ {
+ "address":"0xd4fe7bc31cedb7bfb8a345f31e668033056b2728",
+ "balance":"186cc8bfaefb7be",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425"
+ },
+ {
+ "address":"0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f",
+ "balance":"b14e8feab1ff435",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xecd135fa4f61a655311e86238c92adcd779555d2"
+ },
+ {
+ "address":"0x1975bd06d486162d5dc297798dfc41edd5d160a7",
+ "balance":"359d26614cb5070c77",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6"
+ },
+ {
+ "address":"0x319f70bab6845585f412ec7724b744fec6095c85",
+ "balance":"6e075cd846d2cb1d42",
+ "extraBalance":"13d34fd41b545b81",
+ "extraBalanceAccount":"0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936"
+ },
+ {
+ "address":"0x5c8536898fbb74fc7445814902fd08422eac56d0",
+ "balance":"b1e5593558008fd78",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x6966ab0d485353095148a2155858910e0965b6f9"
+ },
+ {
+ "address":"0x779543a0491a837ca36ce8c635d6154e3c4911a6",
+ "balance":"392eaa20d1aad59a4c",
+ "extraBalance":"426938826a96c9",
+ "extraBalanceAccount":"0x2a5ed960395e2a49b1c758cef4aa15213cfd874c"
+ },
+ {
+ "address":"0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5",
+ "balance":"2875d22b29793d4ba7",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x9c50426be05db97f5d64fc54bf89eff947f0a321"
+ },
+ {
+ "address":"0x200450f06520bdd6c527622a273333384d870efb",
+ "balance":"43c341d9f96954c049",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xbe8539bfe837b67d1282b2b1d61c3f723966f049"
+ },
+ {
+ "address":"0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb",
+ "balance":"75251057154d70fa816",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xf1385fb24aad0cd7432824085e42aff90886fef5"
+ },
+ {
+ "address":"0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091",
+ "balance":"392409769296cf67f36",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd"
+ },
+ {
+ "address":"0x51e0ddd9998364a2eb38588679f0d2c42653e4a6",
+ "balance":"8ac72eccbf4e8083",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x627a0a960c079c21c34f7612d5d230e01b4ad4c7"
+ },
+ {
+ "address":"0xf0b1aa0eb660754448a7937c022e30aa692fe0c5",
+ "balance":"82289c3bb3e8c98799",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x24c4d950dfd4dd1902bbed3508144a54542bba94"
+ },
+ {
+ "address":"0x9f27daea7aca0aa0446220b98d028715e3bc803d",
+ "balance":"56bc29049ebed40fd",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90"
+ },
+ {
+ "address":"0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b",
+ "balance":"56bc7d3ff79110524",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x63ed5a272de2f6d968408b4acb9024f4cc208ebf"
+ },
+ {
+ "address":"0x6f6704e5a10332af6672e50b3d9754dc460dfa4d",
+ "balance":"23b651bd48cbc70cc",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6"
+ },
+ {
+ "address":"0x492ea3bb0f3315521c31f273e565b868fc090f17",
+ "balance":"13ea6d4fee651dd7c9",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00"
+ },
+ {
+ "address":"0x9ea779f907f0b315b364b0cfc39a0fde5b02a416",
+ "balance":"35ac471a3836ae7de5a",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xceaeb481747ca6c540a000c1f3641f8cef161fa7"
+ },
+ {
+ "address":"0xcc34673c6c40e791051898567a1222daf90be287",
+ "balance":"d529c0b76b7aa0",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x579a80d909f346fbfb1189493f521d7f48d52238"
+ },
+ {
+ "address":"0xe308bd1ac5fda103967359b2712dd89deffb7973",
+ "balance":"5cd9e7df3a8e5cdd3",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c"
+ },
+ {
+ "address":"0xac1ecab32727358dba8962a0f3b261731aad9723",
+ "balance":"2c8442fe35363313b93",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x4fd6ace747f06ece9c49699c7cabc62d02211f75"
+ },
+ {
+ "address":"0x440c59b325d2997a134c2c7c60a8c61611212bad",
+ "balance":"e77583a3958130e53",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x4486a3d68fac6967006d7a517b889fd3f98c102b"
+ },
+ {
+ "address":"0x9c15b54878ba618f494b38f0ae7443db6af648ba",
+ "balance":"1f0b6ade348ca998",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x27b137a85656544b1ccb5a0f2e561a5703c6a68f"
+ },
+ {
+ "address":"0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241",
+ "balance":"61725880736659",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x23b75c2f6791eef49c69684db4c6c1f93bf49a50"
+ },
+ {
+ "address":"0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b",
+ "balance":"42948d8dc7ddbc22d",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xb9637156d330c0d605a791f1c31ba5890582fe1c"
+ },
+ {
+ "address":"0x6131c42fa982e56929107413a9d526fd99405560",
+ "balance":"7306683851d1eafbfa",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x1591fc0f688c81fbeb17f5426a162a7024d430c2"
+ },
+ {
+ "address":"0x542a9515200d14b68e934e9830d91645a980dd7a",
+ "balance":"2a8457d0d8432e21d0c",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xc4bbd073882dd2add2424cf47d35213405b01324"
+ },
+ {
+ "address":"0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4",
+ "balance":"d8d7391feaeaa8cdb",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb"
+ },
+ {
+ "address":"0x3ba4d81db016dc2890c81f3acec2454bff5aada5",
+ "balance":"1",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab"
+ },
+ {
+ "address":"0xe4ae1efdfc53b73893af49113d8694a057b9c0d1",
+ "balance":"456397665fa74041",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5"
+ },
+ {
+ "address":"0x0737a6b837f97f46ebade41b9bc3e1c509c85c53",
+ "balance":"6324dcb7126ecbef",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x97f43a37f595ab5dd318fb46e7a155eae057317a"
+ },
+ {
+ "address":"0x52c5317c848ba20c7504cb2c8052abd1fde29d03",
+ "balance":"6c3419b0705c01cd0d",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x4863226780fe7c0356454236d3b1c8792785748d"
+ },
+ {
+ "address":"0x5d2b2e6fcbe3b11d26b525e085ff818dae332479",
+ "balance":"456397665fa74041",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c"
+ },
+ {
+ "address":"0x057b56736d32b86616a10f619859c6cd6f59092a",
+ "balance":"232c025bb44b46",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x9aa008f65de0b923a2a4f02012ad034a5e2e2192"
+ },
+ {
+ "address":"0x304a554a310c7e546dfe434669c62820b7d83490",
+ "balance":"3034f5ca7d45e17df199b",
+ "extraBalance":"f7d15162c44e97b6e",
+ "extraBalanceAccount":"0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79"
+ },
+ {
+ "address":"0x4deb0033bb26bc534b197e61d19e0733e5679784",
+ "balance":"4417e96ed796591e09",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a"
+ },
+ {
+ "address":"0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b",
+ "balance":"d3ff7771412bbcc9",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x4fa802324e929786dbda3b8820dc7834e9134a2a"
+ },
+ {
+ "address":"0x9da397b9e80755301a3b32173283a91c0ef6c87e",
+ "balance":"32ae324c233816b4c2",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6"
+ },
+ {
+ "address":"0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9",
+ "balance":"1e530695b705f037c6",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x5dc28b15dffed94048d73806ce4b7a4612a1d48f"
+ },
+ {
+ "address":"0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76",
+ "balance":"68013bad5b4b1133fc5",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x12e626b0eebfe86a56d633b9864e389b45dcb260"
+ },
+ {
+ "address":"0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7",
+ "balance":"456397665fa74041",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5"
+ },
+ {
+ "address":"0xd164b088bd9108b60d0ca3751da4bceb207b0782",
+ "balance":"3635ce47fabaaa336e",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x6231b6d0d5e77fe001c2a460bd9584fee60d409b"
+ },
+ {
+ "address":"0x1cba23d343a983e9b5cfd19496b9a9701ada385f",
+ "balance":"f3abd9906c170a",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xa82f360a8d3455c5c41366975bde739c37bfeb8a"
+ },
+ {
+ "address":"0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339",
+ "balance":"4c6679d9d9b95a4e08",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x005f5cee7a43331d5a3d3eec71305925a62f34b6"
+ },
+ {
+ "address":"0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d",
+ "balance":"40f622936475de31849",
+ "extraBalance":"671e1bbabded39754",
+ "extraBalanceAccount":"0xd131637d5275fd1a68a3200f4ad25c71a2a9522e"
+ },
+ {
+ "address":"0xbc07118b9ac290e4622f5e77a0853539789effbe",
+ "balance":"1316ccfa4a35db5e58f",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x47e7aa56d6bdf3f36be34619660de61275420af8"
+ },
+ {
+ "address":"0xacd87e28b0c9d1254e868b81cba4cc20d9a32225",
+ "balance":"b3ad6bb72000bab9f",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xadf80daec7ba8dcf15392f1ac611fff65d94f880"
+ },
+ {
+ "address":"0x5524c55fb03cf21f549444ccbecb664d0acad706",
+ "balance":"16f2da372a5c8a70967",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x40b803a9abce16f50f36a77ba41180eb90023925"
+ },
+ {
+ "address":"0xfe24cdd8648121a43a7c86d289be4dd2951ed49f",
+ "balance":"ea0b1bdc78f500a43",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x17802f43a0137c506ba92291391a8a8f207f487d"
+ },
+ {
+ "address":"0x253488078a4edf4d6f42f113d1e62836a942cf1a",
+ "balance":"3060e3aed135cc80",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915"
+ },
+ {
+ "address":"0xb136707642a4ea12fb4bae820f03d2562ebff487",
+ "balance":"6050bdeb3354b5c98adc3",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940"
+ },
+ {
+ "address":"0xf14c14075d6c4ed84b86798af0956deef67365b5",
+ "balance":"1d77844e94c25ba2",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xca544e5c4687d109611d0f8f928b53a25af72448"
+ },
+ {
+ "address":"0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c",
+ "balance":"2e93a72de4fc5ec0ed",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7"
+ },
+ {
+ "address":"0x6d87578288b6cb5549d5076a207456a1f6a63dc0",
+ "balance":"1afd340799e48c18",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e"
+ },
+ {
+ "address":"0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6",
+ "balance":"14d0944eb3be947a8",
+ "extraBalance":"0",
+ "extraBalanceAccount":"0x2b3455ec7fedf16e646268bf88846bd7a2319bb2"
+ },
+ {
+ "address":"0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a",
+ "balance":"6202b236a200e365eba",
+ "extraBalance":"11979be9020f03ec4ec",
+ "extraBalanceAccount":"0xd343b217de44030afaa275f54d31a9317c7f441e"
+ },
+ {
+ "address":"0x84ef4b2357079cd7a7c69fd7a37cd0609a679106",
+ "balance":"7ed634ebbba531901e07",
+ "extraBalance":"f9c5eff28cb08720c85",
+ "extraBalanceAccount":"0xda2fef9e4a3230988ff17df2165440f37e8b1708"
+ },
+ {
+ "address":"0xf4c64518ea10f995918a454158c6b61407ea345c",
+ "balance":"39152e15508a96ff894a",
+ "extraBalance":"14041ca908bcc185c8",
+ "extraBalanceAccount":"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97"
+ },
+ {
+ "address":"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
+ "balance":"1",
+ "extraBalance":"5553ebc",
+ "extraBalanceAccount":"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
+ }
+]
+`
diff --git a/params/util.go b/params/util.go
index b37bc79b2..9d1fa54e6 100644
--- a/params/util.go
+++ b/params/util.go
@@ -19,6 +19,6 @@ package params
import "math/big"
var (
- TestNetHomesteadBlock = big.NewInt(494000) // testnet homestead block
- MainNetHomesteadBlock = big.NewInt(1150000) // mainnet homestead block
+ TestNetHomesteadBlock = big.NewInt(494000) // Testnet homestead block
+ MainNetHomesteadBlock = big.NewInt(1150000) // Mainnet homestead block
)
diff --git a/release/release.go b/release/release.go
index 05b4885b5..21b5e2ce2 100644
--- a/release/release.go
+++ b/release/release.go
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
+ "golang.org/x/net/context"
)
// Interval to check for new releases
@@ -110,7 +111,9 @@ func (r *ReleaseService) checker() {
timer.Reset(releaseRecheckInterval)
// Retrieve the current version, and handle missing contracts gracefully
- version, err := r.oracle.CurrentVersion(nil)
+ ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
+ opts := &bind.CallOpts{Context: ctx}
+ version, err := r.oracle.CurrentVersion(opts)
if err != nil {
if err == bind.ErrNoCode {
glog.V(logger.Debug).Infof("Release oracle not found at %x", r.config.Oracle)
diff --git a/rpc/client.go b/rpc/client.go
new file mode 100644
index 000000000..4ff9a8cb9
--- /dev/null
+++ b/rpc/client.go
@@ -0,0 +1,740 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package rpc
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "reflect"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "golang.org/x/net/context"
+)
+
+var (
+ ErrClientQuit = errors.New("client is closed")
+ ErrNoResult = errors.New("no result in JSON-RPC response")
+)
+
+const (
+ clientSubscriptionBuffer = 100 // if exceeded, the client stops reading
+ tcpKeepAliveInterval = 30 * time.Second
+ defaultDialTimeout = 10 * time.Second // used when dialing if the context has no deadline
+ defaultWriteTimeout = 10 * time.Second // used for calls if the context has no deadline
+ subscribeTimeout = 5 * time.Second // overall timeout eth_subscribe, rpc_modules calls
+)
+
+// BatchElem is an element in a batch request.
+type BatchElem struct {
+ Method string
+ Args []interface{}
+ // The result is unmarshaled into this field. Result must be set to a
+ // non-nil pointer value of the desired type, otherwise the response will be
+ // discarded.
+ Result interface{}
+ // Error is set if the server returns an error for this request, or if
+ // unmarshaling into Result fails. It is not set for I/O errors.
+ Error error
+}
+
+// A value of this type can a JSON-RPC request, notification, successful response or
+// error response. Which one it is depends on the fields.
+type jsonrpcMessage struct {
+ Version string `json:"jsonrpc"`
+ ID json.RawMessage `json:"id,omitempty"`
+ Method string `json:"method,omitempty"`
+ Params json.RawMessage `json:"params,omitempty"`
+ Error *jsonError `json:"error,omitempty"`
+ Result json.RawMessage `json:"result,omitempty"`
+}
+
+func (msg *jsonrpcMessage) isNotification() bool {
+ return msg.ID == nil && msg.Method != ""
+}
+
+func (msg *jsonrpcMessage) isResponse() bool {
+ return msg.hasValidID() && msg.Method == "" && len(msg.Params) == 0
+}
+
+func (msg *jsonrpcMessage) hasValidID() bool {
+ return len(msg.ID) > 0 && msg.ID[0] != '{' && msg.ID[0] != '['
+}
+
+func (msg *jsonrpcMessage) String() string {
+ b, _ := json.Marshal(msg)
+ return string(b)
+}
+
+// Client represents a connection to an RPC server.
+type Client struct {
+ idCounter uint32
+ connectFunc func(ctx context.Context) (net.Conn, error)
+ isHTTP bool
+
+ // writeConn is only safe to access outside dispatch, with the
+ // write lock held. The write lock is taken by sending on
+ // requestOp and released by sending on sendDone.
+ writeConn net.Conn
+
+ // for dispatch
+ close chan struct{}
+ didQuit chan struct{} // closed when client quits
+ reconnected chan net.Conn // where write/reconnect sends the new connection
+ readErr chan error // errors from read
+ readResp chan []*jsonrpcMessage // valid messages from read
+ requestOp chan *requestOp // for registering response IDs
+ sendDone chan error // signals write completion, releases write lock
+ respWait map[string]*requestOp // active requests
+ subs map[string]*ClientSubscription // active subscriptions
+}
+
+type requestOp struct {
+ ids []json.RawMessage
+ err error
+ resp chan *jsonrpcMessage // receives up to len(ids) responses
+ sub *ClientSubscription // only set for EthSubscribe requests
+}
+
+func (op *requestOp) wait(ctx context.Context) (*jsonrpcMessage, error) {
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case resp := <-op.resp:
+ return resp, op.err
+ }
+}
+
+// Dial creates a new client for the given URL.
+//
+// The currently supported URL schemes are "http", "https", "ws" and "wss". If rawurl is a
+// file name with no URL scheme, a local socket connection is established using UNIX
+// domain sockets on supported platforms and named pipes on Windows. If you want to
+// configure transport options, use DialHTTP, DialWebsocket or DialIPC instead.
+//
+// For websocket connections, the origin is set to the local host name.
+//
+// The client reconnects automatically if the connection is lost.
+func Dial(rawurl string) (*Client, error) {
+ return DialContext(context.Background(), rawurl)
+}
+
+// DialContext creates a new RPC client, just like Dial.
+//
+// The context is used to cancel or time out the initial connection establishment. It does
+// not affect subsequent interactions with the client.
+func DialContext(ctx context.Context, rawurl string) (*Client, error) {
+ u, err := url.Parse(rawurl)
+ if err != nil {
+ return nil, err
+ }
+ switch u.Scheme {
+ case "http", "https":
+ return DialHTTP(rawurl)
+ case "ws", "wss":
+ return DialWebsocket(ctx, rawurl, "")
+ case "":
+ return DialIPC(ctx, rawurl)
+ default:
+ return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme)
+ }
+}
+
+func newClient(initctx context.Context, connectFunc func(context.Context) (net.Conn, error)) (*Client, error) {
+ conn, err := connectFunc(initctx)
+ if err != nil {
+ return nil, err
+ }
+ _, isHTTP := conn.(*httpConn)
+
+ c := &Client{
+ writeConn: conn,
+ isHTTP: isHTTP,
+ connectFunc: connectFunc,
+ close: make(chan struct{}),
+ didQuit: make(chan struct{}),
+ reconnected: make(chan net.Conn),
+ readErr: make(chan error),
+ readResp: make(chan []*jsonrpcMessage),
+ requestOp: make(chan *requestOp),
+ sendDone: make(chan error, 1),
+ respWait: make(map[string]*requestOp),
+ subs: make(map[string]*ClientSubscription),
+ }
+ if !isHTTP {
+ go c.dispatch(conn)
+ }
+ return c, nil
+}
+
+func (c *Client) nextID() json.RawMessage {
+ id := atomic.AddUint32(&c.idCounter, 1)
+ return []byte(strconv.FormatUint(uint64(id), 10))
+}
+
+// SupportedModules calls the rpc_modules method, retrieving the list of
+// APIs that are available on the server.
+func (c *Client) SupportedModules() (map[string]string, error) {
+ var result map[string]string
+ ctx, cancel := context.WithTimeout(context.Background(), subscribeTimeout)
+ defer cancel()
+ err := c.CallContext(ctx, &result, "rpc_modules")
+ return result, err
+}
+
+// Close closes the client, aborting any in-flight requests.
+func (c *Client) Close() {
+ if c.isHTTP {
+ return
+ }
+ select {
+ case c.close <- struct{}{}:
+ <-c.didQuit
+ case <-c.didQuit:
+ }
+}
+
+// Call performs a JSON-RPC call with the given arguments and unmarshals into
+// result if no error occurred.
+//
+// The result must be a pointer so that package json can unmarshal into it. You
+// can also pass nil, in which case the result is ignored.
+func (c *Client) Call(result interface{}, method string, args ...interface{}) error {
+ ctx := context.Background()
+ return c.CallContext(ctx, result, method, args...)
+}
+
+// CallContext performs a JSON-RPC call with the given arguments. If the context is
+// canceled before the call has successfully returned, CallContext returns immediately.
+//
+// The result must be a pointer so that package json can unmarshal into it. You
+// can also pass nil, in which case the result is ignored.
+func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
+ msg, err := c.newMessage(method, args...)
+ if err != nil {
+ return err
+ }
+ op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
+
+ if c.isHTTP {
+ err = c.sendHTTP(ctx, op, msg)
+ } else {
+ err = c.send(ctx, op, msg)
+ }
+ if err != nil {
+ return err
+ }
+
+ // dispatch has accepted the request and will close the channel it when it quits.
+ switch resp, err := op.wait(ctx); {
+ case err != nil:
+ return err
+ case resp.Error != nil:
+ return resp.Error
+ case len(resp.Result) == 0:
+ return ErrNoResult
+ default:
+ return json.Unmarshal(resp.Result, &result)
+ }
+}
+
+// BatchCall sends all given requests as a single batch and waits for the server
+// to return a response for all of them.
+//
+// In contrast to Call, BatchCall only returns I/O errors. Any error specific to
+// a request is reported through the Error field of the corresponding BatchElem.
+//
+// Note that batch calls may not be executed atomically on the server side.
+func (c *Client) BatchCall(b []BatchElem) error {
+ ctx := context.Background()
+ return c.BatchCallContext(ctx, b)
+}
+
+// BatchCall sends all given requests as a single batch and waits for the server
+// to return a response for all of them. The wait duration is bounded by the
+// context's deadline.
+//
+// In contrast to CallContext, BatchCallContext only returns I/O errors. Any
+// error specific to a request is reported through the Error field of the
+// corresponding BatchElem.
+//
+// Note that batch calls may not be executed atomically on the server side.
+func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
+ msgs := make([]*jsonrpcMessage, len(b))
+ op := &requestOp{
+ ids: make([]json.RawMessage, len(b)),
+ resp: make(chan *jsonrpcMessage, len(b)),
+ }
+ for i, elem := range b {
+ msg, err := c.newMessage(elem.Method, elem.Args...)
+ if err != nil {
+ return err
+ }
+ msgs[i] = msg
+ op.ids[i] = msg.ID
+ }
+
+ var err error
+ if c.isHTTP {
+ err = c.sendBatchHTTP(ctx, op, msgs)
+ } else {
+ err = c.send(ctx, op, msgs)
+ }
+
+ // Wait for all responses to come back.
+ for n := 0; n < len(b) && err == nil; n++ {
+ var resp *jsonrpcMessage
+ resp, err = op.wait(ctx)
+ if err != nil {
+ break
+ }
+ // Find the element corresponding to this response.
+ // The element is guaranteed to be present because dispatch
+ // only sends valid IDs to our channel.
+ var elem *BatchElem
+ for i := range msgs {
+ if bytes.Equal(msgs[i].ID, resp.ID) {
+ elem = &b[i]
+ break
+ }
+ }
+ if resp.Error != nil {
+ elem.Error = resp.Error
+ continue
+ }
+ if len(resp.Result) == 0 {
+ elem.Error = ErrNoResult
+ continue
+ }
+ elem.Error = json.Unmarshal(resp.Result, elem.Result)
+ }
+ return err
+}
+
+// EthSubscribe calls the "eth_subscribe" method with the given arguments,
+// registering a subscription. Server notifications for the subscription are
+// sent to the given channel. The element type of the channel must match the
+// expected type of content returned by the subscription.
+//
+// Callers should not use the same channel for multiple calls to EthSubscribe.
+// The channel is closed when the notification is unsubscribed or an error
+// occurs. The error can be retrieved via the Err method of the subscription.
+//
+// Slow subscribers will block the clients ingress path eventually.
+func (c *Client) EthSubscribe(channel interface{}, args ...interface{}) (*ClientSubscription, error) {
+ // Check type of channel first.
+ chanVal := reflect.ValueOf(channel)
+ if chanVal.Kind() != reflect.Chan || chanVal.Type().ChanDir()&reflect.SendDir == 0 {
+ panic("first argument to EthSubscribe must be a writable channel")
+ }
+ if chanVal.IsNil() {
+ panic("channel given to EthSubscribe must not be nil")
+ }
+ if c.isHTTP {
+ return nil, ErrNotificationsUnsupported
+ }
+
+ msg, err := c.newMessage(subscribeMethod, args...)
+ if err != nil {
+ return nil, err
+ }
+ op := &requestOp{
+ ids: []json.RawMessage{msg.ID},
+ resp: make(chan *jsonrpcMessage),
+ sub: newClientSubscription(c, chanVal),
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), subscribeTimeout)
+ defer cancel()
+
+ // Send the subscription request.
+ // The arrival and validity of the response is signaled on sub.quit.
+ if err := c.send(ctx, op, msg); err != nil {
+ return nil, err
+ }
+ if _, err := op.wait(ctx); err != nil {
+ return nil, err
+ }
+ return op.sub, nil
+}
+
+func (c *Client) newMessage(method string, paramsIn ...interface{}) (*jsonrpcMessage, error) {
+ params, err := json.Marshal(paramsIn)
+ if err != nil {
+ return nil, err
+ }
+ return &jsonrpcMessage{Version: "2.0", ID: c.nextID(), Method: method, Params: params}, nil
+}
+
+// send registers op with the dispatch loop, then sends msg on the connection.
+// if sending fails, op is deregistered.
+func (c *Client) send(ctx context.Context, op *requestOp, msg interface{}) error {
+ select {
+ case c.requestOp <- op:
+ if glog.V(logger.Detail) {
+ glog.Info("sending ", msg)
+ }
+ err := c.write(ctx, msg)
+ c.sendDone <- err
+ return err
+ case <-c.didQuit:
+ return ErrClientQuit
+ }
+}
+
+func (c *Client) write(ctx context.Context, msg interface{}) error {
+ deadline, ok := ctx.Deadline()
+ if !ok {
+ deadline = time.Now().Add(defaultWriteTimeout)
+ }
+ // The previous write failed. Try to establish a new connection.
+ if c.writeConn == nil {
+ if err := c.reconnect(ctx); err != nil {
+ return err
+ }
+ }
+ c.writeConn.SetWriteDeadline(deadline)
+ err := json.NewEncoder(c.writeConn).Encode(msg)
+ if err != nil {
+ c.writeConn = nil
+ }
+ return err
+}
+
+func (c *Client) reconnect(ctx context.Context) error {
+ newconn, err := c.connectFunc(ctx)
+ if err != nil {
+ glog.V(logger.Detail).Infof("reconnect failed: %v", err)
+ return err
+ }
+ select {
+ case c.reconnected <- newconn:
+ c.writeConn = newconn
+ return nil
+ case <-c.didQuit:
+ newconn.Close()
+ return ErrClientQuit
+ }
+}
+
+// dispatch is the main loop of the client.
+// It sends read messages to waiting calls to Call and BatchCall
+// and subscription notifications to registered subscriptions.
+func (c *Client) dispatch(conn net.Conn) {
+ // Spawn the initial read loop.
+ go c.read(conn)
+
+ var (
+ lastOp *requestOp // tracks last send operation
+ requestOpLock = c.requestOp // nil while the send lock is held
+ reading = true // if true, a read loop is running
+ )
+ defer close(c.didQuit)
+ defer func() {
+ c.closeRequestOps(ErrClientQuit)
+ conn.Close()
+ if reading {
+ // Empty read channels until read is dead.
+ for {
+ select {
+ case <-c.readResp:
+ case <-c.readErr:
+ return
+ }
+ }
+ }
+ }()
+
+ for {
+ select {
+ case <-c.close:
+ return
+
+ // Read path.
+ case batch := <-c.readResp:
+ for _, msg := range batch {
+ switch {
+ case msg.isNotification():
+ if glog.V(logger.Detail) {
+ glog.Info("<-readResp: notification ", msg)
+ }
+ c.handleNotification(msg)
+ case msg.isResponse():
+ if glog.V(logger.Detail) {
+ glog.Info("<-readResp: response ", msg)
+ }
+ c.handleResponse(msg)
+ default:
+ if glog.V(logger.Debug) {
+ glog.Error("<-readResp: dropping weird message", msg)
+ }
+ // TODO: maybe close
+ }
+ }
+
+ case err := <-c.readErr:
+ glog.V(logger.Debug).Infof("<-readErr: %v", err)
+ c.closeRequestOps(err)
+ conn.Close()
+ reading = false
+
+ case newconn := <-c.reconnected:
+ glog.V(logger.Debug).Infof("<-reconnected: (reading=%t) %v", reading, conn.RemoteAddr())
+ if reading {
+ // Wait for the previous read loop to exit. This is a rare case.
+ conn.Close()
+ <-c.readErr
+ }
+ go c.read(newconn)
+ reading = true
+ conn = newconn
+
+ // Send path.
+ case op := <-requestOpLock:
+ // Stop listening for further send ops until the current one is done.
+ requestOpLock = nil
+ lastOp = op
+ for _, id := range op.ids {
+ c.respWait[string(id)] = op
+ }
+
+ case err := <-c.sendDone:
+ if err != nil {
+ // Remove response handlers for the last send. We remove those here
+ // because the error is already handled in Call or BatchCall. When the
+ // read loop goes down, it will signal all other current operations.
+ for _, id := range lastOp.ids {
+ delete(c.respWait, string(id))
+ }
+ }
+ // Listen for send ops again.
+ requestOpLock = c.requestOp
+ lastOp = nil
+ }
+ }
+}
+
+// closeRequestOps unblocks pending send ops and active subscriptions.
+func (c *Client) closeRequestOps(err error) {
+ didClose := make(map[*requestOp]bool)
+
+ for id, op := range c.respWait {
+ // Remove the op so that later calls will not close op.resp again.
+ delete(c.respWait, id)
+
+ if !didClose[op] {
+ op.err = err
+ close(op.resp)
+ didClose[op] = true
+ }
+ }
+ for id, sub := range c.subs {
+ delete(c.subs, id)
+ sub.quitWithError(err, false)
+ }
+}
+
+func (c *Client) handleNotification(msg *jsonrpcMessage) {
+ if msg.Method != notificationMethod {
+ glog.V(logger.Debug).Info("dropping non-subscription message: ", msg)
+ return
+ }
+ var subResult struct {
+ ID string `json:"subscription"`
+ Result json.RawMessage `json:"result"`
+ }
+ if err := json.Unmarshal(msg.Params, &subResult); err != nil {
+ glog.V(logger.Debug).Info("dropping invalid subscription message: ", msg)
+ return
+ }
+ if c.subs[subResult.ID] != nil {
+ c.subs[subResult.ID].deliver(subResult.Result)
+ }
+}
+
+func (c *Client) handleResponse(msg *jsonrpcMessage) {
+ op := c.respWait[string(msg.ID)]
+ if op == nil {
+ glog.V(logger.Debug).Infof("unsolicited response %v", msg)
+ return
+ }
+ delete(c.respWait, string(msg.ID))
+ // For normal responses, just forward the reply to Call/BatchCall.
+ if op.sub == nil {
+ op.resp <- msg
+ return
+ }
+ // For subscription responses, start the subscription if the server
+ // indicates success. EthSubscribe gets unblocked in either case through
+ // the op.resp channel.
+ defer close(op.resp)
+ if msg.Error != nil {
+ op.err = msg.Error
+ return
+ }
+ if op.err = json.Unmarshal(msg.Result, &op.sub.subid); op.err == nil {
+ go op.sub.start()
+ c.subs[op.sub.subid] = op.sub
+ }
+}
+
+// Reading happens on a dedicated goroutine.
+
+func (c *Client) read(conn net.Conn) error {
+ var (
+ buf json.RawMessage
+ dec = json.NewDecoder(conn)
+ )
+ readMessage := func() (rs []*jsonrpcMessage, err error) {
+ buf = buf[:0]
+ if err = dec.Decode(&buf); err != nil {
+ return nil, err
+ }
+ if isBatch(buf) {
+ err = json.Unmarshal(buf, &rs)
+ } else {
+ rs = make([]*jsonrpcMessage, 1)
+ err = json.Unmarshal(buf, &rs[0])
+ }
+ return rs, err
+ }
+
+ for {
+ resp, err := readMessage()
+ if err != nil {
+ c.readErr <- err
+ return err
+ }
+ c.readResp <- resp
+ }
+}
+
+// Subscriptions.
+
+// A ClientSubscription represents a subscription established through EthSubscribe.
+type ClientSubscription struct {
+ client *Client
+ etype reflect.Type
+ channel reflect.Value
+ subid string
+ in chan json.RawMessage
+
+ quitOnce sync.Once // ensures quit is closed once
+ quit chan struct{} // quit is closed when the subscription exits
+ errOnce sync.Once // ensures err is closed once
+ err chan error
+}
+
+func newClientSubscription(c *Client, channel reflect.Value) *ClientSubscription {
+ sub := &ClientSubscription{
+ client: c,
+ etype: channel.Type().Elem(),
+ channel: channel,
+ quit: make(chan struct{}),
+ err: make(chan error, 1),
+ // in is buffered so dispatch can continue even if the subscriber is slow.
+ in: make(chan json.RawMessage, clientSubscriptionBuffer),
+ }
+ return sub
+}
+
+// Err returns the subscription error channel. The intended use of Err is to schedule
+// resubscription when the client connection is closed unexpectedly.
+//
+// The error channel receives a value when the subscription has ended due
+// to an error. The received error is ErrClientQuit if Close has been called
+// on the underlying client and no other error has occurred.
+//
+// The error channel is closed when Unsubscribe is called on the subscription.
+func (sub *ClientSubscription) Err() <-chan error {
+ return sub.err
+}
+
+// Unsubscribe unsubscribes the notification and closes the error channel.
+// It can safely be called more than once.
+func (sub *ClientSubscription) Unsubscribe() {
+ sub.quitWithError(nil, true)
+ sub.errOnce.Do(func() { close(sub.err) })
+}
+
+func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) {
+ sub.quitOnce.Do(func() {
+ if unsubscribeServer {
+ sub.requestUnsubscribe()
+ }
+ if err != nil {
+ sub.err <- err
+ }
+ close(sub.quit)
+ })
+}
+
+func (sub *ClientSubscription) deliver(result json.RawMessage) (ok bool) {
+ select {
+ case sub.in <- result:
+ return true
+ case <-sub.quit:
+ return false
+ }
+}
+
+func (sub *ClientSubscription) start() {
+ sub.quitWithError(sub.forward())
+}
+
+func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) {
+ cases := []reflect.SelectCase{
+ {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)},
+ {Dir: reflect.SelectSend, Chan: sub.channel},
+ }
+ for {
+ select {
+ case result := <-sub.in:
+ val, err := sub.unmarshal(result)
+ if err != nil {
+ return err, true
+ }
+ cases[1].Send = val
+ switch chosen, _, _ := reflect.Select(cases); chosen {
+ case 0: // <-sub.quit
+ return nil, false
+ case 1: // sub.channel<-
+ continue
+ }
+ case <-sub.quit:
+ return nil, false
+ }
+ }
+}
+
+func (sub *ClientSubscription) unmarshal(result json.RawMessage) (reflect.Value, error) {
+ val := reflect.New(sub.etype)
+ err := json.Unmarshal(result, val.Interface())
+ return val.Elem(), err
+}
+
+func (sub *ClientSubscription) requestUnsubscribe() error {
+ var result interface{}
+ return sub.client.Call(&result, unsubscribeMethod, sub.subid)
+}
diff --git a/rpc/client_context_go1.4.go b/rpc/client_context_go1.4.go
new file mode 100644
index 000000000..ac956a17d
--- /dev/null
+++ b/rpc/client_context_go1.4.go
@@ -0,0 +1,60 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// +build !go1.5
+
+package rpc
+
+import (
+ "net"
+ "net/http"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// In older versions of Go (below 1.5), dials cannot be canceled
+// via a channel or context. The context deadline can still applied.
+
+// contextDialer returns a dialer that applies the deadline value from the given context.
+func contextDialer(ctx context.Context) *net.Dialer {
+ dialer := &net.Dialer{KeepAlive: tcpKeepAliveInterval}
+ if deadline, ok := ctx.Deadline(); ok {
+ dialer.Deadline = deadline
+ } else {
+ dialer.Deadline = time.Now().Add(defaultDialTimeout)
+ }
+ return dialer
+}
+
+// dialContext connects to the given address, aborting the dial if ctx is canceled.
+func dialContext(ctx context.Context, network, addr string) (net.Conn, error) {
+ return contextDialer(ctx).Dial(network, addr)
+}
+
+// requestWithContext copies req, adding the cancelation channel and deadline from ctx.
+func requestWithContext(c *http.Client, req *http.Request, ctx context.Context) (*http.Client, *http.Request) {
+ // Set Timeout on the client if the context has a deadline.
+ // Note that there is no default timeout (unlike in contextDialer) because
+ // the timeout applies to the entire request, including reads from body.
+ if deadline, ok := ctx.Deadline(); ok {
+ c2 := *c
+ c2.Timeout = deadline.Sub(time.Now())
+ c = &c2
+ }
+ req2 := *req
+ return c, &req2
+}
diff --git a/rpc/client_context_go1.5.go b/rpc/client_context_go1.5.go
new file mode 100644
index 000000000..4a007d9f8
--- /dev/null
+++ b/rpc/client_context_go1.5.go
@@ -0,0 +1,61 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// +build go1.5,!go1.6
+
+package rpc
+
+import (
+ "net"
+ "net/http"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// In Go 1.5, dials cannot be canceled via a channel or context. The context deadline can
+// still be applied. Go 1.5 adds the ability to cancel HTTP requests via a channel.
+
+// contextDialer returns a dialer that applies the deadline value from the given context.
+func contextDialer(ctx context.Context) *net.Dialer {
+ dialer := &net.Dialer{KeepAlive: tcpKeepAliveInterval}
+ if deadline, ok := ctx.Deadline(); ok {
+ dialer.Deadline = deadline
+ } else {
+ dialer.Deadline = time.Now().Add(defaultDialTimeout)
+ }
+ return dialer
+}
+
+// dialContext connects to the given address, aborting the dial if ctx is canceled.
+func dialContext(ctx context.Context, network, addr string) (net.Conn, error) {
+ return contextDialer(ctx).Dial(network, addr)
+}
+
+// requestWithContext copies req, adding the cancelation channel and deadline from ctx.
+func requestWithContext(c *http.Client, req *http.Request, ctx context.Context) (*http.Client, *http.Request) {
+ // Set Timeout on the client if the context has a deadline.
+ // Note that there is no default timeout (unlike in contextDialer) because
+ // the timeout applies to the entire request, including reads from body.
+ if deadline, ok := ctx.Deadline(); ok {
+ c2 := *c
+ c2.Timeout = deadline.Sub(time.Now())
+ c = &c2
+ }
+ req2 := *req
+ req2.Cancel = ctx.Done()
+ return c, &req2
+}
diff --git a/rpc/client_context_go1.6.go b/rpc/client_context_go1.6.go
new file mode 100644
index 000000000..67777ddc6
--- /dev/null
+++ b/rpc/client_context_go1.6.go
@@ -0,0 +1,55 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// +build go1.6,!go1.7
+
+package rpc
+
+import (
+ "net"
+ "net/http"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// In Go 1.6, net.Dialer gained the ability to cancel via a channel.
+
+// contextDialer returns a dialer that applies the deadline value from the given context.
+func contextDialer(ctx context.Context) *net.Dialer {
+ dialer := &net.Dialer{Cancel: ctx.Done(), KeepAlive: tcpKeepAliveInterval}
+ if deadline, ok := ctx.Deadline(); ok {
+ dialer.Deadline = deadline
+ } else {
+ dialer.Deadline = time.Now().Add(defaultDialTimeout)
+ }
+ return dialer
+}
+
+// dialContext connects to the given address, aborting the dial if ctx is canceled.
+func dialContext(ctx context.Context, network, addr string) (net.Conn, error) {
+ return contextDialer(ctx).Dial(network, addr)
+}
+
+// requestWithContext copies req, adding the cancelation channel and deadline from ctx.
+func requestWithContext(c *http.Client, req *http.Request, ctx context.Context) (*http.Client, *http.Request) {
+ // We set Timeout on the client for Go <= 1.5. There
+ // is no need to do that here because the dial will be canceled
+ // by package http.
+ req2 := *req
+ req2.Cancel = ctx.Done()
+ return c, &req2
+}
diff --git a/rpc/client_context_go1.7.go b/rpc/client_context_go1.7.go
new file mode 100644
index 000000000..56ce12ab8
--- /dev/null
+++ b/rpc/client_context_go1.7.go
@@ -0,0 +1,51 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// +build go1.7
+
+package rpc
+
+import (
+ "context"
+ "net"
+ "net/http"
+ "time"
+)
+
+// In Go 1.7, context moved into the standard library and support
+// for cancelation via context was added to net.Dialer and http.Request.
+
+// contextDialer returns a dialer that applies the deadline value from the given context.
+func contextDialer(ctx context.Context) *net.Dialer {
+ dialer := &net.Dialer{Cancel: ctx.Done(), KeepAlive: tcpKeepAliveInterval}
+ if deadline, ok := ctx.Deadline(); ok {
+ dialer.Deadline = deadline
+ } else {
+ dialer.Deadline = time.Now().Add(defaultDialTimeout)
+ }
+ return dialer
+}
+
+// dialContext connects to the given address, aborting the dial if ctx is canceled.
+func dialContext(ctx context.Context, network, addr string) (net.Conn, error) {
+ d := &net.Dialer{KeepAlive: tcpKeepAliveInterval}
+ return d.DialContext(ctx, network, addr)
+}
+
+// requestWithContext copies req, adding the cancelation channel and deadline from ctx.
+func requestWithContext(c *http.Client, req *http.Request, ctx context.Context) (*http.Client, *http.Request) {
+ return c, req.WithContext(ctx)
+}
diff --git a/rpc/client_example_test.go b/rpc/client_example_test.go
new file mode 100644
index 000000000..84b4b67bb
--- /dev/null
+++ b/rpc/client_example_test.go
@@ -0,0 +1,83 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package rpc_test
+
+import (
+ "fmt"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// In this example, our client whishes to track the latest 'block number'
+// known to the server. The server supports two methods:
+//
+// eth_getBlockByNumber("latest", {})
+// returns the latest block object.
+//
+// eth_subscribe("newBlocks")
+// creates a subscription which fires block objects when new blocks arrive.
+
+type Block struct {
+ Number *big.Int
+}
+
+func ExampleClientSubscription() {
+ // Connect the client.
+ client, _ := rpc.Dial("ws://127.0.0.1:8485")
+ subch := make(chan Block)
+ go subscribeBlocks(client, subch)
+
+ // Print events from the subscription as they arrive.
+ for block := range subch {
+ fmt.Println("latest block:", block.Number)
+ }
+}
+
+// subscribeBlocks runs in its own goroutine and maintains
+// a subscription for new blocks.
+func subscribeBlocks(client *rpc.Client, subch chan Block) {
+ for i := 0; ; i++ {
+ if i > 0 {
+ time.Sleep(2 * time.Second)
+ }
+
+ // Subscribe to new blocks.
+ sub, err := client.EthSubscribe(subch, "newBlocks")
+ if err == rpc.ErrClientQuit {
+ return // Stop reconnecting if the client was closed.
+ } else if err != nil {
+ fmt.Println("subscribe error:", err)
+ continue
+ }
+
+ // The connection is established now.
+ // Update the channel with the current block.
+ var lastBlock Block
+ if err := client.Call(&lastBlock, "eth_getBlockByNumber", "latest"); err != nil {
+ fmt.Println("can't get latest block:", err)
+ continue
+ }
+ subch <- lastBlock
+
+ // The subscription will deliver events to the channel. Wait for the
+ // subscription to end for any reason, then loop around to re-establish
+ // the connection.
+ fmt.Println("connection lost: ", <-sub.Err())
+ }
+}
diff --git a/rpc/client_test.go b/rpc/client_test.go
new file mode 100644
index 000000000..58dceada0
--- /dev/null
+++ b/rpc/client_test.go
@@ -0,0 +1,489 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package rpc
+
+import (
+ "fmt"
+ "math/rand"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "reflect"
+ "runtime"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "golang.org/x/net/context"
+)
+
+func TestClientRequest(t *testing.T) {
+ server := newTestServer("service", new(Service))
+ defer server.Stop()
+ client := DialInProc(server)
+ defer client.Close()
+
+ var resp Result
+ if err := client.Call(&resp, "service_echo", "hello", 10, &Args{"world"}); err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(resp, Result{"hello", 10, &Args{"world"}}) {
+ t.Errorf("incorrect result %#v", resp)
+ }
+}
+
+func TestClientBatchRequest(t *testing.T) {
+ server := newTestServer("service", new(Service))
+ defer server.Stop()
+ client := DialInProc(server)
+ defer client.Close()
+
+ batch := []BatchElem{
+ {
+ Method: "service_echo",
+ Args: []interface{}{"hello", 10, &Args{"world"}},
+ Result: new(Result),
+ },
+ {
+ Method: "service_echo",
+ Args: []interface{}{"hello2", 11, &Args{"world"}},
+ Result: new(Result),
+ },
+ {
+ Method: "no_such_method",
+ Args: []interface{}{1, 2, 3},
+ Result: new(int),
+ },
+ }
+ if err := client.BatchCall(batch); err != nil {
+ t.Fatal(err)
+ }
+ wantResult := []BatchElem{
+ {
+ Method: "service_echo",
+ Args: []interface{}{"hello", 10, &Args{"world"}},
+ Result: &Result{"hello", 10, &Args{"world"}},
+ },
+ {
+ Method: "service_echo",
+ Args: []interface{}{"hello2", 11, &Args{"world"}},
+ Result: &Result{"hello2", 11, &Args{"world"}},
+ },
+ {
+ Method: "no_such_method",
+ Args: []interface{}{1, 2, 3},
+ Result: new(int),
+ Error: &jsonError{Code: -32601, Message: "The method no_such_method_ does not exist/is not available"},
+ },
+ }
+ if !reflect.DeepEqual(batch, wantResult) {
+ t.Errorf("batch results mismatch:\ngot %swant %s", spew.Sdump(batch), spew.Sdump(wantResult))
+ }
+}
+
+// func TestClientCancelInproc(t *testing.T) { testClientCancel("inproc", t) }
+func TestClientCancelWebsocket(t *testing.T) { testClientCancel("ws", t) }
+func TestClientCancelHTTP(t *testing.T) { testClientCancel("http", t) }
+func TestClientCancelIPC(t *testing.T) { testClientCancel("ipc", t) }
+
+// This test checks that requests made through CallContext can be canceled by canceling
+// the context.
+func testClientCancel(transport string, t *testing.T) {
+ server := newTestServer("service", new(Service))
+ defer server.Stop()
+
+ // What we want to achieve is that the context gets canceled
+ // at various stages of request processing. The interesting cases
+ // are:
+ // - cancel during dial
+ // - cancel while performing a HTTP request
+ // - cancel while waiting for a response
+ //
+ // To trigger those, the times are chosen such that connections
+ // are killed within the deadline for every other call (maxKillTimeout
+ // is 2x maxCancelTimeout).
+ //
+ // Once a connection is dead, there is a fair chance it won't connect
+ // successfully because the accept is delayed by 1s.
+ maxContextCancelTimeout := 300 * time.Millisecond
+ fl := &flakeyListener{
+ maxAcceptDelay: 1 * time.Second,
+ maxKillTimeout: 600 * time.Millisecond,
+ }
+
+ var client *Client
+ switch transport {
+ case "ws", "http":
+ c, hs := httpTestClient(server, transport, fl)
+ defer hs.Close()
+ client = c
+ case "ipc":
+ c, l := ipcTestClient(server, fl)
+ defer l.Close()
+ client = c
+ default:
+ panic("unknown transport: " + transport)
+ }
+
+ // These tests take a lot of time, run them all at once.
+ // You probably want to run with -parallel 1 or comment out
+ // the call to t.Parallel if you enable the logging.
+ t.Parallel()
+ // glog.SetV(6)
+ // glog.SetToStderr(true)
+ // defer glog.SetToStderr(false)
+ // glog.Infoln("testing ", transport)
+
+ // The actual test starts here.
+ var (
+ wg sync.WaitGroup
+ nreqs = 10
+ ncallers = 6
+ )
+ caller := func(index int) {
+ defer wg.Done()
+ for i := 0; i < nreqs; i++ {
+ var (
+ ctx context.Context
+ cancel func()
+ timeout = time.Duration(rand.Int63n(int64(maxContextCancelTimeout)))
+ )
+ if index < ncallers/2 {
+ // For half of the callers, create a context without deadline
+ // and cancel it later.
+ ctx, cancel = context.WithCancel(context.Background())
+ time.AfterFunc(timeout, cancel)
+ } else {
+ // For the other half, create a context with a deadline instead. This is
+ // different because the context deadline is used to set the socket write
+ // deadline.
+ ctx, cancel = context.WithTimeout(context.Background(), timeout)
+ }
+ // Now perform a call with the context.
+ // The key thing here is that no call will ever complete successfully.
+ err := client.CallContext(ctx, nil, "service_sleep", 2*maxContextCancelTimeout)
+ if err != nil {
+ glog.V(logger.Debug).Infoln("got expected error:", err)
+ } else {
+ t.Errorf("no error for call with %v wait time", timeout)
+ }
+ cancel()
+ }
+ }
+ wg.Add(ncallers)
+ for i := 0; i < ncallers; i++ {
+ go caller(i)
+ }
+ wg.Wait()
+}
+
+func TestClientSubscribeInvalidArg(t *testing.T) {
+ server := newTestServer("service", new(Service))
+ defer server.Stop()
+ client := DialInProc(server)
+ defer client.Close()
+
+ check := func(shouldPanic bool, arg interface{}) {
+ defer func() {
+ err := recover()
+ if shouldPanic && err == nil {
+ t.Errorf("EthSubscribe should've panicked for %#v", arg)
+ }
+ if !shouldPanic && err != nil {
+ t.Errorf("EthSubscribe shouldn't have panicked for %#v", arg)
+ buf := make([]byte, 1024*1024)
+ buf = buf[:runtime.Stack(buf, false)]
+ t.Error(err)
+ t.Error(string(buf))
+ }
+ }()
+ client.EthSubscribe(arg, "foo_bar")
+ }
+ check(true, nil)
+ check(true, 1)
+ check(true, (chan int)(nil))
+ check(true, make(<-chan int))
+ check(false, make(chan int))
+ check(false, make(chan<- int))
+}
+
+func TestClientSubscribe(t *testing.T) {
+ server := newTestServer("eth", new(NotificationTestService))
+ defer server.Stop()
+ client := DialInProc(server)
+ defer client.Close()
+
+ nc := make(chan int)
+ count := 10
+ sub, err := client.EthSubscribe(nc, "someSubscription", count, 0)
+ if err != nil {
+ t.Fatal("can't subscribe:", err)
+ }
+ for i := 0; i < count; i++ {
+ if val := <-nc; val != i {
+ t.Fatalf("value mismatch: got %d, want %d", val, i)
+ }
+ }
+
+ sub.Unsubscribe()
+ select {
+ case v := <-nc:
+ t.Fatal("received value after unsubscribe:", v)
+ case err := <-sub.Err():
+ if err != nil {
+ t.Fatalf("Err returned a non-nil error after explicit unsubscribe: %q", err)
+ }
+ case <-time.After(1 * time.Second):
+ t.Fatalf("subscription not closed within 1s after unsubscribe")
+ }
+}
+
+// In this test, the connection drops while EthSubscribe is
+// waiting for a response.
+func TestClientSubscribeClose(t *testing.T) {
+ service := &NotificationTestService{
+ gotHangSubscriptionReq: make(chan struct{}),
+ unblockHangSubscription: make(chan struct{}),
+ }
+ server := newTestServer("eth", service)
+ defer server.Stop()
+ client := DialInProc(server)
+ defer client.Close()
+
+ var (
+ nc = make(chan int)
+ errc = make(chan error)
+ sub *ClientSubscription
+ err error
+ )
+ go func() {
+ sub, err = client.EthSubscribe(nc, "hangSubscription", 999)
+ errc <- err
+ }()
+
+ <-service.gotHangSubscriptionReq
+ client.Close()
+ service.unblockHangSubscription <- struct{}{}
+
+ select {
+ case err := <-errc:
+ if err == nil {
+ t.Errorf("EthSubscribe returned nil error after Close")
+ }
+ if sub != nil {
+ t.Error("EthSubscribe returned non-nil subscription after Close")
+ }
+ case <-time.After(1 * time.Second):
+ t.Fatalf("EthSubscribe did not return within 1s after Close")
+ }
+}
+
+func TestClientHTTP(t *testing.T) {
+ server := newTestServer("service", new(Service))
+ defer server.Stop()
+
+ client, hs := httpTestClient(server, "http", nil)
+ defer hs.Close()
+ defer client.Close()
+
+ // Launch concurrent requests.
+ var (
+ results = make([]Result, 100)
+ errc = make(chan error)
+ wantResult = Result{"a", 1, new(Args)}
+ )
+ defer client.Close()
+ for i := range results {
+ i := i
+ go func() {
+ errc <- client.Call(&results[i], "service_echo",
+ wantResult.String, wantResult.Int, wantResult.Args)
+ }()
+ }
+
+ // Wait for all of them to complete.
+ timeout := time.NewTimer(5 * time.Second)
+ defer timeout.Stop()
+ for i := range results {
+ select {
+ case err := <-errc:
+ if err != nil {
+ t.Fatal(err)
+ }
+ case <-timeout.C:
+ t.Fatalf("timeout (got %d/%d) results)", i+1, len(results))
+ }
+ }
+
+ // Check results.
+ for i := range results {
+ if !reflect.DeepEqual(results[i], wantResult) {
+ t.Errorf("result %d mismatch: got %#v, want %#v", i, results[i], wantResult)
+ }
+ }
+}
+
+func TestClientReconnect(t *testing.T) {
+ startServer := func(addr string) (*Server, net.Listener) {
+ srv := newTestServer("service", new(Service))
+ l, err := net.Listen("tcp", addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ go http.Serve(l, srv.WebsocketHandler("*"))
+ return srv, l
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+
+ // Start a server and corresponding client.
+ s1, l1 := startServer("127.0.0.1:0")
+ client, err := DialContext(ctx, "ws://"+l1.Addr().String())
+ if err != nil {
+ t.Fatal("can't dial", err)
+ }
+
+ // Perform a call. This should work because the server is up.
+ var resp Result
+ if err := client.CallContext(ctx, &resp, "service_echo", "", 1, nil); err != nil {
+ t.Fatal(err)
+ }
+
+ // Shut down the server and try calling again. It shouldn't work.
+ l1.Close()
+ s1.Stop()
+ if err := client.CallContext(ctx, &resp, "service_echo", "", 2, nil); err == nil {
+ t.Error("successful call while the server is down")
+ t.Logf("resp: %#v", resp)
+ }
+
+ // Allow for some cool down time so we can listen on the same address again.
+ time.Sleep(2 * time.Second)
+
+ // Start it up again and call again. The connection should be reestablished.
+ // We spawn multiple calls here to check whether this hangs somehow.
+ s2, l2 := startServer(l1.Addr().String())
+ defer l2.Close()
+ defer s2.Stop()
+
+ start := make(chan struct{})
+ errors := make(chan error, 20)
+ for i := 0; i < cap(errors); i++ {
+ go func() {
+ <-start
+ var resp Result
+ errors <- client.CallContext(ctx, &resp, "service_echo", "", 3, nil)
+ }()
+ }
+ close(start)
+ errcount := 0
+ for i := 0; i < cap(errors); i++ {
+ if err = <-errors; err != nil {
+ errcount++
+ }
+ }
+ t.Log("err:", err)
+ if errcount > 1 {
+ t.Errorf("expected one error after disconnect, got %d", errcount)
+ }
+}
+
+func newTestServer(serviceName string, service interface{}) *Server {
+ server := NewServer()
+ if err := server.RegisterName(serviceName, service); err != nil {
+ panic(err)
+ }
+ return server
+}
+
+func httpTestClient(srv *Server, transport string, fl *flakeyListener) (*Client, *httptest.Server) {
+ // Create the HTTP server.
+ var hs *httptest.Server
+ switch transport {
+ case "ws":
+ hs = httptest.NewUnstartedServer(srv.WebsocketHandler("*"))
+ case "http":
+ hs = httptest.NewUnstartedServer(srv)
+ default:
+ panic("unknown HTTP transport: " + transport)
+ }
+ // Wrap the listener if required.
+ if fl != nil {
+ fl.Listener = hs.Listener
+ hs.Listener = fl
+ }
+ // Connect the client.
+ hs.Start()
+ client, err := Dial(transport + "://" + hs.Listener.Addr().String())
+ if err != nil {
+ panic(err)
+ }
+ return client, hs
+}
+
+func ipcTestClient(srv *Server, fl *flakeyListener) (*Client, net.Listener) {
+ // Listen on a random endpoint.
+ endpoint := fmt.Sprintf("go-ethereum-test-ipc-%d-%d", os.Getpid(), rand.Int63())
+ if runtime.GOOS == "windows" {
+ endpoint = `\\.\pipe\` + endpoint
+ } else {
+ endpoint = os.TempDir() + "/" + endpoint
+ }
+ l, err := ipcListen(endpoint)
+ if err != nil {
+ panic(err)
+ }
+ // Connect the listener to the server.
+ if fl != nil {
+ fl.Listener = l
+ l = fl
+ }
+ go srv.ServeListener(l)
+ // Connect the client.
+ client, err := Dial(endpoint)
+ if err != nil {
+ panic(err)
+ }
+ return client, l
+}
+
+// flakeyListener kills accepted connections after a random timeout.
+type flakeyListener struct {
+ net.Listener
+ maxKillTimeout time.Duration
+ maxAcceptDelay time.Duration
+}
+
+func (l *flakeyListener) Accept() (net.Conn, error) {
+ delay := time.Duration(rand.Int63n(int64(l.maxAcceptDelay)))
+ time.Sleep(delay)
+
+ c, err := l.Listener.Accept()
+ if err == nil {
+ timeout := time.Duration(rand.Int63n(int64(l.maxKillTimeout)))
+ time.AfterFunc(timeout, func() {
+ glog.V(logger.Debug).Infof("killing conn %v after %v", c.LocalAddr(), timeout)
+ c.Close()
+ })
+ }
+ return c, err
+}
diff --git a/rpc/errors.go b/rpc/errors.go
index bc352fc45..9cf9dc60c 100644
--- a/rpc/errors.go
+++ b/rpc/errors.go
@@ -24,74 +24,43 @@ type methodNotFoundError struct {
method string
}
-func (e *methodNotFoundError) Code() int {
- return -32601
-}
+func (e *methodNotFoundError) ErrorCode() int { return -32601 }
func (e *methodNotFoundError) Error() string {
return fmt.Sprintf("The method %s%s%s does not exist/is not available", e.service, serviceMethodSeparator, e.method)
}
// received message isn't a valid request
-type invalidRequestError struct {
- message string
-}
+type invalidRequestError struct{ message string }
-func (e *invalidRequestError) Code() int {
- return -32600
-}
+func (e *invalidRequestError) ErrorCode() int { return -32600 }
-func (e *invalidRequestError) Error() string {
- return e.message
-}
+func (e *invalidRequestError) Error() string { return e.message }
// received message is invalid
-type invalidMessageError struct {
- message string
-}
+type invalidMessageError struct{ message string }
-func (e *invalidMessageError) Code() int {
- return -32700
-}
+func (e *invalidMessageError) ErrorCode() int { return -32700 }
-func (e *invalidMessageError) Error() string {
- return e.message
-}
+func (e *invalidMessageError) Error() string { return e.message }
// unable to decode supplied params, or an invalid number of parameters
-type invalidParamsError struct {
- message string
-}
+type invalidParamsError struct{ message string }
-func (e *invalidParamsError) Code() int {
- return -32602
-}
+func (e *invalidParamsError) ErrorCode() int { return -32602 }
-func (e *invalidParamsError) Error() string {
- return e.message
-}
+func (e *invalidParamsError) Error() string { return e.message }
// logic error, callback returned an error
-type callbackError struct {
- message string
-}
+type callbackError struct{ message string }
-func (e *callbackError) Code() int {
- return -32000
-}
+func (e *callbackError) ErrorCode() int { return -32000 }
-func (e *callbackError) Error() string {
- return e.message
-}
+func (e *callbackError) Error() string { return e.message }
// issued when a request is received after the server is issued to stop.
-type shutdownError struct {
-}
+type shutdownError struct{}
-func (e *shutdownError) Code() int {
- return -32000
-}
+func (e *shutdownError) ErrorCode() int { return -32000 }
-func (e *shutdownError) Error() string {
- return "server is shutting down"
-}
+func (e *shutdownError) Error() string { return "server is shutting down" }
diff --git a/rpc/http.go b/rpc/http.go
index 9283ce0ec..afcdd4bd6 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -22,71 +22,108 @@ import (
"fmt"
"io"
"io/ioutil"
+ "net"
"net/http"
- "net/url"
"strings"
+ "sync"
+ "time"
"github.com/rs/cors"
+ "golang.org/x/net/context"
)
const (
maxHTTPRequestContentLength = 1024 * 128
)
-// httpClient connects to a geth RPC server over HTTP.
-type httpClient struct {
- endpoint *url.URL // HTTP-RPC server endpoint
- httpClient http.Client // reuse connection
- lastRes []byte // HTTP requests are synchronous, store last response
+var nullAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:0")
+
+type httpConn struct {
+ client *http.Client
+ req *http.Request
+ closeOnce sync.Once
+ closed chan struct{}
+}
+
+// httpConn is treated specially by Client.
+func (hc *httpConn) LocalAddr() net.Addr { return nullAddr }
+func (hc *httpConn) RemoteAddr() net.Addr { return nullAddr }
+func (hc *httpConn) SetReadDeadline(time.Time) error { return nil }
+func (hc *httpConn) SetWriteDeadline(time.Time) error { return nil }
+func (hc *httpConn) SetDeadline(time.Time) error { return nil }
+func (hc *httpConn) Write([]byte) (int, error) { panic("Write called") }
+
+func (hc *httpConn) Read(b []byte) (int, error) {
+ <-hc.closed
+ return 0, io.EOF
+}
+
+func (hc *httpConn) Close() error {
+ hc.closeOnce.Do(func() { close(hc.closed) })
+ return nil
}
-// NewHTTPClient create a new RPC clients that connection to a geth RPC server
-// over HTTP.
-func NewHTTPClient(endpoint string) (Client, error) {
- url, err := url.Parse(endpoint)
+// DialHTTP creates a new RPC clients that connection to an RPC server over HTTP.
+func DialHTTP(endpoint string) (*Client, error) {
+ req, err := http.NewRequest("POST", endpoint, nil)
if err != nil {
return nil, err
}
- return &httpClient{endpoint: url}, nil
-}
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Accept", "application/json")
-// Send will serialize the given msg to JSON and sends it to the RPC server.
-// Since HTTP is synchronous the response is stored until Recv is called.
-func (client *httpClient) Send(msg interface{}) error {
- var body []byte
- var err error
+ initctx := context.Background()
+ return newClient(initctx, func(context.Context) (net.Conn, error) {
+ return &httpConn{client: new(http.Client), req: req, closed: make(chan struct{})}, nil
+ })
+}
- client.lastRes = nil
- if body, err = json.Marshal(msg); err != nil {
+func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) error {
+ hc := c.writeConn.(*httpConn)
+ respBody, err := hc.doRequest(ctx, msg)
+ if err != nil {
return err
}
+ defer respBody.Close()
+ var respmsg jsonrpcMessage
+ if err := json.NewDecoder(respBody).Decode(&respmsg); err != nil {
+ return err
+ }
+ op.resp <- &respmsg
+ return nil
+}
- resp, err := client.httpClient.Post(client.endpoint.String(), "application/json", bytes.NewReader(body))
+func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonrpcMessage) error {
+ hc := c.writeConn.(*httpConn)
+ respBody, err := hc.doRequest(ctx, msgs)
if err != nil {
return err
}
-
- defer resp.Body.Close()
- if resp.StatusCode == http.StatusOK {
- client.lastRes, err = ioutil.ReadAll(resp.Body)
+ defer respBody.Close()
+ var respmsgs []jsonrpcMessage
+ if err := json.NewDecoder(respBody).Decode(&respmsgs); err != nil {
return err
}
-
- return fmt.Errorf("request failed: %s", resp.Status)
-}
-
-// Recv will try to deserialize the last received response into the given msg.
-func (client *httpClient) Recv(msg interface{}) error {
- return json.Unmarshal(client.lastRes, &msg)
+ for _, respmsg := range respmsgs {
+ op.resp <- &respmsg
+ }
+ return nil
}
-// Close is not necessary for httpClient
-func (client *httpClient) Close() {
-}
+func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadCloser, error) {
+ body, err := json.Marshal(msg)
+ if err != nil {
+ return nil, err
+ }
+ client, req := requestWithContext(hc.client, hc.req, ctx)
+ req.Body = ioutil.NopCloser(bytes.NewReader(body))
+ req.ContentLength = int64(len(body))
-// SupportedModules will return the collection of offered RPC modules.
-func (client *httpClient) SupportedModules() (map[string]string, error) {
- return SupportedModules(client)
+ resp, err := client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ return resp.Body, nil
}
// httpReadWriteNopCloser wraps a io.Reader and io.Writer with a NOP Close method.
@@ -100,43 +137,39 @@ func (t *httpReadWriteNopCloser) Close() error {
return nil
}
-// newJSONHTTPHandler creates a HTTP handler that will parse incoming JSON requests,
-// send the request to the given API provider and sends the response back to the caller.
-func newJSONHTTPHandler(srv *Server) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- if r.ContentLength > maxHTTPRequestContentLength {
- http.Error(w,
- fmt.Sprintf("content length too large (%d>%d)", r.ContentLength, maxHTTPRequestContentLength),
- http.StatusRequestEntityTooLarge)
- return
- }
-
- w.Header().Set("content-type", "application/json")
-
- // create a codec that reads direct from the request body until
- // EOF and writes the response to w and order the server to process
- // a single request.
- codec := NewJSONCodec(&httpReadWriteNopCloser{r.Body, w})
- defer codec.Close()
- srv.ServeSingleRequest(codec, OptionMethodInvocation)
+// NewHTTPServer creates a new HTTP RPC server around an API provider.
+//
+// Deprecated: Server implements http.Handler
+func NewHTTPServer(corsString string, srv *Server) *http.Server {
+ return &http.Server{Handler: newCorsHandler(srv, corsString)}
+}
+
+// ServeHTTP serves JSON-RPC requests over HTTP.
+func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.ContentLength > maxHTTPRequestContentLength {
+ http.Error(w,
+ fmt.Sprintf("content length too large (%d>%d)", r.ContentLength, maxHTTPRequestContentLength),
+ http.StatusRequestEntityTooLarge)
+ return
}
+ w.Header().Set("content-type", "application/json")
+
+ // create a codec that reads direct from the request body until
+ // EOF and writes the response to w and order the server to process
+ // a single request.
+ codec := NewJSONCodec(&httpReadWriteNopCloser{r.Body, w})
+ defer codec.Close()
+ srv.ServeSingleRequest(codec, OptionMethodInvocation)
}
-// NewHTTPServer creates a new HTTP RPC server around an API provider.
-func NewHTTPServer(corsString string, srv *Server) *http.Server {
+func newCorsHandler(srv *Server, corsString string) http.Handler {
var allowedOrigins []string
for _, domain := range strings.Split(corsString, ",") {
allowedOrigins = append(allowedOrigins, strings.TrimSpace(domain))
}
-
c := cors.New(cors.Options{
AllowedOrigins: allowedOrigins,
AllowedMethods: []string{"POST", "GET"},
})
-
- handler := c.Handler(newJSONHTTPHandler(srv))
-
- return &http.Server{
- Handler: handler,
- }
+ return c.Handler(srv)
}
diff --git a/rpc/inproc.go b/rpc/inproc.go
index 250f5c787..f72b97497 100644
--- a/rpc/inproc.go
+++ b/rpc/inproc.go
@@ -17,45 +17,18 @@
package rpc
import (
- "encoding/json"
- "io"
"net"
-)
-
-// inProcClient is an in-process buffer stream attached to an RPC server.
-type inProcClient struct {
- server *Server
- cl io.Closer
- enc *json.Encoder
- dec *json.Decoder
-}
-// Close tears down the request channel of the in-proc client.
-func (c *inProcClient) Close() {
- c.cl.Close()
-}
-
-// NewInProcRPCClient creates an in-process buffer stream attachment to a given
-// RPC server.
-func NewInProcRPCClient(handler *Server) Client {
- p1, p2 := net.Pipe()
- go handler.ServeCodec(NewJSONCodec(p1), OptionMethodInvocation|OptionSubscriptions)
- return &inProcClient{handler, p2, json.NewEncoder(p2), json.NewDecoder(p2)}
-}
-
-// Send marshals a message into a json format and injects in into the client
-// request channel.
-func (c *inProcClient) Send(msg interface{}) error {
- return c.enc.Encode(msg)
-}
-
-// Recv reads a message from the response channel and tries to parse it into the
-// given msg interface.
-func (c *inProcClient) Recv(msg interface{}) error {
- return c.dec.Decode(msg)
-}
+ "golang.org/x/net/context"
+)
-// Returns the collection of modules the RPC server offers.
-func (c *inProcClient) SupportedModules() (map[string]string, error) {
- return SupportedModules(c)
+// NewInProcClient attaches an in-process connection to the given RPC server.
+func DialInProc(handler *Server) *Client {
+ initctx := context.Background()
+ c, _ := newClient(initctx, func(context.Context) (net.Conn, error) {
+ p1, p2 := net.Pipe()
+ go handler.ServeCodec(NewJSONCodec(p1), OptionMethodInvocation|OptionSubscriptions)
+ return p2, nil
+ })
+ return c
}
diff --git a/rpc/ipc.go b/rpc/ipc.go
index 05d8909ca..c2b9e3871 100644
--- a/rpc/ipc.go
+++ b/rpc/ipc.go
@@ -17,68 +17,39 @@
package rpc
import (
- "encoding/json"
"net"
+
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+ "golang.org/x/net/context"
)
-// CreateIPCListener creates an listener, on Unix platforms this is a unix socket, on Windows this is a named pipe
+// CreateIPCListener creates an listener, on Unix platforms this is a unix socket, on
+// Windows this is a named pipe
func CreateIPCListener(endpoint string) (net.Listener, error) {
return ipcListen(endpoint)
}
-// ipcClient represent an IPC RPC client. It will connect to a given endpoint and tries to communicate with a node using
-// JSON serialization.
-type ipcClient struct {
- endpoint string
- conn net.Conn
- out *json.Encoder
- in *json.Decoder
-}
-
-// NewIPCClient create a new IPC client that will connect on the given endpoint. Messages are JSON encoded and encoded.
-// On Unix it assumes the endpoint is the full path to a unix socket, and Windows the endpoint is an identifier for a
-// named pipe.
-func NewIPCClient(endpoint string) (Client, error) {
- conn, err := newIPCConnection(endpoint)
- if err != nil {
- return nil, err
- }
- return &ipcClient{endpoint: endpoint, conn: conn, in: json.NewDecoder(conn), out: json.NewEncoder(conn)}, nil
-}
-
-// Send will serialize the given message and send it to the server.
-// When sending the message fails it will try to reconnect once and send the message again.
-func (client *ipcClient) Send(msg interface{}) error {
- if err := client.out.Encode(msg); err == nil {
- return nil
- }
-
- // retry once
- client.conn.Close()
-
- conn, err := newIPCConnection(client.endpoint)
- if err != nil {
- return err
+// ServeListener accepts connections on l, serving JSON-RPC on them.
+func (srv *Server) ServeListener(l net.Listener) error {
+ for {
+ conn, err := l.Accept()
+ if err != nil {
+ return err
+ }
+ glog.V(logger.Detail).Infoln("accepted conn", conn.RemoteAddr())
+ go srv.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions)
}
-
- client.conn = conn
- client.in = json.NewDecoder(conn)
- client.out = json.NewEncoder(conn)
-
- return client.out.Encode(msg)
-}
-
-// Recv will read a message from the connection and tries to parse it. It assumes the received message is JSON encoded.
-func (client *ipcClient) Recv(msg interface{}) error {
- return client.in.Decode(&msg)
-}
-
-// Close will close the underlying IPC connection
-func (client *ipcClient) Close() {
- client.conn.Close()
}
-// SupportedModules will return the collection of offered RPC modules.
-func (client *ipcClient) SupportedModules() (map[string]string, error) {
- return SupportedModules(client)
+// DialIPC create a new IPC client that connects to the given endpoint. On Unix it assumes
+// the endpoint is the full path to a unix socket, and Windows the endpoint is an
+// identifier for a named pipe.
+//
+// The context is used for the initial connection establishment. It does not
+// affect subsequent interactions with the client.
+func DialIPC(ctx context.Context, endpoint string) (*Client, error) {
+ return newClient(ctx, func(ctx context.Context) (net.Conn, error) {
+ return newIPCConnection(ctx, endpoint)
+ })
}
diff --git a/rpc/ipc_unix.go b/rpc/ipc_unix.go
index 9ece01240..a25b21627 100644
--- a/rpc/ipc_unix.go
+++ b/rpc/ipc_unix.go
@@ -22,6 +22,8 @@ import (
"net"
"os"
"path/filepath"
+
+ "golang.org/x/net/context"
)
// ipcListen will create a Unix socket on the given endpoint.
@@ -40,6 +42,6 @@ func ipcListen(endpoint string) (net.Listener, error) {
}
// newIPCConnection will connect to a Unix socket on the given endpoint.
-func newIPCConnection(endpoint string) (net.Conn, error) {
- return net.DialUnix("unix", nil, &net.UnixAddr{Name: endpoint, Net: "unix"})
+func newIPCConnection(ctx context.Context, endpoint string) (net.Conn, error) {
+ return dialContext(ctx, "unix", endpoint)
}
diff --git a/rpc/ipc_windows.go b/rpc/ipc_windows.go
index 8762cdb0d..68234d215 100644
--- a/rpc/ipc_windows.go
+++ b/rpc/ipc_windows.go
@@ -22,16 +22,27 @@ import (
"net"
"time"
- winio "github.com/microsoft/go-winio"
+ "golang.org/x/net/context"
+ "gopkg.in/natefinch/npipe.v2"
)
+// This is used if the dialing context has no deadline. It is much smaller than the
+// defaultDialTimeout because named pipes are local and there is no need to wait so long.
+const defaultPipeDialTimeout = 2 * time.Second
+
// ipcListen will create a named pipe on the given endpoint.
func ipcListen(endpoint string) (net.Listener, error) {
- return winio.ListenPipe(endpoint, &winio.PipeConfig{})
+ return npipe.Listen(endpoint)
}
// newIPCConnection will connect to a named pipe with the given endpoint as name.
-func newIPCConnection(endpoint string) (net.Conn, error) {
- timeout := 5 * time.Second
- return winio.DialPipe(endpoint, &timeout)
+func newIPCConnection(ctx context.Context, endpoint string) (net.Conn, error) {
+ timeout := defaultPipeDialTimeout
+ if deadline, ok := ctx.Deadline(); ok {
+ timeout = deadline.Sub(time.Now())
+ if timeout < 0 {
+ timeout = 0
+ }
+ }
+ return npipe.DialTimeout(endpoint, timeout)
}
diff --git a/rpc/json.go b/rpc/json.go
index 151ed546e..a7053e3f5 100644
--- a/rpc/json.go
+++ b/rpc/json.go
@@ -30,49 +30,43 @@ import (
)
const (
- JSONRPCVersion = "2.0"
+ jsonrpcVersion = "2.0"
serviceMethodSeparator = "_"
subscribeMethod = "eth_subscribe"
unsubscribeMethod = "eth_unsubscribe"
notificationMethod = "eth_subscription"
)
-// JSON-RPC request
-type JSONRequest struct {
+type jsonRequest struct {
Method string `json:"method"`
Version string `json:"jsonrpc"`
Id json.RawMessage `json:"id,omitempty"`
Payload json.RawMessage `json:"params,omitempty"`
}
-// JSON-RPC response
-type JSONSuccessResponse struct {
+type jsonSuccessResponse struct {
Version string `json:"jsonrpc"`
Id interface{} `json:"id,omitempty"`
Result interface{} `json:"result"`
}
-// JSON-RPC error object
-type JSONError struct {
+type jsonError struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
-// JSON-RPC error response
-type JSONErrResponse struct {
+type jsonErrResponse struct {
Version string `json:"jsonrpc"`
Id interface{} `json:"id,omitempty"`
- Error JSONError `json:"error"`
+ Error jsonError `json:"error"`
}
-// JSON-RPC notification payload
type jsonSubscription struct {
Subscription string `json:"subscription"`
Result interface{} `json:"result,omitempty"`
}
-// JSON-RPC notification
type jsonNotification struct {
Version string `json:"jsonrpc"`
Method string `json:"method"`
@@ -91,6 +85,17 @@ type jsonCodec struct {
rw io.ReadWriteCloser // connection
}
+func (err *jsonError) Error() string {
+ if err.Message == "" {
+ return fmt.Sprintf("json-rpc error %d", err.Code)
+ }
+ return err.Message
+}
+
+func (err *jsonError) ErrorCode() int {
+ return err.Code
+}
+
// NewJSONCodec creates a new RPC server codec with support for JSON-RPC 2.0
func NewJSONCodec(rwc io.ReadWriteCloser) ServerCodec {
d := json.NewDecoder(rwc)
@@ -113,7 +118,7 @@ func isBatch(msg json.RawMessage) bool {
// ReadRequestHeaders will read new requests without parsing the arguments. It will
// return a collection of requests, an indication if these requests are in batch
// form or an error when the incoming message could not be read/parsed.
-func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, RPCError) {
+func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, Error) {
c.decMu.Lock()
defer c.decMu.Unlock()
@@ -148,8 +153,8 @@ func checkReqId(reqId json.RawMessage) error {
// parseRequest will parse a single request from the given RawMessage. It will return
// the parsed request, an indication if the request was a batch or an error when
// the request could not be parsed.
-func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) {
- var in JSONRequest
+func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) {
+ var in jsonRequest
if err := json.Unmarshal(incomingMsg, &in); err != nil {
return nil, false, &invalidMessageError{err.Error()}
}
@@ -182,12 +187,12 @@ func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) {
method: unsubscribeMethod, params: in.Payload}}, false, nil
}
- // regular RPC call
elems := strings.Split(in.Method, serviceMethodSeparator)
if len(elems) != 2 {
return nil, false, &methodNotFoundError{in.Method, ""}
}
+ // regular RPC call
if len(in.Payload) == 0 {
return []rpcRequest{rpcRequest{service: elems[0], method: elems[1], id: &in.Id}}, false, nil
}
@@ -197,8 +202,8 @@ func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) {
// parseBatchRequest will parse a batch request into a collection of requests from the given RawMessage, an indication
// if the request was a batch or an error when the request could not be read.
-func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) {
- var in []JSONRequest
+func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) {
+ var in []jsonRequest
if err := json.Unmarshal(incomingMsg, &in); err != nil {
return nil, false, &invalidMessageError{err.Error()}
}
@@ -236,15 +241,15 @@ func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCErro
continue
}
- elems := strings.Split(r.Method, serviceMethodSeparator)
- if len(elems) != 2 {
- return nil, true, &methodNotFoundError{r.Method, ""}
- }
-
if len(r.Payload) == 0 {
- requests[i] = rpcRequest{service: elems[0], method: elems[1], id: id, params: nil}
+ requests[i] = rpcRequest{id: id, params: nil}
+ } else {
+ requests[i] = rpcRequest{id: id, params: r.Payload}
+ }
+ if elem := strings.Split(r.Method, serviceMethodSeparator); len(elem) == 2 {
+ requests[i].service, requests[i].method = elem[0], elem[1]
} else {
- requests[i] = rpcRequest{service: elems[0], method: elems[1], id: id, params: r.Payload}
+ requests[i].err = &methodNotFoundError{r.Method, ""}
}
}
@@ -253,7 +258,7 @@ func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCErro
// ParseRequestArguments tries to parse the given params (json.RawMessage) with the given types. It returns the parsed
// values or an error when the parsing failed.
-func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, RPCError) {
+func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) {
if args, ok := params.(json.RawMessage); !ok {
return nil, &invalidParamsError{"Invalid params supplied"}
} else {
@@ -264,7 +269,7 @@ func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interf
// parsePositionalArguments tries to parse the given args to an array of values with the given types.
// It returns the parsed values or an error when the args could not be parsed. Missing optional arguments
// are returned as reflect.Zero values.
-func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) ([]reflect.Value, RPCError) {
+func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) ([]reflect.Value, Error) {
params := make([]interface{}, 0, len(callbackArgs))
for _, t := range callbackArgs {
params = append(params, reflect.New(t).Interface())
@@ -302,31 +307,31 @@ func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type)
// CreateResponse will create a JSON-RPC success response with the given id and reply as result.
func (c *jsonCodec) CreateResponse(id interface{}, reply interface{}) interface{} {
if isHexNum(reflect.TypeOf(reply)) {
- return &JSONSuccessResponse{Version: JSONRPCVersion, Id: id, Result: fmt.Sprintf(`%#x`, reply)}
+ return &jsonSuccessResponse{Version: jsonrpcVersion, Id: id, Result: fmt.Sprintf(`%#x`, reply)}
}
- return &JSONSuccessResponse{Version: JSONRPCVersion, Id: id, Result: reply}
+ return &jsonSuccessResponse{Version: jsonrpcVersion, Id: id, Result: reply}
}
// CreateErrorResponse will create a JSON-RPC error response with the given id and error.
-func (c *jsonCodec) CreateErrorResponse(id interface{}, err RPCError) interface{} {
- return &JSONErrResponse{Version: JSONRPCVersion, Id: id, Error: JSONError{Code: err.Code(), Message: err.Error()}}
+func (c *jsonCodec) CreateErrorResponse(id interface{}, err Error) interface{} {
+ return &jsonErrResponse{Version: jsonrpcVersion, Id: id, Error: jsonError{Code: err.ErrorCode(), Message: err.Error()}}
}
// CreateErrorResponseWithInfo will create a JSON-RPC error response with the given id and error.
// info is optional and contains additional information about the error. When an empty string is passed it is ignored.
-func (c *jsonCodec) CreateErrorResponseWithInfo(id interface{}, err RPCError, info interface{}) interface{} {
- return &JSONErrResponse{Version: JSONRPCVersion, Id: id,
- Error: JSONError{Code: err.Code(), Message: err.Error(), Data: info}}
+func (c *jsonCodec) CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{} {
+ return &jsonErrResponse{Version: jsonrpcVersion, Id: id,
+ Error: jsonError{Code: err.ErrorCode(), Message: err.Error(), Data: info}}
}
// CreateNotification will create a JSON-RPC notification with the given subscription id and event as params.
func (c *jsonCodec) CreateNotification(subid string, event interface{}) interface{} {
if isHexNum(reflect.TypeOf(event)) {
- return &jsonNotification{Version: JSONRPCVersion, Method: notificationMethod,
+ return &jsonNotification{Version: jsonrpcVersion, Method: notificationMethod,
Params: jsonSubscription{Subscription: subid, Result: fmt.Sprintf(`%#x`, event)}}
}
- return &jsonNotification{Version: JSONRPCVersion, Method: notificationMethod,
+ return &jsonNotification{Version: jsonrpcVersion, Method: notificationMethod,
Params: jsonSubscription{Subscription: subid, Result: event}}
}
diff --git a/rpc/notification.go b/rpc/notification.go
index e84e26a58..875433071 100644
--- a/rpc/notification.go
+++ b/rpc/notification.go
@@ -28,7 +28,7 @@ import (
var (
// ErrNotificationsUnsupported is returned when the connection doesn't support notifications
- ErrNotificationsUnsupported = errors.New("notifications not supported")
+ ErrNotificationsUnsupported = errors.New("subscription notifications not supported by the current transport")
// ErrNotificationNotFound is returned when the notification for the given id is not found
ErrNotificationNotFound = errors.New("notification not found")
diff --git a/rpc/notification_test.go b/rpc/notification_test.go
index 1bcede177..280503222 100644
--- a/rpc/notification_test.go
+++ b/rpc/notification_test.go
@@ -19,20 +19,31 @@ package rpc
import (
"encoding/json"
"net"
+ "sync"
"testing"
"time"
"golang.org/x/net/context"
)
-type NotificationTestService struct{}
+type NotificationTestService struct {
+ mu sync.Mutex
+ unsubscribed bool
-var (
- unsubCallbackCalled = false
-)
+ gotHangSubscriptionReq chan struct{}
+ unblockHangSubscription chan struct{}
+}
+
+func (s *NotificationTestService) wasUnsubCallbackCalled() bool {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.unsubscribed
+}
func (s *NotificationTestService) Unsubscribe(subid string) {
- unsubCallbackCalled = true
+ s.mu.Lock()
+ s.unsubscribed = true
+ s.mu.Unlock()
}
func (s *NotificationTestService) SomeSubscription(ctx context.Context, n, val int) (Subscription, error) {
@@ -60,6 +71,26 @@ func (s *NotificationTestService) SomeSubscription(ctx context.Context, n, val i
return subscription, nil
}
+// HangSubscription blocks on s.unblockHangSubscription before
+// sending anything.
+func (s *NotificationTestService) HangSubscription(ctx context.Context, val int) (Subscription, error) {
+ notifier, supported := NotifierFromContext(ctx)
+ if !supported {
+ return nil, ErrNotificationsUnsupported
+ }
+
+ s.gotHangSubscriptionReq <- struct{}{}
+ <-s.unblockHangSubscription
+ subscription, err := notifier.NewSubscription(s.Unsubscribe)
+ if err != nil {
+ return nil, err
+ }
+ go func() {
+ subscription.Notify(val)
+ }()
+ return subscription, nil
+}
+
func TestNotifications(t *testing.T) {
server := NewServer()
service := &NotificationTestService{}
@@ -90,7 +121,7 @@ func TestNotifications(t *testing.T) {
}
var subid string
- response := JSONSuccessResponse{Result: subid}
+ response := jsonSuccessResponse{Result: subid}
if err := in.Decode(&response); err != nil {
t.Fatal(err)
}
@@ -114,7 +145,7 @@ func TestNotifications(t *testing.T) {
clientConn.Close() // causes notification unsubscribe callback to be called
time.Sleep(1 * time.Second)
- if !unsubCallbackCalled {
+ if !service.wasUnsubCallbackCalled() {
t.Error("unsubscribe callback not called after closing connection")
}
}
diff --git a/rpc/server.go b/rpc/server.go
index 7b7d22063..040805a5c 100644
--- a/rpc/server.go
+++ b/rpc/server.go
@@ -21,7 +21,6 @@ import (
"reflect"
"runtime"
"sync/atomic"
- "time"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
@@ -30,8 +29,6 @@ import (
)
const (
- stopPendingRequestTimeout = 3 * time.Second // give pending requests stopPendingRequestTimeout the time to finish when the server is stopped
-
notificationBufferSize = 10000 // max buffered notifications before codec is closed
MetadataApi = "rpc"
@@ -183,7 +180,7 @@ func (s *Server) serveRequest(codec ServerCodec, singleShot bool, options CodecO
for atomic.LoadInt32(&s.run) == 1 {
reqs, batch, err := s.readRequest(codec)
if err != nil {
- glog.V(logger.Debug).Infof("%v\n", err)
+ glog.V(logger.Debug).Infof("read error %v\n", err)
codec.Write(codec.CreateErrorResponse(nil, err))
return nil
}
@@ -240,13 +237,11 @@ func (s *Server) ServeSingleRequest(codec ServerCodec, options CodecOption) {
func (s *Server) Stop() {
if atomic.CompareAndSwapInt32(&s.run, 1, 0) {
glog.V(logger.Debug).Infoln("RPC Server shutdown initiatied")
- time.AfterFunc(stopPendingRequestTimeout, func() {
- s.codecsMu.Lock()
- defer s.codecsMu.Unlock()
- s.codecs.Each(func(c interface{}) bool {
- c.(ServerCodec).Close()
- return true
- })
+ s.codecsMu.Lock()
+ defer s.codecsMu.Unlock()
+ s.codecs.Each(func(c interface{}) bool {
+ c.(ServerCodec).Close()
+ return true
})
}
}
@@ -386,7 +381,7 @@ func (s *Server) execBatch(ctx context.Context, codec ServerCodec, requests []*s
// readRequest requests the next (batch) request from the codec. It will return the collection
// of requests, an indication if the request was a batch, the invalid request identifier and an
// error when the request could not be read/parsed.
-func (s *Server) readRequest(codec ServerCodec) ([]*serverRequest, bool, RPCError) {
+func (s *Server) readRequest(codec ServerCodec) ([]*serverRequest, bool, Error) {
reqs, batch, err := codec.ReadRequestHeaders()
if err != nil {
return nil, batch, err
@@ -399,6 +394,11 @@ func (s *Server) readRequest(codec ServerCodec) ([]*serverRequest, bool, RPCErro
var ok bool
var svc *service
+ if r.err != nil {
+ requests[i] = &serverRequest{id: r.id, err: r.err}
+ continue
+ }
+
if r.isPubSub && r.method == unsubscribeMethod {
requests[i] = &serverRequest{id: r.id, isUnsubscribe: true}
argTypes := []reflect.Type{reflect.TypeOf("")} // expect subscription id as first arg
diff --git a/rpc/server_test.go b/rpc/server_test.go
index de47e1afd..e6840bde4 100644
--- a/rpc/server_test.go
+++ b/rpc/server_test.go
@@ -21,6 +21,7 @@ import (
"net"
"reflect"
"testing"
+ "time"
"golang.org/x/net/context"
)
@@ -48,6 +49,13 @@ func (s *Service) EchoWithCtx(ctx context.Context, str string, i int, args *Args
return Result{str, i, args}
}
+func (s *Service) Sleep(ctx context.Context, duration time.Duration) {
+ select {
+ case <-time.After(duration):
+ case <-ctx.Done():
+ }
+}
+
func (s *Service) Rets() (string, error) {
return "", nil
}
@@ -85,8 +93,8 @@ func TestServerRegisterName(t *testing.T) {
t.Fatalf("Expected service calc to be registered")
}
- if len(svc.callbacks) != 4 {
- t.Errorf("Expected 4 callbacks for service 'calc', got %d", len(svc.callbacks))
+ if len(svc.callbacks) != 5 {
+ t.Errorf("Expected 5 callbacks for service 'calc', got %d", len(svc.callbacks))
}
if len(svc.subscriptions) != 1 {
@@ -126,7 +134,7 @@ func testServerMethodExecution(t *testing.T, method string) {
t.Fatal(err)
}
- response := JSONSuccessResponse{Result: &Result{}}
+ response := jsonSuccessResponse{Result: &Result{}}
if err := in.Decode(&response); err != nil {
t.Fatal(err)
}
diff --git a/rpc/types.go b/rpc/types.go
index a1f36fbd2..2a7268ad8 100644
--- a/rpc/types.go
+++ b/rpc/types.go
@@ -62,7 +62,7 @@ type serverRequest struct {
callb *callback
args []reflect.Value
isUnsubscribe bool
- err RPCError
+ err Error
}
type serviceRegistry map[string]*service // collection of services
@@ -88,14 +88,13 @@ type rpcRequest struct {
id interface{}
isPubSub bool
params interface{}
+ err Error // invalid batch element
}
-// RPCError implements RPC error, is add support for error codec over regular go errors
-type RPCError interface {
- // RPC error code
- Code() int
- // Error message
- Error() string
+// Error wraps RPC errors, which contain an error code in addition to the message.
+type Error interface {
+ Error() string // returns the message
+ ErrorCode() int // returns the code
}
// ServerCodec implements reading, parsing and writing RPC messages for the server side of
@@ -103,15 +102,15 @@ type RPCError interface {
// multiple go-routines concurrently.
type ServerCodec interface {
// Read next request
- ReadRequestHeaders() ([]rpcRequest, bool, RPCError)
+ ReadRequestHeaders() ([]rpcRequest, bool, Error)
// Parse request argument to the given types
- ParseRequestArguments([]reflect.Type, interface{}) ([]reflect.Value, RPCError)
+ ParseRequestArguments([]reflect.Type, interface{}) ([]reflect.Value, Error)
// Assemble success response, expects response id and payload
CreateResponse(interface{}, interface{}) interface{}
// Assemble error response, expects response id and error
- CreateErrorResponse(interface{}, RPCError) interface{}
+ CreateErrorResponse(interface{}, Error) interface{}
// Assemble error response with extra information about the error through info
- CreateErrorResponseWithInfo(id interface{}, err RPCError, info interface{}) interface{}
+ CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{}
// Create notification response
CreateNotification(string, interface{}) interface{}
// Write msg to client.
@@ -273,14 +272,3 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
func (bn *BlockNumber) Int64() int64 {
return (int64)(*bn)
}
-
-// Client defines the interface for go client that wants to connect to a geth RPC endpoint
-type Client interface {
- // SupportedModules returns the collection of API's the server offers
- SupportedModules() (map[string]string, error)
-
- Send(req interface{}) error
- Recv(msg interface{}) error
-
- Close()
-}
diff --git a/rpc/utils.go b/rpc/utils.go
index fe482e19d..1ac6698f5 100644
--- a/rpc/utils.go
+++ b/rpc/utils.go
@@ -20,7 +20,6 @@ import (
"crypto/rand"
"encoding/hex"
"errors"
- "fmt"
"math/big"
"reflect"
"unicode"
@@ -227,31 +226,3 @@ func newSubscriptionID() (string, error) {
}
return "0x" + hex.EncodeToString(subid[:]), nil
}
-
-// SupportedModules returns the collection of API's that the RPC server offers
-// on which the given client connects.
-func SupportedModules(client Client) (map[string]string, error) {
- req := JSONRequest{
- Id: []byte("1"),
- Version: "2.0",
- Method: MetadataApi + "_modules",
- }
- if err := client.Send(req); err != nil {
- return nil, err
- }
-
- var response JSONSuccessResponse
- if err := client.Recv(&response); err != nil {
- return nil, err
- }
- if response.Result != nil {
- mods := make(map[string]string)
- if modules, ok := response.Result.(map[string]interface{}); ok {
- for m, v := range modules {
- mods[m] = fmt.Sprintf("%s", v)
- }
- return mods, nil
- }
- }
- return nil, fmt.Errorf("unable to retrieve modules")
-}
diff --git a/rpc/websocket.go b/rpc/websocket.go
index fe9354d94..fc3cd0709 100644
--- a/rpc/websocket.go
+++ b/rpc/websocket.go
@@ -17,36 +17,39 @@
package rpc
import (
+ "crypto/tls"
"fmt"
+ "net"
"net/http"
+ "net/url"
"os"
"strings"
- "sync"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
+ "golang.org/x/net/context"
"golang.org/x/net/websocket"
"gopkg.in/fatih/set.v0"
)
-// wsReaderWriterCloser reads and write payloads from and to a websocket connection.
-type wsReaderWriterCloser struct {
- c *websocket.Conn
-}
-
-// Read will read incoming payload data into p.
-func (rw *wsReaderWriterCloser) Read(p []byte) (int, error) {
- return rw.c.Read(p)
-}
-
-// Write writes p to the websocket.
-func (rw *wsReaderWriterCloser) Write(p []byte) (int, error) {
- return rw.c.Write(p)
+// WebsocketHandler returns a handler that serves JSON-RPC to WebSocket connections.
+//
+// allowedOrigins should be a comma-separated list of allowed origin URLs.
+// To allow connections with any origin, pass "*".
+func (srv *Server) WebsocketHandler(allowedOrigins string) http.Handler {
+ return websocket.Server{
+ Handshake: wsHandshakeValidator(strings.Split(allowedOrigins, ",")),
+ Handler: func(conn *websocket.Conn) {
+ srv.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions)
+ },
+ }
}
-// Close closes the websocket connection.
-func (rw *wsReaderWriterCloser) Close() error {
- return rw.c.Close()
+// NewWSServer creates a new websocket RPC server around an API provider.
+//
+// Deprecated: use Server.WebsocketHandler
+func NewWSServer(allowedOrigins string, srv *Server) *http.Server {
+ return &http.Server{Handler: srv.WebsocketHandler(allowedOrigins)}
}
// wsHandshakeValidator returns a handler that verifies the origin during the
@@ -87,96 +90,63 @@ func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http
return f
}
-// NewWSServer creates a new websocket RPC server around an API provider.
-func NewWSServer(allowedOrigins string, handler *Server) *http.Server {
- return &http.Server{
- Handler: websocket.Server{
- Handshake: wsHandshakeValidator(strings.Split(allowedOrigins, ",")),
- Handler: func(conn *websocket.Conn) {
- handler.ServeCodec(NewJSONCodec(&wsReaderWriterCloser{conn}),
- OptionMethodInvocation|OptionSubscriptions)
- },
- },
+// DialWebsocket creates a new RPC client that communicates with a JSON-RPC server
+// that is listening on the given endpoint.
+//
+// The context is used for the initial connection establishment. It does not
+// affect subsequent interactions with the client.
+func DialWebsocket(ctx context.Context, endpoint, origin string) (*Client, error) {
+ if origin == "" {
+ var err error
+ if origin, err = os.Hostname(); err != nil {
+ return nil, err
+ }
+ if strings.HasPrefix(endpoint, "wss") {
+ origin = "https://" + strings.ToLower(origin)
+ } else {
+ origin = "http://" + strings.ToLower(origin)
+ }
+ }
+ config, err := websocket.NewConfig(endpoint, origin)
+ if err != nil {
+ return nil, err
}
-}
-
-// wsClient represents a RPC client that communicates over websockets with a
-// RPC server.
-type wsClient struct {
- endpoint string
- connMu sync.Mutex
- conn *websocket.Conn
-}
-// NewWSClientj creates a new RPC client that communicates with a RPC server
-// that is listening on the given endpoint using JSON encoding.
-func NewWSClient(endpoint string) (Client, error) {
- return &wsClient{endpoint: endpoint}, nil
+ return newClient(ctx, func(ctx context.Context) (net.Conn, error) {
+ return wsDialContext(ctx, config)
+ })
}
-// connection will return a websocket connection to the RPC server. It will
-// (re)connect when necessary.
-func (client *wsClient) connection() (*websocket.Conn, error) {
- if client.conn != nil {
- return client.conn, nil
+func wsDialContext(ctx context.Context, config *websocket.Config) (*websocket.Conn, error) {
+ var conn net.Conn
+ var err error
+ switch config.Location.Scheme {
+ case "ws":
+ conn, err = dialContext(ctx, "tcp", wsDialAddress(config.Location))
+ case "wss":
+ dialer := contextDialer(ctx)
+ conn, err = tls.DialWithDialer(dialer, "tcp", wsDialAddress(config.Location), config.TlsConfig)
+ default:
+ err = websocket.ErrBadScheme
}
-
- origin, err := os.Hostname()
if err != nil {
return nil, err
}
-
- origin = "http://" + origin
- client.conn, err = websocket.Dial(client.endpoint, "", origin)
-
- return client.conn, err
-}
-
-// SupportedModules is the collection of modules the RPC server offers.
-func (client *wsClient) SupportedModules() (map[string]string, error) {
- return SupportedModules(client)
-}
-
-// Send writes the JSON serialized msg to the websocket. It will create a new
-// websocket connection to the server if the client is currently not connected.
-func (client *wsClient) Send(msg interface{}) (err error) {
- client.connMu.Lock()
- defer client.connMu.Unlock()
-
- var conn *websocket.Conn
- if conn, err = client.connection(); err == nil {
- if err = websocket.JSON.Send(conn, msg); err != nil {
- client.conn.Close()
- client.conn = nil
- }
+ ws, err := websocket.NewClient(config, conn)
+ if err != nil {
+ conn.Close()
+ return nil, err
}
-
- return err
+ return ws, err
}
-// Recv reads a JSON message from the websocket and unmarshals it into msg.
-func (client *wsClient) Recv(msg interface{}) (err error) {
- client.connMu.Lock()
- defer client.connMu.Unlock()
+var wsPortMap = map[string]string{"ws": "80", "wss": "443"}
- var conn *websocket.Conn
- if conn, err = client.connection(); err == nil {
- if err = websocket.JSON.Receive(conn, msg); err != nil {
- client.conn.Close()
- client.conn = nil
+func wsDialAddress(location *url.URL) string {
+ if _, ok := wsPortMap[location.Scheme]; ok {
+ if _, _, err := net.SplitHostPort(location.Host); err != nil {
+ return net.JoinHostPort(location.Host, wsPortMap[location.Scheme])
}
}
- return
-}
-
-// Close closes the underlaying websocket connection.
-func (client *wsClient) Close() {
- client.connMu.Lock()
- defer client.connMu.Unlock()
-
- if client.conn != nil {
- client.conn.Close()
- client.conn = nil
- }
-
+ return location.Host
}
diff --git a/tests/block_test.go b/tests/block_test.go
index c258268db..448f2bd76 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -23,63 +23,63 @@ import (
)
func TestBcValidBlockTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcUncleHeaderValidityTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcUncleTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcForkUncleTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcInvalidHeaderTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcInvalidRLPTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcRPCAPITests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcForkBlockTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcForkStress(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
@@ -89,21 +89,21 @@ func TestBcTotalDifficulty(t *testing.T) {
// skip because these will fail due to selfish mining fix
t.Skip()
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcWallet(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcGasPricer(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
@@ -111,7 +111,7 @@ func TestBcGasPricer(t *testing.T) {
// TODO: iterate over files once we got more than a few
func TestBcRandom(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
@@ -121,14 +121,14 @@ func TestBcMultiChain(t *testing.T) {
// skip due to selfish mining
t.Skip()
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcState(t *testing.T) {
- err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
@@ -136,77 +136,85 @@ func TestBcState(t *testing.T) {
// Homestead tests
func TestHomesteadBcValidBlockTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcUncleTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcRPCAPITests(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcForkStress(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcTotalDifficulty(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcWallet(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcGasPricer(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcMultiChain(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcState(t *testing.T) {
- err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
+ err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+// DAO hard-fork tests
+func TestDAOBcTheDao(t *testing.T) {
+ err := RunBlockTest(big.NewInt(5), big.NewInt(8), filepath.Join(blockTestDir, "TestNetwork", "bcTheDaoTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index d9a5eec08..7da15cebe 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -103,7 +103,7 @@ type btTransaction struct {
Value string
}
-func RunBlockTestWithReader(homesteadBlock *big.Int, r io.Reader, skipTests []string) error {
+func RunBlockTestWithReader(homesteadBlock, daoForkBlock *big.Int, r io.Reader, skipTests []string) error {
btjs := make(map[string]*btJSON)
if err := readJson(r, &btjs); err != nil {
return err
@@ -114,13 +114,13 @@ func RunBlockTestWithReader(homesteadBlock *big.Int, r io.Reader, skipTests []st
return err
}
- if err := runBlockTests(homesteadBlock, bt, skipTests); err != nil {
+ if err := runBlockTests(homesteadBlock, daoForkBlock, bt, skipTests); err != nil {
return err
}
return nil
}
-func RunBlockTest(homesteadBlock *big.Int, file string, skipTests []string) error {
+func RunBlockTest(homesteadBlock, daoForkBlock *big.Int, file string, skipTests []string) error {
btjs := make(map[string]*btJSON)
if err := readJsonFile(file, &btjs); err != nil {
return err
@@ -130,13 +130,13 @@ func RunBlockTest(homesteadBlock *big.Int, file string, skipTests []string) erro
if err != nil {
return err
}
- if err := runBlockTests(homesteadBlock, bt, skipTests); err != nil {
+ if err := runBlockTests(homesteadBlock, daoForkBlock, bt, skipTests); err != nil {
return err
}
return nil
}
-func runBlockTests(homesteadBlock *big.Int, bt map[string]*BlockTest, skipTests []string) error {
+func runBlockTests(homesteadBlock, daoForkBlock *big.Int, bt map[string]*BlockTest, skipTests []string) error {
skipTest := make(map[string]bool, len(skipTests))
for _, name := range skipTests {
skipTest[name] = true
@@ -148,7 +148,7 @@ func runBlockTests(homesteadBlock *big.Int, bt map[string]*BlockTest, skipTests
continue
}
// test the block
- if err := runBlockTest(homesteadBlock, test); err != nil {
+ if err := runBlockTest(homesteadBlock, daoForkBlock, test); err != nil {
return fmt.Errorf("%s: %v", name, err)
}
glog.Infoln("Block test passed: ", name)
@@ -157,7 +157,7 @@ func runBlockTests(homesteadBlock *big.Int, bt map[string]*BlockTest, skipTests
return nil
}
-func runBlockTest(homesteadBlock *big.Int, test *BlockTest) error {
+func runBlockTest(homesteadBlock, daoForkBlock *big.Int, test *BlockTest) error {
// import pre accounts & construct test genesis block & state root
db, _ := ethdb.NewMemDatabase()
if _, err := test.InsertPreState(db); err != nil {
@@ -169,7 +169,7 @@ func runBlockTest(homesteadBlock *big.Int, test *BlockTest) error {
core.WriteCanonicalHash(db, test.Genesis.Hash(), test.Genesis.NumberU64())
core.WriteHeadBlockHash(db, test.Genesis.Hash())
evmux := new(event.TypeMux)
- config := &core.ChainConfig{HomesteadBlock: homesteadBlock}
+ config := &core.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true}
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux)
if err != nil {
return err
diff --git a/tests/files/BlockchainTests/TestNetwork/bcTheDaoTest.json b/tests/files/BlockchainTests/TestNetwork/bcTheDaoTest.json
new file mode 100644
index 000000000..ad01b82d1
--- /dev/null
+++ b/tests/files/BlockchainTests/TestNetwork/bcTheDaoTest.json
@@ -0,0 +1,8599 @@
+{
+ "DaoTransactions" : {
+ "blocks" : [
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "0bf4b15cb25eccec0a0706fc625c525be7da876bd7a8bf60baa8d9e1bce126d3",
+ "mixHash" : "22ffe16d1d516b8d15428b2347fe62901a12fa4977945b1ae8ced773c27e6755",
+ "nonce" : "f51d5dc330f2df67",
+ "number" : "0x01",
+ "parentHash" : "cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09",
+ "receiptTrie" : "37aee413d1d4f1335720ed1ee882bac4b2d41c8072453b23445020c951682054",
+ "stateRoot" : "d3f60d7c23e6d3e8eeaa691dd6d54b653e9d33ce579ed821a1e408c1e89cf01a",
+ "timestamp" : "0x5788dc1d",
+ "transactionsTrie" : "ac81275d7a81a720240146377982939179218535bfcfa9469c8bdd3e264ef179",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "1",
+ "rlp" : "0xf9024cf901f9a0cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0d3f60d7c23e6d3e8eeaa691dd6d54b653e9d33ce579ed821a1e408c1e89cf01aa0ac81275d7a81a720240146377982939179218535bfcfa9469c8bdd3e264ef179a037aee413d1d4f1335720ed1ee882bac4b2d41c8072453b23445020c951682054b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba825208845788dc1d80a022ffe16d1d516b8d15428b2347fe62901a12fa4977945b1ae8ced773c27e675588f51d5dc330f2df67f84df84b8001827530800a801ca057cb46c0b702929c4fd4127b2370f28a7aeeaa65509699e58eedf7692090a0a9a05ba7c83d99be6a9bca0c81947023ba3b5f2162516d82d0757bf8004f3e9bc03ac0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x00",
+ "r" : "0x57cb46c0b702929c4fd4127b2370f28a7aeeaa65509699e58eedf7692090a0a9",
+ "s" : "0x5ba7c83d99be6a9bca0c81947023ba3b5f2162516d82d0757bf8004f3e9bc03a",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020040",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "ce3ecad2a028ecd1d70c3c4683c1f74d8c521dfdc7cde9bb3857e1740e914402",
+ "mixHash" : "07d75cbc66143f80cb0b7ed64d88ff9789d1cb72f7701cbc8b5d4a3940610058",
+ "nonce" : "82a2b2eb85f7ad3c",
+ "number" : "0x02",
+ "parentHash" : "0bf4b15cb25eccec0a0706fc625c525be7da876bd7a8bf60baa8d9e1bce126d3",
+ "receiptTrie" : "9a62bdf5dbcf4d27f17a31d5506d3249c5a6ca549787b1902ba01584bb33cf64",
+ "stateRoot" : "c97eb33ff96a24bd16aaa76040aff370a690e6e52f0172eba3a436d7c867a988",
+ "timestamp" : "0x5788dc28",
+ "transactionsTrie" : "76c7a0ce7644661f276c76fb9a82eaee879d0642cf4ed244fc10afc02c646abf",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "2",
+ "rlp" : "0xf9024cf901f9a00bf4b15cb25eccec0a0706fc625c525be7da876bd7a8bf60baa8d9e1bce126d3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c97eb33ff96a24bd16aaa76040aff370a690e6e52f0172eba3a436d7c867a988a076c7a0ce7644661f276c76fb9a82eaee879d0642cf4ed244fc10afc02c646abfa09a62bdf5dbcf4d27f17a31d5506d3249c5a6ca549787b1902ba01584bb33cf64b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefba825208845788dc2880a007d75cbc66143f80cb0b7ed64d88ff9789d1cb72f7701cbc8b5d4a39406100588882a2b2eb85f7ad3cf84df84b0101827530800a801ca0bb6e3cf3f281af13ef1393d7052b03cab367079a9eb71aa829ec72b231a60e1fa04bcfe1da53f26bb95806d38e9f42fef262aaaf5191e16ec473a695c8978a0b05c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x01",
+ "r" : "0xbb6e3cf3f281af13ef1393d7052b03cab367079a9eb71aa829ec72b231a60e1f",
+ "s" : "0x4bcfe1da53f26bb95806d38e9f42fef262aaaf5191e16ec473a695c8978a0b05",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020080",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "3c6ffdf610c30eab3de8cb9ee5ca2218659c998f5996b971016031464dba78c7",
+ "mixHash" : "3df8b7976e1892e74ef5d6cf859b1436d89454800d7bca1f9d3bbde6cf828d9f",
+ "nonce" : "159e3b259feea379",
+ "number" : "0x03",
+ "parentHash" : "ce3ecad2a028ecd1d70c3c4683c1f74d8c521dfdc7cde9bb3857e1740e914402",
+ "receiptTrie" : "b9ca869c5641896a8e22fe74b4225c6a43cbc3303b24d13e0af94517180c8097",
+ "stateRoot" : "9cb74b15edd72a2075b114d9154f4bbdf784054658912024747ea9423e0d2af8",
+ "timestamp" : "0x5788dc2a",
+ "transactionsTrie" : "3798aa164b61e27b93484c76a5f319bd93c808dc78ef31cf8b93f4e1b248ca2c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "3",
+ "rlp" : "0xf9024cf901f9a0ce3ecad2a028ecd1d70c3c4683c1f74d8c521dfdc7cde9bb3857e1740e914402a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a09cb74b15edd72a2075b114d9154f4bbdf784054658912024747ea9423e0d2af8a03798aa164b61e27b93484c76a5f319bd93c808dc78ef31cf8b93f4e1b248ca2ca0b9ca869c5641896a8e22fe74b4225c6a43cbc3303b24d13e0af94517180c8097b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba825208845788dc2a80a03df8b7976e1892e74ef5d6cf859b1436d89454800d7bca1f9d3bbde6cf828d9f88159e3b259feea379f84df84b0201827530800a801ca0f6d884cae1f86bdff1281e95e416089c544a4a5578a75d5e8ad76118e341b055a075b7d88985ed5acd61f30c9f9570c6c33bb92f3ad1a32b86a0747817fbc5ededc0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x02",
+ "r" : "0xf6d884cae1f86bdff1281e95e416089c544a4a5578a75d5e8ad76118e341b055",
+ "s" : "0x75b7d88985ed5acd61f30c9f9570c6c33bb92f3ad1a32b86a0747817fbc5eded",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x0200c0",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "9f33c42c79dd227e07cd7333ec5beabfa4f628abb778f94073e7dcf623c4f6c9",
+ "mixHash" : "d88ae9006c4143fd0de18950ef90ebe42037502c338eac1154ce21d45375b287",
+ "nonce" : "8647150d7bfbe0cd",
+ "number" : "0x04",
+ "parentHash" : "3c6ffdf610c30eab3de8cb9ee5ca2218659c998f5996b971016031464dba78c7",
+ "receiptTrie" : "d69ea0fac668bb7ece043f8e6ac833c5d10a7d5bf08ebfe40a8dc1721a3aa4fd",
+ "stateRoot" : "aeaa38b30cbc02db5cd17a91e9212346cd839fafcb1fc06126cf64b5b782b877",
+ "timestamp" : "0x5788dc31",
+ "transactionsTrie" : "4cc1b34b3a9d29bf69842a54e1c48bc97afc433883f66d2c59287f118c9c3c2c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "4",
+ "rlp" : "0xf9024cf901f9a03c6ffdf610c30eab3de8cb9ee5ca2218659c998f5996b971016031464dba78c7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0aeaa38b30cbc02db5cd17a91e9212346cd839fafcb1fc06126cf64b5b782b877a04cc1b34b3a9d29bf69842a54e1c48bc97afc433883f66d2c59287f118c9c3c2ca0d69ea0fac668bb7ece043f8e6ac833c5d10a7d5bf08ebfe40a8dc1721a3aa4fdb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200c004832fefba825208845788dc3180a0d88ae9006c4143fd0de18950ef90ebe42037502c338eac1154ce21d45375b287888647150d7bfbe0cdf84df84b0301827530800a801ca0753ee5d896db8d87fe850e7935418587277cd9c010dfaaf7dd09b0a2e73785dca066deb3c241d532c7b880ae7a9a311ee7a92ef1c5e4e2bf3307990a2881bc13b0c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x03",
+ "r" : "0x753ee5d896db8d87fe850e7935418587277cd9c010dfaaf7dd09b0a2e73785dc",
+ "s" : "0x66deb3c241d532c7b880ae7a9a311ee7a92ef1c5e4e2bf3307990a2881bc13b0",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020100",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xcf08",
+ "hash" : "341d9eae5bd8696e5e8c4e445cd36ff60a85d9c43ef94df01fbef0ec2ff7125f",
+ "mixHash" : "ec72429dc3f952b9c7bb2ad9f5b23f8cd23015bdf9cee1258c817a15da6b4a8a",
+ "nonce" : "a21bef974871f679",
+ "number" : "0x05",
+ "parentHash" : "9f33c42c79dd227e07cd7333ec5beabfa4f628abb778f94073e7dcf623c4f6c9",
+ "receiptTrie" : "d7f28f5ba69ca1893569465903e8d942153c57912f7d1f6b3e33088e8ad17fee",
+ "stateRoot" : "f54737efdead0a75d49cc6ceaedf75fd4aacf933e8f361a9a9c0a1647bcf6ab5",
+ "timestamp" : "0x5788dc34",
+ "transactionsTrie" : "165af780d27795ebc80c27759d3d949a9c4b05d35fcc7e9d3da8be357f5340cd",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "5",
+ "rlp" : "0xf9024cf901f9a09f33c42c79dd227e07cd7333ec5beabfa4f628abb778f94073e7dcf623c4f6c9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0f54737efdead0a75d49cc6ceaedf75fd4aacf933e8f361a9a9c0a1647bcf6ab5a0165af780d27795ebc80c27759d3d949a9c4b05d35fcc7e9d3da8be357f5340cda0d7f28f5ba69ca1893569465903e8d942153c57912f7d1f6b3e33088e8ad17feeb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302010005832fefba82cf08845788dc3480a0ec72429dc3f952b9c7bb2ad9f5b23f8cd23015bdf9cee1258c817a15da6b4a8a88a21bef974871f679f84df84b040182ea60800a801ba0cb1400f01459519ac3dc0426c6d7f95641dc6a7b8008069c9dfbe4f94b167169a07445362aadae8c25e4f0b494ad553bfc652bf34fb2ed0ccbf9a6b089c2b09f62c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x04",
+ "r" : "0xcb1400f01459519ac3dc0426c6d7f95641dc6a7b8008069c9dfbe4f94b167169",
+ "s" : "0x7445362aadae8c25e4f0b494ad553bfc652bf34fb2ed0ccbf9a6b089c2b09f62",
+ "to" : "",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020140",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xcf08",
+ "hash" : "bef208f4cf5571b952ab436a84a60934d96a81c4453aa1cd80c79d6fd61242dc",
+ "mixHash" : "ec1e3b01a1cbae6c8aa72dbefa7711c041a55c8e293a8c70653f604fa892eb3a",
+ "nonce" : "0580f086c036719d",
+ "number" : "0x06",
+ "parentHash" : "341d9eae5bd8696e5e8c4e445cd36ff60a85d9c43ef94df01fbef0ec2ff7125f",
+ "receiptTrie" : "975eeeb6e46fc2d858080444f0536a1f3a688638fdf0bcbc1958dedc5eda4405",
+ "stateRoot" : "05ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174",
+ "timestamp" : "0x5788dc38",
+ "transactionsTrie" : "ef009c3c274a522a6e2ca98232fffff747bdfab79189be3e2b5e5dc54e2a51be",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "6",
+ "rlp" : "0xf9024cf901f9a0341d9eae5bd8696e5e8c4e445cd36ff60a85d9c43ef94df01fbef0ec2ff7125fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a005ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174a0ef009c3c274a522a6e2ca98232fffff747bdfab79189be3e2b5e5dc54e2a51bea0975eeeb6e46fc2d858080444f0536a1f3a688638fdf0bcbc1958dedc5eda4405b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014006832fefba82cf08845788dc3880a0ec1e3b01a1cbae6c8aa72dbefa7711c041a55c8e293a8c70653f604fa892eb3a880580f086c036719df84df84b050182ea60800a801ba04d147b172eb81fdb11a21826eabad091084f6e9613d340b5897872843efa6435a023640d906f65fd156b92d518068263d99d94dc88c3e0950fd7633fb0d4d237eec0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x05",
+ "r" : "0x4d147b172eb81fdb11a21826eabad091084f6e9613d340b5897872843efa6435",
+ "s" : "0x23640d906f65fd156b92d518068263d99d94dc88c3e0950fd7633fb0d4d237ee",
+ "to" : "",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xa042",
+ "hash" : "9c835a5982dbd3e45af50a688075f16b3661a330c87af0f8019ca65329ca7636",
+ "mixHash" : "3943078bb0754d40ec78d9809de292aa2ec6bf5bad40d85d8da01276752db5ae",
+ "nonce" : "37f3decdc9a7e0bd",
+ "number" : "0x07",
+ "parentHash" : "bef208f4cf5571b952ab436a84a60934d96a81c4453aa1cd80c79d6fd61242dc",
+ "receiptTrie" : "aec104fc55d9aa0c1767af2dcf73c512f650f24bf89b9b78eb236d70a2de848f",
+ "stateRoot" : "40d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029",
+ "timestamp" : "0x5788dc3c",
+ "transactionsTrie" : "b2d17fa171d19df4e817ffb15f38526d125a42b7879cd712584b130dc8ad341c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "7",
+ "rlp" : "0xf90260f901f9a0bef208f4cf5571b952ab436a84a60934d96a81c4453aa1cd80c79d6fd61242dca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a040d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029a0b2d17fa171d19df4e817ffb15f38526d125a42b7879cd712584b130dc8ad341ca0aec104fc55d9aa0c1767af2dcf73c512f650f24bf89b9b78eb236d70a2de848fb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018007832fefba82a042845788dc3c80a03943078bb0754d40ec78d9809de292aa2ec6bf5bad40d85d8da01276752db5ae8837f3decdc9a7e0bdf861f85f060182ea609410000000000000000000000000000000000000070a801ba0bb8523d4c53ed16b355d0a2dba02154d23a5480449dc3894be40ef95511d2fe9a010ad725c2df4979b7a071b3fa9b6b719223f0167d68b98f213e8611f84d4d81bc0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x06",
+ "r" : "0xbb8523d4c53ed16b355d0a2dba02154d23a5480449dc3894be40ef95511d2fe9",
+ "s" : "0x10ad725c2df4979b7a071b3fa9b6b719223f0167d68b98f213e8611f84d4d81b",
+ "to" : "1000000000000000000000000000000000000007",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "8",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f070182ea609410000000000000000000000000000000000000080a801ba03bce709627e1c9340795f11cc866742a0b5ced2b7e2da53e0cfe6f5f1df0a77ea02df804cdb52edacc4e01d8632050101cf7de7b235d37c31b504010910ec8f1f6c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x65aa",
+ "hash" : "37197cab54e89c31d93dfa050c38c916efe2e8a5849b43b245305ecc450eea70",
+ "mixHash" : "1eb50717ca7b4c633ba350969235157017427af1f807946adcc61098ca98e596",
+ "nonce" : "81e6b44c39618f34",
+ "number" : "0x08",
+ "parentHash" : "9c835a5982dbd3e45af50a688075f16b3661a330c87af0f8019ca65329ca7636",
+ "receiptTrie" : "2df25a52fb0817ad3948868d59d50cab8f7f780fc5e3939b4c9140936d7bb187",
+ "stateRoot" : "8565b6c0a57e2566bb768c6c67aaad77794da4e1589966ee51bd0370a9db3d1c",
+ "timestamp" : "0x5788dc46",
+ "transactionsTrie" : "2982eb44bedb5b2484b9606fe37f966942a2cce51f0705537f9040ef0614d54e",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "8",
+ "rlp" : "0xf9026df90206a09c835a5982dbd3e45af50a688075f16b3661a330c87af0f8019ca65329ca7636a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a08565b6c0a57e2566bb768c6c67aaad77794da4e1589966ee51bd0370a9db3d1ca02982eb44bedb5b2484b9606fe37f966942a2cce51f0705537f9040ef0614d54ea02df25a52fb0817ad3948868d59d50cab8f7f780fc5e3939b4c9140936d7bb187b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018008832fefba8265aa845788dc468d64616f2d686172642d666f726ba01eb50717ca7b4c633ba350969235157017427af1f807946adcc61098ca98e5968881e6b44c39618f34f861f85f070182ea609410000000000000000000000000000000000000080a801ba03bce709627e1c9340795f11cc866742a0b5ced2b7e2da53e0cfe6f5f1df0a77ea02df804cdb52edacc4e01d8632050101cf7de7b235d37c31b504010910ec8f1f6c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x07",
+ "r" : "0x3bce709627e1c9340795f11cc866742a0b5ced2b7e2da53e0cfe6f5f1df0a77e",
+ "s" : "0x2df804cdb52edacc4e01d8632050101cf7de7b235d37c31b504010910ec8f1f6",
+ "to" : "1000000000000000000000000000000000000008",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "9",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f080182ea6094100000000000000000000000000000000000000101801ba0af2bb21c6953c5c7bb966a9c09e43c52641e6e317ab738cd409a5fb9ef5e753fa010db71dc8b41e52ce746895f743c1cc1fe7ed32f17ff7935b610fcbccdc75720c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "fcc08674a7d7b521954d2545f7d09c02ebee682ce9a2e408aa094ff254c8b772",
+ "mixHash" : "188325449fab4b060f142fad86dd35c5b9a5d09e4b3cb0da9855818c832de7ac",
+ "nonce" : "d4c9a029ed38257b",
+ "number" : "0x09",
+ "parentHash" : "37197cab54e89c31d93dfa050c38c916efe2e8a5849b43b245305ecc450eea70",
+ "receiptTrie" : "06ba5b9bbbcf94865cd9b522c4de701287f0fcb197fc2a19e54aa23d0fb20218",
+ "stateRoot" : "0eef10cd08a0a4a20df81757eeb4114a0db434c8d41e6cc35e8cf9d8c22d81c7",
+ "timestamp" : "0x5788dc51",
+ "transactionsTrie" : "7dac38119a2beeb72d0f67b77bef9a4cbae22ca5c7151f1e737f9db1bf37b135",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "9",
+ "rlp" : "0xf9026df90206a037197cab54e89c31d93dfa050c38c916efe2e8a5849b43b245305ecc450eea70a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a00eef10cd08a0a4a20df81757eeb4114a0db434c8d41e6cc35e8cf9d8c22d81c7a07dac38119a2beeb72d0f67b77bef9a4cbae22ca5c7151f1e737f9db1bf37b135a006ba5b9bbbcf94865cd9b522c4de701287f0fcb197fc2a19e54aa23d0fb20218b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018009832fefba825208845788dc518d64616f2d686172642d666f726ba0188325449fab4b060f142fad86dd35c5b9a5d09e4b3cb0da9855818c832de7ac88d4c9a029ed38257bf861f85f080182ea6094100000000000000000000000000000000000000101801ba0af2bb21c6953c5c7bb966a9c09e43c52641e6e317ab738cd409a5fb9ef5e753fa010db71dc8b41e52ce746895f743c1cc1fe7ed32f17ff7935b610fcbccdc75720c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x08",
+ "r" : "0xaf2bb21c6953c5c7bb966a9c09e43c52641e6e317ab738cd409a5fb9ef5e753f",
+ "s" : "0x10db71dc8b41e52ce746895f743c1cc1fe7ed32f17ff7935b610fcbccdc75720",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1b",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "10",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f090182ea6094100000000000000000000000000000000000000101801ca0c3d783e93561599d86cbf460e153b3cb37d90478a3c47bfc08bd29563c9d849fa0100e466f7a4c6af73a9030988c63ec88ccaba460fd6a1fb1adc30b61dbdd0857c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "5f58b34c4108e44ab7bfbfe9c70b5b86097cdff8b21ae7a990d8ed0c31a04634",
+ "mixHash" : "fd36229270002f66be02e74dcc3088b324a862e9c2797bf551a064441eb41553",
+ "nonce" : "0c81358b772e61d1",
+ "number" : "0x0a",
+ "parentHash" : "fcc08674a7d7b521954d2545f7d09c02ebee682ce9a2e408aa094ff254c8b772",
+ "receiptTrie" : "2f00350472bd9d8d635a091a20bac638d9c6bcb1d6b5c81736a0d1ca5fee93be",
+ "stateRoot" : "96859e95e173eef8004bb592b19cefd71ff683ef0900de4bba7bfe44b96fab3b",
+ "timestamp" : "0x5788dc5b",
+ "transactionsTrie" : "771cef5982e1119f26a627bbeeadc21e350838157aad275b2f4a884a57e277da",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "10",
+ "rlp" : "0xf9026df90206a0fcc08674a7d7b521954d2545f7d09c02ebee682ce9a2e408aa094ff254c8b772a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a096859e95e173eef8004bb592b19cefd71ff683ef0900de4bba7bfe44b96fab3ba0771cef5982e1119f26a627bbeeadc21e350838157aad275b2f4a884a57e277daa02f00350472bd9d8d635a091a20bac638d9c6bcb1d6b5c81736a0d1ca5fee93beb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201800a832fefba825208845788dc5b8d64616f2d686172642d666f726ba0fd36229270002f66be02e74dcc3088b324a862e9c2797bf551a064441eb41553880c81358b772e61d1f861f85f090182ea6094100000000000000000000000000000000000000101801ca0c3d783e93561599d86cbf460e153b3cb37d90478a3c47bfc08bd29563c9d849fa0100e466f7a4c6af73a9030988c63ec88ccaba460fd6a1fb1adc30b61dbdd0857c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x09",
+ "r" : "0xc3d783e93561599d86cbf460e153b3cb37d90478a3c47bfc08bd29563c9d849f",
+ "s" : "0x100e466f7a4c6af73a9030988c63ec88ccaba460fd6a1fb1adc30b61dbdd0857",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1c",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "11",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f0a0182ea6094100000000000000000000000000000000000000101801ca076766ba9925c43448e1ac5c05f7583e6d3a3366eb3dc95a3489ff363b449795ca059b8da33b7aea0d60059f5c1eabce26c1e23e32f31930bff3b49eb1e94cc62a0c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x0201c0",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "851a805fb871ff549a759409ed3b909ec2e3abbca7c4df259a473489c346ba43",
+ "mixHash" : "89999ed1fac8370a082cb0a364de948d6cf9db298d40c3632936cbe9efe7d58e",
+ "nonce" : "8ce8d22f2893653c",
+ "number" : "0x0b",
+ "parentHash" : "5f58b34c4108e44ab7bfbfe9c70b5b86097cdff8b21ae7a990d8ed0c31a04634",
+ "receiptTrie" : "324f8d9eb5892134e0d375c7a4826bbd28ba0f6e73b9b64bbb595e410387ddc3",
+ "stateRoot" : "56bf73c2776f59118fdb82e8b01dc88c3cbb1e2ded3c1d7ef17c4603c500346d",
+ "timestamp" : "0x5788dc63",
+ "transactionsTrie" : "10a81573cb14d5c2794e1b406e26b6d9612c888bbc98c453131bd9b06f61d7c9",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "11",
+ "rlp" : "0xf9026df90206a05f58b34c4108e44ab7bfbfe9c70b5b86097cdff8b21ae7a990d8ed0c31a04634a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a056bf73c2776f59118fdb82e8b01dc88c3cbb1e2ded3c1d7ef17c4603c500346da010a81573cb14d5c2794e1b406e26b6d9612c888bbc98c453131bd9b06f61d7c9a0324f8d9eb5892134e0d375c7a4826bbd28ba0f6e73b9b64bbb595e410387ddc3b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201c00b832fefba825208845788dc638d64616f2d686172642d666f726ba089999ed1fac8370a082cb0a364de948d6cf9db298d40c3632936cbe9efe7d58e888ce8d22f2893653cf861f85f0a0182ea6094100000000000000000000000000000000000000101801ca076766ba9925c43448e1ac5c05f7583e6d3a3366eb3dc95a3489ff363b449795ca059b8da33b7aea0d60059f5c1eabce26c1e23e32f31930bff3b49eb1e94cc62a0c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x0a",
+ "r" : "0x76766ba9925c43448e1ac5c05f7583e6d3a3366eb3dc95a3489ff363b449795c",
+ "s" : "0x59b8da33b7aea0d60059f5c1eabce26c1e23e32f31930bff3b49eb1e94cc62a0",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1c",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "12",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f0b0182ea6094100000000000000000000000000000000000000101801ca085939abfa5d1d2dd8e1bde2655e44236d8e1940a075000301d6deab472ccd680a078d2ae659006c58f9ccc5af29955f7439e48b30b2efe64abdd001165364faa9ac0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020200",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "d2248eb423eb10de5f570b455f4ada1d53e59b254be9c74a011952412652f96a",
+ "mixHash" : "6adfeb8c142a16fe8a4ca09d37997694a3d3a55b3cf93ba063cbca9e68e91b79",
+ "nonce" : "8319bcd74da15bc7",
+ "number" : "0x0c",
+ "parentHash" : "851a805fb871ff549a759409ed3b909ec2e3abbca7c4df259a473489c346ba43",
+ "receiptTrie" : "e150d54f9f244d65a2d906bbb8b0fe9f218119c8b0e00906846ac5cbdab800d1",
+ "stateRoot" : "c545bccf90c734ea9de210666693ada930bbcdbb0cefcde9a57848dc363e8397",
+ "timestamp" : "0x5788dc6b",
+ "transactionsTrie" : "b7757adef51c8c3b9b0433d1a0db70fe5505e8db1848934da1c1d2c6aafc3f65",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "12",
+ "rlp" : "0xf9026df90206a0851a805fb871ff549a759409ed3b909ec2e3abbca7c4df259a473489c346ba43a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c545bccf90c734ea9de210666693ada930bbcdbb0cefcde9a57848dc363e8397a0b7757adef51c8c3b9b0433d1a0db70fe5505e8db1848934da1c1d2c6aafc3f65a0e150d54f9f244d65a2d906bbb8b0fe9f218119c8b0e00906846ac5cbdab800d1b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830202000c832fefba825208845788dc6b8d64616f2d686172642d666f726ba06adfeb8c142a16fe8a4ca09d37997694a3d3a55b3cf93ba063cbca9e68e91b79888319bcd74da15bc7f861f85f0b0182ea6094100000000000000000000000000000000000000101801ca085939abfa5d1d2dd8e1bde2655e44236d8e1940a075000301d6deab472ccd680a078d2ae659006c58f9ccc5af29955f7439e48b30b2efe64abdd001165364faa9ac0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x0b",
+ "r" : "0x85939abfa5d1d2dd8e1bde2655e44236d8e1940a075000301d6deab472ccd680",
+ "s" : "0x78d2ae659006c58f9ccc5af29955f7439e48b30b2efe64abdd001165364faa9a",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1c",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "13",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f0c0182ea6094100000000000000000000000000000000000000101801ca00bb5ae599741966cbd02d6080937bd1f247dfaa266e19891228a4fbfc0c85226a07a4f56371aa5b685bc10d64e180e24850ae18b0fcc675e7d187f877b8d9b1bf6c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020200",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "746b52c52853e38f8b42e10bb36c6325094bd7c49ff77f0e04dd383dfde4b3e5",
+ "mixHash" : "0e925fa65c46cb3527b304c1a699ba9b9244e58715b3c0be8d30f78fbbf91bb7",
+ "nonce" : "c43118c563e4752c",
+ "number" : "0x0d",
+ "parentHash" : "d2248eb423eb10de5f570b455f4ada1d53e59b254be9c74a011952412652f96a",
+ "receiptTrie" : "f5e02249f25bfb35d3338fc0b9407ba4a2da198ad27050ee5fe76f434163f789",
+ "stateRoot" : "0d62f6b628aa29c160a6c6c5462b2395d55fc8699251ef44dd6f7bfb78096359",
+ "timestamp" : "0x5788dc76",
+ "transactionsTrie" : "38b9ac6344a8e2cdd0c0b598f70f21997ab1b39d3ecb2f7a8c7af93e300e0398",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "13",
+ "rlp" : "0xf9026df90206a0d2248eb423eb10de5f570b455f4ada1d53e59b254be9c74a011952412652f96aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a00d62f6b628aa29c160a6c6c5462b2395d55fc8699251ef44dd6f7bfb78096359a038b9ac6344a8e2cdd0c0b598f70f21997ab1b39d3ecb2f7a8c7af93e300e0398a0f5e02249f25bfb35d3338fc0b9407ba4a2da198ad27050ee5fe76f434163f789b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830202000d832fefba825208845788dc768d64616f2d686172642d666f726ba00e925fa65c46cb3527b304c1a699ba9b9244e58715b3c0be8d30f78fbbf91bb788c43118c563e4752cf861f85f0c0182ea6094100000000000000000000000000000000000000101801ca00bb5ae599741966cbd02d6080937bd1f247dfaa266e19891228a4fbfc0c85226a07a4f56371aa5b685bc10d64e180e24850ae18b0fcc675e7d187f877b8d9b1bf6c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x0c",
+ "r" : "0x0bb5ae599741966cbd02d6080937bd1f247dfaa266e19891228a4fbfc0c85226",
+ "s" : "0x7a4f56371aa5b685bc10d64e180e24850ae18b0fcc675e7d187f877b8d9b1bf6",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1c",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "14",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f0d0182ea6094100000000000000000000000000000000000000101801ba0db8f9cd690ad1f6481c09a5445a4185d4fcfdeed76f7ba403d303985c1abaa4ca01ed5f2e9fd9a021103acc910cbefcdaa82d2afd44205a8f681f0c17ebf2da192c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020200",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "19831eb58833d70ba74fc813e112201365ac4f4cdd33026d06df377dfae52498",
+ "mixHash" : "5e7e6fe4790cf6518a643d5351f35fd6b8f6a62b281bb5074138851bac66eb13",
+ "nonce" : "be71f6cdf480c4a2",
+ "number" : "0x0e",
+ "parentHash" : "746b52c52853e38f8b42e10bb36c6325094bd7c49ff77f0e04dd383dfde4b3e5",
+ "receiptTrie" : "308cbfc04d0a5d4821a96fec27ea00f2e278886545add9ed961c28015970ec5c",
+ "stateRoot" : "159a6f365d9aa0930979cb60b9d04cd3c72b50c2f830aa27d610f8c014a600b1",
+ "timestamp" : "0x5788dc80",
+ "transactionsTrie" : "4b6ff42fd8884c83615bf62830df849b18901c07615aafef9aaf16d33f807349",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "14",
+ "rlp" : "0xf9026df90206a0746b52c52853e38f8b42e10bb36c6325094bd7c49ff77f0e04dd383dfde4b3e5a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0159a6f365d9aa0930979cb60b9d04cd3c72b50c2f830aa27d610f8c014a600b1a04b6ff42fd8884c83615bf62830df849b18901c07615aafef9aaf16d33f807349a0308cbfc04d0a5d4821a96fec27ea00f2e278886545add9ed961c28015970ec5cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830202000e832fefba825208845788dc808d64616f2d686172642d666f726ba05e7e6fe4790cf6518a643d5351f35fd6b8f6a62b281bb5074138851bac66eb1388be71f6cdf480c4a2f861f85f0d0182ea6094100000000000000000000000000000000000000101801ba0db8f9cd690ad1f6481c09a5445a4185d4fcfdeed76f7ba403d303985c1abaa4ca01ed5f2e9fd9a021103acc910cbefcdaa82d2afd44205a8f681f0c17ebf2da192c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x0d",
+ "r" : "0xdb8f9cd690ad1f6481c09a5445a4185d4fcfdeed76f7ba403d303985c1abaa4c",
+ "s" : "0x1ed5f2e9fd9a021103acc910cbefcdaa82d2afd44205a8f681f0c17ebf2da192",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1b",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "15",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f0e0182ea6094100000000000000000000000000000000000000101801ca0af8f37a08239d55138f8b92680c682d4118da357c79d6a6b148a6dcce4d961d1a057bf5b29fc32419091bd8e170fed46703b7a2640be0ca91d6903d75c932be160c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020200",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "53337dbe188bd181ba13c0b12333b3560b21969c17f4ca2ce73b327d32a1bd17",
+ "mixHash" : "1203fe51e0609473cbc778ac000373a21d3e4b4b620e869e58281e98b9d46ffe",
+ "nonce" : "ab0199bac390816d",
+ "number" : "0x0f",
+ "parentHash" : "19831eb58833d70ba74fc813e112201365ac4f4cdd33026d06df377dfae52498",
+ "receiptTrie" : "3ceb3d74ba79019e8aac7a6a4de23c5584109dfcff70ed61c160e24ab46bcd3d",
+ "stateRoot" : "d2f5a74b3962d04c2124d780ffa38fc2181e1b09eabb7f4bf5a172a18f75d4d7",
+ "timestamp" : "0x5788dc8e",
+ "transactionsTrie" : "ce025c4f49fea19fbb8b91252f03fd36d2ff6e9e8817c701452992098534abda",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "15",
+ "rlp" : "0xf9026df90206a019831eb58833d70ba74fc813e112201365ac4f4cdd33026d06df377dfae52498a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0d2f5a74b3962d04c2124d780ffa38fc2181e1b09eabb7f4bf5a172a18f75d4d7a0ce025c4f49fea19fbb8b91252f03fd36d2ff6e9e8817c701452992098534abdaa03ceb3d74ba79019e8aac7a6a4de23c5584109dfcff70ed61c160e24ab46bcd3db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830202000f832fefba825208845788dc8e8d64616f2d686172642d666f726ba01203fe51e0609473cbc778ac000373a21d3e4b4b620e869e58281e98b9d46ffe88ab0199bac390816df861f85f0e0182ea6094100000000000000000000000000000000000000101801ca0af8f37a08239d55138f8b92680c682d4118da357c79d6a6b148a6dcce4d961d1a057bf5b29fc32419091bd8e170fed46703b7a2640be0ca91d6903d75c932be160c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x0e",
+ "r" : "0xaf8f37a08239d55138f8b92680c682d4118da357c79d6a6b148a6dcce4d961d1",
+ "s" : "0x57bf5b29fc32419091bd8e170fed46703b7a2640be0ca91d6903d75c932be160",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1c",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "16",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f0f0182ea6094100000000000000000000000000000000000000101801ba040a5467881266422758d59ae66fb3d2511f0131038b0e43abc397d01527fd61ea0172ed4b9c3cf917bf071cb6cc716c4f6754949ea94888d4bb9657eac98fd2c10c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020240",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "6b1d0b868bd5920d3edc2d9073a3c9fc4c9dc7656a51e2ebe89ac5fb2f0e90b3",
+ "mixHash" : "29a4eb947f50b1296aa46d5393e59f002aa01c34a9e7bed6f1fd40e66362e1e2",
+ "nonce" : "98376d65695940d3",
+ "number" : "0x10",
+ "parentHash" : "53337dbe188bd181ba13c0b12333b3560b21969c17f4ca2ce73b327d32a1bd17",
+ "receiptTrie" : "1139851ae488ee33e16c5ef766d36d924d6c4ead16eb1996a92856a5640e938e",
+ "stateRoot" : "c57fab6567df96712cd7031f96a3073f6f1706e637d91ed15fcefd308b024b86",
+ "timestamp" : "0x5788dc97",
+ "transactionsTrie" : "6f2130deb628c7742532339d5b5f1539f9579edcab16996b3b05836a6883073f",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "16",
+ "rlp" : "0xf9026df90206a053337dbe188bd181ba13c0b12333b3560b21969c17f4ca2ce73b327d32a1bd17a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c57fab6567df96712cd7031f96a3073f6f1706e637d91ed15fcefd308b024b86a06f2130deb628c7742532339d5b5f1539f9579edcab16996b3b05836a6883073fa01139851ae488ee33e16c5ef766d36d924d6c4ead16eb1996a92856a5640e938eb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302024010832fefba825208845788dc978d64616f2d686172642d666f726ba029a4eb947f50b1296aa46d5393e59f002aa01c34a9e7bed6f1fd40e66362e1e28898376d65695940d3f861f85f0f0182ea6094100000000000000000000000000000000000000101801ba040a5467881266422758d59ae66fb3d2511f0131038b0e43abc397d01527fd61ea0172ed4b9c3cf917bf071cb6cc716c4f6754949ea94888d4bb9657eac98fd2c10c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x0f",
+ "r" : "0x40a5467881266422758d59ae66fb3d2511f0131038b0e43abc397d01527fd61e",
+ "s" : "0x172ed4b9c3cf917bf071cb6cc716c4f6754949ea94888d4bb9657eac98fd2c10",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1b",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "17",
+ "rlp" : "0xf9024af901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f861f85f100182ea6094100000000000000000000000000000000000000101801ba0d7933ba406ea332cdec2d673bbf5789c34a43224629c220bd0ac2c9d81c7b094a05e0a096cbe3bdc9047b18de6be4822165c669bddf712456567dc525547059ff8c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020240",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "7cda04f38d4a31d51370d4d8cc763b3d15e53eb4fe76575a2a87a22f5c53a5cf",
+ "mixHash" : "38824245bf0d625f30f725a2daa9245035240449cbe011358328fc36066a7d91",
+ "nonce" : "16893c7414215a57",
+ "number" : "0x11",
+ "parentHash" : "6b1d0b868bd5920d3edc2d9073a3c9fc4c9dc7656a51e2ebe89ac5fb2f0e90b3",
+ "receiptTrie" : "f71904ef163e1bb258f38fba942af54f6f2947ded4702309ff60fb2a70291dc8",
+ "stateRoot" : "719b70fcc0d130db91c3ec672245c08728fb3636d3e5068de03b1eacb5dec827",
+ "timestamp" : "0x5788dca1",
+ "transactionsTrie" : "316f3430ee504cbaa58cec2ce451de2fc9e0f1e7f99b16b33f69ab3ca93130be",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "17",
+ "rlp" : "0xf9026df90206a06b1d0b868bd5920d3edc2d9073a3c9fc4c9dc7656a51e2ebe89ac5fb2f0e90b3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0719b70fcc0d130db91c3ec672245c08728fb3636d3e5068de03b1eacb5dec827a0316f3430ee504cbaa58cec2ce451de2fc9e0f1e7f99b16b33f69ab3ca93130bea0f71904ef163e1bb258f38fba942af54f6f2947ded4702309ff60fb2a70291dc8b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302024011832fefba825208845788dca18d64616f2d686172642d666f726ba038824245bf0d625f30f725a2daa9245035240449cbe011358328fc36066a7d918816893c7414215a57f861f85f100182ea6094100000000000000000000000000000000000000101801ba0d7933ba406ea332cdec2d673bbf5789c34a43224629c220bd0ac2c9d81c7b094a05e0a096cbe3bdc9047b18de6be4822165c669bddf712456567dc525547059ff8c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x10",
+ "r" : "0xd7933ba406ea332cdec2d673bbf5789c34a43224629c220bd0ac2c9d81c7b094",
+ "s" : "0x5e0a096cbe3bdc9047b18de6be4822165c669bddf712456567dc525547059ff8",
+ "to" : "1000000000000000000000000000000000000001",
+ "v" : "0x1b",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ }
+ ],
+ "genesisBlockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x42",
+ "gasLimit" : "0x2fefd8",
+ "gasUsed" : "0x00",
+ "hash" : "cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09",
+ "mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "nonce" : "0102030405060708",
+ "number" : "0x00",
+ "parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "6bff69e94b94f30e1b69f86d3e09712edfb583ac73a46a522345e1965ca9c66d",
+ "timestamp" : "0x54c98c81",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a06bff69e94b94f30e1b69f86d3e09712edfb583ac73a46a522345e1965ca9c66da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
+ "lastblockhash" : "7cda04f38d4a31d51370d4d8cc763b3d15e53eb4fe76575a2a87a22f5c53a5cf",
+ "postState" : {
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0c243ebe6a031753dc0dd850acf422844a3efb76" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000001" : {
+ "balance" : "0x09",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000007" : {
+ "balance" : "0x0a",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ "0x00" : "0x02540be400"
+ }
+ },
+ "1000000000000000000000000000000000000008" : {
+ "balance" : "0x0a",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "248f0f0f33eadb89e9d87fd5c127f58567f3ffde" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "85c2f277588ea1e6901ed59e587bea222c575f87" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8888f1f195afa192cfee860698584c030f4c9db1" : {
+ "balance" : "0x049b9ca9a6943ace64",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x3b93fb43",
+ "code" : "0x",
+ "nonce" : "0x11",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b1d37cf6180ceb738ca45b5005a2f418c02e204b" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bf4ed7b27f1d666546e30d74d50d173d20bca754" : {
+ "balance" : "0x010bc166ae40",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ },
+ "pre" : {
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000007" : {
+ "balance" : "0x00",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000008" : {
+ "balance" : "0x00",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x3b9aca00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x0f4240",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ }
+ },
+ "DaoTransactions_EmptyTransactionAndForkBlocksAhead" : {
+ "blocks" : [
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "2d909e451e1b958a488fd067628526a424c0bc3fbb0afe78998e92f6ef92c880",
+ "mixHash" : "02c435f7b9734da7aa6db2217ba1a4522f3465a99006cbd44942272fc793e5c7",
+ "nonce" : "c94ecb5430e81c0c",
+ "number" : "0x01",
+ "parentHash" : "cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09",
+ "receiptTrie" : "37aee413d1d4f1335720ed1ee882bac4b2d41c8072453b23445020c951682054",
+ "stateRoot" : "d3f60d7c23e6d3e8eeaa691dd6d54b653e9d33ce579ed821a1e408c1e89cf01a",
+ "timestamp" : "0x5788dca6",
+ "transactionsTrie" : "ac81275d7a81a720240146377982939179218535bfcfa9469c8bdd3e264ef179",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "1",
+ "rlp" : "0xf9024cf901f9a0cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0d3f60d7c23e6d3e8eeaa691dd6d54b653e9d33ce579ed821a1e408c1e89cf01aa0ac81275d7a81a720240146377982939179218535bfcfa9469c8bdd3e264ef179a037aee413d1d4f1335720ed1ee882bac4b2d41c8072453b23445020c951682054b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba825208845788dca680a002c435f7b9734da7aa6db2217ba1a4522f3465a99006cbd44942272fc793e5c788c94ecb5430e81c0cf84df84b8001827530800a801ca057cb46c0b702929c4fd4127b2370f28a7aeeaa65509699e58eedf7692090a0a9a05ba7c83d99be6a9bca0c81947023ba3b5f2162516d82d0757bf8004f3e9bc03ac0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x00",
+ "r" : "0x57cb46c0b702929c4fd4127b2370f28a7aeeaa65509699e58eedf7692090a0a9",
+ "s" : "0x5ba7c83d99be6a9bca0c81947023ba3b5f2162516d82d0757bf8004f3e9bc03a",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020040",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "59d2678d1e13c27405ca21d6cc09303c52422c3eb5b9233f0431260e4314a8ff",
+ "mixHash" : "43d612b9569a9a1e1fcefc3fdff9ee4b15d6844c1b912925c15e852bc2eee47a",
+ "nonce" : "bc6be4c140452074",
+ "number" : "0x02",
+ "parentHash" : "2d909e451e1b958a488fd067628526a424c0bc3fbb0afe78998e92f6ef92c880",
+ "receiptTrie" : "9a62bdf5dbcf4d27f17a31d5506d3249c5a6ca549787b1902ba01584bb33cf64",
+ "stateRoot" : "c97eb33ff96a24bd16aaa76040aff370a690e6e52f0172eba3a436d7c867a988",
+ "timestamp" : "0x5788dcac",
+ "transactionsTrie" : "76c7a0ce7644661f276c76fb9a82eaee879d0642cf4ed244fc10afc02c646abf",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "2",
+ "rlp" : "0xf9024cf901f9a02d909e451e1b958a488fd067628526a424c0bc3fbb0afe78998e92f6ef92c880a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c97eb33ff96a24bd16aaa76040aff370a690e6e52f0172eba3a436d7c867a988a076c7a0ce7644661f276c76fb9a82eaee879d0642cf4ed244fc10afc02c646abfa09a62bdf5dbcf4d27f17a31d5506d3249c5a6ca549787b1902ba01584bb33cf64b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefba825208845788dcac80a043d612b9569a9a1e1fcefc3fdff9ee4b15d6844c1b912925c15e852bc2eee47a88bc6be4c140452074f84df84b0101827530800a801ca0bb6e3cf3f281af13ef1393d7052b03cab367079a9eb71aa829ec72b231a60e1fa04bcfe1da53f26bb95806d38e9f42fef262aaaf5191e16ec473a695c8978a0b05c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x01",
+ "r" : "0xbb6e3cf3f281af13ef1393d7052b03cab367079a9eb71aa829ec72b231a60e1f",
+ "s" : "0x4bcfe1da53f26bb95806d38e9f42fef262aaaf5191e16ec473a695c8978a0b05",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020080",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "7051d31496dd62effea9d15df0bfa702853ccbe9febbcbaac756fe10c48afa31",
+ "mixHash" : "1267559086eed7764a14877cbc3ef681f1e8b6948d15f06babe3e99004fbe948",
+ "nonce" : "4806557d56b8ca98",
+ "number" : "0x03",
+ "parentHash" : "59d2678d1e13c27405ca21d6cc09303c52422c3eb5b9233f0431260e4314a8ff",
+ "receiptTrie" : "b9ca869c5641896a8e22fe74b4225c6a43cbc3303b24d13e0af94517180c8097",
+ "stateRoot" : "9cb74b15edd72a2075b114d9154f4bbdf784054658912024747ea9423e0d2af8",
+ "timestamp" : "0x5788dcb4",
+ "transactionsTrie" : "3798aa164b61e27b93484c76a5f319bd93c808dc78ef31cf8b93f4e1b248ca2c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "3",
+ "rlp" : "0xf9024cf901f9a059d2678d1e13c27405ca21d6cc09303c52422c3eb5b9233f0431260e4314a8ffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a09cb74b15edd72a2075b114d9154f4bbdf784054658912024747ea9423e0d2af8a03798aa164b61e27b93484c76a5f319bd93c808dc78ef31cf8b93f4e1b248ca2ca0b9ca869c5641896a8e22fe74b4225c6a43cbc3303b24d13e0af94517180c8097b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba825208845788dcb480a01267559086eed7764a14877cbc3ef681f1e8b6948d15f06babe3e99004fbe948884806557d56b8ca98f84df84b0201827530800a801ca0f6d884cae1f86bdff1281e95e416089c544a4a5578a75d5e8ad76118e341b055a075b7d88985ed5acd61f30c9f9570c6c33bb92f3ad1a32b86a0747817fbc5ededc0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x02",
+ "r" : "0xf6d884cae1f86bdff1281e95e416089c544a4a5578a75d5e8ad76118e341b055",
+ "s" : "0x75b7d88985ed5acd61f30c9f9570c6c33bb92f3ad1a32b86a0747817fbc5eded",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x0200c0",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "2d861373e66c78d1d5eaa5833386489938365e7cb368a8666c5fbc215cbce406",
+ "mixHash" : "db2e0f7741e497b519d547dc38ef0531db80fd5410884545dfdaeb694dc57de1",
+ "nonce" : "fb70478bc0ec196f",
+ "number" : "0x04",
+ "parentHash" : "7051d31496dd62effea9d15df0bfa702853ccbe9febbcbaac756fe10c48afa31",
+ "receiptTrie" : "d69ea0fac668bb7ece043f8e6ac833c5d10a7d5bf08ebfe40a8dc1721a3aa4fd",
+ "stateRoot" : "aeaa38b30cbc02db5cd17a91e9212346cd839fafcb1fc06126cf64b5b782b877",
+ "timestamp" : "0x5788dcb6",
+ "transactionsTrie" : "4cc1b34b3a9d29bf69842a54e1c48bc97afc433883f66d2c59287f118c9c3c2c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "4",
+ "rlp" : "0xf9024cf901f9a07051d31496dd62effea9d15df0bfa702853ccbe9febbcbaac756fe10c48afa31a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0aeaa38b30cbc02db5cd17a91e9212346cd839fafcb1fc06126cf64b5b782b877a04cc1b34b3a9d29bf69842a54e1c48bc97afc433883f66d2c59287f118c9c3c2ca0d69ea0fac668bb7ece043f8e6ac833c5d10a7d5bf08ebfe40a8dc1721a3aa4fdb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200c004832fefba825208845788dcb680a0db2e0f7741e497b519d547dc38ef0531db80fd5410884545dfdaeb694dc57de188fb70478bc0ec196ff84df84b0301827530800a801ca0753ee5d896db8d87fe850e7935418587277cd9c010dfaaf7dd09b0a2e73785dca066deb3c241d532c7b880ae7a9a311ee7a92ef1c5e4e2bf3307990a2881bc13b0c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x03",
+ "r" : "0x753ee5d896db8d87fe850e7935418587277cd9c010dfaaf7dd09b0a2e73785dc",
+ "s" : "0x66deb3c241d532c7b880ae7a9a311ee7a92ef1c5e4e2bf3307990a2881bc13b0",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020100",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xcf08",
+ "hash" : "5d08215124863936106a33d44911139e90b5727af7dd7e00f641e69b3651a6f7",
+ "mixHash" : "936c648b4f2d8097f8f38341961112d5002d725a43c916895af6478db2320dee",
+ "nonce" : "93aebe2f5096c2f0",
+ "number" : "0x05",
+ "parentHash" : "2d861373e66c78d1d5eaa5833386489938365e7cb368a8666c5fbc215cbce406",
+ "receiptTrie" : "d7f28f5ba69ca1893569465903e8d942153c57912f7d1f6b3e33088e8ad17fee",
+ "stateRoot" : "f54737efdead0a75d49cc6ceaedf75fd4aacf933e8f361a9a9c0a1647bcf6ab5",
+ "timestamp" : "0x5788dcbb",
+ "transactionsTrie" : "165af780d27795ebc80c27759d3d949a9c4b05d35fcc7e9d3da8be357f5340cd",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "5",
+ "rlp" : "0xf9024cf901f9a02d861373e66c78d1d5eaa5833386489938365e7cb368a8666c5fbc215cbce406a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0f54737efdead0a75d49cc6ceaedf75fd4aacf933e8f361a9a9c0a1647bcf6ab5a0165af780d27795ebc80c27759d3d949a9c4b05d35fcc7e9d3da8be357f5340cda0d7f28f5ba69ca1893569465903e8d942153c57912f7d1f6b3e33088e8ad17feeb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302010005832fefba82cf08845788dcbb80a0936c648b4f2d8097f8f38341961112d5002d725a43c916895af6478db2320dee8893aebe2f5096c2f0f84df84b040182ea60800a801ba0cb1400f01459519ac3dc0426c6d7f95641dc6a7b8008069c9dfbe4f94b167169a07445362aadae8c25e4f0b494ad553bfc652bf34fb2ed0ccbf9a6b089c2b09f62c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x04",
+ "r" : "0xcb1400f01459519ac3dc0426c6d7f95641dc6a7b8008069c9dfbe4f94b167169",
+ "s" : "0x7445362aadae8c25e4f0b494ad553bfc652bf34fb2ed0ccbf9a6b089c2b09f62",
+ "to" : "",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020140",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xcf08",
+ "hash" : "acbdff199573486fb95c161701899d39b1c185b3d0b47f84e6dfeb523460b23d",
+ "mixHash" : "68b8605bad23304f622a5c84c7f3fa3b4552147c025ef7c4ccfc6eba9249f73a",
+ "nonce" : "a7abc8bf394b64c6",
+ "number" : "0x06",
+ "parentHash" : "5d08215124863936106a33d44911139e90b5727af7dd7e00f641e69b3651a6f7",
+ "receiptTrie" : "975eeeb6e46fc2d858080444f0536a1f3a688638fdf0bcbc1958dedc5eda4405",
+ "stateRoot" : "05ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174",
+ "timestamp" : "0x5788dcbe",
+ "transactionsTrie" : "ef009c3c274a522a6e2ca98232fffff747bdfab79189be3e2b5e5dc54e2a51be",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "6",
+ "rlp" : "0xf9024cf901f9a05d08215124863936106a33d44911139e90b5727af7dd7e00f641e69b3651a6f7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a005ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174a0ef009c3c274a522a6e2ca98232fffff747bdfab79189be3e2b5e5dc54e2a51bea0975eeeb6e46fc2d858080444f0536a1f3a688638fdf0bcbc1958dedc5eda4405b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014006832fefba82cf08845788dcbe80a068b8605bad23304f622a5c84c7f3fa3b4552147c025ef7c4ccfc6eba9249f73a88a7abc8bf394b64c6f84df84b050182ea60800a801ba04d147b172eb81fdb11a21826eabad091084f6e9613d340b5897872843efa6435a023640d906f65fd156b92d518068263d99d94dc88c3e0950fd7633fb0d4d237eec0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x05",
+ "r" : "0x4d147b172eb81fdb11a21826eabad091084f6e9613d340b5897872843efa6435",
+ "s" : "0x23640d906f65fd156b92d518068263d99d94dc88c3e0950fd7633fb0d4d237ee",
+ "to" : "",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xa042",
+ "hash" : "f49bb56fe54a6b9b5f680fabdda650282ed775dfd61f680b1aa22ae7981ad0f3",
+ "mixHash" : "fa179ecc633681c23745afc1b9302c33b34713054722cc90fcafa66c4626af9b",
+ "nonce" : "da2c320a8cf4466b",
+ "number" : "0x07",
+ "parentHash" : "acbdff199573486fb95c161701899d39b1c185b3d0b47f84e6dfeb523460b23d",
+ "receiptTrie" : "aec104fc55d9aa0c1767af2dcf73c512f650f24bf89b9b78eb236d70a2de848f",
+ "stateRoot" : "40d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029",
+ "timestamp" : "0x5788dcc4",
+ "transactionsTrie" : "b2d17fa171d19df4e817ffb15f38526d125a42b7879cd712584b130dc8ad341c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "7",
+ "rlp" : "0xf90260f901f9a0acbdff199573486fb95c161701899d39b1c185b3d0b47f84e6dfeb523460b23da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a040d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029a0b2d17fa171d19df4e817ffb15f38526d125a42b7879cd712584b130dc8ad341ca0aec104fc55d9aa0c1767af2dcf73c512f650f24bf89b9b78eb236d70a2de848fb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018007832fefba82a042845788dcc480a0fa179ecc633681c23745afc1b9302c33b34713054722cc90fcafa66c4626af9b88da2c320a8cf4466bf861f85f060182ea609410000000000000000000000000000000000000070a801ba0bb8523d4c53ed16b355d0a2dba02154d23a5480449dc3894be40ef95511d2fe9a010ad725c2df4979b7a071b3fa9b6b719223f0167d68b98f213e8611f84d4d81bc0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x06",
+ "r" : "0xbb8523d4c53ed16b355d0a2dba02154d23a5480449dc3894be40ef95511d2fe9",
+ "s" : "0x10ad725c2df4979b7a071b3fa9b6b719223f0167d68b98f213e8611f84d4d81b",
+ "to" : "1000000000000000000000000000000000000007",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "8",
+ "rlp" : "0xf901e8f901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c0c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x0201c0",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x00",
+ "hash" : "f72712a3cc7a529b9f546210021b6656869b4b7a087ae7edd46813b3d16d6f33",
+ "mixHash" : "ce2560cb248158e7d6dc7b91b9c9bfe33ec595e0b8c28949295fd0f3825fb3c5",
+ "nonce" : "e1456cf26b175da3",
+ "number" : "0x08",
+ "parentHash" : "f49bb56fe54a6b9b5f680fabdda650282ed775dfd61f680b1aa22ae7981ad0f3",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "c98502a5a62b5f861b5b8a73b1bdcf94045f2929024e5cc9d8af8e3989c388e1",
+ "timestamp" : "0x5788dccd",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "8",
+ "rlp" : "0xf90209f90204a0f49bb56fe54a6b9b5f680fabdda650282ed775dfd61f680b1aa22ae7981ad0f3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c98502a5a62b5f861b5b8a73b1bdcf94045f2929024e5cc9d8af8e3989c388e1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201c008832fefba80845788dccd8d64616f2d686172642d666f726ba0ce2560cb248158e7d6dc7b91b9c9bfe33ec595e0b8c28949295fd0f3825fb3c588e1456cf26b175da3c0c0",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020200",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x65aa",
+ "hash" : "f413ffd0487431795bb6ddc294a5d1bf3521ec030306c2753d16fad0faa7a75a",
+ "mixHash" : "0d26e09d369ab5b1fc31616bc6d88eecf0c34f548c5491a508c3ae31dbebb301",
+ "nonce" : "584a1e99e55da8aa",
+ "number" : "0x09",
+ "parentHash" : "f72712a3cc7a529b9f546210021b6656869b4b7a087ae7edd46813b3d16d6f33",
+ "receiptTrie" : "495e1248e1c24cb86cd27272086718c404d4b87531e03fa943ff149511a0faa6",
+ "stateRoot" : "deb10c3f01687b15e4c3af95f7d12cf003e80af3196bc77a80fafa75b527c31d",
+ "timestamp" : "0x5788dcd3",
+ "transactionsTrie" : "964e2a482dc1856fff3b00f545aaf8720aeef70a3ffe86cebf05bbc2c34bf539",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "9",
+ "rlp" : "0xf9026df90206a0f72712a3cc7a529b9f546210021b6656869b4b7a087ae7edd46813b3d16d6f33a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0deb10c3f01687b15e4c3af95f7d12cf003e80af3196bc77a80fafa75b527c31da0964e2a482dc1856fff3b00f545aaf8720aeef70a3ffe86cebf05bbc2c34bf539a0495e1248e1c24cb86cd27272086718c404d4b87531e03fa943ff149511a0faa6b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302020009832fefba8265aa845788dcd38d64616f2d686172642d666f726ba00d26e09d369ab5b1fc31616bc6d88eecf0c34f548c5491a508c3ae31dbebb30188584a1e99e55da8aaf861f85f070182ea6094100000000000000000000000000000000000000801801ba09e18981c45e9f6bb54e3f52cae58f2c3c00f2220a9f1c788d0ee3fc2394d4956a038207c17c10faae1fa83bff79770fa38134a19b6ca6f04059d7a307c05f67e6ac0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x07",
+ "r" : "0x9e18981c45e9f6bb54e3f52cae58f2c3c00f2220a9f1c788d0ee3fc2394d4956",
+ "s" : "0x38207c17c10faae1fa83bff79770fa38134a19b6ca6f04059d7a307c05f67e6a",
+ "to" : "1000000000000000000000000000000000000008",
+ "v" : "0x1b",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "10",
+ "rlp" : "0xf90236f901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f84df84b080182ea608001801ba066a8a933ff9208ecb2334a7edcf0592751d68e5e9cf155814238cd3072a7d38ba02cd8720983a8172b1304aad194d3f2ea3daeaf5c51bc3dc983d8218448f063bdc0"
+ },
+ {
+ "blocknumber" : "11",
+ "rlp" : "0xf90236f901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f84df84b090182ea608001801ba08c41aab2b35a0c8c82f88076fe817d2c3a261e6bbab3c270f2d5f6c8ba077f2ea04861726cfb49b87296466ab8cf0790d7790e7e371168dc7e960361bc3479e985c0"
+ }
+ ],
+ "genesisBlockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x42",
+ "gasLimit" : "0x2fefd8",
+ "gasUsed" : "0x00",
+ "hash" : "cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09",
+ "mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "nonce" : "0102030405060708",
+ "number" : "0x00",
+ "parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "6bff69e94b94f30e1b69f86d3e09712edfb583ac73a46a522345e1965ca9c66d",
+ "timestamp" : "0x54c98c81",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a06bff69e94b94f30e1b69f86d3e09712edfb583ac73a46a522345e1965ca9c66da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
+ "lastblockhash" : "f413ffd0487431795bb6ddc294a5d1bf3521ec030306c2753d16fad0faa7a75a",
+ "postState" : {
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0c243ebe6a031753dc0dd850acf422844a3efb76" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000007" : {
+ "balance" : "0x0a",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ "0x00" : "0x02540be400"
+ }
+ },
+ "1000000000000000000000000000000000000008" : {
+ "balance" : "0x01",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "248f0f0f33eadb89e9d87fd5c127f58567f3ffde" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "85c2f277588ea1e6901ed59e587bea222c575f87" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8888f1f195afa192cfee860698584c030f4c9db1" : {
+ "balance" : "0x0270801d946c97ec1c",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x3b96dd9d",
+ "code" : "0x",
+ "nonce" : "0x08",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b1d37cf6180ceb738ca45b5005a2f418c02e204b" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bf4ed7b27f1d666546e30d74d50d173d20bca754" : {
+ "balance" : "0x010bc166ae40",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ },
+ "pre" : {
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000007" : {
+ "balance" : "0x00",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000008" : {
+ "balance" : "0x00",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x3b9aca00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x0f4240",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ }
+ },
+ "DaoTransactions_UncleExtradata" : {
+ "blocks" : [
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "6a6235d2937cb55dd1bb0c84f64943011c6b9aa655ecf949d0f3677d3df37fe9",
+ "mixHash" : "dc5b0e1a8b5e111a45474596139eceef6e3ef2c96226dacf6e282262a7e69d5a",
+ "nonce" : "09e6701cc7e04da7",
+ "number" : "0x01",
+ "parentHash" : "cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09",
+ "receiptTrie" : "37aee413d1d4f1335720ed1ee882bac4b2d41c8072453b23445020c951682054",
+ "stateRoot" : "d3f60d7c23e6d3e8eeaa691dd6d54b653e9d33ce579ed821a1e408c1e89cf01a",
+ "timestamp" : "0x5788dce1",
+ "transactionsTrie" : "ac81275d7a81a720240146377982939179218535bfcfa9469c8bdd3e264ef179",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "1",
+ "rlp" : "0xf9024cf901f9a0cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0d3f60d7c23e6d3e8eeaa691dd6d54b653e9d33ce579ed821a1e408c1e89cf01aa0ac81275d7a81a720240146377982939179218535bfcfa9469c8bdd3e264ef179a037aee413d1d4f1335720ed1ee882bac4b2d41c8072453b23445020c951682054b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba825208845788dce180a0dc5b0e1a8b5e111a45474596139eceef6e3ef2c96226dacf6e282262a7e69d5a8809e6701cc7e04da7f84df84b8001827530800a801ca057cb46c0b702929c4fd4127b2370f28a7aeeaa65509699e58eedf7692090a0a9a05ba7c83d99be6a9bca0c81947023ba3b5f2162516d82d0757bf8004f3e9bc03ac0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x00",
+ "r" : "0x57cb46c0b702929c4fd4127b2370f28a7aeeaa65509699e58eedf7692090a0a9",
+ "s" : "0x5ba7c83d99be6a9bca0c81947023ba3b5f2162516d82d0757bf8004f3e9bc03a",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020040",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "d79fd92f80a0745c29abc6e28578aeb8f063f2dec88c246e241b5dd5bdb8ba7d",
+ "mixHash" : "c39d82b340083da577ef2f0299521ecdf7062575dad75cb15566b77869493a4e",
+ "nonce" : "a0344ef0a4622d51",
+ "number" : "0x02",
+ "parentHash" : "6a6235d2937cb55dd1bb0c84f64943011c6b9aa655ecf949d0f3677d3df37fe9",
+ "receiptTrie" : "9a62bdf5dbcf4d27f17a31d5506d3249c5a6ca549787b1902ba01584bb33cf64",
+ "stateRoot" : "c97eb33ff96a24bd16aaa76040aff370a690e6e52f0172eba3a436d7c867a988",
+ "timestamp" : "0x5788dce9",
+ "transactionsTrie" : "76c7a0ce7644661f276c76fb9a82eaee879d0642cf4ed244fc10afc02c646abf",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "2",
+ "rlp" : "0xf9024cf901f9a06a6235d2937cb55dd1bb0c84f64943011c6b9aa655ecf949d0f3677d3df37fe9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c97eb33ff96a24bd16aaa76040aff370a690e6e52f0172eba3a436d7c867a988a076c7a0ce7644661f276c76fb9a82eaee879d0642cf4ed244fc10afc02c646abfa09a62bdf5dbcf4d27f17a31d5506d3249c5a6ca549787b1902ba01584bb33cf64b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefba825208845788dce980a0c39d82b340083da577ef2f0299521ecdf7062575dad75cb15566b77869493a4e88a0344ef0a4622d51f84df84b0101827530800a801ca0bb6e3cf3f281af13ef1393d7052b03cab367079a9eb71aa829ec72b231a60e1fa04bcfe1da53f26bb95806d38e9f42fef262aaaf5191e16ec473a695c8978a0b05c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x01",
+ "r" : "0xbb6e3cf3f281af13ef1393d7052b03cab367079a9eb71aa829ec72b231a60e1f",
+ "s" : "0x4bcfe1da53f26bb95806d38e9f42fef262aaaf5191e16ec473a695c8978a0b05",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020080",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "a067ecb45dd483817f54e229556952f8eb6ffa57a88b29e989c0e3ea9f21d3fb",
+ "mixHash" : "2bbcca39f731d951481da431940b17549721062c1d213c6b6f49099030ad5767",
+ "nonce" : "94eaf9f574478fe4",
+ "number" : "0x03",
+ "parentHash" : "d79fd92f80a0745c29abc6e28578aeb8f063f2dec88c246e241b5dd5bdb8ba7d",
+ "receiptTrie" : "b9ca869c5641896a8e22fe74b4225c6a43cbc3303b24d13e0af94517180c8097",
+ "stateRoot" : "9cb74b15edd72a2075b114d9154f4bbdf784054658912024747ea9423e0d2af8",
+ "timestamp" : "0x5788dcec",
+ "transactionsTrie" : "3798aa164b61e27b93484c76a5f319bd93c808dc78ef31cf8b93f4e1b248ca2c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "3",
+ "rlp" : "0xf9024cf901f9a0d79fd92f80a0745c29abc6e28578aeb8f063f2dec88c246e241b5dd5bdb8ba7da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a09cb74b15edd72a2075b114d9154f4bbdf784054658912024747ea9423e0d2af8a03798aa164b61e27b93484c76a5f319bd93c808dc78ef31cf8b93f4e1b248ca2ca0b9ca869c5641896a8e22fe74b4225c6a43cbc3303b24d13e0af94517180c8097b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba825208845788dcec80a02bbcca39f731d951481da431940b17549721062c1d213c6b6f49099030ad57678894eaf9f574478fe4f84df84b0201827530800a801ca0f6d884cae1f86bdff1281e95e416089c544a4a5578a75d5e8ad76118e341b055a075b7d88985ed5acd61f30c9f9570c6c33bb92f3ad1a32b86a0747817fbc5ededc0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x02",
+ "r" : "0xf6d884cae1f86bdff1281e95e416089c544a4a5578a75d5e8ad76118e341b055",
+ "s" : "0x75b7d88985ed5acd61f30c9f9570c6c33bb92f3ad1a32b86a0747817fbc5eded",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x0200c0",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "f0b1b300b01ca901967fd47745e84afaf28c2d15f863da355e5791b94a911107",
+ "mixHash" : "28e1a30ba4c89a6b1a5ff007226250b3091b4bb930ce6b83a07c8e835c83f52d",
+ "nonce" : "54210a32ae9561fd",
+ "number" : "0x04",
+ "parentHash" : "a067ecb45dd483817f54e229556952f8eb6ffa57a88b29e989c0e3ea9f21d3fb",
+ "receiptTrie" : "d69ea0fac668bb7ece043f8e6ac833c5d10a7d5bf08ebfe40a8dc1721a3aa4fd",
+ "stateRoot" : "aeaa38b30cbc02db5cd17a91e9212346cd839fafcb1fc06126cf64b5b782b877",
+ "timestamp" : "0x5788dcf0",
+ "transactionsTrie" : "4cc1b34b3a9d29bf69842a54e1c48bc97afc433883f66d2c59287f118c9c3c2c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "4",
+ "rlp" : "0xf9024cf901f9a0a067ecb45dd483817f54e229556952f8eb6ffa57a88b29e989c0e3ea9f21d3fba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0aeaa38b30cbc02db5cd17a91e9212346cd839fafcb1fc06126cf64b5b782b877a04cc1b34b3a9d29bf69842a54e1c48bc97afc433883f66d2c59287f118c9c3c2ca0d69ea0fac668bb7ece043f8e6ac833c5d10a7d5bf08ebfe40a8dc1721a3aa4fdb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200c004832fefba825208845788dcf080a028e1a30ba4c89a6b1a5ff007226250b3091b4bb930ce6b83a07c8e835c83f52d8854210a32ae9561fdf84df84b0301827530800a801ca0753ee5d896db8d87fe850e7935418587277cd9c010dfaaf7dd09b0a2e73785dca066deb3c241d532c7b880ae7a9a311ee7a92ef1c5e4e2bf3307990a2881bc13b0c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0x7530",
+ "gasPrice" : "0x01",
+ "nonce" : "0x03",
+ "r" : "0x753ee5d896db8d87fe850e7935418587277cd9c010dfaaf7dd09b0a2e73785dc",
+ "s" : "0x66deb3c241d532c7b880ae7a9a311ee7a92ef1c5e4e2bf3307990a2881bc13b0",
+ "to" : "",
+ "v" : "0x1c",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020100",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xcf08",
+ "hash" : "48c11a9d9affbcd36782770bc512f0fdc5b31dbef334fc6dea2ce6f6a6d1741a",
+ "mixHash" : "b3c1ccf41831ee494eab1190c9f69a9d671031114342821bc327a30cf3d74bf2",
+ "nonce" : "395f46219e639a8a",
+ "number" : "0x05",
+ "parentHash" : "f0b1b300b01ca901967fd47745e84afaf28c2d15f863da355e5791b94a911107",
+ "receiptTrie" : "d7f28f5ba69ca1893569465903e8d942153c57912f7d1f6b3e33088e8ad17fee",
+ "stateRoot" : "f54737efdead0a75d49cc6ceaedf75fd4aacf933e8f361a9a9c0a1647bcf6ab5",
+ "timestamp" : "0x5788dcf4",
+ "transactionsTrie" : "165af780d27795ebc80c27759d3d949a9c4b05d35fcc7e9d3da8be357f5340cd",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "5",
+ "rlp" : "0xf9024cf901f9a0f0b1b300b01ca901967fd47745e84afaf28c2d15f863da355e5791b94a911107a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0f54737efdead0a75d49cc6ceaedf75fd4aacf933e8f361a9a9c0a1647bcf6ab5a0165af780d27795ebc80c27759d3d949a9c4b05d35fcc7e9d3da8be357f5340cda0d7f28f5ba69ca1893569465903e8d942153c57912f7d1f6b3e33088e8ad17feeb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302010005832fefba82cf08845788dcf480a0b3c1ccf41831ee494eab1190c9f69a9d671031114342821bc327a30cf3d74bf288395f46219e639a8af84df84b040182ea60800a801ba0cb1400f01459519ac3dc0426c6d7f95641dc6a7b8008069c9dfbe4f94b167169a07445362aadae8c25e4f0b494ad553bfc652bf34fb2ed0ccbf9a6b089c2b09f62c0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x04",
+ "r" : "0xcb1400f01459519ac3dc0426c6d7f95641dc6a7b8008069c9dfbe4f94b167169",
+ "s" : "0x7445362aadae8c25e4f0b494ad553bfc652bf34fb2ed0ccbf9a6b089c2b09f62",
+ "to" : "",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020140",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xcf08",
+ "hash" : "5fc71cd93151a07d5c8e223178a472dfadf85c7c0d601c461bb2412ad90008cf",
+ "mixHash" : "8cf9efd45d62f0c5e539295f5c88f2d41a449fa31413a4ac2fa0b679f41cdd46",
+ "nonce" : "76c3a1561e24c932",
+ "number" : "0x06",
+ "parentHash" : "48c11a9d9affbcd36782770bc512f0fdc5b31dbef334fc6dea2ce6f6a6d1741a",
+ "receiptTrie" : "975eeeb6e46fc2d858080444f0536a1f3a688638fdf0bcbc1958dedc5eda4405",
+ "stateRoot" : "05ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174",
+ "timestamp" : "0x5788dcf7",
+ "transactionsTrie" : "ef009c3c274a522a6e2ca98232fffff747bdfab79189be3e2b5e5dc54e2a51be",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "6",
+ "rlp" : "0xf9024cf901f9a048c11a9d9affbcd36782770bc512f0fdc5b31dbef334fc6dea2ce6f6a6d1741aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a005ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174a0ef009c3c274a522a6e2ca98232fffff747bdfab79189be3e2b5e5dc54e2a51bea0975eeeb6e46fc2d858080444f0536a1f3a688638fdf0bcbc1958dedc5eda4405b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014006832fefba82cf08845788dcf780a08cf9efd45d62f0c5e539295f5c88f2d41a449fa31413a4ac2fa0b679f41cdd468876c3a1561e24c932f84df84b050182ea60800a801ba04d147b172eb81fdb11a21826eabad091084f6e9613d340b5897872843efa6435a023640d906f65fd156b92d518068263d99d94dc88c3e0950fd7633fb0d4d237eec0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x05",
+ "r" : "0x4d147b172eb81fdb11a21826eabad091084f6e9613d340b5897872843efa6435",
+ "s" : "0x23640d906f65fd156b92d518068263d99d94dc88c3e0950fd7633fb0d4d237ee",
+ "to" : "",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0xa042",
+ "hash" : "faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265",
+ "mixHash" : "f117fd70e501a76776c5dd7c227a2ae6d28aa5a4422b9ce31fdd3d57d411c6b3",
+ "nonce" : "33b7682fbfa5a723",
+ "number" : "0x07",
+ "parentHash" : "5fc71cd93151a07d5c8e223178a472dfadf85c7c0d601c461bb2412ad90008cf",
+ "receiptTrie" : "aec104fc55d9aa0c1767af2dcf73c512f650f24bf89b9b78eb236d70a2de848f",
+ "stateRoot" : "40d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029",
+ "timestamp" : "0x5788dcfc",
+ "transactionsTrie" : "b2d17fa171d19df4e817ffb15f38526d125a42b7879cd712584b130dc8ad341c",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "7",
+ "rlp" : "0xf90260f901f9a05fc71cd93151a07d5c8e223178a472dfadf85c7c0d601c461bb2412ad90008cfa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a040d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029a0b2d17fa171d19df4e817ffb15f38526d125a42b7879cd712584b130dc8ad341ca0aec104fc55d9aa0c1767af2dcf73c512f650f24bf89b9b78eb236d70a2de848fb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018007832fefba82a042845788dcfc80a0f117fd70e501a76776c5dd7c227a2ae6d28aa5a4422b9ce31fdd3d57d411c6b38833b7682fbfa5a723f861f85f060182ea609410000000000000000000000000000000000000070a801ba0bb8523d4c53ed16b355d0a2dba02154d23a5480449dc3894be40ef95511d2fe9a010ad725c2df4979b7a071b3fa9b6b719223f0167d68b98f213e8611f84d4d81bc0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x06",
+ "r" : "0xbb8523d4c53ed16b355d0a2dba02154d23a5480449dc3894be40ef95511d2fe9",
+ "s" : "0x10ad725c2df4979b7a071b3fa9b6b719223f0167d68b98f213e8611f84d4d81b",
+ "to" : "1000000000000000000000000000000000000007",
+ "v" : "0x1b",
+ "value" : "0x0a"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blocknumber" : "8",
+ "rlp" : "0xf901e8f901e3a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808080a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c0c0"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x0201c0",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x00",
+ "hash" : "0101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322",
+ "mixHash" : "90da7c2e5e892d3ca197843e4d70c4c1b4db9b437f6911c7dc0cb2e9b5ce5be0",
+ "nonce" : "51dac304188a318e",
+ "number" : "0x08",
+ "parentHash" : "faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "2c4f51b520aa26de8db4dc7d8d70eb0bbf8ce35afc6d61ed09881869d2feaa78",
+ "timestamp" : "0x5788dd05",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "bea28d341a7519c623e60a8f6eb59c216e918b839e87eb3004af1896aea29397"
+ },
+ "blocknumber" : "8",
+ "rlp" : "0xf90405f90204a0faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265a0bea28d341a7519c623e60a8f6eb59c216e918b839e87eb3004af1896aea29397948888f1f195afa192cfee860698584c030f4c9db1a02c4f51b520aa26de8db4dc7d8d70eb0bbf8ce35afc6d61ed09881869d2feaa78a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201c008832fefba80845788dd058d64616f2d686172642d666f726ba090da7c2e5e892d3ca197843e4d70c4c1b4db9b437f6911c7dc0cb2e9b5ce5be08851dac304188a318ec0f901faf901f7a05fc71cd93151a07d5c8e223178a472dfadf85c7c0d601c461bb2412ad90008cfa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a005ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014007832fefba80845788dd0480a0afe4af48fc8d02068f2f45db556679093e0bff8e468f09bb9cc85565eb4917db88b0ae44f2f84decfb",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "0000000000000000000000000000000000000000",
+ "difficulty" : "0x020140",
+ "extraData" : "0x",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x00",
+ "hash" : "e4dd13214af7bbb7505256ae793b3ab744b9c055a296e31460ff7e8bc5854730",
+ "mixHash" : "afe4af48fc8d02068f2f45db556679093e0bff8e468f09bb9cc85565eb4917db",
+ "nonce" : "b0ae44f2f84decfb",
+ "number" : "0x07",
+ "parentHash" : "5fc71cd93151a07d5c8e223178a472dfadf85c7c0d601c461bb2412ad90008cf",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "05ecd1a706137ddc9359328005f80a4ca233a4dc443748b04275e3ef6faed174",
+ "timestamp" : "0x5788dd04",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ }
+ ]
+ },
+ {
+ "blocknumber" : "9",
+ "rlp" : "0xf90670f90206a00101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322a0e51c2b710360bb753022b0c98232a56129062b29e1c0821d3370f09f9fd41a45948888f1f195afa192cfee860698584c030f4c9db1a0f57f69858375f69a698ad907ede7a2475a95cce18e5f17b612a3e3083c5106ada0964e2a482dc1856fff3b00f545aaf8720aeef70a3ffe86cebf05bbc2c34bf539a05691b60b35567c06fd15723f333ee23a85b059e2a63e05b1bf0dd6a61d10b7d4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201c009832fefba8265aa845788dd188d64616f2d686172642d666f726ba0da8d1ebb0584e85f5eedc7d7468eb7884f13698a02ddc85e880dfc193ca7b3d3887bb80ac0706f11e9f861f85f070182ea6094100000000000000000000000000000000000000801801ba09e18981c45e9f6bb54e3f52cae58f2c3c00f2220a9f1c788d0ee3fc2394d4956a038207c17c10faae1fa83bff79770fa38134a19b6ca6f04059d7a307c05f67e6af90401f90204a0faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a040d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018008832fefba80845788dd0c8d64616f2d686172642d666f726ba0ded20d0e31e931d74374026b4b931f0510b1c0b02fb3f76312195b8b74ad83938806b256afd30a542ff901f7a0faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a040d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014008832fefba80845788dd1180a05c67667031b65a3d1520ab7fd79fd1dcc53b608155235f19ce92b2104bf7d51a887a3058ce3363d576"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x65aa",
+ "hash" : "47fbd76ebee44e255941f76197c8ea50697e4b5d2f07477575ad1b1b2d4f0467",
+ "mixHash" : "fcb6b3c42755d3c943c7b97da78fe729cc791d53631f140f3c2466ad06098282",
+ "nonce" : "f4e5de74b2c0afd3",
+ "number" : "0x09",
+ "parentHash" : "0101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322",
+ "receiptTrie" : "5691b60b35567c06fd15723f333ee23a85b059e2a63e05b1bf0dd6a61d10b7d4",
+ "stateRoot" : "f57f69858375f69a698ad907ede7a2475a95cce18e5f17b612a3e3083c5106ad",
+ "timestamp" : "0x5788dd1f",
+ "transactionsTrie" : "964e2a482dc1856fff3b00f545aaf8720aeef70a3ffe86cebf05bbc2c34bf539",
+ "uncleHash" : "c2c05564ceaf59f1a73e832e24ac60cf96e3cc220e0479ebaf09f12977707461"
+ },
+ "blocknumber" : "9",
+ "rlp" : "0xf90476f90206a00101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322a0c2c05564ceaf59f1a73e832e24ac60cf96e3cc220e0479ebaf09f12977707461948888f1f195afa192cfee860698584c030f4c9db1a0f57f69858375f69a698ad907ede7a2475a95cce18e5f17b612a3e3083c5106ada0964e2a482dc1856fff3b00f545aaf8720aeef70a3ffe86cebf05bbc2c34bf539a05691b60b35567c06fd15723f333ee23a85b059e2a63e05b1bf0dd6a61d10b7d4b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018009832fefba8265aa845788dd1f8d64616f2d686172642d666f726ba0fcb6b3c42755d3c943c7b97da78fe729cc791d53631f140f3c2466ad0609828288f4e5de74b2c0afd3f861f85f070182ea6094100000000000000000000000000000000000000801801ba09e18981c45e9f6bb54e3f52cae58f2c3c00f2220a9f1c788d0ee3fc2394d4956a038207c17c10faae1fa83bff79770fa38134a19b6ca6f04059d7a307c05f67e6af90207f90204a0faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a040d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302010008832fefba80845788dd1d8d64616f2d686172642d666f726ba03ced26fe3256e9f8287b52861a5582a4b551fd0b7f3a65411cb86f141ece54598895fa805c6deebdfd",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x07",
+ "r" : "0x9e18981c45e9f6bb54e3f52cae58f2c3c00f2220a9f1c788d0ee3fc2394d4956",
+ "s" : "0x38207c17c10faae1fa83bff79770fa38134a19b6ca6f04059d7a307c05f67e6a",
+ "to" : "1000000000000000000000000000000000000008",
+ "v" : "0x1b",
+ "value" : "0x01"
+ }
+ ],
+ "uncleHeaders" : [
+ {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "0000000000000000000000000000000000000000",
+ "difficulty" : "0x020100",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x00",
+ "hash" : "7c8dd6f59379615cff1a7edbb0a9060d824d86d19ec8447c1b580ca6859e6c05",
+ "mixHash" : "3ced26fe3256e9f8287b52861a5582a4b551fd0b7f3a65411cb86f141ece5459",
+ "nonce" : "95fa805c6deebdfd",
+ "number" : "0x08",
+ "parentHash" : "faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "40d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029",
+ "timestamp" : "0x5788dd1d",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ }
+ ]
+ },
+ {
+ "blocknumber" : "10",
+ "rlp" : "0xf90455f90206a047fbd76ebee44e255941f76197c8ea50697e4b5d2f07477575ad1b1b2d4f0467a09669b09c1fca3cae0e8a34eca70a63fbc62c36715074e8b75cc649da0a149396948888f1f195afa192cfee860698584c030f4c9db1a0a536759560008986d9adbb774618686a1a7cf849a2c08c5f6a047e9a3de66945a0f49ed12e4a98811e40b2cd24a470e3ff48ab6c1887d36fa68f79440321685d00a0f07f905c4fcfce60993e277c6ccd5bf0eacae30e71b10fa765fd98b046ada645b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201c00a832fefba82cf08845788dd258d64616f2d686172642d666f726ba0340f8760a46bbb41fc96589bc68ff07cf828b32e8a32fbc3fe6f373973472dd288fb347ffe902d0bb1f84df84b080182ea608001801ba066a8a933ff9208ecb2334a7edcf0592751d68e5e9cf155814238cd3072a7d38ba02cd8720983a8172b1304aad194d3f2ea3daeaf5c51bc3dc983d8218448f063bdf901faf901f7a00101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a02c4f51b520aa26de8db4dc7d8d70eb0bbf8ce35afc6d61ed09881869d2feaa78a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014009832fefba80845788dd2380a0eeea53c657dbbb61a2e239cef19464574829fd2284728bf311e1c94230a118b9886f043bd4378b18cd"
+ },
+ {
+ "blocknumber" : "11",
+ "rlp" : "0xf905fff90204a047fbd76ebee44e255941f76197c8ea50697e4b5d2f07477575ad1b1b2d4f0467a02332e0883af77a9c57cd2f1dbd55f7c2b6a7b3a0946ebb94e9d29a7d6559428d948888f1f195afa192cfee860698584c030f4c9db1a09e8229dc7d51defa7f3d18c110cb776f2807f6a244dfe9775a5ecbbaa2d97527a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201800a832fefba80845788dd2d8d64616f2d686172642d666f726ba0413905ed55d67309eb11a9d2a12b786f94b7c0e70d79ffa08d9cdce8efaa34cb8852cdc9bfdccf22cac0f903f4f901f7a00101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a02c4f51b520aa26de8db4dc7d8d70eb0bbf8ce35afc6d61ed09881869d2feaa78a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014009832fefba80845788dd2980a0ec71a16d14838a637784d4f25a4641b290ef1ad4f726d59b659709e38a690f7a88dc1dbd1bb6d69415f901f7a047fbd76ebee44e255941f76197c8ea50697e4b5d2f07477575ad1b1b2d4f0467a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f57f69858375f69a698ad907ede7a2475a95cce18e5f17b612a3e3083c5106ada056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201800a832fefba80845788dd2a80a0d611411c515295dfe7b7b60021f8542f99e82959d67d00d8ea830a10fdb700d28863bbcc6e20f60707"
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020140",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x5208",
+ "hash" : "ca32dc51f04be8d5858f1565794edafc5b558c66aabbd5b468fdd9e5f2b0dde2",
+ "mixHash" : "4c8184afdf266ded8ba03efefb9b383f124af8a420d4b0623724e76c16362309",
+ "nonce" : "df8d645fe80a1c5f",
+ "number" : "0x0a",
+ "parentHash" : "47fbd76ebee44e255941f76197c8ea50697e4b5d2f07477575ad1b1b2d4f0467",
+ "receiptTrie" : "e3e8a54108fb9689ac6f724e4f0189db4bb7df7ca6f343f939195449e94c54a8",
+ "stateRoot" : "c1673db25cd7b78891984f84cb2d44a435b87c0408f9faac1b0771f3221034c9",
+ "timestamp" : "0x5788dd37",
+ "transactionsTrie" : "916147a0805a950d8cc91ea336b3b7237474ac724029dc99f96b07eef085e4d7",
+ "uncleHash" : "5c1818947711e59c2039312ff6f53c67abf9c4bdc9aa558ade6acd0fb82d4c68"
+ },
+ "blocknumber" : "10",
+ "rlp" : "0xf9067df90206a047fbd76ebee44e255941f76197c8ea50697e4b5d2f07477575ad1b1b2d4f0467a05c1818947711e59c2039312ff6f53c67abf9c4bdc9aa558ade6acd0fb82d4c68948888f1f195afa192cfee860698584c030f4c9db1a0c1673db25cd7b78891984f84cb2d44a435b87c0408f9faac1b0771f3221034c9a0916147a0805a950d8cc91ea336b3b7237474ac724029dc99f96b07eef085e4d7a0e3e8a54108fb9689ac6f724e4f0189db4bb7df7ca6f343f939195449e94c54a8b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201400a832fefba825208845788dd378d64616f2d686172642d666f726ba04c8184afdf266ded8ba03efefb9b383f124af8a420d4b0623724e76c1636230988df8d645fe80a1c5ff861f85f080182ea609410000000000000000000000000000000000000106f801ba047acd0e2edbc13fbfed74b1b5e6f5afaae464ff6662fc15fc76cf16f6821a72da02e989a61feb7751d802ec9ec12d30a6c419a65c8ba6acd96857a73c18b6a5564f9040ef90204a0faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a040d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008008832fefba80845788dd338d64616f2d686172642d666f726ba0b4857ee254e0403f258dc214738b57bf08690794e4c438012eb18c507fa2ae9588e806cb4705dd9c46f90204a00101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a02c4f51b520aa26de8db4dc7d8d70eb0bbf8ce35afc6d61ed09881869d2feaa78a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302010009832fefba80845788dd338d64616f2d686172642d666f726ba006254cab91d3348cf91a9db6ea7f1f94943b6647a3b1ac2be6f1d0f2773bf0e088edc8d858b2798c52",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x08",
+ "r" : "0x47acd0e2edbc13fbfed74b1b5e6f5afaae464ff6662fc15fc76cf16f6821a72d",
+ "s" : "0x2e989a61feb7751d802ec9ec12d30a6c419a65c8ba6acd96857a73c18b6a5564",
+ "to" : "1000000000000000000000000000000000000010",
+ "v" : "0x1b",
+ "value" : "0x6f"
+ }
+ ],
+ "uncleHeaders" : [
+ {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "0000000000000000000000000000000000000000",
+ "difficulty" : "0x020080",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x00",
+ "hash" : "12fc96f2e58a510584d8e01a02b2834c293945bba1e1f2fc48b539d345febe90",
+ "mixHash" : "b4857ee254e0403f258dc214738b57bf08690794e4c438012eb18c507fa2ae95",
+ "nonce" : "e806cb4705dd9c46",
+ "number" : "0x08",
+ "parentHash" : "faf53d9cbf0bb0503e4313936019eb34a342b75770f6c2d92412d1fe38a99265",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "40d119003a07ed2dece2e87393e1affed584f81ee4c8c262e27984b10356a029",
+ "timestamp" : "0x5788dd33",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "0000000000000000000000000000000000000000",
+ "difficulty" : "0x020100",
+ "extraData" : "0x64616f2d686172642d666f726b",
+ "gasLimit" : "0x2fefba",
+ "gasUsed" : "0x00",
+ "hash" : "f1ae04879bd8627a69a274c283ed05a38a985bae61d9cf553f4b9453c1d5a601",
+ "mixHash" : "06254cab91d3348cf91a9db6ea7f1f94943b6647a3b1ac2be6f1d0f2773bf0e0",
+ "nonce" : "edc8d858b2798c52",
+ "number" : "0x09",
+ "parentHash" : "0101dba7ec26e5cbe190ca00a34ce4b6f7ead20b0e77ebc8db7ea02eb4d56322",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "2c4f51b520aa26de8db4dc7d8d70eb0bbf8ce35afc6d61ed09881869d2feaa78",
+ "timestamp" : "0x5788dd33",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ }
+ ]
+ }
+ ],
+ "genesisBlockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x42",
+ "gasLimit" : "0x2fefd8",
+ "gasUsed" : "0x00",
+ "hash" : "cad74b3b4723472b370737ffaf503f6f746bcae45bd5a39d767c5647afa5bb09",
+ "mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "nonce" : "0102030405060708",
+ "number" : "0x00",
+ "parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "6bff69e94b94f30e1b69f86d3e09712edfb583ac73a46a522345e1965ca9c66d",
+ "timestamp" : "0x54c98c81",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a06bff69e94b94f30e1b69f86d3e09712edfb583ac73a46a522345e1965ca9c66da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
+ "lastblockhash" : "ca32dc51f04be8d5858f1565794edafc5b558c66aabbd5b468fdd9e5f2b0dde2",
+ "postState" : {
+ "0000000000000000000000000000000000000000" : {
+ "balance" : "0xea300b17a8b78000",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0c243ebe6a031753dc0dd850acf422844a3efb76" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000007" : {
+ "balance" : "0x0a",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ "0x00" : "0x02540be400"
+ }
+ },
+ "1000000000000000000000000000000000000008" : {
+ "balance" : "0x01",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000010" : {
+ "balance" : "0x6f",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "248f0f0f33eadb89e9d87fd5c127f58567f3ffde" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "85c2f277588ea1e6901ed59e587bea222c575f87" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8888f1f195afa192cfee860698584c030f4c9db1" : {
+ "balance" : "0x02be902146fa2abe24",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x3b968b26",
+ "code" : "0x",
+ "nonce" : "0x09",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b1d37cf6180ceb738ca45b5005a2f418c02e204b" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bf4ed7b27f1d666546e30d74d50d173d20bca754" : {
+ "balance" : "0x010bc166ae40",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : {
+ "balance" : "0x0a",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ },
+ "pre" : {
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000007" : {
+ "balance" : "0x00",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000008" : {
+ "balance" : "0x00",
+ "code" : "0x73807640a13483f8ac783c557fcdf27be11ea4ac7a31600055",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x3b9aca00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x0f4240",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ }
+ },
+ "DaoTransactions_XBlockm1" : {
+ "blocks" : [
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x",
+ "gasLimit" : "0x12b501f5",
+ "gasUsed" : "0x00",
+ "hash" : "7f8d325fa7077dffa1aef268597e0fa735306bb937866e3eb73bfcb11eaeb65b",
+ "mixHash" : "a41acffbfc68c63efb5df04aaa733d9d6a28826dc367a8a2770bc02486219532",
+ "nonce" : "14742b9b68fab457",
+ "number" : "0x01",
+ "parentHash" : "76de3875ca93859a55779bf4c963c58dda6eed39cb34c9f8d1360580f299b16a",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "17d99e7cdc3d010789109a0d1733004627c114253436be8b343b74dc8bc77dc4",
+ "timestamp" : "0x5788dd3f",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "1",
+ "rlp" : "0xf901fdf901f8a076de3875ca93859a55779bf4c963c58dda6eed39cb34c9f8d1360580f299b16aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a017d99e7cdc3d010789109a0d1733004627c114253436be8b343b74dc8bc77dc4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018412b501f580845788dd3f80a0a41acffbfc68c63efb5df04aaa733d9d6a28826dc367a8a2770bc024862195328814742b9b68fab457c0c0",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020040",
+ "extraData" : "0x",
+ "gasLimit" : "0x12b054b6",
+ "gasUsed" : "0x00",
+ "hash" : "b41308b0a12c1b1a06208b827d9dd659619d47b163b9b8c1b1feedbaad7a64af",
+ "mixHash" : "e56494277ca75cf1ec6060f31d34b45d76e7a133363acdffc1f512a0528a710b",
+ "nonce" : "ee6d9193ba857f47",
+ "number" : "0x02",
+ "parentHash" : "7f8d325fa7077dffa1aef268597e0fa735306bb937866e3eb73bfcb11eaeb65b",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "a639bc369df2e6dcdb261e53927d3129e7e727054063bdb15fd31b8dfad3e67d",
+ "timestamp" : "0x5788dd46",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "2",
+ "rlp" : "0xf901fdf901f8a07f8d325fa7077dffa1aef268597e0fa735306bb937866e3eb73bfcb11eaeb65ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a639bc369df2e6dcdb261e53927d3129e7e727054063bdb15fd31b8dfad3e67da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020040028412b054b680845788dd4680a0e56494277ca75cf1ec6060f31d34b45d76e7a133363acdffc1f512a0528a710b88ee6d9193ba857f47c0c0",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020080",
+ "extraData" : "0x",
+ "gasLimit" : "0x12aba8a2",
+ "gasUsed" : "0x00",
+ "hash" : "21b654accfe3e0120ee79787bfc95a6f454f66ea5002ba0f0c84f7c2a6aa28ee",
+ "mixHash" : "b27d43fead80c5cc7c05c6345638d52e8a88e6da13b675a279afffa9aaa90ecb",
+ "nonce" : "08f46890e77a57a1",
+ "number" : "0x03",
+ "parentHash" : "b41308b0a12c1b1a06208b827d9dd659619d47b163b9b8c1b1feedbaad7a64af",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "8cf3da7258f9aa5c4deb300f6fce33a5fb374b363b64ebbd6a05a71ceaf62268",
+ "timestamp" : "0x5788dd4a",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "3",
+ "rlp" : "0xf901fdf901f8a0b41308b0a12c1b1a06208b827d9dd659619d47b163b9b8c1b1feedbaad7a64afa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a08cf3da7258f9aa5c4deb300f6fce33a5fb374b363b64ebbd6a05a71ceaf62268a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020080038412aba8a280845788dd4a80a0b27d43fead80c5cc7c05c6345638d52e8a88e6da13b675a279afffa9aaa90ecb8808f46890e77a57a1c0c0",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x0200c0",
+ "extraData" : "0x",
+ "gasLimit" : "0x12a6fdb9",
+ "gasUsed" : "0x00",
+ "hash" : "5473f8af2b586839c3298a36272c7753f57618fc65093a8af7ac4b6f6ea6e8ce",
+ "mixHash" : "81a197fb4cbcc54d7924aaa10c039113a4fe9b39aa6caebd4cb678c2c323630d",
+ "nonce" : "274ccd17ac4b439a",
+ "number" : "0x04",
+ "parentHash" : "21b654accfe3e0120ee79787bfc95a6f454f66ea5002ba0f0c84f7c2a6aa28ee",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "f9b0c98fed434c398e22415e46d50b0e928c2dc247c328cb0528ea94728eee3f",
+ "timestamp" : "0x5788dd50",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "4",
+ "rlp" : "0xf901fdf901f8a021b654accfe3e0120ee79787bfc95a6f454f66ea5002ba0f0c84f7c2a6aa28eea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0f9b0c98fed434c398e22415e46d50b0e928c2dc247c328cb0528ea94728eee3fa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200c0048412a6fdb980845788dd5080a081a197fb4cbcc54d7924aaa10c039113a4fe9b39aa6caebd4cb678c2c323630d88274ccd17ac4b439ac0c0",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020100",
+ "extraData" : "0x",
+ "gasLimit" : "0x12a253fb",
+ "gasUsed" : "0x00",
+ "hash" : "31865cc304691e510efdb76576c2b2294545bfcb406aae97337b762ca8ceb91a",
+ "mixHash" : "01dc5f253639977a6f67487657287d5997ff5bd061e0aa12409a3db38c6c5e4b",
+ "nonce" : "c645fb05954a417d",
+ "number" : "0x05",
+ "parentHash" : "5473f8af2b586839c3298a36272c7753f57618fc65093a8af7ac4b6f6ea6e8ce",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "27d25b8ec2fe581a790cf37c4c2be363799f12c8ebd70d6b703f30f676de6cd2",
+ "timestamp" : "0x5788dd54",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "5",
+ "rlp" : "0xf901fdf901f8a05473f8af2b586839c3298a36272c7753f57618fc65093a8af7ac4b6f6ea6e8cea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a027d25b8ec2fe581a790cf37c4c2be363799f12c8ebd70d6b703f30f676de6cd2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020100058412a253fb80845788dd5480a001dc5f253639977a6f67487657287d5997ff5bd061e0aa12409a3db38c6c5e4b88c645fb05954a417dc0c0",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020140",
+ "extraData" : "0x",
+ "gasLimit" : "0x129dab68",
+ "gasUsed" : "0x00",
+ "hash" : "f4dfacab1c75d769193ff4b46190ab4e758528bcad44e0723347f705de171142",
+ "mixHash" : "bdd40a39ba235400737c0587dc140a1dc02f51f1f7a716e4ba52a7723b614657",
+ "nonce" : "dc09580bc9ac6c81",
+ "number" : "0x06",
+ "parentHash" : "31865cc304691e510efdb76576c2b2294545bfcb406aae97337b762ca8ceb91a",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "186b7bee2b8ab05978991904147c7b4b58bd498e3c8a9932210f057ea7e38c62",
+ "timestamp" : "0x5788dd5a",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "6",
+ "rlp" : "0xf901fdf901f8a031865cc304691e510efdb76576c2b2294545bfcb406aae97337b762ca8ceb91aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0186b7bee2b8ab05978991904147c7b4b58bd498e3c8a9932210f057ea7e38c62a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201400684129dab6880845788dd5a80a0bdd40a39ba235400737c0587dc140a1dc02f51f1f7a716e4ba52a7723b61465788dc09580bc9ac6c81c0c0",
+ "transactions" : [
+ ],
+ "uncleHeaders" : [
+ ]
+ },
+ {
+ "blockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020180",
+ "extraData" : "0x",
+ "gasLimit" : "0x129903ff",
+ "gasUsed" : "0x5208",
+ "hash" : "b4fd754ea31355af44d104be9c93c4ff5c69e3de6692b84234bbffa2a8935762",
+ "mixHash" : "8b3b3daa6fef89706df93df25cd7160359b3029eb183dc0d03279db3e1d668fe",
+ "nonce" : "b8bc0f59998aca79",
+ "number" : "0x07",
+ "parentHash" : "f4dfacab1c75d769193ff4b46190ab4e758528bcad44e0723347f705de171142",
+ "receiptTrie" : "8494555e17e5455b9b7c734c4e6dd720a575f04e741302abecbb610896e1bdb4",
+ "stateRoot" : "6d5aa4970c1810949e15062da2fd638123b2b1cab467a18381676cc7dfbcb331",
+ "timestamp" : "0x5788dd60",
+ "transactionsTrie" : "2067f9535b492e7070dd88a15bd979eff4f2d03814c8514cdd8cb1b7715c6d6b",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "blocknumber" : "7",
+ "rlp" : "0xf90261f901faa0f4dfacab1c75d769193ff4b46190ab4e758528bcad44e0723347f705de171142a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a06d5aa4970c1810949e15062da2fd638123b2b1cab467a18381676cc7dfbcb331a02067f9535b492e7070dd88a15bd979eff4f2d03814c8514cdd8cb1b7715c6d6ba08494555e17e5455b9b7c734c4e6dd720a575f04e741302abecbb610896e1bdb4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201800784129903ff825208845788dd6080a08b3b3daa6fef89706df93df25cd7160359b3029eb183dc0d03279db3e1d668fe88b8bc0f59998aca79f861f85f800182ea6094100000000000000000000000000000000000000780801ba065741e61c886da761be2693206b25ef48db266aeb92b120137496d3c3b4a7429a05c16257cbbcd7f1076ca12277fe0f029835c2e5fe36796f1bf2d7b0edeca79afc0",
+ "transactions" : [
+ {
+ "data" : "0x",
+ "gasLimit" : "0xea60",
+ "gasPrice" : "0x01",
+ "nonce" : "0x00",
+ "r" : "0x65741e61c886da761be2693206b25ef48db266aeb92b120137496d3c3b4a7429",
+ "s" : "0x5c16257cbbcd7f1076ca12277fe0f029835c2e5fe36796f1bf2d7b0edeca79af",
+ "to" : "1000000000000000000000000000000000000007",
+ "v" : "0x1b",
+ "value" : "0x00"
+ }
+ ],
+ "uncleHeaders" : [
+ ]
+ }
+ ],
+ "genesisBlockHeader" : {
+ "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "extraData" : "0x42",
+ "gasLimit" : "0x12b9b060",
+ "gasUsed" : "0x00",
+ "hash" : "76de3875ca93859a55779bf4c963c58dda6eed39cb34c9f8d1360580f299b16a",
+ "mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "nonce" : "0102030405060708",
+ "number" : "0x00",
+ "parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "stateRoot" : "42b6c06dc02697e651f409032cfda2b524b81e1d12443b75648b2bedcbca4865",
+ "timestamp" : "0x54c98c81",
+ "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
+ },
+ "genesisRLP" : "0xf901fdf901f8a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a042b6c06dc02697e651f409032cfda2b524b81e1d12443b75648b2bedcbca4865a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808412b9b060808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
+ "lastblockhash" : "b4fd754ea31355af44d104be9c93c4ff5c69e3de6692b84234bbffa2a8935762",
+ "postState" : {
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1000000000000000000000000000000000000007" : {
+ "balance" : "0x00",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8888f1f195afa192cfee860698584c030f4c9db1" : {
+ "balance" : "0x01e5b8fa8fe2ac5208",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0xe8d4a4bdf8",
+ "code" : "0x",
+ "nonce" : "0x01",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x0f4240",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ },
+ "pre" : {
+ "005f5cee7a43331d5a3d3eec71305925a62f34b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "057b56736d32b86616a10f619859c6cd6f59092a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "06706dd3f2c9abf0a21ddcc6941d9b86f0596936" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0737a6b837f97f46ebade41b9bc3e1c509c85c53" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "07f5c1e1bc2c93e0402f23341973a0e043f7bf8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0e0da70933f4c7849fc0d203f5d1d43b9ae4532d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0ff30d6de14a8224aa97b78aea5388d1c51c1f00" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "12e626b0eebfe86a56d633b9864e389b45dcb260" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1591fc0f688c81fbeb17f5426a162a7024d430c2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "17802f43a0137c506ba92291391a8a8f207f487d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1975bd06d486162d5dc297798dfc41edd5d160a7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "1cba23d343a983e9b5cfd19496b9a9701ada385f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "200450f06520bdd6c527622a273333384d870efb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "23b75c2f6791eef49c69684db4c6c1f93bf49a50" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "24c4d950dfd4dd1902bbed3508144a54542bba94" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "253488078a4edf4d6f42f113d1e62836a942cf1a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "27b137a85656544b1ccb5a0f2e561a5703c6a68f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2a5ed960395e2a49b1c758cef4aa15213cfd874c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2b3455ec7fedf16e646268bf88846bd7a2319bb2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "2c19c7f9ae8b751e37aeb2d93a699722395ae18f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "304a554a310c7e546dfe434669c62820b7d83490" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "319f70bab6845585f412ec7724b744fec6095c85" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "35a051a0010aba705c9008d7a7eff6fb88f6ea7b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3ba4d81db016dc2890c81f3acec2454bff5aada5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "3c02a7bc0391e86d91b7d144e61c2c01a25a79c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "40b803a9abce16f50f36a77ba41180eb90023925" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "440c59b325d2997a134c2c7c60a8c61611212bad" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4486a3d68fac6967006d7a517b889fd3f98c102b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4613f3bca5c44ea06337a9e439fbc6d42e501d0a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "47e7aa56d6bdf3f36be34619660de61275420af8" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4863226780fe7c0356454236d3b1c8792785748d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "492ea3bb0f3315521c31f273e565b868fc090f17" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4cb31628079fb14e4bc3cd5e30c2f7489b00960c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4deb0033bb26bc534b197e61d19e0733e5679784" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fa802324e929786dbda3b8820dc7834e9134a2a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "4fd6ace747f06ece9c49699c7cabc62d02211f75" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "51e0ddd9998364a2eb38588679f0d2c42653e4a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "52c5317c848ba20c7504cb2c8052abd1fde29d03" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "542a9515200d14b68e934e9830d91645a980dd7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5524c55fb03cf21f549444ccbecb664d0acad706" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "579a80d909f346fbfb1189493f521d7f48d52238" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "58b95c9a9d5d26825e70a82b6adb139d3fd829eb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5c8536898fbb74fc7445814902fd08422eac56d0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5d2b2e6fcbe3b11d26b525e085ff818dae332479" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5dc28b15dffed94048d73806ce4b7a4612a1d48f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "5f9f3392e9f62f63b8eac0beb55541fc8627f42c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6131c42fa982e56929107413a9d526fd99405560" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6231b6d0d5e77fe001c2a460bd9584fee60d409b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "627a0a960c079c21c34f7612d5d230e01b4ad4c7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "63ed5a272de2f6d968408b4acb9024f4cc208ebf" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6966ab0d485353095148a2155858910e0965b6f9" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6d87578288b6cb5549d5076a207456a1f6a63dc0" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "6f6704e5a10332af6672e50b3d9754dc460dfa4d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "7602b46df5390e432ef1c307d4f2c9ff6d65cc97" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "779543a0491a837ca36ce8c635d6154e3c4911a6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "782495b7b3355efb2833d56ecb34dc22ad7dfcc4" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "807640a13483f8ac783c557fcdf27be11ea4ac7a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8163e7fb499e90f8544ea62bbf80d21cd26d9efd" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "84ef4b2357079cd7a7c69fd7a37cd0609a679106" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "86af3e9626fce1957c82e88cbf04ddf3a2ed7915" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "8d9edb3054ce5c5774a420ac37ebae0ac02343c6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "97f43a37f595ab5dd318fb46e7a155eae057317a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9aa008f65de0b923a2a4f02012ad034a5e2e2192" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c15b54878ba618f494b38f0ae7443db6af648ba" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9c50426be05db97f5d64fc54bf89eff947f0a321" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9da397b9e80755301a3b32173283a91c0ef6c87e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9ea779f907f0b315b364b0cfc39a0fde5b02a416" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9f27daea7aca0aa0446220b98d028715e3bc803d" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "9fcd2deaff372a39cc679d5c5e4de7bafb0b1339" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a2f1ccba9395d7fcb155bba8bc92db9bafaeade7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a3acf3a1e16b1d7c315e23510fdd7847b48234f6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a82f360a8d3455c5c41366975bde739c37bfeb8a" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0xe8d4a51000",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ac1ecab32727358dba8962a0f3b261731aad9723" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "accc230e8a6e5be9160b8cdf2864dd2a001c28b6" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "acd87e28b0c9d1254e868b81cba4cc20d9a32225" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "adf80daec7ba8dcf15392f1ac611fff65d94f880" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "aeeb8ff27288bdabc0fa5ebb731b6f409507516c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b136707642a4ea12fb4bae820f03d2562ebff487" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b3fb0e5aba0e20e5c49d252dfd30e102b171a425" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b52042c8ca3f8aa246fa79c3feaa3d959347c0ab" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "b9637156d330c0d605a791f1c31ba5890582fe1c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bb9bc244d798123fde783fcc1c72d3bb8c189413" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bc07118b9ac290e4622f5e77a0853539789effbe" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "bcf899e6c7d9d5a215ab1e3444c86806fa854c76" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "be8539bfe837b67d1282b2b1d61c3f723966f049" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "c4bbd073882dd2add2424cf47d35213405b01324" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ca544e5c4687d109611d0f8f928b53a25af72448" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cbb9d3703e651b0d496cdefb8b92c25aeb2171f7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "cc34673c6c40e791051898567a1222daf90be287" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ceaeb481747ca6c540a000c1f3641f8cef161fa7" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d131637d5275fd1a68a3200f4ad25c71a2a9522e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d164b088bd9108b60d0ca3751da4bceb207b0782" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d1ac8b1ef1b69ff51d1d401a476e7e612414f091" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d343b217de44030afaa275f54d31a9317c7f441e" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d4fe7bc31cedb7bfb8a345f31e668033056b2728" : {
+ "balance" : "0x0f4240",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "d9aef3a1e38a39c16b31d1ace71bca8ef58d315b" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "da2fef9e4a3230988ff17df2165440f37e8b1708" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "dbe9b615a3ae8709af8b93336ce9b477e4ac0940" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e308bd1ac5fda103967359b2712dd89deffb7973" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "e4ae1efdfc53b73893af49113d8694a057b9c0d1" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "ecd135fa4f61a655311e86238c92adcd779555d2" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f0b1aa0eb660754448a7937c022e30aa692fe0c5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f1385fb24aad0cd7432824085e42aff90886fef5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f14c14075d6c4ed84b86798af0956deef67365b5" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "f4c64518ea10f995918a454158c6b61407ea345c" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "fe24cdd8648121a43a7c86d289be4dd2951ed49f" : {
+ "balance" : "0x02540be400",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+ }
+ }
+}
diff --git a/tests/util.go b/tests/util.go
index 035903ccc..8d1917d15 100644
--- a/tests/util.go
+++ b/tests/util.go
@@ -141,6 +141,8 @@ type VmTest struct {
type RuleSet struct {
HomesteadBlock *big.Int
+ DAOForkBlock *big.Int
+ DAOForkSupport bool
}
func (r RuleSet) IsHomestead(n *big.Int) bool {
@@ -207,7 +209,6 @@ func NewEnvFromMap(ruleSet RuleSet, state *state.StateDB, envValues map[string]s
return env
}
-func (self *Env) MarkCodeHash(common.Hash) {}
func (self *Env) RuleSet() vm.RuleSet { return self.ruleSet }
func (self *Env) Vm() vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return self.origin }
@@ -313,4 +314,5 @@ func (self Message) GasPrice() *big.Int { return self.price }
func (self Message) Gas() *big.Int { return self.gas }
func (self Message) Value() *big.Int { return self.value }
func (self Message) Nonce() uint64 { return self.nonce }
+func (self Message) CheckNonce() bool { return true }
func (self Message) Data() []byte { return self.data }
diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go
index 2f516951b..37f0af33c 100644
--- a/tests/vm_test_util.go
+++ b/tests/vm_test_util.go
@@ -241,7 +241,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs,
caller := state.GetOrNewStateObject(from)
- vmenv := NewEnvFromMap(RuleSet{params.MainNetHomesteadBlock}, state, env, exec)
+ vmenv := NewEnvFromMap(RuleSet{params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, true}, state, env, exec)
vmenv.vmTest = true
vmenv.skipTransfer = true
vmenv.initial = true