aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Godeps/Godeps.json12
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml19
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/README.md17
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/appveyor.yml43
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go576
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go176
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go25
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/setup.py47
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/CMakeLists.txt46
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/benchmark.cpp63
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/CMakeLists.txt2
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.cpp143
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.h26
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner_kernel.cl5
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/CMakeLists.txt5
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/data_sizes.h1476
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/endian.h74
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/ethash.h215
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/fnv.h7
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c630
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h149
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.c129
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h197
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_posix.c102
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c103
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap.h47
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap_win32.c84
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.c194
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.h12
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.cpp14
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.h7
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h10
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util_win32.c (renamed from Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.c)9
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/python/core.c79
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/test/c/CMakeLists.txt13
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp879
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.sh13
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/test/go/ethash_test.go82
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/test/test.sh9
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-colorable/README.md42
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go16
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go594
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-isatty/README.md37
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-isatty/doc.go2
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_bsd.go17
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_linux.go17
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_windows.go18
-rw-r--r--cmd/geth/admin.go103
-rw-r--r--cmd/geth/js.go4
-rw-r--r--cmd/geth/main.go50
-rw-r--r--cmd/mist/bindings.go2
-rw-r--r--cmd/mist/ui_lib.go1
-rw-r--r--cmd/utils/flags.go2
-rw-r--r--common/resolver/resolver.go4
-rw-r--r--common/types.go15
-rw-r--r--core/chain_makers.go4
-rw-r--r--core/chain_manager.go31
-rw-r--r--core/transaction_pool.go2
-rw-r--r--eth/backend.go10
-rw-r--r--eth/downloader/downloader.go344
-rw-r--r--eth/downloader/downloader_test.go91
-rw-r--r--eth/downloader/queue.go65
-rw-r--r--eth/downloader/queue_test.go62
-rw-r--r--eth/handler.go159
-rw-r--r--eth/sync.go108
-rw-r--r--jsre/jsre.go233
-rw-r--r--jsre/jsre_test.go28
-rw-r--r--miner/agent.go2
-rw-r--r--miner/miner.go7
-rw-r--r--p2p/discover/database.go2
-rw-r--r--p2p/discover/database_test.go74
-rw-r--r--p2p/discover/node.go98
-rw-r--r--p2p/discover/node_test.go95
-rw-r--r--p2p/discover/table.go72
-rw-r--r--p2p/discover/table_test.go352
-rw-r--r--p2p/discover/udp.go114
-rw-r--r--p2p/discover/udp_test.go99
-rw-r--r--p2p/handshake_test.go12
-rw-r--r--p2p/peer.go2
-rw-r--r--p2p/server.go2
-rw-r--r--p2p/server_test.go8
-rw-r--r--pow/dagger/dagger.go6
-rw-r--r--pow/ezp/pow.go8
-rw-r--r--pow/pow.go2
-rw-r--r--rpc/api.go8
-rw-r--r--rpc/args.go10
-rw-r--r--rpc/jeth.go69
-rw-r--r--tests/block_test.go14
-rw-r--r--xeth/xeth.go10
89 files changed, 5815 insertions, 3051 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 576efab00..2480ff9a2 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -17,8 +17,8 @@
},
{
"ImportPath": "github.com/ethereum/ethash",
- "Comment": "v23.1-82-g908aad3",
- "Rev": "908aad345c9fbf3ab9bbb94031dc02d0d90df1b8"
+ "Comment": "v23.1-195-g4d50db9",
+ "Rev": "4d50db90d8bb5f2fae357570366cb8c657a4ddfc"
},
{
"ImportPath": "github.com/howeyc/fsnotify",
@@ -38,6 +38,14 @@
"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
},
{
+ "ImportPath": "github.com/mattn/go-colorable",
+ "Rev": "043ae16291351db8465272edf465c9f388161627"
+ },
+ {
+ "ImportPath": "github.com/mattn/go-isatty",
+ "Rev": "fdbe02a1b44e75977b2690062b83cf507d70c013"
+ },
+ {
"ImportPath": "github.com/obscuren/qml",
"Rev": "c288002b52e905973b131089a8a7c761d4a2c36a"
},
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml b/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml
index 30e944a68..b83b02bf3 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml
@@ -1,14 +1,23 @@
-# making our travis.yml play well with C++11 by obtaining g++4.8
-# Taken from this file:
-# https://github.com/beark/ftl/blob/master/.travis.yml
+language: go
+go:
+ - 1.4.2
+
before_install:
+ # for g++4.8 and C++11
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
+
+ # Set up go-ethereum
- sudo apt-get update -y -qq
+ - sudo apt-get install -yqq libgmp3-dev
+ - git clone --depth=10 https://github.com/ethereum/go-ethereum ${GOPATH}/src/github.com/ethereum/go-ethereum
+ # use canned dependencies from the go-ethereum repository
+ - export GOPATH=$GOPATH:$GOPATH/src/github.com/ethereum/go-ethereum/Godeps/_workspace/
+ - echo $GOPATH
install:
+ # need to explicitly request version 1.48 since by default we get 1.46 which does not work with C++11
- sudo apt-get install -qq --yes --force-yes g++-4.8
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50
- # need to explicitly request version 1.48 since by default we get 1.46 which does not work with C++11
- - sudo apt-get install -qq wget cmake bash libboost-test1.48-dev libboost-system1.48-dev libboost-filesystem1.48-dev nodejs python-pip python-dev
+ - sudo apt-get install -qq wget cmake bash libboost-test1.48-dev libboost-system1.48-dev libboost-filesystem1.48-dev nodejs python-pip python-dev valgrind
- sudo pip install virtualenv -q
script: "./test/test.sh"
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/README.md b/Godeps/_workspace/src/github.com/ethereum/ethash/README.md
index 8b9e015cf..2b2c3b544 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/README.md
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/README.md
@@ -1,7 +1,22 @@
[![Build Status](https://travis-ci.org/ethereum/ethash.svg?branch=master)](https://travis-ci.org/ethereum/ethash)
-
+[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/debris/ethash?branch=master&svg=true)](https://ci.appveyor.com/project/debris/ethash-nr37r/branch/master)
# Ethash
For details on this project, please see the Ethereum wiki:
https://github.com/ethereum/wiki/wiki/Ethash
+
+### Coding Style for C++ code:
+
+Follow the same exact style as in [cpp-ethereum](https://github.com/ethereum/cpp-ethereum/blob/develop/CodingStandards.txt)
+
+### Coding Style for C code:
+
+The main thing above all is code consistency.
+
+- Tabs for indentation. A tab is 4 spaces
+- Try to stick to the [K&R](http://en.wikipedia.org/wiki/Indent_style#K.26R_style),
+ especially for the C code.
+- Keep the line lengths reasonable. No hard limit on 80 characters but don't go further
+ than 110. Some people work with multiple buffers next to each other.
+ Make them like you :)
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/appveyor.yml b/Godeps/_workspace/src/github.com/ethereum/ethash/appveyor.yml
new file mode 100644
index 000000000..ac36a0626
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/appveyor.yml
@@ -0,0 +1,43 @@
+version: 1.0.0.{build}
+
+environment:
+ BOOST_ROOT: "c:/projects/ethash/deps/boost"
+
+branches:
+ only:
+ - master
+ - develop
+
+os: Windows Server 2012 R2
+
+clone_folder: c:\projects\ethash
+
+#platform: Any CPU
+#configuration: Debug
+
+install:
+ # by default, all script lines are interpreted as batch
+
+# scripts to run before build
+before_build:
+ - echo "Downloading boost..."
+ - mkdir c:\projects\ethash\deps
+ - cd c:\projects\ethash\deps
+ - curl -O https://build.ethdev.com/builds/windows-precompiled/boost.tar.gz
+ - echo "Unzipping boost..."
+ - 7z x boost.tar.gz > nul
+ - 7z x boost.tar > nul
+ - ls
+ - echo "Running cmake..."
+ - cd c:\projects\ethash
+ - cmake .
+
+build:
+ project: ALL_BUILD.vcxproj # path to Visual Studio solution or project
+
+after_build:
+ - echo "Running tests..."
+ - cd c:\projects\ethash\test\c\Debug
+ - Test.exe
+ - echo "Finished!"
+
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
index 74285a33c..5b94711c4 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
@@ -1,32 +1,22 @@
-/*
-###################################################################################
-###################################################################################
-#################### ####################
-#################### EDIT AND YOU SHALL FEEL MY WRATH - jeff ####################
-#################### ####################
-###################################################################################
-###################################################################################
-*/
-
package ethash
/*
-#cgo CFLAGS: -std=gnu99 -Wall
-#include "src/libethash/util.c"
-#include "src/libethash/internal.c"
-#include "src/libethash/sha3.c"
+#include "src/libethash/internal.h"
+
+int ethashGoCallback_cgo(unsigned);
*/
import "C"
import (
- "bytes"
- "encoding/binary"
+ "errors"
"fmt"
"io/ioutil"
"math/big"
"math/rand"
"os"
- "path"
+ "os/user"
+ "path/filepath"
+ "runtime"
"sync"
"time"
"unsafe"
@@ -38,318 +28,267 @@ import (
"github.com/ethereum/go-ethereum/pow"
)
-var minDifficulty = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0))
-
-type ParamsAndCache struct {
- params *C.ethash_params
- cache *C.ethash_cache
- Epoch uint64
-}
-
-type DAG struct {
- dag unsafe.Pointer // full GB of memory for dag
- file bool
- paramsAndCache *ParamsAndCache
-}
-
-type Ethash struct {
- turbo bool
- HashRate int64
- chainManager pow.ChainManager
- dag *DAG
- paramsAndCache *ParamsAndCache
- ret *C.ethash_return_value
- dagMutex *sync.RWMutex
- cacheMutex *sync.RWMutex
-}
+var (
+ minDifficulty = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0))
+ sharedLight = new(Light)
+)
-func parseNonce(nonce []byte) (uint64, error) {
- nonceBuf := bytes.NewBuffer(nonce)
- nonceInt, err := binary.ReadUvarint(nonceBuf)
- if err != nil {
- return 0, err
- }
- return nonceInt, nil
-}
+const (
+ epochLength uint64 = 30000
+ cacheSizeForTesting C.uint64_t = 1024
+ dagSizeForTesting C.uint64_t = 1024 * 32
+)
-const epochLength uint64 = 30000
+var DefaultDir = defaultDir()
-func makeParamsAndCache(chainManager pow.ChainManager, blockNum uint64) (*ParamsAndCache, error) {
- if blockNum >= epochLength*2048 {
- return nil, fmt.Errorf("block number is out of bounds (value %v, limit is %v)", blockNum, epochLength*2048)
+func defaultDir() string {
+ home := os.Getenv("HOME")
+ if user, err := user.Current(); err == nil {
+ home = user.HomeDir
}
- paramsAndCache := &ParamsAndCache{
- params: new(C.ethash_params),
- cache: new(C.ethash_cache),
- Epoch: blockNum / epochLength,
+ if runtime.GOOS == "windows" {
+ return filepath.Join(home, "AppData", "Ethash")
}
- C.ethash_params_init(paramsAndCache.params, C.uint32_t(uint32(blockNum)))
- paramsAndCache.cache.mem = C.malloc(C.size_t(paramsAndCache.params.cache_size))
-
- seedHash, err := GetSeedHash(blockNum)
- if err != nil {
- return nil, err
- }
-
- glog.V(logger.Info).Infof("Making cache for epoch: %d (%v) (%x)\n", paramsAndCache.Epoch, blockNum, seedHash)
- start := time.Now()
- C.ethash_mkcache(paramsAndCache.cache, paramsAndCache.params, (*C.ethash_blockhash_t)(unsafe.Pointer(&seedHash[0])))
+ return filepath.Join(home, ".ethash")
+}
- if glog.V(logger.Info) {
- glog.Infoln("Took:", time.Since(start))
- }
+// cache wraps an ethash_light_t with some metadata
+// and automatic memory management.
+type cache struct {
+ epoch uint64
+ test bool
- return paramsAndCache, nil
+ gen sync.Once // ensures cache is only generated once.
+ ptr *C.struct_ethash_light
}
-func (pow *Ethash) UpdateCache(blockNum uint64, force bool) error {
- pow.cacheMutex.Lock()
- defer pow.cacheMutex.Unlock()
-
- thisEpoch := blockNum / epochLength
- if force || pow.paramsAndCache.Epoch != thisEpoch {
- var err error
- pow.paramsAndCache, err = makeParamsAndCache(pow.chainManager, blockNum)
- if err != nil {
- panic(err)
+// generate creates the actual cache. it can be called from multiple
+// goroutines. the first call will generate the cache, subsequent
+// calls wait until it is generated.
+func (cache *cache) generate() {
+ cache.gen.Do(func() {
+ started := time.Now()
+ seedHash := makeSeedHash(cache.epoch)
+ glog.V(logger.Debug).Infof("Generating cache for epoch %d (%x)", cache.epoch, seedHash)
+ size := C.ethash_get_cachesize(C.uint64_t(cache.epoch * epochLength))
+ if cache.test {
+ size = cacheSizeForTesting
}
- }
-
- return nil
+ cache.ptr = C.ethash_light_new_internal(size, (*C.ethash_h256_t)(unsafe.Pointer(&seedHash[0])))
+ runtime.SetFinalizer(cache, freeCache)
+ glog.V(logger.Debug).Infof("Done generating cache for epoch %d, it took %v", cache.epoch, time.Since(started))
+ })
}
-func makeDAG(p *ParamsAndCache) *DAG {
- d := &DAG{
- dag: C.malloc(C.size_t(p.params.full_size)),
- file: false,
- paramsAndCache: p,
- }
+func freeCache(cache *cache) {
+ C.ethash_light_delete(cache.ptr)
+ cache.ptr = nil
+}
- donech := make(chan string)
- go func() {
- t := time.NewTicker(5 * time.Second)
- tstart := time.Now()
- done:
- for {
- select {
- case <-t.C:
- glog.V(logger.Info).Infof("... still generating DAG (%v) ...\n", time.Since(tstart).Seconds())
- case str := <-donech:
- glog.V(logger.Info).Infof("... %s ...\n", str)
- break done
- }
- }
- }()
- C.ethash_compute_full_data(d.dag, p.params, p.cache)
- donech <- "DAG generation completed"
- return d
+// Light implements the Verify half of the proof of work.
+// It uses a small in-memory cache to verify the nonces
+// found by Full.
+type Light struct {
+ test bool // if set use a smaller cache size
+ mu sync.Mutex // protects current
+ current *cache // last cache which was generated.
+ // TODO: keep multiple caches.
}
-func (pow *Ethash) writeDagToDisk(dag *DAG, epoch uint64) *os.File {
- if epoch > 2048 {
- panic(fmt.Errorf("Epoch must be less than 2048 (is %v)", epoch))
+// Verify checks whether the block's nonce is valid.
+func (l *Light) Verify(block pow.Block) bool {
+ // TODO: do ethash_quick_verify before getCache in order
+ // to prevent DOS attacks.
+ var (
+ blockNum = block.NumberU64()
+ difficulty = block.Difficulty()
+ cache = l.getCache(blockNum)
+ dagSize = C.ethash_get_datasize(C.uint64_t(blockNum))
+ )
+ if l.test {
+ dagSize = dagSizeForTesting
}
- data := C.GoBytes(unsafe.Pointer(dag.dag), C.int(dag.paramsAndCache.params.full_size))
- file, err := os.Create("/tmp/dag")
- if err != nil {
- panic(err)
+ if blockNum >= epochLength*2048 {
+ glog.V(logger.Debug).Infof("block number %d too high, limit is %d", epochLength*2048)
+ return false
}
+ // Recompute the hash using the cache.
+ hash := hashToH256(block.HashNoNonce())
+ ret := C.ethash_light_compute_internal(cache.ptr, dagSize, hash, C.uint64_t(block.Nonce()))
+ if !ret.success {
+ return false
+ }
+ // Make sure cache is live until after the C call.
+ // This is important because a GC might happen and execute
+ // the finalizer before the call completes.
+ _ = cache
+ // The actual check.
+ target := new(big.Int).Div(minDifficulty, difficulty)
+ return h256ToHash(ret.result).Big().Cmp(target) <= 0
+}
- dataEpoch := make([]byte, 8)
- binary.BigEndian.PutUint64(dataEpoch, epoch)
-
- file.Write(dataEpoch)
- file.Write(data)
+func h256ToHash(in C.ethash_h256_t) common.Hash {
+ return *(*common.Hash)(unsafe.Pointer(&in.b))
+}
- return file
+func hashToH256(in common.Hash) C.ethash_h256_t {
+ return C.ethash_h256_t{b: *(*[32]C.uint8_t)(unsafe.Pointer(&in[0]))}
}
-func (pow *Ethash) UpdateDAG() {
- blockNum := pow.chainManager.CurrentBlock().NumberU64()
- if blockNum >= epochLength*2048 {
- // This will crash in the 2030s or 2040s
- panic(fmt.Errorf("Current block number is out of bounds (value %v, limit is %v)", blockNum, epochLength*2048))
+func (l *Light) getCache(blockNum uint64) *cache {
+ var c *cache
+ epoch := blockNum / epochLength
+ // Update or reuse the last cache.
+ l.mu.Lock()
+ if l.current != nil && l.current.epoch == epoch {
+ c = l.current
+ } else {
+ c = &cache{epoch: epoch, test: l.test}
+ l.current = c
}
+ l.mu.Unlock()
+ // Wait for the cache to finish generating.
+ c.generate()
+ return c
+}
- pow.dagMutex.Lock()
- defer pow.dagMutex.Unlock()
- thisEpoch := blockNum / epochLength
- if pow.dag == nil || pow.dag.paramsAndCache.Epoch != thisEpoch {
- if pow.dag != nil && pow.dag.dag != nil {
- C.free(pow.dag.dag)
- pow.dag.dag = nil
- }
+// dag wraps an ethash_full_t with some metadata
+// and automatic memory management.
+type dag struct {
+ epoch uint64
+ test bool
+ dir string
- if pow.dag != nil && pow.dag.paramsAndCache.cache.mem != nil {
- C.free(pow.dag.paramsAndCache.cache.mem)
- pow.dag.paramsAndCache.cache.mem = nil
- }
+ gen sync.Once // ensures DAG is only generated once.
+ ptr *C.struct_ethash_full
+}
- // Make the params and cache for the DAG
- paramsAndCache, err := makeParamsAndCache(pow.chainManager, blockNum)
- if err != nil {
- panic(err)
+// generate creates the actual DAG. it can be called from multiple
+// goroutines. the first call will generate the DAG, subsequent
+// calls wait until it is generated.
+func (d *dag) generate() {
+ d.gen.Do(func() {
+ var (
+ started = time.Now()
+ seedHash = makeSeedHash(d.epoch)
+ blockNum = C.uint64_t(d.epoch * epochLength)
+ cacheSize = C.ethash_get_cachesize(blockNum)
+ dagSize = C.ethash_get_datasize(blockNum)
+ )
+ if d.test {
+ cacheSize = cacheSizeForTesting
+ dagSize = dagSizeForTesting
}
-
- // TODO: On non-SSD disks, loading the DAG from disk takes longer than generating it in memory
- pow.paramsAndCache = paramsAndCache
- path := path.Join("/", "tmp", "dag")
- pow.dag = nil
- glog.V(logger.Info).Infoln("Retrieving DAG")
- start := time.Now()
-
- file, err := os.Open(path)
- if err != nil {
- glog.V(logger.Info).Infof("No DAG found. Generating new DAG in '%s' (this takes a while)...\n", path)
- pow.dag = makeDAG(paramsAndCache)
- file = pow.writeDagToDisk(pow.dag, thisEpoch)
- pow.dag.file = true
- } else {
- data, err := ioutil.ReadAll(file)
- if err != nil {
- glog.V(logger.Info).Infof("DAG load err: %v\n", err)
- }
-
- if len(data) < 8 {
- glog.V(logger.Info).Infof("DAG in '%s' is less than 8 bytes, it must be corrupted. Generating new DAG (this takes a while)...\n", path)
- pow.dag = makeDAG(paramsAndCache)
- file = pow.writeDagToDisk(pow.dag, thisEpoch)
- pow.dag.file = true
- } else {
- dataEpoch := binary.BigEndian.Uint64(data[0:8])
- if dataEpoch < thisEpoch {
- glog.V(logger.Info).Infof("DAG in '%s' is stale. Generating new DAG (this takes a while)...\n", path)
- pow.dag = makeDAG(paramsAndCache)
- file = pow.writeDagToDisk(pow.dag, thisEpoch)
- pow.dag.file = true
- } else if dataEpoch > thisEpoch {
- // FIXME
- panic(fmt.Errorf("Saved DAG in '%s' reports to be from future epoch %v (current epoch is %v)\n", path, dataEpoch, thisEpoch))
- } else if len(data) != (int(paramsAndCache.params.full_size) + 8) {
- glog.V(logger.Info).Infof("DAG in '%s' is corrupted. Generating new DAG (this takes a while)...\n", path)
- pow.dag = makeDAG(paramsAndCache)
- file = pow.writeDagToDisk(pow.dag, thisEpoch)
- pow.dag.file = true
- } else {
- data = data[8:]
- pow.dag = &DAG{
- dag: unsafe.Pointer(&data[0]),
- file: true,
- paramsAndCache: paramsAndCache,
- }
- }
- }
+ if d.dir == "" {
+ d.dir = DefaultDir
}
- glog.V(logger.Info).Infoln("Took:", time.Since(start))
-
- file.Close()
- }
-}
-
-func New(chainManager pow.ChainManager) *Ethash {
- paramsAndCache, err := makeParamsAndCache(chainManager, chainManager.CurrentBlock().NumberU64())
- if err != nil {
- panic(err)
- }
-
- return &Ethash{
- turbo: true,
- paramsAndCache: paramsAndCache,
- chainManager: chainManager,
- dag: nil,
- cacheMutex: new(sync.RWMutex),
- dagMutex: new(sync.RWMutex),
- }
+ glog.V(logger.Info).Infof("Generating DAG for epoch %d (%x)", d.epoch, seedHash)
+ // Generate a temporary cache.
+ // TODO: this could share the cache with Light
+ cache := C.ethash_light_new_internal(cacheSize, (*C.ethash_h256_t)(unsafe.Pointer(&seedHash[0])))
+ defer C.ethash_light_delete(cache)
+ // Generate the actual DAG.
+ d.ptr = C.ethash_full_new_internal(
+ C.CString(d.dir),
+ hashToH256(seedHash),
+ dagSize,
+ cache,
+ (C.ethash_callback_t)(unsafe.Pointer(C.ethashGoCallback_cgo)),
+ )
+ if d.ptr == nil {
+ panic("ethash_full_new IO or memory error")
+ }
+ runtime.SetFinalizer(d, freeDAG)
+ glog.V(logger.Info).Infof("Done generating DAG for epoch %d, it took %v", d.epoch, time.Since(started))
+ })
}
-func (pow *Ethash) DAGSize() uint64 {
- return uint64(pow.dag.paramsAndCache.params.full_size)
+func freeDAG(h *dag) {
+ C.ethash_full_delete(h.ptr)
+ h.ptr = nil
}
-func (pow *Ethash) CacheSize() uint64 {
- return uint64(pow.paramsAndCache.params.cache_size)
+//export ethashGoCallback
+func ethashGoCallback(percent C.unsigned) C.int {
+ glog.V(logger.Info).Infof("Still generating DAG: %d%%", percent)
+ return 0
}
-func GetSeedHash(blockNum uint64) ([]byte, error) {
+// MakeDAG pre-generates a DAG file for the given block number in the
+// given directory. If dir is the empty string, the default directory
+// is used.
+func MakeDAG(blockNum uint64, dir string) error {
+ d := &dag{epoch: blockNum / epochLength, dir: dir}
if blockNum >= epochLength*2048 {
- return nil, fmt.Errorf("block number is out of bounds (value %v, limit is %v)", blockNum, epochLength*2048)
- }
-
- epoch := blockNum / epochLength
- seedHash := make([]byte, 32)
- var i uint64
- for i = 0; i < 32; i++ {
- seedHash[i] = 0
+ return fmt.Errorf("block number too high, limit is %d", epochLength*2048)
}
- for i = 0; i < epoch; i++ {
- seedHash = crypto.Sha3(seedHash)
+ d.generate()
+ if d.ptr == nil {
+ return errors.New("failed")
}
- return seedHash, nil
+ return nil
}
-func (pow *Ethash) Stop() {
- pow.cacheMutex.Lock()
- pow.dagMutex.Lock()
- defer pow.dagMutex.Unlock()
- defer pow.cacheMutex.Unlock()
+// Full implements the Search half of the proof of work.
+type Full struct {
+ Dir string // use this to specify a non-default DAG directory
- if pow.paramsAndCache.cache != nil {
- C.free(pow.paramsAndCache.cache.mem)
- }
- if pow.dag.dag != nil && !pow.dag.file {
- C.free(pow.dag.dag)
- }
- if pow.dag != nil && pow.dag.paramsAndCache != nil && pow.dag.paramsAndCache.cache.mem != nil {
- C.free(pow.dag.paramsAndCache.cache.mem)
- pow.dag.paramsAndCache.cache.mem = nil
- }
- pow.dag.dag = nil
+ test bool // if set use a smaller DAG size
+ turbo bool
+ hashRate int64
+
+ mu sync.Mutex // protects dag
+ current *dag // current full DAG
}
-func (pow *Ethash) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte, []byte) {
- pow.UpdateDAG()
+func (pow *Full) getDAG(blockNum uint64) (d *dag) {
+ epoch := blockNum / epochLength
+ pow.mu.Lock()
+ if pow.current != nil && pow.current.epoch == epoch {
+ d = pow.current
+ } else {
+ d = &dag{epoch: epoch, test: pow.test, dir: pow.Dir}
+ pow.current = d
+ }
+ pow.mu.Unlock()
+ // wait for it to finish generating.
+ d.generate()
+ return d
+}
- pow.dagMutex.RLock()
- defer pow.dagMutex.RUnlock()
+func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mixDigest []byte) {
+ dag := pow.getDAG(block.NumberU64())
r := rand.New(rand.NewSource(time.Now().UnixNano()))
- miningHash := block.HashNoNonce()
diff := block.Difficulty()
i := int64(0)
starti := i
start := time.Now().UnixNano()
- nonce := uint64(r.Int63())
- cMiningHash := (*C.ethash_blockhash_t)(unsafe.Pointer(&miningHash[0]))
+ nonce = uint64(r.Int63())
+ hash := hashToH256(block.HashNoNonce())
target := new(big.Int).Div(minDifficulty, diff)
-
- var ret C.ethash_return_value
for {
select {
case <-stop:
- pow.HashRate = 0
- return 0, nil, nil
+ pow.hashRate = 0
+ return 0, nil
default:
i++
elapsed := time.Now().UnixNano() - start
hashes := ((float64(1e9) / float64(elapsed)) * float64(i-starti)) / 1000
- pow.HashRate = int64(hashes)
+ pow.hashRate = int64(hashes)
- C.ethash_full(&ret, pow.dag.dag, pow.dag.paramsAndCache.params, cMiningHash, C.uint64_t(nonce))
- result := common.Bytes2Big(C.GoBytes(unsafe.Pointer(&ret.result), C.int(32)))
+ ret := C.ethash_full_compute(dag.ptr, hash, C.uint64_t(nonce))
+ result := h256ToHash(ret.result).Big()
// TODO: disagrees with the spec https://github.com/ethereum/wiki/wiki/Ethash#mining
- if result.Cmp(target) <= 0 {
- mixDigest := C.GoBytes(unsafe.Pointer(&ret.mix_hash), C.int(32))
- seedHash, err := GetSeedHash(block.NumberU64()) // This seedhash is useless
- if err != nil {
- panic(err)
- }
- return nonce, mixDigest, seedHash
+ if ret.success && result.Cmp(target) <= 0 {
+ mixDigest = C.GoBytes(unsafe.Pointer(&ret.mix_hash), C.int(32))
+ return nonce, mixDigest
}
-
nonce += 1
}
@@ -357,82 +296,57 @@ func (pow *Ethash) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte
time.Sleep(20 * time.Microsecond)
}
}
-
}
-func (pow *Ethash) Verify(block pow.Block) bool {
-
- return pow.verify(block.HashNoNonce(), block.MixDigest(), block.Difficulty(), block.NumberU64(), block.Nonce())
+func (pow *Full) GetHashrate() int64 {
+ // TODO: this needs to use an atomic operation.
+ return pow.hashRate
}
-func (pow *Ethash) verify(hash common.Hash, mixDigest common.Hash, difficulty *big.Int, blockNum uint64, nonce uint64) bool {
- // Make sure the block num is valid
- if blockNum >= epochLength*2048 {
- glog.V(logger.Info).Infoln(fmt.Sprintf("Block number exceeds limit, invalid (value is %v, limit is %v)",
- blockNum, epochLength*2048))
- return false
- }
-
- // First check: make sure header, mixDigest, nonce are correct without hitting the cache
- // This is to prevent DOS attacks
- chash := (*C.ethash_blockhash_t)(unsafe.Pointer(&hash[0]))
- cnonce := C.uint64_t(nonce)
- target := new(big.Int).Div(minDifficulty, difficulty)
-
- var pAc *ParamsAndCache
- // If its an old block (doesn't use the current cache)
- // get the cache for it but don't update (so we don't need the mutex)
- // Otherwise, it's the current block or a future block.
- // If current, updateCache will do nothing.
- if blockNum/epochLength < pow.paramsAndCache.Epoch {
- var err error
- // If we can't make the params for some reason, this block is invalid
- pAc, err = makeParamsAndCache(pow.chainManager, blockNum)
- if err != nil {
- glog.V(logger.Info).Infoln("big fucking eror", err)
- return false
- }
- } else {
- pow.UpdateCache(blockNum, false)
- pow.cacheMutex.RLock()
- defer pow.cacheMutex.RUnlock()
- pAc = pow.paramsAndCache
- }
-
- ret := new(C.ethash_return_value)
-
- C.ethash_light(ret, pAc.cache, pAc.params, chash, cnonce)
+func (pow *Full) Turbo(on bool) {
+ // TODO: this needs to use an atomic operation.
+ pow.turbo = on
+}
- result := common.Bytes2Big(C.GoBytes(unsafe.Pointer(&ret.result), C.int(32)))
- return result.Cmp(target) <= 0
+// Ethash combines block verification with Light and
+// nonce searching with Full into a single proof of work.
+type Ethash struct {
+ *Light
+ *Full
}
-func (pow *Ethash) GetHashrate() int64 {
- return pow.HashRate
+// New creates an instance of the proof of work.
+// A single instance of Light is shared across all instances
+// created with New.
+func New() *Ethash {
+ return &Ethash{sharedLight, &Full{turbo: true}}
}
-func (pow *Ethash) Turbo(on bool) {
- pow.turbo = on
+// NewForTesting creates a proof of work for use in unit tests.
+// It uses a smaller DAG and cache size to keep test times low.
+// DAG files are stored in a temporary directory.
+//
+// Nonces found by a testing instance are not verifiable with a
+// regular-size cache.
+func NewForTesting() (*Ethash, error) {
+ dir, err := ioutil.TempDir("", "ethash-test")
+ if err != nil {
+ return nil, err
+ }
+ return &Ethash{&Light{test: true}, &Full{Dir: dir, test: true}}, nil
}
-func (pow *Ethash) FullHash(nonce uint64, miningHash []byte) []byte {
- pow.UpdateDAG()
- pow.dagMutex.Lock()
- defer pow.dagMutex.Unlock()
- cMiningHash := (*C.ethash_blockhash_t)(unsafe.Pointer(&miningHash[0]))
- cnonce := C.uint64_t(nonce)
- ret := new(C.ethash_return_value)
- // pow.hash is the output/return of ethash_full
- C.ethash_full(ret, pow.dag.dag, pow.paramsAndCache.params, cMiningHash, cnonce)
- ghash_full := C.GoBytes(unsafe.Pointer(&ret.result), 32)
- return ghash_full
+func GetSeedHash(blockNum uint64) ([]byte, error) {
+ if blockNum >= epochLength*2048 {
+ return nil, fmt.Errorf("block number too high, limit is %d", epochLength*2048)
+ }
+ sh := makeSeedHash(blockNum / epochLength)
+ return sh[:], nil
}
-func (pow *Ethash) LightHash(nonce uint64, miningHash []byte) []byte {
- cMiningHash := (*C.ethash_blockhash_t)(unsafe.Pointer(&miningHash[0]))
- cnonce := C.uint64_t(nonce)
- ret := new(C.ethash_return_value)
- C.ethash_light(ret, pow.paramsAndCache.cache, pow.paramsAndCache.params, cMiningHash, cnonce)
- ghash_light := C.GoBytes(unsafe.Pointer(&ret.result), 32)
- return ghash_light
+func makeSeedHash(epoch uint64) (sh common.Hash) {
+ for ; epoch > 0; epoch-- {
+ sh = crypto.Sha3Hash(sh[:])
+ }
+ return sh
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go
new file mode 100644
index 000000000..42be77b94
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go
@@ -0,0 +1,176 @@
+package ethash
+
+import (
+ "bytes"
+ "crypto/rand"
+ "encoding/hex"
+ "log"
+ "math/big"
+ "os"
+ "sync"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func init() {
+ // glog.SetV(6)
+ // glog.SetToStderr(true)
+}
+
+type testBlock struct {
+ difficulty *big.Int
+ hashNoNonce common.Hash
+ nonce uint64
+ mixDigest common.Hash
+ number uint64
+}
+
+func (b *testBlock) Difficulty() *big.Int { return b.difficulty }
+func (b *testBlock) HashNoNonce() common.Hash { return b.hashNoNonce }
+func (b *testBlock) Nonce() uint64 { return b.nonce }
+func (b *testBlock) MixDigest() common.Hash { return b.mixDigest }
+func (b *testBlock) NumberU64() uint64 { return b.number }
+
+var validBlocks = []*testBlock{
+ // from proof of concept nine testnet, epoch 0
+ {
+ number: 22,
+ hashNoNonce: common.HexToHash("372eca2454ead349c3df0ab5d00b0b706b23e49d469387db91811cee0358fc6d"),
+ difficulty: big.NewInt(132416),
+ nonce: 0x495732e0ed7a801c,
+ },
+ // from proof of concept nine testnet, epoch 1
+ {
+ number: 30001,
+ hashNoNonce: common.HexToHash("7e44356ee3441623bc72a683fd3708fdf75e971bbe294f33e539eedad4b92b34"),
+ difficulty: big.NewInt(1532671),
+ nonce: 0x318df1c8adef7e5e,
+ },
+ // from proof of concept nine testnet, epoch 2
+ {
+ number: 60000,
+ hashNoNonce: common.HexToHash("5fc898f16035bf5ac9c6d9077ae1e3d5fc1ecc3c9fd5bee8bb00e810fdacbaa0"),
+ difficulty: big.NewInt(2467358),
+ nonce: 0x50377003e5d830ca,
+ },
+}
+
+func TestEthashVerifyValid(t *testing.T) {
+ eth := New()
+ for i, block := range validBlocks {
+ if !eth.Verify(block) {
+ t.Errorf("block %d (%x) did not validate.", i, block.hashNoNonce[:6])
+ }
+ }
+}
+
+func TestEthashConcurrentVerify(t *testing.T) {
+ eth, err := NewForTesting()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(eth.Full.Dir)
+
+ block := &testBlock{difficulty: big.NewInt(10)}
+ nonce, _ := eth.Search(block, nil)
+ block.nonce = nonce
+
+ // Verify the block concurrently to check for data races.
+ var wg sync.WaitGroup
+ wg.Add(100)
+ for i := 0; i < 100; i++ {
+ go func() {
+ if !eth.Verify(block) {
+ t.Error("Block could not be verified")
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
+
+func TestEthashConcurrentSearch(t *testing.T) {
+ eth, err := NewForTesting()
+ if err != nil {
+ t.Fatal(err)
+ }
+ eth.Turbo(true)
+ defer os.RemoveAll(eth.Full.Dir)
+
+ // launch n searches concurrently.
+ var (
+ block = &testBlock{difficulty: big.NewInt(35000)}
+ nsearch = 10
+ wg = new(sync.WaitGroup)
+ found = make(chan uint64)
+ stop = make(chan struct{})
+ )
+ rand.Read(block.hashNoNonce[:])
+ wg.Add(nsearch)
+ for i := 0; i < nsearch; i++ {
+ go func() {
+ nonce, _ := eth.Search(block, stop)
+ select {
+ case found <- nonce:
+ case <-stop:
+ }
+ wg.Done()
+ }()
+ }
+
+ // wait for one of them to find the nonce
+ nonce := <-found
+ // stop the others
+ close(stop)
+ wg.Wait()
+
+ if block.nonce = nonce; !eth.Verify(block) {
+ t.Error("Block could not be verified")
+ }
+}
+
+func TestEthashSearchAcrossEpoch(t *testing.T) {
+ eth, err := NewForTesting()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(eth.Full.Dir)
+
+ for i := epochLength - 40; i < epochLength+40; i++ {
+ block := &testBlock{number: i, difficulty: big.NewInt(90)}
+ rand.Read(block.hashNoNonce[:])
+ nonce, _ := eth.Search(block, nil)
+ block.nonce = nonce
+ if !eth.Verify(block) {
+ t.Fatalf("Block could not be verified")
+ }
+ }
+}
+
+func TestGetSeedHash(t *testing.T) {
+ seed0, err := GetSeedHash(0)
+ if err != nil {
+ t.Errorf("Failed to get seedHash for block 0: %v", err)
+ }
+ if bytes.Compare(seed0, make([]byte, 32)) != 0 {
+ log.Printf("seedHash for block 0 should be 0s, was: %v\n", seed0)
+ }
+ seed1, err := GetSeedHash(30000)
+ if err != nil {
+ t.Error(err)
+ }
+
+ // From python:
+ // > from pyethash import get_seedhash
+ // > get_seedhash(30000)
+ expectedSeed1, err := hex.DecodeString("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
+ if err != nil {
+ t.Error(err)
+ }
+
+ if bytes.Compare(seed1, expectedSeed1) != 0 {
+ log.Printf("seedHash for block 1 should be: %v,\nactual value: %v\n", expectedSeed1, seed1)
+ }
+
+}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go
new file mode 100644
index 000000000..25863828f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go
@@ -0,0 +1,25 @@
+package ethash
+
+/*
+#cgo CFLAGS: -std=gnu99 -Wall
+#cgo windows CFLAGS: -mno-stack-arg-probe
+#cgo LDFLAGS: -lm
+
+#include "src/libethash/internal.c"
+#include "src/libethash/sha3.c"
+#include "src/libethash/io.c"
+
+#ifdef _WIN32
+# include "src/libethash/util_win32.c"
+# include "src/libethash/io_win32.c"
+# include "src/libethash/mmap_win32.c"
+#else
+# include "src/libethash/io_posix.c"
+#endif
+
+// 'gateway function' for calling back into go.
+extern int ethashGoCallback(unsigned);
+int ethashGoCallback_cgo(unsigned percent) { return ethashGoCallback(percent); }
+
+*/
+import "C"
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py b/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py
index 6a6b93839..18aa20f6d 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py
@@ -1,23 +1,36 @@
#!/usr/bin/env python
+import os
from distutils.core import setup, Extension
-
+sources = [
+ 'src/python/core.c',
+ 'src/libethash/io.c',
+ 'src/libethash/internal.c',
+ 'src/libethash/sha3.c']
+if os.name == 'nt':
+ sources += [
+ 'src/libethash/util_win32.c',
+ 'src/libethash/io_win32.c',
+ 'src/libethash/mmap_win32.c',
+ ]
+else:
+ sources += [
+ 'src/libethash/io_posix.c'
+ ]
+depends = [
+ 'src/libethash/ethash.h',
+ 'src/libethash/compiler.h',
+ 'src/libethash/data_sizes.h',
+ 'src/libethash/endian.h',
+ 'src/libethash/ethash.h',
+ 'src/libethash/io.h',
+ 'src/libethash/fnv.h',
+ 'src/libethash/internal.h',
+ 'src/libethash/sha3.h',
+ 'src/libethash/util.h',
+]
pyethash = Extension('pyethash',
- sources=[
- 'src/python/core.c',
- 'src/libethash/util.c',
- 'src/libethash/internal.c',
- 'src/libethash/sha3.c'],
- depends=[
- 'src/libethash/ethash.h',
- 'src/libethash/compiler.h',
- 'src/libethash/data_sizes.h',
- 'src/libethash/endian.h',
- 'src/libethash/ethash.h',
- 'src/libethash/fnv.h',
- 'src/libethash/internal.h',
- 'src/libethash/sha3.h',
- 'src/libethash/util.h'
- ],
+ sources=sources,
+ depends=depends,
extra_compile_args=["-Isrc/", "-std=gnu99", "-Wall"])
setup(
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/CMakeLists.txt b/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/CMakeLists.txt
index 840fe5146..3df4ab596 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/CMakeLists.txt
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/CMakeLists.txt
@@ -3,56 +3,56 @@ include_directories(..)
set(CMAKE_BUILD_TYPE Release)
if (MSVC)
- add_definitions("/openmp")
+ add_definitions("/openmp")
endif()
# enable C++11, should probably be a bit more specific about compiler
if (NOT MSVC)
- SET(CMAKE_CXX_FLAGS "-std=c++11")
+ SET(CMAKE_CXX_FLAGS "-std=c++11")
endif()
if (NOT MPI_FOUND)
- find_package(MPI)
+ find_package(MPI)
endif()
if (NOT CRYPTOPP_FOUND)
- find_package(CryptoPP 5.6.2)
+ find_package(CryptoPP 5.6.2)
endif()
if (CRYPTOPP_FOUND)
- add_definitions(-DWITH_CRYPTOPP)
+ add_definitions(-DWITH_CRYPTOPP)
+ find_package (Threads REQUIRED)
endif()
if (NOT OpenCL_FOUND)
- find_package(OpenCL)
+ find_package(OpenCL)
endif()
if (OpenCL_FOUND)
- add_definitions(-DWITH_OPENCL)
- include_directories(${OpenCL_INCLUDE_DIRS})
- list(APPEND FILES ethash_cl_miner.cpp ethash_cl_miner.h)
+ add_definitions(-DWITH_OPENCL)
+ include_directories(${OpenCL_INCLUDE_DIRS})
+ list(APPEND FILES ethash_cl_miner.cpp ethash_cl_miner.h)
endif()
if (MPI_FOUND)
- include_directories(${MPI_INCLUDE_PATH})
- add_executable (Benchmark_MPI_FULL benchmark.cpp)
- target_link_libraries (Benchmark_MPI_FULL ${ETHHASH_LIBS} ${MPI_LIBRARIES})
- SET_TARGET_PROPERTIES(Benchmark_MPI_FULL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} ${MPI_COMPILE_FLAGS} -DFULL -DMPI")
+ include_directories(${MPI_INCLUDE_PATH})
+ add_executable (Benchmark_MPI_FULL benchmark.cpp)
+ target_link_libraries (Benchmark_MPI_FULL ${ETHHASH_LIBS} ${MPI_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+ SET_TARGET_PROPERTIES(Benchmark_MPI_FULL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} ${MPI_COMPILE_FLAGS} -DFULL -DMPI")
- add_executable (Benchmark_MPI_LIGHT benchmark.cpp)
- target_link_libraries (Benchmark_MPI_LIGHT ${ETHHASH_LIBS} ${MPI_LIBRARIES})
- SET_TARGET_PROPERTIES(Benchmark_MPI_LIGHT PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} ${MPI_COMPILE_FLAGS} -DMPI")
+ add_executable (Benchmark_MPI_LIGHT benchmark.cpp)
+ target_link_libraries (Benchmark_MPI_LIGHT ${ETHHASH_LIBS} ${MPI_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+ SET_TARGET_PROPERTIES(Benchmark_MPI_LIGHT PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} ${MPI_COMPILE_FLAGS} -DMPI")
endif()
add_executable (Benchmark_FULL benchmark.cpp)
-target_link_libraries (Benchmark_FULL ${ETHHASH_LIBS})
+target_link_libraries (Benchmark_FULL ${ETHHASH_LIBS} ${CMAKE_THREAD_LIBS_INIT})
SET_TARGET_PROPERTIES(Benchmark_FULL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DFULL")
add_executable (Benchmark_LIGHT benchmark.cpp)
-target_link_libraries (Benchmark_LIGHT ${ETHHASH_LIBS})
+target_link_libraries (Benchmark_LIGHT ${ETHHASH_LIBS} ${CMAKE_THREAD_LIBS_INIT})
if (OpenCL_FOUND)
- add_executable (Benchmark_CL benchmark.cpp)
- target_link_libraries (Benchmark_CL ${ETHHASH_LIBS} ethash-cl)
- SET_TARGET_PROPERTIES(Benchmark_CL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DOPENCL")
-endif()
-
+ add_executable (Benchmark_CL benchmark.cpp)
+ target_link_libraries (Benchmark_CL ${ETHHASH_LIBS} ethash-cl ${CMAKE_THREAD_LIBS_INIT})
+ SET_TARGET_PROPERTIES(Benchmark_CL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DOPENCL")
+endif() \ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/benchmark.cpp b/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/benchmark.cpp
index 2635c8038..1a648edf4 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/benchmark.cpp
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/benchmark/benchmark.cpp
@@ -96,6 +96,11 @@ static std::string bytesToHexString(uint8_t const* bytes, unsigned size)
return str;
}
+static std::string bytesToHexString(ethash_h256_t const *hash, unsigned size)
+{
+ return bytesToHexString((uint8_t*)hash, size);
+}
+
extern "C" int main(void)
{
// params for ethash
@@ -106,12 +111,12 @@ extern "C" int main(void)
//params.full_size = 8209 * 4096; // 8MBish;
//params.cache_size = 8209*4096;
//params.cache_size = 2053*4096;
- ethash_blockhash_t seed;
- ethash_blockhash_t previous_hash;
+ ethash_h256_t seed;
+ ethash_h256_t previous_hash;
memcpy(&seed, hexStringToBytes("9410b944535a83d9adf6bbdcc80e051f30676173c16ca0d32d6f1263fc246466").data(), 32);
memcpy(&previous_hash, hexStringToBytes("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").data(), 32);
-
+
// allocate page aligned buffer for dataset
#ifdef FULL
void* full_mem_buf = malloc(params.full_size + 4095);
@@ -122,24 +127,24 @@ extern "C" int main(void)
ethash_cache cache;
cache.mem = cache_mem;
-
+
// compute cache or full data
{
auto startTime = high_resolution_clock::now();
- ethash_mkcache(&cache, &params, seed);
+ ethash_mkcache(&cache, &params, &seed);
auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count();
- ethash_blockhash_t cache_hash;
+ ethash_h256_t cache_hash;
SHA3_256(&cache_hash, (uint8_t const*)cache_mem, params.cache_size);
- debugf("ethash_mkcache: %ums, sha3: %s\n", (unsigned)((time*1000)/CLOCKS_PER_SEC), bytesToHexString(cache_hash,sizeof(cache_hash)).data());
+ debugf("ethash_mkcache: %ums, sha3: %s\n", (unsigned)((time*1000)/CLOCKS_PER_SEC), bytesToHexString(&cache_hash, sizeof(cache_hash)).data());
// print a couple of test hashes
{
auto startTime = high_resolution_clock::now();
ethash_return_value hash;
- ethash_light(&hash, &cache, &params, previous_hash, 0);
+ ethash_light(&hash, &cache, &params, &previous_hash, 0);
auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count();
- debugf("ethash_light test: %ums, %s\n", (unsigned)time, bytesToHexString(hash.result, 32).data());
+ debugf("ethash_light test: %ums, %s\n", (unsigned)time, bytesToHexString(&hash.result, 32).data());
}
#ifdef FULL
@@ -154,34 +159,34 @@ extern "C" int main(void)
ethash_cl_miner miner;
{
auto startTime = high_resolution_clock::now();
- if (!miner.init(params, seed))
+ if (!miner.init(params, &seed))
exit(-1);
auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count();
- debugf("ethash_cl_miner init: %ums\n", (unsigned)time);
+ debugf("ethash_cl_miner init: %ums\n", (unsigned)time);
}
#endif
#ifdef FULL
- {
- auto startTime = high_resolution_clock::now();
+ {
+ auto startTime = high_resolution_clock::now();
ethash_return_value hash;
- ethash_full(&hash, full_mem, &params, previous_hash, 0);
- auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count();
- debugf("ethash_full test: %uns, %s\n", (unsigned)time);
- }
+ ethash_full(&hash, full_mem, &params, &previous_hash, 0);
+ auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count();
+ debugf("ethash_full test: %uns\n", (unsigned)time);
+ }
#endif
#ifdef OPENCL
// validate 1024 hashes against CPU
- miner.hash(g_hashes, previous_hash, 0, 1024);
+ miner.hash(g_hashes, (uint8_t*)&previous_hash, 0, 1024);
for (unsigned i = 0; i != 1024; ++i)
{
ethash_return_value hash;
- ethash_light(&hash, &cache, &params, previous_hash, i);
- if (memcmp(hash.result, g_hashes + 32*i, 32) != 0)
+ ethash_light(&hash, &cache, &params, &previous_hash, i);
+ if (memcmp(&hash.result, g_hashes + 32*i, 32) != 0)
{
- debugf("nonce %u failed: %s %s\n", i, bytesToHexString(g_hashes + 32*i, 32).c_str(), bytesToHexString(hash.result, 32).c_str());
+ debugf("nonce %u failed: %s %s\n", i, bytesToHexString(g_hashes + 32*i, 32).c_str(), bytesToHexString(&hash.result, 32).c_str());
static unsigned c = 0;
if (++c == 16)
{
@@ -189,14 +194,14 @@ extern "C" int main(void)
}
}
}
-
+
// ensure nothing else is going on
miner.finish();
#endif
auto startTime = high_resolution_clock::now();
unsigned hash_count = trials;
-
+
#ifdef OPENCL
{
struct search_hook : ethash_cl_miner::search_hook
@@ -220,14 +225,14 @@ extern "C" int main(void)
search_hook hook;
hook.hash_count = 0;
- miner.search(previous_hash, 0x000000ffffffffff, hook);
+ miner.search((uint8_t*)&previous_hash, 0x000000ffffffffff, hook);
for (unsigned i = 0; i != hook.nonce_vec.size(); ++i)
{
uint64_t nonce = hook.nonce_vec[i];
ethash_return_value hash;
- ethash_light(&hash, &cache, &params, previous_hash, nonce);
- debugf("found: %.8x%.8x -> %s\n", unsigned(nonce>>32), unsigned(nonce), bytesToHexString(hash.result, 32).c_str());
+ ethash_light(&hash, &cache, &params, &previous_hash, nonce);
+ debugf("found: %.8x%.8x -> %s\n", unsigned(nonce>>32), unsigned(nonce), bytesToHexString(&hash.result, 32).c_str());
}
hash_count = hook.hash_count;
@@ -239,9 +244,9 @@ extern "C" int main(void)
{
ethash_return_value hash;
#ifdef FULL
- ethash_full(&hash, full_mem, &params, previous_hash, nonce);
+ ethash_full(&hash, full_mem, &params, &previous_hash, nonce);
#else
- ethash_light(&hash, &cache, &params, previous_hash, nonce);
+ ethash_light(&hash, &cache, &params, &previous_hash, nonce);
#endif // FULL
}
}
@@ -249,7 +254,7 @@ extern "C" int main(void)
auto time = std::chrono::duration_cast<std::chrono::microseconds>(high_resolution_clock::now() - startTime).count();
debugf("Search took: %ums\n", (unsigned)time/1000);
- unsigned read_size = ACCESSES * MIX_BYTES;
+ unsigned read_size = ETHASH_ACCESSES * ETHASH_MIX_BYTES;
#if defined(OPENCL) || defined(FULL)
debugf(
"hashrate: %8.2f Mh/s, bw: %8.2f GB/s\n",
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/CMakeLists.txt b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/CMakeLists.txt
index 30fa7ed4b..3cfe1644d 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/CMakeLists.txt
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/CMakeLists.txt
@@ -13,7 +13,7 @@ if (NOT MSVC)
set(CMAKE_CXX_FLAGS "-Wall -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
- set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG")
+ set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
# Compiler-specific C++11 activation.
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.cpp b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.cpp
index bf7bb2128..65f15d7ca 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.cpp
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.cpp
@@ -24,12 +24,15 @@
#include <cstdio>
#include <cstdlib>
+#include <iostream>
#include <assert.h>
#include <queue>
#include <vector>
+#include <libethash/util.h>
+#include <libethash/ethash.h>
+#include <libethash/internal.h>
#include "ethash_cl_miner.h"
#include "ethash_cl_miner_kernel.h"
-#include <libethash/util.h>
#define ETHASH_BYTES 32
@@ -42,6 +45,8 @@
#undef min
#undef max
+using namespace std;
+
static void add_definition(std::string& source, char const* id, unsigned value)
{
char buf[256];
@@ -49,52 +54,108 @@ static void add_definition(std::string& source, char const* id, unsigned value)
source.insert(source.begin(), buf, buf + strlen(buf));
}
+ethash_cl_miner::search_hook::~search_hook() {}
+
ethash_cl_miner::ethash_cl_miner()
: m_opencl_1_1()
{
}
-bool ethash_cl_miner::init(ethash_params const& params, ethash_blockhash_t const *seed, unsigned workgroup_size)
+std::string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId)
+{
+ std::vector<cl::Platform> platforms;
+ cl::Platform::get(&platforms);
+ if (platforms.empty())
+ {
+ cout << "No OpenCL platforms found." << endl;
+ return std::string();
+ }
+
+ // get GPU device of the selected platform
+ std::vector<cl::Device> devices;
+ unsigned platform_num = std::min<unsigned>(_platformId, platforms.size() - 1);
+ platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices);
+ if (devices.empty())
+ {
+ cout << "No OpenCL devices found." << endl;
+ return std::string();
+ }
+
+ // use selected default device
+ unsigned device_num = std::min<unsigned>(_deviceId, devices.size() - 1);
+ cl::Device& device = devices[device_num];
+ std::string device_version = device.getInfo<CL_DEVICE_VERSION>();
+
+ return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }";
+}
+
+unsigned ethash_cl_miner::get_num_devices(unsigned _platformId)
+{
+ std::vector<cl::Platform> platforms;
+ cl::Platform::get(&platforms);
+ if (platforms.empty())
+ {
+ cout << "No OpenCL platforms found." << endl;
+ return 0;
+ }
+
+ std::vector<cl::Device> devices;
+ unsigned platform_num = std::min<unsigned>(_platformId, platforms.size() - 1);
+ platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices);
+ if (devices.empty())
+ {
+ cout << "No OpenCL devices found." << endl;
+ return 0;
+ }
+ return devices.size();
+}
+
+void ethash_cl_miner::finish()
+{
+ if (m_queue())
+ m_queue.finish();
+}
+
+bool ethash_cl_miner::init(uint64_t block_number, std::function<void(void*)> _fillDAG, unsigned workgroup_size, unsigned _platformId, unsigned _deviceId)
{
// store params
- m_params = params;
+ m_fullSize = ethash_get_datasize(block_number);
// get all platforms
- std::vector<cl::Platform> platforms;
- cl::Platform::get(&platforms);
+ std::vector<cl::Platform> platforms;
+ cl::Platform::get(&platforms);
if (platforms.empty())
{
- debugf("No OpenCL platforms found.\n");
+ cout << "No OpenCL platforms found." << endl;
return false;
}
- // use default platform
- debugf("Using platform: %s\n", platforms[0].getInfo<CL_PLATFORM_NAME>().c_str());
+ // use selected platform
+ _platformId = std::min<unsigned>(_platformId, platforms.size() - 1);
- // get GPU device of the default platform
- std::vector<cl::Device> devices;
- platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);
- if (devices.empty())
+ cout << "Using platform: " << platforms[_platformId].getInfo<CL_PLATFORM_NAME>().c_str() << endl;
+
+ // get GPU device of the default platform
+ std::vector<cl::Device> devices;
+ platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices);
+ if (devices.empty())
{
- debugf("No OpenCL devices found.\n");
+ cout << "No OpenCL devices found." << endl;
return false;
}
- // use default device
- unsigned device_num = 0;
- cl::Device& device = devices[device_num];
+ // use selected device
+ cl::Device& device = devices[std::min<unsigned>(_deviceId, devices.size() - 1)];
std::string device_version = device.getInfo<CL_DEVICE_VERSION>();
- debugf("Using device: %s (%s)\n", device.getInfo<CL_DEVICE_NAME>().c_str(),device_version.c_str());
+ cout << "Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")" << endl;
if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0)
{
- debugf("OpenCL 1.0 is not supported.\n");
+ cout << "OpenCL 1.0 is not supported." << endl;
return false;
}
if (strncmp("OpenCL 1.1", device_version.c_str(), 10) == 0)
- {
m_opencl_1_1 = true;
- }
// create context
m_context = cl::Context(std::vector<cl::Device>(&device, &device + 1));
@@ -106,8 +167,8 @@ bool ethash_cl_miner::init(ethash_params const& params, ethash_blockhash_t const
// patch source code
std::string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE);
add_definition(code, "GROUP_SIZE", m_workgroup_size);
- add_definition(code, "DAG_SIZE", (unsigned)(params.full_size / MIX_BYTES));
- add_definition(code, "ACCESSES", ACCESSES);
+ add_definition(code, "DAG_SIZE", (unsigned)(m_fullSize / ETHASH_MIX_BYTES));
+ add_definition(code, "ACCESSES", ETHASH_ACCESSES);
add_definition(code, "MAX_OUTPUTS", c_max_search_results);
//debugf("%s", code.c_str());
@@ -122,31 +183,25 @@ bool ethash_cl_miner::init(ethash_params const& params, ethash_blockhash_t const
}
catch (cl::Error err)
{
- debugf("%s\n", program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str());
+ cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str();
return false;
}
m_hash_kernel = cl::Kernel(program, "ethash_hash");
m_search_kernel = cl::Kernel(program, "ethash_search");
// create buffer for dag
- m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, params.full_size);
-
+ m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, m_fullSize);
+
// create buffer for header
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
// compute dag on CPU
{
- void* cache_mem = malloc(params.cache_size + 63);
- ethash_cache cache;
- cache.mem = (void*)(((uintptr_t)cache_mem + 63) & ~63);
- ethash_mkcache(&cache, &params, seed);
-
// if this throws then it's because we probably need to subdivide the dag uploads for compatibility
- void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, params.full_size);
- ethash_compute_full_data(dag_ptr, &params, &cache);
+ void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, m_fullSize);
+ // memcpying 1GB: horrible... really. horrible. but necessary since we can't mmap *and* gpumap.
+ _fillDAG(dag_ptr);
m_queue.enqueueUnmapMemObject(m_dag, dag_ptr);
-
- free(cache_mem);
}
// create mining buffers
@@ -167,7 +222,7 @@ void ethash_cl_miner::hash(uint8_t* ret, uint8_t const* header, uint64_t nonce,
unsigned buf;
};
std::queue<pending_batch> pending;
-
+
// update header constant buffer
m_queue.enqueueWriteBuffer(m_header, true, 0, 32, header);
@@ -191,8 +246,8 @@ void ethash_cl_miner::hash(uint8_t* ret, uint8_t const* header, uint64_t nonce,
// how many this batch
if (i < count)
{
- unsigned const this_count = std::min(count - i, c_hash_batch_size);
- unsigned const batch_count = std::max(this_count, m_workgroup_size);
+ unsigned const this_count = std::min<unsigned>(count - i, c_hash_batch_size);
+ unsigned const batch_count = std::max<unsigned>(this_count, m_workgroup_size);
// supply output hash buffer to kernel
m_hash_kernel.setArg(0, m_hash_buf[buf]);
@@ -205,7 +260,7 @@ void ethash_cl_miner::hash(uint8_t* ret, uint8_t const* header, uint64_t nonce,
cl::NDRange(m_workgroup_size)
);
m_queue.flush();
-
+
pending.push({i, this_count, buf});
i += this_count;
buf = (buf + 1) % c_num_buffers;
@@ -245,7 +300,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero);
}
-#if CL_VERSION_1_2
+#if CL_VERSION_1_2 && 0
cl::Event pre_return_event;
if (!m_opencl_1_1)
{
@@ -284,7 +339,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
// execute it!
m_queue.enqueueNDRangeKernel(m_search_kernel, cl::NullRange, c_search_batch_size, m_workgroup_size);
-
+
pending.push({start_nonce, buf});
buf = (buf + 1) % c_num_buffers;
@@ -295,16 +350,16 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
// could use pinned host pointer instead
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1+c_max_search_results) * sizeof(uint32_t));
- unsigned num_found = std::min(results[0], c_max_search_results);
+ unsigned num_found = std::min<unsigned>(results[0], c_max_search_results);
uint64_t nonces[c_max_search_results];
for (unsigned i = 0; i != num_found; ++i)
{
nonces[i] = batch.start_nonce + results[i+1];
}
-
+
m_queue.enqueueUnmapMemObject(m_search_buf[batch.buf], results);
-
+
bool exit = num_found && hook.found(nonces, num_found);
exit |= hook.searched(batch.start_nonce, c_search_batch_size); // always report searched before exit
if (exit)
@@ -319,7 +374,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
}
// not safe to return until this is ready
-#if CL_VERSION_1_2
+#if CL_VERSION_1_2 && 0
if (!m_opencl_1_1)
{
pre_return_event.wait();
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.h
index af614b3e4..23868b2c7 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.h
@@ -1,9 +1,19 @@
#pragma once
-#define __CL_ENABLE_EXCEPTIONS
+#define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#include "cl.hpp"
+#pragma clang diagnostic pop
+#else
#include "cl.hpp"
+#endif
+
#include <time.h>
+#include <functional>
#include <libethash/ethash.h>
class ethash_cl_miner
@@ -11,6 +21,8 @@ class ethash_cl_miner
public:
struct search_hook
{
+ virtual ~search_hook(); // always a virtual destructor for a class with virtuals.
+
// reports progress, return true to abort
virtual bool found(uint64_t const* nonces, uint32_t count) = 0;
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0;
@@ -19,19 +31,19 @@ public:
public:
ethash_cl_miner();
- bool init(ethash_params const& params, ethash_blockhash_t const *seed, unsigned workgroup_size = 64);
+ bool init(uint64_t block_number, std::function<void(void*)> _fillDAG, unsigned workgroup_size = 64, unsigned _platformId = 0, unsigned _deviceId = 0);
+ static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0);
+ static unsigned get_num_devices(unsigned _platformId = 0);
+
void finish();
void hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count);
void search(uint8_t const* header, uint64_t target, search_hook& hook);
private:
- static unsigned const c_max_search_results = 63;
- static unsigned const c_num_buffers = 2;
- static unsigned const c_hash_batch_size = 1024;
- static unsigned const c_search_batch_size = 1024*256;
+ enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 };
- ethash_params m_params;
+ uint64_t m_fullSize;
cl::Context m_context;
cl::CommandQueue m_queue;
cl::Kernel m_hash_kernel;
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner_kernel.cl b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner_kernel.cl
index ee21a331e..3c8b9dc92 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner_kernel.cl
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner_kernel.cl
@@ -415,8 +415,7 @@ __kernel void ethash_search_simple(
{
uint const gid = get_global_id(0);
hash32_t hash = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate);
-
- if (hash.ulongs[countof(hash.ulongs)-1] < target)
+ if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target)
{
uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1);
g_output[slot] = gid;
@@ -453,7 +452,7 @@ __kernel void ethash_search(
uint const gid = get_global_id(0);
hash32_t hash = compute_hash(share, g_header, g_dag, start_nonce + gid, isolate);
- if (hash.ulongs[countof(hash.ulongs)-1] < target)
+ if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target)
{
uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1);
g_output[slot] = gid;
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/CMakeLists.txt b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/CMakeLists.txt
index c92240086..a65621c3e 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/CMakeLists.txt
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/CMakeLists.txt
@@ -10,8 +10,7 @@ if (NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
endif()
-set(FILES util.c
- util.h
+set(FILES util.h
io.c
internal.c
ethash.h
@@ -21,7 +20,7 @@ set(FILES util.c
data_sizes.h)
if (MSVC)
- list(APPEND FILES io_win32.c)
+ list(APPEND FILES util_win32.c io_win32.c mmap_win32.c)
else()
list(APPEND FILES io_posix.c)
endif()
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/data_sizes.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/data_sizes.h
index cf52ae4f8..83cc30bcb 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/data_sizes.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/data_sizes.h
@@ -49,416 +49,416 @@ extern "C" {
static const uint64_t dag_sizes[2048] = {
- 1073739904U, 1082130304U, 1090514816U, 1098906752U, 1107293056U,
- 1115684224U, 1124070016U, 1132461952U, 1140849536U, 1149232768U,
- 1157627776U, 1166013824U, 1174404736U, 1182786944U, 1191180416U,
- 1199568512U, 1207958912U, 1216345216U, 1224732032U, 1233124736U,
- 1241513344U, 1249902464U, 1258290304U, 1266673792U, 1275067264U,
- 1283453312U, 1291844992U, 1300234112U, 1308619904U, 1317010048U,
- 1325397376U, 1333787776U, 1342176128U, 1350561664U, 1358954368U,
- 1367339392U, 1375731584U, 1384118144U, 1392507008U, 1400897408U,
- 1409284736U, 1417673344U, 1426062464U, 1434451072U, 1442839168U,
- 1451229056U, 1459615616U, 1468006016U, 1476394112U, 1484782976U,
- 1493171584U, 1501559168U, 1509948032U, 1518337664U, 1526726528U,
- 1535114624U, 1543503488U, 1551892096U, 1560278656U, 1568669056U,
- 1577056384U, 1585446272U, 1593831296U, 1602219392U, 1610610304U,
- 1619000192U, 1627386752U, 1635773824U, 1644164224U, 1652555648U,
- 1660943488U, 1669332608U, 1677721216U, 1686109312U, 1694497664U,
- 1702886272U, 1711274624U, 1719661184U, 1728047744U, 1736434816U,
- 1744829056U, 1753218944U, 1761606272U, 1769995904U, 1778382464U,
- 1786772864U, 1795157888U, 1803550592U, 1811937664U, 1820327552U,
- 1828711552U, 1837102976U, 1845488768U, 1853879936U, 1862269312U,
- 1870656896U, 1879048064U, 1887431552U, 1895825024U, 1904212096U,
- 1912601216U, 1920988544U, 1929379456U, 1937765504U, 1946156672U,
- 1954543232U, 1962932096U, 1971321728U, 1979707264U, 1988093056U,
- 1996487552U, 2004874624U, 2013262208U, 2021653888U, 2030039936U,
- 2038430848U, 2046819968U, 2055208576U, 2063596672U, 2071981952U,
- 2080373632U, 2088762752U, 2097149056U, 2105539712U, 2113928576U,
- 2122315136U, 2130700672U, 2139092608U, 2147483264U, 2155872128U,
- 2164257664U, 2172642176U, 2181035392U, 2189426048U, 2197814912U,
- 2206203008U, 2214587264U, 2222979712U, 2231367808U, 2239758208U,
- 2248145024U, 2256527744U, 2264922752U, 2273312128U, 2281701248U,
- 2290086272U, 2298476672U, 2306867072U, 2315251072U, 2323639168U,
- 2332032128U, 2340420224U, 2348808064U, 2357196416U, 2365580416U,
- 2373966976U, 2382363008U, 2390748544U, 2399139968U, 2407530368U,
- 2415918976U, 2424307328U, 2432695424U, 2441084288U, 2449472384U,
- 2457861248U, 2466247808U, 2474637184U, 2483026816U, 2491414144U,
- 2499803776U, 2508191872U, 2516582272U, 2524970368U, 2533359232U,
- 2541743488U, 2550134144U, 2558525056U, 2566913408U, 2575301504U,
- 2583686528U, 2592073856U, 2600467328U, 2608856192U, 2617240448U,
- 2625631616U, 2634022016U, 2642407552U, 2650796416U, 2659188352U,
- 2667574912U, 2675965312U, 2684352896U, 2692738688U, 2701130624U,
- 2709518464U, 2717907328U, 2726293376U, 2734685056U, 2743073152U,
- 2751462016U, 2759851648U, 2768232832U, 2776625536U, 2785017728U,
- 2793401984U, 2801794432U, 2810182016U, 2818571648U, 2826959488U,
- 2835349376U, 2843734144U, 2852121472U, 2860514432U, 2868900992U,
- 2877286784U, 2885676928U, 2894069632U, 2902451584U, 2910843008U,
- 2919234688U, 2927622784U, 2936011648U, 2944400768U, 2952789376U,
- 2961177728U, 2969565568U, 2977951616U, 2986338944U, 2994731392U,
- 3003120256U, 3011508352U, 3019895936U, 3028287104U, 3036675968U,
- 3045063808U, 3053452928U, 3061837696U, 3070228352U, 3078615424U,
- 3087003776U, 3095394944U, 3103782272U, 3112173184U, 3120562048U,
- 3128944768U, 3137339264U, 3145725056U, 3154109312U, 3162505088U,
- 3170893184U, 3179280256U, 3187669376U, 3196056704U, 3204445568U,
- 3212836736U, 3221224064U, 3229612928U, 3238002304U, 3246391168U,
- 3254778496U, 3263165824U, 3271556224U, 3279944576U, 3288332416U,
- 3296719232U, 3305110912U, 3313500032U, 3321887104U, 3330273152U,
- 3338658944U, 3347053184U, 3355440512U, 3363827072U, 3372220288U,
- 3380608384U, 3388997504U, 3397384576U, 3405774208U, 3414163072U,
- 3422551936U, 3430937984U, 3439328384U, 3447714176U, 3456104576U,
- 3464493952U, 3472883584U, 3481268864U, 3489655168U, 3498048896U,
- 3506434432U, 3514826368U, 3523213952U, 3531603584U, 3539987072U,
- 3548380288U, 3556763264U, 3565157248U, 3573545344U, 3581934464U,
- 3590324096U, 3598712704U, 3607098752U, 3615488384U, 3623877248U,
- 3632265856U, 3640646528U, 3649043584U, 3657430144U, 3665821568U,
- 3674207872U, 3682597504U, 3690984832U, 3699367808U, 3707764352U,
- 3716152448U, 3724541056U, 3732925568U, 3741318016U, 3749706368U,
- 3758091136U, 3766481536U, 3774872704U, 3783260032U, 3791650432U,
- 3800036224U, 3808427648U, 3816815488U, 3825204608U, 3833592704U,
- 3841981568U, 3850370432U, 3858755968U, 3867147904U, 3875536256U,
- 3883920512U, 3892313728U, 3900702592U, 3909087872U, 3917478784U,
- 3925868416U, 3934256512U, 3942645376U, 3951032192U, 3959422336U,
- 3967809152U, 3976200064U, 3984588416U, 3992974976U, 4001363584U,
- 4009751168U, 4018141312U, 4026530432U, 4034911616U, 4043308928U,
- 4051695488U, 4060084352U, 4068472448U, 4076862848U, 4085249408U,
- 4093640576U, 4102028416U, 4110413696U, 4118805632U, 4127194496U,
- 4135583104U, 4143971968U, 4152360832U, 4160746112U, 4169135744U,
- 4177525888U, 4185912704U, 4194303616U, 4202691968U, 4211076736U,
- 4219463552U, 4227855488U, 4236246656U, 4244633728U, 4253022848U,
- 4261412224U, 4269799808U, 4278184832U, 4286578048U, 4294962304U,
- 4303349632U, 4311743104U, 4320130432U, 4328521088U, 4336909184U,
- 4345295488U, 4353687424U, 4362073472U, 4370458496U, 4378852736U,
- 4387238528U, 4395630208U, 4404019072U, 4412407424U, 4420790656U,
- 4429182848U, 4437571456U, 4445962112U, 4454344064U, 4462738048U,
- 4471119232U, 4479516544U, 4487904128U, 4496289664U, 4504682368U,
- 4513068416U, 4521459584U, 4529846144U, 4538232704U, 4546619776U,
- 4555010176U, 4563402112U, 4571790208U, 4580174464U, 4588567936U,
- 4596957056U, 4605344896U, 4613734016U, 4622119808U, 4630511488U,
- 4638898816U, 4647287936U, 4655675264U, 4664065664U, 4672451968U,
- 4680842624U, 4689231488U, 4697620352U, 4706007424U, 4714397056U,
- 4722786176U, 4731173248U, 4739562368U, 4747951744U, 4756340608U,
- 4764727936U, 4773114496U, 4781504384U, 4789894784U, 4798283648U,
- 4806667648U, 4815059584U, 4823449472U, 4831835776U, 4840226176U,
- 4848612224U, 4857003392U, 4865391488U, 4873780096U, 4882169728U,
- 4890557312U, 4898946944U, 4907333248U, 4915722368U, 4924110976U,
- 4932499328U, 4940889728U, 4949276032U, 4957666432U, 4966054784U,
- 4974438016U, 4982831488U, 4991221376U, 4999607168U, 5007998848U,
- 5016386432U, 5024763776U, 5033164672U, 5041544576U, 5049941888U,
- 5058329728U, 5066717056U, 5075107456U, 5083494272U, 5091883904U,
- 5100273536U, 5108662144U, 5117048192U, 5125436032U, 5133827456U,
- 5142215296U, 5150605184U, 5158993024U, 5167382144U, 5175769472U,
- 5184157568U, 5192543872U, 5200936064U, 5209324928U, 5217711232U,
- 5226102656U, 5234490496U, 5242877312U, 5251263872U, 5259654016U,
- 5268040832U, 5276434304U, 5284819328U, 5293209728U, 5301598592U,
- 5309986688U, 5318374784U, 5326764416U, 5335151488U, 5343542144U,
- 5351929472U, 5360319872U, 5368706944U, 5377096576U, 5385484928U,
- 5393871232U, 5402263424U, 5410650496U, 5419040384U, 5427426944U,
- 5435816576U, 5444205952U, 5452594816U, 5460981376U, 5469367936U,
- 5477760896U, 5486148736U, 5494536832U, 5502925952U, 5511315328U,
- 5519703424U, 5528089984U, 5536481152U, 5544869504U, 5553256064U,
- 5561645696U, 5570032768U, 5578423936U, 5586811264U, 5595193216U,
- 5603585408U, 5611972736U, 5620366208U, 5628750464U, 5637143936U,
- 5645528192U, 5653921408U, 5662310272U, 5670694784U, 5679082624U,
- 5687474048U, 5695864448U, 5704251008U, 5712641408U, 5721030272U,
- 5729416832U, 5737806208U, 5746194304U, 5754583936U, 5762969984U,
- 5771358592U, 5779748224U, 5788137856U, 5796527488U, 5804911232U,
- 5813300608U, 5821692544U, 5830082176U, 5838468992U, 5846855552U,
- 5855247488U, 5863636096U, 5872024448U, 5880411008U, 5888799872U,
- 5897186432U, 5905576832U, 5913966976U, 5922352768U, 5930744704U,
- 5939132288U, 5947522432U, 5955911296U, 5964299392U, 5972688256U,
- 5981074304U, 5989465472U, 5997851008U, 6006241408U, 6014627968U,
- 6023015552U, 6031408256U, 6039796096U, 6048185216U, 6056574848U,
- 6064963456U, 6073351808U, 6081736064U, 6090128768U, 6098517632U,
- 6106906496U, 6115289216U, 6123680896U, 6132070016U, 6140459648U,
- 6148849024U, 6157237376U, 6165624704U, 6174009728U, 6182403712U,
- 6190792064U, 6199176064U, 6207569792U, 6215952256U, 6224345216U,
- 6232732544U, 6241124224U, 6249510272U, 6257899136U, 6266287744U,
- 6274676864U, 6283065728U, 6291454336U, 6299843456U, 6308232064U,
- 6316620928U, 6325006208U, 6333395584U, 6341784704U, 6350174848U,
- 6358562176U, 6366951296U, 6375337856U, 6383729536U, 6392119168U,
- 6400504192U, 6408895616U, 6417283456U, 6425673344U, 6434059136U,
- 6442444672U, 6450837376U, 6459223424U, 6467613056U, 6476004224U,
- 6484393088U, 6492781952U, 6501170048U, 6509555072U, 6517947008U,
- 6526336384U, 6534725504U, 6543112832U, 6551500672U, 6559888768U,
- 6568278656U, 6576662912U, 6585055616U, 6593443456U, 6601834112U,
- 6610219648U, 6618610304U, 6626999168U, 6635385472U, 6643777408U,
- 6652164224U, 6660552832U, 6668941952U, 6677330048U, 6685719424U,
- 6694107776U, 6702493568U, 6710882176U, 6719274112U, 6727662976U,
- 6736052096U, 6744437632U, 6752825984U, 6761213824U, 6769604224U,
- 6777993856U, 6786383488U, 6794770816U, 6803158144U, 6811549312U,
- 6819937664U, 6828326528U, 6836706176U, 6845101696U, 6853491328U,
- 6861880448U, 6870269312U, 6878655104U, 6887046272U, 6895433344U,
- 6903822208U, 6912212864U, 6920596864U, 6928988288U, 6937377152U,
- 6945764992U, 6954149248U, 6962544256U, 6970928768U, 6979317376U,
- 6987709312U, 6996093824U, 7004487296U, 7012875392U, 7021258624U,
- 7029652352U, 7038038912U, 7046427776U, 7054818944U, 7063207808U,
- 7071595136U, 7079980928U, 7088372608U, 7096759424U, 7105149824U,
- 7113536896U, 7121928064U, 7130315392U, 7138699648U, 7147092352U,
- 7155479168U, 7163865728U, 7172249984U, 7180648064U, 7189036672U,
- 7197424768U, 7205810816U, 7214196608U, 7222589824U, 7230975104U,
- 7239367552U, 7247755904U, 7256145536U, 7264533376U, 7272921472U,
- 7281308032U, 7289694848U, 7298088832U, 7306471808U, 7314864512U,
- 7323253888U, 7331643008U, 7340029568U, 7348419712U, 7356808832U,
- 7365196672U, 7373585792U, 7381973888U, 7390362752U, 7398750592U,
- 7407138944U, 7415528576U, 7423915648U, 7432302208U, 7440690304U,
- 7449080192U, 7457472128U, 7465860992U, 7474249088U, 7482635648U,
- 7491023744U, 7499412608U, 7507803008U, 7516192384U, 7524579968U,
- 7532967296U, 7541358464U, 7549745792U, 7558134656U, 7566524032U,
- 7574912896U, 7583300992U, 7591690112U, 7600075136U, 7608466816U,
- 7616854912U, 7625244544U, 7633629824U, 7642020992U, 7650410368U,
- 7658794112U, 7667187328U, 7675574912U, 7683961984U, 7692349568U,
- 7700739712U, 7709130368U, 7717519232U, 7725905536U, 7734295424U,
- 7742683264U, 7751069056U, 7759457408U, 7767849088U, 7776238208U,
- 7784626816U, 7793014912U, 7801405312U, 7809792128U, 7818179968U,
- 7826571136U, 7834957184U, 7843347328U, 7851732352U, 7860124544U,
- 7868512384U, 7876902016U, 7885287808U, 7893679744U, 7902067072U,
- 7910455936U, 7918844288U, 7927230848U, 7935622784U, 7944009344U,
- 7952400256U, 7960786048U, 7969176704U, 7977565312U, 7985953408U,
- 7994339968U, 8002730368U, 8011119488U, 8019508096U, 8027896192U,
- 8036285056U, 8044674688U, 8053062272U, 8061448832U, 8069838464U,
- 8078227328U, 8086616704U, 8095006592U, 8103393664U, 8111783552U,
- 8120171392U, 8128560256U, 8136949376U, 8145336704U, 8153726848U,
- 8162114944U, 8170503296U, 8178891904U, 8187280768U, 8195669632U,
- 8204058496U, 8212444544U, 8220834176U, 8229222272U, 8237612672U,
- 8246000768U, 8254389376U, 8262775168U, 8271167104U, 8279553664U,
- 8287944064U, 8296333184U, 8304715136U, 8313108352U, 8321497984U,
- 8329885568U, 8338274432U, 8346663296U, 8355052928U, 8363441536U,
- 8371828352U, 8380217984U, 8388606592U, 8396996224U, 8405384576U,
- 8413772672U, 8422161536U, 8430549376U, 8438939008U, 8447326592U,
- 8455715456U, 8464104832U, 8472492928U, 8480882048U, 8489270656U,
- 8497659776U, 8506045312U, 8514434944U, 8522823808U, 8531208832U,
- 8539602304U, 8547990656U, 8556378752U, 8564768384U, 8573154176U,
- 8581542784U, 8589933952U, 8598322816U, 8606705024U, 8615099264U,
- 8623487872U, 8631876992U, 8640264064U, 8648653952U, 8657040256U,
- 8665430656U, 8673820544U, 8682209152U, 8690592128U, 8698977152U,
- 8707374464U, 8715763328U, 8724151424U, 8732540032U, 8740928384U,
- 8749315712U, 8757704576U, 8766089344U, 8774480768U, 8782871936U,
- 8791260032U, 8799645824U, 8808034432U, 8816426368U, 8824812928U,
- 8833199488U, 8841591424U, 8849976448U, 8858366336U, 8866757248U,
- 8875147136U, 8883532928U, 8891923328U, 8900306816U, 8908700288U,
- 8917088384U, 8925478784U, 8933867392U, 8942250368U, 8950644608U,
- 8959032704U, 8967420544U, 8975809664U, 8984197504U, 8992584064U,
- 9000976256U, 9009362048U, 9017752448U, 9026141312U, 9034530688U,
- 9042917504U, 9051307904U, 9059694208U, 9068084864U, 9076471424U,
- 9084861824U, 9093250688U, 9101638528U, 9110027648U, 9118416512U,
- 9126803584U, 9135188096U, 9143581312U, 9151969664U, 9160356224U,
- 9168747136U, 9177134464U, 9185525632U, 9193910144U, 9202302848U,
- 9210690688U, 9219079552U, 9227465344U, 9235854464U, 9244244864U,
- 9252633472U, 9261021824U, 9269411456U, 9277799296U, 9286188928U,
- 9294574208U, 9302965888U, 9311351936U, 9319740032U, 9328131968U,
- 9336516736U, 9344907392U, 9353296768U, 9361685888U, 9370074752U,
- 9378463616U, 9386849408U, 9395239808U, 9403629184U, 9412016512U,
- 9420405376U, 9428795008U, 9437181568U, 9445570688U, 9453960832U,
- 9462346624U, 9470738048U, 9479121536U, 9487515008U, 9495903616U,
- 9504289664U, 9512678528U, 9521067904U, 9529456256U, 9537843584U,
- 9546233728U, 9554621312U, 9563011456U, 9571398784U, 9579788672U,
- 9588178304U, 9596567168U, 9604954496U, 9613343104U, 9621732992U,
- 9630121856U, 9638508416U, 9646898816U, 9655283584U, 9663675776U,
- 9672061312U, 9680449664U, 9688840064U, 9697230464U, 9705617536U,
- 9714003584U, 9722393984U, 9730772608U, 9739172224U, 9747561088U,
- 9755945344U, 9764338816U, 9772726144U, 9781116544U, 9789503872U,
- 9797892992U, 9806282624U, 9814670464U, 9823056512U, 9831439232U,
- 9839833984U, 9848224384U, 9856613504U, 9865000576U, 9873391232U,
- 9881772416U, 9890162816U, 9898556288U, 9906940544U, 9915333248U,
- 9923721088U, 9932108672U, 9940496512U, 9948888448U, 9957276544U,
- 9965666176U, 9974048384U, 9982441088U, 9990830464U, 9999219584U,
- 10007602816U, 10015996544U, 10024385152U, 10032774016U, 10041163648U,
- 10049548928U, 10057940096U, 10066329472U, 10074717824U, 10083105152U,
- 10091495296U, 10099878784U, 10108272256U, 10116660608U, 10125049216U,
- 10133437312U, 10141825664U, 10150213504U, 10158601088U, 10166991232U,
- 10175378816U, 10183766144U, 10192157312U, 10200545408U, 10208935552U,
- 10217322112U, 10225712768U, 10234099328U, 10242489472U, 10250876032U,
- 10259264896U, 10267656064U, 10276042624U, 10284429184U, 10292820352U,
- 10301209472U, 10309598848U, 10317987712U, 10326375296U, 10334763392U,
- 10343153536U, 10351541632U, 10359930752U, 10368318592U, 10376707456U,
- 10385096576U, 10393484672U, 10401867136U, 10410262144U, 10418647424U,
- 10427039104U, 10435425664U, 10443810176U, 10452203648U, 10460589952U,
- 10468982144U, 10477369472U, 10485759104U, 10494147712U, 10502533504U,
- 10510923392U, 10519313536U, 10527702656U, 10536091264U, 10544478592U,
- 10552867712U, 10561255808U, 10569642368U, 10578032768U, 10586423168U,
- 10594805632U, 10603200128U, 10611588992U, 10619976064U, 10628361344U,
- 10636754048U, 10645143424U, 10653531776U, 10661920384U, 10670307968U,
- 10678696832U, 10687086464U, 10695475072U, 10703863168U, 10712246144U,
- 10720639616U, 10729026688U, 10737414784U, 10745806208U, 10754190976U,
- 10762581376U, 10770971264U, 10779356288U, 10787747456U, 10796135552U,
- 10804525184U, 10812915584U, 10821301888U, 10829692288U, 10838078336U,
- 10846469248U, 10854858368U, 10863247232U, 10871631488U, 10880023424U,
- 10888412032U, 10896799616U, 10905188992U, 10913574016U, 10921964672U,
- 10930352768U, 10938742912U, 10947132544U, 10955518592U, 10963909504U,
- 10972298368U, 10980687488U, 10989074816U, 10997462912U, 11005851776U,
- 11014241152U, 11022627712U, 11031017344U, 11039403904U, 11047793024U,
- 11056184704U, 11064570752U, 11072960896U, 11081343872U, 11089737856U,
- 11098128256U, 11106514816U, 11114904448U, 11123293568U, 11131680128U,
- 11140065152U, 11148458368U, 11156845696U, 11165236864U, 11173624192U,
- 11182013824U, 11190402688U, 11198790784U, 11207179136U, 11215568768U,
- 11223957376U, 11232345728U, 11240734592U, 11249122688U, 11257511296U,
- 11265899648U, 11274285952U, 11282675584U, 11291065472U, 11299452544U,
- 11307842432U, 11316231296U, 11324616832U, 11333009024U, 11341395584U,
- 11349782656U, 11358172288U, 11366560384U, 11374950016U, 11383339648U,
- 11391721856U, 11400117376U, 11408504192U, 11416893568U, 11425283456U,
- 11433671552U, 11442061184U, 11450444672U, 11458837888U, 11467226752U,
- 11475611776U, 11484003968U, 11492392064U, 11500780672U, 11509169024U,
- 11517550976U, 11525944448U, 11534335616U, 11542724224U, 11551111808U,
- 11559500672U, 11567890304U, 11576277376U, 11584667008U, 11593056128U,
- 11601443456U, 11609830016U, 11618221952U, 11626607488U, 11634995072U,
- 11643387776U, 11651775104U, 11660161664U, 11668552576U, 11676940928U,
- 11685330304U, 11693718656U, 11702106496U, 11710496128U, 11718882688U,
- 11727273088U, 11735660416U, 11744050048U, 11752437376U, 11760824704U,
- 11769216128U, 11777604736U, 11785991296U, 11794381952U, 11802770048U,
- 11811157888U, 11819548544U, 11827932544U, 11836324736U, 11844713344U,
- 11853100928U, 11861486464U, 11869879936U, 11878268032U, 11886656896U,
- 11895044992U, 11903433088U, 11911822976U, 11920210816U, 11928600448U,
- 11936987264U, 11945375872U, 11953761152U, 11962151296U, 11970543488U,
- 11978928512U, 11987320448U, 11995708288U, 12004095104U, 12012486272U,
- 12020875136U, 12029255552U, 12037652096U, 12046039168U, 12054429568U,
- 12062813824U, 12071206528U, 12079594624U, 12087983744U, 12096371072U,
- 12104759936U, 12113147264U, 12121534592U, 12129924992U, 12138314624U,
- 12146703232U, 12155091584U, 12163481216U, 12171864704U, 12180255872U,
- 12188643968U, 12197034112U, 12205424512U, 12213811328U, 12222199424U,
- 12230590336U, 12238977664U, 12247365248U, 12255755392U, 12264143488U,
- 12272531584U, 12280920448U, 12289309568U, 12297694592U, 12306086528U,
- 12314475392U, 12322865024U, 12331253632U, 12339640448U, 12348029312U,
- 12356418944U, 12364805248U, 12373196672U, 12381580928U, 12389969024U,
- 12398357632U, 12406750592U, 12415138432U, 12423527552U, 12431916416U,
- 12440304512U, 12448692352U, 12457081216U, 12465467776U, 12473859968U,
- 12482245504U, 12490636672U, 12499025536U, 12507411584U, 12515801728U,
- 12524190592U, 12532577152U, 12540966272U, 12549354368U, 12557743232U,
- 12566129536U, 12574523264U, 12582911872U, 12591299456U, 12599688064U,
- 12608074624U, 12616463488U, 12624845696U, 12633239936U, 12641631616U,
- 12650019968U, 12658407296U, 12666795136U, 12675183232U, 12683574656U,
- 12691960192U, 12700350592U, 12708740224U, 12717128576U, 12725515904U,
- 12733906816U, 12742295168U, 12750680192U, 12759071872U, 12767460736U,
- 12775848832U, 12784236928U, 12792626816U, 12801014656U, 12809404288U,
- 12817789312U, 12826181504U, 12834568832U, 12842954624U, 12851345792U,
- 12859732352U, 12868122496U, 12876512128U, 12884901248U, 12893289088U,
- 12901672832U, 12910067584U, 12918455168U, 12926842496U, 12935232896U,
- 12943620736U, 12952009856U, 12960396928U, 12968786816U, 12977176192U,
- 12985563776U, 12993951104U, 13002341504U, 13010730368U, 13019115392U,
- 13027506304U, 13035895168U, 13044272512U, 13052673152U, 13061062528U,
- 13069446272U, 13077838976U, 13086227072U, 13094613632U, 13103000192U,
- 13111393664U, 13119782528U, 13128157568U, 13136559232U, 13144945024U,
- 13153329536U, 13161724288U, 13170111872U, 13178502784U, 13186884736U,
- 13195279744U, 13203667072U, 13212057472U, 13220445824U, 13228832128U,
- 13237221248U, 13245610624U, 13254000512U, 13262388352U, 13270777472U,
- 13279166336U, 13287553408U, 13295943296U, 13304331904U, 13312719488U,
- 13321108096U, 13329494656U, 13337885824U, 13346274944U, 13354663808U,
- 13363051136U, 13371439232U, 13379825024U, 13388210816U, 13396605056U,
- 13404995456U, 13413380224U, 13421771392U, 13430159744U, 13438546048U,
- 13446937216U, 13455326848U, 13463708288U, 13472103808U, 13480492672U,
- 13488875648U, 13497269888U, 13505657728U, 13514045312U, 13522435712U,
- 13530824576U, 13539210112U, 13547599232U, 13555989376U, 13564379008U,
- 13572766336U, 13581154432U, 13589544832U, 13597932928U, 13606320512U,
- 13614710656U, 13623097472U, 13631477632U, 13639874944U, 13648264064U,
- 13656652928U, 13665041792U, 13673430656U, 13681818496U, 13690207616U,
- 13698595712U, 13706982272U, 13715373184U, 13723762048U, 13732150144U,
- 13740536704U, 13748926592U, 13757316224U, 13765700992U, 13774090112U,
- 13782477952U, 13790869376U, 13799259008U, 13807647872U, 13816036736U,
- 13824425344U, 13832814208U, 13841202304U, 13849591424U, 13857978752U,
- 13866368896U, 13874754688U, 13883145344U, 13891533184U, 13899919232U,
- 13908311168U, 13916692096U, 13925085056U, 13933473152U, 13941866368U,
- 13950253696U, 13958643584U, 13967032192U, 13975417216U, 13983807616U,
- 13992197504U, 14000582272U, 14008973696U, 14017363072U, 14025752192U,
- 14034137984U, 14042528384U, 14050918016U, 14059301504U, 14067691648U,
- 14076083584U, 14084470144U, 14092852352U, 14101249664U, 14109635968U,
- 14118024832U, 14126407552U, 14134804352U, 14143188608U, 14151577984U,
- 14159968384U, 14168357248U, 14176741504U, 14185127296U, 14193521024U,
- 14201911424U, 14210301824U, 14218685056U, 14227067264U, 14235467392U,
- 14243855488U, 14252243072U, 14260630144U, 14269021568U, 14277409408U,
- 14285799296U, 14294187904U, 14302571392U, 14310961792U, 14319353728U,
- 14327738752U, 14336130944U, 14344518784U, 14352906368U, 14361296512U,
- 14369685376U, 14378071424U, 14386462592U, 14394848128U, 14403230848U,
- 14411627392U, 14420013952U, 14428402304U, 14436793472U, 14445181568U,
- 14453569664U, 14461959808U, 14470347904U, 14478737024U, 14487122816U,
- 14495511424U, 14503901824U, 14512291712U, 14520677504U, 14529064832U,
- 14537456768U, 14545845632U, 14554234496U, 14562618496U, 14571011456U,
- 14579398784U, 14587789184U, 14596172672U, 14604564608U, 14612953984U,
- 14621341312U, 14629724288U, 14638120832U, 14646503296U, 14654897536U,
- 14663284864U, 14671675264U, 14680061056U, 14688447616U, 14696835968U,
- 14705228416U, 14713616768U, 14722003328U, 14730392192U, 14738784128U,
- 14747172736U, 14755561088U, 14763947648U, 14772336512U, 14780725376U,
- 14789110144U, 14797499776U, 14805892736U, 14814276992U, 14822670208U,
- 14831056256U, 14839444352U, 14847836032U, 14856222848U, 14864612992U,
- 14872997504U, 14881388672U, 14889775744U, 14898165376U, 14906553472U,
- 14914944896U, 14923329664U, 14931721856U, 14940109696U, 14948497024U,
- 14956887424U, 14965276544U, 14973663616U, 14982053248U, 14990439808U,
- 14998830976U, 15007216768U, 15015605888U, 15023995264U, 15032385152U,
- 15040768384U, 15049154944U, 15057549184U, 15065939072U, 15074328448U,
- 15082715008U, 15091104128U, 15099493504U, 15107879296U, 15116269184U,
- 15124659584U, 15133042304U, 15141431936U, 15149824384U, 15158214272U,
- 15166602368U, 15174991232U, 15183378304U, 15191760512U, 15200154496U,
- 15208542592U, 15216931712U, 15225323392U, 15233708416U, 15242098048U,
- 15250489216U, 15258875264U, 15267265408U, 15275654528U, 15284043136U,
- 15292431488U, 15300819584U, 15309208192U, 15317596544U, 15325986176U,
- 15334374784U, 15342763648U, 15351151744U, 15359540608U, 15367929728U,
- 15376318336U, 15384706432U, 15393092992U, 15401481856U, 15409869952U,
- 15418258816U, 15426649984U, 15435037568U, 15443425664U, 15451815296U,
- 15460203392U, 15468589184U, 15476979328U, 15485369216U, 15493755776U,
- 15502146944U, 15510534272U, 15518924416U, 15527311232U, 15535699072U,
- 15544089472U, 15552478336U, 15560866688U, 15569254528U, 15577642624U,
- 15586031488U, 15594419072U, 15602809472U, 15611199104U, 15619586432U,
- 15627975296U, 15636364928U, 15644753792U, 15653141888U, 15661529216U,
- 15669918848U, 15678305152U, 15686696576U, 15695083136U, 15703474048U,
- 15711861632U, 15720251264U, 15728636288U, 15737027456U, 15745417088U,
- 15753804928U, 15762194048U, 15770582656U, 15778971008U, 15787358336U,
- 15795747712U, 15804132224U, 15812523392U, 15820909696U, 15829300096U,
- 15837691264U, 15846071936U, 15854466944U, 15862855808U, 15871244672U,
- 15879634816U, 15888020608U, 15896409728U, 15904799104U, 15913185152U,
- 15921577088U, 15929966464U, 15938354816U, 15946743424U, 15955129472U,
- 15963519872U, 15971907968U, 15980296064U, 15988684928U, 15997073024U,
- 16005460864U, 16013851264U, 16022241152U, 16030629248U, 16039012736U,
- 16047406976U, 16055794816U, 16064181376U, 16072571264U, 16080957824U,
- 16089346688U, 16097737856U, 16106125184U, 16114514816U, 16122904192U,
- 16131292544U, 16139678848U, 16148066944U, 16156453504U, 16164839552U,
- 16173236096U, 16181623424U, 16190012032U, 16198401152U, 16206790528U,
- 16215177344U, 16223567744U, 16231956352U, 16240344704U, 16248731008U,
- 16257117824U, 16265504384U, 16273898624U, 16282281856U, 16290668672U,
- 16299064192U, 16307449216U, 16315842176U, 16324230016U, 16332613504U,
- 16341006464U, 16349394304U, 16357783168U, 16366172288U, 16374561664U,
- 16382951296U, 16391337856U, 16399726208U, 16408116352U, 16416505472U,
- 16424892032U, 16433282176U, 16441668224U, 16450058624U, 16458448768U,
- 16466836864U, 16475224448U, 16483613056U, 16492001408U, 16500391808U,
- 16508779648U, 16517166976U, 16525555328U, 16533944192U, 16542330752U,
- 16550719616U, 16559110528U, 16567497088U, 16575888512U, 16584274816U,
- 16592665472U, 16601051008U, 16609442944U, 16617832064U, 16626218624U,
- 16634607488U, 16642996096U, 16651385728U, 16659773824U, 16668163712U,
- 16676552576U, 16684938112U, 16693328768U, 16701718144U, 16710095488U,
- 16718492288U, 16726883968U, 16735272832U, 16743661184U, 16752049792U,
- 16760436608U, 16768827008U, 16777214336U, 16785599104U, 16793992832U,
- 16802381696U, 16810768768U, 16819151744U, 16827542656U, 16835934848U,
- 16844323712U, 16852711552U, 16861101952U, 16869489536U, 16877876864U,
- 16886265728U, 16894653056U, 16903044736U, 16911431296U, 16919821696U,
- 16928207488U, 16936592768U, 16944987776U, 16953375616U, 16961763968U,
- 16970152832U, 16978540928U, 16986929536U, 16995319168U, 17003704448U,
- 17012096896U, 17020481152U, 17028870784U, 17037262208U, 17045649536U,
- 17054039936U, 17062426496U, 17070814336U, 17079205504U, 17087592064U,
- 17095978112U, 17104369024U, 17112759424U, 17121147776U, 17129536384U,
- 17137926016U, 17146314368U, 17154700928U, 17163089792U, 17171480192U,
- 17179864192U, 17188256896U, 17196644992U, 17205033856U, 17213423488U,
- 17221811072U, 17230198912U, 17238588032U, 17246976896U, 17255360384U,
- 17263754624U, 17272143232U, 17280530048U, 17288918912U, 17297309312U,
- 17305696384U, 17314085504U, 17322475136U, 17330863744U, 17339252096U,
- 17347640192U, 17356026496U, 17364413824U, 17372796544U, 17381190016U,
- 17389583488U, 17397972608U, 17406360704U, 17414748544U, 17423135872U,
- 17431527296U, 17439915904U, 17448303232U, 17456691584U, 17465081728U,
- 17473468288U, 17481857408U, 17490247552U, 17498635904U, 17507022464U,
- 17515409024U, 17523801728U, 17532189824U, 17540577664U, 17548966016U,
- 17557353344U, 17565741184U, 17574131584U, 17582519168U, 17590907008U,
- 17599296128U, 17607687808U, 17616076672U, 17624455808U, 17632852352U,
- 17641238656U, 17649630848U, 17658018944U, 17666403968U, 17674794112U,
- 17683178368U, 17691573376U, 17699962496U, 17708350592U, 17716739968U,
- 17725126528U, 17733517184U, 17741898112U, 17750293888U, 17758673024U,
- 17767070336U, 17775458432U, 17783848832U, 17792236928U, 17800625536U,
- 17809012352U, 17817402752U, 17825785984U, 17834178944U, 17842563968U,
- 17850955648U, 17859344512U, 17867732864U, 17876119424U, 17884511872U,
- 17892900224U, 17901287296U, 17909677696U, 17918058112U, 17926451072U,
- 17934843776U, 17943230848U, 17951609216U, 17960008576U, 17968397696U,
- 17976784256U, 17985175424U, 17993564032U, 18001952128U, 18010339712U,
- 18018728576U, 18027116672U, 18035503232U, 18043894144U, 18052283264U,
- 18060672128U, 18069056384U, 18077449856U, 18085837184U, 18094225792U,
- 18102613376U, 18111004544U, 18119388544U, 18127781248U, 18136170368U,
- 18144558976U, 18152947328U, 18161336192U, 18169724288U, 18178108544U,
- 18186498944U, 18194886784U, 18203275648U, 18211666048U, 18220048768U,
- 18228444544U, 18236833408U, 18245220736U
+ 1073739904U, 1082130304U, 1090514816U, 1098906752U, 1107293056U,
+ 1115684224U, 1124070016U, 1132461952U, 1140849536U, 1149232768U,
+ 1157627776U, 1166013824U, 1174404736U, 1182786944U, 1191180416U,
+ 1199568512U, 1207958912U, 1216345216U, 1224732032U, 1233124736U,
+ 1241513344U, 1249902464U, 1258290304U, 1266673792U, 1275067264U,
+ 1283453312U, 1291844992U, 1300234112U, 1308619904U, 1317010048U,
+ 1325397376U, 1333787776U, 1342176128U, 1350561664U, 1358954368U,
+ 1367339392U, 1375731584U, 1384118144U, 1392507008U, 1400897408U,
+ 1409284736U, 1417673344U, 1426062464U, 1434451072U, 1442839168U,
+ 1451229056U, 1459615616U, 1468006016U, 1476394112U, 1484782976U,
+ 1493171584U, 1501559168U, 1509948032U, 1518337664U, 1526726528U,
+ 1535114624U, 1543503488U, 1551892096U, 1560278656U, 1568669056U,
+ 1577056384U, 1585446272U, 1593831296U, 1602219392U, 1610610304U,
+ 1619000192U, 1627386752U, 1635773824U, 1644164224U, 1652555648U,
+ 1660943488U, 1669332608U, 1677721216U, 1686109312U, 1694497664U,
+ 1702886272U, 1711274624U, 1719661184U, 1728047744U, 1736434816U,
+ 1744829056U, 1753218944U, 1761606272U, 1769995904U, 1778382464U,
+ 1786772864U, 1795157888U, 1803550592U, 1811937664U, 1820327552U,
+ 1828711552U, 1837102976U, 1845488768U, 1853879936U, 1862269312U,
+ 1870656896U, 1879048064U, 1887431552U, 1895825024U, 1904212096U,
+ 1912601216U, 1920988544U, 1929379456U, 1937765504U, 1946156672U,
+ 1954543232U, 1962932096U, 1971321728U, 1979707264U, 1988093056U,
+ 1996487552U, 2004874624U, 2013262208U, 2021653888U, 2030039936U,
+ 2038430848U, 2046819968U, 2055208576U, 2063596672U, 2071981952U,
+ 2080373632U, 2088762752U, 2097149056U, 2105539712U, 2113928576U,
+ 2122315136U, 2130700672U, 2139092608U, 2147483264U, 2155872128U,
+ 2164257664U, 2172642176U, 2181035392U, 2189426048U, 2197814912U,
+ 2206203008U, 2214587264U, 2222979712U, 2231367808U, 2239758208U,
+ 2248145024U, 2256527744U, 2264922752U, 2273312128U, 2281701248U,
+ 2290086272U, 2298476672U, 2306867072U, 2315251072U, 2323639168U,
+ 2332032128U, 2340420224U, 2348808064U, 2357196416U, 2365580416U,
+ 2373966976U, 2382363008U, 2390748544U, 2399139968U, 2407530368U,
+ 2415918976U, 2424307328U, 2432695424U, 2441084288U, 2449472384U,
+ 2457861248U, 2466247808U, 2474637184U, 2483026816U, 2491414144U,
+ 2499803776U, 2508191872U, 2516582272U, 2524970368U, 2533359232U,
+ 2541743488U, 2550134144U, 2558525056U, 2566913408U, 2575301504U,
+ 2583686528U, 2592073856U, 2600467328U, 2608856192U, 2617240448U,
+ 2625631616U, 2634022016U, 2642407552U, 2650796416U, 2659188352U,
+ 2667574912U, 2675965312U, 2684352896U, 2692738688U, 2701130624U,
+ 2709518464U, 2717907328U, 2726293376U, 2734685056U, 2743073152U,
+ 2751462016U, 2759851648U, 2768232832U, 2776625536U, 2785017728U,
+ 2793401984U, 2801794432U, 2810182016U, 2818571648U, 2826959488U,
+ 2835349376U, 2843734144U, 2852121472U, 2860514432U, 2868900992U,
+ 2877286784U, 2885676928U, 2894069632U, 2902451584U, 2910843008U,
+ 2919234688U, 2927622784U, 2936011648U, 2944400768U, 2952789376U,
+ 2961177728U, 2969565568U, 2977951616U, 2986338944U, 2994731392U,
+ 3003120256U, 3011508352U, 3019895936U, 3028287104U, 3036675968U,
+ 3045063808U, 3053452928U, 3061837696U, 3070228352U, 3078615424U,
+ 3087003776U, 3095394944U, 3103782272U, 3112173184U, 3120562048U,
+ 3128944768U, 3137339264U, 3145725056U, 3154109312U, 3162505088U,
+ 3170893184U, 3179280256U, 3187669376U, 3196056704U, 3204445568U,
+ 3212836736U, 3221224064U, 3229612928U, 3238002304U, 3246391168U,
+ 3254778496U, 3263165824U, 3271556224U, 3279944576U, 3288332416U,
+ 3296719232U, 3305110912U, 3313500032U, 3321887104U, 3330273152U,
+ 3338658944U, 3347053184U, 3355440512U, 3363827072U, 3372220288U,
+ 3380608384U, 3388997504U, 3397384576U, 3405774208U, 3414163072U,
+ 3422551936U, 3430937984U, 3439328384U, 3447714176U, 3456104576U,
+ 3464493952U, 3472883584U, 3481268864U, 3489655168U, 3498048896U,
+ 3506434432U, 3514826368U, 3523213952U, 3531603584U, 3539987072U,
+ 3548380288U, 3556763264U, 3565157248U, 3573545344U, 3581934464U,
+ 3590324096U, 3598712704U, 3607098752U, 3615488384U, 3623877248U,
+ 3632265856U, 3640646528U, 3649043584U, 3657430144U, 3665821568U,
+ 3674207872U, 3682597504U, 3690984832U, 3699367808U, 3707764352U,
+ 3716152448U, 3724541056U, 3732925568U, 3741318016U, 3749706368U,
+ 3758091136U, 3766481536U, 3774872704U, 3783260032U, 3791650432U,
+ 3800036224U, 3808427648U, 3816815488U, 3825204608U, 3833592704U,
+ 3841981568U, 3850370432U, 3858755968U, 3867147904U, 3875536256U,
+ 3883920512U, 3892313728U, 3900702592U, 3909087872U, 3917478784U,
+ 3925868416U, 3934256512U, 3942645376U, 3951032192U, 3959422336U,
+ 3967809152U, 3976200064U, 3984588416U, 3992974976U, 4001363584U,
+ 4009751168U, 4018141312U, 4026530432U, 4034911616U, 4043308928U,
+ 4051695488U, 4060084352U, 4068472448U, 4076862848U, 4085249408U,
+ 4093640576U, 4102028416U, 4110413696U, 4118805632U, 4127194496U,
+ 4135583104U, 4143971968U, 4152360832U, 4160746112U, 4169135744U,
+ 4177525888U, 4185912704U, 4194303616U, 4202691968U, 4211076736U,
+ 4219463552U, 4227855488U, 4236246656U, 4244633728U, 4253022848U,
+ 4261412224U, 4269799808U, 4278184832U, 4286578048U, 4294962304U,
+ 4303349632U, 4311743104U, 4320130432U, 4328521088U, 4336909184U,
+ 4345295488U, 4353687424U, 4362073472U, 4370458496U, 4378852736U,
+ 4387238528U, 4395630208U, 4404019072U, 4412407424U, 4420790656U,
+ 4429182848U, 4437571456U, 4445962112U, 4454344064U, 4462738048U,
+ 4471119232U, 4479516544U, 4487904128U, 4496289664U, 4504682368U,
+ 4513068416U, 4521459584U, 4529846144U, 4538232704U, 4546619776U,
+ 4555010176U, 4563402112U, 4571790208U, 4580174464U, 4588567936U,
+ 4596957056U, 4605344896U, 4613734016U, 4622119808U, 4630511488U,
+ 4638898816U, 4647287936U, 4655675264U, 4664065664U, 4672451968U,
+ 4680842624U, 4689231488U, 4697620352U, 4706007424U, 4714397056U,
+ 4722786176U, 4731173248U, 4739562368U, 4747951744U, 4756340608U,
+ 4764727936U, 4773114496U, 4781504384U, 4789894784U, 4798283648U,
+ 4806667648U, 4815059584U, 4823449472U, 4831835776U, 4840226176U,
+ 4848612224U, 4857003392U, 4865391488U, 4873780096U, 4882169728U,
+ 4890557312U, 4898946944U, 4907333248U, 4915722368U, 4924110976U,
+ 4932499328U, 4940889728U, 4949276032U, 4957666432U, 4966054784U,
+ 4974438016U, 4982831488U, 4991221376U, 4999607168U, 5007998848U,
+ 5016386432U, 5024763776U, 5033164672U, 5041544576U, 5049941888U,
+ 5058329728U, 5066717056U, 5075107456U, 5083494272U, 5091883904U,
+ 5100273536U, 5108662144U, 5117048192U, 5125436032U, 5133827456U,
+ 5142215296U, 5150605184U, 5158993024U, 5167382144U, 5175769472U,
+ 5184157568U, 5192543872U, 5200936064U, 5209324928U, 5217711232U,
+ 5226102656U, 5234490496U, 5242877312U, 5251263872U, 5259654016U,
+ 5268040832U, 5276434304U, 5284819328U, 5293209728U, 5301598592U,
+ 5309986688U, 5318374784U, 5326764416U, 5335151488U, 5343542144U,
+ 5351929472U, 5360319872U, 5368706944U, 5377096576U, 5385484928U,
+ 5393871232U, 5402263424U, 5410650496U, 5419040384U, 5427426944U,
+ 5435816576U, 5444205952U, 5452594816U, 5460981376U, 5469367936U,
+ 5477760896U, 5486148736U, 5494536832U, 5502925952U, 5511315328U,
+ 5519703424U, 5528089984U, 5536481152U, 5544869504U, 5553256064U,
+ 5561645696U, 5570032768U, 5578423936U, 5586811264U, 5595193216U,
+ 5603585408U, 5611972736U, 5620366208U, 5628750464U, 5637143936U,
+ 5645528192U, 5653921408U, 5662310272U, 5670694784U, 5679082624U,
+ 5687474048U, 5695864448U, 5704251008U, 5712641408U, 5721030272U,
+ 5729416832U, 5737806208U, 5746194304U, 5754583936U, 5762969984U,
+ 5771358592U, 5779748224U, 5788137856U, 5796527488U, 5804911232U,
+ 5813300608U, 5821692544U, 5830082176U, 5838468992U, 5846855552U,
+ 5855247488U, 5863636096U, 5872024448U, 5880411008U, 5888799872U,
+ 5897186432U, 5905576832U, 5913966976U, 5922352768U, 5930744704U,
+ 5939132288U, 5947522432U, 5955911296U, 5964299392U, 5972688256U,
+ 5981074304U, 5989465472U, 5997851008U, 6006241408U, 6014627968U,
+ 6023015552U, 6031408256U, 6039796096U, 6048185216U, 6056574848U,
+ 6064963456U, 6073351808U, 6081736064U, 6090128768U, 6098517632U,
+ 6106906496U, 6115289216U, 6123680896U, 6132070016U, 6140459648U,
+ 6148849024U, 6157237376U, 6165624704U, 6174009728U, 6182403712U,
+ 6190792064U, 6199176064U, 6207569792U, 6215952256U, 6224345216U,
+ 6232732544U, 6241124224U, 6249510272U, 6257899136U, 6266287744U,
+ 6274676864U, 6283065728U, 6291454336U, 6299843456U, 6308232064U,
+ 6316620928U, 6325006208U, 6333395584U, 6341784704U, 6350174848U,
+ 6358562176U, 6366951296U, 6375337856U, 6383729536U, 6392119168U,
+ 6400504192U, 6408895616U, 6417283456U, 6425673344U, 6434059136U,
+ 6442444672U, 6450837376U, 6459223424U, 6467613056U, 6476004224U,
+ 6484393088U, 6492781952U, 6501170048U, 6509555072U, 6517947008U,
+ 6526336384U, 6534725504U, 6543112832U, 6551500672U, 6559888768U,
+ 6568278656U, 6576662912U, 6585055616U, 6593443456U, 6601834112U,
+ 6610219648U, 6618610304U, 6626999168U, 6635385472U, 6643777408U,
+ 6652164224U, 6660552832U, 6668941952U, 6677330048U, 6685719424U,
+ 6694107776U, 6702493568U, 6710882176U, 6719274112U, 6727662976U,
+ 6736052096U, 6744437632U, 6752825984U, 6761213824U, 6769604224U,
+ 6777993856U, 6786383488U, 6794770816U, 6803158144U, 6811549312U,
+ 6819937664U, 6828326528U, 6836706176U, 6845101696U, 6853491328U,
+ 6861880448U, 6870269312U, 6878655104U, 6887046272U, 6895433344U,
+ 6903822208U, 6912212864U, 6920596864U, 6928988288U, 6937377152U,
+ 6945764992U, 6954149248U, 6962544256U, 6970928768U, 6979317376U,
+ 6987709312U, 6996093824U, 7004487296U, 7012875392U, 7021258624U,
+ 7029652352U, 7038038912U, 7046427776U, 7054818944U, 7063207808U,
+ 7071595136U, 7079980928U, 7088372608U, 7096759424U, 7105149824U,
+ 7113536896U, 7121928064U, 7130315392U, 7138699648U, 7147092352U,
+ 7155479168U, 7163865728U, 7172249984U, 7180648064U, 7189036672U,
+ 7197424768U, 7205810816U, 7214196608U, 7222589824U, 7230975104U,
+ 7239367552U, 7247755904U, 7256145536U, 7264533376U, 7272921472U,
+ 7281308032U, 7289694848U, 7298088832U, 7306471808U, 7314864512U,
+ 7323253888U, 7331643008U, 7340029568U, 7348419712U, 7356808832U,
+ 7365196672U, 7373585792U, 7381973888U, 7390362752U, 7398750592U,
+ 7407138944U, 7415528576U, 7423915648U, 7432302208U, 7440690304U,
+ 7449080192U, 7457472128U, 7465860992U, 7474249088U, 7482635648U,
+ 7491023744U, 7499412608U, 7507803008U, 7516192384U, 7524579968U,
+ 7532967296U, 7541358464U, 7549745792U, 7558134656U, 7566524032U,
+ 7574912896U, 7583300992U, 7591690112U, 7600075136U, 7608466816U,
+ 7616854912U, 7625244544U, 7633629824U, 7642020992U, 7650410368U,
+ 7658794112U, 7667187328U, 7675574912U, 7683961984U, 7692349568U,
+ 7700739712U, 7709130368U, 7717519232U, 7725905536U, 7734295424U,
+ 7742683264U, 7751069056U, 7759457408U, 7767849088U, 7776238208U,
+ 7784626816U, 7793014912U, 7801405312U, 7809792128U, 7818179968U,
+ 7826571136U, 7834957184U, 7843347328U, 7851732352U, 7860124544U,
+ 7868512384U, 7876902016U, 7885287808U, 7893679744U, 7902067072U,
+ 7910455936U, 7918844288U, 7927230848U, 7935622784U, 7944009344U,
+ 7952400256U, 7960786048U, 7969176704U, 7977565312U, 7985953408U,
+ 7994339968U, 8002730368U, 8011119488U, 8019508096U, 8027896192U,
+ 8036285056U, 8044674688U, 8053062272U, 8061448832U, 8069838464U,
+ 8078227328U, 8086616704U, 8095006592U, 8103393664U, 8111783552U,
+ 8120171392U, 8128560256U, 8136949376U, 8145336704U, 8153726848U,
+ 8162114944U, 8170503296U, 8178891904U, 8187280768U, 8195669632U,
+ 8204058496U, 8212444544U, 8220834176U, 8229222272U, 8237612672U,
+ 8246000768U, 8254389376U, 8262775168U, 8271167104U, 8279553664U,
+ 8287944064U, 8296333184U, 8304715136U, 8313108352U, 8321497984U,
+ 8329885568U, 8338274432U, 8346663296U, 8355052928U, 8363441536U,
+ 8371828352U, 8380217984U, 8388606592U, 8396996224U, 8405384576U,
+ 8413772672U, 8422161536U, 8430549376U, 8438939008U, 8447326592U,
+ 8455715456U, 8464104832U, 8472492928U, 8480882048U, 8489270656U,
+ 8497659776U, 8506045312U, 8514434944U, 8522823808U, 8531208832U,
+ 8539602304U, 8547990656U, 8556378752U, 8564768384U, 8573154176U,
+ 8581542784U, 8589933952U, 8598322816U, 8606705024U, 8615099264U,
+ 8623487872U, 8631876992U, 8640264064U, 8648653952U, 8657040256U,
+ 8665430656U, 8673820544U, 8682209152U, 8690592128U, 8698977152U,
+ 8707374464U, 8715763328U, 8724151424U, 8732540032U, 8740928384U,
+ 8749315712U, 8757704576U, 8766089344U, 8774480768U, 8782871936U,
+ 8791260032U, 8799645824U, 8808034432U, 8816426368U, 8824812928U,
+ 8833199488U, 8841591424U, 8849976448U, 8858366336U, 8866757248U,
+ 8875147136U, 8883532928U, 8891923328U, 8900306816U, 8908700288U,
+ 8917088384U, 8925478784U, 8933867392U, 8942250368U, 8950644608U,
+ 8959032704U, 8967420544U, 8975809664U, 8984197504U, 8992584064U,
+ 9000976256U, 9009362048U, 9017752448U, 9026141312U, 9034530688U,
+ 9042917504U, 9051307904U, 9059694208U, 9068084864U, 9076471424U,
+ 9084861824U, 9093250688U, 9101638528U, 9110027648U, 9118416512U,
+ 9126803584U, 9135188096U, 9143581312U, 9151969664U, 9160356224U,
+ 9168747136U, 9177134464U, 9185525632U, 9193910144U, 9202302848U,
+ 9210690688U, 9219079552U, 9227465344U, 9235854464U, 9244244864U,
+ 9252633472U, 9261021824U, 9269411456U, 9277799296U, 9286188928U,
+ 9294574208U, 9302965888U, 9311351936U, 9319740032U, 9328131968U,
+ 9336516736U, 9344907392U, 9353296768U, 9361685888U, 9370074752U,
+ 9378463616U, 9386849408U, 9395239808U, 9403629184U, 9412016512U,
+ 9420405376U, 9428795008U, 9437181568U, 9445570688U, 9453960832U,
+ 9462346624U, 9470738048U, 9479121536U, 9487515008U, 9495903616U,
+ 9504289664U, 9512678528U, 9521067904U, 9529456256U, 9537843584U,
+ 9546233728U, 9554621312U, 9563011456U, 9571398784U, 9579788672U,
+ 9588178304U, 9596567168U, 9604954496U, 9613343104U, 9621732992U,
+ 9630121856U, 9638508416U, 9646898816U, 9655283584U, 9663675776U,
+ 9672061312U, 9680449664U, 9688840064U, 9697230464U, 9705617536U,
+ 9714003584U, 9722393984U, 9730772608U, 9739172224U, 9747561088U,
+ 9755945344U, 9764338816U, 9772726144U, 9781116544U, 9789503872U,
+ 9797892992U, 9806282624U, 9814670464U, 9823056512U, 9831439232U,
+ 9839833984U, 9848224384U, 9856613504U, 9865000576U, 9873391232U,
+ 9881772416U, 9890162816U, 9898556288U, 9906940544U, 9915333248U,
+ 9923721088U, 9932108672U, 9940496512U, 9948888448U, 9957276544U,
+ 9965666176U, 9974048384U, 9982441088U, 9990830464U, 9999219584U,
+ 10007602816U, 10015996544U, 10024385152U, 10032774016U, 10041163648U,
+ 10049548928U, 10057940096U, 10066329472U, 10074717824U, 10083105152U,
+ 10091495296U, 10099878784U, 10108272256U, 10116660608U, 10125049216U,
+ 10133437312U, 10141825664U, 10150213504U, 10158601088U, 10166991232U,
+ 10175378816U, 10183766144U, 10192157312U, 10200545408U, 10208935552U,
+ 10217322112U, 10225712768U, 10234099328U, 10242489472U, 10250876032U,
+ 10259264896U, 10267656064U, 10276042624U, 10284429184U, 10292820352U,
+ 10301209472U, 10309598848U, 10317987712U, 10326375296U, 10334763392U,
+ 10343153536U, 10351541632U, 10359930752U, 10368318592U, 10376707456U,
+ 10385096576U, 10393484672U, 10401867136U, 10410262144U, 10418647424U,
+ 10427039104U, 10435425664U, 10443810176U, 10452203648U, 10460589952U,
+ 10468982144U, 10477369472U, 10485759104U, 10494147712U, 10502533504U,
+ 10510923392U, 10519313536U, 10527702656U, 10536091264U, 10544478592U,
+ 10552867712U, 10561255808U, 10569642368U, 10578032768U, 10586423168U,
+ 10594805632U, 10603200128U, 10611588992U, 10619976064U, 10628361344U,
+ 10636754048U, 10645143424U, 10653531776U, 10661920384U, 10670307968U,
+ 10678696832U, 10687086464U, 10695475072U, 10703863168U, 10712246144U,
+ 10720639616U, 10729026688U, 10737414784U, 10745806208U, 10754190976U,
+ 10762581376U, 10770971264U, 10779356288U, 10787747456U, 10796135552U,
+ 10804525184U, 10812915584U, 10821301888U, 10829692288U, 10838078336U,
+ 10846469248U, 10854858368U, 10863247232U, 10871631488U, 10880023424U,
+ 10888412032U, 10896799616U, 10905188992U, 10913574016U, 10921964672U,
+ 10930352768U, 10938742912U, 10947132544U, 10955518592U, 10963909504U,
+ 10972298368U, 10980687488U, 10989074816U, 10997462912U, 11005851776U,
+ 11014241152U, 11022627712U, 11031017344U, 11039403904U, 11047793024U,
+ 11056184704U, 11064570752U, 11072960896U, 11081343872U, 11089737856U,
+ 11098128256U, 11106514816U, 11114904448U, 11123293568U, 11131680128U,
+ 11140065152U, 11148458368U, 11156845696U, 11165236864U, 11173624192U,
+ 11182013824U, 11190402688U, 11198790784U, 11207179136U, 11215568768U,
+ 11223957376U, 11232345728U, 11240734592U, 11249122688U, 11257511296U,
+ 11265899648U, 11274285952U, 11282675584U, 11291065472U, 11299452544U,
+ 11307842432U, 11316231296U, 11324616832U, 11333009024U, 11341395584U,
+ 11349782656U, 11358172288U, 11366560384U, 11374950016U, 11383339648U,
+ 11391721856U, 11400117376U, 11408504192U, 11416893568U, 11425283456U,
+ 11433671552U, 11442061184U, 11450444672U, 11458837888U, 11467226752U,
+ 11475611776U, 11484003968U, 11492392064U, 11500780672U, 11509169024U,
+ 11517550976U, 11525944448U, 11534335616U, 11542724224U, 11551111808U,
+ 11559500672U, 11567890304U, 11576277376U, 11584667008U, 11593056128U,
+ 11601443456U, 11609830016U, 11618221952U, 11626607488U, 11634995072U,
+ 11643387776U, 11651775104U, 11660161664U, 11668552576U, 11676940928U,
+ 11685330304U, 11693718656U, 11702106496U, 11710496128U, 11718882688U,
+ 11727273088U, 11735660416U, 11744050048U, 11752437376U, 11760824704U,
+ 11769216128U, 11777604736U, 11785991296U, 11794381952U, 11802770048U,
+ 11811157888U, 11819548544U, 11827932544U, 11836324736U, 11844713344U,
+ 11853100928U, 11861486464U, 11869879936U, 11878268032U, 11886656896U,
+ 11895044992U, 11903433088U, 11911822976U, 11920210816U, 11928600448U,
+ 11936987264U, 11945375872U, 11953761152U, 11962151296U, 11970543488U,
+ 11978928512U, 11987320448U, 11995708288U, 12004095104U, 12012486272U,
+ 12020875136U, 12029255552U, 12037652096U, 12046039168U, 12054429568U,
+ 12062813824U, 12071206528U, 12079594624U, 12087983744U, 12096371072U,
+ 12104759936U, 12113147264U, 12121534592U, 12129924992U, 12138314624U,
+ 12146703232U, 12155091584U, 12163481216U, 12171864704U, 12180255872U,
+ 12188643968U, 12197034112U, 12205424512U, 12213811328U, 12222199424U,
+ 12230590336U, 12238977664U, 12247365248U, 12255755392U, 12264143488U,
+ 12272531584U, 12280920448U, 12289309568U, 12297694592U, 12306086528U,
+ 12314475392U, 12322865024U, 12331253632U, 12339640448U, 12348029312U,
+ 12356418944U, 12364805248U, 12373196672U, 12381580928U, 12389969024U,
+ 12398357632U, 12406750592U, 12415138432U, 12423527552U, 12431916416U,
+ 12440304512U, 12448692352U, 12457081216U, 12465467776U, 12473859968U,
+ 12482245504U, 12490636672U, 12499025536U, 12507411584U, 12515801728U,
+ 12524190592U, 12532577152U, 12540966272U, 12549354368U, 12557743232U,
+ 12566129536U, 12574523264U, 12582911872U, 12591299456U, 12599688064U,
+ 12608074624U, 12616463488U, 12624845696U, 12633239936U, 12641631616U,
+ 12650019968U, 12658407296U, 12666795136U, 12675183232U, 12683574656U,
+ 12691960192U, 12700350592U, 12708740224U, 12717128576U, 12725515904U,
+ 12733906816U, 12742295168U, 12750680192U, 12759071872U, 12767460736U,
+ 12775848832U, 12784236928U, 12792626816U, 12801014656U, 12809404288U,
+ 12817789312U, 12826181504U, 12834568832U, 12842954624U, 12851345792U,
+ 12859732352U, 12868122496U, 12876512128U, 12884901248U, 12893289088U,
+ 12901672832U, 12910067584U, 12918455168U, 12926842496U, 12935232896U,
+ 12943620736U, 12952009856U, 12960396928U, 12968786816U, 12977176192U,
+ 12985563776U, 12993951104U, 13002341504U, 13010730368U, 13019115392U,
+ 13027506304U, 13035895168U, 13044272512U, 13052673152U, 13061062528U,
+ 13069446272U, 13077838976U, 13086227072U, 13094613632U, 13103000192U,
+ 13111393664U, 13119782528U, 13128157568U, 13136559232U, 13144945024U,
+ 13153329536U, 13161724288U, 13170111872U, 13178502784U, 13186884736U,
+ 13195279744U, 13203667072U, 13212057472U, 13220445824U, 13228832128U,
+ 13237221248U, 13245610624U, 13254000512U, 13262388352U, 13270777472U,
+ 13279166336U, 13287553408U, 13295943296U, 13304331904U, 13312719488U,
+ 13321108096U, 13329494656U, 13337885824U, 13346274944U, 13354663808U,
+ 13363051136U, 13371439232U, 13379825024U, 13388210816U, 13396605056U,
+ 13404995456U, 13413380224U, 13421771392U, 13430159744U, 13438546048U,
+ 13446937216U, 13455326848U, 13463708288U, 13472103808U, 13480492672U,
+ 13488875648U, 13497269888U, 13505657728U, 13514045312U, 13522435712U,
+ 13530824576U, 13539210112U, 13547599232U, 13555989376U, 13564379008U,
+ 13572766336U, 13581154432U, 13589544832U, 13597932928U, 13606320512U,
+ 13614710656U, 13623097472U, 13631477632U, 13639874944U, 13648264064U,
+ 13656652928U, 13665041792U, 13673430656U, 13681818496U, 13690207616U,
+ 13698595712U, 13706982272U, 13715373184U, 13723762048U, 13732150144U,
+ 13740536704U, 13748926592U, 13757316224U, 13765700992U, 13774090112U,
+ 13782477952U, 13790869376U, 13799259008U, 13807647872U, 13816036736U,
+ 13824425344U, 13832814208U, 13841202304U, 13849591424U, 13857978752U,
+ 13866368896U, 13874754688U, 13883145344U, 13891533184U, 13899919232U,
+ 13908311168U, 13916692096U, 13925085056U, 13933473152U, 13941866368U,
+ 13950253696U, 13958643584U, 13967032192U, 13975417216U, 13983807616U,
+ 13992197504U, 14000582272U, 14008973696U, 14017363072U, 14025752192U,
+ 14034137984U, 14042528384U, 14050918016U, 14059301504U, 14067691648U,
+ 14076083584U, 14084470144U, 14092852352U, 14101249664U, 14109635968U,
+ 14118024832U, 14126407552U, 14134804352U, 14143188608U, 14151577984U,
+ 14159968384U, 14168357248U, 14176741504U, 14185127296U, 14193521024U,
+ 14201911424U, 14210301824U, 14218685056U, 14227067264U, 14235467392U,
+ 14243855488U, 14252243072U, 14260630144U, 14269021568U, 14277409408U,
+ 14285799296U, 14294187904U, 14302571392U, 14310961792U, 14319353728U,
+ 14327738752U, 14336130944U, 14344518784U, 14352906368U, 14361296512U,
+ 14369685376U, 14378071424U, 14386462592U, 14394848128U, 14403230848U,
+ 14411627392U, 14420013952U, 14428402304U, 14436793472U, 14445181568U,
+ 14453569664U, 14461959808U, 14470347904U, 14478737024U, 14487122816U,
+ 14495511424U, 14503901824U, 14512291712U, 14520677504U, 14529064832U,
+ 14537456768U, 14545845632U, 14554234496U, 14562618496U, 14571011456U,
+ 14579398784U, 14587789184U, 14596172672U, 14604564608U, 14612953984U,
+ 14621341312U, 14629724288U, 14638120832U, 14646503296U, 14654897536U,
+ 14663284864U, 14671675264U, 14680061056U, 14688447616U, 14696835968U,
+ 14705228416U, 14713616768U, 14722003328U, 14730392192U, 14738784128U,
+ 14747172736U, 14755561088U, 14763947648U, 14772336512U, 14780725376U,
+ 14789110144U, 14797499776U, 14805892736U, 14814276992U, 14822670208U,
+ 14831056256U, 14839444352U, 14847836032U, 14856222848U, 14864612992U,
+ 14872997504U, 14881388672U, 14889775744U, 14898165376U, 14906553472U,
+ 14914944896U, 14923329664U, 14931721856U, 14940109696U, 14948497024U,
+ 14956887424U, 14965276544U, 14973663616U, 14982053248U, 14990439808U,
+ 14998830976U, 15007216768U, 15015605888U, 15023995264U, 15032385152U,
+ 15040768384U, 15049154944U, 15057549184U, 15065939072U, 15074328448U,
+ 15082715008U, 15091104128U, 15099493504U, 15107879296U, 15116269184U,
+ 15124659584U, 15133042304U, 15141431936U, 15149824384U, 15158214272U,
+ 15166602368U, 15174991232U, 15183378304U, 15191760512U, 15200154496U,
+ 15208542592U, 15216931712U, 15225323392U, 15233708416U, 15242098048U,
+ 15250489216U, 15258875264U, 15267265408U, 15275654528U, 15284043136U,
+ 15292431488U, 15300819584U, 15309208192U, 15317596544U, 15325986176U,
+ 15334374784U, 15342763648U, 15351151744U, 15359540608U, 15367929728U,
+ 15376318336U, 15384706432U, 15393092992U, 15401481856U, 15409869952U,
+ 15418258816U, 15426649984U, 15435037568U, 15443425664U, 15451815296U,
+ 15460203392U, 15468589184U, 15476979328U, 15485369216U, 15493755776U,
+ 15502146944U, 15510534272U, 15518924416U, 15527311232U, 15535699072U,
+ 15544089472U, 15552478336U, 15560866688U, 15569254528U, 15577642624U,
+ 15586031488U, 15594419072U, 15602809472U, 15611199104U, 15619586432U,
+ 15627975296U, 15636364928U, 15644753792U, 15653141888U, 15661529216U,
+ 15669918848U, 15678305152U, 15686696576U, 15695083136U, 15703474048U,
+ 15711861632U, 15720251264U, 15728636288U, 15737027456U, 15745417088U,
+ 15753804928U, 15762194048U, 15770582656U, 15778971008U, 15787358336U,
+ 15795747712U, 15804132224U, 15812523392U, 15820909696U, 15829300096U,
+ 15837691264U, 15846071936U, 15854466944U, 15862855808U, 15871244672U,
+ 15879634816U, 15888020608U, 15896409728U, 15904799104U, 15913185152U,
+ 15921577088U, 15929966464U, 15938354816U, 15946743424U, 15955129472U,
+ 15963519872U, 15971907968U, 15980296064U, 15988684928U, 15997073024U,
+ 16005460864U, 16013851264U, 16022241152U, 16030629248U, 16039012736U,
+ 16047406976U, 16055794816U, 16064181376U, 16072571264U, 16080957824U,
+ 16089346688U, 16097737856U, 16106125184U, 16114514816U, 16122904192U,
+ 16131292544U, 16139678848U, 16148066944U, 16156453504U, 16164839552U,
+ 16173236096U, 16181623424U, 16190012032U, 16198401152U, 16206790528U,
+ 16215177344U, 16223567744U, 16231956352U, 16240344704U, 16248731008U,
+ 16257117824U, 16265504384U, 16273898624U, 16282281856U, 16290668672U,
+ 16299064192U, 16307449216U, 16315842176U, 16324230016U, 16332613504U,
+ 16341006464U, 16349394304U, 16357783168U, 16366172288U, 16374561664U,
+ 16382951296U, 16391337856U, 16399726208U, 16408116352U, 16416505472U,
+ 16424892032U, 16433282176U, 16441668224U, 16450058624U, 16458448768U,
+ 16466836864U, 16475224448U, 16483613056U, 16492001408U, 16500391808U,
+ 16508779648U, 16517166976U, 16525555328U, 16533944192U, 16542330752U,
+ 16550719616U, 16559110528U, 16567497088U, 16575888512U, 16584274816U,
+ 16592665472U, 16601051008U, 16609442944U, 16617832064U, 16626218624U,
+ 16634607488U, 16642996096U, 16651385728U, 16659773824U, 16668163712U,
+ 16676552576U, 16684938112U, 16693328768U, 16701718144U, 16710095488U,
+ 16718492288U, 16726883968U, 16735272832U, 16743661184U, 16752049792U,
+ 16760436608U, 16768827008U, 16777214336U, 16785599104U, 16793992832U,
+ 16802381696U, 16810768768U, 16819151744U, 16827542656U, 16835934848U,
+ 16844323712U, 16852711552U, 16861101952U, 16869489536U, 16877876864U,
+ 16886265728U, 16894653056U, 16903044736U, 16911431296U, 16919821696U,
+ 16928207488U, 16936592768U, 16944987776U, 16953375616U, 16961763968U,
+ 16970152832U, 16978540928U, 16986929536U, 16995319168U, 17003704448U,
+ 17012096896U, 17020481152U, 17028870784U, 17037262208U, 17045649536U,
+ 17054039936U, 17062426496U, 17070814336U, 17079205504U, 17087592064U,
+ 17095978112U, 17104369024U, 17112759424U, 17121147776U, 17129536384U,
+ 17137926016U, 17146314368U, 17154700928U, 17163089792U, 17171480192U,
+ 17179864192U, 17188256896U, 17196644992U, 17205033856U, 17213423488U,
+ 17221811072U, 17230198912U, 17238588032U, 17246976896U, 17255360384U,
+ 17263754624U, 17272143232U, 17280530048U, 17288918912U, 17297309312U,
+ 17305696384U, 17314085504U, 17322475136U, 17330863744U, 17339252096U,
+ 17347640192U, 17356026496U, 17364413824U, 17372796544U, 17381190016U,
+ 17389583488U, 17397972608U, 17406360704U, 17414748544U, 17423135872U,
+ 17431527296U, 17439915904U, 17448303232U, 17456691584U, 17465081728U,
+ 17473468288U, 17481857408U, 17490247552U, 17498635904U, 17507022464U,
+ 17515409024U, 17523801728U, 17532189824U, 17540577664U, 17548966016U,
+ 17557353344U, 17565741184U, 17574131584U, 17582519168U, 17590907008U,
+ 17599296128U, 17607687808U, 17616076672U, 17624455808U, 17632852352U,
+ 17641238656U, 17649630848U, 17658018944U, 17666403968U, 17674794112U,
+ 17683178368U, 17691573376U, 17699962496U, 17708350592U, 17716739968U,
+ 17725126528U, 17733517184U, 17741898112U, 17750293888U, 17758673024U,
+ 17767070336U, 17775458432U, 17783848832U, 17792236928U, 17800625536U,
+ 17809012352U, 17817402752U, 17825785984U, 17834178944U, 17842563968U,
+ 17850955648U, 17859344512U, 17867732864U, 17876119424U, 17884511872U,
+ 17892900224U, 17901287296U, 17909677696U, 17918058112U, 17926451072U,
+ 17934843776U, 17943230848U, 17951609216U, 17960008576U, 17968397696U,
+ 17976784256U, 17985175424U, 17993564032U, 18001952128U, 18010339712U,
+ 18018728576U, 18027116672U, 18035503232U, 18043894144U, 18052283264U,
+ 18060672128U, 18069056384U, 18077449856U, 18085837184U, 18094225792U,
+ 18102613376U, 18111004544U, 18119388544U, 18127781248U, 18136170368U,
+ 18144558976U, 18152947328U, 18161336192U, 18169724288U, 18178108544U,
+ 18186498944U, 18194886784U, 18203275648U, 18211666048U, 18220048768U,
+ 18228444544U, 18236833408U, 18245220736U
};
@@ -478,335 +478,335 @@ static const uint64_t dag_sizes[2048] = {
// Sow[i*HashBytes]; j++]]]][[2]][[1]]
const uint64_t cache_sizes[2048] = {
- 16776896U, 16907456U, 17039296U, 17170112U, 17301056U, 17432512U, 17563072U,
- 17693888U, 17824192U, 17955904U, 18087488U, 18218176U, 18349504U, 18481088U,
- 18611392U, 18742336U, 18874304U, 19004224U, 19135936U, 19267264U, 19398208U,
- 19529408U, 19660096U, 19791424U, 19922752U, 20053952U, 20184896U, 20315968U,
- 20446912U, 20576576U, 20709184U, 20840384U, 20971072U, 21102272U, 21233216U,
- 21364544U, 21494848U, 21626816U, 21757376U, 21887552U, 22019392U, 22151104U,
- 22281536U, 22412224U, 22543936U, 22675264U, 22806464U, 22935872U, 23068096U,
- 23198272U, 23330752U, 23459008U, 23592512U, 23723968U, 23854912U, 23986112U,
- 24116672U, 24247616U, 24378688U, 24509504U, 24640832U, 24772544U, 24903488U,
- 25034432U, 25165376U, 25296704U, 25427392U, 25558592U, 25690048U, 25820096U,
- 25951936U, 26081728U, 26214208U, 26345024U, 26476096U, 26606656U, 26737472U,
- 26869184U, 26998208U, 27131584U, 27262528U, 27393728U, 27523904U, 27655744U,
- 27786688U, 27917888U, 28049344U, 28179904U, 28311488U, 28441792U, 28573504U,
- 28700864U, 28835648U, 28966208U, 29096768U, 29228608U, 29359808U, 29490752U,
- 29621824U, 29752256U, 29882816U, 30014912U, 30144448U, 30273728U, 30406976U,
- 30538432U, 30670784U, 30799936U, 30932672U, 31063744U, 31195072U, 31325248U,
- 31456192U, 31588288U, 31719232U, 31850432U, 31981504U, 32110784U, 32243392U,
- 32372672U, 32505664U, 32636608U, 32767808U, 32897344U, 33029824U, 33160768U,
- 33289664U, 33423296U, 33554368U, 33683648U, 33816512U, 33947456U, 34076992U,
- 34208704U, 34340032U, 34471744U, 34600256U, 34734016U, 34864576U, 34993984U,
- 35127104U, 35258176U, 35386688U, 35518528U, 35650624U, 35782336U, 35910976U,
- 36044608U, 36175808U, 36305728U, 36436672U, 36568384U, 36699968U, 36830656U,
- 36961984U, 37093312U, 37223488U, 37355072U, 37486528U, 37617472U, 37747904U,
- 37879232U, 38009792U, 38141888U, 38272448U, 38403392U, 38535104U, 38660672U,
- 38795584U, 38925632U, 39059264U, 39190336U, 39320768U, 39452096U, 39581632U,
- 39713984U, 39844928U, 39974848U, 40107968U, 40238144U, 40367168U, 40500032U,
- 40631744U, 40762816U, 40894144U, 41023552U, 41155904U, 41286208U, 41418304U,
- 41547712U, 41680448U, 41811904U, 41942848U, 42073792U, 42204992U, 42334912U,
- 42467008U, 42597824U, 42729152U, 42860096U, 42991552U, 43122368U, 43253696U,
- 43382848U, 43515712U, 43646912U, 43777088U, 43907648U, 44039104U, 44170432U,
- 44302144U, 44433344U, 44564288U, 44694976U, 44825152U, 44956864U, 45088448U,
- 45219008U, 45350464U, 45481024U, 45612608U, 45744064U, 45874496U, 46006208U,
- 46136768U, 46267712U, 46399424U, 46529344U, 46660672U, 46791488U, 46923328U,
- 47053504U, 47185856U, 47316928U, 47447872U, 47579072U, 47710144U, 47839936U,
- 47971648U, 48103232U, 48234176U, 48365248U, 48496192U, 48627136U, 48757312U,
- 48889664U, 49020736U, 49149248U, 49283008U, 49413824U, 49545152U, 49675712U,
- 49807168U, 49938368U, 50069056U, 50200256U, 50331584U, 50462656U, 50593472U,
- 50724032U, 50853952U, 50986048U, 51117632U, 51248576U, 51379904U, 51510848U,
- 51641792U, 51773248U, 51903296U, 52035136U, 52164032U, 52297664U, 52427968U,
- 52557376U, 52690112U, 52821952U, 52952896U, 53081536U, 53213504U, 53344576U,
- 53475776U, 53608384U, 53738816U, 53870528U, 54000832U, 54131776U, 54263744U,
- 54394688U, 54525248U, 54655936U, 54787904U, 54918592U, 55049152U, 55181248U,
- 55312064U, 55442752U, 55574336U, 55705024U, 55836224U, 55967168U, 56097856U,
- 56228672U, 56358592U, 56490176U, 56621888U, 56753728U, 56884928U, 57015488U,
- 57146816U, 57278272U, 57409216U, 57540416U, 57671104U, 57802432U, 57933632U,
- 58064576U, 58195264U, 58326976U, 58457408U, 58588864U, 58720192U, 58849984U,
- 58981696U, 59113024U, 59243456U, 59375552U, 59506624U, 59637568U, 59768512U,
- 59897792U, 60030016U, 60161984U, 60293056U, 60423872U, 60554432U, 60683968U,
- 60817216U, 60948032U, 61079488U, 61209664U, 61341376U, 61471936U, 61602752U,
- 61733696U, 61865792U, 61996736U, 62127808U, 62259136U, 62389568U, 62520512U,
- 62651584U, 62781632U, 62910784U, 63045056U, 63176128U, 63307072U, 63438656U,
- 63569216U, 63700928U, 63831616U, 63960896U, 64093888U, 64225088U, 64355392U,
- 64486976U, 64617664U, 64748608U, 64879424U, 65009216U, 65142464U, 65273792U,
- 65402816U, 65535424U, 65666752U, 65797696U, 65927744U, 66060224U, 66191296U,
- 66321344U, 66453056U, 66584384U, 66715328U, 66846656U, 66977728U, 67108672U,
- 67239104U, 67370432U, 67501888U, 67631296U, 67763776U, 67895104U, 68026304U,
- 68157248U, 68287936U, 68419264U, 68548288U, 68681408U, 68811968U, 68942912U,
- 69074624U, 69205568U, 69337024U, 69467584U, 69599168U, 69729472U, 69861184U,
- 69989824U, 70122944U, 70253888U, 70385344U, 70515904U, 70647232U, 70778816U,
- 70907968U, 71040832U, 71171648U, 71303104U, 71432512U, 71564992U, 71695168U,
- 71826368U, 71958464U, 72089536U, 72219712U, 72350144U, 72482624U, 72613568U,
- 72744512U, 72875584U, 73006144U, 73138112U, 73268672U, 73400128U, 73530944U,
- 73662272U, 73793344U, 73924544U, 74055104U, 74185792U, 74316992U, 74448832U,
- 74579392U, 74710976U, 74841664U, 74972864U, 75102784U, 75233344U, 75364544U,
- 75497024U, 75627584U, 75759296U, 75890624U, 76021696U, 76152256U, 76283072U,
- 76414144U, 76545856U, 76676672U, 76806976U, 76937792U, 77070016U, 77200832U,
- 77331392U, 77462464U, 77593664U, 77725376U, 77856448U, 77987776U, 78118336U,
- 78249664U, 78380992U, 78511424U, 78642496U, 78773056U, 78905152U, 79033664U,
- 79166656U, 79297472U, 79429568U, 79560512U, 79690816U, 79822784U, 79953472U,
- 80084672U, 80214208U, 80346944U, 80477632U, 80608576U, 80740288U, 80870848U,
- 81002048U, 81133504U, 81264448U, 81395648U, 81525952U, 81657536U, 81786304U,
- 81919808U, 82050112U, 82181312U, 82311616U, 82443968U, 82573376U, 82705984U,
- 82835776U, 82967744U, 83096768U, 83230528U, 83359552U, 83491264U, 83622464U,
- 83753536U, 83886016U, 84015296U, 84147776U, 84277184U, 84409792U, 84540608U,
- 84672064U, 84803008U, 84934336U, 85065152U, 85193792U, 85326784U, 85458496U,
- 85589312U, 85721024U, 85851968U, 85982656U, 86112448U, 86244416U, 86370112U,
- 86506688U, 86637632U, 86769344U, 86900672U, 87031744U, 87162304U, 87293632U,
- 87424576U, 87555392U, 87687104U, 87816896U, 87947968U, 88079168U, 88211264U,
- 88341824U, 88473152U, 88603712U, 88735424U, 88862912U, 88996672U, 89128384U,
- 89259712U, 89390272U, 89521984U, 89652544U, 89783872U, 89914816U, 90045376U,
- 90177088U, 90307904U, 90438848U, 90569152U, 90700096U, 90832832U, 90963776U,
- 91093696U, 91223744U, 91356992U, 91486784U, 91618496U, 91749824U, 91880384U,
- 92012224U, 92143552U, 92273344U, 92405696U, 92536768U, 92666432U, 92798912U,
- 92926016U, 93060544U, 93192128U, 93322816U, 93453632U, 93583936U, 93715136U,
- 93845056U, 93977792U, 94109504U, 94240448U, 94371776U, 94501184U, 94632896U,
- 94764224U, 94895552U, 95023424U, 95158208U, 95287744U, 95420224U, 95550016U,
- 95681216U, 95811904U, 95943872U, 96075328U, 96203584U, 96337856U, 96468544U,
- 96599744U, 96731072U, 96860992U, 96992576U, 97124288U, 97254848U, 97385536U,
- 97517248U, 97647808U, 97779392U, 97910464U, 98041408U, 98172608U, 98303168U,
- 98434496U, 98565568U, 98696768U, 98827328U, 98958784U, 99089728U, 99220928U,
- 99352384U, 99482816U, 99614272U, 99745472U, 99876416U, 100007104U,
- 100138048U, 100267072U, 100401088U, 100529984U, 100662592U, 100791872U,
- 100925248U, 101056064U, 101187392U, 101317952U, 101449408U, 101580608U,
- 101711296U, 101841728U, 101973824U, 102104896U, 102235712U, 102366016U,
- 102498112U, 102628672U, 102760384U, 102890432U, 103021888U, 103153472U,
- 103284032U, 103415744U, 103545152U, 103677248U, 103808576U, 103939648U,
- 104070976U, 104201792U, 104332736U, 104462528U, 104594752U, 104725952U,
- 104854592U, 104988608U, 105118912U, 105247808U, 105381184U, 105511232U,
- 105643072U, 105774784U, 105903296U, 106037056U, 106167872U, 106298944U,
- 106429504U, 106561472U, 106691392U, 106822592U, 106954304U, 107085376U,
- 107216576U, 107346368U, 107478464U, 107609792U, 107739712U, 107872192U,
- 108003136U, 108131392U, 108265408U, 108396224U, 108527168U, 108657344U,
- 108789568U, 108920384U, 109049792U, 109182272U, 109312576U, 109444928U,
- 109572928U, 109706944U, 109837888U, 109969088U, 110099648U, 110230976U,
- 110362432U, 110492992U, 110624704U, 110755264U, 110886208U, 111017408U,
- 111148864U, 111279296U, 111410752U, 111541952U, 111673024U, 111803456U,
- 111933632U, 112066496U, 112196416U, 112328512U, 112457792U, 112590784U,
- 112715968U, 112852672U, 112983616U, 113114944U, 113244224U, 113376448U,
- 113505472U, 113639104U, 113770304U, 113901376U, 114031552U, 114163264U,
- 114294592U, 114425536U, 114556864U, 114687424U, 114818624U, 114948544U,
- 115080512U, 115212224U, 115343296U, 115473472U, 115605184U, 115736128U,
- 115867072U, 115997248U, 116128576U, 116260288U, 116391488U, 116522944U,
- 116652992U, 116784704U, 116915648U, 117046208U, 117178304U, 117308608U,
- 117440192U, 117569728U, 117701824U, 117833024U, 117964096U, 118094656U,
- 118225984U, 118357312U, 118489024U, 118617536U, 118749632U, 118882112U,
- 119012416U, 119144384U, 119275328U, 119406016U, 119537344U, 119668672U,
- 119798464U, 119928896U, 120061376U, 120192832U, 120321728U, 120454336U,
- 120584512U, 120716608U, 120848192U, 120979136U, 121109056U, 121241408U,
- 121372352U, 121502912U, 121634752U, 121764416U, 121895744U, 122027072U,
- 122157632U, 122289088U, 122421184U, 122550592U, 122682944U, 122813888U,
- 122945344U, 123075776U, 123207488U, 123338048U, 123468736U, 123600704U,
- 123731264U, 123861952U, 123993664U, 124124608U, 124256192U, 124386368U,
- 124518208U, 124649024U, 124778048U, 124911296U, 125041088U, 125173696U,
- 125303744U, 125432896U, 125566912U, 125696576U, 125829056U, 125958592U,
- 126090304U, 126221248U, 126352832U, 126483776U, 126615232U, 126746432U,
- 126876608U, 127008704U, 127139392U, 127270336U, 127401152U, 127532224U,
- 127663552U, 127794752U, 127925696U, 128055232U, 128188096U, 128319424U,
- 128449856U, 128581312U, 128712256U, 128843584U, 128973632U, 129103808U,
- 129236288U, 129365696U, 129498944U, 129629888U, 129760832U, 129892288U,
- 130023104U, 130154048U, 130283968U, 130416448U, 130547008U, 130678336U,
- 130807616U, 130939456U, 131071552U, 131202112U, 131331776U, 131464384U,
- 131594048U, 131727296U, 131858368U, 131987392U, 132120256U, 132250816U,
- 132382528U, 132513728U, 132644672U, 132774976U, 132905792U, 133038016U,
- 133168832U, 133299392U, 133429312U, 133562048U, 133692992U, 133823296U,
- 133954624U, 134086336U, 134217152U, 134348608U, 134479808U, 134607296U,
- 134741056U, 134872384U, 135002944U, 135134144U, 135265472U, 135396544U,
- 135527872U, 135659072U, 135787712U, 135921472U, 136052416U, 136182848U,
- 136313792U, 136444864U, 136576448U, 136707904U, 136837952U, 136970048U,
- 137099584U, 137232064U, 137363392U, 137494208U, 137625536U, 137755712U,
- 137887424U, 138018368U, 138149824U, 138280256U, 138411584U, 138539584U,
- 138672832U, 138804928U, 138936128U, 139066688U, 139196864U, 139328704U,
- 139460032U, 139590208U, 139721024U, 139852864U, 139984576U, 140115776U,
- 140245696U, 140376512U, 140508352U, 140640064U, 140769856U, 140902336U,
- 141032768U, 141162688U, 141294016U, 141426496U, 141556544U, 141687488U,
- 141819584U, 141949888U, 142080448U, 142212544U, 142342336U, 142474432U,
- 142606144U, 142736192U, 142868288U, 142997824U, 143129408U, 143258944U,
- 143392448U, 143523136U, 143653696U, 143785024U, 143916992U, 144045632U,
- 144177856U, 144309184U, 144440768U, 144570688U, 144701888U, 144832448U,
- 144965056U, 145096384U, 145227584U, 145358656U, 145489856U, 145620928U,
- 145751488U, 145883072U, 146011456U, 146144704U, 146275264U, 146407232U,
- 146538176U, 146668736U, 146800448U, 146931392U, 147062336U, 147193664U,
- 147324224U, 147455936U, 147586624U, 147717056U, 147848768U, 147979456U,
- 148110784U, 148242368U, 148373312U, 148503232U, 148635584U, 148766144U,
- 148897088U, 149028416U, 149159488U, 149290688U, 149420224U, 149551552U,
- 149683136U, 149814976U, 149943616U, 150076352U, 150208064U, 150338624U,
- 150470464U, 150600256U, 150732224U, 150862784U, 150993088U, 151125952U,
- 151254976U, 151388096U, 151519168U, 151649728U, 151778752U, 151911104U,
- 152042944U, 152174144U, 152304704U, 152435648U, 152567488U, 152698816U,
- 152828992U, 152960576U, 153091648U, 153222976U, 153353792U, 153484096U,
- 153616192U, 153747008U, 153878336U, 154008256U, 154139968U, 154270912U,
- 154402624U, 154533824U, 154663616U, 154795712U, 154926272U, 155057984U,
- 155188928U, 155319872U, 155450816U, 155580608U, 155712064U, 155843392U,
- 155971136U, 156106688U, 156237376U, 156367424U, 156499264U, 156630976U,
- 156761536U, 156892352U, 157024064U, 157155008U, 157284416U, 157415872U,
- 157545536U, 157677248U, 157810496U, 157938112U, 158071744U, 158203328U,
- 158334656U, 158464832U, 158596288U, 158727616U, 158858048U, 158988992U,
- 159121216U, 159252416U, 159381568U, 159513152U, 159645632U, 159776192U,
- 159906496U, 160038464U, 160169536U, 160300352U, 160430656U, 160563008U,
- 160693952U, 160822208U, 160956352U, 161086784U, 161217344U, 161349184U,
- 161480512U, 161611456U, 161742272U, 161873216U, 162002752U, 162135872U,
- 162266432U, 162397888U, 162529216U, 162660032U, 162790976U, 162922048U,
- 163052096U, 163184576U, 163314752U, 163446592U, 163577408U, 163707968U,
- 163839296U, 163969984U, 164100928U, 164233024U, 164364224U, 164494912U,
- 164625856U, 164756672U, 164887616U, 165019072U, 165150016U, 165280064U,
- 165412672U, 165543104U, 165674944U, 165805888U, 165936832U, 166067648U,
- 166198336U, 166330048U, 166461248U, 166591552U, 166722496U, 166854208U,
- 166985408U, 167116736U, 167246656U, 167378368U, 167508416U, 167641024U,
- 167771584U, 167903168U, 168034112U, 168164032U, 168295744U, 168427456U,
- 168557632U, 168688448U, 168819136U, 168951616U, 169082176U, 169213504U,
- 169344832U, 169475648U, 169605952U, 169738048U, 169866304U, 169999552U,
- 170131264U, 170262464U, 170393536U, 170524352U, 170655424U, 170782016U,
- 170917696U, 171048896U, 171179072U, 171310784U, 171439936U, 171573184U,
- 171702976U, 171835072U, 171966272U, 172097216U, 172228288U, 172359232U,
- 172489664U, 172621376U, 172747712U, 172883264U, 173014208U, 173144512U,
- 173275072U, 173407424U, 173539136U, 173669696U, 173800768U, 173931712U,
- 174063424U, 174193472U, 174325696U, 174455744U, 174586816U, 174718912U,
- 174849728U, 174977728U, 175109696U, 175242688U, 175374272U, 175504832U,
- 175636288U, 175765696U, 175898432U, 176028992U, 176159936U, 176291264U,
- 176422592U, 176552512U, 176684864U, 176815424U, 176946496U, 177076544U,
- 177209152U, 177340096U, 177470528U, 177600704U, 177731648U, 177864256U,
- 177994816U, 178126528U, 178257472U, 178387648U, 178518464U, 178650176U,
- 178781888U, 178912064U, 179044288U, 179174848U, 179305024U, 179436736U,
- 179568448U, 179698496U, 179830208U, 179960512U, 180092608U, 180223808U,
- 180354752U, 180485696U, 180617152U, 180748096U, 180877504U, 181009984U,
- 181139264U, 181272512U, 181402688U, 181532608U, 181663168U, 181795136U,
- 181926592U, 182057536U, 182190016U, 182320192U, 182451904U, 182582336U,
- 182713792U, 182843072U, 182976064U, 183107264U, 183237056U, 183368384U,
- 183494848U, 183631424U, 183762752U, 183893824U, 184024768U, 184154816U,
- 184286656U, 184417984U, 184548928U, 184680128U, 184810816U, 184941248U,
- 185072704U, 185203904U, 185335616U, 185465408U, 185596352U, 185727296U,
- 185859904U, 185989696U, 186121664U, 186252992U, 186383552U, 186514112U,
- 186645952U, 186777152U, 186907328U, 187037504U, 187170112U, 187301824U,
- 187429184U, 187562048U, 187693504U, 187825472U, 187957184U, 188087104U,
- 188218304U, 188349376U, 188481344U, 188609728U, 188743616U, 188874304U,
- 189005248U, 189136448U, 189265088U, 189396544U, 189528128U, 189660992U,
- 189791936U, 189923264U, 190054208U, 190182848U, 190315072U, 190447424U,
- 190577984U, 190709312U, 190840768U, 190971328U, 191102656U, 191233472U,
- 191364032U, 191495872U, 191626816U, 191758016U, 191888192U, 192020288U,
- 192148928U, 192282176U, 192413504U, 192542528U, 192674752U, 192805952U,
- 192937792U, 193068608U, 193198912U, 193330496U, 193462208U, 193592384U,
- 193723456U, 193854272U, 193985984U, 194116672U, 194247232U, 194379712U,
- 194508352U, 194641856U, 194772544U, 194900672U, 195035072U, 195166016U,
- 195296704U, 195428032U, 195558592U, 195690304U, 195818176U, 195952576U,
- 196083392U, 196214336U, 196345792U, 196476736U, 196607552U, 196739008U,
- 196869952U, 197000768U, 197130688U, 197262784U, 197394368U, 197523904U,
- 197656384U, 197787584U, 197916608U, 198049472U, 198180544U, 198310208U,
- 198442432U, 198573632U, 198705088U, 198834368U, 198967232U, 199097792U,
- 199228352U, 199360192U, 199491392U, 199621696U, 199751744U, 199883968U,
- 200014016U, 200146624U, 200276672U, 200408128U, 200540096U, 200671168U,
- 200801984U, 200933312U, 201062464U, 201194944U, 201326144U, 201457472U,
- 201588544U, 201719744U, 201850816U, 201981632U, 202111552U, 202244032U,
- 202374464U, 202505152U, 202636352U, 202767808U, 202898368U, 203030336U,
- 203159872U, 203292608U, 203423296U, 203553472U, 203685824U, 203816896U,
- 203947712U, 204078272U, 204208192U, 204341056U, 204472256U, 204603328U,
- 204733888U, 204864448U, 204996544U, 205125568U, 205258304U, 205388864U,
- 205517632U, 205650112U, 205782208U, 205913536U, 206044736U, 206176192U,
- 206307008U, 206434496U, 206569024U, 206700224U, 206831168U, 206961856U,
- 207093056U, 207223616U, 207355328U, 207486784U, 207616832U, 207749056U,
- 207879104U, 208010048U, 208141888U, 208273216U, 208404032U, 208534336U,
- 208666048U, 208796864U, 208927424U, 209059264U, 209189824U, 209321792U,
- 209451584U, 209582656U, 209715136U, 209845568U, 209976896U, 210106432U,
- 210239296U, 210370112U, 210501568U, 210630976U, 210763712U, 210894272U,
- 211024832U, 211156672U, 211287616U, 211418176U, 211549376U, 211679296U,
- 211812032U, 211942592U, 212074432U, 212204864U, 212334016U, 212467648U,
- 212597824U, 212727616U, 212860352U, 212991424U, 213120832U, 213253952U,
- 213385024U, 213515584U, 213645632U, 213777728U, 213909184U, 214040128U,
- 214170688U, 214302656U, 214433728U, 214564544U, 214695232U, 214826048U,
- 214956992U, 215089088U, 215219776U, 215350592U, 215482304U, 215613248U,
- 215743552U, 215874752U, 216005312U, 216137024U, 216267328U, 216399296U,
- 216530752U, 216661696U, 216790592U, 216923968U, 217054528U, 217183168U,
- 217316672U, 217448128U, 217579072U, 217709504U, 217838912U, 217972672U,
- 218102848U, 218233024U, 218364736U, 218496832U, 218627776U, 218759104U,
- 218888896U, 219021248U, 219151936U, 219281728U, 219413056U, 219545024U,
- 219675968U, 219807296U, 219938624U, 220069312U, 220200128U, 220331456U,
- 220461632U, 220592704U, 220725184U, 220855744U, 220987072U, 221117888U,
- 221249216U, 221378368U, 221510336U, 221642048U, 221772736U, 221904832U,
- 222031808U, 222166976U, 222297536U, 222428992U, 222559936U, 222690368U,
- 222820672U, 222953152U, 223083968U, 223213376U, 223345984U, 223476928U,
- 223608512U, 223738688U, 223869376U, 224001472U, 224132672U, 224262848U,
- 224394944U, 224524864U, 224657344U, 224788288U, 224919488U, 225050432U,
- 225181504U, 225312704U, 225443776U, 225574592U, 225704768U, 225834176U,
- 225966784U, 226097216U, 226229824U, 226360384U, 226491712U, 226623424U,
- 226754368U, 226885312U, 227015104U, 227147456U, 227278528U, 227409472U,
- 227539904U, 227669696U, 227802944U, 227932352U, 228065216U, 228196288U,
- 228326464U, 228457792U, 228588736U, 228720064U, 228850112U, 228981056U,
- 229113152U, 229243328U, 229375936U, 229505344U, 229636928U, 229769152U,
- 229894976U, 230030272U, 230162368U, 230292416U, 230424512U, 230553152U,
- 230684864U, 230816704U, 230948416U, 231079616U, 231210944U, 231342016U,
- 231472448U, 231603776U, 231733952U, 231866176U, 231996736U, 232127296U,
- 232259392U, 232388672U, 232521664U, 232652608U, 232782272U, 232914496U,
- 233043904U, 233175616U, 233306816U, 233438528U, 233569984U, 233699776U,
- 233830592U, 233962688U, 234092224U, 234221888U, 234353984U, 234485312U,
- 234618304U, 234749888U, 234880832U, 235011776U, 235142464U, 235274048U,
- 235403456U, 235535936U, 235667392U, 235797568U, 235928768U, 236057152U,
- 236190272U, 236322752U, 236453312U, 236583616U, 236715712U, 236846528U,
- 236976448U, 237108544U, 237239104U, 237371072U, 237501632U, 237630784U,
- 237764416U, 237895232U, 238026688U, 238157632U, 238286912U, 238419392U,
- 238548032U, 238681024U, 238812608U, 238941632U, 239075008U, 239206336U,
- 239335232U, 239466944U, 239599168U, 239730496U, 239861312U, 239992384U,
- 240122816U, 240254656U, 240385856U, 240516928U, 240647872U, 240779072U,
- 240909632U, 241040704U, 241171904U, 241302848U, 241433408U, 241565248U,
- 241696192U, 241825984U, 241958848U, 242088256U, 242220224U, 242352064U,
- 242481856U, 242611648U, 242744896U, 242876224U, 243005632U, 243138496U,
- 243268672U, 243400384U, 243531712U, 243662656U, 243793856U, 243924544U,
- 244054592U, 244187072U, 244316608U, 244448704U, 244580032U, 244710976U,
- 244841536U, 244972864U, 245104448U, 245233984U, 245365312U, 245497792U,
- 245628736U, 245759936U, 245889856U, 246021056U, 246152512U, 246284224U,
- 246415168U, 246545344U, 246675904U, 246808384U, 246939584U, 247070144U,
- 247199552U, 247331648U, 247463872U, 247593536U, 247726016U, 247857088U,
- 247987648U, 248116928U, 248249536U, 248380736U, 248512064U, 248643008U,
- 248773312U, 248901056U, 249036608U, 249167552U, 249298624U, 249429184U,
- 249560512U, 249692096U, 249822784U, 249954112U, 250085312U, 250215488U,
- 250345792U, 250478528U, 250608704U, 250739264U, 250870976U, 251002816U,
- 251133632U, 251263552U, 251395136U, 251523904U, 251657792U, 251789248U,
- 251919424U, 252051392U, 252182464U, 252313408U, 252444224U, 252575552U,
- 252706624U, 252836032U, 252968512U, 253099712U, 253227584U, 253361728U,
- 253493056U, 253623488U, 253754432U, 253885504U, 254017216U, 254148032U,
- 254279488U, 254410432U, 254541376U, 254672576U, 254803264U, 254933824U,
- 255065792U, 255196736U, 255326528U, 255458752U, 255589952U, 255721408U,
- 255851072U, 255983296U, 256114624U, 256244416U, 256374208U, 256507712U,
- 256636096U, 256768832U, 256900544U, 257031616U, 257162176U, 257294272U,
- 257424448U, 257555776U, 257686976U, 257818432U, 257949632U, 258079552U,
- 258211136U, 258342464U, 258473408U, 258603712U, 258734656U, 258867008U,
- 258996544U, 259127744U, 259260224U, 259391296U, 259522112U, 259651904U,
- 259784384U, 259915328U, 260045888U, 260175424U, 260308544U, 260438336U,
- 260570944U, 260700992U, 260832448U, 260963776U, 261092672U, 261226304U,
- 261356864U, 261487936U, 261619648U, 261750592U, 261879872U, 262011968U,
- 262143424U, 262274752U, 262404416U, 262537024U, 262667968U, 262799296U,
- 262928704U, 263061184U, 263191744U, 263322944U, 263454656U, 263585216U,
- 263716672U, 263847872U, 263978944U, 264108608U, 264241088U, 264371648U,
- 264501184U, 264632768U, 264764096U, 264895936U, 265024576U, 265158464U,
- 265287488U, 265418432U, 265550528U, 265681216U, 265813312U, 265943488U,
- 266075968U, 266206144U, 266337728U, 266468032U, 266600384U, 266731072U,
- 266862272U, 266993344U, 267124288U, 267255616U, 267386432U, 267516992U,
- 267648704U, 267777728U, 267910592U, 268040512U, 268172096U, 268302784U,
- 268435264U, 268566208U, 268696256U, 268828096U, 268959296U, 269090368U,
- 269221312U, 269352256U, 269482688U, 269614784U, 269745856U, 269876416U,
- 270007616U, 270139328U, 270270272U, 270401216U, 270531904U, 270663616U,
- 270791744U, 270924736U, 271056832U, 271186112U, 271317184U, 271449536U,
- 271580992U, 271711936U, 271843136U, 271973056U, 272105408U, 272236352U,
- 272367296U, 272498368U, 272629568U, 272759488U, 272891456U, 273022784U,
- 273153856U, 273284672U, 273415616U, 273547072U, 273677632U, 273808448U,
- 273937088U, 274071488U, 274200896U, 274332992U, 274463296U, 274595392U,
- 274726208U, 274857536U, 274988992U, 275118656U, 275250496U, 275382208U,
- 275513024U, 275643968U, 275775296U, 275906368U, 276037184U, 276167872U,
- 276297664U, 276429376U, 276560576U, 276692672U, 276822976U, 276955072U,
- 277085632U, 277216832U, 277347008U, 277478848U, 277609664U, 277740992U,
- 277868608U, 278002624U, 278134336U, 278265536U, 278395328U, 278526784U,
- 278657728U, 278789824U, 278921152U, 279052096U, 279182912U, 279313088U,
- 279443776U, 279576256U, 279706048U, 279838528U, 279969728U, 280099648U,
- 280230976U, 280361408U, 280493632U, 280622528U, 280755392U, 280887104U,
- 281018176U, 281147968U, 281278912U, 281411392U, 281542592U, 281673152U,
- 281803712U, 281935552U, 282066496U, 282197312U, 282329024U, 282458816U,
- 282590272U, 282720832U, 282853184U, 282983744U, 283115072U, 283246144U,
- 283377344U, 283508416U, 283639744U, 283770304U, 283901504U, 284032576U,
- 284163136U, 284294848U, 284426176U, 284556992U, 284687296U, 284819264U,
- 284950208U, 285081536U
+ 16776896U, 16907456U, 17039296U, 17170112U, 17301056U, 17432512U, 17563072U,
+ 17693888U, 17824192U, 17955904U, 18087488U, 18218176U, 18349504U, 18481088U,
+ 18611392U, 18742336U, 18874304U, 19004224U, 19135936U, 19267264U, 19398208U,
+ 19529408U, 19660096U, 19791424U, 19922752U, 20053952U, 20184896U, 20315968U,
+ 20446912U, 20576576U, 20709184U, 20840384U, 20971072U, 21102272U, 21233216U,
+ 21364544U, 21494848U, 21626816U, 21757376U, 21887552U, 22019392U, 22151104U,
+ 22281536U, 22412224U, 22543936U, 22675264U, 22806464U, 22935872U, 23068096U,
+ 23198272U, 23330752U, 23459008U, 23592512U, 23723968U, 23854912U, 23986112U,
+ 24116672U, 24247616U, 24378688U, 24509504U, 24640832U, 24772544U, 24903488U,
+ 25034432U, 25165376U, 25296704U, 25427392U, 25558592U, 25690048U, 25820096U,
+ 25951936U, 26081728U, 26214208U, 26345024U, 26476096U, 26606656U, 26737472U,
+ 26869184U, 26998208U, 27131584U, 27262528U, 27393728U, 27523904U, 27655744U,
+ 27786688U, 27917888U, 28049344U, 28179904U, 28311488U, 28441792U, 28573504U,
+ 28700864U, 28835648U, 28966208U, 29096768U, 29228608U, 29359808U, 29490752U,
+ 29621824U, 29752256U, 29882816U, 30014912U, 30144448U, 30273728U, 30406976U,
+ 30538432U, 30670784U, 30799936U, 30932672U, 31063744U, 31195072U, 31325248U,
+ 31456192U, 31588288U, 31719232U, 31850432U, 31981504U, 32110784U, 32243392U,
+ 32372672U, 32505664U, 32636608U, 32767808U, 32897344U, 33029824U, 33160768U,
+ 33289664U, 33423296U, 33554368U, 33683648U, 33816512U, 33947456U, 34076992U,
+ 34208704U, 34340032U, 34471744U, 34600256U, 34734016U, 34864576U, 34993984U,
+ 35127104U, 35258176U, 35386688U, 35518528U, 35650624U, 35782336U, 35910976U,
+ 36044608U, 36175808U, 36305728U, 36436672U, 36568384U, 36699968U, 36830656U,
+ 36961984U, 37093312U, 37223488U, 37355072U, 37486528U, 37617472U, 37747904U,
+ 37879232U, 38009792U, 38141888U, 38272448U, 38403392U, 38535104U, 38660672U,
+ 38795584U, 38925632U, 39059264U, 39190336U, 39320768U, 39452096U, 39581632U,
+ 39713984U, 39844928U, 39974848U, 40107968U, 40238144U, 40367168U, 40500032U,
+ 40631744U, 40762816U, 40894144U, 41023552U, 41155904U, 41286208U, 41418304U,
+ 41547712U, 41680448U, 41811904U, 41942848U, 42073792U, 42204992U, 42334912U,
+ 42467008U, 42597824U, 42729152U, 42860096U, 42991552U, 43122368U, 43253696U,
+ 43382848U, 43515712U, 43646912U, 43777088U, 43907648U, 44039104U, 44170432U,
+ 44302144U, 44433344U, 44564288U, 44694976U, 44825152U, 44956864U, 45088448U,
+ 45219008U, 45350464U, 45481024U, 45612608U, 45744064U, 45874496U, 46006208U,
+ 46136768U, 46267712U, 46399424U, 46529344U, 46660672U, 46791488U, 46923328U,
+ 47053504U, 47185856U, 47316928U, 47447872U, 47579072U, 47710144U, 47839936U,
+ 47971648U, 48103232U, 48234176U, 48365248U, 48496192U, 48627136U, 48757312U,
+ 48889664U, 49020736U, 49149248U, 49283008U, 49413824U, 49545152U, 49675712U,
+ 49807168U, 49938368U, 50069056U, 50200256U, 50331584U, 50462656U, 50593472U,
+ 50724032U, 50853952U, 50986048U, 51117632U, 51248576U, 51379904U, 51510848U,
+ 51641792U, 51773248U, 51903296U, 52035136U, 52164032U, 52297664U, 52427968U,
+ 52557376U, 52690112U, 52821952U, 52952896U, 53081536U, 53213504U, 53344576U,
+ 53475776U, 53608384U, 53738816U, 53870528U, 54000832U, 54131776U, 54263744U,
+ 54394688U, 54525248U, 54655936U, 54787904U, 54918592U, 55049152U, 55181248U,
+ 55312064U, 55442752U, 55574336U, 55705024U, 55836224U, 55967168U, 56097856U,
+ 56228672U, 56358592U, 56490176U, 56621888U, 56753728U, 56884928U, 57015488U,
+ 57146816U, 57278272U, 57409216U, 57540416U, 57671104U, 57802432U, 57933632U,
+ 58064576U, 58195264U, 58326976U, 58457408U, 58588864U, 58720192U, 58849984U,
+ 58981696U, 59113024U, 59243456U, 59375552U, 59506624U, 59637568U, 59768512U,
+ 59897792U, 60030016U, 60161984U, 60293056U, 60423872U, 60554432U, 60683968U,
+ 60817216U, 60948032U, 61079488U, 61209664U, 61341376U, 61471936U, 61602752U,
+ 61733696U, 61865792U, 61996736U, 62127808U, 62259136U, 62389568U, 62520512U,
+ 62651584U, 62781632U, 62910784U, 63045056U, 63176128U, 63307072U, 63438656U,
+ 63569216U, 63700928U, 63831616U, 63960896U, 64093888U, 64225088U, 64355392U,
+ 64486976U, 64617664U, 64748608U, 64879424U, 65009216U, 65142464U, 65273792U,
+ 65402816U, 65535424U, 65666752U, 65797696U, 65927744U, 66060224U, 66191296U,
+ 66321344U, 66453056U, 66584384U, 66715328U, 66846656U, 66977728U, 67108672U,
+ 67239104U, 67370432U, 67501888U, 67631296U, 67763776U, 67895104U, 68026304U,
+ 68157248U, 68287936U, 68419264U, 68548288U, 68681408U, 68811968U, 68942912U,
+ 69074624U, 69205568U, 69337024U, 69467584U, 69599168U, 69729472U, 69861184U,
+ 69989824U, 70122944U, 70253888U, 70385344U, 70515904U, 70647232U, 70778816U,
+ 70907968U, 71040832U, 71171648U, 71303104U, 71432512U, 71564992U, 71695168U,
+ 71826368U, 71958464U, 72089536U, 72219712U, 72350144U, 72482624U, 72613568U,
+ 72744512U, 72875584U, 73006144U, 73138112U, 73268672U, 73400128U, 73530944U,
+ 73662272U, 73793344U, 73924544U, 74055104U, 74185792U, 74316992U, 74448832U,
+ 74579392U, 74710976U, 74841664U, 74972864U, 75102784U, 75233344U, 75364544U,
+ 75497024U, 75627584U, 75759296U, 75890624U, 76021696U, 76152256U, 76283072U,
+ 76414144U, 76545856U, 76676672U, 76806976U, 76937792U, 77070016U, 77200832U,
+ 77331392U, 77462464U, 77593664U, 77725376U, 77856448U, 77987776U, 78118336U,
+ 78249664U, 78380992U, 78511424U, 78642496U, 78773056U, 78905152U, 79033664U,
+ 79166656U, 79297472U, 79429568U, 79560512U, 79690816U, 79822784U, 79953472U,
+ 80084672U, 80214208U, 80346944U, 80477632U, 80608576U, 80740288U, 80870848U,
+ 81002048U, 81133504U, 81264448U, 81395648U, 81525952U, 81657536U, 81786304U,
+ 81919808U, 82050112U, 82181312U, 82311616U, 82443968U, 82573376U, 82705984U,
+ 82835776U, 82967744U, 83096768U, 83230528U, 83359552U, 83491264U, 83622464U,
+ 83753536U, 83886016U, 84015296U, 84147776U, 84277184U, 84409792U, 84540608U,
+ 84672064U, 84803008U, 84934336U, 85065152U, 85193792U, 85326784U, 85458496U,
+ 85589312U, 85721024U, 85851968U, 85982656U, 86112448U, 86244416U, 86370112U,
+ 86506688U, 86637632U, 86769344U, 86900672U, 87031744U, 87162304U, 87293632U,
+ 87424576U, 87555392U, 87687104U, 87816896U, 87947968U, 88079168U, 88211264U,
+ 88341824U, 88473152U, 88603712U, 88735424U, 88862912U, 88996672U, 89128384U,
+ 89259712U, 89390272U, 89521984U, 89652544U, 89783872U, 89914816U, 90045376U,
+ 90177088U, 90307904U, 90438848U, 90569152U, 90700096U, 90832832U, 90963776U,
+ 91093696U, 91223744U, 91356992U, 91486784U, 91618496U, 91749824U, 91880384U,
+ 92012224U, 92143552U, 92273344U, 92405696U, 92536768U, 92666432U, 92798912U,
+ 92926016U, 93060544U, 93192128U, 93322816U, 93453632U, 93583936U, 93715136U,
+ 93845056U, 93977792U, 94109504U, 94240448U, 94371776U, 94501184U, 94632896U,
+ 94764224U, 94895552U, 95023424U, 95158208U, 95287744U, 95420224U, 95550016U,
+ 95681216U, 95811904U, 95943872U, 96075328U, 96203584U, 96337856U, 96468544U,
+ 96599744U, 96731072U, 96860992U, 96992576U, 97124288U, 97254848U, 97385536U,
+ 97517248U, 97647808U, 97779392U, 97910464U, 98041408U, 98172608U, 98303168U,
+ 98434496U, 98565568U, 98696768U, 98827328U, 98958784U, 99089728U, 99220928U,
+ 99352384U, 99482816U, 99614272U, 99745472U, 99876416U, 100007104U,
+ 100138048U, 100267072U, 100401088U, 100529984U, 100662592U, 100791872U,
+ 100925248U, 101056064U, 101187392U, 101317952U, 101449408U, 101580608U,
+ 101711296U, 101841728U, 101973824U, 102104896U, 102235712U, 102366016U,
+ 102498112U, 102628672U, 102760384U, 102890432U, 103021888U, 103153472U,
+ 103284032U, 103415744U, 103545152U, 103677248U, 103808576U, 103939648U,
+ 104070976U, 104201792U, 104332736U, 104462528U, 104594752U, 104725952U,
+ 104854592U, 104988608U, 105118912U, 105247808U, 105381184U, 105511232U,
+ 105643072U, 105774784U, 105903296U, 106037056U, 106167872U, 106298944U,
+ 106429504U, 106561472U, 106691392U, 106822592U, 106954304U, 107085376U,
+ 107216576U, 107346368U, 107478464U, 107609792U, 107739712U, 107872192U,
+ 108003136U, 108131392U, 108265408U, 108396224U, 108527168U, 108657344U,
+ 108789568U, 108920384U, 109049792U, 109182272U, 109312576U, 109444928U,
+ 109572928U, 109706944U, 109837888U, 109969088U, 110099648U, 110230976U,
+ 110362432U, 110492992U, 110624704U, 110755264U, 110886208U, 111017408U,
+ 111148864U, 111279296U, 111410752U, 111541952U, 111673024U, 111803456U,
+ 111933632U, 112066496U, 112196416U, 112328512U, 112457792U, 112590784U,
+ 112715968U, 112852672U, 112983616U, 113114944U, 113244224U, 113376448U,
+ 113505472U, 113639104U, 113770304U, 113901376U, 114031552U, 114163264U,
+ 114294592U, 114425536U, 114556864U, 114687424U, 114818624U, 114948544U,
+ 115080512U, 115212224U, 115343296U, 115473472U, 115605184U, 115736128U,
+ 115867072U, 115997248U, 116128576U, 116260288U, 116391488U, 116522944U,
+ 116652992U, 116784704U, 116915648U, 117046208U, 117178304U, 117308608U,
+ 117440192U, 117569728U, 117701824U, 117833024U, 117964096U, 118094656U,
+ 118225984U, 118357312U, 118489024U, 118617536U, 118749632U, 118882112U,
+ 119012416U, 119144384U, 119275328U, 119406016U, 119537344U, 119668672U,
+ 119798464U, 119928896U, 120061376U, 120192832U, 120321728U, 120454336U,
+ 120584512U, 120716608U, 120848192U, 120979136U, 121109056U, 121241408U,
+ 121372352U, 121502912U, 121634752U, 121764416U, 121895744U, 122027072U,
+ 122157632U, 122289088U, 122421184U, 122550592U, 122682944U, 122813888U,
+ 122945344U, 123075776U, 123207488U, 123338048U, 123468736U, 123600704U,
+ 123731264U, 123861952U, 123993664U, 124124608U, 124256192U, 124386368U,
+ 124518208U, 124649024U, 124778048U, 124911296U, 125041088U, 125173696U,
+ 125303744U, 125432896U, 125566912U, 125696576U, 125829056U, 125958592U,
+ 126090304U, 126221248U, 126352832U, 126483776U, 126615232U, 126746432U,
+ 126876608U, 127008704U, 127139392U, 127270336U, 127401152U, 127532224U,
+ 127663552U, 127794752U, 127925696U, 128055232U, 128188096U, 128319424U,
+ 128449856U, 128581312U, 128712256U, 128843584U, 128973632U, 129103808U,
+ 129236288U, 129365696U, 129498944U, 129629888U, 129760832U, 129892288U,
+ 130023104U, 130154048U, 130283968U, 130416448U, 130547008U, 130678336U,
+ 130807616U, 130939456U, 131071552U, 131202112U, 131331776U, 131464384U,
+ 131594048U, 131727296U, 131858368U, 131987392U, 132120256U, 132250816U,
+ 132382528U, 132513728U, 132644672U, 132774976U, 132905792U, 133038016U,
+ 133168832U, 133299392U, 133429312U, 133562048U, 133692992U, 133823296U,
+ 133954624U, 134086336U, 134217152U, 134348608U, 134479808U, 134607296U,
+ 134741056U, 134872384U, 135002944U, 135134144U, 135265472U, 135396544U,
+ 135527872U, 135659072U, 135787712U, 135921472U, 136052416U, 136182848U,
+ 136313792U, 136444864U, 136576448U, 136707904U, 136837952U, 136970048U,
+ 137099584U, 137232064U, 137363392U, 137494208U, 137625536U, 137755712U,
+ 137887424U, 138018368U, 138149824U, 138280256U, 138411584U, 138539584U,
+ 138672832U, 138804928U, 138936128U, 139066688U, 139196864U, 139328704U,
+ 139460032U, 139590208U, 139721024U, 139852864U, 139984576U, 140115776U,
+ 140245696U, 140376512U, 140508352U, 140640064U, 140769856U, 140902336U,
+ 141032768U, 141162688U, 141294016U, 141426496U, 141556544U, 141687488U,
+ 141819584U, 141949888U, 142080448U, 142212544U, 142342336U, 142474432U,
+ 142606144U, 142736192U, 142868288U, 142997824U, 143129408U, 143258944U,
+ 143392448U, 143523136U, 143653696U, 143785024U, 143916992U, 144045632U,
+ 144177856U, 144309184U, 144440768U, 144570688U, 144701888U, 144832448U,
+ 144965056U, 145096384U, 145227584U, 145358656U, 145489856U, 145620928U,
+ 145751488U, 145883072U, 146011456U, 146144704U, 146275264U, 146407232U,
+ 146538176U, 146668736U, 146800448U, 146931392U, 147062336U, 147193664U,
+ 147324224U, 147455936U, 147586624U, 147717056U, 147848768U, 147979456U,
+ 148110784U, 148242368U, 148373312U, 148503232U, 148635584U, 148766144U,
+ 148897088U, 149028416U, 149159488U, 149290688U, 149420224U, 149551552U,
+ 149683136U, 149814976U, 149943616U, 150076352U, 150208064U, 150338624U,
+ 150470464U, 150600256U, 150732224U, 150862784U, 150993088U, 151125952U,
+ 151254976U, 151388096U, 151519168U, 151649728U, 151778752U, 151911104U,
+ 152042944U, 152174144U, 152304704U, 152435648U, 152567488U, 152698816U,
+ 152828992U, 152960576U, 153091648U, 153222976U, 153353792U, 153484096U,
+ 153616192U, 153747008U, 153878336U, 154008256U, 154139968U, 154270912U,
+ 154402624U, 154533824U, 154663616U, 154795712U, 154926272U, 155057984U,
+ 155188928U, 155319872U, 155450816U, 155580608U, 155712064U, 155843392U,
+ 155971136U, 156106688U, 156237376U, 156367424U, 156499264U, 156630976U,
+ 156761536U, 156892352U, 157024064U, 157155008U, 157284416U, 157415872U,
+ 157545536U, 157677248U, 157810496U, 157938112U, 158071744U, 158203328U,
+ 158334656U, 158464832U, 158596288U, 158727616U, 158858048U, 158988992U,
+ 159121216U, 159252416U, 159381568U, 159513152U, 159645632U, 159776192U,
+ 159906496U, 160038464U, 160169536U, 160300352U, 160430656U, 160563008U,
+ 160693952U, 160822208U, 160956352U, 161086784U, 161217344U, 161349184U,
+ 161480512U, 161611456U, 161742272U, 161873216U, 162002752U, 162135872U,
+ 162266432U, 162397888U, 162529216U, 162660032U, 162790976U, 162922048U,
+ 163052096U, 163184576U, 163314752U, 163446592U, 163577408U, 163707968U,
+ 163839296U, 163969984U, 164100928U, 164233024U, 164364224U, 164494912U,
+ 164625856U, 164756672U, 164887616U, 165019072U, 165150016U, 165280064U,
+ 165412672U, 165543104U, 165674944U, 165805888U, 165936832U, 166067648U,
+ 166198336U, 166330048U, 166461248U, 166591552U, 166722496U, 166854208U,
+ 166985408U, 167116736U, 167246656U, 167378368U, 167508416U, 167641024U,
+ 167771584U, 167903168U, 168034112U, 168164032U, 168295744U, 168427456U,
+ 168557632U, 168688448U, 168819136U, 168951616U, 169082176U, 169213504U,
+ 169344832U, 169475648U, 169605952U, 169738048U, 169866304U, 169999552U,
+ 170131264U, 170262464U, 170393536U, 170524352U, 170655424U, 170782016U,
+ 170917696U, 171048896U, 171179072U, 171310784U, 171439936U, 171573184U,
+ 171702976U, 171835072U, 171966272U, 172097216U, 172228288U, 172359232U,
+ 172489664U, 172621376U, 172747712U, 172883264U, 173014208U, 173144512U,
+ 173275072U, 173407424U, 173539136U, 173669696U, 173800768U, 173931712U,
+ 174063424U, 174193472U, 174325696U, 174455744U, 174586816U, 174718912U,
+ 174849728U, 174977728U, 175109696U, 175242688U, 175374272U, 175504832U,
+ 175636288U, 175765696U, 175898432U, 176028992U, 176159936U, 176291264U,
+ 176422592U, 176552512U, 176684864U, 176815424U, 176946496U, 177076544U,
+ 177209152U, 177340096U, 177470528U, 177600704U, 177731648U, 177864256U,
+ 177994816U, 178126528U, 178257472U, 178387648U, 178518464U, 178650176U,
+ 178781888U, 178912064U, 179044288U, 179174848U, 179305024U, 179436736U,
+ 179568448U, 179698496U, 179830208U, 179960512U, 180092608U, 180223808U,
+ 180354752U, 180485696U, 180617152U, 180748096U, 180877504U, 181009984U,
+ 181139264U, 181272512U, 181402688U, 181532608U, 181663168U, 181795136U,
+ 181926592U, 182057536U, 182190016U, 182320192U, 182451904U, 182582336U,
+ 182713792U, 182843072U, 182976064U, 183107264U, 183237056U, 183368384U,
+ 183494848U, 183631424U, 183762752U, 183893824U, 184024768U, 184154816U,
+ 184286656U, 184417984U, 184548928U, 184680128U, 184810816U, 184941248U,
+ 185072704U, 185203904U, 185335616U, 185465408U, 185596352U, 185727296U,
+ 185859904U, 185989696U, 186121664U, 186252992U, 186383552U, 186514112U,
+ 186645952U, 186777152U, 186907328U, 187037504U, 187170112U, 187301824U,
+ 187429184U, 187562048U, 187693504U, 187825472U, 187957184U, 188087104U,
+ 188218304U, 188349376U, 188481344U, 188609728U, 188743616U, 188874304U,
+ 189005248U, 189136448U, 189265088U, 189396544U, 189528128U, 189660992U,
+ 189791936U, 189923264U, 190054208U, 190182848U, 190315072U, 190447424U,
+ 190577984U, 190709312U, 190840768U, 190971328U, 191102656U, 191233472U,
+ 191364032U, 191495872U, 191626816U, 191758016U, 191888192U, 192020288U,
+ 192148928U, 192282176U, 192413504U, 192542528U, 192674752U, 192805952U,
+ 192937792U, 193068608U, 193198912U, 193330496U, 193462208U, 193592384U,
+ 193723456U, 193854272U, 193985984U, 194116672U, 194247232U, 194379712U,
+ 194508352U, 194641856U, 194772544U, 194900672U, 195035072U, 195166016U,
+ 195296704U, 195428032U, 195558592U, 195690304U, 195818176U, 195952576U,
+ 196083392U, 196214336U, 196345792U, 196476736U, 196607552U, 196739008U,
+ 196869952U, 197000768U, 197130688U, 197262784U, 197394368U, 197523904U,
+ 197656384U, 197787584U, 197916608U, 198049472U, 198180544U, 198310208U,
+ 198442432U, 198573632U, 198705088U, 198834368U, 198967232U, 199097792U,
+ 199228352U, 199360192U, 199491392U, 199621696U, 199751744U, 199883968U,
+ 200014016U, 200146624U, 200276672U, 200408128U, 200540096U, 200671168U,
+ 200801984U, 200933312U, 201062464U, 201194944U, 201326144U, 201457472U,
+ 201588544U, 201719744U, 201850816U, 201981632U, 202111552U, 202244032U,
+ 202374464U, 202505152U, 202636352U, 202767808U, 202898368U, 203030336U,
+ 203159872U, 203292608U, 203423296U, 203553472U, 203685824U, 203816896U,
+ 203947712U, 204078272U, 204208192U, 204341056U, 204472256U, 204603328U,
+ 204733888U, 204864448U, 204996544U, 205125568U, 205258304U, 205388864U,
+ 205517632U, 205650112U, 205782208U, 205913536U, 206044736U, 206176192U,
+ 206307008U, 206434496U, 206569024U, 206700224U, 206831168U, 206961856U,
+ 207093056U, 207223616U, 207355328U, 207486784U, 207616832U, 207749056U,
+ 207879104U, 208010048U, 208141888U, 208273216U, 208404032U, 208534336U,
+ 208666048U, 208796864U, 208927424U, 209059264U, 209189824U, 209321792U,
+ 209451584U, 209582656U, 209715136U, 209845568U, 209976896U, 210106432U,
+ 210239296U, 210370112U, 210501568U, 210630976U, 210763712U, 210894272U,
+ 211024832U, 211156672U, 211287616U, 211418176U, 211549376U, 211679296U,
+ 211812032U, 211942592U, 212074432U, 212204864U, 212334016U, 212467648U,
+ 212597824U, 212727616U, 212860352U, 212991424U, 213120832U, 213253952U,
+ 213385024U, 213515584U, 213645632U, 213777728U, 213909184U, 214040128U,
+ 214170688U, 214302656U, 214433728U, 214564544U, 214695232U, 214826048U,
+ 214956992U, 215089088U, 215219776U, 215350592U, 215482304U, 215613248U,
+ 215743552U, 215874752U, 216005312U, 216137024U, 216267328U, 216399296U,
+ 216530752U, 216661696U, 216790592U, 216923968U, 217054528U, 217183168U,
+ 217316672U, 217448128U, 217579072U, 217709504U, 217838912U, 217972672U,
+ 218102848U, 218233024U, 218364736U, 218496832U, 218627776U, 218759104U,
+ 218888896U, 219021248U, 219151936U, 219281728U, 219413056U, 219545024U,
+ 219675968U, 219807296U, 219938624U, 220069312U, 220200128U, 220331456U,
+ 220461632U, 220592704U, 220725184U, 220855744U, 220987072U, 221117888U,
+ 221249216U, 221378368U, 221510336U, 221642048U, 221772736U, 221904832U,
+ 222031808U, 222166976U, 222297536U, 222428992U, 222559936U, 222690368U,
+ 222820672U, 222953152U, 223083968U, 223213376U, 223345984U, 223476928U,
+ 223608512U, 223738688U, 223869376U, 224001472U, 224132672U, 224262848U,
+ 224394944U, 224524864U, 224657344U, 224788288U, 224919488U, 225050432U,
+ 225181504U, 225312704U, 225443776U, 225574592U, 225704768U, 225834176U,
+ 225966784U, 226097216U, 226229824U, 226360384U, 226491712U, 226623424U,
+ 226754368U, 226885312U, 227015104U, 227147456U, 227278528U, 227409472U,
+ 227539904U, 227669696U, 227802944U, 227932352U, 228065216U, 228196288U,
+ 228326464U, 228457792U, 228588736U, 228720064U, 228850112U, 228981056U,
+ 229113152U, 229243328U, 229375936U, 229505344U, 229636928U, 229769152U,
+ 229894976U, 230030272U, 230162368U, 230292416U, 230424512U, 230553152U,
+ 230684864U, 230816704U, 230948416U, 231079616U, 231210944U, 231342016U,
+ 231472448U, 231603776U, 231733952U, 231866176U, 231996736U, 232127296U,
+ 232259392U, 232388672U, 232521664U, 232652608U, 232782272U, 232914496U,
+ 233043904U, 233175616U, 233306816U, 233438528U, 233569984U, 233699776U,
+ 233830592U, 233962688U, 234092224U, 234221888U, 234353984U, 234485312U,
+ 234618304U, 234749888U, 234880832U, 235011776U, 235142464U, 235274048U,
+ 235403456U, 235535936U, 235667392U, 235797568U, 235928768U, 236057152U,
+ 236190272U, 236322752U, 236453312U, 236583616U, 236715712U, 236846528U,
+ 236976448U, 237108544U, 237239104U, 237371072U, 237501632U, 237630784U,
+ 237764416U, 237895232U, 238026688U, 238157632U, 238286912U, 238419392U,
+ 238548032U, 238681024U, 238812608U, 238941632U, 239075008U, 239206336U,
+ 239335232U, 239466944U, 239599168U, 239730496U, 239861312U, 239992384U,
+ 240122816U, 240254656U, 240385856U, 240516928U, 240647872U, 240779072U,
+ 240909632U, 241040704U, 241171904U, 241302848U, 241433408U, 241565248U,
+ 241696192U, 241825984U, 241958848U, 242088256U, 242220224U, 242352064U,
+ 242481856U, 242611648U, 242744896U, 242876224U, 243005632U, 243138496U,
+ 243268672U, 243400384U, 243531712U, 243662656U, 243793856U, 243924544U,
+ 244054592U, 244187072U, 244316608U, 244448704U, 244580032U, 244710976U,
+ 244841536U, 244972864U, 245104448U, 245233984U, 245365312U, 245497792U,
+ 245628736U, 245759936U, 245889856U, 246021056U, 246152512U, 246284224U,
+ 246415168U, 246545344U, 246675904U, 246808384U, 246939584U, 247070144U,
+ 247199552U, 247331648U, 247463872U, 247593536U, 247726016U, 247857088U,
+ 247987648U, 248116928U, 248249536U, 248380736U, 248512064U, 248643008U,
+ 248773312U, 248901056U, 249036608U, 249167552U, 249298624U, 249429184U,
+ 249560512U, 249692096U, 249822784U, 249954112U, 250085312U, 250215488U,
+ 250345792U, 250478528U, 250608704U, 250739264U, 250870976U, 251002816U,
+ 251133632U, 251263552U, 251395136U, 251523904U, 251657792U, 251789248U,
+ 251919424U, 252051392U, 252182464U, 252313408U, 252444224U, 252575552U,
+ 252706624U, 252836032U, 252968512U, 253099712U, 253227584U, 253361728U,
+ 253493056U, 253623488U, 253754432U, 253885504U, 254017216U, 254148032U,
+ 254279488U, 254410432U, 254541376U, 254672576U, 254803264U, 254933824U,
+ 255065792U, 255196736U, 255326528U, 255458752U, 255589952U, 255721408U,
+ 255851072U, 255983296U, 256114624U, 256244416U, 256374208U, 256507712U,
+ 256636096U, 256768832U, 256900544U, 257031616U, 257162176U, 257294272U,
+ 257424448U, 257555776U, 257686976U, 257818432U, 257949632U, 258079552U,
+ 258211136U, 258342464U, 258473408U, 258603712U, 258734656U, 258867008U,
+ 258996544U, 259127744U, 259260224U, 259391296U, 259522112U, 259651904U,
+ 259784384U, 259915328U, 260045888U, 260175424U, 260308544U, 260438336U,
+ 260570944U, 260700992U, 260832448U, 260963776U, 261092672U, 261226304U,
+ 261356864U, 261487936U, 261619648U, 261750592U, 261879872U, 262011968U,
+ 262143424U, 262274752U, 262404416U, 262537024U, 262667968U, 262799296U,
+ 262928704U, 263061184U, 263191744U, 263322944U, 263454656U, 263585216U,
+ 263716672U, 263847872U, 263978944U, 264108608U, 264241088U, 264371648U,
+ 264501184U, 264632768U, 264764096U, 264895936U, 265024576U, 265158464U,
+ 265287488U, 265418432U, 265550528U, 265681216U, 265813312U, 265943488U,
+ 266075968U, 266206144U, 266337728U, 266468032U, 266600384U, 266731072U,
+ 266862272U, 266993344U, 267124288U, 267255616U, 267386432U, 267516992U,
+ 267648704U, 267777728U, 267910592U, 268040512U, 268172096U, 268302784U,
+ 268435264U, 268566208U, 268696256U, 268828096U, 268959296U, 269090368U,
+ 269221312U, 269352256U, 269482688U, 269614784U, 269745856U, 269876416U,
+ 270007616U, 270139328U, 270270272U, 270401216U, 270531904U, 270663616U,
+ 270791744U, 270924736U, 271056832U, 271186112U, 271317184U, 271449536U,
+ 271580992U, 271711936U, 271843136U, 271973056U, 272105408U, 272236352U,
+ 272367296U, 272498368U, 272629568U, 272759488U, 272891456U, 273022784U,
+ 273153856U, 273284672U, 273415616U, 273547072U, 273677632U, 273808448U,
+ 273937088U, 274071488U, 274200896U, 274332992U, 274463296U, 274595392U,
+ 274726208U, 274857536U, 274988992U, 275118656U, 275250496U, 275382208U,
+ 275513024U, 275643968U, 275775296U, 275906368U, 276037184U, 276167872U,
+ 276297664U, 276429376U, 276560576U, 276692672U, 276822976U, 276955072U,
+ 277085632U, 277216832U, 277347008U, 277478848U, 277609664U, 277740992U,
+ 277868608U, 278002624U, 278134336U, 278265536U, 278395328U, 278526784U,
+ 278657728U, 278789824U, 278921152U, 279052096U, 279182912U, 279313088U,
+ 279443776U, 279576256U, 279706048U, 279838528U, 279969728U, 280099648U,
+ 280230976U, 280361408U, 280493632U, 280622528U, 280755392U, 280887104U,
+ 281018176U, 281147968U, 281278912U, 281411392U, 281542592U, 281673152U,
+ 281803712U, 281935552U, 282066496U, 282197312U, 282329024U, 282458816U,
+ 282590272U, 282720832U, 282853184U, 282983744U, 283115072U, 283246144U,
+ 283377344U, 283508416U, 283639744U, 283770304U, 283901504U, 284032576U,
+ 284163136U, 284294848U, 284426176U, 284556992U, 284687296U, 284819264U,
+ 284950208U, 285081536U
};
#ifdef __cplusplus
}
-#endif \ No newline at end of file
+#endif
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/endian.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/endian.h
index 9ca842e47..0ee402d9a 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/endian.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/endian.h
@@ -3,38 +3,6 @@
#include <stdint.h>
#include "compiler.h"
-static const uint8_t BitReverseTable256[] =
- {
- 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
- 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
- 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
- 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
- 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
- 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
- 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
- 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
- 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
- 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
- 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
- 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
- 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
- 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
- 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
- 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
- };
-
-static inline uint32_t bitfn_swap32(uint32_t a) {
- return (BitReverseTable256[a & 0xff] << 24) |
- (BitReverseTable256[(a >> 8) & 0xff] << 16) |
- (BitReverseTable256[(a >> 16) & 0xff] << 8) |
- (BitReverseTable256[(a >> 24) & 0xff]);
-}
-
-static inline uint64_t bitfn_swap64(uint64_t a) {
- return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) |
- (((uint64_t) bitfn_swap32((uint32_t) a)) << 32);
-}
-
#if defined(__MINGW32__) || defined(_WIN32)
# define LITTLE_ENDIAN 1234
# define BYTE_ORDER LITTLE_ENDIAN
@@ -53,22 +21,52 @@ static inline uint64_t bitfn_swap64(uint64_t a) {
# define BIG_ENDIAN 1234
# define BYTE_ORDER BIG_ENDIAN
#else
-
# include <endian.h>
+#endif
+#if defined(_WIN32)
+#include <stdlib.h>
+#define ethash_swap_u32(input_) _byteswap_ulong(input_)
+#define ethash_swap_u64(input_) _byteswap_uint64(input_)
+#elif defined(__APPLE__)
+#include <libkern/OSByteOrder.h>
+#define ethash_swap_u32(input_) OSSwapInt32(input_)
+#define ethash_swap_u64(input_) OSSwapInt64(input_)
+#else // posix
+#include <byteswap.h>
+#define ethash_swap_u32(input_) __bswap_32(input_)
+#define ethash_swap_u64(input_) __bswap_64(input_)
#endif
#if LITTLE_ENDIAN == BYTE_ORDER
-#define fix_endian32(x) (x)
-#define fix_endian64(x) (x)
+#define fix_endian32(dst_ ,src_) dst_ = src_
+#define fix_endian32_same(val_)
+#define fix_endian64(dst_, src_) dst_ = src_
+#define fix_endian64_same(val_)
+#define fix_endian_arr32(arr_, size_)
+#define fix_endian_arr64(arr_, size_)
#elif BIG_ENDIAN == BYTE_ORDER
-#define fix_endian32(x) bitfn_swap32(x)
-#define fix_endian64(x) bitfn_swap64(x)
+#define fix_endian32(dst_, src_) dst_ = ethash_swap_u32(src_)
+#define fix_endian32_same(val_) val_ = ethash_swap_u32(val_)
+#define fix_endian64(dst_, src_) dst_ = ethash_swap_u64(src_
+#define fix_endian64_same(val_) val_ = ethash_swap_u64(val_)
+#define fix_endian_arr32(arr_, size_) \
+ do { \
+ for (unsigned i_ = 0; i_ < (size_), ++i_) { \
+ arr_[i_] = ethash_swap_u32(arr_[i_]); \
+ } \
+ while (0)
+#define fix_endian_arr64(arr_, size_) \
+ do { \
+ for (unsigned i_ = 0; i_ < (size_), ++i_) { \
+ arr_[i_] = ethash_swap_u64(arr_[i_]); \
+ } \
+ while (0) \
#else
# error "endian not supported"
-#endif // BYTE_ORDER \ No newline at end of file
+#endif // BYTE_ORDER
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/ethash.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/ethash.h
index fad964449..0c6a1f9e9 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/ethash.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/ethash.h
@@ -26,124 +26,121 @@
#include <stddef.h>
#include "compiler.h"
-#define REVISION 23
-#define DATASET_BYTES_INIT 1073741824U // 2**30
-#define DATASET_BYTES_GROWTH 8388608U // 2**23
-#define CACHE_BYTES_INIT 1073741824U // 2**24
-#define CACHE_BYTES_GROWTH 131072U // 2**17
-#define EPOCH_LENGTH 30000U
-#define MIX_BYTES 128
-#define HASH_BYTES 64
-#define DATASET_PARENTS 256
-#define CACHE_ROUNDS 3
-#define ACCESSES 64
+#define ETHASH_REVISION 23
+#define ETHASH_DATASET_BYTES_INIT 1073741824U // 2**30
+#define ETHASH_DATASET_BYTES_GROWTH 8388608U // 2**23
+#define ETHASH_CACHE_BYTES_INIT 1073741824U // 2**24
+#define ETHASH_CACHE_BYTES_GROWTH 131072U // 2**17
+#define ETHASH_EPOCH_LENGTH 30000U
+#define ETHASH_MIX_BYTES 128
+#define ETHASH_HASH_BYTES 64
+#define ETHASH_DATASET_PARENTS 256
+#define ETHASH_CACHE_ROUNDS 3
+#define ETHASH_ACCESSES 64
+#define ETHASH_DAG_MAGIC_NUM_SIZE 8
+#define ETHASH_DAG_MAGIC_NUM 0xFEE1DEADBADDCAFE
#ifdef __cplusplus
extern "C" {
#endif
-typedef struct ethash_params {
- uint64_t full_size; // Size of full data set (in bytes, multiple of mix size (128)).
- uint64_t cache_size; // Size of compute cache (in bytes, multiple of node size (64)).
-} ethash_params;
+/// Type of a seedhash/blockhash e.t.c.
+typedef struct ethash_h256 { uint8_t b[32]; } ethash_h256_t;
-/// Type of a blockhash
-typedef struct ethash_blockhash { uint8_t b[32]; } ethash_blockhash_t;
-static inline uint8_t ethash_blockhash_get(ethash_blockhash_t const* hash, unsigned int i)
-{
- return hash->b[i];
-}
+// convenience macro to statically initialize an h256_t
+// usage:
+// ethash_h256_t a = ethash_h256_static_init(1, 2, 3, ... )
+// have to provide all 32 values. If you don't provide all the rest
+// will simply be unitialized (not guranteed to be 0)
+#define ethash_h256_static_init(...) \
+ { {__VA_ARGS__} }
-static inline void ethash_blockhash_set(ethash_blockhash_t *hash, unsigned int i, uint8_t v)
-{
- hash->b[i] = v;
-}
-
-static inline void ethash_blockhash_reset(ethash_blockhash_t *hash)
-{
- memset(hash, 0, 32);
-}
+struct ethash_light;
+typedef struct ethash_light* ethash_light_t;
+struct ethash_full;
+typedef struct ethash_full* ethash_full_t;
+typedef int(*ethash_callback_t)(unsigned);
typedef struct ethash_return_value {
- ethash_blockhash_t result;
- ethash_blockhash_t mix_hash;
-} ethash_return_value;
-
-uint64_t ethash_get_datasize(const uint32_t block_number);
-uint64_t ethash_get_cachesize(const uint32_t block_number);
-
-// initialize the parameters
-static inline void ethash_params_init(ethash_params *params, const uint32_t block_number) {
- params->full_size = ethash_get_datasize(block_number);
- params->cache_size = ethash_get_cachesize(block_number);
-}
-
-typedef struct ethash_cache {
- void *mem;
-} ethash_cache;
-
-void ethash_mkcache(ethash_cache *cache, ethash_params const *params, ethash_blockhash_t const *seed);
-void ethash_compute_full_data(void *mem, ethash_params const *params, ethash_cache const *cache);
-void ethash_full(ethash_return_value *ret,
- void const *full_mem,
- ethash_params const *params,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce);
-void ethash_light(ethash_return_value *ret,
- ethash_cache const *cache,
- ethash_params const *params,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce);
-void ethash_get_seedhash(ethash_blockhash_t *seedhash, const uint32_t block_number);
-
-static inline void ethash_prep_light(void *cache, ethash_params const *params, ethash_blockhash_t const* seed)
-{
- ethash_cache c;
- c.mem = cache;
- ethash_mkcache(&c, params, seed);
-}
-
-static inline void ethash_compute_light(ethash_return_value *ret, void const *cache, ethash_params const *params, ethash_blockhash_t const *header_hash, const uint64_t nonce)
-{
- ethash_cache c;
- c.mem = (void *) cache;
- ethash_light(ret, &c, params, header_hash, nonce);
-}
-
-static inline void ethash_prep_full(void *full, ethash_params const *params, void const *cache)
-{
- ethash_cache c;
- c.mem = (void *) cache;
- ethash_compute_full_data(full, params, &c);
-}
-
-static inline void ethash_compute_full(ethash_return_value *ret,
- void const *full,
- ethash_params const *params,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce)
-{
- ethash_full(ret, full, params, header_hash, nonce);
-}
-
-// Returns if hash is less than or equal to difficulty
-static inline int ethash_check_difficulty(ethash_blockhash_t const *hash,
- ethash_blockhash_t const *difficulty)
-{
- // Difficulty is big endian
- for (int i = 0; i < 32; i++) {
- if (ethash_blockhash_get(hash, i) == ethash_blockhash_get(difficulty, i)) {
- continue;
- }
- return ethash_blockhash_get(hash, i) < ethash_blockhash_get(difficulty, i);
- }
- return 1;
-}
-
-int ethash_quick_check_difficulty(ethash_blockhash_t const *header_hash,
- const uint64_t nonce,
- ethash_blockhash_t const *mix_hash,
- ethash_blockhash_t const *difficulty);
+ ethash_h256_t result;
+ ethash_h256_t mix_hash;
+ bool success;
+} ethash_return_value_t;
+
+/**
+ * Allocate and initialize a new ethash_light handler
+ *
+ * @param block_number The block number for which to create the handler
+ * @return Newly allocated ethash_light handler or NULL in case of
+ * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
+ */
+ethash_light_t ethash_light_new(uint64_t block_number);
+/**
+ * Frees a previously allocated ethash_light handler
+ * @param light The light handler to free
+ */
+void ethash_light_delete(ethash_light_t light);
+/**
+ * Calculate the light client data
+ *
+ * @param light The light client handler
+ * @param header_hash The header hash to pack into the mix
+ * @param nonce The nonce to pack into the mix
+ * @return an object of ethash_return_value_t holding the return values
+ */
+ethash_return_value_t ethash_light_compute(
+ ethash_light_t light,
+ ethash_h256_t const header_hash,
+ uint64_t nonce
+);
+
+/**
+ * Allocate and initialize a new ethash_full handler
+ *
+ * @param light The light handler containing the cache.
+ * @param callback A callback function with signature of @ref ethash_callback_t
+ * It accepts an unsigned with which a progress of DAG calculation
+ * can be displayed. If all goes well the callback should return 0.
+ * If a non-zero value is returned then DAG generation will stop.
+ * Be advised. A progress value of 100 means that DAG creation is
+ * almost complete and that this function will soon return succesfully.
+ * It does not mean that the function has already had a succesfull return.
+ * @return Newly allocated ethash_full handler or NULL in case of
+ * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
+ */
+ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback);
+
+/**
+ * Frees a previously allocated ethash_full handler
+ * @param full The light handler to free
+ */
+void ethash_full_delete(ethash_full_t full);
+/**
+ * Calculate the full client data
+ *
+ * @param full The full client handler
+ * @param header_hash The header hash to pack into the mix
+ * @param nonce The nonce to pack into the mix
+ * @return An object of ethash_return_value to hold the return value
+ */
+ethash_return_value_t ethash_full_compute(
+ ethash_full_t full,
+ ethash_h256_t const header_hash,
+ uint64_t nonce
+);
+/**
+ * Get a pointer to the full DAG data
+ */
+void const* ethash_full_dag(ethash_full_t full);
+/**
+ * Get the size of the DAG data
+ */
+uint64_t ethash_full_dag_size(ethash_full_t full);
+
+/**
+ * Calculate the seedhash for a given block number
+ */
+ethash_h256_t ethash_get_seedhash(uint64_t block_number);
#ifdef __cplusplus
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/fnv.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/fnv.h
index edabeaae2..d23c4e247 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/fnv.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/fnv.h
@@ -29,10 +29,11 @@ extern "C" {
#define FNV_PRIME 0x01000193
-static inline uint32_t fnv_hash(const uint32_t x, const uint32_t y) {
- return x*FNV_PRIME ^ y;
+static inline uint32_t fnv_hash(uint32_t const x, uint32_t const y)
+{
+ return x * FNV_PRIME ^ y;
}
#ifdef __cplusplus
}
-#endif \ No newline at end of file
+#endif
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c
index 5009d52f5..607e44138 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c
@@ -8,11 +8,11 @@
ethash 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
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file internal.c
* @author Tim Hughes <tim@twistedfury.com>
@@ -23,11 +23,15 @@
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
+#include <errno.h>
+#include <math.h>
+#include "mmap.h"
#include "ethash.h"
#include "fnv.h"
#include "endian.h"
#include "internal.h"
#include "data_sizes.h"
+#include "io.h"
#ifdef WITH_CRYPTOPP
@@ -37,274 +41,456 @@
#include "sha3.h"
#endif // WITH_CRYPTOPP
-uint64_t ethash_get_datasize(const uint32_t block_number) {
- assert(block_number / EPOCH_LENGTH < 2048);
- return dag_sizes[block_number / EPOCH_LENGTH];
+uint64_t ethash_get_datasize(uint64_t const block_number)
+{
+ assert(block_number / ETHASH_EPOCH_LENGTH < 2048);
+ return dag_sizes[block_number / ETHASH_EPOCH_LENGTH];
}
-uint64_t ethash_get_cachesize(const uint32_t block_number) {
- assert(block_number / EPOCH_LENGTH < 2048);
- return cache_sizes[block_number / EPOCH_LENGTH];
+uint64_t ethash_get_cachesize(uint64_t const block_number)
+{
+ assert(block_number / ETHASH_EPOCH_LENGTH < 2048);
+ return cache_sizes[block_number / ETHASH_EPOCH_LENGTH];
}
// Follows Sergio's "STRICT MEMORY HARD HASHING FUNCTIONS" (2014)
// https://bitslog.files.wordpress.com/2013/12/memohash-v0-3.pdf
// SeqMemoHash(s, R, N)
-void static ethash_compute_cache_nodes(node *const nodes,
- ethash_params const *params,
- ethash_blockhash_t const* seed)
-{
- assert((params->cache_size % sizeof(node)) == 0);
- uint32_t const num_nodes = (uint32_t) (params->cache_size / sizeof(node));
-
- SHA3_512(nodes[0].bytes, (uint8_t*)seed, 32);
-
- for (unsigned i = 1; i != num_nodes; ++i) {
- SHA3_512(nodes[i].bytes, nodes[i - 1].bytes, 64);
- }
-
- for (unsigned j = 0; j != CACHE_ROUNDS; j++) {
- for (unsigned i = 0; i != num_nodes; i++) {
- uint32_t const idx = nodes[i].words[0] % num_nodes;
- node data;
- data = nodes[(num_nodes - 1 + i) % num_nodes];
- for (unsigned w = 0; w != NODE_WORDS; ++w) {
- data.words[w] ^= nodes[idx].words[w];
- }
- SHA3_512(nodes[i].bytes, data.bytes, sizeof(data));
- }
- }
-
- // now perform endian conversion
-#if BYTE_ORDER != LITTLE_ENDIAN
- for (unsigned w = 0; w != (num_nodes*NODE_WORDS); ++w)
- {
- nodes->words[w] = fix_endian32(nodes->words[w]);
- }
-#endif
-}
-
-void ethash_mkcache(ethash_cache *cache,
- ethash_params const *params,
- ethash_blockhash_t const* seed)
+bool static ethash_compute_cache_nodes(
+ node* const nodes,
+ uint64_t cache_size,
+ ethash_h256_t const* seed
+)
{
- node *nodes = (node *) cache->mem;
- ethash_compute_cache_nodes(nodes, params, seed);
+ if (cache_size % sizeof(node) != 0) {
+ return false;
+ }
+ uint32_t const num_nodes = (uint32_t) (cache_size / sizeof(node));
+
+ SHA3_512(nodes[0].bytes, (uint8_t*)seed, 32);
+
+ for (uint32_t i = 1; i != num_nodes; ++i) {
+ SHA3_512(nodes[i].bytes, nodes[i - 1].bytes, 64);
+ }
+
+ for (uint32_t j = 0; j != ETHASH_CACHE_ROUNDS; j++) {
+ for (uint32_t i = 0; i != num_nodes; i++) {
+ uint32_t const idx = nodes[i].words[0] % num_nodes;
+ node data;
+ data = nodes[(num_nodes - 1 + i) % num_nodes];
+ for (uint32_t w = 0; w != NODE_WORDS; ++w) {
+ data.words[w] ^= nodes[idx].words[w];
+ }
+ SHA3_512(nodes[i].bytes, data.bytes, sizeof(data));
+ }
+ }
+
+ // now perform endian conversion
+ fix_endian_arr32(nodes->words, num_nodes * NODE_WORDS);
+ return true;
}
-void ethash_calculate_dag_item(node *const ret,
- const unsigned node_index,
- const struct ethash_params *params,
- const struct ethash_cache *cache)
+void ethash_calculate_dag_item(
+ node* const ret,
+ uint32_t node_index,
+ ethash_light_t const light
+)
{
- uint32_t num_parent_nodes = (uint32_t) (params->cache_size / sizeof(node));
- node const *cache_nodes = (node const *) cache->mem;
- node const *init = &cache_nodes[node_index % num_parent_nodes];
-
- memcpy(ret, init, sizeof(node));
- ret->words[0] ^= node_index;
- SHA3_512(ret->bytes, ret->bytes, sizeof(node));
-
+ uint32_t num_parent_nodes = (uint32_t) (light->cache_size / sizeof(node));
+ node const* cache_nodes = (node const *) light->cache;
+ node const* init = &cache_nodes[node_index % num_parent_nodes];
+ memcpy(ret, init, sizeof(node));
+ ret->words[0] ^= node_index;
+ SHA3_512(ret->bytes, ret->bytes, sizeof(node));
#if defined(_M_X64) && ENABLE_SSE
- __m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME);
- __m128i xmm0 = ret->xmm[0];
- __m128i xmm1 = ret->xmm[1];
- __m128i xmm2 = ret->xmm[2];
- __m128i xmm3 = ret->xmm[3];
+ __m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME);
+ __m128i xmm0 = ret->xmm[0];
+ __m128i xmm1 = ret->xmm[1];
+ __m128i xmm2 = ret->xmm[2];
+ __m128i xmm3 = ret->xmm[3];
#endif
- for (unsigned i = 0; i != DATASET_PARENTS; ++i) {
- uint32_t parent_index = ((node_index ^ i) * FNV_PRIME ^ ret->words[i % NODE_WORDS]) % num_parent_nodes;
- node const *parent = &cache_nodes[parent_index];
+ for (uint32_t i = 0; i != ETHASH_DATASET_PARENTS; ++i) {
+ uint32_t parent_index = fnv_hash(node_index ^ i, ret->words[i % NODE_WORDS]) % num_parent_nodes;
+ node const *parent = &cache_nodes[parent_index];
#if defined(_M_X64) && ENABLE_SSE
- {
- xmm0 = _mm_mullo_epi32(xmm0, fnv_prime);
- xmm1 = _mm_mullo_epi32(xmm1, fnv_prime);
- xmm2 = _mm_mullo_epi32(xmm2, fnv_prime);
- xmm3 = _mm_mullo_epi32(xmm3, fnv_prime);
- xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]);
- xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]);
- xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]);
- xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]);
-
- // have to write to ret as values are used to compute index
- ret->xmm[0] = xmm0;
- ret->xmm[1] = xmm1;
- ret->xmm[2] = xmm2;
- ret->xmm[3] = xmm3;
- }
- #else
- {
- for (unsigned w = 0; w != NODE_WORDS; ++w) {
- ret->words[w] = fnv_hash(ret->words[w], parent->words[w]);
- }
- }
+ {
+ xmm0 = _mm_mullo_epi32(xmm0, fnv_prime);
+ xmm1 = _mm_mullo_epi32(xmm1, fnv_prime);
+ xmm2 = _mm_mullo_epi32(xmm2, fnv_prime);
+ xmm3 = _mm_mullo_epi32(xmm3, fnv_prime);
+ xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]);
+ xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]);
+ xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]);
+ xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]);
+
+ // have to write to ret as values are used to compute index
+ ret->xmm[0] = xmm0;
+ ret->xmm[1] = xmm1;
+ ret->xmm[2] = xmm2;
+ ret->xmm[3] = xmm3;
+ }
+ #else
+ {
+ for (unsigned w = 0; w != NODE_WORDS; ++w) {
+ ret->words[w] = fnv_hash(ret->words[w], parent->words[w]);
+ }
+ }
#endif
- }
-
- SHA3_512(ret->bytes, ret->bytes, sizeof(node));
+ }
+ SHA3_512(ret->bytes, ret->bytes, sizeof(node));
}
-void ethash_compute_full_data(
- void *mem,
- ethash_params const *params,
- ethash_cache const *cache) {
- assert((params->full_size % (sizeof(uint32_t) * MIX_WORDS)) == 0);
- assert((params->full_size % sizeof(node)) == 0);
- node *full_nodes = mem;
-
- // now compute full nodes
- for (unsigned n = 0; n != (params->full_size / sizeof(node)); ++n) {
- ethash_calculate_dag_item(&(full_nodes[n]), n, params, cache);
- }
+bool ethash_compute_full_data(
+ void* mem,
+ uint64_t full_size,
+ ethash_light_t const light,
+ ethash_callback_t callback
+)
+{
+ if (full_size % (sizeof(uint32_t) * MIX_WORDS) != 0 ||
+ (full_size % sizeof(node)) != 0) {
+ return false;
+ }
+ uint32_t const max_n = (uint32_t)(full_size / sizeof(node));
+ node* full_nodes = mem;
+ double const progress_change = 1.0f / max_n;
+ double progress = 0.0f;
+ // now compute full nodes
+ for (uint32_t n = 0; n != max_n; ++n) {
+ if (callback &&
+ n % (max_n / 100) == 0 &&
+ callback((unsigned int)(ceil(progress * 100.0f))) != 0) {
+
+ return false;
+ }
+ progress += progress_change;
+ ethash_calculate_dag_item(&(full_nodes[n]), n, light);
+ }
+ return true;
}
-static void ethash_hash(ethash_return_value *ret,
- node const *full_nodes,
- ethash_cache const *cache,
- ethash_params const *params,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce)
+static bool ethash_hash(
+ ethash_return_value_t* ret,
+ node const* full_nodes,
+ ethash_light_t const light,
+ uint64_t full_size,
+ ethash_h256_t const header_hash,
+ uint64_t const nonce
+)
{
+ if (full_size % MIX_WORDS != 0) {
+ return false;
+ }
+
+ // pack hash and nonce together into first 40 bytes of s_mix
+ assert(sizeof(node) * 8 == 512);
+ node s_mix[MIX_NODES + 1];
+ memcpy(s_mix[0].bytes, &header_hash, 32);
+ fix_endian64(s_mix[0].double_words[4], nonce);
+
+ // compute sha3-512 hash and replicate across mix
+ SHA3_512(s_mix->bytes, s_mix->bytes, 40);
+ fix_endian_arr32(s_mix[0].words, 16);
+
+ node* const mix = s_mix + 1;
+ for (uint32_t w = 0; w != MIX_WORDS; ++w) {
+ mix->words[w] = s_mix[0].words[w % NODE_WORDS];
+ }
+
+ unsigned const page_size = sizeof(uint32_t) * MIX_WORDS;
+ unsigned const num_full_pages = (unsigned) (full_size / page_size);
+
+ for (unsigned i = 0; i != ETHASH_ACCESSES; ++i) {
+ uint32_t const index = fnv_hash(s_mix->words[0] ^ i, mix->words[i % MIX_WORDS]) % num_full_pages;
+
+ for (unsigned n = 0; n != MIX_NODES; ++n) {
+ node const* dag_node;
+ if (full_nodes) {
+ dag_node = &full_nodes[MIX_NODES * index + n];
+ } else {
+ node tmp_node;
+ ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, light);
+ dag_node = &tmp_node;
+ }
- assert((params->full_size % MIX_WORDS) == 0);
-
- // pack hash and nonce together into first 40 bytes of s_mix
- assert(sizeof(node) * 8 == 512);
- node s_mix[MIX_NODES + 1];
- memcpy(s_mix[0].bytes, header_hash, 32);
-
-#if BYTE_ORDER != LITTLE_ENDIAN
- s_mix[0].double_words[4] = fix_endian64(nonce);
-#else
- s_mix[0].double_words[4] = nonce;
+#if defined(_M_X64) && ENABLE_SSE
+ {
+ __m128i fnv_prime = _mm_set1_epi32(FNV_PRIME);
+ __m128i xmm0 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[0]);
+ __m128i xmm1 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[1]);
+ __m128i xmm2 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[2]);
+ __m128i xmm3 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[3]);
+ mix[n].xmm[0] = _mm_xor_si128(xmm0, dag_node->xmm[0]);
+ mix[n].xmm[1] = _mm_xor_si128(xmm1, dag_node->xmm[1]);
+ mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]);
+ mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]);
+ }
+ #else
+ {
+ for (unsigned w = 0; w != NODE_WORDS; ++w) {
+ mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]);
+ }
+ }
#endif
+ }
+
+ }
+
+ // compress mix
+ for (uint32_t w = 0; w != MIX_WORDS; w += 4) {
+ uint32_t reduction = mix->words[w + 0];
+ reduction = reduction * FNV_PRIME ^ mix->words[w + 1];
+ reduction = reduction * FNV_PRIME ^ mix->words[w + 2];
+ reduction = reduction * FNV_PRIME ^ mix->words[w + 3];
+ mix->words[w / 4] = reduction;
+ }
+
+ fix_endian_arr32(mix->words, MIX_WORDS / 4);
+ memcpy(&ret->mix_hash, mix->bytes, 32);
+ // final Keccak hash
+ SHA3_256(&ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix)
+ return true;
+}
- // compute sha3-512 hash and replicate across mix
- SHA3_512(s_mix->bytes, s_mix->bytes, 40);
-
-#if BYTE_ORDER != LITTLE_ENDIAN
- for (unsigned w = 0; w != 16; ++w) {
- s_mix[0].words[w] = fix_endian32(s_mix[0].words[w]);
- }
-#endif
+void ethash_quick_hash(
+ ethash_h256_t* return_hash,
+ ethash_h256_t const* header_hash,
+ uint64_t const nonce,
+ ethash_h256_t const* mix_hash
+)
+{
+ uint8_t buf[64 + 32];
+ memcpy(buf, header_hash, 32);
+ fix_endian64_same(nonce);
+ memcpy(&(buf[32]), &nonce, 8);
+ SHA3_512(buf, buf, 40);
+ memcpy(&(buf[64]), mix_hash, 32);
+ SHA3_256(return_hash, buf, 64 + 32);
+}
- node *const mix = s_mix + 1;
- for (unsigned w = 0; w != MIX_WORDS; ++w) {
- mix->words[w] = s_mix[0].words[w % NODE_WORDS];
- }
+ethash_h256_t ethash_get_seedhash(uint64_t block_number)
+{
+ ethash_h256_t ret;
+ ethash_h256_reset(&ret);
+ uint64_t const epochs = block_number / ETHASH_EPOCH_LENGTH;
+ for (uint32_t i = 0; i < epochs; ++i)
+ SHA3_256(&ret, (uint8_t*)&ret, 32);
+ return ret;
+}
- unsigned const
- page_size = sizeof(uint32_t) * MIX_WORDS,
- num_full_pages = (unsigned) (params->full_size / page_size);
+int ethash_quick_check_difficulty(
+ ethash_h256_t const* header_hash,
+ uint64_t const nonce,
+ ethash_h256_t const* mix_hash,
+ ethash_h256_t const* difficulty
+)
+{
+ ethash_h256_t return_hash;
+ ethash_quick_hash(&return_hash, header_hash, nonce, mix_hash);
+ return ethash_check_difficulty(&return_hash, difficulty);
+}
- for (unsigned i = 0; i != ACCESSES; ++i) {
- uint32_t const index = ((s_mix->words[0] ^ i) * FNV_PRIME ^ mix->words[i % MIX_WORDS]) % num_full_pages;
+ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed)
+{
+ struct ethash_light *ret;
+ ret = calloc(sizeof(*ret), 1);
+ if (!ret) {
+ return NULL;
+ }
+ ret->cache = malloc((size_t)cache_size);
+ if (!ret->cache) {
+ goto fail_free_light;
+ }
+ node* nodes = (node*)ret->cache;
+ if (!ethash_compute_cache_nodes(nodes, cache_size, seed)) {
+ goto fail_free_cache_mem;
+ }
+ ret->cache_size = cache_size;
+ return ret;
+
+fail_free_cache_mem:
+ free(ret->cache);
+fail_free_light:
+ free(ret);
+ return NULL;
+}
- for (unsigned n = 0; n != MIX_NODES; ++n) {
- const node *dag_node = &full_nodes[MIX_NODES * index + n];
+ethash_light_t ethash_light_new(uint64_t block_number)
+{
+ ethash_h256_t seedhash = ethash_get_seedhash(block_number);
+ ethash_light_t ret;
+ ret = ethash_light_new_internal(ethash_get_cachesize(block_number), &seedhash);
+ ret->block_number = block_number;
+ return ret;
+}
- if (!full_nodes) {
- node tmp_node;
- ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, params, cache);
- dag_node = &tmp_node;
- }
+void ethash_light_delete(ethash_light_t light)
+{
+ if (light->cache) {
+ free(light->cache);
+ }
+ free(light);
+}
-#if defined(_M_X64) && ENABLE_SSE
- {
- __m128i fnv_prime = _mm_set1_epi32(FNV_PRIME);
- __m128i xmm0 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[0]);
- __m128i xmm1 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[1]);
- __m128i xmm2 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[2]);
- __m128i xmm3 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[3]);
- mix[n].xmm[0] = _mm_xor_si128(xmm0, dag_node->xmm[0]);
- mix[n].xmm[1] = _mm_xor_si128(xmm1, dag_node->xmm[1]);
- mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]);
- mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]);
- }
- #else
- {
- for (unsigned w = 0; w != NODE_WORDS; ++w) {
- mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]);
- }
- }
-#endif
- }
-
- }
-
- // compress mix
- for (unsigned w = 0; w != MIX_WORDS; w += 4) {
- uint32_t reduction = mix->words[w + 0];
- reduction = reduction * FNV_PRIME ^ mix->words[w + 1];
- reduction = reduction * FNV_PRIME ^ mix->words[w + 2];
- reduction = reduction * FNV_PRIME ^ mix->words[w + 3];
- mix->words[w / 4] = reduction;
- }
-
-#if BYTE_ORDER != LITTLE_ENDIAN
- for (unsigned w = 0; w != MIX_WORDS/4; ++w) {
- mix->words[w] = fix_endian32(mix->words[w]);
- }
-#endif
+ethash_return_value_t ethash_light_compute_internal(
+ ethash_light_t light,
+ uint64_t full_size,
+ ethash_h256_t const header_hash,
+ uint64_t nonce
+)
+{
+ ethash_return_value_t ret;
+ ret.success = true;
+ if (!ethash_hash(&ret, NULL, light, full_size, header_hash, nonce)) {
+ ret.success = false;
+ }
+ return ret;
+}
- memcpy(&ret->mix_hash, mix->bytes, 32);
- // final Keccak hash
- SHA3_256(&ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix)
+ethash_return_value_t ethash_light_compute(
+ ethash_light_t light,
+ ethash_h256_t const header_hash,
+ uint64_t nonce
+)
+{
+ uint64_t full_size = ethash_get_datasize(light->block_number);
+ return ethash_light_compute_internal(light, full_size, header_hash, nonce);
}
-void ethash_quick_hash(ethash_blockhash_t *return_hash,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce,
- ethash_blockhash_t const *mix_hash)
+static bool ethash_mmap(struct ethash_full* ret, FILE* f)
{
+ int fd;
+ char* mmapped_data;
+ ret->file = f;
+ if ((fd = ethash_fileno(ret->file)) == -1) {
+ return false;
+ }
+ mmapped_data= mmap(
+ NULL,
+ (size_t)ret->file_size + ETHASH_DAG_MAGIC_NUM_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd,
+ 0
+ );
+ if (mmapped_data == MAP_FAILED) {
+ return false;
+ }
+ ret->data = (node*)(mmapped_data + ETHASH_DAG_MAGIC_NUM_SIZE);
+ return true;
+}
- uint8_t buf[64 + 32];
- memcpy(buf, header_hash, 32);
-#if BYTE_ORDER != LITTLE_ENDIAN
- nonce = fix_endian64(nonce);
-#endif
- memcpy(&(buf[32]), &nonce, 8);
- SHA3_512(buf, buf, 40);
- memcpy(&(buf[64]), mix_hash, 32);
- SHA3_256(return_hash, buf, 64 + 32);
+ethash_full_t ethash_full_new_internal(
+ char const* dirname,
+ ethash_h256_t const seed_hash,
+ uint64_t full_size,
+ ethash_light_t const light,
+ ethash_callback_t callback
+)
+{
+ struct ethash_full* ret;
+ FILE *f = NULL;
+ ret = calloc(sizeof(*ret), 1);
+ if (!ret) {
+ return NULL;
+ }
+ ret->file_size = (size_t)full_size;
+ switch (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, false)) {
+ case ETHASH_IO_FAIL:
+ goto fail_free_full;
+ case ETHASH_IO_MEMO_MATCH:
+ if (!ethash_mmap(ret, f)) {
+ goto fail_close_file;
+ }
+ return ret;
+ case ETHASH_IO_MEMO_SIZE_MISMATCH:
+ // if a DAG of same filename but unexpected size is found, silently force new file creation
+ if (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, true) != ETHASH_IO_MEMO_MISMATCH) {
+ goto fail_free_full;
+ }
+ // fallthrough to the mismatch case here, DO NOT go through match
+ case ETHASH_IO_MEMO_MISMATCH:
+ if (!ethash_mmap(ret, f)) {
+ goto fail_close_file;
+ }
+ break;
+ }
+
+ if (!ethash_compute_full_data(ret->data, full_size, light, callback)) {
+ goto fail_free_full_data;
+ }
+
+ // after the DAG has been filled then we finalize it by writting the magic number at the beginning
+ if (fseek(f, 0, SEEK_SET) != 0) {
+ goto fail_free_full_data;
+ }
+ uint64_t const magic_num = ETHASH_DAG_MAGIC_NUM;
+ if (fwrite(&magic_num, ETHASH_DAG_MAGIC_NUM_SIZE, 1, f) != 1) {
+ goto fail_free_full_data;
+ }
+ fflush(f); // make sure the magic number IS there
+ return ret;
+
+fail_free_full_data:
+ // could check that munmap(..) == 0 but even if it did not can't really do anything here
+ munmap(ret->data, (size_t)full_size);
+fail_close_file:
+ fclose(ret->file);
+fail_free_full:
+ free(ret);
+ return NULL;
}
-void ethash_get_seedhash(ethash_blockhash_t *seedhash, const uint32_t block_number)
+ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback)
{
- ethash_blockhash_reset(seedhash);
- const uint32_t epochs = block_number / EPOCH_LENGTH;
- for (uint32_t i = 0; i < epochs; ++i)
- SHA3_256(seedhash, (uint8_t*)seedhash, 32);
+ char strbuf[256];
+ if (!ethash_get_default_dirname(strbuf, 256)) {
+ return NULL;
+ }
+ uint64_t full_size = ethash_get_datasize(light->block_number);
+ ethash_h256_t seedhash = ethash_get_seedhash(light->block_number);
+ return ethash_full_new_internal(strbuf, seedhash, full_size, light, callback);
}
-int ethash_quick_check_difficulty(ethash_blockhash_t const *header_hash,
- const uint64_t nonce,
- ethash_blockhash_t const *mix_hash,
- ethash_blockhash_t const *difficulty)
+void ethash_full_delete(ethash_full_t full)
{
+ // could check that munmap(..) == 0 but even if it did not can't really do anything here
+ munmap(full->data, (size_t)full->file_size);
+ if (full->file) {
+ fclose(full->file);
+ }
+ free(full);
+}
- ethash_blockhash_t return_hash;
- ethash_quick_hash(&return_hash, header_hash, nonce, mix_hash);
- return ethash_check_difficulty(&return_hash, difficulty);
+ethash_return_value_t ethash_full_compute(
+ ethash_full_t full,
+ ethash_h256_t const header_hash,
+ uint64_t nonce
+)
+{
+ ethash_return_value_t ret;
+ ret.success = true;
+ if (!ethash_hash(
+ &ret,
+ (node const*)full->data,
+ NULL,
+ full->file_size,
+ header_hash,
+ nonce)) {
+ ret.success = false;
+ }
+ return ret;
}
-void ethash_full(ethash_return_value *ret,
- void const *full_mem,
- ethash_params const *params,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce)
+void const* ethash_full_dag(ethash_full_t full)
{
- ethash_hash(ret, (node const *) full_mem, NULL, params, header_hash, nonce);
+ return full->data;
}
-void ethash_light(ethash_return_value *ret,
- ethash_cache const *cache,
- ethash_params const *params,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce)
+uint64_t ethash_full_dag_size(ethash_full_t full)
{
- ethash_hash(ret, NULL, cache, params, header_hash, nonce);
+ return full->file_size;
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h
index 1e19cd1fd..221ff290a 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h
@@ -2,6 +2,7 @@
#include "compiler.h"
#include "endian.h"
#include "ethash.h"
+#include <stdio.h>
#define ENABLE_SSE 0
@@ -15,14 +16,14 @@ extern "C" {
// compile time settings
#define NODE_WORDS (64/4)
-#define MIX_WORDS (MIX_BYTES/4)
+#define MIX_WORDS (ETHASH_MIX_BYTES/4)
#define MIX_NODES (MIX_WORDS / NODE_WORDS)
#include <stdint.h>
typedef union node {
- uint8_t bytes[NODE_WORDS * 4];
- uint32_t words[NODE_WORDS];
- uint64_t double_words[NODE_WORDS / 2];
+ uint8_t bytes[NODE_WORDS * 4];
+ uint32_t words[NODE_WORDS];
+ uint64_t double_words[NODE_WORDS / 2];
#if defined(_M_X64) && ENABLE_SSE
__m128i xmm[NODE_WORDS/4];
@@ -30,15 +31,139 @@ typedef union node {
} node;
-void ethash_calculate_dag_item(node *const ret,
- const unsigned node_index,
- ethash_params const *params,
- ethash_cache const *cache);
+static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i)
+{
+ return hash->b[i];
+}
+
+static inline void ethash_h256_set(ethash_h256_t* hash, unsigned int i, uint8_t v)
+{
+ hash->b[i] = v;
+}
+
+static inline void ethash_h256_reset(ethash_h256_t* hash)
+{
+ memset(hash, 0, 32);
+}
+
+// Returns if hash is less than or equal to difficulty
+static inline int ethash_check_difficulty(
+ ethash_h256_t const* hash,
+ ethash_h256_t const* difficulty
+)
+{
+ // Difficulty is big endian
+ for (int i = 0; i < 32; i++) {
+ if (ethash_h256_get(hash, i) == ethash_h256_get(difficulty, i)) {
+ continue;
+ }
+ return ethash_h256_get(hash, i) < ethash_h256_get(difficulty, i);
+ }
+ return 1;
+}
+
+int ethash_quick_check_difficulty(
+ ethash_h256_t const* header_hash,
+ uint64_t const nonce,
+ ethash_h256_t const* mix_hash,
+ ethash_h256_t const* difficulty
+);
+
+struct ethash_light {
+ void* cache;
+ uint64_t cache_size;
+ uint64_t block_number;
+};
+
+/**
+ * Allocate and initialize a new ethash_light handler. Internal version
+ *
+ * @param cache_size The size of the cache in bytes
+ * @param seed Block seedhash to be used during the computation of the
+ * cache nodes
+ * @return Newly allocated ethash_light handler or NULL in case of
+ * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
+ */
+ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed);
+
+/**
+ * Calculate the light client data. Internal version.
+ *
+ * @param light The light client handler
+ * @param full_size The size of the full data in bytes.
+ * @param header_hash The header hash to pack into the mix
+ * @param nonce The nonce to pack into the mix
+ * @return The resulting hash.
+ */
+ethash_return_value_t ethash_light_compute_internal(
+ ethash_light_t light,
+ uint64_t full_size,
+ ethash_h256_t const header_hash,
+ uint64_t nonce
+);
+
+struct ethash_full {
+ FILE* file;
+ uint64_t file_size;
+ node* data;
+};
+
+/**
+ * Allocate and initialize a new ethash_full handler. Internal version.
+ *
+ * @param dirname The directory in which to put the DAG file.
+ * @param seedhash The seed hash of the block. Used in the DAG file naming.
+ * @param full_size The size of the full data in bytes.
+ * @param cache A cache object to use that was allocated with @ref ethash_cache_new().
+ * Iff this function succeeds the ethash_full_t will take memory
+ * memory ownership of the cache and free it at deletion. If
+ * not then the user still has to handle freeing of the cache himself.
+ * @param callback A callback function with signature of @ref ethash_callback_t
+ * It accepts an unsigned with which a progress of DAG calculation
+ * can be displayed. If all goes well the callback should return 0.
+ * If a non-zero value is returned then DAG generation will stop.
+ * @return Newly allocated ethash_full handler or NULL in case of
+ * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
+ */
+ethash_full_t ethash_full_new_internal(
+ char const* dirname,
+ ethash_h256_t const seed_hash,
+ uint64_t full_size,
+ ethash_light_t const light,
+ ethash_callback_t callback
+);
+
+void ethash_calculate_dag_item(
+ node* const ret,
+ uint32_t node_index,
+ ethash_light_t const cache
+);
+
+void ethash_quick_hash(
+ ethash_h256_t* return_hash,
+ ethash_h256_t const* header_hash,
+ const uint64_t nonce,
+ ethash_h256_t const* mix_hash
+);
+
+uint64_t ethash_get_datasize(uint64_t const block_number);
+uint64_t ethash_get_cachesize(uint64_t const block_number);
-void ethash_quick_hash(ethash_blockhash_t *return_hash,
- ethash_blockhash_t const *header_hash,
- const uint64_t nonce,
- ethash_blockhash_t const *mix_hash);
+/**
+ * Compute the memory data for a full node's memory
+ *
+ * @param mem A pointer to an ethash full's memory
+ * @param full_size The size of the full data in bytes
+ * @param cache A cache object to use in the calculation
+ * @param callback The callback function. Check @ref ethash_full_new() for details.
+ * @return true if all went fine and false for invalid parameters
+ */
+bool ethash_compute_full_data(
+ void* mem,
+ uint64_t full_size,
+ ethash_light_t const light,
+ ethash_callback_t callback
+);
#ifdef __cplusplus
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.c
index 5a8eebae5..5b4e7da2b 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.c
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.c
@@ -22,68 +22,81 @@
#include <string.h>
#include <stdio.h>
-// silly macro to save some typing
-#define PASS_ARR(c_) (c_), sizeof(c_)
-
-static bool ethash_io_write_file(char const *dirname,
- char const* filename,
- size_t filename_length,
- void const* data,
- size_t data_size)
-{
- bool ret = false;
- char *fullname = ethash_io_create_filename(dirname, filename, filename_length);
- if (!fullname) {
- return false;
- }
- FILE *f = fopen(fullname, "wb");
- if (!f) {
- goto free_name;
- }
- if (data_size != fwrite(data, 1, data_size, f)) {
- goto close;
- }
-
- ret = true;
-close:
- fclose(f);
-free_name:
- free(fullname);
- return ret;
-}
-
-bool ethash_io_write(char const *dirname,
- ethash_params const* params,
- ethash_blockhash_t seedhash,
- void const* cache,
- uint8_t **data,
- uint64_t *data_size)
+enum ethash_io_rc ethash_io_prepare(
+ char const* dirname,
+ ethash_h256_t const seedhash,
+ FILE** output_file,
+ uint64_t file_size,
+ bool force_create
+)
{
- char info_buffer[DAG_MEMO_BYTESIZE];
- // allocate the bytes
- uint8_t *temp_data_ptr = malloc((size_t)params->full_size);
- if (!temp_data_ptr) {
- goto end;
- }
- ethash_compute_full_data(temp_data_ptr, params, cache);
+ char mutable_name[DAG_MUTABLE_NAME_MAX_SIZE];
+ enum ethash_io_rc ret = ETHASH_IO_FAIL;
- if (!ethash_io_write_file(dirname, PASS_ARR(DAG_FILE_NAME), temp_data_ptr, (size_t)params->full_size)) {
- goto fail_free;
- }
+ // assert directory exists
+ if (!ethash_mkdir(dirname)) {
+ goto end;
+ }
- ethash_io_serialize_info(REVISION, seedhash, info_buffer);
- if (!ethash_io_write_file(dirname, PASS_ARR(DAG_MEMO_NAME), info_buffer, DAG_MEMO_BYTESIZE)) {
- goto fail_free;
- }
+ ethash_io_mutable_name(ETHASH_REVISION, &seedhash, mutable_name);
+ char* tmpfile = ethash_io_create_filename(dirname, mutable_name, strlen(mutable_name));
+ if (!tmpfile) {
+ goto end;
+ }
- *data = temp_data_ptr;
- *data_size = params->full_size;
- return true;
+ FILE *f;
+ if (!force_create) {
+ // try to open the file
+ f = ethash_fopen(tmpfile, "rb+");
+ if (f) {
+ size_t found_size;
+ if (!ethash_file_size(f, &found_size)) {
+ fclose(f);
+ goto free_memo;
+ }
+ if (file_size != found_size - ETHASH_DAG_MAGIC_NUM_SIZE) {
+ fclose(f);
+ ret = ETHASH_IO_MEMO_SIZE_MISMATCH;
+ goto free_memo;
+ }
+ // compare the magic number, no need to care about endianess since it's local
+ uint64_t magic_num;
+ if (fread(&magic_num, ETHASH_DAG_MAGIC_NUM_SIZE, 1, f) != 1) {
+ // I/O error
+ fclose(f);
+ ret = ETHASH_IO_MEMO_SIZE_MISMATCH;
+ goto free_memo;
+ }
+ if (magic_num != ETHASH_DAG_MAGIC_NUM) {
+ fclose(f);
+ ret = ETHASH_IO_MEMO_SIZE_MISMATCH;
+ goto free_memo;
+ }
+ ret = ETHASH_IO_MEMO_MATCH;
+ goto set_file;
+ }
+ }
+
+ // file does not exist, will need to be created
+ f = ethash_fopen(tmpfile, "wb+");
+ if (!f) {
+ goto free_memo;
+ }
+ // make sure it's of the proper size
+ if (fseek(f, (long int)(file_size + ETHASH_DAG_MAGIC_NUM_SIZE - 1), SEEK_SET) != 0) {
+ fclose(f);
+ goto free_memo;
+ }
+ fputc('\n', f);
+ fflush(f);
+ ret = ETHASH_IO_MEMO_MISMATCH;
+ goto set_file;
-fail_free:
- free(temp_data_ptr);
+ ret = ETHASH_IO_MEMO_MATCH;
+set_file:
+ *output_file = f;
+free_memo:
+ free(tmpfile);
end:
- return false;
+ return ret;
}
-
-#undef PASS_ARR
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h
index 8cf8b69bf..4fe46d756 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h
@@ -22,93 +22,162 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
+#include <stdio.h>
+#ifdef __cplusplus
+#define __STDC_FORMAT_MACROS 1
+#endif
+#include <inttypes.h>
+#include "endian.h"
#include "ethash.h"
#ifdef __cplusplus
extern "C" {
#endif
-
-static const char DAG_FILE_NAME[] = "full";
-static const char DAG_MEMO_NAME[] = "full.info";
-// MSVC thinks that "static const unsigned int" is not a compile time variable. Sorry for the #define :(
-#define DAG_MEMO_BYTESIZE 36
-
+// Maximum size for mutable part of DAG file name
+// 10 is for maximum number of digits of a uint32_t (for REVISION)
+// 1 is for _ and 16 is for the first 16 hex digits for first 8 bytes of
+// the seedhash and last 1 is for the null terminating character
+// Reference: https://github.com/ethereum/wiki/wiki/Ethash-DAG
+#define DAG_MUTABLE_NAME_MAX_SIZE (10 + 1 + 16 + 1)
/// Possible return values of @see ethash_io_prepare
enum ethash_io_rc {
- ETHASH_IO_FAIL = 0, ///< There has been an IO failure
- ETHASH_IO_MEMO_MISMATCH, ///< Memo file either did not exist or there was content mismatch
- ETHASH_IO_MEMO_MATCH, ///< Memo file existed and contents matched. No need to do anything
+ ETHASH_IO_FAIL = 0, ///< There has been an IO failure
+ ETHASH_IO_MEMO_SIZE_MISMATCH, ///< DAG with revision/hash match, but file size was wrong.
+ ETHASH_IO_MEMO_MISMATCH, ///< The DAG file did not exist or there was revision/hash mismatch
+ ETHASH_IO_MEMO_MATCH, ///< DAG file existed and revision/hash matched. No need to do anything
};
+// small hack for windows. I don't feel I should use va_args and forward just
+// to have this one function properly cross-platform abstracted
+#if defined(_WIN32) && !defined(__GNUC__)
+#define snprintf(...) sprintf_s(__VA_ARGS__)
+#endif
+
/**
* Prepares io for ethash
*
- * Create the DAG directory if it does not exist, and check if the memo file matches.
- * If it does not match then it's deleted to pave the way for @ref ethash_io_write()
+ * Create the DAG directory and the DAG file if they don't exist.
*
- * @param dirname A null terminated c-string of the path of the ethash
- * data directory. If it does not exist it's created.
- * @param seedhash The seedhash of the current block number
- * @return For possible return values @see enum ethash_io_rc
+ * @param[in] dirname A null terminated c-string of the path of the ethash
+ * data directory. If it does not exist it's created.
+ * @param[in] seedhash The seedhash of the current block number, used in the
+ * naming of the file as can be seen from the spec at:
+ * https://github.com/ethereum/wiki/wiki/Ethash-DAG
+ * @param[out] output_file If there was no failure then this will point to an open
+ * file descriptor. User is responsible for closing it.
+ * In the case of memo match then the file is open on read
+ * mode, while on the case of mismatch a new file is created
+ * on write mode
+ * @param[in] file_size The size that the DAG file should have on disk
+ * @param[out] force_create If true then there is no check to see if the file
+ * already exists
+ * @return For possible return values @see enum ethash_io_rc
*/
-enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash);
+enum ethash_io_rc ethash_io_prepare(
+ char const* dirname,
+ ethash_h256_t const seedhash,
+ FILE** output_file,
+ uint64_t file_size,
+ bool force_create
+);
/**
- * Fully computes data and writes it to the file on disk.
+ * An fopen wrapper for no-warnings crossplatform fopen.
*
- * This function should be called after @see ethash_io_prepare() and only if
- * its return value is @c ETHASH_IO_MEMO_MISMATCH. Will write both the full data
- * and the memo file.
+ * Msvc compiler considers fopen to be insecure and suggests to use their
+ * alternative. This is a wrapper for this alternative. Another way is to
+ * #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does
+ * not sound like a good idea.
*
- * @param[in] dirname A null terminated c-string of the path of the ethash
- * data directory. Has to exist.
- * @param[in] params An ethash_params object containing the full size
- * and the cache size
- * @param[in] seedhash The seedhash of the current block number
- * @param[in] cache The cache data. Would have usually been calulated by
- * @see ethash_prep_light().
- * @param[out] data Pass a pointer to uint8_t by reference here. If the
- * function is succesfull then this point to the allocated
- * data calculated by @see ethash_prep_full(). Memory
- * ownership is transfered to the callee. Remember that
- * you eventually need to free this with a call to free().
- * @param[out] data_size Pass a uint64_t by value. If the function is succesfull
- * then this will contain the number of bytes allocated
- * for @a data.
- * @return True for success and false in case of failure.
+ * @param file_name The path to the file to open
+ * @param mode Opening mode. Check fopen()
+ * @return The FILE* or NULL in failure
*/
-bool ethash_io_write(char const *dirname,
- ethash_params const* params,
- ethash_blockhash_t seedhash,
- void const* cache,
- uint8_t **data,
- uint64_t *data_size);
+FILE* ethash_fopen(char const* file_name, char const* mode);
-static inline void ethash_io_serialize_info(uint32_t revision,
- ethash_blockhash_t seed_hash,
- char *output)
-{
- // if .info is only consumed locally we don't really care about endianess
- memcpy(output, &revision, 4);
- memcpy(output + 4, &seed_hash, 32);
-}
+/**
+ * An strncat wrapper for no-warnings crossplatform strncat.
+ *
+ * Msvc compiler considers strncat to be insecure and suggests to use their
+ * alternative. This is a wrapper for this alternative. Another way is to
+ * #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does
+ * not sound like a good idea.
+ *
+ * @param des Destination buffer
+ * @param dest_size Maximum size of the destination buffer. This is the
+ * extra argument for the MSVC secure strncat
+ * @param src Souce buffer
+ * @param count Number of bytes to copy from source
+ * @return If all is well returns the dest buffer. If there is an
+ * error returns NULL
+ */
+char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count);
-static inline char *ethash_io_create_filename(char const *dirname,
- char const* filename,
- size_t filename_length)
-{
- // in C the cast is not needed, but a C++ compiler will complain for invalid conversion
- char *name = (char*)malloc(strlen(dirname) + filename_length);
- if (!name) {
- return NULL;
- }
+/**
+ * A cross-platform mkdir wrapper to create a directory or assert it's there
+ *
+ * @param dirname The full path of the directory to create
+ * @return true if the directory was created or if it already
+ * existed
+ */
+bool ethash_mkdir(char const* dirname);
- name[0] = '\0';
- strcat(name, dirname);
- strcat(name, filename);
- return name;
-}
+/**
+ * Get a file's size
+ *
+ * @param[in] f The open file stream whose size to get
+ * @param[out] size Pass a size_t by reference to contain the file size
+ * @return true in success and false if there was a failure
+ */
+bool ethash_file_size(FILE* f, size_t* ret_size);
+
+/**
+ * Get a file descriptor number from a FILE stream
+ *
+ * @param f The file stream whose fd to get
+ * @return Platform specific fd handler
+ */
+int ethash_fileno(FILE* f);
+/**
+ * Create the filename for the DAG.
+ *
+ * @param dirname The directory name in which the DAG file should reside
+ * If it does not end with a directory separator it is appended.
+ * @param filename The actual name of the file
+ * @param filename_length The length of the filename in bytes
+ * @return A char* containing the full name. User must deallocate.
+ */
+char* ethash_io_create_filename(
+ char const* dirname,
+ char const* filename,
+ size_t filename_length
+);
+
+/**
+ * Gets the default directory name for the DAG depending on the system
+ *
+ * The spec defining this directory is here: https://github.com/ethereum/wiki/wiki/Ethash-DAG
+ *
+ * @param[out] strbuf A string buffer of sufficient size to keep the
+ * null termninated string of the directory name
+ * @param[in] buffsize Size of @a strbuf in bytes
+ * @return true for success and false otherwise
+ */
+bool ethash_get_default_dirname(char* strbuf, size_t buffsize);
+
+static inline bool ethash_io_mutable_name(
+ uint32_t revision,
+ ethash_h256_t const* seed_hash,
+ char* output
+)
+{
+ uint64_t hash = *((uint64_t*)seed_hash);
+#if LITTLE_ENDIAN == BYTE_ORDER
+ hash = ethash_swap_u64(hash);
+#endif
+ return snprintf(output, DAG_MUTABLE_NAME_MAX_SIZE, "%u_%016" PRIx64, revision, hash) >= 0;
+}
#ifdef __cplusplus
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_posix.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_posix.c
index 693bdf750..7f03d5482 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_posix.c
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_posix.c
@@ -27,50 +27,76 @@
#include <stdio.h>
#include <unistd.h>
-enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash)
+FILE* ethash_fopen(char const* file_name, char const* mode)
{
- char read_buffer[DAG_MEMO_BYTESIZE];
- char expect_buffer[DAG_MEMO_BYTESIZE];
- enum ethash_io_rc ret = ETHASH_IO_FAIL;
+ return fopen(file_name, mode);
+}
- // assert directory exists, full owner permissions and read/search for others
- int rc = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- if (rc == -1 && errno != EEXIST) {
- goto end;
- }
+char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count)
+{
+ return strlen(dest) + count + 1 <= dest_size ? strncat(dest, src, count) : NULL;
+}
- char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME));
- if (!memofile) {
- goto end;
- }
+bool ethash_mkdir(char const* dirname)
+{
+ int rc = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ return rc != -1 || errno == EEXIST;
+}
- // try to open memo file
- FILE *f = fopen(memofile, "rb");
- if (!f) {
- // file does not exist, so no checking happens. All is fine.
- ret = ETHASH_IO_MEMO_MISMATCH;
- goto free_memo;
- }
+int ethash_fileno(FILE *f)
+{
+ return fileno(f);
+}
- if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) {
- goto close;
- }
+char* ethash_io_create_filename(
+ char const* dirname,
+ char const* filename,
+ size_t filename_length
+)
+{
+ size_t dirlen = strlen(dirname);
+ size_t dest_size = dirlen + filename_length + 1;
+ if (dirname[dirlen] != '/') {
+ dest_size += 1;
+ }
+ char* name = malloc(dest_size);
+ if (!name) {
+ return NULL;
+ }
- ethash_io_serialize_info(REVISION, seedhash, expect_buffer);
- if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) {
- // we have different memo contents so delete the memo file
- if (unlink(memofile) != 0) {
- goto close;
- }
- ret = ETHASH_IO_MEMO_MISMATCH;
- }
+ name[0] = '\0';
+ ethash_strncat(name, dest_size, dirname, dirlen);
+ if (dirname[dirlen] != '/') {
+ ethash_strncat(name, dest_size, "/", 1);
+ }
+ ethash_strncat(name, dest_size, filename, filename_length);
+ return name;
+}
- ret = ETHASH_IO_MEMO_MATCH;
+bool ethash_file_size(FILE* f, size_t* ret_size)
+{
+ struct stat st;
+ int fd;
+ if ((fd = fileno(f)) == -1 || fstat(fd, &st) != 0) {
+ return false;
+ }
+ *ret_size = st.st_size;
+ return true;
+}
-close:
- fclose(f);
-free_memo:
- free(memofile);
-end:
- return ret;
+bool ethash_get_default_dirname(char* strbuf, size_t buffsize)
+{
+ static const char dir_suffix[] = ".ethash/";
+ strbuf[0] = '\0';
+ char* home_dir = getenv("HOME");
+ size_t len = strlen(home_dir);
+ if (!ethash_strncat(strbuf, buffsize, home_dir, len)) {
+ return false;
+ }
+ if (home_dir[len] != '/') {
+ if (!ethash_strncat(strbuf, buffsize, "/", 1)) {
+ return false;
+ }
+ }
+ return ethash_strncat(strbuf, buffsize, dir_suffix, sizeof(dir_suffix));
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c
index 2cabc939a..d9c54d141 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c
@@ -23,51 +23,78 @@
#include <direct.h>
#include <errno.h>
#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <Shlobj.h>
-enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash)
+FILE* ethash_fopen(char const* file_name, char const* mode)
{
- char read_buffer[DAG_MEMO_BYTESIZE];
- char expect_buffer[DAG_MEMO_BYTESIZE];
- enum ethash_io_rc ret = ETHASH_IO_FAIL;
+ FILE* f;
+ return fopen_s(&f, file_name, mode) == 0 ? f : NULL;
+}
- // assert directory exists
- int rc = _mkdir(dirname);
- if (rc == -1 && errno != EEXIST) {
- goto end;
- }
+char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count)
+{
+ return strncat_s(dest, dest_size, src, count) == 0 ? dest : NULL;
+}
- char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME));
- if (!memofile) {
- goto end;
- }
+bool ethash_mkdir(char const* dirname)
+{
+ int rc = _mkdir(dirname);
+ return rc != -1 || errno == EEXIST;
+}
- // try to open memo file
- FILE *f = fopen(memofile, "rb");
- if (!f) {
- // file does not exist, so no checking happens. All is fine.
- ret = ETHASH_IO_MEMO_MISMATCH;
- goto free_memo;
- }
+int ethash_fileno(FILE* f)
+{
+ return _fileno(f);
+}
- if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) {
- goto close;
- }
+char* ethash_io_create_filename(
+ char const* dirname,
+ char const* filename,
+ size_t filename_length
+)
+{
+ size_t dirlen = strlen(dirname);
+ size_t dest_size = dirlen + filename_length + 1;
+ if (dirname[dirlen] != '\\' || dirname[dirlen] != '/') {
+ dest_size += 1;
+ }
+ char* name = malloc(dest_size);
+ if (!name) {
+ return NULL;
+ }
+
+ name[0] = '\0';
+ ethash_strncat(name, dest_size, dirname, dirlen);
+ if (dirname[dirlen] != '\\' || dirname[dirlen] != '/') {
+ ethash_strncat(name, dest_size, "\\", 1);
+ }
+ ethash_strncat(name, dest_size, filename, filename_length);
+ return name;
+}
- ethash_io_serialize_info(REVISION, seedhash, expect_buffer);
- if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) {
- // we have different memo contents so delete the memo file
- if (_unlink(memofile) != 0) {
- goto close;
- }
- ret = ETHASH_IO_MEMO_MISMATCH;
- }
+bool ethash_file_size(FILE* f, size_t* ret_size)
+{
+ struct _stat st;
+ int fd;
+ if ((fd = _fileno(f)) == -1 || _fstat(fd, &st) != 0) {
+ return false;
+ }
+ *ret_size = st.st_size;
+ return true;
+}
- ret = ETHASH_IO_MEMO_MATCH;
+bool ethash_get_default_dirname(char* strbuf, size_t buffsize)
+{
+ static const char dir_suffix[] = "Appdata\\Ethash\\";
+ strbuf[0] = '\0';
+ if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)strbuf))) {
+ return false;
+ }
+ if (!ethash_strncat(strbuf, buffsize, "\\", 1)) {
+ return false;
+ }
-close:
- fclose(f);
-free_memo:
- free(memofile);
-end:
- return ret;
+ return ethash_strncat(strbuf, buffsize, dir_suffix, sizeof(dir_suffix));
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap.h
new file mode 100644
index 000000000..1e226e83f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap.h
@@ -0,0 +1,47 @@
+/*
+ This file is part of ethash.
+
+ ethash 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.
+
+ ethash 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 ethash. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file mmap.h
+ * @author Lefteris Karapetsas <lefteris@ethdev.com>
+ * @date 2015
+ */
+#pragma once
+#if defined(__MINGW32__) || defined(_WIN32)
+#include <sys/types.h>
+
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+/* This flag is only available in WinXP+ */
+#ifdef FILE_MAP_EXECUTE
+#define PROT_EXEC 0x4
+#else
+#define PROT_EXEC 0x0
+#define FILE_MAP_EXECUTE 0
+#endif
+
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+#define MAP_FAILED ((void *) -1)
+
+void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);
+void munmap(void* addr, size_t length);
+#else // posix, yay! ^_^
+#include <sys/mman.h>
+#endif
+
+
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap_win32.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap_win32.c
new file mode 100644
index 000000000..42968b98a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/mmap_win32.c
@@ -0,0 +1,84 @@
+/* mmap() replacement for Windows
+ *
+ * Author: Mike Frysinger <vapier@gentoo.org>
+ * Placed into the public domain
+ */
+
+/* References:
+ * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
+ * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
+ * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
+ * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
+ */
+
+#include <io.h>
+#include <windows.h>
+#include "mmap.h"
+
+#ifdef __USE_FILE_OFFSET64
+# define DWORD_HI(x) (x >> 32)
+# define DWORD_LO(x) ((x) & 0xffffffff)
+#else
+# define DWORD_HI(x) (0)
+# define DWORD_LO(x) (x)
+#endif
+
+void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return MAP_FAILED;
+ if (fd == -1) {
+ if (!(flags & MAP_ANON) || offset)
+ return MAP_FAILED;
+ } else if (flags & MAP_ANON)
+ return MAP_FAILED;
+
+ DWORD flProtect;
+ if (prot & PROT_WRITE) {
+ if (prot & PROT_EXEC)
+ flProtect = PAGE_EXECUTE_READWRITE;
+ else
+ flProtect = PAGE_READWRITE;
+ } else if (prot & PROT_EXEC) {
+ if (prot & PROT_READ)
+ flProtect = PAGE_EXECUTE_READ;
+ else if (prot & PROT_EXEC)
+ flProtect = PAGE_EXECUTE;
+ } else
+ flProtect = PAGE_READONLY;
+
+ off_t end = length + offset;
+ HANDLE mmap_fd, h;
+ if (fd == -1)
+ mmap_fd = INVALID_HANDLE_VALUE;
+ else
+ mmap_fd = (HANDLE)_get_osfhandle(fd);
+ h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
+ if (h == NULL)
+ return MAP_FAILED;
+
+ DWORD dwDesiredAccess;
+ if (prot & PROT_WRITE)
+ dwDesiredAccess = FILE_MAP_WRITE;
+ else
+ dwDesiredAccess = FILE_MAP_READ;
+ if (prot & PROT_EXEC)
+ dwDesiredAccess |= FILE_MAP_EXECUTE;
+ if (flags & MAP_PRIVATE)
+ dwDesiredAccess |= FILE_MAP_COPY;
+ void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
+ if (ret == NULL) {
+ ret = MAP_FAILED;
+ }
+ // since we are handling the file ourselves with fd, close the Windows Handle here
+ CloseHandle(h);
+ return ret;
+}
+
+void munmap(void* addr, size_t length)
+{
+ UnmapViewOfFile(addr);
+}
+
+#undef DWORD_HI
+#undef DWORD_LO
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.c
index 0c28230b8..e72fe1018 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.c
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.c
@@ -17,65 +17,65 @@
/*** Constants. ***/
static const uint8_t rho[24] = \
- { 1, 3, 6, 10, 15, 21,
- 28, 36, 45, 55, 2, 14,
- 27, 41, 56, 8, 25, 43,
- 62, 18, 39, 61, 20, 44};
+ { 1, 3, 6, 10, 15, 21,
+ 28, 36, 45, 55, 2, 14,
+ 27, 41, 56, 8, 25, 43,
+ 62, 18, 39, 61, 20, 44};
static const uint8_t pi[24] = \
- {10, 7, 11, 17, 18, 3,
- 5, 16, 8, 21, 24, 4,
- 15, 23, 19, 13, 12, 2,
- 20, 14, 22, 9, 6, 1};
+ {10, 7, 11, 17, 18, 3,
+ 5, 16, 8, 21, 24, 4,
+ 15, 23, 19, 13, 12, 2,
+ 20, 14, 22, 9, 6, 1};
static const uint64_t RC[24] = \
- {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
- 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
- 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
- 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
- 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
- 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
+ {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
+ 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
+ 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
+ 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
+ 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
+ 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
/*** Helper macros to unroll the permutation. ***/
#define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
#define REPEAT6(e) e e e e e e
#define REPEAT24(e) REPEAT6(e e e e)
#define REPEAT5(e) e e e e e
-#define FOR5(v, s, e) \
- v = 0; \
- REPEAT5(e; v += s;)
+#define FOR5(v, s, e) \
+ v = 0; \
+ REPEAT5(e; v += s;)
/*** Keccak-f[1600] ***/
static inline void keccakf(void* state) {
- uint64_t* a = (uint64_t*)state;
- uint64_t b[5] = {0};
- uint64_t t = 0;
- uint8_t x, y;
+ uint64_t* a = (uint64_t*)state;
+ uint64_t b[5] = {0};
+ uint64_t t = 0;
+ uint8_t x, y;
- for (int i = 0; i < 24; i++) {
- // Theta
- FOR5(x, 1,
- b[x] = 0;
- FOR5(y, 5,
- b[x] ^= a[x + y]; ))
- FOR5(x, 1,
- FOR5(y, 5,
- a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
- // Rho and pi
- t = a[1];
- x = 0;
- REPEAT24(b[0] = a[pi[x]];
- a[pi[x]] = rol(t, rho[x]);
- t = b[0];
- x++; )
- // Chi
- FOR5(y,
- 5,
- FOR5(x, 1,
- b[x] = a[y + x];)
- FOR5(x, 1,
- a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
- // Iota
- a[0] ^= RC[i];
- }
+ for (int i = 0; i < 24; i++) {
+ // Theta
+ FOR5(x, 1,
+ b[x] = 0;
+ FOR5(y, 5,
+ b[x] ^= a[x + y]; ))
+ FOR5(x, 1,
+ FOR5(y, 5,
+ a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
+ // Rho and pi
+ t = a[1];
+ x = 0;
+ REPEAT24(b[0] = a[pi[x]];
+ a[pi[x]] = rol(t, rho[x]);
+ t = b[0];
+ x++; )
+ // Chi
+ FOR5(y,
+ 5,
+ FOR5(x, 1,
+ b[x] = a[y + x];)
+ FOR5(x, 1,
+ a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
+ // Iota
+ a[0] ^= RC[i];
+ }
}
/******** The FIPS202-defined functions. ********/
@@ -83,20 +83,20 @@ static inline void keccakf(void* state) {
/*** Some helper macros. ***/
#define _(S) do { S } while (0)
-#define FOR(i, ST, L, S) \
- _(for (size_t i = 0; i < L; i += ST) { S; })
-#define mkapply_ds(NAME, S) \
- static inline void NAME(uint8_t* dst, \
- const uint8_t* src, \
- size_t len) { \
- FOR(i, 1, len, S); \
- }
-#define mkapply_sd(NAME, S) \
- static inline void NAME(const uint8_t* src, \
- uint8_t* dst, \
- size_t len) { \
- FOR(i, 1, len, S); \
- }
+#define FOR(i, ST, L, S) \
+ _(for (size_t i = 0; i < L; i += ST) { S; })
+#define mkapply_ds(NAME, S) \
+ static inline void NAME(uint8_t* dst, \
+ const uint8_t* src, \
+ size_t len) { \
+ FOR(i, 1, len, S); \
+ }
+#define mkapply_sd(NAME, S) \
+ static inline void NAME(const uint8_t* src, \
+ uint8_t* dst, \
+ size_t len) { \
+ FOR(i, 1, len, S); \
+ }
mkapply_ds(xorin, dst[i] ^= src[i]) // xorin
mkapply_sd(setout, dst[i] = src[i]) // setout
@@ -105,47 +105,47 @@ mkapply_sd(setout, dst[i] = src[i]) // setout
#define Plen 200
// Fold P*F over the full blocks of an input.
-#define foldP(I, L, F) \
- while (L >= rate) { \
- F(a, I, rate); \
- P(a); \
- I += rate; \
- L -= rate; \
- }
+#define foldP(I, L, F) \
+ while (L >= rate) { \
+ F(a, I, rate); \
+ P(a); \
+ I += rate; \
+ L -= rate; \
+ }
/** The sponge-based hash construction. **/
static inline int hash(uint8_t* out, size_t outlen,
- const uint8_t* in, size_t inlen,
- size_t rate, uint8_t delim) {
- if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
- return -1;
- }
- uint8_t a[Plen] = {0};
- // Absorb input.
- foldP(in, inlen, xorin);
- // Xor in the DS and pad frame.
- a[inlen] ^= delim;
- a[rate - 1] ^= 0x80;
- // Xor in the last block.
- xorin(a, in, inlen);
- // Apply P
- P(a);
- // Squeeze output.
- foldP(out, outlen, setout);
- setout(a, out, outlen);
- memset(a, 0, 200);
- return 0;
+ const uint8_t* in, size_t inlen,
+ size_t rate, uint8_t delim) {
+ if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
+ return -1;
+ }
+ uint8_t a[Plen] = {0};
+ // Absorb input.
+ foldP(in, inlen, xorin);
+ // Xor in the DS and pad frame.
+ a[inlen] ^= delim;
+ a[rate - 1] ^= 0x80;
+ // Xor in the last block.
+ xorin(a, in, inlen);
+ // Apply P
+ P(a);
+ // Squeeze output.
+ foldP(out, outlen, setout);
+ setout(a, out, outlen);
+ memset(a, 0, 200);
+ return 0;
}
-#define defsha3(bits) \
- int sha3_##bits(uint8_t* out, size_t outlen, \
- const uint8_t* in, size_t inlen) { \
- if (outlen > (bits/8)) { \
- return -1; \
- } \
- return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \
- }
+#define defsha3(bits) \
+ int sha3_##bits(uint8_t* out, size_t outlen, \
+ const uint8_t* in, size_t inlen) { \
+ if (outlen > (bits/8)) { \
+ return -1; \
+ } \
+ return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \
+ }
/*** FIPS202 SHA3 FOFs ***/
defsha3(256)
-defsha3(512) \ No newline at end of file
+defsha3(512)
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.h
index 84dca241b..a38006292 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3.h
@@ -8,22 +8,22 @@ extern "C" {
#include <stdint.h>
#include <stdlib.h>
-struct ethash_blockhash;
+struct ethash_h256;
#define decsha3(bits) \
- int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t);
+ int sha3_##bits(uint8_t*, size_t, uint8_t const*, size_t);
decsha3(256)
decsha3(512)
-static inline void SHA3_256(struct ethash_blockhash const* ret, uint8_t const *data, const size_t size)
+static inline void SHA3_256(struct ethash_h256 const* ret, uint8_t const* data, size_t const size)
{
- sha3_256((uint8_t*)ret, 32, data, size);
+ sha3_256((uint8_t*)ret, 32, data, size);
}
-static inline void SHA3_512(uint8_t *ret, uint8_t const *data, const size_t size)
+static inline void SHA3_512(uint8_t* ret, uint8_t const* data, size_t const size)
{
- sha3_512(ret, 64, data, size);
+ sha3_512(ret, 64, data, size);
}
#ifdef __cplusplus
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.cpp b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.cpp
index e4d8b1855..2a7c02664 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.cpp
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.cpp
@@ -23,13 +23,15 @@
#include <cryptopp/sha3.h>
extern "C" {
-struct ethash_blockhash;
-typedef struct ethash_blockhash ethash_blockhash_t;
-void SHA3_256(ethash_blockhash_t const* ret, const uint8_t *data, size_t size) {
- CryptoPP::SHA3_256().CalculateDigest((uint8_t*)ret, data, size);
+struct ethash_h256;
+typedef struct ethash_h256 ethash_h256_t;
+void SHA3_256(ethash_h256_t const* ret, uint8_t const* data, size_t size)
+{
+ CryptoPP::SHA3_256().CalculateDigest((uint8_t*)ret, data, size);
}
-void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size) {
- CryptoPP::SHA3_512().CalculateDigest(ret, data, size);
+void SHA3_512(uint8_t* const ret, uint8_t const* data, size_t size)
+{
+ CryptoPP::SHA3_512().CalculateDigest(ret, data, size);
}
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.h
index 6b257b87c..9edc407d5 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/sha3_cryptopp.h
@@ -8,11 +8,10 @@
extern "C" {
#endif
-struct ethash_blockhash;
-typedef struct ethash_blockhash ethash_blockhash_t;
+struct ethash_h256;
-void SHA3_256(ethash_blockhash_t *const ret, const uint8_t *data, size_t size);
-void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size);
+void SHA3_256(struct ethash_h256 const* ret, uint8_t const* data, size_t size);
+void SHA3_512(uint8_t* const ret, uint8_t const* data, size_t size);
#ifdef __cplusplus
}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h
index ba8957815..0d2307f3d 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h
@@ -26,11 +26,11 @@
extern "C" {
#endif
-#ifdef _MSC_VER
-void debugf(const char *str, ...);
-#else
-#define debugf printf
-#endif
+//#ifdef _MSC_VER
+void debugf(char const* str, ...);
+//#else
+//#define debugf printf
+//#endif
static inline uint32_t min_u32(uint32_t a, uint32_t b)
{
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util_win32.c
index fbf268b7d..268e6db05 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.c
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util_win32.c
@@ -22,20 +22,17 @@
#include <stdio.h>
#include "util.h"
-#ifdef _MSC_VER
// foward declare without all of Windows.h
-__declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString);
+__declspec(dllimport) void __stdcall OutputDebugStringA(char const* lpOutputString);
-void debugf(const char *str, ...)
+void debugf(char const* str, ...)
{
va_list args;
- va_start(args, str);
+ va_start(args, str);
char buf[1<<16];
_vsnprintf_s(buf, sizeof(buf), sizeof(buf), str, args);
buf[sizeof(buf)-1] = '\0';
OutputDebugStringA(buf);
}
-
-#endif
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/python/core.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/python/core.c
index 9024bd584..d77b9761b 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/python/core.c
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/python/core.c
@@ -13,16 +13,16 @@
#define PY_CONST_STRING_FORMAT "s"
#endif
-#define MIX_WORDS (MIX_BYTES/4)
+#define MIX_WORDS (ETHASH_MIX_BYTES/4)
static PyObject *
get_cache_size(PyObject *self, PyObject *args) {
unsigned long block_number;
if (!PyArg_ParseTuple(args, "k", &block_number))
return 0;
- if (block_number >= EPOCH_LENGTH * 2048) {
+ if (block_number >= ETHASH_EPOCH_LENGTH * 2048) {
char error_message[1024];
- sprintf(error_message, "Block number must be less than %i (was %lu)", EPOCH_LENGTH * 2048, block_number);
+ sprintf(error_message, "Block number must be less than %i (was %lu)", ETHASH_EPOCH_LENGTH * 2048, block_number);
PyErr_SetString(PyExc_ValueError, error_message);
return 0;
@@ -36,9 +36,9 @@ get_full_size(PyObject *self, PyObject *args) {
unsigned long block_number;
if (!PyArg_ParseTuple(args, "k", &block_number))
return 0;
- if (block_number >= EPOCH_LENGTH * 2048) {
+ if (block_number >= ETHASH_EPOCH_LENGTH * 2048) {
char error_message[1024];
- sprintf(error_message, "Block number must be less than %i (was %lu)", EPOCH_LENGTH * 2048, block_number);
+ sprintf(error_message, "Block number must be less than %i (was %lu)", ETHASH_EPOCH_LENGTH * 2048, block_number);
PyErr_SetString(PyExc_ValueError, error_message);
return 0;
@@ -69,7 +69,7 @@ mkcache_bytes(PyObject *self, PyObject *args) {
params.cache_size = (size_t) cache_size;
ethash_cache cache;
cache.mem = malloc(cache_size);
- ethash_mkcache(&cache, &params, (ethash_blockhash_t *) seed);
+ ethash_mkcache(&cache, &params, (ethash_h256_t *) seed);
PyObject * val = Py_BuildValue(PY_STRING_FORMAT, cache.mem, cache_size);
free(cache.mem);
return val;
@@ -92,9 +92,9 @@ calc_dataset_bytes(PyObject *self, PyObject *args) {
return 0;
}
- if (cache_size % HASH_BYTES != 0) {
+ if (cache_size % ETHASH_HASH_BYTES != 0) {
char error_message[1024];
- sprintf(error_message, "The size of the cache must be a multiple of %i bytes (was %i)", HASH_BYTES, cache_size);
+ sprintf(error_message, "The size of the cache must be a multiple of %i bytes (was %i)", ETHASH_HASH_BYTES, cache_size);
PyErr_SetString(PyExc_ValueError, error_message);
return 0;
}
@@ -127,9 +127,9 @@ hashimoto_light(PyObject *self, PyObject *args) {
PyErr_SetString(PyExc_ValueError, error_message);
return 0;
}
- if (cache_size % HASH_BYTES != 0) {
+ if (cache_size % ETHASH_HASH_BYTES != 0) {
char error_message[1024];
- sprintf(error_message, "The size of the cache must be a multiple of %i bytes (was %i)", HASH_BYTES, cache_size);
+ sprintf(error_message, "The size of the cache must be a multiple of %i bytes (was %i)", ETHASH_HASH_BYTES, cache_size);
PyErr_SetString(PyExc_ValueError, error_message);
return 0;
}
@@ -146,7 +146,7 @@ hashimoto_light(PyObject *self, PyObject *args) {
params.full_size = (size_t) full_size;
ethash_cache cache;
cache.mem = (void *) cache_bytes;
- ethash_light(&out, &cache, &params, (ethash_blockhash_t *) header, nonce);
+ ethash_light(&out, &cache, &params, (ethash_h256_t *) header, nonce);
return Py_BuildValue("{" PY_CONST_STRING_FORMAT ":" PY_STRING_FORMAT "," PY_CONST_STRING_FORMAT ":" PY_STRING_FORMAT "}",
"mix digest", &out.mix_hash, 32,
"result", &out.result, 32);
@@ -181,7 +181,7 @@ hashimoto_full(PyObject *self, PyObject *args) {
ethash_return_value out;
ethash_params params;
params.full_size = (size_t) full_size;
- ethash_full(&out, (void *) full_bytes, &params, (ethash_blockhash_t *) header, nonce);
+ ethash_full(&out, (void *) full_bytes, &params, (ethash_h256_t *) header, nonce);
return Py_BuildValue("{" PY_CONST_STRING_FORMAT ":" PY_STRING_FORMAT ", " PY_CONST_STRING_FORMAT ":" PY_STRING_FORMAT "}",
"mix digest", &out.mix_hash, 32,
"result", &out.result, 32);
@@ -227,9 +227,9 @@ mine(PyObject *self, PyObject *args) {
// TODO: Multi threading?
do {
- ethash_full(&out, (void *) full_bytes, &params, (const ethash_blockhash_t *) header, nonce++);
+ ethash_full(&out, (void *) full_bytes, &params, (const ethash_h256_t *) header, nonce++);
// TODO: disagrees with the spec https://github.com/ethereum/wiki/wiki/Ethash#mining
- } while (!ethash_check_difficulty(&out.result, (const ethash_blockhash_t *) difficulty));
+ } while (!ethash_check_difficulty(&out.result, (const ethash_h256_t *) difficulty));
return Py_BuildValue("{" PY_CONST_STRING_FORMAT ":" PY_STRING_FORMAT ", " PY_CONST_STRING_FORMAT ":" PY_STRING_FORMAT ", " PY_CONST_STRING_FORMAT ":K}",
"mix digest", &out.mix_hash, 32,
@@ -243,15 +243,14 @@ get_seedhash(PyObject *self, PyObject *args) {
unsigned long block_number;
if (!PyArg_ParseTuple(args, "k", &block_number))
return 0;
- if (block_number >= EPOCH_LENGTH * 2048) {
+ if (block_number >= ETHASH_EPOCH_LENGTH * 2048) {
char error_message[1024];
- sprintf(error_message, "Block number must be less than %i (was %lu)", EPOCH_LENGTH * 2048, block_number);
+ sprintf(error_message, "Block number must be less than %i (was %lu)", ETHASH_EPOCH_LENGTH * 2048, block_number);
PyErr_SetString(PyExc_ValueError, error_message);
return 0;
}
- ethash_blockhash_t seedhash;
- ethash_get_seedhash(&seedhash, block_number);
+ ethash_h256_t seedhash = ethash_get_seedhash(block_number);
return Py_BuildValue(PY_STRING_FORMAT, (char *) &seedhash, 32);
}
@@ -306,17 +305,17 @@ static struct PyModuleDef PyethashModule = {
PyMODINIT_FUNC PyInit_pyethash(void) {
PyObject *module = PyModule_Create(&PyethashModule);
// Following Spec: https://github.com/ethereum/wiki/wiki/Ethash#definitions
- PyModule_AddIntConstant(module, "REVISION", (long) REVISION);
- PyModule_AddIntConstant(module, "DATASET_BYTES_INIT", (long) DATASET_BYTES_INIT);
- PyModule_AddIntConstant(module, "DATASET_BYTES_GROWTH", (long) DATASET_BYTES_GROWTH);
- PyModule_AddIntConstant(module, "CACHE_BYTES_INIT", (long) CACHE_BYTES_INIT);
- PyModule_AddIntConstant(module, "CACHE_BYTES_GROWTH", (long) CACHE_BYTES_GROWTH);
- PyModule_AddIntConstant(module, "EPOCH_LENGTH", (long) EPOCH_LENGTH);
- PyModule_AddIntConstant(module, "MIX_BYTES", (long) MIX_BYTES);
- PyModule_AddIntConstant(module, "HASH_BYTES", (long) HASH_BYTES);
- PyModule_AddIntConstant(module, "DATASET_PARENTS", (long) DATASET_PARENTS);
- PyModule_AddIntConstant(module, "CACHE_ROUNDS", (long) CACHE_ROUNDS);
- PyModule_AddIntConstant(module, "ACCESSES", (long) ACCESSES);
+ PyModule_AddIntConstant(module, "REVISION", (long) ETHASH_REVISION);
+ PyModule_AddIntConstant(module, "DATASET_BYTES_INIT", (long) ETHASH_DATASET_BYTES_INIT);
+ PyModule_AddIntConstant(module, "DATASET_BYTES_GROWTH", (long) ETHASH_DATASET_BYTES_GROWTH);
+ PyModule_AddIntConstant(module, "CACHE_BYTES_INIT", (long) ETHASH_CACHE_BYTES_INIT);
+ PyModule_AddIntConstant(module, "CACHE_BYTES_GROWTH", (long) ETHASH_CACHE_BYTES_GROWTH);
+ PyModule_AddIntConstant(module, "EPOCH_LENGTH", (long) ETHASH_EPOCH_LENGTH);
+ PyModule_AddIntConstant(module, "MIX_BYTES", (long) ETHASH_MIX_BYTES);
+ PyModule_AddIntConstant(module, "HASH_BYTES", (long) ETHASH_HASH_BYTES);
+ PyModule_AddIntConstant(module, "DATASET_PARENTS", (long) ETHASH_DATASET_PARENTS);
+ PyModule_AddIntConstant(module, "CACHE_ROUNDS", (long) ETHASH_CACHE_ROUNDS);
+ PyModule_AddIntConstant(module, "ACCESSES", (long) ETHASH_ACCESSES);
return module;
}
#else
@@ -324,16 +323,16 @@ PyMODINIT_FUNC
initpyethash(void) {
PyObject *module = Py_InitModule("pyethash", PyethashMethods);
// Following Spec: https://github.com/ethereum/wiki/wiki/Ethash#definitions
- PyModule_AddIntConstant(module, "REVISION", (long) REVISION);
- PyModule_AddIntConstant(module, "DATASET_BYTES_INIT", (long) DATASET_BYTES_INIT);
- PyModule_AddIntConstant(module, "DATASET_BYTES_GROWTH", (long) DATASET_BYTES_GROWTH);
- PyModule_AddIntConstant(module, "CACHE_BYTES_INIT", (long) CACHE_BYTES_INIT);
- PyModule_AddIntConstant(module, "CACHE_BYTES_GROWTH", (long) CACHE_BYTES_GROWTH);
- PyModule_AddIntConstant(module, "EPOCH_LENGTH", (long) EPOCH_LENGTH);
- PyModule_AddIntConstant(module, "MIX_BYTES", (long) MIX_BYTES);
- PyModule_AddIntConstant(module, "HASH_BYTES", (long) HASH_BYTES);
- PyModule_AddIntConstant(module, "DATASET_PARENTS", (long) DATASET_PARENTS);
- PyModule_AddIntConstant(module, "CACHE_ROUNDS", (long) CACHE_ROUNDS);
- PyModule_AddIntConstant(module, "ACCESSES", (long) ACCESSES);
+ PyModule_AddIntConstant(module, "REVISION", (long) ETHASH_REVISION);
+ PyModule_AddIntConstant(module, "DATASET_BYTES_INIT", (long) ETHASH_DATASET_BYTES_INIT);
+ PyModule_AddIntConstant(module, "DATASET_BYTES_GROWTH", (long) ETHASH_DATASET_BYTES_GROWTH);
+ PyModule_AddIntConstant(module, "CACHE_BYTES_INIT", (long) ETHASH_CACHE_BYTES_INIT);
+ PyModule_AddIntConstant(module, "CACHE_BYTES_GROWTH", (long) ETHASH_CACHE_BYTES_GROWTH);
+ PyModule_AddIntConstant(module, "EPOCH_LENGTH", (long) ETHASH_EPOCH_LENGTH);
+ PyModule_AddIntConstant(module, "MIX_BYTES", (long) ETHASH_MIX_BYTES);
+ PyModule_AddIntConstant(module, "HASH_BYTES", (long) ETHASH_HASH_BYTES);
+ PyModule_AddIntConstant(module, "DATASET_PARENTS", (long) ETHASH_DATASET_PARENTS);
+ PyModule_AddIntConstant(module, "CACHE_ROUNDS", (long) ETHASH_CACHE_ROUNDS);
+ PyModule_AddIntConstant(module, "ACCESSES", (long) ETHASH_ACCESSES);
}
#endif
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/CMakeLists.txt b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/CMakeLists.txt
index dd91d8a92..f94531c3d 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/CMakeLists.txt
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/CMakeLists.txt
@@ -27,13 +27,16 @@ IF( NOT Boost_FOUND )
find_package(Boost 1.48.0 COMPONENTS unit_test_framework system filesystem)
ENDIF()
-IF( Boost_FOUND )
+IF (Boost_FOUND)
+ message(STATUS "boost header: ${Boost_INCLUDE_DIRS}")
+ message(STATUS "boost libs : ${Boost_LIBRARIES}")
+
include_directories( ${Boost_INCLUDE_DIR} )
include_directories(../../src)
- link_directories ( ${Boost_LIBRARY_DIRS} )
+ link_directories(${Boost_LIBRARY_DIRS})
file(GLOB HEADERS "*.h")
- if (NOT MSVC)
+ if ((NOT MSVC) AND (NOT APPLE))
ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK)
endif()
if (NOT CRYPTOPP_FOUND)
@@ -48,11 +51,11 @@ IF( Boost_FOUND )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
endif()
- add_executable (Test test.cpp ${HEADERS})
+ add_executable (Test "./test.cpp" ${HEADERS})
target_link_libraries(Test ${ETHHASH_LIBS})
target_link_libraries(Test ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(Test ${Boost_SYSTEM_LIBRARIES})
- target_link_libraries (Test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ target_link_libraries(Test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
if (CRYPTOPP_FOUND)
TARGET_LINK_LIBRARIES(Test ${CRYPTOPP_LIBRARIES})
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp
index ffe8d53f3..55fe02316 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp
@@ -12,6 +12,11 @@
#include <libethash/sha3.h>
#endif // WITH_CRYPTOPP
+#ifdef _WIN32
+#include <windows.h>
+#include <Shlobj.h>
+#endif
+
#define BOOST_TEST_MODULE Daggerhashimoto
#define BOOST_TEST_MAIN
@@ -22,367 +27,609 @@
#include <boost/test/unit_test.hpp>
using namespace std;
+using byte = uint8_t;
+using bytes = std::vector<byte>;
namespace fs = boost::filesystem;
// Just an alloca "wrapper" to silence uint64_t to size_t conversion warnings in windows
// consider replacing alloca calls with something better though!
#define our_alloca(param__) alloca((size_t)(param__))
-std::string bytesToHexString(const uint8_t *str, const uint64_t s) {
- std::ostringstream ret;
- for (size_t i = 0; i < s; ++i)
- ret << std::hex << std::setfill('0') << std::setw(2) << std::nouppercase << (int) str[i];
+// some functions taken from eth::dev for convenience.
+std::string bytesToHexString(const uint8_t *str, const uint64_t s)
+{
+ std::ostringstream ret;
+
+ for (size_t i = 0; i < s; ++i)
+ ret << std::hex << std::setfill('0') << std::setw(2) << std::nouppercase << (int) str[i];
+
+ return ret.str();
+}
+
+std::string blockhashToHexString(ethash_h256_t* _hash)
+{
+ return bytesToHexString((uint8_t*)_hash, 32);
+}
- return ret.str();
+int fromHex(char _i)
+{
+ if (_i >= '0' && _i <= '9')
+ return _i - '0';
+ if (_i >= 'a' && _i <= 'f')
+ return _i - 'a' + 10;
+ if (_i >= 'A' && _i <= 'F')
+ return _i - 'A' + 10;
+
+ BOOST_REQUIRE_MESSAGE(false, "should never get here");
+ return -1;
}
-std::string blockhashToHexString(ethash_blockhash_t *hash) {
- return bytesToHexString((uint8_t*)hash, 32);
+bytes hexStringToBytes(std::string const& _s)
+{
+ unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0;
+ std::vector<uint8_t> ret;
+ ret.reserve((_s.size() - s + 1) / 2);
+
+ if (_s.size() % 2)
+ try
+ {
+ ret.push_back(fromHex(_s[s++]));
+ }
+ catch (...)
+ {
+ ret.push_back(0);
+ }
+ for (unsigned i = s; i < _s.size(); i += 2)
+ try
+ {
+ ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1])));
+ }
+ catch (...){
+ ret.push_back(0);
+ }
+ return ret;
}
+ethash_h256_t stringToBlockhash(std::string const& _s)
+{
+ ethash_h256_t ret;
+ bytes b = hexStringToBytes(_s);
+ memcpy(&ret, b.data(), b.size());
+ return ret;
+}
+
+
+
BOOST_AUTO_TEST_CASE(fnv_hash_check) {
- uint32_t x = 1235U;
- const uint32_t
- y = 9999999U,
- expected = (FNV_PRIME * x) ^y;
+ uint32_t x = 1235U;
+ const uint32_t
+ y = 9999999U,
+ expected = (FNV_PRIME * x) ^y;
- x = fnv_hash(x, y);
+ x = fnv_hash(x, y);
- BOOST_REQUIRE_MESSAGE(x == expected,
- "\nexpected: " << expected << "\n"
- << "actual: " << x << "\n");
+ BOOST_REQUIRE_MESSAGE(x == expected,
+ "\nexpected: " << expected << "\n"
+ << "actual: " << x << "\n");
}
BOOST_AUTO_TEST_CASE(SHA256_check) {
- ethash_blockhash_t input;
- ethash_blockhash_t out;
- memcpy(&input, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
- SHA3_256(&out, (uint8_t*)&input, 32);
- const std::string
- expected = "2b5ddf6f4d21c23de216f44d5e4bdc68e044b71897837ea74c83908be7037cd7",
- actual = bytesToHexString((uint8_t*)&out, 32);
- BOOST_REQUIRE_MESSAGE(expected == actual,
- "\nexpected: " << expected.c_str() << "\n"
- << "actual: " << actual.c_str() << "\n");
+ ethash_h256_t input;
+ ethash_h256_t out;
+ memcpy(&input, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+ SHA3_256(&out, (uint8_t*)&input, 32);
+ const std::string
+ expected = "2b5ddf6f4d21c23de216f44d5e4bdc68e044b71897837ea74c83908be7037cd7",
+ actual = bytesToHexString((uint8_t*)&out, 32);
+ BOOST_REQUIRE_MESSAGE(expected == actual,
+ "\nexpected: " << expected.c_str() << "\n"
+ << "actual: " << actual.c_str() << "\n");
}
BOOST_AUTO_TEST_CASE(SHA512_check) {
- uint8_t input[64], out[64];
- memcpy(input, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 64);
- SHA3_512(out, input, 64);
- const std::string
- expected = "0be8a1d334b4655fe58c6b38789f984bb13225684e86b20517a55ab2386c7b61c306f25e0627c60064cecd6d80cd67a82b3890bd1289b7ceb473aad56a359405",
- actual = bytesToHexString(out, 64);
- BOOST_REQUIRE_MESSAGE(expected == actual,
- "\nexpected: " << expected.c_str() << "\n"
- << "actual: " << actual.c_str() << "\n");
+ uint8_t input[64], out[64];
+ memcpy(input, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 64);
+ SHA3_512(out, input, 64);
+ const std::string
+ expected = "0be8a1d334b4655fe58c6b38789f984bb13225684e86b20517a55ab2386c7b61c306f25e0627c60064cecd6d80cd67a82b3890bd1289b7ceb473aad56a359405",
+ actual = bytesToHexString(out, 64);
+ BOOST_REQUIRE_MESSAGE(expected == actual,
+ "\nexpected: " << expected.c_str() << "\n"
+ << "actual: " << actual.c_str() << "\n");
+}
+
+BOOST_AUTO_TEST_CASE(test_swap_endian32) {
+ uint32_t v32 = (uint32_t)0xBAADF00D;
+ v32 = ethash_swap_u32(v32);
+ BOOST_REQUIRE_EQUAL(v32, (uint32_t)0x0DF0ADBA);
+}
+
+BOOST_AUTO_TEST_CASE(test_swap_endian64) {
+ uint64_t v64 = (uint64_t)0xFEE1DEADDEADBEEF;
+ v64 = ethash_swap_u64(v64);
+ BOOST_REQUIRE_EQUAL(v64, (uint64_t)0xEFBEADDEADDEE1FE);
}
BOOST_AUTO_TEST_CASE(ethash_params_init_genesis_check) {
- ethash_params params;
- ethash_params_init(&params, 0);
- BOOST_REQUIRE_MESSAGE(params.full_size < DATASET_BYTES_INIT,
- "\nfull size: " << params.full_size << "\n"
- << "should be less than or equal to: " << DATASET_BYTES_INIT << "\n");
- BOOST_REQUIRE_MESSAGE(params.full_size + 20 * MIX_BYTES >= DATASET_BYTES_INIT,
- "\nfull size + 20*MIX_BYTES: " << params.full_size + 20 * MIX_BYTES << "\n"
- << "should be greater than or equal to: " << DATASET_BYTES_INIT << "\n");
- BOOST_REQUIRE_MESSAGE(params.cache_size < DATASET_BYTES_INIT / 32,
- "\ncache size: " << params.cache_size << "\n"
- << "should be less than or equal to: " << DATASET_BYTES_INIT / 32 << "\n");
+ uint64_t full_size = ethash_get_datasize(0);
+ uint64_t cache_size = ethash_get_cachesize(0);
+ BOOST_REQUIRE_MESSAGE(full_size < ETHASH_DATASET_BYTES_INIT,
+ "\nfull size: " << full_size << "\n"
+ << "should be less than or equal to: " << ETHASH_DATASET_BYTES_INIT << "\n");
+ BOOST_REQUIRE_MESSAGE(full_size + 20 * ETHASH_MIX_BYTES >= ETHASH_DATASET_BYTES_INIT,
+ "\nfull size + 20*MIX_BYTES: " << full_size + 20 * ETHASH_MIX_BYTES << "\n"
+ << "should be greater than or equal to: " << ETHASH_DATASET_BYTES_INIT << "\n");
+ BOOST_REQUIRE_MESSAGE(cache_size < ETHASH_DATASET_BYTES_INIT / 32,
+ "\ncache size: " << cache_size << "\n"
+ << "should be less than or equal to: " << ETHASH_DATASET_BYTES_INIT / 32 << "\n");
}
BOOST_AUTO_TEST_CASE(ethash_params_init_genesis_calcifide_check) {
- ethash_params params;
- ethash_params_init(&params, 0);
- const uint32_t expected_full_size = 1073739904;
- const uint32_t expected_cache_size = 16776896;
- BOOST_REQUIRE_MESSAGE(params.full_size == expected_full_size,
- "\nexpected: " << expected_cache_size << "\n"
- << "actual: " << params.full_size << "\n");
- BOOST_REQUIRE_MESSAGE(params.cache_size == expected_cache_size,
- "\nexpected: " << expected_cache_size << "\n"
- << "actual: " << params.cache_size << "\n");
+ uint64_t full_size = ethash_get_datasize(0);
+ uint64_t cache_size = ethash_get_cachesize(0);
+ const uint32_t expected_full_size = 1073739904;
+ const uint32_t expected_cache_size = 16776896;
+ BOOST_REQUIRE_MESSAGE(full_size == expected_full_size,
+ "\nexpected: " << expected_cache_size << "\n"
+ << "actual: " << full_size << "\n");
+ BOOST_REQUIRE_MESSAGE(cache_size == expected_cache_size,
+ "\nexpected: " << expected_cache_size << "\n"
+ << "actual: " << cache_size << "\n");
}
-BOOST_AUTO_TEST_CASE(light_and_full_client_checks) {
- ethash_params params;
- ethash_blockhash_t seed;
- ethash_blockhash_t hash;
- ethash_blockhash_t difficulty;
- ethash_return_value light_out;
- ethash_return_value full_out;
- memcpy(&seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
- memcpy(&hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
-
- // Set the difficulty
- ethash_blockhash_set(&difficulty, 0, 197);
- ethash_blockhash_set(&difficulty, 1, 90);
- for (int i = 2; i < 32; i++)
- ethash_blockhash_set(&difficulty, i, 255);
-
- ethash_params_init(&params, 0);
- params.cache_size = 1024;
- params.full_size = 1024 * 32;
- ethash_cache cache;
- cache.mem = our_alloca(params.cache_size);
- ethash_mkcache(&cache, &params, &seed);
- node *full_mem = (node *) our_alloca(params.full_size);
- ethash_compute_full_data(full_mem, &params, &cache);
-
- {
- const std::string
- expected = "2da2b506f21070e1143d908e867962486d6b0a02e31d468fd5e3a7143aafa76a14201f63374314e2a6aaf84ad2eb57105dea3378378965a1b3873453bb2b78f9a8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995c259440b89fa3481c2c33171477c305c8e1e421f8d8f6d59585449d0034f3e421808d8da6bbd0b6378f567647cc6c4ba6c434592b198ad444e7284905b7c6adaf70bf43ec2daa7bd5e8951aa609ab472c124cf9eba3d38cff5091dc3f58409edcc386c743c3bd66f92408796ee1e82dd149eaefbf52b00ce33014a6eb3e50625413b072a58bc01da28262f42cbe4f87d4abc2bf287d15618405a1fe4e386fcdafbb171064bd99901d8f81dd6789396ce5e364ac944bbbd75a7827291c70b42d26385910cd53ca535ab29433dd5c5714d26e0dce95514c5ef866329c12e958097e84462197c2b32087849dab33e88b11da61d52f9dbc0b92cc61f742c07dbbf751c49d7678624ee60dfbe62e5e8c47a03d8247643f3d16ad8c8e663953bcda1f59d7e2d4a9bf0768e789432212621967a8f41121ad1df6ae1fa78782530695414c6213942865b2730375019105cae91a4c17a558d4b63059661d9f108362143107babe0b848de412e4da59168cce82bfbff3c99e022dd6ac1e559db991f2e3f7bb910cefd173e65ed00a8d5d416534e2c8416ff23977dbf3eb7180b75c71580d08ce95efeb9b0afe904ea12285a392aff0c8561ff79fca67f694a62b9e52377485c57cc3598d84cac0a9d27960de0cc31ff9bbfe455acaa62c8aa5d2cce96f345da9afe843d258a99c4eaf3650fc62efd81c7b81cd0d534d2d71eeda7a6e315d540b4473c80f8730037dc2ae3e47b986240cfc65ccc565f0d8cde0bc68a57e39a271dda57440b3598bee19f799611d25731a96b5dbbbefdff6f4f656161462633030d62560ea4e9c161cf78fc96a2ca5aaa32453a6c5dea206f766244e8c9d9a8dc61185ce37f1fc804459c5f07434f8ecb34141b8dcae7eae704c950b55556c5f40140c3714b45eddb02637513268778cbf937a33e4e33183685f9deb31ef54e90161e76d969587dd782eaa94e289420e7c2ee908517f5893a26fdb5873d68f92d118d4bcf98d7a4916794d6ab290045e30f9ea00ca547c584b8482b0331ba1539a0f2714fddc3a0b06b0cfbb6a607b8339c39bcfd6640b1f653e9d70ef6c985b",
- actual = bytesToHexString((uint8_t const *) cache.mem, params.cache_size);
-
- BOOST_REQUIRE_MESSAGE(expected == actual,
- "\nexpected: " << expected.c_str() << "\n"
- << "actual: " << actual.c_str() << "\n");
- }
-
-
- {
- node node;
- ethash_calculate_dag_item(&node, 0, &params, &cache);
- const std::string
- actual = bytesToHexString((uint8_t const *) &node, sizeof(node)),
- expected = "b1698f829f90b35455804e5185d78f549fcb1bdce2bee006d4d7e68eb154b596be1427769eb1c3c3e93180c760af75f81d1023da6a0ffbe321c153a7c0103597";
- BOOST_REQUIRE_MESSAGE(actual == expected,
- "\n" << "expected: " << expected.c_str() << "\n"
- << "actual: " << actual.c_str() << "\n");
- }
-
- {
- for (int i = 0; i < params.full_size / sizeof(node); ++i) {
- for (uint32_t j = 0; j < 32; ++j) {
- node expected_node;
- ethash_calculate_dag_item(&expected_node, j, &params, &cache);
- const std::string
- actual = bytesToHexString((uint8_t const *) &(full_mem[j]), sizeof(node)),
- expected = bytesToHexString((uint8_t const *) &expected_node, sizeof(node));
- BOOST_REQUIRE_MESSAGE(actual == expected,
- "\ni: " << j << "\n"
- << "expected: " << expected.c_str() << "\n"
- << "actual: " << actual.c_str() << "\n");
- }
- }
- }
-
- {
- uint64_t nonce = 0x7c7c597c;
- ethash_full(&full_out, full_mem, &params, &hash, nonce);
- ethash_light(&light_out, &cache, &params, &hash, nonce);
- const std::string
- light_result_string = blockhashToHexString(&light_out.result),
- full_result_string = blockhashToHexString(&full_out.result);
- BOOST_REQUIRE_MESSAGE(light_result_string == full_result_string,
- "\nlight result: " << light_result_string.c_str() << "\n"
- << "full result: " << full_result_string.c_str() << "\n");
- const std::string
- light_mix_hash_string = blockhashToHexString(&light_out.mix_hash),
- full_mix_hash_string = blockhashToHexString(&full_out.mix_hash);
- BOOST_REQUIRE_MESSAGE(full_mix_hash_string == light_mix_hash_string,
- "\nlight mix hash: " << light_mix_hash_string.c_str() << "\n"
- << "full mix hash: " << full_mix_hash_string.c_str() << "\n");
- ethash_blockhash_t check_hash;
- ethash_quick_hash(&check_hash, &hash, nonce, &full_out.mix_hash);
- const std::string check_hash_string = blockhashToHexString(&check_hash);
- BOOST_REQUIRE_MESSAGE(check_hash_string == full_result_string,
- "\ncheck hash string: " << check_hash_string.c_str() << "\n"
- << "full result: " << full_result_string.c_str() << "\n");
- }
- {
- ethash_full(&full_out, full_mem, &params, &hash, 5);
- std::string
- light_result_string = blockhashToHexString(&light_out.result),
- full_result_string = blockhashToHexString(&full_out.result);
-
- BOOST_REQUIRE_MESSAGE(light_result_string != full_result_string,
- "\nlight result and full result should differ: " << light_result_string.c_str() << "\n");
-
- ethash_light(&light_out, &cache, &params, &hash, 5);
- light_result_string = blockhashToHexString(&light_out.result);
- BOOST_REQUIRE_MESSAGE(light_result_string == full_result_string,
- "\nlight result and full result should be the same\n"
- << "light result: " << light_result_string.c_str() << "\n"
- << "full result: " << full_result_string.c_str() << "\n");
- std::string
- light_mix_hash_string = blockhashToHexString(&light_out.mix_hash),
- full_mix_hash_string = blockhashToHexString(&full_out.mix_hash);
- BOOST_REQUIRE_MESSAGE(full_mix_hash_string == light_mix_hash_string,
- "\nlight mix hash: " << light_mix_hash_string.c_str() << "\n"
- << "full mix hash: " << full_mix_hash_string.c_str() << "\n");
- BOOST_REQUIRE_MESSAGE(ethash_check_difficulty(&full_out.result, &difficulty),
- "ethash_check_difficulty failed"
- );
- BOOST_REQUIRE_MESSAGE(ethash_quick_check_difficulty(&hash, 5U, &full_out.mix_hash, &difficulty),
- "ethash_quick_check_difficulty failed"
- );
- }
+BOOST_AUTO_TEST_CASE(ethash_check_difficulty_check) {
+ ethash_h256_t hash;
+ ethash_h256_t target;
+ memcpy(&hash, "11111111111111111111111111111111", 32);
+ memcpy(&target, "22222222222222222222222222222222", 32);
+ BOOST_REQUIRE_MESSAGE(
+ ethash_check_difficulty(&hash, &target),
+ "\nexpected \"" << std::string((char *) &hash, 32).c_str() << "\" to have the same or less difficulty than \"" << std::string((char *) &target, 32).c_str() << "\"\n");
+ BOOST_REQUIRE_MESSAGE(
+ ethash_check_difficulty(&hash, &hash), "");
+ // "\nexpected \"" << hash << "\" to have the same or less difficulty than \"" << hash << "\"\n");
+ memcpy(&target, "11111111111111111111111111111112", 32);
+ BOOST_REQUIRE_MESSAGE(
+ ethash_check_difficulty(&hash, &target), "");
+ // "\nexpected \"" << hash << "\" to have the same or less difficulty than \"" << target << "\"\n");
+ memcpy(&target, "11111111111111111111111111111110", 32);
+ BOOST_REQUIRE_MESSAGE(
+ !ethash_check_difficulty(&hash, &target), "");
+ // "\nexpected \"" << hash << "\" to have more difficulty than \"" << target << "\"\n");
}
-BOOST_AUTO_TEST_CASE(ethash_check_difficulty_check) {
- ethash_blockhash_t hash;
- ethash_blockhash_t target;
- memcpy(&hash, "11111111111111111111111111111111", 32);
- memcpy(&target, "22222222222222222222222222222222", 32);
- BOOST_REQUIRE_MESSAGE(
- ethash_check_difficulty(&hash, &target),
- "\nexpected \"" << std::string((char *) &hash, 32).c_str() << "\" to have the same or less difficulty than \"" << std::string((char *) &target, 32).c_str() << "\"\n");
- BOOST_REQUIRE_MESSAGE(
- ethash_check_difficulty(&hash, &hash), "");
- // "\nexpected \"" << hash << "\" to have the same or less difficulty than \"" << hash << "\"\n");
- memcpy(&target, "11111111111111111111111111111112", 32);
- BOOST_REQUIRE_MESSAGE(
- ethash_check_difficulty(&hash, &target), "");
- // "\nexpected \"" << hash << "\" to have the same or less difficulty than \"" << target << "\"\n");
- memcpy(&target, "11111111111111111111111111111110", 32);
- BOOST_REQUIRE_MESSAGE(
- !ethash_check_difficulty(&hash, &target), "");
- // "\nexpected \"" << hash << "\" to have more difficulty than \"" << target << "\"\n");
+BOOST_AUTO_TEST_CASE(test_ethash_io_mutable_name) {
+ char mutable_name[DAG_MUTABLE_NAME_MAX_SIZE];
+ // should have at least 8 bytes provided since this is what we test :)
+ ethash_h256_t seed1 = ethash_h256_static_init(0, 10, 65, 255, 34, 55, 22, 8);
+ ethash_io_mutable_name(1, &seed1, mutable_name);
+ BOOST_REQUIRE_EQUAL(0, strcmp(mutable_name, "1_000a41ff22371608"));
+ ethash_h256_t seed2 = ethash_h256_static_init(0, 0, 0, 0, 0, 0, 0, 0);
+ ethash_io_mutable_name(44, &seed2, mutable_name);
+ BOOST_REQUIRE_EQUAL(0, strcmp(mutable_name, "44_0000000000000000"));
}
BOOST_AUTO_TEST_CASE(test_ethash_dir_creation) {
- ethash_blockhash_t seedhash;
- memset(&seedhash, 0, 32);
- BOOST_REQUIRE_EQUAL(
- ETHASH_IO_MEMO_MISMATCH,
- ethash_io_prepare("./test_ethash_directory/", seedhash)
- );
-
- // let's make sure that the directory was created
- BOOST_REQUIRE(fs::is_directory(fs::path("./test_ethash_directory/")));
-
- // cleanup
- fs::remove_all("./test_ethash_directory/");
+ ethash_h256_t seedhash;
+ FILE *f = NULL;
+ memset(&seedhash, 0, 32);
+ BOOST_REQUIRE_EQUAL(
+ ETHASH_IO_MEMO_MISMATCH,
+ ethash_io_prepare("./test_ethash_directory/", seedhash, &f, 64, false)
+ );
+ BOOST_REQUIRE(f);
+
+ // let's make sure that the directory was created
+ BOOST_REQUIRE(fs::is_directory(fs::path("./test_ethash_directory/")));
+
+ // cleanup
+ fclose(f);
+ fs::remove_all("./test_ethash_directory/");
+}
+
+BOOST_AUTO_TEST_CASE(test_ethash_io_memo_file_match) {
+ uint64_t full_size;
+ uint64_t cache_size;
+ ethash_h256_t seed;
+ ethash_h256_t hash;
+ FILE* f;
+ memcpy(&seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+ memcpy(&hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+
+ cache_size = 1024;
+ full_size = 1024 * 32;
+
+ ethash_light_t light = ethash_light_new_internal(cache_size, &seed);
+ ethash_full_t full = ethash_full_new_internal(
+ "./test_ethash_directory/",
+ seed,
+ full_size,
+ light,
+ NULL
+ );
+ BOOST_ASSERT(full);
+ // let's make sure that the directory was created
+ BOOST_REQUIRE(fs::is_directory(fs::path("./test_ethash_directory/")));
+ // delete the full here so that memory is properly unmapped and FILE handler freed
+ ethash_full_delete(full);
+ // and check that we have a match when checking again
+ BOOST_REQUIRE_EQUAL(
+ ETHASH_IO_MEMO_MATCH,
+ ethash_io_prepare("./test_ethash_directory/", seed, &f, full_size, false)
+ );
+ BOOST_REQUIRE(f);
+
+ // cleanup
+ fclose(f);
+ ethash_light_delete(light);
+ fs::remove_all("./test_ethash_directory/");
}
-BOOST_AUTO_TEST_CASE(test_ethash_io_write_files_are_created) {
- ethash_blockhash_t seedhash;
- static const int blockn = 0;
- ethash_get_seedhash(&seedhash, blockn);
- BOOST_REQUIRE_EQUAL(
- ETHASH_IO_MEMO_MISMATCH,
- ethash_io_prepare("./test_ethash_directory/", seedhash)
- );
-
- // let's make sure that the directory was created
- BOOST_REQUIRE(fs::is_directory(fs::path("./test_ethash_directory/")));
-
- ethash_cache cache;
- ethash_params params;
- uint8_t *data;
- uint64_t size;
- ethash_params_init(&params, blockn);
- params.cache_size = 1024;
- params.full_size = 1024 * 32;
- cache.mem = our_alloca(params.cache_size);
- ethash_mkcache(&cache, &params, &seedhash);
-
- BOOST_REQUIRE(
- ethash_io_write("./test_ethash_directory/", &params, seedhash, &cache, &data, &size)
- );
-
- BOOST_REQUIRE(fs::exists(fs::path("./test_ethash_directory/full")));
- BOOST_REQUIRE(fs::exists(fs::path("./test_ethash_directory/full.info")));
-
- // cleanup
- fs::remove_all("./test_ethash_directory/");
- free(data);
+BOOST_AUTO_TEST_CASE(test_ethash_io_memo_file_size_mismatch) {
+ static const int blockn = 0;
+ ethash_h256_t seedhash = ethash_get_seedhash(blockn);
+ FILE *f = NULL;
+ BOOST_REQUIRE_EQUAL(
+ ETHASH_IO_MEMO_MISMATCH,
+ ethash_io_prepare("./test_ethash_directory/", seedhash, &f, 64, false)
+ );
+ BOOST_REQUIRE(f);
+ fclose(f);
+
+ // let's make sure that the directory was created
+ BOOST_REQUIRE(fs::is_directory(fs::path("./test_ethash_directory/")));
+ // and check that we get the size mismatch detected if we request diffferent size
+ BOOST_REQUIRE_EQUAL(
+ ETHASH_IO_MEMO_SIZE_MISMATCH,
+ ethash_io_prepare("./test_ethash_directory/", seedhash, &f, 65, false)
+ );
+
+ // cleanup
+ fs::remove_all("./test_ethash_directory/");
}
-BOOST_AUTO_TEST_CASE(test_ethash_io_memo_file_match) {
- ethash_blockhash_t seedhash;
- static const int blockn = 0;
- ethash_get_seedhash(&seedhash, blockn);
- BOOST_REQUIRE_EQUAL(
- ETHASH_IO_MEMO_MISMATCH,
- ethash_io_prepare("./test_ethash_directory/", seedhash)
- );
-
- // let's make sure that the directory was created
- BOOST_REQUIRE(fs::is_directory(fs::path("./test_ethash_directory/")));
-
- ethash_cache cache;
- ethash_params params;
- uint8_t *data;
- uint64_t size;
- ethash_params_init(&params, blockn);
- params.cache_size = 1024;
- params.full_size = 1024 * 32;
- cache.mem = our_alloca(params.cache_size);
- ethash_mkcache(&cache, &params, &seedhash);
-
- BOOST_REQUIRE(
- ethash_io_write("./test_ethash_directory/", &params, seedhash, &cache, &data, &size)
- );
-
- BOOST_REQUIRE(fs::exists(fs::path("./test_ethash_directory/full")));
- BOOST_REQUIRE(fs::exists(fs::path("./test_ethash_directory/full.info")));
-
- BOOST_REQUIRE_EQUAL(
- ETHASH_IO_MEMO_MATCH,
- ethash_io_prepare("./test_ethash_directory/", seedhash)
- );
-
- // cleanup
- fs::remove_all("./test_ethash_directory/");
- free(data);
+BOOST_AUTO_TEST_CASE(test_ethash_get_default_dirname) {
+ char result[256];
+ // this is really not an easy thing to test for in a unit test, so yeah it does look ugly
+#ifdef _WIN32
+ char homedir[256];
+ BOOST_REQUIRE(SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)homedir)));
+ BOOST_REQUIRE(ethash_get_default_dirname(result, 256));
+ std::string res = std::string(homedir) + std::string("\\Appdata\\Ethash\\");
+#else
+ char* homedir = getenv("HOME");
+ BOOST_REQUIRE(ethash_get_default_dirname(result, 256));
+ std::string res = std::string(homedir) + std::string("/.ethash/");
+#endif
+ BOOST_CHECK_MESSAGE(strcmp(res.c_str(), result) == 0,
+ "Expected \"" + res + "\" but got \"" + std::string(result) + "\""
+ );
+}
+
+BOOST_AUTO_TEST_CASE(light_and_full_client_checks) {
+ uint64_t full_size;
+ uint64_t cache_size;
+ ethash_h256_t seed;
+ ethash_h256_t hash;
+ ethash_h256_t difficulty;
+ ethash_return_value_t light_out;
+ ethash_return_value_t full_out;
+ memcpy(&seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+ memcpy(&hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+
+ // Set the difficulty
+ ethash_h256_set(&difficulty, 0, 197);
+ ethash_h256_set(&difficulty, 1, 90);
+ for (int i = 2; i < 32; i++)
+ ethash_h256_set(&difficulty, i, 255);
+
+ cache_size = 1024;
+ full_size = 1024 * 32;
+
+ ethash_light_t light = ethash_light_new_internal(cache_size, &seed);
+ ethash_full_t full = ethash_full_new_internal(
+ "./test_ethash_directory/",
+ seed,
+ full_size,
+ light,
+ NULL
+ );
+ BOOST_ASSERT(full);
+ {
+ const std::string
+ expected = "2da2b506f21070e1143d908e867962486d6b0a02e31d468fd5e3a7143aafa76a14201f63374314e2a6aaf84ad2eb57105dea3378378965a1b3873453bb2b78f9a8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995c259440b89fa3481c2c33171477c305c8e1e421f8d8f6d59585449d0034f3e421808d8da6bbd0b6378f567647cc6c4ba6c434592b198ad444e7284905b7c6adaf70bf43ec2daa7bd5e8951aa609ab472c124cf9eba3d38cff5091dc3f58409edcc386c743c3bd66f92408796ee1e82dd149eaefbf52b00ce33014a6eb3e50625413b072a58bc01da28262f42cbe4f87d4abc2bf287d15618405a1fe4e386fcdafbb171064bd99901d8f81dd6789396ce5e364ac944bbbd75a7827291c70b42d26385910cd53ca535ab29433dd5c5714d26e0dce95514c5ef866329c12e958097e84462197c2b32087849dab33e88b11da61d52f9dbc0b92cc61f742c07dbbf751c49d7678624ee60dfbe62e5e8c47a03d8247643f3d16ad8c8e663953bcda1f59d7e2d4a9bf0768e789432212621967a8f41121ad1df6ae1fa78782530695414c6213942865b2730375019105cae91a4c17a558d4b63059661d9f108362143107babe0b848de412e4da59168cce82bfbff3c99e022dd6ac1e559db991f2e3f7bb910cefd173e65ed00a8d5d416534e2c8416ff23977dbf3eb7180b75c71580d08ce95efeb9b0afe904ea12285a392aff0c8561ff79fca67f694a62b9e52377485c57cc3598d84cac0a9d27960de0cc31ff9bbfe455acaa62c8aa5d2cce96f345da9afe843d258a99c4eaf3650fc62efd81c7b81cd0d534d2d71eeda7a6e315d540b4473c80f8730037dc2ae3e47b986240cfc65ccc565f0d8cde0bc68a57e39a271dda57440b3598bee19f799611d25731a96b5dbbbefdff6f4f656161462633030d62560ea4e9c161cf78fc96a2ca5aaa32453a6c5dea206f766244e8c9d9a8dc61185ce37f1fc804459c5f07434f8ecb34141b8dcae7eae704c950b55556c5f40140c3714b45eddb02637513268778cbf937a33e4e33183685f9deb31ef54e90161e76d969587dd782eaa94e289420e7c2ee908517f5893a26fdb5873d68f92d118d4bcf98d7a4916794d6ab290045e30f9ea00ca547c584b8482b0331ba1539a0f2714fddc3a0b06b0cfbb6a607b8339c39bcfd6640b1f653e9d70ef6c985b",
+ actual = bytesToHexString((uint8_t const *) light->cache, cache_size);
+
+ BOOST_REQUIRE_MESSAGE(expected == actual,
+ "\nexpected: " << expected.c_str() << "\n"
+ << "actual: " << actual.c_str() << "\n");
+ }
+ {
+ node node;
+ ethash_calculate_dag_item(&node, 0, light);
+ const std::string
+ actual = bytesToHexString((uint8_t const *) &node, sizeof(node)),
+ expected = "b1698f829f90b35455804e5185d78f549fcb1bdce2bee006d4d7e68eb154b596be1427769eb1c3c3e93180c760af75f81d1023da6a0ffbe321c153a7c0103597";
+ BOOST_REQUIRE_MESSAGE(actual == expected,
+ "\n" << "expected: " << expected.c_str() << "\n"
+ << "actual: " << actual.c_str() << "\n");
+ }
+ {
+ for (int i = 0; i < full_size / sizeof(node); ++i) {
+ for (uint32_t j = 0; j < 32; ++j) {
+ node expected_node;
+ ethash_calculate_dag_item(&expected_node, j, light);
+ const std::string
+ actual = bytesToHexString((uint8_t const *) &(full->data[j]), sizeof(node)),
+ expected = bytesToHexString((uint8_t const *) &expected_node, sizeof(node));
+ BOOST_REQUIRE_MESSAGE(actual == expected,
+ "\ni: " << j << "\n"
+ << "expected: " << expected.c_str() << "\n"
+ << "actual: " << actual.c_str() << "\n");
+ }
+ }
+ }
+ {
+ uint64_t nonce = 0x7c7c597c;
+ full_out = ethash_full_compute(full, hash, nonce);
+ BOOST_REQUIRE(full_out.success);
+ light_out = ethash_light_compute_internal(light, full_size, hash, nonce);
+ BOOST_REQUIRE(light_out.success);
+ const std::string
+ light_result_string = blockhashToHexString(&light_out.result),
+ full_result_string = blockhashToHexString(&full_out.result);
+ BOOST_REQUIRE_MESSAGE(light_result_string == full_result_string,
+ "\nlight result: " << light_result_string.c_str() << "\n"
+ << "full result: " << full_result_string.c_str() << "\n");
+ const std::string
+ light_mix_hash_string = blockhashToHexString(&light_out.mix_hash),
+ full_mix_hash_string = blockhashToHexString(&full_out.mix_hash);
+ BOOST_REQUIRE_MESSAGE(full_mix_hash_string == light_mix_hash_string,
+ "\nlight mix hash: " << light_mix_hash_string.c_str() << "\n"
+ << "full mix hash: " << full_mix_hash_string.c_str() << "\n");
+ ethash_h256_t check_hash;
+ ethash_quick_hash(&check_hash, &hash, nonce, &full_out.mix_hash);
+ const std::string check_hash_string = blockhashToHexString(&check_hash);
+ BOOST_REQUIRE_MESSAGE(check_hash_string == full_result_string,
+ "\ncheck hash string: " << check_hash_string.c_str() << "\n"
+ << "full result: " << full_result_string.c_str() << "\n");
+ }
+ {
+ full_out = ethash_full_compute(full, hash, 5);
+ BOOST_REQUIRE(full_out.success);
+ std::string
+ light_result_string = blockhashToHexString(&light_out.result),
+ full_result_string = blockhashToHexString(&full_out.result);
+ BOOST_REQUIRE_MESSAGE(light_result_string != full_result_string,
+ "\nlight result and full result should differ: " << light_result_string.c_str() << "\n");
+
+ light_out = ethash_light_compute_internal(light, full_size, hash, 5);
+ BOOST_REQUIRE(light_out.success);
+ light_result_string = blockhashToHexString(&light_out.result);
+ BOOST_REQUIRE_MESSAGE(light_result_string == full_result_string,
+ "\nlight result and full result should be the same\n"
+ << "light result: " << light_result_string.c_str() << "\n"
+ << "full result: " << full_result_string.c_str() << "\n");
+ std::string
+ light_mix_hash_string = blockhashToHexString(&light_out.mix_hash),
+ full_mix_hash_string = blockhashToHexString(&full_out.mix_hash);
+ BOOST_REQUIRE_MESSAGE(full_mix_hash_string == light_mix_hash_string,
+ "\nlight mix hash: " << light_mix_hash_string.c_str() << "\n"
+ << "full mix hash: " << full_mix_hash_string.c_str() << "\n");
+ BOOST_REQUIRE_MESSAGE(ethash_check_difficulty(&full_out.result, &difficulty),
+ "ethash_check_difficulty failed"
+ );
+ BOOST_REQUIRE_MESSAGE(ethash_quick_check_difficulty(&hash, 5U, &full_out.mix_hash, &difficulty),
+ "ethash_quick_check_difficulty failed"
+ );
+ }
+ ethash_light_delete(light);
+ ethash_full_delete(full);
+ fs::remove_all("./test_ethash_directory/");
+}
+
+BOOST_AUTO_TEST_CASE(ethash_full_new_when_dag_exists_with_wrong_size) {
+ uint64_t full_size;
+ uint64_t cache_size;
+ ethash_h256_t seed;
+ ethash_h256_t hash;
+ ethash_return_value_t full_out;
+ ethash_return_value_t light_out;
+ memcpy(&seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+ memcpy(&hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+
+ cache_size = 1024;
+ full_size = 1024 * 32;
+
+ // first make a DAG file of "wrong size"
+ FILE *f;
+ BOOST_REQUIRE_EQUAL(
+ ETHASH_IO_MEMO_MISMATCH,
+ ethash_io_prepare("./test_ethash_directory/", seed, &f, 64, false)
+ );
+ fclose(f);
+
+ // then create new DAG, which should detect the wrong size and force create a new file
+ ethash_light_t light = ethash_light_new_internal(cache_size, &seed);
+ BOOST_ASSERT(light);
+ ethash_full_t full = ethash_full_new_internal(
+ "./test_ethash_directory/",
+ seed,
+ full_size,
+ light,
+ NULL
+ );
+ BOOST_ASSERT(full);
+ {
+ uint64_t nonce = 0x7c7c597c;
+ full_out = ethash_full_compute(full, hash, nonce);
+ BOOST_REQUIRE(full_out.success);
+ light_out = ethash_light_compute_internal(light, full_size, hash, nonce);
+ BOOST_REQUIRE(light_out.success);
+ const std::string
+ light_result_string = blockhashToHexString(&light_out.result),
+ full_result_string = blockhashToHexString(&full_out.result);
+ BOOST_REQUIRE_MESSAGE(light_result_string == full_result_string,
+ "\nlight result: " << light_result_string.c_str() << "\n"
+ << "full result: " << full_result_string.c_str() << "\n");
+ const std::string
+ light_mix_hash_string = blockhashToHexString(&light_out.mix_hash),
+ full_mix_hash_string = blockhashToHexString(&full_out.mix_hash);
+ BOOST_REQUIRE_MESSAGE(full_mix_hash_string == light_mix_hash_string,
+ "\nlight mix hash: " << light_mix_hash_string.c_str() << "\n"
+ << "full mix hash: " << full_mix_hash_string.c_str() << "\n");
+ ethash_h256_t check_hash;
+ ethash_quick_hash(&check_hash, &hash, nonce, &full_out.mix_hash);
+ const std::string check_hash_string = blockhashToHexString(&check_hash);
+ BOOST_REQUIRE_MESSAGE(check_hash_string == full_result_string,
+ "\ncheck hash string: " << check_hash_string.c_str() << "\n"
+ << "full result: " << full_result_string.c_str() << "\n");
+ }
+
+ ethash_light_delete(light);
+ ethash_full_delete(full);
+ fs::remove_all("./test_ethash_directory/");
}
-// could have used dev::contentsNew but don't wanna try to import
-// libdevcore just for one function
-static std::vector<char> readFileIntoVector(char const* filename)
+static bool g_executed = false;
+static unsigned g_prev_progress = 0;
+static int test_full_callback(unsigned _progress)
{
- ifstream ifs(filename, ios::binary|ios::ate);
- ifstream::pos_type pos = ifs.tellg();
+ g_executed = true;
+ BOOST_CHECK(_progress >= g_prev_progress);
+ g_prev_progress = _progress;
+ return 0;
+}
- std::vector<char> result((unsigned int)pos);
+static int test_full_callback_that_fails(unsigned _progress)
+{
+ return 1;
+}
- ifs.seekg(0, ios::beg);
- ifs.read(&result[0], pos);
+static int test_full_callback_create_incomplete_dag(unsigned _progress)
+{
+ if (_progress >= 30) {
+ return 1;
+ }
+ return 0;
+}
+
+BOOST_AUTO_TEST_CASE(full_client_callback) {
+ uint64_t full_size;
+ uint64_t cache_size;
+ ethash_h256_t seed;
+ ethash_h256_t hash;
+ memcpy(&seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+ memcpy(&hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+
+ cache_size = 1024;
+ full_size = 1024 * 32;
+
+ ethash_light_t light = ethash_light_new_internal(cache_size, &seed);
+ ethash_full_t full = ethash_full_new_internal(
+ "./test_ethash_directory/",
+ seed,
+ full_size,
+ light,
+ test_full_callback
+ );
+ BOOST_ASSERT(full);
+ BOOST_CHECK(g_executed);
+ BOOST_REQUIRE_EQUAL(g_prev_progress, 100);
+
+ ethash_full_delete(full);
+ ethash_light_delete(light);
+ fs::remove_all("./test_ethash_directory/");
+}
+
+BOOST_AUTO_TEST_CASE(failing_full_client_callback) {
+ uint64_t full_size;
+ uint64_t cache_size;
+ ethash_h256_t seed;
+ ethash_h256_t hash;
+ memcpy(&seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+ memcpy(&hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+
+ cache_size = 1024;
+ full_size = 1024 * 32;
+
+ ethash_light_t light = ethash_light_new_internal(cache_size, &seed);
+ ethash_full_t full = ethash_full_new_internal(
+ "./test_ethash_directory/",
+ seed,
+ full_size,
+ light,
+ test_full_callback_that_fails
+ );
+ BOOST_ASSERT(!full);
+ ethash_light_delete(light);
+ fs::remove_all("./test_ethash_directory/");
+}
- return result;
+BOOST_AUTO_TEST_CASE(test_incomplete_dag_file) {
+ uint64_t full_size;
+ uint64_t cache_size;
+ ethash_h256_t seed;
+ ethash_h256_t hash;
+ memcpy(&seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+ memcpy(&hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32);
+
+ cache_size = 1024;
+ full_size = 1024 * 32;
+
+ ethash_light_t light = ethash_light_new_internal(cache_size, &seed);
+ // create a full but stop at 30%, so no magic number is written
+ ethash_full_t full = ethash_full_new_internal(
+ "./test_ethash_directory/",
+ seed,
+ full_size,
+ light,
+ test_full_callback_create_incomplete_dag
+ );
+ BOOST_ASSERT(!full);
+ FILE *f = NULL;
+ // confirm that we get a size_mismatch because the magic number is missing
+ BOOST_REQUIRE_EQUAL(
+ ETHASH_IO_MEMO_SIZE_MISMATCH,
+ ethash_io_prepare("./test_ethash_directory/", seed, &f, full_size, false)
+ );
+ ethash_light_delete(light);
+ fs::remove_all("./test_ethash_directory/");
+}
+
+BOOST_AUTO_TEST_CASE(test_block_verification) {
+ ethash_light_t light = ethash_light_new(22);
+ ethash_h256_t seedhash = stringToBlockhash("372eca2454ead349c3df0ab5d00b0b706b23e49d469387db91811cee0358fc6d");
+ BOOST_ASSERT(light);
+ ethash_return_value_t ret = ethash_light_compute(
+ light,
+ seedhash,
+ 0x495732e0ed7a801c
+ );
+ BOOST_REQUIRE_EQUAL(blockhashToHexString(&ret.result), "00000b184f1fdd88bfd94c86c39e65db0c36144d5e43f745f722196e730cb614");
+ ethash_light_delete(light);
+}
+
+// Test of Full DAG creation with the minimal ethash.h API.
+// Commented out since travis tests would take too much time.
+// Uncomment and run on your own machine if you want to confirm
+// it works fine.
+#if 0
+static int lef_cb(unsigned _progress)
+{
+ printf("CREATING DAG. PROGRESS: %u\n", _progress);
+ fflush(stdout);
+ return 0;
}
-BOOST_AUTO_TEST_CASE(test_ethash_io_memo_file_contents) {
- ethash_blockhash_t seedhash;
- static const int blockn = 0;
- ethash_get_seedhash(&seedhash, blockn);
- BOOST_REQUIRE_EQUAL(
- ETHASH_IO_MEMO_MISMATCH,
- ethash_io_prepare("./test_ethash_directory/", seedhash)
- );
-
- // let's make sure that the directory was created
- BOOST_REQUIRE(fs::is_directory(fs::path("./test_ethash_directory/")));
-
- ethash_cache cache;
- ethash_params params;
- uint8_t *data;
- uint64_t size;
- ethash_params_init(&params, blockn);
- params.cache_size = 1024;
- params.full_size = 1024 * 32;
- cache.mem = our_alloca(params.cache_size);
- ethash_mkcache(&cache, &params, &seedhash);
-
- BOOST_REQUIRE(
- ethash_io_write("./test_ethash_directory/", &params, seedhash, &cache, &data, &size)
- );
-
- BOOST_REQUIRE(fs::exists(fs::path("./test_ethash_directory/full")));
- BOOST_REQUIRE(fs::exists(fs::path("./test_ethash_directory/full.info")));
-
- char expect_buffer[DAG_MEMO_BYTESIZE];
- ethash_io_serialize_info(REVISION, seedhash, expect_buffer);
- auto vec = readFileIntoVector("./test_ethash_directory/full.info");
- BOOST_REQUIRE_EQUAL(vec.size(), DAG_MEMO_BYTESIZE);
- BOOST_REQUIRE(memcmp(expect_buffer, &vec[0], DAG_MEMO_BYTESIZE) == 0);
-
- // cleanup
- fs::remove_all("./test_ethash_directory/");
- free(data);
+BOOST_AUTO_TEST_CASE(full_dag_test) {
+ ethash_light_t light = ethash_light_new(55);
+ BOOST_ASSERT(light);
+ ethash_full_t full = ethash_full_new(light, lef_cb);
+ BOOST_ASSERT(full);
+ ethash_light_delete(light);
+ ethash_full_delete(full);
}
+#endif
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.sh b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.sh
index 6d02d30f8..92b6b8b66 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.sh
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.sh
@@ -3,6 +3,13 @@
# Strict mode
set -e
+VALGRIND_ARGS="--tool=memcheck"
+VALGRIND_ARGS+=" --leak-check=yes"
+VALGRIND_ARGS+=" --track-origins=yes"
+VALGRIND_ARGS+=" --show-reachable=yes"
+VALGRIND_ARGS+=" --num-callers=20"
+VALGRIND_ARGS+=" --track-fds=yes"
+
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
@@ -17,3 +24,9 @@ cd $TEST_DIR/build ;
cmake ../../.. > /dev/null
make Test
./test/c/Test
+
+# If we have valgrind also run memory check tests
+if hash valgrind 2>/dev/null; then
+ echo "======== Running tests under valgrind ========";
+ cd $TEST_DIR/build/ && valgrind $VALGRIND_ARGS ./test/c/Test
+fi
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/go/ethash_test.go b/Godeps/_workspace/src/github.com/ethereum/ethash/test/go/ethash_test.go
deleted file mode 100644
index 67ca51702..000000000
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/go/ethash_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-package ethashTest
-
-import (
- "bytes"
- "crypto/rand"
- "encoding/hex"
- "log"
- "math/big"
- "testing"
-
- "github.com/ethereum/ethash"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/ethdb"
-)
-
-func TestEthash(t *testing.T) {
- seedHash := make([]byte, 32)
- _, err := rand.Read(seedHash)
- if err != nil {
- panic(err)
- }
-
- db, err := ethdb.NewMemDatabase()
- if err != nil {
- panic(err)
- }
-
- blockProcessor, err := core.NewCanonical(5, db)
- if err != nil {
- panic(err)
- }
-
- log.Println("Block Number: ", blockProcessor.ChainManager().CurrentBlock().Number())
-
- e := ethash.New(blockProcessor.ChainManager())
-
- miningHash := make([]byte, 32)
- if _, err := rand.Read(miningHash); err != nil {
- panic(err)
- }
- diff := big.NewInt(10000)
- log.Println("difficulty", diff)
-
- nonce := uint64(0)
-
- ghash_full := e.FullHash(nonce, miningHash)
- log.Printf("ethash full (on nonce): %x %x\n", ghash_full, nonce)
-
- ghash_light := e.LightHash(nonce, miningHash)
- log.Printf("ethash light (on nonce): %x %x\n", ghash_light, nonce)
-
- if bytes.Compare(ghash_full, ghash_light) != 0 {
- t.Errorf("full: %x, light: %x", ghash_full, ghash_light)
- }
-}
-
-func TestGetSeedHash(t *testing.T) {
- seed0, err := ethash.GetSeedHash(0)
- if err != nil {
- t.Errorf("Failed to get seedHash for block 0: %v", err)
- }
- if bytes.Compare(seed0, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) != 0 {
- log.Printf("seedHash for block 0 should be 0s, was: %v\n", seed0)
- }
- seed1, err := ethash.GetSeedHash(30000)
- if err != nil {
- t.Error(err)
- }
-
- // From python:
- // > from pyethash import get_seedhash
- // > get_seedhash(30000)
- expectedSeed1, err := hex.DecodeString("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
- if err != nil {
- t.Error(err)
- }
-
- if bytes.Compare(seed1, expectedSeed1) != 0 {
- log.Printf("seedHash for block 1 should be: %v,\nactual value: %v\n", expectedSeed1, seed1)
- }
-
-}
diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/test.sh b/Godeps/_workspace/src/github.com/ethereum/ethash/test/test.sh
index fd3508609..aaeaa878c 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/test.sh
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/test/test.sh
@@ -24,8 +24,9 @@ fi
echo -e "\n################# Testing C ##################"
$TEST_DIR/c/test.sh
-echo -e "\n################# Testing Python ##################"
-$TEST_DIR/python/test.sh
+# Temporarily commenting out python tests until they conform to the API
+#echo -e "\n################# Testing Python ##################"
+#$TEST_DIR/python/test.sh
-#echo "################# Testing Go ##################"
-#$TEST_DIR/go/test.sh
+echo "################# Testing Go ##################"
+cd $TEST_DIR/.. && go test -timeout 9999s
diff --git a/Godeps/_workspace/src/github.com/mattn/go-colorable/README.md b/Godeps/_workspace/src/github.com/mattn/go-colorable/README.md
new file mode 100644
index 000000000..c69da4a76
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-colorable/README.md
@@ -0,0 +1,42 @@
+# go-colorable
+
+Colorable writer for windows.
+
+For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
+This package is possible to handle escape sequence for ansi color on windows.
+
+## Too Bad!
+
+![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png)
+
+
+## So Good!
+
+![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png)
+
+## Usage
+
+```go
+logrus.SetOutput(colorable.NewColorableStdout())
+
+logrus.Info("succeeded")
+logrus.Warn("not correct")
+logrus.Error("something error")
+logrus.Fatal("panic")
+```
+
+You can compile above code on non-windows OSs.
+
+## Installation
+
+```
+$ go get github.com/mattn/go-colorable
+```
+
+# License
+
+MIT
+
+# Author
+
+Yasuhiro Matsumoto (a.k.a mattn)
diff --git a/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go b/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go
new file mode 100644
index 000000000..219f02f62
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go
@@ -0,0 +1,16 @@
+// +build !windows
+
+package colorable
+
+import (
+ "io"
+ "os"
+)
+
+func NewColorableStdout() io.Writer {
+ return os.Stdout
+}
+
+func NewColorableStderr() io.Writer {
+ return os.Stderr
+}
diff --git a/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go b/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go
new file mode 100644
index 000000000..6a2787808
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go
@@ -0,0 +1,594 @@
+package colorable
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "github.com/mattn/go-isatty"
+)
+
+const (
+ foregroundBlue = 0x1
+ foregroundGreen = 0x2
+ foregroundRed = 0x4
+ foregroundIntensity = 0x8
+ foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
+ backgroundBlue = 0x10
+ backgroundGreen = 0x20
+ backgroundRed = 0x40
+ backgroundIntensity = 0x80
+ backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
+)
+
+type wchar uint16
+type short int16
+type dword uint32
+type word uint16
+
+type coord struct {
+ x short
+ y short
+}
+
+type smallRect struct {
+ left short
+ top short
+ right short
+ bottom short
+}
+
+type consoleScreenBufferInfo struct {
+ size coord
+ cursorPosition coord
+ attributes word
+ window smallRect
+ maximumWindowSize coord
+}
+
+var (
+ kernel32 = syscall.NewLazyDLL("kernel32.dll")
+ procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
+ procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
+)
+
+type Writer struct {
+ out io.Writer
+ handle syscall.Handle
+ lastbuf bytes.Buffer
+ oldattr word
+}
+
+func NewColorableStdout() io.Writer {
+ var csbi consoleScreenBufferInfo
+ out := os.Stdout
+ if !isatty.IsTerminal(out.Fd()) {
+ return out
+ }
+ handle := syscall.Handle(out.Fd())
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+ return &Writer{out: out, handle: handle, oldattr: csbi.attributes}
+}
+
+func NewColorableStderr() io.Writer {
+ var csbi consoleScreenBufferInfo
+ out := os.Stderr
+ if !isatty.IsTerminal(out.Fd()) {
+ return out
+ }
+ handle := syscall.Handle(out.Fd())
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+ return &Writer{out: out, handle: handle, oldattr: csbi.attributes}
+}
+
+var color256 = map[int]int{
+ 0: 0x000000,
+ 1: 0x800000,
+ 2: 0x008000,
+ 3: 0x808000,
+ 4: 0x000080,
+ 5: 0x800080,
+ 6: 0x008080,
+ 7: 0xc0c0c0,
+ 8: 0x808080,
+ 9: 0xff0000,
+ 10: 0x00ff00,
+ 11: 0xffff00,
+ 12: 0x0000ff,
+ 13: 0xff00ff,
+ 14: 0x00ffff,
+ 15: 0xffffff,
+ 16: 0x000000,
+ 17: 0x00005f,
+ 18: 0x000087,
+ 19: 0x0000af,
+ 20: 0x0000d7,
+ 21: 0x0000ff,
+ 22: 0x005f00,
+ 23: 0x005f5f,
+ 24: 0x005f87,
+ 25: 0x005faf,
+ 26: 0x005fd7,
+ 27: 0x005fff,
+ 28: 0x008700,
+ 29: 0x00875f,
+ 30: 0x008787,
+ 31: 0x0087af,
+ 32: 0x0087d7,
+ 33: 0x0087ff,
+ 34: 0x00af00,
+ 35: 0x00af5f,
+ 36: 0x00af87,
+ 37: 0x00afaf,
+ 38: 0x00afd7,
+ 39: 0x00afff,
+ 40: 0x00d700,
+ 41: 0x00d75f,
+ 42: 0x00d787,
+ 43: 0x00d7af,
+ 44: 0x00d7d7,
+ 45: 0x00d7ff,
+ 46: 0x00ff00,
+ 47: 0x00ff5f,
+ 48: 0x00ff87,
+ 49: 0x00ffaf,
+ 50: 0x00ffd7,
+ 51: 0x00ffff,
+ 52: 0x5f0000,
+ 53: 0x5f005f,
+ 54: 0x5f0087,
+ 55: 0x5f00af,
+ 56: 0x5f00d7,
+ 57: 0x5f00ff,
+ 58: 0x5f5f00,
+ 59: 0x5f5f5f,
+ 60: 0x5f5f87,
+ 61: 0x5f5faf,
+ 62: 0x5f5fd7,
+ 63: 0x5f5fff,
+ 64: 0x5f8700,
+ 65: 0x5f875f,
+ 66: 0x5f8787,
+ 67: 0x5f87af,
+ 68: 0x5f87d7,
+ 69: 0x5f87ff,
+ 70: 0x5faf00,
+ 71: 0x5faf5f,
+ 72: 0x5faf87,
+ 73: 0x5fafaf,
+ 74: 0x5fafd7,
+ 75: 0x5fafff,
+ 76: 0x5fd700,
+ 77: 0x5fd75f,
+ 78: 0x5fd787,
+ 79: 0x5fd7af,
+ 80: 0x5fd7d7,
+ 81: 0x5fd7ff,
+ 82: 0x5fff00,
+ 83: 0x5fff5f,
+ 84: 0x5fff87,
+ 85: 0x5fffaf,
+ 86: 0x5fffd7,
+ 87: 0x5fffff,
+ 88: 0x870000,
+ 89: 0x87005f,
+ 90: 0x870087,
+ 91: 0x8700af,
+ 92: 0x8700d7,
+ 93: 0x8700ff,
+ 94: 0x875f00,
+ 95: 0x875f5f,
+ 96: 0x875f87,
+ 97: 0x875faf,
+ 98: 0x875fd7,
+ 99: 0x875fff,
+ 100: 0x878700,
+ 101: 0x87875f,
+ 102: 0x878787,
+ 103: 0x8787af,
+ 104: 0x8787d7,
+ 105: 0x8787ff,
+ 106: 0x87af00,
+ 107: 0x87af5f,
+ 108: 0x87af87,
+ 109: 0x87afaf,
+ 110: 0x87afd7,
+ 111: 0x87afff,
+ 112: 0x87d700,
+ 113: 0x87d75f,
+ 114: 0x87d787,
+ 115: 0x87d7af,
+ 116: 0x87d7d7,
+ 117: 0x87d7ff,
+ 118: 0x87ff00,
+ 119: 0x87ff5f,
+ 120: 0x87ff87,
+ 121: 0x87ffaf,
+ 122: 0x87ffd7,
+ 123: 0x87ffff,
+ 124: 0xaf0000,
+ 125: 0xaf005f,
+ 126: 0xaf0087,
+ 127: 0xaf00af,
+ 128: 0xaf00d7,
+ 129: 0xaf00ff,
+ 130: 0xaf5f00,
+ 131: 0xaf5f5f,
+ 132: 0xaf5f87,
+ 133: 0xaf5faf,
+ 134: 0xaf5fd7,
+ 135: 0xaf5fff,
+ 136: 0xaf8700,
+ 137: 0xaf875f,
+ 138: 0xaf8787,
+ 139: 0xaf87af,
+ 140: 0xaf87d7,
+ 141: 0xaf87ff,
+ 142: 0xafaf00,
+ 143: 0xafaf5f,
+ 144: 0xafaf87,
+ 145: 0xafafaf,
+ 146: 0xafafd7,
+ 147: 0xafafff,
+ 148: 0xafd700,
+ 149: 0xafd75f,
+ 150: 0xafd787,
+ 151: 0xafd7af,
+ 152: 0xafd7d7,
+ 153: 0xafd7ff,
+ 154: 0xafff00,
+ 155: 0xafff5f,
+ 156: 0xafff87,
+ 157: 0xafffaf,
+ 158: 0xafffd7,
+ 159: 0xafffff,
+ 160: 0xd70000,
+ 161: 0xd7005f,
+ 162: 0xd70087,
+ 163: 0xd700af,
+ 164: 0xd700d7,
+ 165: 0xd700ff,
+ 166: 0xd75f00,
+ 167: 0xd75f5f,
+ 168: 0xd75f87,
+ 169: 0xd75faf,
+ 170: 0xd75fd7,
+ 171: 0xd75fff,
+ 172: 0xd78700,
+ 173: 0xd7875f,
+ 174: 0xd78787,
+ 175: 0xd787af,
+ 176: 0xd787d7,
+ 177: 0xd787ff,
+ 178: 0xd7af00,
+ 179: 0xd7af5f,
+ 180: 0xd7af87,
+ 181: 0xd7afaf,
+ 182: 0xd7afd7,
+ 183: 0xd7afff,
+ 184: 0xd7d700,
+ 185: 0xd7d75f,
+ 186: 0xd7d787,
+ 187: 0xd7d7af,
+ 188: 0xd7d7d7,
+ 189: 0xd7d7ff,
+ 190: 0xd7ff00,
+ 191: 0xd7ff5f,
+ 192: 0xd7ff87,
+ 193: 0xd7ffaf,
+ 194: 0xd7ffd7,
+ 195: 0xd7ffff,
+ 196: 0xff0000,
+ 197: 0xff005f,
+ 198: 0xff0087,
+ 199: 0xff00af,
+ 200: 0xff00d7,
+ 201: 0xff00ff,
+ 202: 0xff5f00,
+ 203: 0xff5f5f,
+ 204: 0xff5f87,
+ 205: 0xff5faf,
+ 206: 0xff5fd7,
+ 207: 0xff5fff,
+ 208: 0xff8700,
+ 209: 0xff875f,
+ 210: 0xff8787,
+ 211: 0xff87af,
+ 212: 0xff87d7,
+ 213: 0xff87ff,
+ 214: 0xffaf00,
+ 215: 0xffaf5f,
+ 216: 0xffaf87,
+ 217: 0xffafaf,
+ 218: 0xffafd7,
+ 219: 0xffafff,
+ 220: 0xffd700,
+ 221: 0xffd75f,
+ 222: 0xffd787,
+ 223: 0xffd7af,
+ 224: 0xffd7d7,
+ 225: 0xffd7ff,
+ 226: 0xffff00,
+ 227: 0xffff5f,
+ 228: 0xffff87,
+ 229: 0xffffaf,
+ 230: 0xffffd7,
+ 231: 0xffffff,
+ 232: 0x080808,
+ 233: 0x121212,
+ 234: 0x1c1c1c,
+ 235: 0x262626,
+ 236: 0x303030,
+ 237: 0x3a3a3a,
+ 238: 0x444444,
+ 239: 0x4e4e4e,
+ 240: 0x585858,
+ 241: 0x626262,
+ 242: 0x6c6c6c,
+ 243: 0x767676,
+ 244: 0x808080,
+ 245: 0x8a8a8a,
+ 246: 0x949494,
+ 247: 0x9e9e9e,
+ 248: 0xa8a8a8,
+ 249: 0xb2b2b2,
+ 250: 0xbcbcbc,
+ 251: 0xc6c6c6,
+ 252: 0xd0d0d0,
+ 253: 0xdadada,
+ 254: 0xe4e4e4,
+ 255: 0xeeeeee,
+}
+
+func (w *Writer) Write(data []byte) (n int, err error) {
+ var csbi consoleScreenBufferInfo
+ procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
+
+ er := bytes.NewBuffer(data)
+loop:
+ for {
+ r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
+ if r1 == 0 {
+ break loop
+ }
+
+ c1, _, err := er.ReadRune()
+ if err != nil {
+ break loop
+ }
+ if c1 != 0x1b {
+ fmt.Fprint(w.out, string(c1))
+ continue
+ }
+ c2, _, err := er.ReadRune()
+ if err != nil {
+ w.lastbuf.WriteRune(c1)
+ break loop
+ }
+ if c2 != 0x5b {
+ w.lastbuf.WriteRune(c1)
+ w.lastbuf.WriteRune(c2)
+ continue
+ }
+
+ var buf bytes.Buffer
+ var m rune
+ for {
+ c, _, err := er.ReadRune()
+ if err != nil {
+ w.lastbuf.WriteRune(c1)
+ w.lastbuf.WriteRune(c2)
+ w.lastbuf.Write(buf.Bytes())
+ break loop
+ }
+ if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
+ m = c
+ break
+ }
+ buf.Write([]byte(string(c)))
+ }
+
+ switch m {
+ case 'm':
+ attr := csbi.attributes
+ cs := buf.String()
+ if cs == "" {
+ procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
+ continue
+ }
+ token := strings.Split(cs, ";")
+ for i, ns := range token {
+ if n, err = strconv.Atoi(ns); err == nil {
+ switch {
+ case n == 0 || n == 100:
+ attr = w.oldattr
+ case 1 <= n && n <= 5:
+ attr |= foregroundIntensity
+ case n == 7:
+ attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
+ case 22 == n || n == 25 || n == 25:
+ attr |= foregroundIntensity
+ case n == 27:
+ attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
+ case 30 <= n && n <= 37:
+ attr = (attr & backgroundMask)
+ if (n-30)&1 != 0 {
+ attr |= foregroundRed
+ }
+ if (n-30)&2 != 0 {
+ attr |= foregroundGreen
+ }
+ if (n-30)&4 != 0 {
+ attr |= foregroundBlue
+ }
+ case n == 38: // set foreground color.
+ if i < len(token)-2 && token[i+1] == "5" {
+ if n256, err := strconv.Atoi(token[i+2]); err == nil {
+ if n256foreAttr == nil {
+ n256setup()
+ }
+ attr &= backgroundMask
+ attr |= n256foreAttr[n256]
+ i += 2
+ }
+ } else {
+ attr = attr & (w.oldattr & backgroundMask)
+ }
+ case n == 39: // reset foreground color.
+ attr &= backgroundMask
+ attr |= w.oldattr & foregroundMask
+ case 40 <= n && n <= 47:
+ attr = (attr & foregroundMask)
+ if (n-40)&1 != 0 {
+ attr |= backgroundRed
+ }
+ if (n-40)&2 != 0 {
+ attr |= backgroundGreen
+ }
+ if (n-40)&4 != 0 {
+ attr |= backgroundBlue
+ }
+ case n == 48: // set background color.
+ if i < len(token)-2 && token[i+1] == "5" {
+ if n256, err := strconv.Atoi(token[i+2]); err == nil {
+ if n256backAttr == nil {
+ n256setup()
+ }
+ attr &= foregroundMask
+ attr |= n256backAttr[n256]
+ i += 2
+ }
+ } else {
+ attr = attr & (w.oldattr & foregroundMask)
+ }
+ case n == 49: // reset foreground color.
+ attr &= foregroundMask
+ attr |= w.oldattr & backgroundMask
+ }
+ procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
+ }
+ }
+ }
+ }
+ return len(data) - w.lastbuf.Len(), nil
+}
+
+type consoleColor struct {
+ red bool
+ green bool
+ blue bool
+ intensity bool
+}
+
+func minmax3(a, b, c int) (min, max int) {
+ if a < b {
+ if b < c {
+ return a, c
+ } else if a < c {
+ return a, b
+ } else {
+ return c, b
+ }
+ } else {
+ if a < c {
+ return b, c
+ } else if b < c {
+ return b, a
+ } else {
+ return c, a
+ }
+ }
+}
+
+func toConsoleColor(rgb int) (c consoleColor) {
+ r, g, b := (rgb&0xFF0000)>>16, (rgb&0x00FF00)>>8, rgb&0x0000FF
+ min, max := minmax3(r, g, b)
+ a := (min + max) / 2
+ if r < 128 && g < 128 && b < 128 {
+ if r >= a {
+ c.red = true
+ }
+ if g >= a {
+ c.green = true
+ }
+ if b >= a {
+ c.blue = true
+ }
+ // non-intensed white is lighter than intensed black, so swap those.
+ if c.red && c.green && c.blue {
+ c.red, c.green, c.blue = false, false, false
+ c.intensity = true
+ }
+ } else {
+ if min < 128 {
+ min = 128
+ a = (min + max) / 2
+ }
+ if r >= a {
+ c.red = true
+ }
+ if g >= a {
+ c.green = true
+ }
+ if b >= a {
+ c.blue = true
+ }
+ c.intensity = true
+ // intensed black is darker than non-intensed white, so swap those.
+ if !c.red && !c.green && !c.blue {
+ c.red, c.green, c.blue = true, true, true
+ c.intensity = false
+ }
+ }
+ return c
+}
+
+func (c consoleColor) foregroundAttr() (attr word) {
+ if c.red {
+ attr |= foregroundRed
+ }
+ if c.green {
+ attr |= foregroundGreen
+ }
+ if c.blue {
+ attr |= foregroundBlue
+ }
+ if c.intensity {
+ attr |= foregroundIntensity
+ }
+ return
+}
+
+func (c consoleColor) backgroundAttr() (attr word) {
+ if c.red {
+ attr |= backgroundRed
+ }
+ if c.green {
+ attr |= backgroundGreen
+ }
+ if c.blue {
+ attr |= backgroundBlue
+ }
+ if c.intensity {
+ attr |= backgroundIntensity
+ }
+ return
+}
+
+var n256foreAttr []word
+var n256backAttr []word
+
+func n256setup() {
+ n256foreAttr = make([]word, 256)
+ n256backAttr = make([]word, 256)
+ for i, rgb := range color256 {
+ c := toConsoleColor(rgb)
+ n256foreAttr[i] = c.foregroundAttr()
+ n256backAttr[i] = c.backgroundAttr()
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/mattn/go-isatty/README.md b/Godeps/_workspace/src/github.com/mattn/go-isatty/README.md
new file mode 100644
index 000000000..74845de4a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-isatty/README.md
@@ -0,0 +1,37 @@
+# go-isatty
+
+isatty for golang
+
+## Usage
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/mattn/go-isatty"
+ "os"
+)
+
+func main() {
+ if isatty.IsTerminal(os.Stdout.Fd()) {
+ fmt.Println("Is Terminal")
+ } else {
+ fmt.Println("Is Not Terminal")
+ }
+}
+```
+
+## Installation
+
+```
+$ go get github.com/mattn/go-isatty
+```
+
+# License
+
+MIT
+
+# Author
+
+Yasuhiro Matsumoto (a.k.a mattn)
diff --git a/Godeps/_workspace/src/github.com/mattn/go-isatty/doc.go b/Godeps/_workspace/src/github.com/mattn/go-isatty/doc.go
new file mode 100644
index 000000000..17d4f90eb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-isatty/doc.go
@@ -0,0 +1,2 @@
+// Package isatty implements interface to isatty
+package isatty
diff --git a/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_bsd.go b/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_bsd.go
new file mode 100644
index 000000000..035274751
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_bsd.go
@@ -0,0 +1,17 @@
+// +build darwin freebsd
+
+package isatty
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+const ioctlReadTermios = syscall.TIOCGETA
+
+// IsTerminal return true if the file descriptor is terminal.
+func IsTerminal(fd uintptr) bool {
+ var termios syscall.Termios
+ _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+ return err == 0
+}
diff --git a/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_linux.go b/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_linux.go
new file mode 100644
index 000000000..8b361d7fb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_linux.go
@@ -0,0 +1,17 @@
+// +build linux
+
+package isatty
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+const ioctlReadTermios = syscall.TCGETS
+
+// IsTerminal return true if the file descriptor is terminal.
+func IsTerminal(fd uintptr) bool {
+ var termios syscall.Termios
+ _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+ return err == 0
+}
diff --git a/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_windows.go b/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_windows.go
new file mode 100644
index 000000000..562ee39ca
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mattn/go-isatty/isatty_windows.go
@@ -0,0 +1,18 @@
+// +build windows
+
+package isatty
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+var kernel32 = syscall.NewLazyDLL("kernel32.dll")
+var procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
+
+// IsTerminal return true if the file descriptor is terminal.
+func IsTerminal(fd uintptr) bool {
+ var st uint32
+ r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
+ return r != 0 && e == 0
+}
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
index 77510b8b8..f15ce89a0 100644
--- a/cmd/geth/admin.go
+++ b/cmd/geth/admin.go
@@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
+ "strconv"
"time"
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -15,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/xeth"
"github.com/robertkrimen/otto"
+ "gopkg.in/fatih/set.v0"
)
/*
@@ -22,6 +24,11 @@ node admin bindings
*/
func (js *jsre) adminBindings() {
+ ethO, _ := js.re.Get("eth")
+ eth := ethO.Object()
+ eth.Set("pendingTransactions", js.pendingTransactions)
+ eth.Set("resend", js.resend)
+
js.re.Set("admin", struct{}{})
t, _ := js.re.Get("admin")
admin := t.Object()
@@ -74,6 +81,70 @@ func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
return nil, errors.New("requires block number or block hash as argument")
}
+func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
+ txs := js.ethereum.TxPool().GetTransactions()
+
+ // grab the accounts from the account manager. This will help with determening which
+ // transactions should be returned.
+ accounts, err := js.ethereum.AccountManager().Accounts()
+ if err != nil {
+ fmt.Println(err)
+ return otto.UndefinedValue()
+ }
+
+ // Add the accouns to a new set
+ accountSet := set.New()
+ for _, account := range accounts {
+ accountSet.Add(common.BytesToAddress(account.Address))
+ }
+
+ //ltxs := make([]*tx, len(txs))
+ var ltxs []*tx
+ for _, tx := range txs {
+ // no need to check err
+ if from, _ := tx.From(); accountSet.Has(from) {
+ ltxs = append(ltxs, newTx(tx))
+ }
+ }
+
+ return js.re.ToVal(ltxs)
+}
+
+func (js *jsre) resend(call otto.FunctionCall) otto.Value {
+ if len(call.ArgumentList) == 0 {
+ fmt.Println("first argument must be a transaction")
+ return otto.FalseValue()
+ }
+
+ v, err := call.Argument(0).Export()
+ if err != nil {
+ fmt.Println(err)
+ return otto.FalseValue()
+ }
+
+ if tx, ok := v.(*tx); ok {
+ gl, gp := tx.GasLimit, tx.GasPrice
+ if len(call.ArgumentList) > 1 {
+ gp = call.Argument(1).String()
+ }
+ if len(call.ArgumentList) > 2 {
+ gl = call.Argument(2).String()
+ }
+
+ ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data)
+ if err != nil {
+ fmt.Println(err)
+ return otto.FalseValue()
+ }
+ js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
+
+ return js.re.ToVal(ret)
+ }
+
+ fmt.Println("first argument must be a transaction")
+ return otto.FalseValue()
+}
+
func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
block, err := js.getBlock(call)
if err != nil {
@@ -421,3 +492,35 @@ func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
return js.re.ToVal(dump)
}
+
+// internal transaction type which will allow us to resend transactions using `eth.resend`
+type tx struct {
+ tx *types.Transaction
+
+ To string
+ From string
+ Nonce string
+ Value string
+ Data string
+ GasLimit string
+ GasPrice string
+}
+
+func newTx(t *types.Transaction) *tx {
+ from, _ := t.From()
+ var to string
+ if t := t.To(); t != nil {
+ to = t.Hex()
+ }
+
+ return &tx{
+ tx: t,
+ To: to,
+ From: from.Hex(),
+ Value: t.Amount.String(),
+ Nonce: strconv.Itoa(int(t.Nonce())),
+ Data: "0x" + common.Bytes2Hex(t.Data()),
+ GasLimit: t.GasLimit.String(),
+ GasPrice: t.GasPrice().String(),
+ }
+}
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index a545de1d0..d8c26eb2f 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -103,6 +103,7 @@ func (js *jsre) apiBindings() {
t, _ := js.re.Get("jeth")
jethObj := t.Object()
jethObj.Set("send", jeth.Send)
+ jethObj.Set("sendAsync", jeth.Send)
err := js.re.Compile("bignumber.js", re.BigNumber_JS)
if err != nil {
@@ -172,8 +173,10 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
func (self *jsre) exec(filename string) error {
if err := self.re.Exec(filename); err != nil {
+ self.re.Stop(false)
return fmt.Errorf("Javascript Error: %v", err)
}
+ self.re.Stop(true)
return nil
}
@@ -201,6 +204,7 @@ func (self *jsre) interactive() {
if self.atexit != nil {
self.atexit()
}
+ self.re.Stop(false)
}
func (self *jsre) withHistory(op func(*os.File)) {
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index ef007051c..f2497ccf4 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -23,14 +23,16 @@ package main
import (
"bufio"
"fmt"
+ "io"
"io/ioutil"
"os"
+ "path"
+ "path/filepath"
"runtime"
"strconv"
+ "strings"
"time"
- "path"
-
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
@@ -41,13 +43,15 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/mattn/go-colorable"
+ "github.com/mattn/go-isatty"
"github.com/peterh/liner"
)
import _ "net/http/pprof"
const (
ClientIdentifier = "Geth"
- Version = "0.9.14"
+ Version = "0.9.15"
)
var (
@@ -301,6 +305,14 @@ func run(ctx *cli.Context) {
}
func console(ctx *cli.Context) {
+ // Wrap the standard output with a colorified stream (windows)
+ if isatty.IsTerminal(os.Stdout.Fd()) {
+ if pr, pw, err := os.Pipe(); err == nil {
+ go io.Copy(colorable.NewColorableStdout(), pr)
+ os.Stdout = pw
+ }
+ }
+
cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
ethereum, err := eth.New(cfg)
if err != nil {
@@ -591,12 +603,32 @@ func dump(ctx *cli.Context) {
}
func makedag(ctx *cli.Context) {
- chain, _, _ := utils.GetChain(ctx)
- pow := ethash.New(chain)
- fmt.Println("making cache")
- pow.UpdateCache(0, true)
- fmt.Println("making DAG")
- pow.UpdateDAG()
+ args := ctx.Args()
+ wrongArgs := func() {
+ utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
+ }
+ switch {
+ case len(args) == 2:
+ blockNum, err := strconv.ParseUint(args[0], 0, 64)
+ dir := args[1]
+ if err != nil {
+ wrongArgs()
+ } else {
+ dir = filepath.Clean(dir)
+ // seems to require a trailing slash
+ if !strings.HasSuffix(dir, "/") {
+ dir = dir + "/"
+ }
+ _, err = ioutil.ReadDir(dir)
+ if err != nil {
+ utils.Fatalf("Can't find dir")
+ }
+ fmt.Println("making DAG, this could take awhile...")
+ ethash.MakeDAG(blockNum, dir)
+ }
+ default:
+ wrongArgs()
+ }
}
func version(c *cli.Context) {
diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go
index e7ce50c35..7512421a1 100644
--- a/cmd/mist/bindings.go
+++ b/cmd/mist/bindings.go
@@ -40,7 +40,7 @@ type plugin struct {
func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
d = common.Bytes2Hex(utils.FormatTransactionData(d))
- return gui.xeth.Transact(from, recipient, value, gas, gasPrice, d)
+ return gui.xeth.Transact(from, recipient, "", value, gas, gasPrice, d)
}
func (self *Gui) AddPlugin(pluginPath string) {
diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go
index bf5588010..a604e87ba 100644
--- a/cmd/mist/ui_lib.go
+++ b/cmd/mist/ui_lib.go
@@ -119,6 +119,7 @@ func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
return self.XEth.Transact(
object["from"],
object["to"],
+ "",
object["value"],
object["gas"],
object["gasPrice"],
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index c013510d8..1fdc8dfe5 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -316,7 +316,7 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Dat
eventMux := new(event.TypeMux)
chainManager := core.NewChainManager(blockDb, stateDb, eventMux)
- pow := ethash.New(chainManager)
+ pow := ethash.New()
txPool := core.NewTxPool(eventMux, chainManager.State, chainManager.GasLimit)
blockProcessor := core.NewBlockProcessor(stateDb, extraDb, pow, txPool, chainManager, eventMux)
chainManager.SetProcessor(blockProcessor)
diff --git a/common/resolver/resolver.go b/common/resolver/resolver.go
index 1e6d03ffb..42348a89c 100644
--- a/common/resolver/resolver.go
+++ b/common/resolver/resolver.go
@@ -24,11 +24,11 @@ var HashRegContractAddress string = "0000000000000000000000000000000000000000000
func CreateContracts(xeth *xe.XEth, addr string) {
var err error
- URLHintContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeURLhint)
+ URLHintContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeURLhint)
if err != nil {
panic(err)
}
- HashRegContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeHashReg)
+ HashRegContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeHashReg)
if err != nil {
panic(err)
}
diff --git a/common/types.go b/common/types.go
index daefcde11..183d48fb3 100644
--- a/common/types.go
+++ b/common/types.go
@@ -1,6 +1,10 @@
package common
-import "math/big"
+import (
+ "math/big"
+ "math/rand"
+ "reflect"
+)
const (
hashLength = 32
@@ -48,6 +52,15 @@ func (h *Hash) Set(other Hash) {
}
}
+// Generate implements testing/quick.Generator.
+func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
+ m := rand.Intn(len(h))
+ for i := len(h) - 1; i > m; i-- {
+ h[i] = byte(rand.Uint32())
+ }
+ return reflect.ValueOf(h)
+}
+
/////////// Address
func BytesToAddress(b []byte) Address {
var a Address
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 73c2205f4..5cd7ab4ab 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -14,8 +14,8 @@ import (
// So we can generate blocks easily
type FakePow struct{}
-func (f FakePow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte, []byte) {
- return 0, nil, nil
+func (f FakePow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte) {
+ return 0, nil
}
func (f FakePow) Verify(block pow.Block) bool { return true }
func (f FakePow) GetHashrate() int64 { return 0 }
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 4fdb2edce..29830188e 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -49,6 +49,10 @@ func CalcDifficulty(block, parent *types.Header) *big.Int {
}
func CalculateTD(block, parent *types.Block) *big.Int {
+ if parent == nil {
+ return block.Difficulty()
+ }
+
td := new(big.Int).Add(parent.Td, block.Header().Difficulty)
return td
@@ -89,6 +93,7 @@ type ChainManager struct {
futureBlocks *BlockCache
quit chan struct{}
+ wg sync.WaitGroup
}
func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *ChainManager {
@@ -478,6 +483,10 @@ func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
func (bc *ChainManager) Stop() {
close(bc.quit)
+
+ bc.wg.Wait()
+
+ glog.V(logger.Info).Infoln("Chain manager stopped")
}
type queueEvent struct {
@@ -500,22 +509,30 @@ func (self *ChainManager) procFutureBlocks() {
// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
// it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
+ self.wg.Add(1)
+ defer self.wg.Done()
+
// A queued approach to delivering events. This is generally faster than direct delivery and requires much less mutex acquiring.
var (
queue = make([]interface{}, len(chain))
queueEvent = queueEvent{queue: queue}
- stats struct{ queued, processed int }
+ stats struct{ queued, processed, ignored int }
tstart = time.Now()
)
for i, block := range chain {
if block == nil {
continue
}
+ // Setting block.Td regardless of error (known for example) prevents errors down the line
+ // in the protocol handler
+ block.Td = new(big.Int).Set(CalculateTD(block, self.GetBlock(block.ParentHash())))
+
// Call in to the block processor and check for errors. It's likely that if one block fails
// all others will fail too (unless a known block is returned).
logs, err := self.processor.Process(block)
if err != nil {
if IsKnownBlockErr(err) {
+ stats.ignored++
continue
}
@@ -545,8 +562,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
return i, err
}
- block.Td = new(big.Int).Set(CalculateTD(block, self.GetBlock(block.ParentHash())))
-
self.mu.Lock()
{
cblock := self.currentBlock
@@ -589,7 +604,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
queueEvent.canonicalCount++
if glog.V(logger.Debug) {
- glog.Infof("inserted block #%d (%d TXs %d UNCs) (%x...)\n", block.Number(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4])
+ glog.Infof("[%v] inserted block #%d (%d TXs %d UNCs) (%x...)\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4])
}
} else {
if glog.V(logger.Detail) {
@@ -607,10 +622,10 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
}
- if (stats.queued > 0 || stats.processed > 0) && bool(glog.V(logger.Info)) {
+ if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) {
tend := time.Since(tstart)
start, end := chain[0], chain[len(chain)-1]
- glog.Infof("imported %d block(s) %d queued in %v. #%v [%x / %x]\n", stats.processed, stats.queued, tend, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
+ glog.Infof("imported %d block(s) (%d queued %d ignored) in %v. #%v [%x / %x]\n", stats.processed, stats.queued, stats.ignored, tend, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
}
go self.eventMux.Post(queueEvent)
@@ -654,7 +669,7 @@ func (self *ChainManager) merge(oldBlock, newBlock *types.Block) {
func (self *ChainManager) update() {
events := self.eventMux.Subscribe(queueEvent{})
- futureTimer := time.NewTicker(5 * time.Second)
+ futureTimer := time.Tick(5 * time.Second)
out:
for {
select {
@@ -681,7 +696,7 @@ out:
self.eventMux.Post(event)
}
}
- case <-futureTimer.C:
+ case <-futureTimer:
self.procFutureBlocks()
case <-self.quit:
break out
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 22a804e1d..bac6b7f0b 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -235,7 +235,7 @@ func (self *TxPool) RemoveTransactions(txs types.Transactions) {
defer self.mu.Unlock()
for _, tx := range txs {
- delete(self.txs, tx.Hash())
+ self.removeTx(tx.Hash())
}
}
diff --git a/eth/backend.go b/eth/backend.go
index 983dd8e4f..791336d75 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -259,8 +259,8 @@ func New(config *Config) (*Ethereum, error) {
}
eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.EventMux())
- eth.downloader = downloader.New(eth.chainManager.HasBlock, eth.chainManager.InsertChain)
- eth.pow = ethash.New(eth.chainManager)
+ eth.downloader = downloader.New(eth.chainManager.HasBlock, eth.chainManager.GetBlock)
+ eth.pow = ethash.New()
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux())
eth.chainManager.SetProcessor(eth.blockProcessor)
@@ -319,8 +319,8 @@ func (s *Ethereum) NodeInfo() *NodeInfo {
NodeUrl: node.String(),
NodeID: node.ID.String(),
IP: node.IP.String(),
- DiscPort: node.DiscPort,
- TCPPort: node.TCPPort,
+ DiscPort: int(node.UDP),
+ TCPPort: int(node.TCP),
ListenAddr: s.net.ListenAddr,
Td: s.ChainManager().Td().String(),
}
@@ -360,7 +360,6 @@ func (s *Ethereum) PeersInfo() (peersinfo []*PeerInfo) {
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
s.chainManager.ResetWithGenesisBlock(gb)
- s.pow.UpdateCache(0, true)
}
func (s *Ethereum) StartMining() error {
@@ -500,6 +499,7 @@ func (s *Ethereum) Stop() {
s.txSub.Unsubscribe() // quits txBroadcastLoop
s.protocolManager.Stop()
+ s.chainManager.Stop()
s.txPool.Stop()
s.eventMux.Stop()
if s.whisper != nil {
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 4cd927fd5..15f4cb0a3 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -3,14 +3,11 @@ package downloader
import (
"errors"
"fmt"
- "math"
- "math/big"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
@@ -27,16 +24,21 @@ var (
minDesiredPeerCount = 5 // Amount of peers desired to start syncing
blockTtl = 20 * time.Second // The amount of time it takes for a block request to time out
- errLowTd = errors.New("peer's TD is too low")
- errBusy = errors.New("busy")
- errUnknownPeer = errors.New("peer's unknown or unhealthy")
- errBadPeer = errors.New("action from bad peer ignored")
- errTimeout = errors.New("timeout")
- errEmptyHashSet = errors.New("empty hash set by peer")
- errPeersUnavailable = errors.New("no peers available or all peers tried for block download process")
+ errLowTd = errors.New("peer's TD is too low")
+ errBusy = errors.New("busy")
+ errUnknownPeer = errors.New("peer's unknown or unhealthy")
+ ErrBadPeer = errors.New("action from bad peer ignored")
+ errNoPeers = errors.New("no peers to keep download active")
+ errPendingQueue = errors.New("pending items in queue")
+ errTimeout = errors.New("timeout")
+ errEmptyHashSet = errors.New("empty hash set by peer")
+ errPeersUnavailable = errors.New("no peers available or all peers tried for block download process")
+ errAlreadyInPool = errors.New("hash already in pool")
+ errBlockNumberOverflow = errors.New("received block which overflows")
)
type hashCheckFn func(common.Hash) bool
+type getBlockFn func(common.Hash) *types.Block
type chainInsertFn func(types.Blocks) (int, error)
type hashIterFn func() (common.Hash, error)
@@ -51,6 +53,11 @@ type syncPack struct {
ignoreInitial bool
}
+type hashPack struct {
+ peerId string
+ hashes []common.Hash
+}
+
type Downloader struct {
mu sync.RWMutex
queue *queue
@@ -58,29 +65,28 @@ type Downloader struct {
activePeer string
// Callbacks
- hasBlock hashCheckFn
- insertChain chainInsertFn
+ hasBlock hashCheckFn
+ getBlock getBlockFn
// Status
fetchingHashes int32
downloadingBlocks int32
- processingBlocks int32
// Channels
newPeerCh chan *peer
- hashCh chan []common.Hash
+ hashCh chan hashPack
blockCh chan blockPack
}
-func New(hasBlock hashCheckFn, insertChain chainInsertFn) *Downloader {
+func New(hasBlock hashCheckFn, getBlock getBlockFn) *Downloader {
downloader := &Downloader{
- queue: newqueue(),
- peers: make(peers),
- hasBlock: hasBlock,
- insertChain: insertChain,
- newPeerCh: make(chan *peer, 1),
- hashCh: make(chan []common.Hash, 1),
- blockCh: make(chan blockPack, 1),
+ queue: newqueue(),
+ peers: make(peers),
+ hasBlock: hasBlock,
+ getBlock: getBlock,
+ newPeerCh: make(chan *peer, 1),
+ hashCh: make(chan hashPack, 1),
+ blockCh: make(chan blockPack, 1),
}
return downloader
@@ -126,6 +132,12 @@ func (d *Downloader) Synchronise(id string, hash common.Hash) error {
return errBusy
}
+ // When a synchronisation attempt is made while the queue stil
+ // contains items we abort the sync attempt
+ if d.queue.size() > 0 {
+ return errPendingQueue
+ }
+
// Fetch the peer using the id or throw an error if the peer couldn't be found
p := d.peers[id]
if p == nil {
@@ -138,30 +150,87 @@ func (d *Downloader) Synchronise(id string, hash common.Hash) error {
return err
}
- return d.process(p)
+ return nil
+}
+
+// Done lets the downloader know that whatever previous hashes were taken
+// are processed. If the block count reaches zero and done is called
+// we reset the queue for the next batch of incoming hashes and blocks.
+func (d *Downloader) Done() {
+ d.queue.mu.Lock()
+ defer d.queue.mu.Unlock()
+
+ if len(d.queue.blocks) == 0 {
+ d.queue.resetNoTS()
+ }
}
-func (d *Downloader) getFromPeer(p *peer, hash common.Hash, ignoreInitial bool) error {
+// TakeBlocks takes blocks from the queue and yields them to the blockTaker handler
+// it's possible it yields no blocks
+func (d *Downloader) TakeBlocks() types.Blocks {
+ d.queue.mu.Lock()
+ defer d.queue.mu.Unlock()
+
+ var blocks types.Blocks
+ if len(d.queue.blocks) > 0 {
+ // Make sure the parent hash is known
+ if d.queue.blocks[0] != nil && !d.hasBlock(d.queue.blocks[0].ParentHash()) {
+ return nil
+ }
+
+ for _, block := range d.queue.blocks {
+ if block == nil {
+ break
+ }
+
+ blocks = append(blocks, block)
+ }
+ d.queue.blockOffset += len(blocks)
+ // delete the blocks from the slice and let them be garbage collected
+ // without this slice trick the blocks would stay in memory until nil
+ // would be assigned to d.queue.blocks
+ copy(d.queue.blocks, d.queue.blocks[len(blocks):])
+ for k, n := len(d.queue.blocks)-len(blocks), len(d.queue.blocks); k < n; k++ {
+ d.queue.blocks[k] = nil
+ }
+ d.queue.blocks = d.queue.blocks[:len(d.queue.blocks)-len(blocks)]
+
+ //d.queue.blocks = d.queue.blocks[len(blocks):]
+ if len(d.queue.blocks) == 0 {
+ d.queue.blocks = nil
+ }
+
+ }
+
+ return blocks
+}
+
+func (d *Downloader) Has(hash common.Hash) bool {
+ return d.queue.has(hash)
+}
+
+func (d *Downloader) getFromPeer(p *peer, hash common.Hash, ignoreInitial bool) (err error) {
d.activePeer = p.id
+ defer func() {
+ // reset on error
+ if err != nil {
+ d.queue.reset()
+ }
+ }()
glog.V(logger.Detail).Infoln("Synchronising with the network using:", p.id)
// Start the fetcher. This will block the update entirely
// interupts need to be send to the appropriate channels
// respectively.
- if err := d.startFetchingHashes(p, hash, ignoreInitial); err != nil {
- // handle error
- glog.V(logger.Debug).Infoln("Error fetching hashes:", err)
- // XXX Reset
+ if err = d.startFetchingHashes(p, hash, ignoreInitial); err != nil {
return err
}
// Start fetching blocks in paralel. The strategy is simple
// take any available peers, seserve a chunk for each peer available,
// let the peer deliver the chunkn and periodically check if a peer
- // has timedout. When done downloading, process blocks.
- if err := d.startFetchingBlocks(p); err != nil {
- glog.V(logger.Debug).Infoln("Error downloading blocks:", err)
- // XXX reset
+ // has timedout.
+ if err = d.startFetchingBlocks(p); err != nil {
return err
}
@@ -171,11 +240,15 @@ func (d *Downloader) getFromPeer(p *peer, hash common.Hash, ignoreInitial bool)
}
// XXX Make synchronous
-func (d *Downloader) startFetchingHashes(p *peer, hash common.Hash, ignoreInitial bool) error {
+func (d *Downloader) startFetchingHashes(p *peer, h common.Hash, ignoreInitial bool) error {
atomic.StoreInt32(&d.fetchingHashes, 1)
defer atomic.StoreInt32(&d.fetchingHashes, 0)
- glog.V(logger.Debug).Infof("Downloading hashes (%x) from %s", hash.Bytes()[:4], p.id)
+ if d.queue.has(h) {
+ return errAlreadyInPool
+ }
+
+ glog.V(logger.Debug).Infof("Downloading hashes (%x) from %s", h[:4], p.id)
start := time.Now()
@@ -183,23 +256,38 @@ func (d *Downloader) startFetchingHashes(p *peer, hash common.Hash, ignoreInitia
// In such circumstances we don't need to download the block so don't add it to the queue.
if !ignoreInitial {
// Add the hash to the queue first
- d.queue.hashPool.Add(hash)
+ d.queue.hashPool.Add(h)
}
// Get the first batch of hashes
- p.getHashes(hash)
+ p.getHashes(h)
- failureResponseTimer := time.NewTimer(hashTtl)
+ var (
+ failureResponseTimer = time.NewTimer(hashTtl)
+ attemptedPeers = make(map[string]bool) // attempted peers will help with retries
+ activePeer = p // active peer will help determine the current active peer
+ hash common.Hash // common and last hash
+ )
+ attemptedPeers[p.id] = true
out:
for {
select {
- case hashes := <-d.hashCh:
+ case hashPack := <-d.hashCh:
+ // make sure the active peer is giving us the hashes
+ if hashPack.peerId != activePeer.id {
+ glog.V(logger.Debug).Infof("Received hashes from incorrect peer(%s)\n", hashPack.peerId)
+ break
+ }
+
failureResponseTimer.Reset(hashTtl)
- var done bool // determines whether we're done fetching hashes (i.e. common hash found)
+ var (
+ hashes = hashPack.hashes
+ done bool // determines whether we're done fetching hashes (i.e. common hash found)
+ )
hashSet := set.New()
- for _, hash := range hashes {
- if d.hasBlock(hash) {
+ for _, hash = range hashes {
+ if d.hasBlock(hash) || d.queue.blockHashes.Has(hash) {
glog.V(logger.Debug).Infof("Found common hash %x\n", hash[:4])
done = true
@@ -212,24 +300,50 @@ out:
// Add hashes to the chunk set
if len(hashes) == 0 { // Make sure the peer actually gave you something valid
- glog.V(logger.Debug).Infof("Peer (%s) responded with empty hash set\n", p.id)
+ glog.V(logger.Debug).Infof("Peer (%s) responded with empty hash set\n", activePeer.id)
d.queue.reset()
return errEmptyHashSet
} else if !done { // Check if we're done fetching
// Get the next set of hashes
- p.getHashes(hashes[len(hashes)-1])
+ activePeer.getHashes(hash)
} else { // we're done
+ // The offset of the queue is determined by the highest known block
+ var offset int
+ if block := d.getBlock(hash); block != nil {
+ offset = int(block.NumberU64() + 1)
+ }
+ // allocate proper size for the queueue
+ d.queue.alloc(offset, d.queue.hashPool.Size())
+
break out
}
case <-failureResponseTimer.C:
glog.V(logger.Debug).Infof("Peer (%s) didn't respond in time for hash request\n", p.id)
- // TODO instead of reseting the queue select a new peer from which we can start downloading hashes.
- // 1. check for peer's best hash to be included in the current hash set;
- // 2. resume from last point (hashes[len(hashes)-1]) using the newly selected peer.
- d.queue.reset()
- return errTimeout
+ var p *peer // p will be set if a peer can be found
+ // Attempt to find a new peer by checking inclusion of peers best hash in our
+ // already fetched hash list. This can't guarantee 100% correctness but does
+ // a fair job. This is always either correct or false incorrect.
+ for id, peer := range d.peers {
+ if d.queue.hashPool.Has(peer.recentHash) && !attemptedPeers[id] {
+ p = peer
+ break
+ }
+ }
+
+ // if all peers have been tried, abort the process entirely or if the hash is
+ // the zero hash.
+ if p == nil || (hash == common.Hash{}) {
+ d.queue.reset()
+ return errTimeout
+ }
+
+ // set p to the active peer. this will invalidate any hashes that may be returned
+ // by our previous (delayed) peer.
+ activePeer = p
+ p.getHashes(hash)
+ glog.V(logger.Debug).Infof("Hash fetching switched to new peer(%s)\n", p.id)
}
}
glog.V(logger.Detail).Infof("Downloaded hashes (%d) in %v\n", d.queue.hashPool.Size(), time.Since(start))
@@ -257,11 +371,27 @@ out:
// If the peer was previously banned and failed to deliver it's pack
// in a reasonable time frame, ignore it's message.
if d.peers[blockPack.peerId] != nil {
+ err := d.queue.deliver(blockPack.peerId, blockPack.blocks)
+ if err != nil {
+ glog.V(logger.Debug).Infof("deliver failed for peer %s: %v\n", blockPack.peerId, err)
+ // FIXME d.UnregisterPeer(blockPack.peerId)
+ break
+ }
+
+ if glog.V(logger.Debug) {
+ glog.Infof("adding %d blocks from: %s\n", len(blockPack.blocks), blockPack.peerId)
+ }
d.peers[blockPack.peerId].promote()
- d.queue.deliver(blockPack.peerId, blockPack.blocks)
d.peers.setState(blockPack.peerId, idleState)
}
case <-ticker.C:
+ // after removing bad peers make sure we actually have suffucient peer left to keep downlading
+ if len(d.peers) == 0 {
+ d.queue.reset()
+
+ return errNoPeers
+ }
+
// If there are unrequested hashes left start fetching
// from the available peers.
if d.queue.hashPool.Size() > 0 {
@@ -310,7 +440,7 @@ out:
if time.Since(chunk.itime) > blockTtl {
badPeers = append(badPeers, pid)
// remove peer as good peer from peer list
- //d.UnregisterPeer(pid)
+ // FIXME d.UnregisterPeer(pid)
}
}
d.queue.mu.Unlock()
@@ -354,112 +484,14 @@ func (d *Downloader) AddHashes(id string, hashes []common.Hash) error {
return fmt.Errorf("received hashes from %s while active peer is %s", id, d.activePeer)
}
- d.hashCh <- hashes
-
- return nil
-}
-
-// Add an (unrequested) block to the downloader. This is usually done through the
-// NewBlockMsg by the protocol handler.
-// Adding blocks is done synchronously. if there are missing blocks, blocks will be
-// fetched first. If the downloader is busy or if some other processed failed an error
-// will be returned.
-func (d *Downloader) AddBlock(id string, block *types.Block, td *big.Int) error {
- hash := block.Hash()
-
- if d.hasBlock(hash) {
- return fmt.Errorf("known block %x", hash.Bytes()[:4])
- }
-
- peer := d.peers.getPeer(id)
- // if the peer is in our healthy list of peers; update the td
- // and add the block. Otherwise just ignore it
- if peer == nil {
- glog.V(logger.Detail).Infof("Ignored block from bad peer %s\n", id)
- return errBadPeer
- }
-
- peer.mu.Lock()
- peer.recentHash = block.Hash()
- peer.mu.Unlock()
- peer.promote()
-
- glog.V(logger.Detail).Infoln("Inserting new block from:", id)
- d.queue.addBlock(id, block)
-
- // if neither go ahead to process
- if d.isBusy() {
- return errBusy
- }
-
- // Check if the parent of the received block is known.
- // If the block is not know, request it otherwise, request.
- phash := block.ParentHash()
- if !d.hasBlock(phash) {
- glog.V(logger.Detail).Infof("Missing parent %x, requires fetching\n", phash.Bytes()[:4])
-
- // Get the missing hashes from the peer (synchronously)
- err := d.getFromPeer(peer, peer.recentHash, true)
- if err != nil {
- return err
- }
+ if glog.V(logger.Detail) && len(hashes) != 0 {
+ from, to := hashes[0], hashes[len(hashes)-1]
+ glog.Infof("adding %d (T=%d) hashes [ %x / %x ] from: %s\n", len(hashes), d.queue.hashPool.Size(), from[:4], to[:4], id)
}
- return d.process(peer)
-}
-
-func (d *Downloader) process(peer *peer) error {
- atomic.StoreInt32(&d.processingBlocks, 1)
- defer atomic.StoreInt32(&d.processingBlocks, 0)
+ d.hashCh <- hashPack{id, hashes}
- // XXX this will move when optimised
- // Sort the blocks by number. This bit needs much improvement. Right now
- // it assumes full honesty form peers (i.e. it's not checked when the blocks
- // link). We should at least check whihc queue match. This code could move
- // to a seperate goroutine where it periodically checks for linked pieces.
- types.BlockBy(types.Number).Sort(d.queue.blocks)
- if len(d.queue.blocks) == 0 {
- return nil
- }
-
- var (
- blocks = d.queue.blocks
- err error
- )
- glog.V(logger.Debug).Infof("Inserting chain with %d blocks (#%v - #%v)\n", len(blocks), blocks[0].Number(), blocks[len(blocks)-1].Number())
-
- // Loop untill we're out of blocks
- for len(blocks) != 0 {
- max := int(math.Min(float64(len(blocks)), 256))
- // TODO check for parent error. When there's a parent error we should stop
- // processing and start requesting the `block.hash` so that it's parent and
- // grandparents can be requested and queued.
- var i int
- i, err = d.insertChain(blocks[:max])
- if err != nil && core.IsParentErr(err) {
- // Ignore the missing blocks. Handler should take care of anything that's missing.
- glog.V(logger.Debug).Infof("Ignored block with missing parent (%d)\n", i)
- blocks = blocks[i+1:]
-
- continue
- } else if err != nil {
- // immediatly unregister the false peer but do not disconnect
- d.UnregisterPeer(d.activePeer)
- // Reset chain completely. This needs much, much improvement.
- // instead: check all blocks leading down to this block false block and remove it
- blocks = nil
- break
- }
- blocks = blocks[max:]
- }
-
- // This will allow the GC to remove the in memory blocks
- if len(blocks) == 0 {
- d.queue.blocks = nil
- } else {
- d.queue.blocks = blocks
- }
- return err
+ return nil
}
func (d *Downloader) isFetchingHashes() bool {
@@ -470,12 +502,8 @@ func (d *Downloader) isDownloadingBlocks() bool {
return atomic.LoadInt32(&d.downloadingBlocks) == 1
}
-func (d *Downloader) isProcessing() bool {
- return atomic.LoadInt32(&d.processingBlocks) == 1
-}
-
func (d *Downloader) isBusy() bool {
- return d.isFetchingHashes() || d.isDownloadingBlocks() || d.isProcessing()
+ return d.isFetchingHashes() || d.isDownloadingBlocks()
}
func (d *Downloader) IsBusy() bool {
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index 5518163ca..872ea02eb 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -8,8 +8,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/logger/glog"
)
var knownHash = common.Hash{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -25,36 +23,47 @@ func createHashes(start, amount int) (hashes []common.Hash) {
return
}
+func createBlock(i int, prevHash, hash common.Hash) *types.Block {
+ header := &types.Header{Number: big.NewInt(int64(i))}
+ block := types.NewBlockWithHeader(header)
+ block.HeaderHash = hash
+ block.ParentHeaderHash = knownHash
+ return block
+}
+
func createBlocksFromHashes(hashes []common.Hash) map[common.Hash]*types.Block {
blocks := make(map[common.Hash]*types.Block)
+
for i, hash := range hashes {
- header := &types.Header{Number: big.NewInt(int64(i))}
- blocks[hash] = types.NewBlockWithHeader(header)
- blocks[hash].HeaderHash = hash
+ blocks[hash] = createBlock(len(hashes)-i, knownHash, hash)
}
return blocks
}
type downloadTester struct {
- downloader *Downloader
- hashes []common.Hash
- blocks map[common.Hash]*types.Block
- t *testing.T
- pcount int
- done chan bool
-
- insertedBlocks int
+ downloader *Downloader
+ hashes []common.Hash
+ blocks map[common.Hash]*types.Block
+ t *testing.T
+ pcount int
+ done chan bool
+ activePeerId string
}
func newTester(t *testing.T, hashes []common.Hash, blocks map[common.Hash]*types.Block) *downloadTester {
tester := &downloadTester{t: t, hashes: hashes, blocks: blocks, done: make(chan bool)}
- downloader := New(tester.hasBlock, tester.insertChain)
+ downloader := New(tester.hasBlock, tester.getBlock)
tester.downloader = downloader
return tester
}
+func (dl *downloadTester) sync(peerId string, hash common.Hash) error {
+ dl.activePeerId = peerId
+ return dl.downloader.Synchronise(peerId, hash)
+}
+
func (dl *downloadTester) hasBlock(hash common.Hash) bool {
if knownHash == hash {
return true
@@ -62,14 +71,12 @@ func (dl *downloadTester) hasBlock(hash common.Hash) bool {
return false
}
-func (dl *downloadTester) insertChain(blocks types.Blocks) (int, error) {
- dl.insertedBlocks += len(blocks)
-
- return 0, nil
+func (dl *downloadTester) getBlock(hash common.Hash) *types.Block {
+ return dl.blocks[knownHash]
}
func (dl *downloadTester) getHashes(hash common.Hash) error {
- dl.downloader.hashCh <- dl.hashes
+ dl.downloader.AddHashes(dl.activePeerId, dl.hashes)
return nil
}
@@ -102,9 +109,6 @@ func (dl *downloadTester) badBlocksPeer(id string, td *big.Int, hash common.Hash
}
func TestDownload(t *testing.T) {
- glog.SetV(logger.Detail)
- glog.SetToStderr(true)
-
minDesiredPeerCount = 4
blockTtl = 1 * time.Second
@@ -117,21 +121,20 @@ func TestDownload(t *testing.T) {
tester.newPeer("peer2", big.NewInt(0), common.Hash{})
tester.badBlocksPeer("peer3", big.NewInt(0), common.Hash{})
tester.badBlocksPeer("peer4", big.NewInt(0), common.Hash{})
+ tester.activePeerId = "peer1"
- err := tester.downloader.Synchronise("peer1", hashes[0])
+ err := tester.sync("peer1", hashes[0])
if err != nil {
t.Error("download error", err)
}
- if tester.insertedBlocks != targetBlocks {
- t.Error("expected", targetBlocks, "have", tester.insertedBlocks)
+ inqueue := len(tester.downloader.queue.blocks)
+ if inqueue != targetBlocks {
+ t.Error("expected", targetBlocks, "have", inqueue)
}
}
func TestMissing(t *testing.T) {
- glog.SetV(logger.Detail)
- glog.SetToStderr(true)
-
targetBlocks := 1000
hashes := createHashes(0, 1000)
extraHashes := createHashes(1001, 1003)
@@ -143,12 +146,38 @@ func TestMissing(t *testing.T) {
hashes = append(extraHashes, hashes[:len(hashes)-1]...)
tester.newPeer("peer2", big.NewInt(0), common.Hash{})
- err := tester.downloader.Synchronise("peer1", hashes[0])
+ err := tester.sync("peer1", hashes[0])
+ if err != nil {
+ t.Error("download error", err)
+ }
+
+ inqueue := len(tester.downloader.queue.blocks)
+ if inqueue != targetBlocks {
+ t.Error("expected", targetBlocks, "have", inqueue)
+ }
+}
+
+func TestTaking(t *testing.T) {
+ minDesiredPeerCount = 4
+ blockTtl = 1 * time.Second
+
+ targetBlocks := 1000
+ hashes := createHashes(0, targetBlocks)
+ blocks := createBlocksFromHashes(hashes)
+ tester := newTester(t, hashes, blocks)
+
+ tester.newPeer("peer1", big.NewInt(10000), hashes[0])
+ tester.newPeer("peer2", big.NewInt(0), common.Hash{})
+ tester.badBlocksPeer("peer3", big.NewInt(0), common.Hash{})
+ tester.badBlocksPeer("peer4", big.NewInt(0), common.Hash{})
+
+ err := tester.sync("peer1", hashes[0])
if err != nil {
t.Error("download error", err)
}
- if tester.insertedBlocks != targetBlocks {
- t.Error("expected", targetBlocks, "have", tester.insertedBlocks)
+ bs1 := tester.downloader.TakeBlocks()
+ if len(bs1) != 1000 {
+ t.Error("expected to take 1000, got", len(bs1))
}
}
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index a21a44706..1b63a5ffb 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -1,6 +1,7 @@
package downloader
import (
+ "fmt"
"math"
"sync"
"time"
@@ -18,7 +19,9 @@ type queue struct {
mu sync.Mutex
fetching map[string]*chunk
- blocks []*types.Block
+
+ blockOffset int
+ blocks []*types.Block
}
func newqueue() *queue {
@@ -34,6 +37,10 @@ func (c *queue) reset() {
c.mu.Lock()
defer c.mu.Unlock()
+ c.resetNoTS()
+}
+func (c *queue) resetNoTS() {
+ c.blockOffset = 0
c.hashPool.Clear()
c.fetchPool.Clear()
c.blockHashes.Clear()
@@ -41,6 +48,10 @@ func (c *queue) reset() {
c.fetching = make(map[string]*chunk)
}
+func (c *queue) size() int {
+ return c.hashPool.Size() + c.blockHashes.Size() + c.fetchPool.Size()
+}
+
// reserve a `max` set of hashes for `p` peer.
func (c *queue) get(p *peer, max int) *chunk {
c.mu.Lock()
@@ -89,22 +100,27 @@ func (c *queue) get(p *peer, max int) *chunk {
}
func (c *queue) has(hash common.Hash) bool {
- return c.hashPool.Has(hash) || c.fetchPool.Has(hash)
+ return c.hashPool.Has(hash) || c.fetchPool.Has(hash) || c.blockHashes.Has(hash)
}
-func (c *queue) addBlock(id string, block *types.Block) {
+func (c *queue) getBlock(hash common.Hash) *types.Block {
c.mu.Lock()
defer c.mu.Unlock()
- // when adding a block make sure it doesn't already exist
- if !c.blockHashes.Has(block.Hash()) {
- c.hashPool.Remove(block.Hash())
- c.blocks = append(c.blocks, block)
+ if !c.blockHashes.Has(hash) {
+ return nil
+ }
+
+ for _, block := range c.blocks {
+ if block.Hash() == hash {
+ return block
+ }
}
+ return nil
}
// deliver delivers a chunk to the queue that was requested of the peer
-func (c *queue) deliver(id string, blocks []*types.Block) {
+func (c *queue) deliver(id string, blocks []*types.Block) (err error) {
c.mu.Lock()
defer c.mu.Unlock()
@@ -119,16 +135,45 @@ func (c *queue) deliver(id string, blocks []*types.Block) {
chunk.peer.ignored.Merge(chunk.hashes)
}
+ // Add the blocks
+ for i, block := range blocks {
+ // See (1) for future limitation
+ n := int(block.NumberU64()) - c.blockOffset
+ if n > len(c.blocks) || n < 0 {
+ // set the error and set the blocks which could be processed
+ // abort the rest of the blocks (FIXME this could be improved)
+ err = fmt.Errorf("received block which overflow (N=%v O=%v)", block.Number(), c.blockOffset)
+ blocks = blocks[:i]
+ break
+ }
+ c.blocks[n] = block
+ }
// seperate the blocks and the hashes
blockHashes := chunk.fetchedHashes(blocks)
// merge block hashes
c.blockHashes.Merge(blockHashes)
- // Add the blocks
- c.blocks = append(c.blocks, blocks...)
// Add back whatever couldn't be delivered
c.hashPool.Merge(chunk.hashes)
+ // Remove the hashes from the fetch pool
c.fetchPool.Separate(chunk.hashes)
}
+
+ return
+}
+
+func (c *queue) alloc(offset, size int) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.blockOffset < offset {
+ c.blockOffset = offset
+ }
+
+ // (1) XXX at some point we could limit allocation to memory and use the disk
+ // to store future blocks.
+ if len(c.blocks) < size {
+ c.blocks = append(c.blocks, make([]*types.Block, size)...)
+ }
}
// puts puts sets of hashes on to the queue for fetching
diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go
new file mode 100644
index 000000000..b163bd9c7
--- /dev/null
+++ b/eth/downloader/queue_test.go
@@ -0,0 +1,62 @@
+package downloader
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "gopkg.in/fatih/set.v0"
+)
+
+func createHashSet(hashes []common.Hash) *set.Set {
+ hset := set.New()
+
+ for _, hash := range hashes {
+ hset.Add(hash)
+ }
+
+ return hset
+}
+
+func createBlocksFromHashSet(hashes *set.Set) []*types.Block {
+ blocks := make([]*types.Block, hashes.Size())
+
+ var i int
+ hashes.Each(func(v interface{}) bool {
+ blocks[i] = createBlock(i, common.Hash{}, v.(common.Hash))
+ i++
+ return true
+ })
+
+ return blocks
+}
+
+func TestChunking(t *testing.T) {
+ queue := newqueue()
+ peer1 := newPeer("peer1", common.Hash{}, nil, nil)
+ peer2 := newPeer("peer2", common.Hash{}, nil, nil)
+
+ // 99 + 1 (1 == known genesis hash)
+ hashes := createHashes(0, 99)
+ hashSet := createHashSet(hashes)
+ queue.put(hashSet)
+
+ chunk1 := queue.get(peer1, 99)
+ if chunk1 == nil {
+ t.Errorf("chunk1 is nil")
+ t.FailNow()
+ }
+ chunk2 := queue.get(peer2, 99)
+ if chunk2 == nil {
+ t.Errorf("chunk2 is nil")
+ t.FailNow()
+ }
+
+ if chunk1.hashes.Size() != 99 {
+ t.Error("expected chunk1 hashes to be 99, got", chunk1.hashes.Size())
+ }
+
+ if chunk2.hashes.Size() != 1 {
+ t.Error("expected chunk1 hashes to be 1, got", chunk2.hashes.Size())
+ }
+}
diff --git a/eth/handler.go b/eth/handler.go
index fecd71632..1e0663816 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -1,39 +1,5 @@
package eth
-// XXX Fair warning, most of the code is re-used from the old protocol. Please be aware that most of this will actually change
-// The idea is that most of the calls within the protocol will become synchronous.
-// Block downloading and block processing will be complete seperate processes
-/*
-# Possible scenarios
-
-// Synching scenario
-// Use the best peer to synchronise
-blocks, err := pm.downloader.Synchronise()
-if err != nil {
- // handle
- break
-}
-pm.chainman.InsertChain(blocks)
-
-// Receiving block with known parent
-if parent_exist {
- if err := pm.chainman.InsertChain(block); err != nil {
- // handle
- break
- }
- pm.BroadcastBlock(block)
-}
-
-// Receiving block with unknown parent
-blocks, err := pm.downloader.SynchroniseWithPeer(peer)
-if err != nil {
- // handle
- break
-}
-pm.chainman.InsertChain(blocks)
-
-*/
-
import (
"fmt"
"math"
@@ -54,7 +20,9 @@ import (
const (
peerCountTimeout = 12 * time.Second // Amount of time it takes for the peer handler to ignore minDesiredPeerCount
- minDesiredPeerCount = 5 // Amount of peers desired to start syncing
+ blockProcTimer = 500 * time.Millisecond
+ minDesiredPeerCount = 5 // Amount of peers desired to start syncing
+ blockProcAmount = 256
)
func errResp(code errCode, format string, v ...interface{}) error {
@@ -91,6 +59,10 @@ type ProtocolManager struct {
newPeerCh chan *peer
quitSync chan struct{}
+ // wait group is used for graceful shutdowns during downloading
+ // and processing
+ wg sync.WaitGroup
+ quit bool
}
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
@@ -122,60 +94,11 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
return manager
}
-func (pm *ProtocolManager) syncHandler() {
- // itimer is used to determine when to start ignoring `minDesiredPeerCount`
- itimer := time.NewTimer(peerCountTimeout)
-out:
- for {
- select {
- case <-pm.newPeerCh:
- // Meet the `minDesiredPeerCount` before we select our best peer
- if len(pm.peers) < minDesiredPeerCount {
- break
- }
-
- // Find the best peer
- peer := getBestPeer(pm.peers)
- if peer == nil {
- glog.V(logger.Debug).Infoln("Sync attempt cancelled. No peers available")
- }
-
- itimer.Stop()
- go pm.synchronise(peer)
- case <-itimer.C:
- // The timer will make sure that the downloader keeps an active state
- // in which it attempts to always check the network for highest td peers
- // Either select the peer or restart the timer if no peers could
- // be selected.
- if peer := getBestPeer(pm.peers); peer != nil {
- go pm.synchronise(peer)
- } else {
- itimer.Reset(5 * time.Second)
- }
- case <-pm.quitSync:
- break out
- }
- }
-}
-
-func (pm *ProtocolManager) synchronise(peer *peer) {
- // Make sure the peer's TD is higher than our own. If not drop.
- if peer.td.Cmp(pm.chainman.Td()) <= 0 {
- return
- }
- // Check downloader if it's busy so it doesn't show the sync message
- // for every attempty
- if pm.downloader.IsBusy() {
- return
- }
-
- glog.V(logger.Info).Infof("Synchronisation attempt using %s TD=%v\n", peer.id, peer.td)
- // Get the hashes from the peer (synchronously)
- err := pm.downloader.Synchronise(peer.id, peer.recentHash)
- if err != nil {
- // handle error
- glog.V(logger.Debug).Infoln("error downloading:", err)
- }
+func (pm *ProtocolManager) removePeer(peer *peer) {
+ pm.pmu.Lock()
+ defer pm.pmu.Unlock()
+ pm.downloader.UnregisterPeer(peer.id)
+ delete(pm.peers, peer.id)
}
func (pm *ProtocolManager) Start() {
@@ -187,18 +110,26 @@ func (pm *ProtocolManager) Start() {
pm.minedBlockSub = pm.eventMux.Subscribe(core.NewMinedBlockEvent{})
go pm.minedBroadcastLoop()
- // sync handler
- go pm.syncHandler()
+ go pm.update()
}
func (pm *ProtocolManager) Stop() {
+ // Showing a log message. During download / process this could actually
+ // take between 5 to 10 seconds and therefor feedback is required.
+ glog.V(logger.Info).Infoln("Stopping ethereum protocol handler...")
+
+ pm.quit = true
pm.txSub.Unsubscribe() // quits txBroadcastLoop
pm.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop
close(pm.quitSync) // quits the sync handler
+
+ // Wait for any process action
+ pm.wg.Wait()
+
+ glog.V(logger.Info).Infoln("Ethereum protocol handler stopped")
}
func (pm *ProtocolManager) newPeer(pv, nv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
-
td, current, genesis := pm.chainman.Status()
return newPeer(pv, nv, genesis, current, td, p, rw)
@@ -214,10 +145,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
pm.downloader.RegisterPeer(p.id, p.recentHash, p.requestHashes, p.requestBlocks)
defer func() {
- pm.pmu.Lock()
- defer pm.pmu.Unlock()
- delete(pm.peers, p.id)
- pm.downloader.UnregisterPeer(p.id)
+ pm.removePeer(p)
}()
// propagate existing transactions. new transactions appearing
@@ -352,6 +280,9 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
// Add the block hash as a known hash to the peer. This will later be used to determine
// who should receive this.
p.blockHashes.Add(hash)
+ // update the peer info
+ p.recentHash = hash
+ p.td = request.TD
_, chainHead, _ := self.chainman.Status()
@@ -376,24 +307,24 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
// Attempt to insert the newly received by checking if the parent exists.
// if the parent exists we process the block and propagate to our peers
- // if the parent does not exists we delegate to the downloader.
+ // otherwise synchronise with the peer
if self.chainman.HasBlock(request.Block.ParentHash()) {
if _, err := self.chainman.InsertChain(types.Blocks{request.Block}); err != nil {
- // handle error
+ glog.V(logger.Error).Infoln("removed peer (", p.id, ") due to block error")
+
+ self.removePeer(p)
+
+ return nil
+ }
+
+ if err := self.verifyTd(p, request); err != nil {
+ glog.V(logger.Error).Infoln(err)
+ // XXX for now return nil so it won't disconnect (we should in the future)
return nil
}
self.BroadcastBlock(hash, request.Block)
} else {
- // adding blocks is synchronous
- go func() {
- // TODO check parent error
- err := self.downloader.AddBlock(p.id, request.Block, request.TD)
- if err != nil {
- glog.V(logger.Detail).Infoln("downloader err:", err)
- return
- }
- self.BroadcastBlock(hash, request.Block)
- }()
+ go self.synchronise(p)
}
default:
return errResp(ErrInvalidMsgCode, "%v", msg.Code)
@@ -401,6 +332,16 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
return nil
}
+func (pm *ProtocolManager) verifyTd(peer *peer, request newBlockMsgData) error {
+ if request.Block.Td.Cmp(request.TD) != 0 {
+ glog.V(logger.Detail).Infoln(peer)
+
+ return fmt.Errorf("invalid TD on block(%v) from peer(%s): block.td=%v, request.td=%v", request.Block.Number(), peer.id, request.Block.Td, request.TD)
+ }
+
+ return nil
+}
+
// BroadcastBlock will propagate the block to its connected peers. It will sort
// out which peers do not contain the block in their block set and will do a
// sqrt(peers) to determine the amount of peers we broadcast to.
@@ -421,7 +362,7 @@ func (pm *ProtocolManager) BroadcastBlock(hash common.Hash, block *types.Block)
for _, peer := range peers {
peer.sendNewBlock(block)
}
- glog.V(logger.Detail).Infoln("broadcast block to", len(peers), "peers. Total propagation time:", time.Since(block.ReceivedAt))
+ glog.V(logger.Detail).Infoln("broadcast block to", len(peers), "peers. Total processing time:", time.Since(block.ReceivedAt))
}
// BroadcastTx will propagate the block to its connected peers. It will sort
diff --git a/eth/sync.go b/eth/sync.go
new file mode 100644
index 000000000..9e8b21a7c
--- /dev/null
+++ b/eth/sync.go
@@ -0,0 +1,108 @@
+package eth
+
+import (
+ "math"
+ "time"
+
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
+)
+
+// Sync contains all synchronisation code for the eth protocol
+
+func (pm *ProtocolManager) update() {
+ // itimer is used to determine when to start ignoring `minDesiredPeerCount`
+ itimer := time.NewTimer(peerCountTimeout)
+ // btimer is used for picking of blocks from the downloader
+ btimer := time.Tick(blockProcTimer)
+
+ for {
+ select {
+ case <-pm.newPeerCh:
+ // Meet the `minDesiredPeerCount` before we select our best peer
+ if len(pm.peers) < minDesiredPeerCount {
+ break
+ }
+
+ // Find the best peer
+ peer := getBestPeer(pm.peers)
+ if peer == nil {
+ glog.V(logger.Debug).Infoln("Sync attempt cancelled. No peers available")
+ }
+
+ itimer.Stop()
+ go pm.synchronise(peer)
+ case <-itimer.C:
+ // The timer will make sure that the downloader keeps an active state
+ // in which it attempts to always check the network for highest td peers
+ // Either select the peer or restart the timer if no peers could
+ // be selected.
+ if peer := getBestPeer(pm.peers); peer != nil {
+ go pm.synchronise(peer)
+ } else {
+ itimer.Reset(5 * time.Second)
+ }
+ case <-btimer:
+ go pm.processBlocks()
+ case <-pm.quitSync:
+ return
+ }
+ }
+}
+
+// processBlocks will attempt to reconstruct a chain by checking the first item and check if it's
+// a known parent. The first block in the chain may be unknown during downloading. When the
+// downloader isn't downloading blocks will be dropped with an unknown parent until either it
+// has depleted the list or found a known parent.
+func (pm *ProtocolManager) processBlocks() error {
+ pm.wg.Add(1)
+ defer pm.wg.Done()
+
+ blocks := pm.downloader.TakeBlocks()
+ if len(blocks) == 0 {
+ return nil
+ }
+ defer pm.downloader.Done()
+
+ glog.V(logger.Debug).Infof("Inserting chain with %d blocks (#%v - #%v)\n", len(blocks), blocks[0].Number(), blocks[len(blocks)-1].Number())
+
+ for len(blocks) != 0 && !pm.quit {
+ max := int(math.Min(float64(len(blocks)), float64(blockProcAmount)))
+ _, err := pm.chainman.InsertChain(blocks[:max])
+ if err != nil {
+ return err
+ }
+ blocks = blocks[max:]
+ }
+ return nil
+}
+
+func (pm *ProtocolManager) synchronise(peer *peer) {
+ // Make sure the peer's TD is higher than our own. If not drop.
+ if peer.td.Cmp(pm.chainman.Td()) <= 0 {
+ return
+ }
+ // Check downloader if it's busy so it doesn't show the sync message
+ // for every attempty
+ if pm.downloader.IsBusy() {
+ return
+ }
+
+ // FIXME if we have the hash in our chain and the TD of the peer is
+ // much higher than ours, something is wrong with us or the peer.
+ // Check if the hash is on our own chain
+ if pm.chainman.HasBlock(peer.recentHash) {
+ return
+ }
+
+ // Get the hashes from the peer (synchronously)
+ err := pm.downloader.Synchronise(peer.id, peer.recentHash)
+ if err != nil && err == downloader.ErrBadPeer {
+ glog.V(logger.Debug).Infoln("removed peer from peer set due to bad action")
+ pm.removePeer(peer)
+ } else if err != nil {
+ // handle error
+ glog.V(logger.Detail).Infoln("error downloading:", err)
+ }
+}
diff --git a/jsre/jsre.go b/jsre/jsre.go
index a49422a12..7549b5e1e 100644
--- a/jsre/jsre.go
+++ b/jsre/jsre.go
@@ -3,10 +3,11 @@ package jsre
import (
"fmt"
"io/ioutil"
-
- "github.com/robertkrimen/otto"
+ "sync"
+ "time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/robertkrimen/otto"
)
/*
@@ -20,59 +21,261 @@ It provides some helper functions to
type JSRE struct {
assetPath string
vm *otto.Otto
+
+ evalQueue chan *evalReq
+ stopEventLoop chan bool
+ loopWg sync.WaitGroup
+}
+
+// jsTimer is a single timer instance with a callback function
+type jsTimer struct {
+ timer *time.Timer
+ duration time.Duration
+ interval bool
+ call otto.FunctionCall
}
+// evalResult is a structure to store the result of any serialized vm execution
+type evalResult struct {
+ result otto.Value
+ err error
+}
+
+// evalReq is a serialized vm execution request put in evalQueue and processed by runEventLoop
+type evalReq struct {
+ fn func(res *evalResult)
+ done chan bool
+ res evalResult
+}
+
+// runtime must be stopped with Stop() after use and cannot be used after stopping
func New(assetPath string) *JSRE {
re := &JSRE{
- assetPath,
- otto.New(),
+ assetPath: assetPath,
+ vm: otto.New(),
}
// load prettyprint func definition
re.vm.Run(pp_js)
re.vm.Set("loadScript", re.loadScript)
+ re.evalQueue = make(chan *evalReq)
+ re.stopEventLoop = make(chan bool)
+ re.loopWg.Add(1)
+ go re.runEventLoop()
+
return re
}
+// this function runs a piece of JS code either in a serialized way (when useEQ is true) or instantly, circumventing the evalQueue
+func (self *JSRE) run(src interface{}, useEQ bool) (value otto.Value, err error) {
+ if useEQ {
+ done := make(chan bool)
+ req := &evalReq{
+ fn: func(res *evalResult) {
+ res.result, res.err = self.vm.Run(src)
+ },
+ done: done,
+ }
+ self.evalQueue <- req
+ <-done
+ return req.res.result, req.res.err
+ } else {
+ return self.vm.Run(src)
+ }
+}
+
+/*
+This function runs the main event loop from a goroutine that is started
+ when JSRE is created. Use Stop() before exiting to properly stop it.
+The event loop processes vm access requests from the evalQueue in a
+ serialized way and calls timer callback functions at the appropriate time.
+
+Exported functions always access the vm through the event queue. You can
+ call the functions of the otto vm directly to circumvent the queue. These
+ functions should be used if and only if running a routine that was already
+ called from JS through an RPC call.
+*/
+func (self *JSRE) runEventLoop() {
+ registry := map[*jsTimer]*jsTimer{}
+ ready := make(chan *jsTimer)
+
+ newTimer := func(call otto.FunctionCall, interval bool) (*jsTimer, otto.Value) {
+
+ delay, _ := call.Argument(1).ToInteger()
+ if 0 >= delay {
+ delay = 1
+ }
+ timer := &jsTimer{
+ duration: time.Duration(delay) * time.Millisecond,
+ call: call,
+ interval: interval,
+ }
+ registry[timer] = timer
+
+ timer.timer = time.AfterFunc(timer.duration, func() {
+ ready <- timer
+ })
+
+ value, err := call.Otto.ToValue(timer)
+ if err != nil {
+ panic(err)
+ }
+
+ return timer, value
+ }
+
+ setTimeout := func(call otto.FunctionCall) otto.Value {
+ _, value := newTimer(call, false)
+ return value
+ }
+
+ setInterval := func(call otto.FunctionCall) otto.Value {
+ _, value := newTimer(call, true)
+ return value
+ }
+
+ clearTimeout := func(call otto.FunctionCall) otto.Value {
+ timer, _ := call.Argument(0).Export()
+ if timer, ok := timer.(*jsTimer); ok {
+ timer.timer.Stop()
+ delete(registry, timer)
+ }
+ return otto.UndefinedValue()
+ }
+
+ var waitForCallbacks bool
+
+loop:
+ for {
+ select {
+ case timer := <-ready:
+ // execute callback, remove/reschedule the timer
+ var arguments []interface{}
+ if len(timer.call.ArgumentList) > 2 {
+ tmp := timer.call.ArgumentList[2:]
+ arguments = make([]interface{}, 2+len(tmp))
+ for i, value := range tmp {
+ arguments[i+2] = value
+ }
+ } else {
+ arguments = make([]interface{}, 1)
+ }
+ arguments[0] = timer.call.ArgumentList[0]
+ _, err := self.vm.Call(`Function.call.call`, nil, arguments...)
+
+ if err != nil {
+ break loop
+ }
+ if timer.interval {
+ timer.timer.Reset(timer.duration)
+ } else {
+ delete(registry, timer)
+ if waitForCallbacks && (len(registry) == 0) {
+ break loop
+ }
+ }
+ case evalReq := <-self.evalQueue:
+ // run the code, send the result back
+ self.vm.Set("setTimeout", setTimeout)
+ self.vm.Set("setInterval", setInterval)
+ self.vm.Set("clearTimeout", clearTimeout)
+ self.vm.Set("clearInterval", clearTimeout)
+ evalReq.fn(&evalReq.res)
+ close(evalReq.done)
+ if waitForCallbacks && (len(registry) == 0) {
+ break loop
+ }
+ case waitForCallbacks = <-self.stopEventLoop:
+ if !waitForCallbacks || (len(registry) == 0) {
+ break loop
+ }
+ }
+ }
+
+ for _, timer := range registry {
+ timer.timer.Stop()
+ delete(registry, timer)
+ }
+
+ self.loopWg.Done()
+}
+
+// stops the event loop before exit, optionally waits for all timers to expire
+func (self *JSRE) Stop(waitForCallbacks bool) {
+ self.stopEventLoop <- waitForCallbacks
+ self.loopWg.Wait()
+}
+
// Exec(file) loads and runs the contents of a file
// if a relative path is given, the jsre's assetPath is used
func (self *JSRE) Exec(file string) error {
- return self.exec(common.AbsolutePath(self.assetPath, file))
+ return self.exec(common.AbsolutePath(self.assetPath, file), true)
}
-func (self *JSRE) exec(path string) error {
+// circumvents the eval queue, see runEventLoop
+func (self *JSRE) execWithoutEQ(file string) error {
+ return self.exec(common.AbsolutePath(self.assetPath, file), false)
+}
+
+func (self *JSRE) exec(path string, useEQ bool) error {
code, err := ioutil.ReadFile(path)
if err != nil {
return err
}
- _, err = self.vm.Run(code)
+ _, err = self.run(code, useEQ)
return err
}
+// assigns value v to a variable in the JS environment
func (self *JSRE) Bind(name string, v interface{}) (err error) {
- self.vm.Set(name, v)
+ self.Set(name, v)
return
}
+// runs a piece of JS code
func (self *JSRE) Run(code string) (otto.Value, error) {
- return self.vm.Run(code)
+ return self.run(code, true)
}
+// returns the value of a variable in the JS environment
func (self *JSRE) Get(ns string) (otto.Value, error) {
- return self.vm.Get(ns)
+ done := make(chan bool)
+ req := &evalReq{
+ fn: func(res *evalResult) {
+ res.result, res.err = self.vm.Get(ns)
+ },
+ done: done,
+ }
+ self.evalQueue <- req
+ <-done
+ return req.res.result, req.res.err
}
+// assigns value v to a variable in the JS environment
func (self *JSRE) Set(ns string, v interface{}) error {
- return self.vm.Set(ns, v)
+ done := make(chan bool)
+ req := &evalReq{
+ fn: func(res *evalResult) {
+ res.err = self.vm.Set(ns, v)
+ },
+ done: done,
+ }
+ self.evalQueue <- req
+ <-done
+ return req.res.err
}
+/*
+Executes a JS script from inside the currently executing JS code.
+Should only be called from inside an RPC routine.
+*/
func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
file, err := call.Argument(0).ToString()
if err != nil {
return otto.FalseValue()
}
- if err := self.Exec(file); err != nil {
+ if err := self.execWithoutEQ(file); err != nil { // loadScript is only called from inside js
fmt.Println("err:", err)
return otto.FalseValue()
}
@@ -80,6 +283,7 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
return otto.TrueValue()
}
+// uses the "prettyPrint" JS function to format a value
func (self *JSRE) PrettyPrint(v interface{}) (val otto.Value, err error) {
var method otto.Value
v, err = self.vm.ToValue(v)
@@ -93,6 +297,7 @@ func (self *JSRE) PrettyPrint(v interface{}) (val otto.Value, err error) {
return method.Call(method, v)
}
+// creates an otto value from a go type
func (self *JSRE) ToVal(v interface{}) otto.Value {
result, err := self.vm.ToValue(v)
if err != nil {
@@ -102,6 +307,7 @@ func (self *JSRE) ToVal(v interface{}) otto.Value {
return result
}
+// evaluates JS function and returns result in a pretty printed string format
func (self *JSRE) Eval(code string) (s string, err error) {
var val otto.Value
val, err = self.Run(code)
@@ -115,11 +321,12 @@ func (self *JSRE) Eval(code string) (s string, err error) {
return fmt.Sprintf("%v", val), nil
}
+// compiles and then runs a piece of JS code
func (self *JSRE) Compile(fn string, src interface{}) error {
script, err := self.vm.Compile(fn, src)
if err != nil {
return err
}
- self.vm.Run(script)
+ self.run(script, true)
return nil
}
diff --git a/jsre/jsre_test.go b/jsre/jsre_test.go
index 667ed4bdc..5eaca2b91 100644
--- a/jsre/jsre_test.go
+++ b/jsre/jsre_test.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"testing"
+ "time"
)
type testNativeObjectBinding struct {
@@ -43,6 +44,31 @@ func TestExec(t *testing.T) {
if exp != got {
t.Errorf("expected '%v', got '%v'", exp, got)
}
+ jsre.Stop(false)
+}
+
+func TestNatto(t *testing.T) {
+ jsre := New("/tmp")
+
+ ioutil.WriteFile("/tmp/test.js", []byte(`setTimeout(function(){msg = "testMsg"}, 1);`), os.ModePerm)
+ err := jsre.Exec("test.js")
+ if err != nil {
+ t.Errorf("expected no error, got %v", err)
+ }
+ time.Sleep(time.Millisecond * 10)
+ val, err := jsre.Run("msg")
+ if err != nil {
+ t.Errorf("expected no error, got %v", err)
+ }
+ if !val.IsString() {
+ t.Errorf("expected string value, got %v", val)
+ }
+ exp := "testMsg"
+ got, _ := val.ToString()
+ if exp != got {
+ t.Errorf("expected '%v', got '%v'", exp, got)
+ }
+ jsre.Stop(false)
}
func TestBind(t *testing.T) {
@@ -59,6 +85,7 @@ func TestBind(t *testing.T) {
t.Errorf("expected no error, got %v", err)
}
t.Logf("no: %v", pp)
+ jsre.Stop(false)
}
func TestLoadScript(t *testing.T) {
@@ -81,4 +108,5 @@ func TestLoadScript(t *testing.T) {
if exp != got {
t.Errorf("expected '%v', got '%v'", exp, got)
}
+ jsre.Stop(false)
}
diff --git a/miner/agent.go b/miner/agent.go
index 547fdfbef..b2f89aaab 100644
--- a/miner/agent.go
+++ b/miner/agent.go
@@ -85,7 +85,7 @@ func (self *CpuMiner) mine(block *types.Block) {
self.chMu.Unlock()
// Mine
- nonce, mixDigest, _ := self.pow.Search(block, self.quitCurrentOp)
+ nonce, mixDigest := self.pow.Search(block, self.quitCurrentOp)
if nonce != 0 {
block.SetNonce(nonce)
block.Header().MixDigest = common.BytesToHash(mixDigest)
diff --git a/miner/miner.go b/miner/miner.go
index 883956370..bff0026dc 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -3,7 +3,6 @@ package miner
import (
"math/big"
- "github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
@@ -41,13 +40,7 @@ func (self *Miner) Mining() bool {
func (self *Miner) Start(coinbase common.Address) {
self.mining = true
self.worker.coinbase = coinbase
-
- if self.threads > 0 {
- self.pow.(*ethash.Ethash).UpdateDAG()
- }
-
self.worker.start()
-
self.worker.commitNewWork()
}
diff --git a/p2p/discover/database.go b/p2p/discover/database.go
index 964f86b84..dc0b97ddf 100644
--- a/p2p/discover/database.go
+++ b/p2p/discover/database.go
@@ -10,6 +10,7 @@ import (
"sync"
"time"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp"
@@ -167,6 +168,7 @@ func (db *nodeDB) node(id NodeID) *Node {
glog.V(logger.Warn).Infof("failed to decode node RLP: %v", err)
return nil
}
+ node.sha = crypto.Sha3Hash(node.ID[:])
return node
}
diff --git a/p2p/discover/database_test.go b/p2p/discover/database_test.go
index f327cf73b..3ed84a099 100644
--- a/p2p/discover/database_test.go
+++ b/p2p/discover/database_test.go
@@ -6,6 +6,7 @@ import (
"net"
"os"
"path/filepath"
+ "reflect"
"testing"
"time"
)
@@ -85,11 +86,12 @@ func TestNodeDBInt64(t *testing.T) {
}
func TestNodeDBFetchStore(t *testing.T) {
- node := &Node{
- ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: net.IP([]byte{192, 168, 0, 1}),
- TCPPort: 30303,
- }
+ node := newNode(
+ MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{192, 168, 0, 1},
+ 30303,
+ 30303,
+ )
inst := time.Now()
db, _ := newNodeDB("", Version)
@@ -124,34 +126,40 @@ func TestNodeDBFetchStore(t *testing.T) {
}
if stored := db.node(node.ID); stored == nil {
t.Errorf("node: not found")
- } else if !bytes.Equal(stored.ID[:], node.ID[:]) || !stored.IP.Equal(node.IP) || stored.TCPPort != node.TCPPort {
+ } else if !reflect.DeepEqual(stored, node) {
t.Errorf("node: data mismatch: have %v, want %v", stored, node)
}
}
var nodeDBSeedQueryNodes = []struct {
- node Node
+ node *Node
pong time.Time
}{
{
- node: Node{
- ID: MustHexID("0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: []byte{127, 0, 0, 1},
- },
+ node: newNode(
+ MustHexID("0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{127, 0, 0, 1},
+ 30303,
+ 30303,
+ ),
pong: time.Now().Add(-2 * time.Second),
},
{
- node: Node{
- ID: MustHexID("0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: []byte{127, 0, 0, 2},
- },
+ node: newNode(
+ MustHexID("0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{127, 0, 0, 2},
+ 30303,
+ 30303,
+ ),
pong: time.Now().Add(-3 * time.Second),
},
{
- node: Node{
- ID: MustHexID("0x03d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: []byte{127, 0, 0, 3},
- },
+ node: newNode(
+ MustHexID("0x03d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{127, 0, 0, 3},
+ 30303,
+ 30303,
+ ),
pong: time.Now().Add(-1 * time.Second),
},
}
@@ -162,7 +170,7 @@ func TestNodeDBSeedQuery(t *testing.T) {
// Insert a batch of nodes for querying
for i, seed := range nodeDBSeedQueryNodes {
- if err := db.updateNode(&seed.node); err != nil {
+ if err := db.updateNode(seed.node); err != nil {
t.Fatalf("node %d: failed to insert: %v", i, err)
}
}
@@ -202,7 +210,7 @@ func TestNodeDBSeedQueryContinuation(t *testing.T) {
// Insert a batch of nodes for querying
for i, seed := range nodeDBSeedQueryNodes {
- if err := db.updateNode(&seed.node); err != nil {
+ if err := db.updateNode(seed.node); err != nil {
t.Fatalf("node %d: failed to insert: %v", i, err)
}
}
@@ -266,22 +274,26 @@ func TestNodeDBPersistency(t *testing.T) {
}
var nodeDBExpirationNodes = []struct {
- node Node
+ node *Node
pong time.Time
exp bool
}{
{
- node: Node{
- ID: MustHexID("0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: []byte{127, 0, 0, 1},
- },
+ node: newNode(
+ MustHexID("0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{127, 0, 0, 1},
+ 30303,
+ 30303,
+ ),
pong: time.Now().Add(-nodeDBNodeExpiration + time.Minute),
exp: false,
}, {
- node: Node{
- ID: MustHexID("0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: []byte{127, 0, 0, 2},
- },
+ node: newNode(
+ MustHexID("0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{127, 0, 0, 2},
+ 30303,
+ 30303,
+ ),
pong: time.Now().Add(-nodeDBNodeExpiration - time.Minute),
exp: true,
},
@@ -293,7 +305,7 @@ func TestNodeDBExpiration(t *testing.T) {
// Add all the test nodes and set their last pong time
for i, seed := range nodeDBExpirationNodes {
- if err := db.updateNode(&seed.node); err != nil {
+ if err := db.updateNode(seed.node); err != nil {
t.Fatalf("node %d: failed to insert: %v", i, err)
}
if err := db.updateLastPong(seed.node.ID, seed.pong); err != nil {
diff --git a/p2p/discover/node.go b/p2p/discover/node.go
index e66ca37a4..a365ade15 100644
--- a/p2p/discover/node.go
+++ b/p2p/discover/node.go
@@ -6,7 +6,6 @@ import (
"encoding/hex"
"errors"
"fmt"
- "io"
"math/big"
"math/rand"
"net"
@@ -14,51 +13,55 @@ import (
"strconv"
"strings"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
- "github.com/ethereum/go-ethereum/rlp"
)
const nodeIDBits = 512
// Node represents a host on the network.
type Node struct {
- ID NodeID
- IP net.IP
+ IP net.IP // len 4 for IPv4 or 16 for IPv6
+ UDP, TCP uint16 // port numbers
+ ID NodeID // the node's public key
- DiscPort int // UDP listening port for discovery protocol
- TCPPort int // TCP listening port for RLPx
+ // This is a cached copy of sha3(ID) which is used for node
+ // distance calculations. This is part of Node in order to make it
+ // possible to write tests that need a node at a certain distance.
+ // In those tests, the content of sha will not actually correspond
+ // with ID.
+ sha common.Hash
}
-func newNode(id NodeID, addr *net.UDPAddr) *Node {
+func newNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node {
+ if ipv4 := ip.To4(); ipv4 != nil {
+ ip = ipv4
+ }
return &Node{
- ID: id,
- IP: addr.IP,
- DiscPort: addr.Port,
- TCPPort: addr.Port,
+ IP: ip,
+ UDP: udpPort,
+ TCP: tcpPort,
+ ID: id,
+ sha: crypto.Sha3Hash(id[:]),
}
}
-func (n *Node) isValid() bool {
- // TODO: don't accept localhost, LAN addresses from internet hosts
- return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.TCPPort != 0 && n.DiscPort != 0
-}
-
func (n *Node) addr() *net.UDPAddr {
- return &net.UDPAddr{IP: n.IP, Port: n.DiscPort}
+ return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)}
}
// The string representation of a Node is a URL.
// Please see ParseNode for a description of the format.
func (n *Node) String() string {
- addr := net.TCPAddr{IP: n.IP, Port: n.TCPPort}
+ addr := net.TCPAddr{IP: n.IP, Port: int(n.TCP)}
u := url.URL{
Scheme: "enode",
User: url.User(fmt.Sprintf("%x", n.ID[:])),
Host: addr.String(),
}
- if n.DiscPort != n.TCPPort {
- u.RawQuery = "discport=" + strconv.Itoa(n.DiscPort)
+ if n.UDP != n.TCP {
+ u.RawQuery = "discport=" + strconv.Itoa(int(n.UDP))
}
return u.String()
}
@@ -80,36 +83,47 @@ func (n *Node) String() string {
//
// enode://<hex node id>@10.3.58.6:30303?discport=30301
func ParseNode(rawurl string) (*Node, error) {
- var n Node
+ var (
+ id NodeID
+ ip net.IP
+ tcpPort, udpPort uint64
+ )
u, err := url.Parse(rawurl)
if u.Scheme != "enode" {
return nil, errors.New("invalid URL scheme, want \"enode\"")
}
+ // Parse the Node ID from the user portion.
if u.User == nil {
return nil, errors.New("does not contain node ID")
}
- if n.ID, err = HexID(u.User.String()); err != nil {
+ if id, err = HexID(u.User.String()); err != nil {
return nil, fmt.Errorf("invalid node ID (%v)", err)
}
- ip, port, err := net.SplitHostPort(u.Host)
+ // Parse the IP address.
+ host, port, err := net.SplitHostPort(u.Host)
if err != nil {
return nil, fmt.Errorf("invalid host: %v", err)
}
- if n.IP = net.ParseIP(ip); n.IP == nil {
+ if ip = net.ParseIP(host); ip == nil {
return nil, errors.New("invalid IP address")
}
- if n.TCPPort, err = strconv.Atoi(port); err != nil {
+ // Ensure the IP is 4 bytes long for IPv4 addresses.
+ if ipv4 := ip.To4(); ipv4 != nil {
+ ip = ipv4
+ }
+ // Parse the port numbers.
+ if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil {
return nil, errors.New("invalid port")
}
+ udpPort = tcpPort
qv := u.Query()
- if qv.Get("discport") == "" {
- n.DiscPort = n.TCPPort
- } else {
- if n.DiscPort, err = strconv.Atoi(qv.Get("discport")); err != nil {
+ if qv.Get("discport") != "" {
+ udpPort, err = strconv.ParseUint(qv.Get("discport"), 10, 16)
+ if err != nil {
return nil, errors.New("invalid discport in query")
}
}
- return &n, nil
+ return newNode(id, ip, uint16(udpPort), uint16(tcpPort)), nil
}
// MustParseNode parses a node URL. It panics if the URL is not valid.
@@ -121,22 +135,6 @@ func MustParseNode(rawurl string) *Node {
return n
}
-func (n Node) EncodeRLP(w io.Writer) error {
- return rlp.Encode(w, rpcNode{IP: n.IP.String(), Port: uint16(n.TCPPort), ID: n.ID})
-}
-func (n *Node) DecodeRLP(s *rlp.Stream) (err error) {
- var ext rpcNode
- if err = s.Decode(&ext); err == nil {
- n.TCPPort = int(ext.Port)
- n.DiscPort = int(ext.Port)
- n.ID = ext.ID
- if n.IP = net.ParseIP(ext.IP); n.IP == nil {
- return errors.New("invalid IP string")
- }
- }
- return err
-}
-
// NodeID is a unique identifier for each node.
// The node identifier is a marshaled elliptic curve public key.
type NodeID [nodeIDBits / 8]byte
@@ -221,7 +219,7 @@ func recoverNodeID(hash, sig []byte) (id NodeID, err error) {
// distcmp compares the distances a->target and b->target.
// Returns -1 if a is closer to target, 1 if b is closer to target
// and 0 if they are equal.
-func distcmp(target, a, b NodeID) int {
+func distcmp(target, a, b common.Hash) int {
for i := range target {
da := a[i] ^ target[i]
db := b[i] ^ target[i]
@@ -271,7 +269,7 @@ var lzcount = [256]int{
}
// logdist returns the logarithmic distance between a and b, log2(a ^ b).
-func logdist(a, b NodeID) int {
+func logdist(a, b common.Hash) int {
lz := 0
for i := range a {
x := a[i] ^ b[i]
@@ -285,8 +283,8 @@ func logdist(a, b NodeID) int {
return len(a)*8 - lz
}
-// randomID returns a random NodeID such that logdist(a, b) == n
-func randomID(a NodeID, n int) (b NodeID) {
+// hashAtDistance returns a random hash such that logdist(a, b) == n
+func hashAtDistance(a common.Hash, n int) (b common.Hash) {
if n == 0 {
return a
}
diff --git a/p2p/discover/node_test.go b/p2p/discover/node_test.go
index 60b01b6ca..b1babd989 100644
--- a/p2p/discover/node_test.go
+++ b/p2p/discover/node_test.go
@@ -9,6 +9,7 @@ import (
"testing/quick"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -48,46 +49,61 @@ var parseNodeTests = []struct {
},
{
rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150",
- wantResult: &Node{
- ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: net.ParseIP("127.0.0.1"),
- DiscPort: 52150,
- TCPPort: 52150,
- },
+ wantResult: newNode(
+ MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{0x7f, 0x0, 0x0, 0x1},
+ 52150,
+ 52150,
+ ),
},
{
rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150",
- wantResult: &Node{
- ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: net.ParseIP("::"),
- DiscPort: 52150,
- TCPPort: 52150,
- },
+ wantResult: newNode(
+ MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.ParseIP("::"),
+ 52150,
+ 52150,
+ ),
},
{
- rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=223344",
- wantResult: &Node{
- ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
- IP: net.ParseIP("127.0.0.1"),
- DiscPort: 223344,
- TCPPort: 52150,
- },
+ rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150",
+ wantResult: newNode(
+ MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.ParseIP("2001:db8:3c4d:15::abcd:ef12"),
+ 52150,
+ 52150,
+ ),
+ },
+ {
+ rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334",
+ wantResult: newNode(
+ MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
+ net.IP{0x7f, 0x0, 0x0, 0x1},
+ 22334,
+ 52150,
+ ),
},
}
func TestParseNode(t *testing.T) {
for i, test := range parseNodeTests {
n, err := ParseNode(test.rawurl)
- if err == nil && test.wantError != "" {
- t.Errorf("test %d: got nil error, expected %#q", i, test.wantError)
- continue
- }
- if err != nil && err.Error() != test.wantError {
- t.Errorf("test %d: got error %#q, expected %#q", i, err.Error(), test.wantError)
- continue
- }
- if !reflect.DeepEqual(n, test.wantResult) {
- t.Errorf("test %d: result mismatch:\ngot: %#v, want: %#v", i, n, test.wantResult)
+ if test.wantError != "" {
+ if err == nil {
+ t.Errorf("test %d: got nil error, expected %#q", i, test.wantError)
+ continue
+ } else if err.Error() != test.wantError {
+ t.Errorf("test %d: got error %#q, expected %#q", i, err.Error(), test.wantError)
+ continue
+ }
+ } else {
+ if err != nil {
+ t.Errorf("test %d: unexpected error: %v", i, err)
+ continue
+ }
+ if !reflect.DeepEqual(n, test.wantResult) {
+ t.Errorf("test %d: result mismatch:\ngot: %#v, want: %#v", i, n, test.wantResult)
+ }
}
}
}
@@ -154,7 +170,7 @@ func TestNodeID_pubkeyBad(t *testing.T) {
}
func TestNodeID_distcmp(t *testing.T) {
- distcmpBig := func(target, a, b NodeID) int {
+ distcmpBig := func(target, a, b common.Hash) int {
tbig := new(big.Int).SetBytes(target[:])
abig := new(big.Int).SetBytes(a[:])
bbig := new(big.Int).SetBytes(b[:])
@@ -167,15 +183,15 @@ func TestNodeID_distcmp(t *testing.T) {
// the random tests is likely to miss the case where they're equal.
func TestNodeID_distcmpEqual(t *testing.T) {
- base := NodeID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
- x := NodeID{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
+ base := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
+ x := common.Hash{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
if distcmp(base, x, x) != 0 {
t.Errorf("distcmp(base, x, x) != 0")
}
}
func TestNodeID_logdist(t *testing.T) {
- logdistBig := func(a, b NodeID) int {
+ logdistBig := func(a, b common.Hash) int {
abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:])
return new(big.Int).Xor(abig, bbig).BitLen()
}
@@ -186,19 +202,19 @@ func TestNodeID_logdist(t *testing.T) {
// the random tests is likely to miss the case where they're equal.
func TestNodeID_logdistEqual(t *testing.T) {
- x := NodeID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
+ x := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
if logdist(x, x) != 0 {
t.Errorf("logdist(x, x) != 0")
}
}
-func TestNodeID_randomID(t *testing.T) {
+func TestNodeID_hashAtDistance(t *testing.T) {
// we don't use quick.Check here because its output isn't
// very helpful when the test fails.
for i := 0; i < quickcfg.MaxCount; i++ {
- a := gen(NodeID{}, quickrand).(NodeID)
- dist := quickrand.Intn(len(NodeID{}) * 8)
- result := randomID(a, dist)
+ a := gen(common.Hash{}, quickrand).(common.Hash)
+ dist := quickrand.Intn(len(common.Hash{}) * 8)
+ result := hashAtDistance(a, dist)
actualdist := logdist(result, a)
if dist != actualdist {
@@ -209,6 +225,9 @@ func TestNodeID_randomID(t *testing.T) {
}
}
+// TODO: this can be dropped when we require Go >= 1.5
+// because testing/quick learned to generate arrays in 1.5.
+
func (NodeID) Generate(rand *rand.Rand, size int) reflect.Value {
var id NodeID
m := rand.Intn(len(id))
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index d3fe373f4..2c9cb80d5 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -7,19 +7,24 @@
package discover
import (
+ "crypto/rand"
"net"
"sort"
"sync"
"time"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
const (
- alpha = 3 // Kademlia concurrency factor
- bucketSize = 16 // Kademlia bucket size
- nBuckets = nodeIDBits + 1 // Number of buckets
+ alpha = 3 // Kademlia concurrency factor
+ bucketSize = 16 // Kademlia bucket size
+ hashBits = len(common.Hash{}) * 8
+ nBuckets = hashBits + 1 // Number of buckets
+
maxBondingPingPongs = 10
)
@@ -71,7 +76,7 @@ func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string
tab := &Table{
net: t,
db: db,
- self: newNode(ourID, ourAddr),
+ self: newNode(ourID, ourAddr.IP, uint16(ourAddr.Port), uint16(ourAddr.Port)),
bonding: make(map[NodeID]*bondproc),
bondslots: make(chan struct{}, maxBondingPingPongs),
}
@@ -105,6 +110,7 @@ func (tab *Table) Bootstrap(nodes []*Node) {
tab.nursery = make([]*Node, 0, len(nodes))
for _, n := range nodes {
cpy := *n
+ cpy.sha = crypto.Sha3Hash(n.ID[:])
tab.nursery = append(tab.nursery, &cpy)
}
tab.mutex.Unlock()
@@ -114,21 +120,23 @@ func (tab *Table) Bootstrap(nodes []*Node) {
// Lookup performs a network search for nodes close
// to the given target. It approaches the target by querying
// nodes that are closer to it on each iteration.
-func (tab *Table) Lookup(target NodeID) []*Node {
+// The given target does not need to be an actual node
+// identifier.
+func (tab *Table) Lookup(targetID NodeID) []*Node {
var (
+ target = crypto.Sha3Hash(targetID[:])
asked = make(map[NodeID]bool)
seen = make(map[NodeID]bool)
reply = make(chan []*Node, alpha)
pendingQueries = 0
)
- // don't query further if we hit the target or ourself.
+ // don't query further if we hit ourself.
// unlikely to happen often in practice.
- asked[target] = true
asked[tab.self.ID] = true
tab.mutex.Lock()
// update last lookup stamp (for refresh logic)
- tab.buckets[logdist(tab.self.ID, target)].lastLookup = time.Now()
+ tab.buckets[logdist(tab.self.sha, target)].lastLookup = time.Now()
// generate initial result set
result := tab.closest(target, bucketSize)
tab.mutex.Unlock()
@@ -141,7 +149,7 @@ func (tab *Table) Lookup(target NodeID) []*Node {
asked[n.ID] = true
pendingQueries++
go func() {
- r, _ := tab.net.findnode(n.ID, n.addr(), target)
+ r, _ := tab.net.findnode(n.ID, n.addr(), targetID)
reply <- tab.bondall(r)
}()
}
@@ -164,17 +172,16 @@ func (tab *Table) Lookup(target NodeID) []*Node {
// refresh performs a lookup for a random target to keep buckets full.
func (tab *Table) refresh() {
- ld := -1 // logdist of chosen bucket
- tab.mutex.Lock()
- for i, b := range tab.buckets {
- if i > 0 && b.lastLookup.Before(time.Now().Add(-1*time.Hour)) {
- ld = i
- break
- }
- }
- tab.mutex.Unlock()
-
- result := tab.Lookup(randomID(tab.self.ID, ld))
+ // The Kademlia paper specifies that the bucket refresh should
+ // perform a refresh in the least recently used bucket. We cannot
+ // adhere to this because the findnode target is a 512bit value
+ // (not hash-sized) and it is not easily possible to generate a
+ // sha3 preimage that falls into a chosen bucket.
+ //
+ // We perform a lookup with a random target instead.
+ var target NodeID
+ rand.Read(target[:])
+ result := tab.Lookup(target)
if len(result) == 0 {
// Pick a batch of previously know seeds to lookup with
seeds := tab.db.querySeeds(10)
@@ -194,7 +201,7 @@ func (tab *Table) refresh() {
// closest returns the n nodes in the table that are closest to the
// given id. The caller must hold tab.mutex.
-func (tab *Table) closest(target NodeID, nresults int) *nodesByDistance {
+func (tab *Table) closest(target common.Hash, nresults int) *nodesByDistance {
// This is a very wasteful way to find the closest nodes but
// obviously correct. I believe that tree-based buckets would make
// this easier to implement efficiently.
@@ -220,7 +227,7 @@ func (tab *Table) bondall(nodes []*Node) (result []*Node) {
rc := make(chan *Node, len(nodes))
for i := range nodes {
go func(n *Node) {
- nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCPPort))
+ nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCP))
rc <- nn
}(nodes[i])
}
@@ -276,7 +283,8 @@ func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16
}
tab.mutex.Lock()
defer tab.mutex.Unlock()
- if b := tab.buckets[logdist(tab.self.ID, n.ID)]; !b.bump(n) {
+ b := tab.buckets[logdist(tab.self.sha, n.sha)]
+ if !b.bump(n) {
tab.pingreplace(n, b)
}
return n, nil
@@ -299,12 +307,7 @@ func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAdd
tab.net.waitping(id)
}
// Bonding succeeded, update the node database
- w.n = &Node{
- ID: id,
- IP: addr.IP,
- DiscPort: addr.Port,
- TCPPort: int(tcpPort),
- }
+ w.n = newNode(id, addr.IP, uint16(addr.Port), tcpPort)
tab.db.updateNode(w.n)
close(w.done)
}
@@ -345,12 +348,11 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
func (tab *Table) add(entries []*Node) {
outer:
for _, n := range entries {
- if n == nil || n.ID == tab.self.ID {
- // skip bad entries. The RLP decoder returns nil for empty
- // input lists.
+ if n.ID == tab.self.ID {
+ // don't add self.
continue
}
- bucket := tab.buckets[logdist(tab.self.ID, n.ID)]
+ bucket := tab.buckets[logdist(tab.self.sha, n.sha)]
for i := range bucket.entries {
if bucket.entries[i].ID == n.ID {
// already in bucket
@@ -379,13 +381,13 @@ func (b *bucket) bump(n *Node) bool {
// distance to target.
type nodesByDistance struct {
entries []*Node
- target NodeID
+ target common.Hash
}
// push adds the given node to the list, keeping the total size below maxElems.
func (h *nodesByDistance) push(n *Node, maxElems int) {
ix := sort.Search(len(h.entries), func(i int) bool {
- return distcmp(h.target, h.entries[i].ID, n.ID) > 0
+ return distcmp(h.target, h.entries[i].sha, n.sha) > 0
})
if len(h.entries) < maxElems {
h.entries = append(h.entries, n)
diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go
index e2bd3c8ad..aa5267928 100644
--- a/p2p/discover/table_test.go
+++ b/p2p/discover/table_test.go
@@ -4,11 +4,13 @@ import (
"crypto/ecdsa"
"fmt"
"math/rand"
+
"net"
"reflect"
"testing"
"testing/quick"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -16,17 +18,19 @@ func TestTable_pingReplace(t *testing.T) {
doit := func(newNodeIsResponding, lastInBucketIsResponding bool) {
transport := newPingRecorder()
tab := newTable(transport, NodeID{}, &net.UDPAddr{}, "")
- last := fillBucket(tab, 200)
- pingSender := randomID(tab.self.ID, 200)
+ pingSender := newNode(MustHexID("a502af0f59b2aab7746995408c79e9ca312d2793cc997e44fc55eda62f0150bbb8c59a6f9269ba3a081518b62699ee807c7c19c20125ddfccca872608af9e370"), net.IP{}, 99, 99)
+
+ // fill up the sender's bucket.
+ last := fillBucket(tab, 253)
- // this gotPing should replace the last node
- // if the last node is not responding.
+ // this call to bond should replace the last node
+ // in its bucket if the node is not responding.
transport.responding[last.ID] = lastInBucketIsResponding
- transport.responding[pingSender] = newNodeIsResponding
- tab.bond(true, pingSender, &net.UDPAddr{}, 0)
+ transport.responding[pingSender.ID] = newNodeIsResponding
+ tab.bond(true, pingSender.ID, &net.UDPAddr{}, 0)
// first ping goes to sender (bonding pingback)
- if !transport.pinged[pingSender] {
+ if !transport.pinged[pingSender.ID] {
t.Error("table did not ping back sender")
}
if newNodeIsResponding {
@@ -39,22 +43,22 @@ func TestTable_pingReplace(t *testing.T) {
tab.mutex.Lock()
defer tab.mutex.Unlock()
- if l := len(tab.buckets[200].entries); l != bucketSize {
- t.Errorf("wrong bucket size after gotPing: got %d, want %d", bucketSize, l)
+ if l := len(tab.buckets[253].entries); l != bucketSize {
+ t.Errorf("wrong bucket size after bond: got %d, want %d", l, bucketSize)
}
if lastInBucketIsResponding || !newNodeIsResponding {
- if !contains(tab.buckets[200].entries, last.ID) {
+ if !contains(tab.buckets[253].entries, last.ID) {
t.Error("last entry was removed")
}
- if contains(tab.buckets[200].entries, pingSender) {
+ if contains(tab.buckets[253].entries, pingSender.ID) {
t.Error("new entry was added")
}
} else {
- if contains(tab.buckets[200].entries, last.ID) {
+ if contains(tab.buckets[253].entries, last.ID) {
t.Error("last entry was not removed")
}
- if !contains(tab.buckets[200].entries, pingSender) {
+ if !contains(tab.buckets[253].entries, pingSender.ID) {
t.Error("new entry was not added")
}
}
@@ -62,7 +66,7 @@ func TestTable_pingReplace(t *testing.T) {
doit(true, true)
doit(false, true)
- doit(false, true)
+ doit(true, false)
doit(false, false)
}
@@ -76,7 +80,7 @@ func TestBucket_bumpNoDuplicates(t *testing.T) {
n := rand.Intn(bucketSize-1) + 1
nodes := make([]*Node, n)
for i := range nodes {
- nodes[i] = &Node{ID: randomID(NodeID{}, 200)}
+ nodes[i] = nodeAtDistance(common.Hash{}, 200)
}
args[0] = reflect.ValueOf(nodes)
// generate random bump positions.
@@ -108,14 +112,26 @@ func TestBucket_bumpNoDuplicates(t *testing.T) {
}
}
+// fillBucket inserts nodes into the given bucket until
+// it is full. The node's IDs dont correspond to their
+// hashes.
func fillBucket(tab *Table, ld int) (last *Node) {
b := tab.buckets[ld]
for len(b.entries) < bucketSize {
- b.entries = append(b.entries, &Node{ID: randomID(tab.self.ID, ld)})
+ b.entries = append(b.entries, nodeAtDistance(tab.self.sha, ld))
}
return b.entries[bucketSize-1]
}
+// nodeAtDistance creates a node for which logdist(base, n.sha) == ld.
+// The node's ID does not correspond to n.sha.
+func nodeAtDistance(base common.Hash, ld int) (n *Node) {
+ n = new(Node)
+ n.sha = hashAtDistance(base, ld)
+ copy(n.ID[:], n.sha[:]) // ensure the node still has a unique ID
+ return n
+}
+
type pingRecorder struct{ responding, pinged map[NodeID]bool }
func newPingRecorder() *pingRecorder {
@@ -177,8 +193,8 @@ func TestTable_closest(t *testing.T) {
if contains(result, n.ID) {
continue // don't run the check below for nodes in result
}
- farthestResult := result[len(result)-1].ID
- if distcmp(test.Target, n.ID, farthestResult) < 0 {
+ farthestResult := result[len(result)-1].sha
+ if distcmp(test.Target, n.sha, farthestResult) < 0 {
t.Errorf("table contains node that is closer to target but it's not in result")
t.Logf(" Target: %v", test.Target)
t.Logf(" Farthest Result: %v", farthestResult)
@@ -196,7 +212,7 @@ func TestTable_closest(t *testing.T) {
type closeTest struct {
Self NodeID
- Target NodeID
+ Target common.Hash
All []*Node
N int
}
@@ -204,7 +220,7 @@ type closeTest struct {
func (*closeTest) Generate(rand *rand.Rand, size int) reflect.Value {
t := &closeTest{
Self: gen(NodeID{}, rand).(NodeID),
- Target: gen(NodeID{}, rand).(NodeID),
+ Target: gen(common.Hash{}, rand).(common.Hash),
N: rand.Intn(bucketSize),
}
for _, id := range gen([]NodeID{}, rand).([]NodeID) {
@@ -214,22 +230,21 @@ func (*closeTest) Generate(rand *rand.Rand, size int) reflect.Value {
}
func TestTable_Lookup(t *testing.T) {
- self := gen(NodeID{}, quickrand).(NodeID)
- target := randomID(self, 200)
- transport := findnodeOracle{t, target}
- tab := newTable(transport, self, &net.UDPAddr{}, "")
+ self := nodeAtDistance(common.Hash{}, 0)
+ tab := newTable(lookupTestnet, self.ID, &net.UDPAddr{}, "")
// lookup on empty table returns no nodes
- if results := tab.Lookup(target); len(results) > 0 {
+ if results := tab.Lookup(lookupTestnet.target); len(results) > 0 {
t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
}
// seed table with initial node (otherwise lookup will terminate immediately)
- tab.add([]*Node{newNode(randomID(target, 200), &net.UDPAddr{Port: 200})})
+ seed := newNode(lookupTestnet.dists[256][0], net.IP{}, 256, 0)
+ tab.add([]*Node{seed})
- results := tab.Lookup(target)
+ results := tab.Lookup(lookupTestnet.target)
t.Logf("results:")
for _, e := range results {
- t.Logf(" ld=%d, %v", logdist(target, e.ID), e.ID)
+ t.Logf(" ld=%d, %x", logdist(lookupTestnet.targetSha, e.sha), e.sha[:])
}
if len(results) != bucketSize {
t.Errorf("wrong number of results: got %d, want %d", len(results), bucketSize)
@@ -237,41 +252,268 @@ func TestTable_Lookup(t *testing.T) {
if hasDuplicates(results) {
t.Errorf("result set contains duplicate entries")
}
- if !sortedByDistanceTo(target, results) {
+ if !sortedByDistanceTo(lookupTestnet.targetSha, results) {
t.Errorf("result set not sorted by distance to target")
}
- if !contains(results, target) {
- t.Errorf("result set does not contain target")
- }
+ // TODO: check result nodes are actually closest
+}
+
+// This is the test network for the Lookup test.
+// The nodes were obtained by running testnet.mine with a random NodeID as target.
+var lookupTestnet = &preminedTestnet{
+ target: MustHexID("166aea4f556532c6d34e8b740e5d314af7e9ac0ca79833bd751d6b665f12dfd38ec563c363b32f02aef4a80b44fd3def94612d497b99cb5f17fd24de454927ec"),
+ targetSha: common.Hash{0x5c, 0x94, 0x4e, 0xe5, 0x1c, 0x5a, 0xe9, 0xf7, 0x2a, 0x95, 0xec, 0xcb, 0x8a, 0xed, 0x3, 0x74, 0xee, 0xcb, 0x51, 0x19, 0xd7, 0x20, 0xcb, 0xea, 0x68, 0x13, 0xe8, 0xe0, 0xd6, 0xad, 0x92, 0x61},
+ dists: [257][]NodeID{
+ 240: []NodeID{
+ MustHexID("2001ad5e3e80c71b952161bc0186731cf5ffe942d24a79230a0555802296238e57ea7a32f5b6f18564eadc1c65389448481f8c9338df0a3dbd18f708cbc2cbcb"),
+ MustHexID("6ba3f4f57d084b6bf94cc4555b8c657e4a8ac7b7baf23c6874efc21dd1e4f56b7eb2721e07f5242d2f1d8381fc8cae535e860197c69236798ba1ad231b105794"),
+ },
+ 244: []NodeID{
+ MustHexID("696ba1f0a9d55c59246f776600542a9e6432490f0cd78f8bb55a196918df2081a9b521c3c3ba48e465a75c10768807717f8f689b0b4adce00e1c75737552a178"),
+ },
+ 246: []NodeID{
+ MustHexID("d6d32178bdc38416f46ffb8b3ec9e4cb2cfff8d04dd7e4311a70e403cb62b10be1b447311b60b4f9ee221a8131fc2cbd45b96dd80deba68a949d467241facfa8"),
+ MustHexID("3ea3d04a43a3dfb5ac11cffc2319248cf41b6279659393c2f55b8a0a5fc9d12581a9d97ef5d8ff9b5abf3321a290e8f63a4f785f450dc8a672aba3ba2ff4fdab"),
+ MustHexID("2fc897f05ae585553e5c014effd3078f84f37f9333afacffb109f00ca8e7a3373de810a3946be971cbccdfd40249f9fe7f322118ea459ac71acca85a1ef8b7f4"),
+ },
+ 247: []NodeID{
+ MustHexID("3155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32"),
+ MustHexID("312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069db"),
+ MustHexID("38643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aac"),
+ MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73"),
+ MustHexID("8b58c6073dd98bbad4e310b97186c8f822d3a5c7d57af40e2136e88e315afd115edb27d2d0685a908cfe5aa49d0debdda6e6e63972691d6bd8c5af2d771dd2a9"),
+ MustHexID("2cbb718b7dc682da19652e7d9eb4fefaf7b7147d82c1c2b6805edf77b85e29fde9f6da195741467ff2638dc62c8d3e014ea5686693c15ed0080b6de90354c137"),
+ MustHexID("e84027696d3f12f2de30a9311afea8fbd313c2360daff52bb5fc8c7094d5295758bec3134e4eef24e4cdf377b40da344993284628a7a346eba94f74160998feb"),
+ MustHexID("f1357a4f04f9d33753a57c0b65ba20a5d8777abbffd04e906014491c9103fb08590e45548d37aa4bd70965e2e81ddba94f31860348df01469eec8c1829200a68"),
+ MustHexID("4ab0a75941b12892369b4490a1928c8ca52a9ad6d3dffbd1d8c0b907bc200fe74c022d011ec39b64808a39c0ca41f1d3254386c3e7733e7044c44259486461b6"),
+ MustHexID("d45150a72dc74388773e68e03133a3b5f51447fe91837d566706b3c035ee4b56f160c878c6273394daee7f56cc398985269052f22f75a8057df2fe6172765354"),
+ },
+ 248: []NodeID{
+ MustHexID("6aadfce366a189bab08ac84721567483202c86590642ea6d6a14f37ca78d82bdb6509eb7b8b2f6f63c78ae3ae1d8837c89509e41497d719b23ad53dd81574afa"),
+ MustHexID("a605ecfd6069a4cf4cf7f5840e5bc0ce10d23a3ac59e2aaa70c6afd5637359d2519b4524f56fc2ca180cdbebe54262f720ccaae8c1b28fd553c485675831624d"),
+ MustHexID("29701451cb9448ca33fc33680b44b840d815be90146eb521641efbffed0859c154e8892d3906eae9934bfacee72cd1d2fa9dd050fd18888eea49da155ab0efd2"),
+ MustHexID("3ed426322dee7572b08592e1e079f8b6c6b30e10e6243edd144a6a48fdbdb83df73a6e41b1143722cb82604f2203a32758610b5d9544f44a1a7921ba001528c1"),
+ MustHexID("b2e2a2b7fdd363572a3256e75435fab1da3b16f7891a8bd2015f30995dae665d7eabfd194d87d99d5df628b4bbc7b04e5b492c596422dd8272746c7a1b0b8e4f"),
+ MustHexID("0c69c9756162c593e85615b814ce57a2a8ca2df6c690b9c4e4602731b61e1531a3bbe3f7114271554427ffabea80ad8f36fa95a49fa77b675ae182c6ccac1728"),
+ MustHexID("8d28be21d5a97b0876442fa4f5e5387f5bf3faad0b6f13b8607b64d6e448c0991ca28dd7fe2f64eb8eadd7150bff5d5666aa6ed868b84c71311f4ba9a38569dd"),
+ MustHexID("2c677e1c64b9c9df6359348a7f5f33dc79e22f0177042486d125f8b6ca7f0dc756b1f672aceee5f1746bcff80aaf6f92a8dc0c9fbeb259b3fa0da060de5ab7e8"),
+ MustHexID("3994880f94a8678f0cd247a43f474a8af375d2a072128da1ad6cae84a244105ff85e94fc7d8496f639468de7ee998908a91c7e33ef7585fff92e984b210941a1"),
+ MustHexID("b45a9153c08d002a48090d15d61a7c7dad8c2af85d4ff5bd36ce23a9a11e0709bf8d56614c7b193bc028c16cbf7f20dfbcc751328b64a924995d47b41e452422"),
+ MustHexID("057ab3a9e53c7a84b0f3fc586117a525cdd18e313f52a67bf31798d48078e325abe5cfee3f6c2533230cb37d0549289d692a29dd400e899b8552d4b928f6f907"),
+ MustHexID("0ddf663d308791eb92e6bd88a2f8cb45e4f4f35bb16708a0e6ff7f1362aa6a73fedd0a1b1557fb3365e38e1b79d6918e2fae2788728b70c9ab6b51a3b94a4338"),
+ MustHexID("f637e07ff50cc1e3731735841c4798411059f2023abcf3885674f3e8032531b0edca50fd715df6feb489b6177c345374d64f4b07d257a7745de393a107b013a5"),
+ MustHexID("e24ec7c6eec094f63c7b3239f56d311ec5a3e45bc4e622a1095a65b95eea6fe13e29f3b6b7a2cbfe40906e3989f17ac834c3102dd0cadaaa26e16ee06d782b72"),
+ MustHexID("b76ea1a6fd6506ef6e3506a4f1f60ed6287fff8114af6141b2ff13e61242331b54082b023cfea5b3083354a4fb3f9eb8be01fb4a518f579e731a5d0707291a6b"),
+ MustHexID("9b53a37950ca8890ee349b325032d7b672cab7eced178d3060137b24ef6b92a43977922d5bdfb4a3409a2d80128e02f795f9dae6d7d99973ad0e23a2afb8442f"),
+ },
+ 249: []NodeID{
+ MustHexID("675ae65567c3c72c50c73bc0fd4f61f202ea5f93346ca57b551de3411ccc614fad61cb9035493af47615311b9d44ee7a161972ee4d77c28fe1ec029d01434e6a"),
+ MustHexID("8eb81408389da88536ae5800392b16ef5109d7ea132c18e9a82928047ecdb502693f6e4a4cdd18b54296caf561db937185731456c456c98bfe7de0baf0eaa495"),
+ MustHexID("2adba8b1612a541771cb93a726a38a4b88e97b18eced2593eb7daf82f05a5321ca94a72cc780c306ff21e551a932fc2c6d791e4681907b5ceab7f084c3fa2944"),
+ MustHexID("b1b4bfbda514d9b8f35b1c28961da5d5216fe50548f4066f69af3b7666a3b2e06eac646735e963e5c8f8138a2fb95af15b13b23ff00c6986eccc0efaa8ee6fb4"),
+ MustHexID("d2139281b289ad0e4d7b4243c4364f5c51aac8b60f4806135de06b12b5b369c9e43a6eb494eab860d115c15c6fbb8c5a1b0e382972e0e460af395b8385363de7"),
+ MustHexID("4a693df4b8fc5bdc7cec342c3ed2e228d7c5b4ab7321ddaa6cccbeb45b05a9f1d95766b4002e6d4791c2deacb8a667aadea6a700da28a3eea810a30395701bbc"),
+ MustHexID("ab41611195ec3c62bb8cd762ee19fb182d194fd141f4a66780efbef4b07ce916246c022b841237a3a6b512a93431157edd221e854ed2a259b72e9c5351f44d0c"),
+ MustHexID("68e8e26099030d10c3c703ae7045c0a48061fb88058d853b3e67880014c449d4311014da99d617d3150a20f1a3da5e34bf0f14f1c51fe4dd9d58afd222823176"),
+ MustHexID("3fbcacf546fb129cd70fc48de3b593ba99d3c473798bc309292aca280320e0eacc04442c914cad5c4cf6950345ba79b0d51302df88285d4e83ee3fe41339eee7"),
+ MustHexID("1d4a623659f7c8f80b6c3939596afdf42e78f892f682c768ad36eb7bfba402dbf97aea3a268f3badd8fe7636be216edf3d67ee1e08789ebbc7be625056bd7109"),
+ MustHexID("a283c474ab09da02bbc96b16317241d0627646fcc427d1fe790b76a7bf1989ced90f92101a973047ae9940c92720dffbac8eff21df8cae468a50f72f9e159417"),
+ MustHexID("dbf7e5ad7f87c3dfecae65d87c3039e14ed0bdc56caf00ce81931073e2e16719d746295512ff7937a15c3b03603e7c41a4f9df94fcd37bb200dd8f332767e9cb"),
+ MustHexID("caaa070a26692f64fc77f30d7b5ae980d419b4393a0f442b1c821ef58c0862898b0d22f74a4f8c5d83069493e3ec0b92f17dc1fe6e4cd437c1ec25039e7ce839"),
+ MustHexID("874cc8d1213beb65c4e0e1de38ef5d8165235893ac74ab5ea937c885eaab25c8d79dad0456e9fd3e9450626cac7e107b004478fb59842f067857f39a47cee695"),
+ MustHexID("d94193f236105010972f5df1b7818b55846592a0445b9cdc4eaed811b8c4c0f7c27dc8cc9837a4774656d6b34682d6d329d42b6ebb55da1d475c2474dc3dfdf4"),
+ MustHexID("edd9af6aded4094e9785637c28fccbd3980cbe28e2eb9a411048a23c2ace4bd6b0b7088a7817997b49a3dd05fc6929ca6c7abbb69438dbdabe65e971d2a794b2"),
+ },
+ 250: []NodeID{
+ MustHexID("53a5bd1215d4ab709ae8fdc2ced50bba320bced78bd9c5dc92947fb402250c914891786db0978c898c058493f86fc68b1c5de8a5cb36336150ac7a88655b6c39"),
+ MustHexID("b7f79e3ab59f79262623c9ccefc8f01d682323aee56ffbe295437487e9d5acaf556a9c92e1f1c6a9601f2b9eb6b027ae1aeaebac71d61b9b78e88676efd3e1a3"),
+ MustHexID("d374bf7e8d7ffff69cc00bebff38ef5bc1dcb0a8d51c1a3d70e61ac6b2e2d6617109254b0ac224354dfbf79009fe4239e09020c483cc60c071e00b9238684f30"),
+ MustHexID("1e1eac1c9add703eb252eb991594f8f5a173255d526a855fab24ae57dc277e055bc3c7a7ae0b45d437c4f47a72d97eb7b126f2ba344ba6c0e14b2c6f27d4b1e6"),
+ MustHexID("ae28953f63d4bc4e706712a59319c111f5ff8f312584f65d7436b4cd3d14b217b958f8486bad666b4481fe879019fb1f767cf15b3e3e2711efc33b56d460448a"),
+ MustHexID("934bb1edf9c7a318b82306aca67feb3d6b434421fa275d694f0b4927afd8b1d3935b727fd4ff6e3d012e0c82f1824385174e8c6450ade59c2a43281a4b3446b6"),
+ MustHexID("9eef3f28f70ce19637519a0916555bf76d26de31312ac656cf9d3e379899ea44e4dd7ffcce923b4f3563f8a00489a34bd6936db0cbb4c959d32c49f017e07d05"),
+ MustHexID("82200872e8f871c48f1fad13daec6478298099b591bb3dbc4ef6890aa28ebee5860d07d70be62f4c0af85085a90ae8179ee8f937cf37915c67ea73e704b03ee7"),
+ MustHexID("6c75a5834a08476b7fc37ff3dc2011dc3ea3b36524bad7a6d319b18878fad813c0ba76d1f4555cacd3890c865438c21f0e0aed1f80e0a157e642124c69f43a11"),
+ MustHexID("995b873742206cb02b736e73a88580c2aacb0bd4a3c97a647b647bcab3f5e03c0e0736520a8b3600da09edf4248991fb01091ec7ff3ec7cdc8a1beae011e7aae"),
+ MustHexID("c773a056594b5cdef2e850d30891ff0e927c3b1b9c35cd8e8d53a1017001e237468e1ece3ae33d612ca3e6abb0a9169aa352e9dcda358e5af2ad982b577447db"),
+ MustHexID("2b46a5f6923f475c6be99ec6d134437a6d11f6bb4b4ac6bcd94572fa1092639d1c08aeefcb51f0912f0a060f71d4f38ee4da70ecc16010b05dd4a674aab14c3a"),
+ MustHexID("af6ab501366debbaa0d22e20e9688f32ef6b3b644440580fd78de4fe0e99e2a16eb5636bbae0d1c259df8ddda77b35b9a35cbc36137473e9c68fbc9d203ba842"),
+ MustHexID("c9f6f2dd1a941926f03f770695bda289859e85fabaf94baaae20b93e5015dc014ba41150176a36a1884adb52f405194693e63b0c464a6891cc9cc1c80d450326"),
+ MustHexID("5b116f0751526868a909b61a30b0c5282c37df6925cc03ddea556ef0d0602a9595fd6c14d371f8ed7d45d89918a032dcd22be4342a8793d88fdbeb3ca3d75bd7"),
+ MustHexID("50f3222fb6b82481c7c813b2172e1daea43e2710a443b9c2a57a12bd160dd37e20f87aa968c82ad639af6972185609d47036c0d93b4b7269b74ebd7073221c10"),
+ },
+ 251: []NodeID{
+ MustHexID("9b8f702a62d1bee67bedfeb102eca7f37fa1713e310f0d6651cc0c33ea7c5477575289ccd463e5a2574a00a676a1fdce05658ba447bb9d2827f0ba47b947e894"),
+ MustHexID("b97532eb83054ed054b4abdf413bb30c00e4205545c93521554dbe77faa3cfaa5bd31ef466a107b0b34a71ec97214c0c83919720142cddac93aa7a3e928d4708"),
+ MustHexID("2f7a5e952bfb67f2f90b8441b5fadc9ee13b1dcde3afeeb3dd64bf937f86663cc5c55d1fa83952b5422763c7df1b7f2794b751c6be316ebc0beb4942e65ab8c1"),
+ MustHexID("42c7483781727051a0b3660f14faf39e0d33de5e643702ae933837d036508ab856ce7eec8ec89c4929a4901256e5233a3d847d5d4893f91bcf21835a9a880fee"),
+ MustHexID("873bae27bf1dc854408fba94046a53ab0c965cebe1e4e12290806fc62b88deb1f4a47f9e18f78fc0e7913a0c6e42ac4d0fc3a20cea6bc65f0c8a0ca90b67521e"),
+ MustHexID("a7e3a370bbd761d413f8d209e85886f68bf73d5c3089b2dc6fa42aab1ecb5162635497eed95dee2417f3c9c74a3e76319625c48ead2e963c7de877cd4551f347"),
+ MustHexID("528597534776a40df2addaaea15b6ff832ce36b9748a265768368f657e76d58569d9f30dbb91e91cf0ae7efe8f402f17aa0ae15f5c55051ba03ba830287f4c42"),
+ MustHexID("461d8bd4f13c3c09031fdb84f104ed737a52f630261463ce0bdb5704259bab4b737dda688285b8444dbecaecad7f50f835190b38684ced5e90c54219e5adf1bc"),
+ MustHexID("6ec50c0be3fd232737090fc0111caaf0bb6b18f72be453428087a11a97fd6b52db0344acbf789a689bd4f5f50f79017ea784f8fd6fe723ad6ae675b9e3b13e21"),
+ MustHexID("12fc5e2f77a83fdcc727b79d8ae7fe6a516881138d3011847ee136b400fed7cfba1f53fd7a9730253c7aa4f39abeacd04f138417ba7fcb0f36cccc3514e0dab6"),
+ MustHexID("4fdbe75914ccd0bce02101606a1ccf3657ec963e3b3c20239d5fec87673fe446d649b4f15f1fe1a40e6cfbd446dda2d31d40bb602b1093b8fcd5f139ba0eb46a"),
+ MustHexID("3753668a0f6281e425ea69b52cb2d17ab97afbe6eb84cf5d25425bc5e53009388857640668fadd7c110721e6047c9697803bd8a6487b43bb343bfa32ebf24039"),
+ MustHexID("2e81b16346637dec4410fd88e527346145b9c0a849dbf2628049ac7dae016c8f4305649d5659ec77f1e8a0fac0db457b6080547226f06283598e3740ad94849a"),
+ MustHexID("802c3cc27f91c89213223d758f8d2ecd41135b357b6d698f24d811cdf113033a81c38e0bdff574a5c005b00a8c193dc2531f8c1fa05fa60acf0ab6f2858af09f"),
+ MustHexID("fcc9a2e1ac3667026ff16192876d1813bb75abdbf39b929a92863012fe8b1d890badea7a0de36274d5c1eb1e8f975785532c50d80fd44b1a4b692f437303393f"),
+ MustHexID("6d8b3efb461151dd4f6de809b62726f5b89e9b38e9ba1391967f61cde844f7528fecf821b74049207cee5a527096b31f3ad623928cd3ce51d926fa345a6b2951"),
+ },
+ 252: []NodeID{
+ MustHexID("f1ae93157cc48c2075dd5868fbf523e79e06caf4b8198f352f6e526680b78ff4227263de92612f7d63472bd09367bb92a636fff16fe46ccf41614f7a72495c2a"),
+ MustHexID("587f482d111b239c27c0cb89b51dd5d574db8efd8de14a2e6a1400c54d4567e77c65f89c1da52841212080b91604104768350276b6682f2f961cdaf4039581c7"),
+ MustHexID("e3f88274d35cefdaabdf205afe0e80e936cc982b8e3e47a84ce664c413b29016a4fb4f3a3ebae0a2f79671f8323661ed462bf4390af94c424dc8ace0c301b90f"),
+ MustHexID("0ddc736077da9a12ba410dc5ea63cbcbe7659dd08596485b2bff3435221f82c10d263efd9af938e128464be64a178b7cd22e19f400d5802f4c9df54bf89f2619"),
+ MustHexID("784aa34d833c6ce63fcc1279630113c3272e82c4ae8c126c5a52a88ac461b6baeed4244e607b05dc14e5b2f41c70a273c3804dea237f14f7a1e546f6d1309d14"),
+ MustHexID("f253a2c354ee0e27cfcae786d726753d4ad24be6516b279a936195a487de4a59dbc296accf20463749ff55293263ed8c1b6365eecb248d44e75e9741c0d18205"),
+ MustHexID("a1910b80357b3ad9b4593e0628922939614dc9056a5fbf477279c8b2c1d0b4b31d89a0c09d0d41f795271d14d3360ef08a3f821e65e7e1f56c07a36afe49c7c5"),
+ MustHexID("f1168552c2efe541160f0909b0b4a9d6aeedcf595cdf0e9b165c97e3e197471a1ee6320e93389edfba28af6eaf10de98597ad56e7ab1b504ed762451996c3b98"),
+ MustHexID("b0c8e5d2c8634a7930e1a6fd082e448c6cf9d2d8b7293558b59238815a4df926c286bf297d2049f14e8296a6eb3256af614ec1812c4f2bbe807673b58bf14c8c"),
+ MustHexID("0fb346076396a38badc342df3679b55bd7f40a609ab103411fe45082c01f12ea016729e95914b2b5540e987ff5c9b133e85862648e7f36abdfd23100d248d234"),
+ MustHexID("f736e0cc83417feaa280d9483f5d4d72d1b036cd0c6d9cbdeb8ac35ceb2604780de46dddaa32a378474e1d5ccdf79b373331c30c7911ade2ae32f98832e5de1f"),
+ MustHexID("8b02991457602f42b38b342d3f2259ae4100c354b3843885f7e4e07bd644f64dab94bb7f38a3915f8b7f11d8e3f81c28e07a0078cf79d7397e38a7b7e0c857e2"),
+ MustHexID("9221d9f04a8a184993d12baa91116692bb685f887671302999d69300ad103eb2d2c75a09d8979404c6dd28f12362f58a1a43619c493d9108fd47588a23ce5824"),
+ MustHexID("652797801744dada833fff207d67484742eea6835d695925f3e618d71b68ec3c65bdd85b4302b2cdcb835ad3f94fd00d8da07e570b41bc0d2bcf69a8de1b3284"),
+ MustHexID("d84f06fe64debc4cd0625e36d19b99014b6218375262cc2209202bdbafd7dffcc4e34ce6398e182e02fd8faeed622c3e175545864902dfd3d1ac57647cddf4c6"),
+ MustHexID("d0ed87b294f38f1d741eb601020eeec30ac16331d05880fe27868f1e454446de367d7457b41c79e202eaf9525b029e4f1d7e17d85a55f83a557c005c68d7328a"),
+ },
+ 253: []NodeID{
+ MustHexID("ad4485e386e3cc7c7310366a7c38fb810b8896c0d52e55944bfd320ca294e7912d6c53c0a0cf85e7ce226e92491d60430e86f8f15cda0161ed71893fb4a9e3a1"),
+ MustHexID("36d0e7e5b7734f98c6183eeeb8ac5130a85e910a925311a19c4941b1290f945d4fc3996b12ef4966960b6fa0fb29b1604f83a0f81bd5fd6398d2e1a22e46af0c"),
+ MustHexID("7d307d8acb4a561afa23bdf0bd945d35c90245e26345ec3a1f9f7df354222a7cdcb81339c9ed6744526c27a1a0c8d10857e98df942fa433602facac71ac68a31"),
+ MustHexID("d97bf55f88c83fae36232661af115d66ca600fc4bd6d1fb35ff9bb4dad674c02cf8c8d05f317525b5522250db58bb1ecafb7157392bf5aa61b178c61f098d995"),
+ MustHexID("7045d678f1f9eb7a4613764d17bd5698796494d0bf977b16f2dbc272b8a0f7858a60805c022fc3d1fe4f31c37e63cdaca0416c0d053ef48a815f8b19121605e0"),
+ MustHexID("14e1f21418d445748de2a95cd9a8c3b15b506f86a0acabd8af44bb968ce39885b19c8822af61b3dd58a34d1f265baec30e3ae56149dc7d2aa4a538f7319f69c8"),
+ MustHexID("b9453d78281b66a4eac95a1546017111eaaa5f92a65d0de10b1122940e92b319728a24edf4dec6acc412321b1c95266d39c7b3a5d265c629c3e49a65fb022c09"),
+ MustHexID("e8a49248419e3824a00d86af422f22f7366e2d4922b304b7169937616a01d9d6fa5abf5cc01061a352dc866f48e1fa2240dbb453d872b1d7be62bdfc1d5e248c"),
+ MustHexID("bebcff24b52362f30e0589ee573ce2d86f073d58d18e6852a592fa86ceb1a6c9b96d7fb9ec7ed1ed98a51b6743039e780279f6bb49d0a04327ac7a182d9a56f6"),
+ MustHexID("d0835e5a4291db249b8d2fca9f503049988180c7d247bedaa2cf3a1bad0a76709360a85d4f9a1423b2cbc82bb4d94b47c0cde20afc430224834c49fe312a9ae3"),
+ MustHexID("6b087fe2a2da5e4f0b0f4777598a4a7fb66bf77dbd5bfc44e8a7eaa432ab585a6e226891f56a7d4f5ed11a7c57b90f1661bba1059590ca4267a35801c2802913"),
+ MustHexID("d901e5bde52d1a0f4ddf010a686a53974cdae4ebe5c6551b3c37d6b6d635d38d5b0e5f80bc0186a2c7809dbf3a42870dd09643e68d32db896c6da8ba734579e7"),
+ MustHexID("96419fb80efae4b674402bb969ebaab86c1274f29a83a311e24516d36cdf148fe21754d46c97688cdd7468f24c08b13e4727c29263393638a3b37b99ff60ebca"),
+ MustHexID("7b9c1889ae916a5d5abcdfb0aaedcc9c6f9eb1c1a4f68d0c2d034fe79ac610ce917c3abc670744150fa891bfcd8ab14fed6983fca964de920aa393fa7b326748"),
+ MustHexID("7a369b2b8962cc4c65900be046482fbf7c14f98a135bbbae25152c82ad168fb2097b3d1429197cf46d3ce9fdeb64808f908a489cc6019725db040060fdfe5405"),
+ MustHexID("47bcae48288da5ecc7f5058dfa07cf14d89d06d6e449cb946e237aa6652ea050d9f5a24a65efdc0013ccf232bf88670979eddef249b054f63f38da9d7796dbd8"),
+ },
+ 254: []NodeID{
+ MustHexID("099739d7abc8abd38ecc7a816c521a1168a4dbd359fa7212a5123ab583ffa1cf485a5fed219575d6475dbcdd541638b2d3631a6c7fce7474e7fe3cba1d4d5853"),
+ MustHexID("c2b01603b088a7182d0cf7ef29fb2b04c70acb320fccf78526bf9472e10c74ee70b3fcfa6f4b11d167bd7d3bc4d936b660f2c9bff934793d97cb21750e7c3d31"),
+ MustHexID("20e4d8f45f2f863e94b45548c1ef22a11f7d36f263e4f8623761e05a64c4572379b000a52211751e2561b0f14f4fc92dd4130410c8ccc71eb4f0e95a700d4ca9"),
+ MustHexID("27f4a16cc085e72d86e25c98bd2eca173eaaee7565c78ec5a52e9e12b2211f35de81b5b45e9195de2ebfe29106742c59112b951a04eb7ae48822911fc1f9389e"),
+ MustHexID("55db5ee7d98e7f0b1c3b9d5be6f2bc619a1b86c3cdd513160ad4dcf267037a5fffad527ac15d50aeb32c59c13d1d4c1e567ebbf4de0d25236130c8361f9aac63"),
+ MustHexID("883df308b0130fc928a8559fe50667a0fff80493bc09685d18213b2db241a3ad11310ed86b0ef662b3ce21fc3d9aa7f3fc24b8d9afe17c7407e9afd3345ae548"),
+ MustHexID("c7af968cc9bc8200c3ee1a387405f7563be1dce6710a3439f42ea40657d0eae9d2b3c16c42d779605351fcdece4da637b9804e60ca08cfb89aec32c197beffa6"),
+ MustHexID("3e66f2b788e3ff1d04106b80597915cd7afa06c405a7ae026556b6e583dca8e05cfbab5039bb9a1b5d06083ffe8de5780b1775550e7218f5e98624bf7af9a0a8"),
+ MustHexID("4fc7f53764de3337fdaec0a711d35d3a923e72fa65025444d12230b3552ed43d9b2d1ad08ccb11f2d50c58809e6dd74dde910e195294fca3b47ae5a3967cc479"),
+ MustHexID("bafdfdcf6ccaa989436752fa97c77477b6baa7deb374b16c095492c529eb133e8e2f99e1977012b64767b9d34b2cf6d2048ed489bd822b5139b523f6a423167b"),
+ MustHexID("7f5d78008a4312fe059104ce80202c82b8915c2eb4411c6b812b16f7642e57c00f2c9425121f5cbac4257fe0b3e81ef5dea97ea2dbaa98f6a8b6fd4d1e5980bb"),
+ MustHexID("598c37fe78f922751a052f463aeb0cb0bc7f52b7c2a4cf2da72ec0931c7c32175d4165d0f8998f7320e87324ac3311c03f9382a5385c55f0407b7a66b2acd864"),
+ MustHexID("f758c4136e1c148777a7f3275a76e2db0b2b04066fd738554ec398c1c6cc9fb47e14a3b4c87bd47deaeab3ffd2110514c3855685a374794daff87b605b27ee2e"),
+ MustHexID("0307bb9e4fd865a49dcf1fe4333d1b944547db650ab580af0b33e53c4fef6c789531110fac801bbcbce21fc4d6f61b6d5b24abdf5b22e3030646d579f6dca9c2"),
+ MustHexID("82504b6eb49bb2c0f91a7006ce9cefdbaf6df38706198502c2e06601091fc9dc91e4f15db3410d45c6af355bc270b0f268d3dff560f956985c7332d4b10bd1ed"),
+ MustHexID("b39b5b677b45944ceebe76e76d1f051de2f2a0ec7b0d650da52135743e66a9a5dba45f638258f9a7545d9a790c7fe6d3fdf82c25425c7887323e45d27d06c057"),
+ },
+ 255: []NodeID{
+ MustHexID("5c4d58d46e055dd1f093f81ee60a675e1f02f54da6206720adee4dccef9b67a31efc5c2a2949c31a04ee31beadc79aba10da31440a1f9ff2a24093c63c36d784"),
+ MustHexID("ea72161ffdd4b1e124c7b93b0684805f4c4b58d617ed498b37a145c670dbc2e04976f8785583d9c805ffbf343c31d492d79f841652bbbd01b61ed85640b23495"),
+ MustHexID("51caa1d93352d47a8e531692a3612adac1e8ac68d0a200d086c1c57ae1e1a91aa285ab242e8c52ef9d7afe374c9485b122ae815f1707b875569d0433c1c3ce85"),
+ MustHexID("c08397d5751b47bd3da044b908be0fb0e510d3149574dff7aeab33749b023bb171b5769990fe17469dbebc100bc150e798aeda426a2dcc766699a225fddd75c6"),
+ MustHexID("0222c1c194b749736e593f937fad67ee348ac57287a15c7e42877aa38a9b87732a408bca370f812efd0eedbff13e6d5b854bf3ba1dec431a796ed47f32552b09"),
+ MustHexID("03d859cd46ef02d9bfad5268461a6955426845eef4126de6be0fa4e8d7e0727ba2385b78f1a883a8239e95ebb814f2af8379632c7d5b100688eebc5841209582"),
+ MustHexID("64d5004b7e043c39ff0bd10cb20094c287721d5251715884c280a612b494b3e9e1c64ba6f67614994c7d969a0d0c0295d107d53fc225d47c44c4b82852d6f960"),
+ MustHexID("b0a5eefb2dab6f786670f35bf9641eefe6dd87fd3f1362bcab4aaa792903500ab23d88fae68411372e0813b057535a601d46e454323745a948017f6063a47b1f"),
+ MustHexID("0cc6df0a3433d448b5684d2a3ffa9d1a825388177a18f44ad0008c7bd7702f1ec0fc38b83506f7de689c3b6ecb552599927e29699eed6bb867ff08f80068b287"),
+ MustHexID("50772f7b8c03a4e153355fbbf79c8a80cf32af656ff0c7873c99911099d04a0dae0674706c357e0145ad017a0ade65e6052cb1b0d574fcd6f67da3eee0ace66b"),
+ MustHexID("1ae37829c9ef41f8b508b82259ebac76b1ed900d7a45c08b7970f25d2d48ddd1829e2f11423a18749940b6dab8598c6e416cef0efd47e46e51f29a0bc65b37cd"),
+ MustHexID("ba973cab31c2af091fc1644a93527d62b2394999e2b6ccbf158dd5ab9796a43d408786f1803ef4e29debfeb62fce2b6caa5ab2b24d1549c822a11c40c2856665"),
+ MustHexID("bc413ad270dd6ea25bddba78f3298b03b8ba6f8608ac03d06007d4116fa78ef5a0cfe8c80155089382fc7a193243ee5500082660cb5d7793f60f2d7d18650964"),
+ MustHexID("5a6a9ef07634d9eec3baa87c997b529b92652afa11473dfee41ef7037d5c06e0ddb9fe842364462d79dd31cff8a59a1b8d5bc2b810dea1d4cbbd3beb80ecec83"),
+ MustHexID("f492c6ee2696d5f682f7f537757e52744c2ae560f1090a07024609e903d334e9e174fc01609c5a229ddbcac36c9d21adaf6457dab38a25bfd44f2f0ee4277998"),
+ MustHexID("459e4db99298cb0467a90acee6888b08bb857450deac11015cced5104853be5adce5b69c740968bc7f931495d671a70cad9f48546d7cd203357fe9af0e8d2164"),
+ },
+ 256: []NodeID{
+ MustHexID("a8593af8a4aef7b806b5197612017951bac8845a1917ca9a6a15dd6086d608505144990b245785c4cd2d67a295701c7aac2aa18823fb0033987284b019656268"),
+ MustHexID("d2eebef914928c3aad77fc1b2a495f52d2294acf5edaa7d8a530b540f094b861a68fe8348a46a7c302f08ab609d85912a4968eacfea0740847b29421b4795d9e"),
+ MustHexID("b14bfcb31495f32b650b63cf7d08492e3e29071fdc73cf2da0da48d4b191a70ba1a65f42ad8c343206101f00f8a48e8db4b08bf3f622c0853e7323b250835b91"),
+ MustHexID("7feaee0d818c03eb30e4e0bf03ade0f3c21ca38e938a761aa1781cf70bda8cc5cd631a6cc53dd44f1d4a6d3e2dae6513c6c66ee50cb2f0e9ad6f7e319b309fd9"),
+ MustHexID("4ca3b657b139311db8d583c25dd5963005e46689e1317620496cc64129c7f3e52870820e0ec7941d28809311df6db8a2867bbd4f235b4248af24d7a9c22d1232"),
+ MustHexID("1181defb1d16851d42dd951d84424d6bd1479137f587fa184d5a8152be6b6b16ed08bcdb2c2ed8539bcde98c80c432875f9f724737c316a2bd385a39d3cab1d8"),
+ MustHexID("d9dd818769fa0c3ec9f553c759b92476f082817252a04a47dc1777740b1731d280058c66f982812f173a294acf4944a85ba08346e2de153ba3ba41ce8a62cb64"),
+ MustHexID("bd7c4f8a9e770aa915c771b15e107ca123d838762da0d3ffc53aa6b53e9cd076cffc534ec4d2e4c334c683f1f5ea72e0e123f6c261915ed5b58ac1b59f003d88"),
+ MustHexID("3dd5739c73649d510456a70e9d6b46a855864a4a3f744e088fd8c8da11b18e4c9b5f2d7da50b1c147b2bae5ca9609ae01f7a3cdea9dce34f80a91d29cd82f918"),
+ MustHexID("f0d7df1efc439b4bcc0b762118c1cfa99b2a6143a9f4b10e3c9465125f4c9fca4ab88a2504169bbcad65492cf2f50da9dd5d077c39574a944f94d8246529066b"),
+ MustHexID("dd598b9ba441448e5fb1a6ec6c5f5aa9605bad6e223297c729b1705d11d05f6bfd3d41988b694681ae69bb03b9a08bff4beab5596503d12a39bffb5cd6e94c7c"),
+ MustHexID("3fce284ac97e567aebae681b15b7a2b6df9d873945536335883e4bbc26460c064370537f323fd1ada828ea43154992d14ac0cec0940a2bd2a3f42ec156d60c83"),
+ MustHexID("7c8dfa8c1311cb14fb29a8ac11bca23ecc115e56d9fcf7b7ac1db9066aa4eb39f8b1dabf46e192a65be95ebfb4e839b5ab4533fef414921825e996b210dd53bd"),
+ MustHexID("cafa6934f82120456620573d7f801390ed5e16ed619613a37e409e44ab355ef755e83565a913b48a9466db786f8d4fbd590bfec474c2524d4a2608d4eafd6abd"),
+ MustHexID("9d16600d0dd310d77045769fed2cb427f32db88cd57d86e49390c2ba8a9698cfa856f775be2013237226e7bf47b248871cf865d23015937d1edeb20db5e3e760"),
+ MustHexID("17be6b6ba54199b1d80eff866d348ea11d8a4b341d63ad9a6681d3ef8a43853ac564d153eb2a8737f0afc9ab320f6f95c55aa11aaa13bbb1ff422fd16bdf8188"),
+ },
+ },
}
-// findnode on this transport always returns at least one node
-// that is one bucket closer to the target.
-type findnodeOracle struct {
- t *testing.T
- target NodeID
+type preminedTestnet struct {
+ target NodeID
+ targetSha common.Hash // sha3(target)
+ dists [hashBits + 1][]NodeID
}
-func (t findnodeOracle) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
- t.t.Logf("findnode query at dist %d", toaddr.Port)
+func (tn *preminedTestnet) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
// current log distance is encoded in port number
- var result []*Node
- switch toaddr.Port {
- case 0:
+ // fmt.Println("findnode query at dist", toaddr.Port)
+ if toaddr.Port == 0 {
panic("query to node at distance 0")
- default:
- // TODO: add more randomness to distances
- next := toaddr.Port - 1
- for i := 0; i < bucketSize; i++ {
- result = append(result, &Node{ID: randomID(t.target, next), DiscPort: next})
- }
+ }
+ if target != tn.target {
+ panic("findnode with wrong target")
+ }
+ next := uint16(toaddr.Port) - 1
+ var result []*Node
+ for i, id := range tn.dists[toaddr.Port] {
+ result = append(result, newNode(id, net.ParseIP("127.0.0.1"), next, uint16(i)))
}
return result, nil
}
-func (t findnodeOracle) close() {}
-func (t findnodeOracle) waitping(from NodeID) error { return nil }
-func (t findnodeOracle) ping(toid NodeID, toaddr *net.UDPAddr) error { return nil }
+func (*preminedTestnet) close() {}
+func (*preminedTestnet) waitping(from NodeID) error { return nil }
+func (*preminedTestnet) ping(toid NodeID, toaddr *net.UDPAddr) error { return nil }
+
+// mine generates a testnet struct literal with nodes at
+// various distances to the given target.
+func (n *preminedTestnet) mine(target NodeID) {
+ n.target = target
+ n.targetSha = crypto.Sha3Hash(n.target[:])
+ found := 0
+ for found < bucketSize*10 {
+ k := newkey()
+ id := PubkeyID(&k.PublicKey)
+ sha := crypto.Sha3Hash(id[:])
+ ld := logdist(n.targetSha, sha)
+ if len(n.dists[ld]) < bucketSize {
+ n.dists[ld] = append(n.dists[ld], id)
+ fmt.Println("found ID with ld", ld)
+ found++
+ }
+ }
+ fmt.Println("&preminedTestnet{")
+ fmt.Printf(" target: %#v,\n", n.target)
+ fmt.Printf(" targetSha: %#v,\n", n.targetSha)
+ fmt.Printf(" dists: [%d][]NodeID{\n", len(n.dists))
+ for ld, ns := range n.dists {
+ if len(ns) == 0 {
+ continue
+ }
+ fmt.Printf(" %d: []NodeID{\n", ld)
+ for _, n := range ns {
+ fmt.Printf(" MustHexID(\"%x\"),\n", n[:])
+ }
+ fmt.Println(" },")
+ }
+ fmt.Println(" },")
+ fmt.Println("}")
+}
func hasDuplicates(slice []*Node) bool {
seen := make(map[NodeID]bool)
@@ -284,13 +526,13 @@ func hasDuplicates(slice []*Node) bool {
return false
}
-func sortedByDistanceTo(distbase NodeID, slice []*Node) bool {
- var last NodeID
+func sortedByDistanceTo(distbase common.Hash, slice []*Node) bool {
+ var last common.Hash
for i, e := range slice {
- if i > 0 && distcmp(distbase, e.ID, last) < 0 {
+ if i > 0 && distcmp(distbase, e.sha, last) < 0 {
return false
}
- last = e.ID
+ last = e.sha
}
return true
}
diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go
index 65741b5f5..7213325da 100644
--- a/p2p/discover/udp.go
+++ b/p2p/discover/udp.go
@@ -15,7 +15,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
-const Version = 3
+const Version = 4
// Errors
var (
@@ -49,36 +49,67 @@ const (
// RPC request structures
type (
ping struct {
- Version uint // must match Version
- IP string // our IP
- Port uint16 // our port
+ Version uint
+ From, To rpcEndpoint
Expiration uint64
}
- // reply to Ping
+ // pong is the reply to ping.
pong struct {
- ReplyTok []byte
- Expiration uint64
+ // This field should mirror the UDP envelope address
+ // of the ping packet, which provides a way to discover the
+ // the external address (after NAT).
+ To rpcEndpoint
+
+ ReplyTok []byte // This contains the hash of the ping packet.
+ Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
}
+ // findnode is a query for nodes close to the given target.
findnode struct {
- // Id to look up. The responding node will send back nodes
- // closest to the target.
- Target NodeID
+ Target NodeID // doesn't need to be an actual public key
Expiration uint64
}
// reply to findnode
neighbors struct {
- Nodes []*Node
+ Nodes []rpcNode
Expiration uint64
}
+
+ rpcNode struct {
+ IP net.IP // len 4 for IPv4 or 16 for IPv6
+ UDP uint16 // for discovery protocol
+ TCP uint16 // for RLPx protocol
+ ID NodeID
+ }
+
+ rpcEndpoint struct {
+ IP net.IP // len 4 for IPv4 or 16 for IPv6
+ UDP uint16 // for discovery protocol
+ TCP uint16 // for RLPx protocol
+ }
)
-type rpcNode struct {
- IP string
- Port uint16
- ID NodeID
+func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint {
+ ip := addr.IP.To4()
+ if ip == nil {
+ ip = addr.IP.To16()
+ }
+ return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort}
+}
+
+func nodeFromRPC(rn rpcNode) (n *Node, valid bool) {
+ // TODO: don't accept localhost, LAN addresses from internet hosts
+ // TODO: check public key is on secp256k1 curve
+ if rn.IP.IsMulticast() || rn.IP.IsUnspecified() || rn.UDP == 0 {
+ return nil, false
+ }
+ return newNode(rn.ID, rn.IP, rn.UDP, rn.TCP), true
+}
+
+func nodeToRPC(n *Node) rpcNode {
+ return rpcNode{ID: n.ID, IP: n.IP, UDP: n.UDP, TCP: n.TCP}
}
type packet interface {
@@ -94,8 +125,9 @@ type conn interface {
// udp implements the RPC protocol.
type udp struct {
- conn conn
- priv *ecdsa.PrivateKey
+ conn conn
+ priv *ecdsa.PrivateKey
+ ourEndpoint rpcEndpoint
addpending chan *pending
gotreply chan reply
@@ -176,6 +208,8 @@ func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath strin
realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
}
}
+ // TODO: separate TCP port
+ udp.ourEndpoint = makeEndpoint(realaddr, uint16(realaddr.Port))
udp.Table = newTable(udp, PubkeyID(&priv.PublicKey), realaddr, nodeDBPath)
go udp.loop()
go udp.readLoop()
@@ -194,8 +228,8 @@ func (t *udp) ping(toid NodeID, toaddr *net.UDPAddr) error {
errc := t.pending(toid, pongPacket, func(interface{}) bool { return true })
t.send(toaddr, pingPacket, ping{
Version: Version,
- IP: t.self.IP.String(),
- Port: uint16(t.self.TCPPort),
+ From: t.ourEndpoint,
+ To: makeEndpoint(toaddr, 0), // TODO: maybe use known TCP port from DB
Expiration: uint64(time.Now().Add(expiration).Unix()),
})
return <-errc
@@ -212,9 +246,9 @@ func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node
nreceived := 0
errc := t.pending(toid, neighborsPacket, func(r interface{}) bool {
reply := r.(*neighbors)
- for _, n := range reply.Nodes {
+ for _, rn := range reply.Nodes {
nreceived++
- if n.isValid() {
+ if n, valid := nodeFromRPC(rn); valid {
nodes = append(nodes, n)
}
}
@@ -374,19 +408,24 @@ func (t *udp) readLoop() {
if err != nil {
return
}
- packet, fromID, hash, err := decodePacket(buf[:nbytes])
- if err != nil {
- glog.V(logger.Debug).Infof("Bad packet from %v: %v\n", from, err)
- continue
- }
- status := "ok"
- if err := packet.handle(t, from, fromID, hash); err != nil {
- status = err.Error()
- }
- glog.V(logger.Detail).Infof("<<< %v %T: %s\n", from, packet, status)
+ t.handlePacket(from, buf[:nbytes])
}
}
+func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error {
+ packet, fromID, hash, err := decodePacket(buf)
+ if err != nil {
+ glog.V(logger.Debug).Infof("Bad packet from %v: %v\n", from, err)
+ return err
+ }
+ status := "ok"
+ if err = packet.handle(t, from, fromID, hash); err != nil {
+ status = err.Error()
+ }
+ glog.V(logger.Detail).Infof("<<< %v %T: %s\n", from, packet, status)
+ return err
+}
+
func decodePacket(buf []byte) (packet, NodeID, []byte, error) {
if len(buf) < headSize+1 {
return nil, NodeID{}, nil, errPacketTooSmall
@@ -425,12 +464,13 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er
return errBadVersion
}
t.send(from, pongPacket, pong{
+ To: makeEndpoint(from, req.From.TCP),
ReplyTok: mac,
Expiration: uint64(time.Now().Add(expiration).Unix()),
})
if !t.handleReply(fromID, pingPacket, req) {
// Note: we're ignoring the provided IP address right now
- go t.bond(true, fromID, from, req.Port)
+ go t.bond(true, fromID, from, req.From.TCP)
}
return nil
}
@@ -459,12 +499,18 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte
// (which is a much bigger packet than findnode) to the victim.
return errUnknownNode
}
+ target := crypto.Sha3Hash(req.Target[:])
t.mutex.Lock()
- closest := t.closest(req.Target, bucketSize).entries
+ closest := t.closest(target, bucketSize).entries
t.mutex.Unlock()
+ // TODO: this conversion could use a cached version of the slice
+ closestrpc := make([]rpcNode, len(closest))
+ for i, n := range closest {
+ closestrpc[i] = nodeToRPC(n)
+ }
t.send(from, neighborsPacket, neighbors{
- Nodes: closest,
+ Nodes: closestrpc,
Expiration: uint64(time.Now().Add(expiration).Unix()),
})
return nil
diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go
index 47e04b85a..a2bb503ff 100644
--- a/p2p/discover/udp_test.go
+++ b/p2p/discover/udp_test.go
@@ -16,6 +16,7 @@ import (
"testing"
"time"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
)
@@ -23,6 +24,15 @@ func init() {
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel))
}
+// shared test variables
+var (
+ futureExp = uint64(time.Now().Add(10 * time.Hour).Unix())
+ testTarget = NodeID{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
+ testRemote = rpcEndpoint{IP: net.ParseIP("1.1.1.1").To4(), UDP: 1, TCP: 2}
+ testLocalAnnounced = rpcEndpoint{IP: net.ParseIP("2.2.2.2").To4(), UDP: 3, TCP: 4}
+ testLocal = rpcEndpoint{IP: net.ParseIP("3.3.3.3").To4(), UDP: 5, TCP: 6}
+)
+
type udpTest struct {
t *testing.T
pipe *dgramPipe
@@ -52,8 +62,7 @@ func (test *udpTest) packetIn(wantError error, ptype byte, data packet) error {
return test.errorf("packet (%d) encode error: %v", err)
}
test.sent = append(test.sent, enc)
- err = data.handle(test.udp, test.remoteaddr, PubkeyID(&test.remotekey.PublicKey), enc[:macSize])
- if err != wantError {
+ if err = test.udp.handlePacket(test.remoteaddr, enc); err != wantError {
return test.errorf("error mismatch: got %q, want %q", err, wantError)
}
return nil
@@ -90,18 +99,12 @@ func (test *udpTest) errorf(format string, args ...interface{}) error {
return err
}
-// shared test variables
-var (
- futureExp = uint64(time.Now().Add(10 * time.Hour).Unix())
- testTarget = MustHexID("01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101")
-)
-
func TestUDP_packetErrors(t *testing.T) {
test := newUDPTest(t)
defer test.table.Close()
- test.packetIn(errExpired, pingPacket, &ping{IP: "foo", Port: 99, Version: Version})
- test.packetIn(errBadVersion, pingPacket, &ping{IP: "foo", Port: 99, Version: 99, Expiration: futureExp})
+ test.packetIn(errExpired, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: Version})
+ test.packetIn(errBadVersion, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: 99, Expiration: futureExp})
test.packetIn(errUnsolicitedReply, pongPacket, &pong{ReplyTok: []byte{}, Expiration: futureExp})
test.packetIn(errUnknownNode, findnodePacket, &findnode{Expiration: futureExp})
test.packetIn(errUnsolicitedReply, neighborsPacket, &neighbors{Expiration: futureExp})
@@ -143,30 +146,25 @@ func TestUDP_findnode(t *testing.T) {
// put a few nodes into the table. their exact
// distribution shouldn't matter much, altough we need to
// take care not to overflow any bucket.
- target := testTarget
- nodes := &nodesByDistance{target: target}
+ targetHash := crypto.Sha3Hash(testTarget[:])
+ nodes := &nodesByDistance{target: targetHash}
for i := 0; i < bucketSize; i++ {
- nodes.push(&Node{
- IP: net.IP{1, 2, 3, byte(i)},
- DiscPort: i + 2,
- TCPPort: i + 2,
- ID: randomID(test.table.self.ID, i+2),
- }, bucketSize)
+ nodes.push(nodeAtDistance(test.table.self.sha, i+2), bucketSize)
}
test.table.add(nodes.entries)
// ensure there's a bond with the test node,
// findnode won't be accepted otherwise.
- test.table.db.updateNode(&Node{
- ID: PubkeyID(&test.remotekey.PublicKey),
- IP: test.remoteaddr.IP,
- DiscPort: test.remoteaddr.Port,
- TCPPort: 99,
- })
+ test.table.db.updateNode(newNode(
+ PubkeyID(&test.remotekey.PublicKey),
+ test.remoteaddr.IP,
+ uint16(test.remoteaddr.Port),
+ 99,
+ ))
// check that closest neighbors are returned.
test.packetIn(nil, findnodePacket, &findnode{Target: testTarget, Expiration: futureExp})
test.waitPacketOut(func(p *neighbors) {
- expected := test.table.closest(testTarget, bucketSize)
+ expected := test.table.closest(targetHash, bucketSize)
if len(p.Nodes) != bucketSize {
t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize)
}
@@ -204,13 +202,17 @@ func TestUDP_findnodeMultiReply(t *testing.T) {
// send the reply as two packets.
list := []*Node{
- MustParseNode("enode://ba85011c70bcc5c04d8607d3a0ed29aa6179c092cbdda10d5d32684fb33ed01bd94f588ca8f91ac48318087dcb02eaf36773a7a453f0eedd6742af668097b29c@10.0.1.16:30303"),
+ MustParseNode("enode://ba85011c70bcc5c04d8607d3a0ed29aa6179c092cbdda10d5d32684fb33ed01bd94f588ca8f91ac48318087dcb02eaf36773a7a453f0eedd6742af668097b29c@10.0.1.16:30303?discport=30304"),
MustParseNode("enode://81fa361d25f157cd421c60dcc28d8dac5ef6a89476633339c5df30287474520caca09627da18543d9079b5b288698b542d56167aa5c09111e55acdbbdf2ef799@10.0.1.16:30303"),
- MustParseNode("enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301"),
+ MustParseNode("enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301?discport=17"),
MustParseNode("enode://1b5b4aa662d7cb44a7221bfba67302590b643028197a7d5214790f3bac7aaa4a3241be9e83c09cf1f6c69d007c634faae3dc1b1221793e8446c0b3a09de65960@10.0.1.16:30303"),
}
- test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: list[:2]})
- test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: list[2:]})
+ rpclist := make([]rpcNode, len(list))
+ for i := range list {
+ rpclist[i] = nodeToRPC(list[i])
+ }
+ test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: rpclist[:2]})
+ test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: rpclist[2:]})
// check that the sent neighbors are all returned by findnode
select {
@@ -231,7 +233,8 @@ func TestUDP_successfulPing(t *testing.T) {
done := make(chan struct{})
go func() {
- test.packetIn(nil, pingPacket, &ping{IP: "foo", Port: 99, Version: Version, Expiration: futureExp})
+ // The remote side sends a ping packet to initiate the exchange.
+ test.packetIn(nil, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: Version, Expiration: futureExp})
close(done)
}()
@@ -239,12 +242,34 @@ func TestUDP_successfulPing(t *testing.T) {
test.waitPacketOut(func(p *pong) {
pinghash := test.sent[0][:macSize]
if !bytes.Equal(p.ReplyTok, pinghash) {
- t.Errorf("got ReplyTok %x, want %x", p.ReplyTok, pinghash)
+ t.Errorf("got pong.ReplyTok %x, want %x", p.ReplyTok, pinghash)
+ }
+ wantTo := rpcEndpoint{
+ // The mirrored UDP address is the UDP packet sender
+ IP: test.remoteaddr.IP, UDP: uint16(test.remoteaddr.Port),
+ // The mirrored TCP port is the one from the ping packet
+ TCP: testRemote.TCP,
+ }
+ if !reflect.DeepEqual(p.To, wantTo) {
+ t.Errorf("got pong.To %v, want %v", p.To, wantTo)
}
})
// remote is unknown, the table pings back.
- test.waitPacketOut(func(p *ping) error { return nil })
+ test.waitPacketOut(func(p *ping) error {
+ if !reflect.DeepEqual(p.From, test.udp.ourEndpoint) {
+ t.Errorf("got ping.From %v, want %v", p.From, test.udp.ourEndpoint)
+ }
+ wantTo := rpcEndpoint{
+ // The mirrored UDP address is the UDP packet sender.
+ IP: test.remoteaddr.IP, UDP: uint16(test.remoteaddr.Port),
+ TCP: 0,
+ }
+ if !reflect.DeepEqual(p.To, wantTo) {
+ t.Errorf("got ping.To %v, want %v", p.To, wantTo)
+ }
+ return nil
+ })
test.packetIn(nil, pongPacket, &pong{Expiration: futureExp})
// ping should return shortly after getting the pong packet.
@@ -259,11 +284,11 @@ func TestUDP_successfulPing(t *testing.T) {
if !bytes.Equal(rnode.IP, test.remoteaddr.IP) {
t.Errorf("node has wrong IP: got %v, want: %v", rnode.IP, test.remoteaddr.IP)
}
- if rnode.DiscPort != test.remoteaddr.Port {
- t.Errorf("node has wrong Port: got %v, want: %v", rnode.DiscPort, test.remoteaddr.Port)
+ if int(rnode.UDP) != test.remoteaddr.Port {
+ t.Errorf("node has wrong UDP port: got %v, want: %v", rnode.UDP, test.remoteaddr.Port)
}
- if rnode.TCPPort != 99 {
- t.Errorf("node has wrong Port: got %v, want: %v", rnode.TCPPort, 99)
+ if rnode.TCP != testRemote.TCP {
+ t.Errorf("node has wrong TCP port: got %v, want: %v", rnode.TCP, testRemote.TCP)
}
}
@@ -327,7 +352,7 @@ func (c *dgramPipe) Close() error {
}
func (c *dgramPipe) LocalAddr() net.Addr {
- return &net.UDPAddr{}
+ return &net.UDPAddr{IP: testLocal.IP, Port: int(testLocal.UDP)}
}
func (c *dgramPipe) waitPacketOut() []byte {
diff --git a/p2p/handshake_test.go b/p2p/handshake_test.go
index 5e63e5c39..9018e14f2 100644
--- a/p2p/handshake_test.go
+++ b/p2p/handshake_test.go
@@ -119,14 +119,14 @@ func TestSetupConn(t *testing.T) {
prv0, _ := crypto.GenerateKey()
prv1, _ := crypto.GenerateKey()
node0 := &discover.Node{
- ID: discover.PubkeyID(&prv0.PublicKey),
- IP: net.IP{1, 2, 3, 4},
- TCPPort: 33,
+ ID: discover.PubkeyID(&prv0.PublicKey),
+ IP: net.IP{1, 2, 3, 4},
+ TCP: 33,
}
node1 := &discover.Node{
- ID: discover.PubkeyID(&prv1.PublicKey),
- IP: net.IP{5, 6, 7, 8},
- TCPPort: 44,
+ ID: discover.PubkeyID(&prv1.PublicKey),
+ IP: net.IP{5, 6, 7, 8},
+ TCP: 44,
}
hs0 := &protoHandshake{
Version: baseProtocolVersion,
diff --git a/p2p/peer.go b/p2p/peer.go
index bc0e6eb5f..94fa03f8d 100644
--- a/p2p/peer.go
+++ b/p2p/peer.go
@@ -15,7 +15,7 @@ import (
)
const (
- baseProtocolVersion = 3
+ baseProtocolVersion = 4
baseProtocolLength = uint64(16)
baseProtocolMaxMsgSize = 10 * 1024 * 1024
diff --git a/p2p/server.go b/p2p/server.go
index 959d61284..4a78e0bb9 100644
--- a/p2p/server.go
+++ b/p2p/server.go
@@ -462,7 +462,7 @@ func (srv *Server) dialLoop() {
}
func (srv *Server) dialNode(dest *discover.Node) {
- addr := &net.TCPAddr{IP: dest.IP, Port: dest.TCPPort}
+ addr := &net.TCPAddr{IP: dest.IP, Port: int(dest.TCP)}
glog.V(logger.Debug).Infof("Dialing %v\n", dest)
conn, err := srv.Dialer.Dial("tcp", addr.String())
if err != nil {
diff --git a/p2p/server_test.go b/p2p/server_test.go
index 5ee9c5ceb..3f9db343c 100644
--- a/p2p/server_test.go
+++ b/p2p/server_test.go
@@ -102,7 +102,7 @@ func TestServerDial(t *testing.T) {
// tell the server to connect
tcpAddr := listener.Addr().(*net.TCPAddr)
- srv.staticDial <- &discover.Node{IP: tcpAddr.IP, TCPPort: tcpAddr.Port}
+ srv.staticDial <- &discover.Node{IP: tcpAddr.IP, TCP: uint16(tcpAddr.Port)}
select {
case conn := <-accepted:
@@ -274,9 +274,9 @@ func TestServerStaticPeers(t *testing.T) {
// Inject a static node and wait for a remote dial, then redial, then nothing
addr := listener.Addr().(*net.TCPAddr)
static := &discover.Node{
- ID: discover.PubkeyID(&newkey().PublicKey),
- IP: addr.IP,
- TCPPort: addr.Port,
+ ID: discover.PubkeyID(&newkey().PublicKey),
+ IP: addr.IP,
+ TCP: uint16(addr.Port),
}
server.AddPeer(static)
diff --git a/pow/dagger/dagger.go b/pow/dagger/dagger.go
index f2d65e8ef..b941c0eeb 100644
--- a/pow/dagger/dagger.go
+++ b/pow/dagger/dagger.go
@@ -6,8 +6,8 @@ import (
"math/rand"
"time"
- "github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/logger"
)
@@ -44,7 +44,7 @@ func (dag *Dagger) Find(obj *big.Int, resChan chan int64) {
resChan <- 0
}
-func (dag *Dagger) Search(hash, diff *big.Int) ([]byte, []byte, []byte) {
+func (dag *Dagger) Search(hash, diff *big.Int) (uint64, []byte) {
// TODO fix multi threading. Somehow it results in the wrong nonce
amountOfRoutines := 1
@@ -69,7 +69,7 @@ func (dag *Dagger) Search(hash, diff *big.Int) ([]byte, []byte, []byte) {
}
}
- return big.NewInt(res).Bytes(), nil, nil
+ return uint64(res), nil
}
func (dag *Dagger) Verify(hash, diff, nonce *big.Int) bool {
diff --git a/pow/ezp/pow.go b/pow/ezp/pow.go
index bd2927fe8..c838dd5ec 100644
--- a/pow/ezp/pow.go
+++ b/pow/ezp/pow.go
@@ -32,7 +32,7 @@ func (pow *EasyPow) Turbo(on bool) {
pow.turbo = on
}
-func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte, []byte) {
+func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
hash := block.HashNoNonce()
diff := block.Difficulty()
@@ -57,7 +57,7 @@ empty:
for {
select {
case <-stop:
- return 0, nil, nil
+ return 0, nil
default:
i++
@@ -67,7 +67,7 @@ empty:
sha := uint64(r.Int63())
if verify(hash, diff, sha) {
- return sha, nil, nil
+ return sha, nil
}
}
@@ -76,7 +76,7 @@ empty:
}
}
- return 0, nil, nil
+ return 0, nil
}
func (pow *EasyPow) Verify(block pow.Block) bool {
diff --git a/pow/pow.go b/pow/pow.go
index 3908e5f76..73984a4ae 100644
--- a/pow/pow.go
+++ b/pow/pow.go
@@ -1,7 +1,7 @@
package pow
type PoW interface {
- Search(block Block, stop <-chan struct{}) (uint64, []byte, []byte)
+ Search(block Block, stop <-chan struct{}) (uint64, []byte)
Verify(block Block) bool
GetHashrate() int64
Turbo(bool)
diff --git a/rpc/api.go b/rpc/api.go
index 6d3a20bfa..b79a1306e 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -173,7 +173,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return fmt.Errorf("Transaction not confirmed")
}
- v, err := api.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
+ // nonce may be nil ("guess" mode)
+ var nonce string
+ if args.Nonce != nil {
+ nonce = args.Nonce.String()
+ }
+
+ v, err := api.xeth().Transact(args.From, args.To, nonce, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
if err != nil {
return err
}
diff --git a/rpc/args.go b/rpc/args.go
index 4bd48e6d6..e61f28c4f 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -157,6 +157,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
type NewTxArgs struct {
From string
To string
+ Nonce *big.Int
Value *big.Int
Gas *big.Int
GasPrice *big.Int
@@ -170,6 +171,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
var ext struct {
From string
To string
+ Nonce interface{}
Value interface{}
Gas interface{}
GasPrice interface{}
@@ -200,6 +202,14 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
args.Data = ext.Data
var num *big.Int
+ if ext.Nonce != nil {
+ num, err = numString(ext.Nonce)
+ if err != nil {
+ return err
+ }
+ }
+ args.Nonce = num
+
if ext.Value == nil {
num = big.NewInt(0)
} else {
diff --git a/rpc/jeth.go b/rpc/jeth.go
index e83212bb5..4739316b2 100644
--- a/rpc/jeth.go
+++ b/rpc/jeth.go
@@ -2,8 +2,7 @@ package rpc
import (
"encoding/json"
- "fmt"
- // "fmt"
+
"github.com/ethereum/go-ethereum/jsre"
"github.com/robertkrimen/otto"
)
@@ -18,12 +17,12 @@ func NewJeth(ethApi *EthereumApi, toVal func(interface{}) otto.Value, re *jsre.J
return &Jeth{ethApi, toVal, re}
}
-func (self *Jeth) err(code int, msg string, id interface{}) (response otto.Value) {
+func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) {
rpcerr := &RpcErrorObject{code, msg}
- self.re.Set("ret_jsonrpc", jsonrpcver)
- self.re.Set("ret_id", id)
- self.re.Set("ret_error", rpcerr)
- response, _ = self.re.Run(`
+ call.Otto.Set("ret_jsonrpc", jsonrpcver)
+ call.Otto.Set("ret_id", id)
+ call.Otto.Set("ret_error", rpcerr)
+ response, _ = call.Otto.Run(`
ret_response = { jsonrpc: ret_jsonrpc, id: ret_id, error: ret_error };
`)
return
@@ -32,27 +31,53 @@ func (self *Jeth) err(code int, msg string, id interface{}) (response otto.Value
func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
reqif, err := call.Argument(0).Export()
if err != nil {
- return self.err(-32700, err.Error(), nil)
+ return self.err(call, -32700, err.Error(), nil)
}
jsonreq, err := json.Marshal(reqif)
- var req RpcRequest
- err = json.Unmarshal(jsonreq, &req)
-
- var respif interface{}
- err = self.ethApi.GetRequestReply(&req, &respif)
+ var reqs []RpcRequest
+ batch := true
+ err = json.Unmarshal(jsonreq, &reqs)
if err != nil {
- fmt.Printf("error: %s\n", err)
- return self.err(-32603, err.Error(), req.Id)
+ reqs = make([]RpcRequest, 1)
+ err = json.Unmarshal(jsonreq, &reqs[0])
+ batch = false
+ }
+
+ call.Otto.Set("response_len", len(reqs))
+ call.Otto.Run("var ret_response = new Array(response_len);")
+
+ for i, req := range reqs {
+ var respif interface{}
+ err = self.ethApi.GetRequestReply(&req, &respif)
+ if err != nil {
+ return self.err(call, -32603, err.Error(), req.Id)
+ }
+ call.Otto.Set("ret_jsonrpc", jsonrpcver)
+ call.Otto.Set("ret_id", req.Id)
+
+ res, _ := json.Marshal(respif)
+
+ call.Otto.Set("ret_result", string(res))
+ call.Otto.Set("response_idx", i)
+ response, err = call.Otto.Run(`
+ ret_response[response_idx] = { jsonrpc: ret_jsonrpc, id: ret_id, result: JSON.parse(ret_result) };
+ `)
+ }
+
+ if !batch {
+ call.Otto.Run("ret_response = ret_response[0];")
+ }
+
+ 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);
+ }
+ `)
}
- self.re.Set("ret_jsonrpc", jsonrpcver)
- self.re.Set("ret_id", req.Id)
- res, _ := json.Marshal(respif)
- self.re.Set("ret_result", string(res))
- response, err = self.re.Run(`
- ret_response = { jsonrpc: ret_jsonrpc, id: ret_id, result: JSON.parse(ret_result) };
- `)
return
}
diff --git a/tests/block_test.go b/tests/block_test.go
index a46751f00..2cf2da75c 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -13,42 +13,37 @@ import (
// TODO: refactor test setup & execution to better align with vm and tx tests
func TestBcValidBlockTests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
runBlockTestsInFile("files/BlockTests/bcValidBlockTest.json", []string{}, t)
}
func TestBcUncleTests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
+ t.Skip("Skipped until https://github.com/ethereum/go-ethereum/pull/857 is merged.")
runBlockTestsInFile("files/BlockTests/bcUncleTest.json", []string{}, t)
}
func TestBcUncleHeaderValidityTests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
+ t.Skip("Skipped until https://github.com/ethereum/go-ethereum/pull/857 is merged.")
runBlockTestsInFile("files/BlockTests/bcUncleHeaderValiditiy.json", []string{}, t)
}
func TestBcInvalidHeaderTests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
runBlockTestsInFile("files/BlockTests/bcInvalidHeaderTest.json", []string{}, t)
}
func TestBcInvalidRLPTests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
runBlockTestsInFile("files/BlockTests/bcInvalidRLPTest.json", []string{}, t)
}
func TestBcJSAPITests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
runBlockTestsInFile("files/BlockTests/bcJS_API_Test.json", []string{}, t)
}
func TestBcRPCAPITests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
+ t.Skip("Skipped until https://github.com/ethereum/go-ethereum/pull/857 is merged.")
runBlockTestsInFile("files/BlockTests/bcRPC_API_Test.json", []string{}, t)
}
func TestBcForkBlockTests(t *testing.T) {
- t.Skip("Skipped in lieu of performance fixes.")
runBlockTestsInFile("files/BlockTests/bcForkBlockTest.json", []string{}, t)
}
@@ -71,7 +66,6 @@ func runBlockTestsInFile(filepath string, snafus []string, t *testing.T) {
}
func runBlockTest(name string, test *BlockTest, t *testing.T) {
- t.Log("Running test: ", name)
cfg := testEthConfig()
ethereum, err := eth.New(cfg)
if err != nil {
@@ -100,7 +94,7 @@ func runBlockTest(name string, test *BlockTest, t *testing.T) {
if err = test.ValidatePostState(statedb); err != nil {
t.Fatal("post state validation failed: %v", err)
}
- t.Log("Test passed: ", name)
+ t.Log("Test passed: ", name)
}
func testEthConfig() *eth.Config {
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 692fb338c..ac59069d5 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -648,7 +648,7 @@ func (self *XEth) ConfirmTransaction(tx string) bool {
}
-func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
+func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
var (
from = common.HexToAddress(fromStr)
to = common.HexToAddress(toStr)
@@ -704,7 +704,13 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
}
state := self.backend.ChainManager().TxState()
- nonce := state.NewNonce(from)
+
+ var nonce uint64
+ if len(nonceStr) != 0 {
+ nonce = common.Big(nonceStr).Uint64()
+ } else {
+ nonce = state.NewNonce(from)
+ }
tx.SetNonce(nonce)
if err := self.sign(tx, from, false); err != nil {