diff options
Diffstat (limited to 'Godeps')
27 files changed, 984 insertions, 314 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 4c8c8281e..c51a2312b 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -22,8 +22,8 @@ }, { "ImportPath": "github.com/ethereum/ethash", - "Comment": "v23.1-33-g6ecb8e6", - "Rev": "6ecb8e610d60240187b44f61e66b06198c26fae6" + "Comment": "v23.1-81-g4039fd0", + "Rev": "4039fd095084679fb0bf3feae91d02506b5d67aa" }, { "ImportPath": "github.com/ethereum/serpent-go", diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml b/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml index 4b929eb69..30e944a68 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/.travis.yml @@ -1,6 +1,14 @@ +# 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 before_install: - - sudo apt-get update -qq - - sudo apt-get install -qq wget cmake gcc bash libboost-test-dev nodejs python-pip python-dev - - sudo pip install virtualenv -q + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + - sudo apt-get update -y -qq +install: + - 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 pip install virtualenv -q script: "./test/test.sh" diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/CMakeLists.txt b/Godeps/_workspace/src/github.com/ethereum/ethash/CMakeLists.txt index 79f2e5335..ea8c1849a 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/CMakeLists.txt +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/CMakeLists.txt @@ -18,4 +18,4 @@ if (OpenCL_FOUND) add_subdirectory(src/libethash-cl) endif() add_subdirectory(src/benchmark EXCLUDE_FROM_ALL) -add_subdirectory(test/c EXCLUDE_FROM_ALL) +add_subdirectory(test/c) diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go index 8746aaca9..c33bfccc4 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go @@ -34,13 +34,12 @@ import ( "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" "github.com/ethereum/go-ethereum/pow" ) var minDifficulty = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) -var powlogger = logger.NewLogger("POW") - type ParamsAndCache struct { params *C.ethash_params cache *C.ethash_cache @@ -85,29 +84,32 @@ func makeParamsAndCache(chainManager pow.ChainManager, blockNum uint64) (*Params Epoch: blockNum / epochLength, } C.ethash_params_init(paramsAndCache.params, C.uint32_t(uint32(blockNum))) - paramsAndCache.cache.mem = C.malloc(paramsAndCache.params.cache_size) + paramsAndCache.cache.mem = C.malloc(C.size_t(paramsAndCache.params.cache_size)) seedHash, err := GetSeedHash(blockNum) if err != nil { return nil, err } - powlogger.Infoln("Making Cache") + glog.V(logger.Info).Infoln("Making cache") start := time.Now() - C.ethash_mkcache(paramsAndCache.cache, paramsAndCache.params, (*C.uint8_t)(unsafe.Pointer(&seedHash[0]))) - powlogger.Infoln("Took:", time.Since(start)) + C.ethash_mkcache(paramsAndCache.cache, paramsAndCache.params, (*C.ethash_blockhash_t)(unsafe.Pointer(&seedHash[0]))) + + if glog.V(logger.Info) { + glog.Infoln("Took:", time.Since(start)) + } return paramsAndCache, nil } -func (pow *Ethash) UpdateCache(force bool) error { +func (pow *Ethash) UpdateCache(blockNum uint64, force bool) error { pow.cacheMutex.Lock() defer pow.cacheMutex.Unlock() - thisEpoch := pow.chainManager.CurrentBlock().NumberU64() / epochLength + thisEpoch := blockNum / epochLength if force || pow.paramsAndCache.Epoch != thisEpoch { var err error - pow.paramsAndCache, err = makeParamsAndCache(pow.chainManager, pow.chainManager.CurrentBlock().NumberU64()) + pow.paramsAndCache, err = makeParamsAndCache(pow.chainManager, blockNum) if err != nil { panic(err) } @@ -118,7 +120,7 @@ func (pow *Ethash) UpdateCache(force bool) error { func makeDAG(p *ParamsAndCache) *DAG { d := &DAG{ - dag: C.malloc(p.params.full_size), + dag: C.malloc(C.size_t(p.params.full_size)), file: false, paramsAndCache: p, } @@ -131,9 +133,9 @@ func makeDAG(p *ParamsAndCache) *DAG { for { select { case <-t.C: - powlogger.Infof("... still generating DAG (%v) ...\n", time.Since(tstart).Seconds()) + glog.V(logger.Info).Infof("... still generating DAG (%v) ...\n", time.Since(tstart).Seconds()) case str := <-donech: - powlogger.Infof("... %s ...\n", str) + glog.V(logger.Info).Infof("... %s ...\n", str) break done } } @@ -193,30 +195,30 @@ func (pow *Ethash) UpdateDAG() { pow.paramsAndCache = paramsAndCache path := path.Join("/", "tmp", "dag") pow.dag = nil - powlogger.Infoln("Retrieving DAG") + glog.V(logger.Info).Infoln("Retrieving DAG") start := time.Now() file, err := os.Open(path) if err != nil { - powlogger.Infof("No DAG found. Generating new DAG in '%s' (this takes a while)...\n", path) + 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 { - powlogger.Infof("DAG load err: %v\n", err) + glog.V(logger.Info).Infof("DAG load err: %v\n", err) } if len(data) < 8 { - powlogger.Infof("DAG in '%s' is less than 8 bytes, it must be corrupted. Generating new DAG (this takes a while)...\n", path) + 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 { - powlogger.Infof("DAG in '%s' is stale. Generating new DAG (this takes a while)...\n", path) + 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 @@ -224,7 +226,7 @@ func (pow *Ethash) UpdateDAG() { // 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) { - powlogger.Infof("DAG in '%s' is corrupted. Generating new DAG (this takes a while)...\n", path) + 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 @@ -238,7 +240,7 @@ func (pow *Ethash) UpdateDAG() { } } } - powlogger.Infoln("Took:", time.Since(start)) + glog.V(logger.Info).Infoln("Took:", time.Since(start)) file.Close() } @@ -319,14 +321,13 @@ func (pow *Ethash) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte start := time.Now().UnixNano() nonce := uint64(r.Int63()) - cMiningHash := (*C.uint8_t)(unsafe.Pointer(&miningHash[0])) + cMiningHash := (*C.ethash_blockhash_t)(unsafe.Pointer(&miningHash[0])) target := new(big.Int).Div(minDifficulty, diff) var ret C.ethash_return_value for { select { case <-stop: - powlogger.Infoln("Breaking from mining") pow.HashRate = 0 return 0, nil, nil default: @@ -337,11 +338,11 @@ func (pow *Ethash) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte 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[0]), C.int(32))) + result := common.Bytes2Big(C.GoBytes(unsafe.Pointer(&ret.result), C.int(32))) // 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[0]), C.int(32)) + 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) @@ -367,14 +368,14 @@ func (pow *Ethash) Verify(block pow.Block) bool { 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 { - powlogger.Infoln(fmt.Sprintf("Block number exceeds limit, invalid (value is %v, limit is %v)", + 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.uint8_t)(unsafe.Pointer(&hash[0])) + chash := (*C.ethash_blockhash_t)(unsafe.Pointer(&hash[0])) cnonce := C.uint64_t(nonce) target := new(big.Int).Div(minDifficulty, difficulty) @@ -386,13 +387,13 @@ func (pow *Ethash) verify(hash common.Hash, mixDigest common.Hash, difficulty *b 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) + pAc, err = makeParamsAndCache(pow.chainManager, blockNum+1) if err != nil { - powlogger.Infoln(err) + glog.V(logger.Info).Infoln("big fucking eror", err) return false } } else { - pow.UpdateCache(false) + pow.UpdateCache(blockNum, false) pow.cacheMutex.RLock() defer pow.cacheMutex.RUnlock() pAc = pow.paramsAndCache @@ -402,7 +403,7 @@ func (pow *Ethash) verify(hash common.Hash, mixDigest common.Hash, difficulty *b C.ethash_light(ret, pAc.cache, pAc.params, chash, cnonce) - result := common.Bytes2Big(C.GoBytes(unsafe.Pointer(&ret.result[0]), C.int(32))) + result := common.Bytes2Big(C.GoBytes(unsafe.Pointer(&ret.result), C.int(32))) return result.Cmp(target) <= 0 } @@ -418,7 +419,7 @@ func (pow *Ethash) FullHash(nonce uint64, miningHash []byte) []byte { pow.UpdateDAG() pow.dagMutex.Lock() defer pow.dagMutex.Unlock() - cMiningHash := (*C.uint8_t)(unsafe.Pointer(&miningHash[0])) + 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 @@ -428,7 +429,7 @@ func (pow *Ethash) FullHash(nonce uint64, miningHash []byte) []byte { } func (pow *Ethash) LightHash(nonce uint64, miningHash []byte) []byte { - cMiningHash := (*C.uint8_t)(unsafe.Pointer(&miningHash[0])) + 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) diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py b/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py index 29d6ad6d2..6a6b93839 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/setup.py @@ -1,33 +1,34 @@ #!/usr/bin/env python from distutils.core import setup, Extension - -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' - ], - extra_compile_args = ["-Isrc/", "-std=gnu99", "-Wall"]) - -setup ( - name = 'pyethash', - author = "Matthew Wampler-Doty", - author_email = "matthew.wampler.doty@gmail.com", - license = 'GPL', - version = '23', - url = 'https://github.com/ethereum/ethash', - download_url = 'https://github.com/ethereum/ethash/tarball/v23', - description = 'Python wrappers for ethash, the ethereum proof of work hashing function', - ext_modules = [pyethash], - ) + +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' + ], + extra_compile_args=["-Isrc/", "-std=gnu99", "-Wall"]) + +setup( + name='pyethash', + author="Matthew Wampler-Doty", + author_email="matthew.wampler.doty@gmail.com", + license='GPL', + version='0.1.23', + url='https://github.com/ethereum/ethash', + download_url='https://github.com/ethereum/ethash/tarball/v23', + description=('Python wrappers for ethash, the ethereum proof of work' + 'hashing function'), + ext_modules=[pyethash], +) 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 e6ba85790..840fe5146 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 @@ -6,6 +6,11 @@ if (MSVC) 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") +endif() + if (NOT MPI_FOUND) find_package(MPI) endif() 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 7dae4f18c..2635c8038 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 @@ -21,7 +21,7 @@ #include <stdio.h> #include <stdlib.h> -#include <time.h> +#include <chrono> #include <libethash/ethash.h> #include <libethash/util.h> #ifdef OPENCL @@ -41,6 +41,8 @@ #undef min #undef max +using std::chrono::high_resolution_clock; + #if defined(OPENCL) const unsigned trials = 1024*1024*32; #elif defined(FULL) @@ -104,10 +106,11 @@ extern "C" int main(void) //params.full_size = 8209 * 4096; // 8MBish; //params.cache_size = 8209*4096; //params.cache_size = 2053*4096; - uint8_t seed[32], previous_hash[32]; + ethash_blockhash_t seed; + ethash_blockhash_t previous_hash; - memcpy(seed, hexStringToBytes("9410b944535a83d9adf6bbdcc80e051f30676173c16ca0d32d6f1263fc246466").data(), 32); - memcpy(previous_hash, hexStringToBytes("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").data(), 32); + memcpy(&seed, hexStringToBytes("9410b944535a83d9adf6bbdcc80e051f30676173c16ca0d32d6f1263fc246466").data(), 32); + memcpy(&previous_hash, hexStringToBytes("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").data(), 32); // allocate page aligned buffer for dataset #ifdef FULL @@ -122,50 +125,50 @@ extern "C" int main(void) // compute cache or full data { - clock_t startTime = clock(); + auto startTime = high_resolution_clock::now(); ethash_mkcache(&cache, ¶ms, seed); - clock_t time = clock() - startTime; + auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count(); - uint8_t cache_hash[32]; - SHA3_256(cache_hash, (uint8_t const*)cache_mem, params.cache_size); + ethash_blockhash_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()); // print a couple of test hashes { - const clock_t startTime = clock(); + auto startTime = high_resolution_clock::now(); ethash_return_value hash; ethash_light(&hash, &cache, ¶ms, previous_hash, 0); - const clock_t time = clock() - startTime; - debugf("ethash_light test: %ums, %s\n", (unsigned)((time*1000)/CLOCKS_PER_SEC), bytesToHexString(hash.result, 32).data()); + 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()); } #ifdef FULL - startTime = clock(); + startTime = high_resolution_clock::now(); ethash_compute_full_data(full_mem, ¶ms, &cache); - time = clock() - startTime; - debugf("ethash_compute_full_data: %ums\n", (unsigned)((time*1000)/CLOCKS_PER_SEC)); + time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count(); + debugf("ethash_compute_full_data: %ums\n", (unsigned)time); #endif // FULL } #ifdef OPENCL ethash_cl_miner miner; { - const clock_t startTime = clock(); + auto startTime = high_resolution_clock::now(); if (!miner.init(params, seed)) exit(-1); - const clock_t time = clock() - startTime; - debugf("ethash_cl_miner init: %ums\n", (unsigned)((time*1000)/CLOCKS_PER_SEC)); + auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count(); + debugf("ethash_cl_miner init: %ums\n", (unsigned)time); } #endif #ifdef FULL { - const clock_t startTime = clock(); + auto startTime = high_resolution_clock::now(); ethash_return_value hash; ethash_full(&hash, full_mem, ¶ms, previous_hash, 0); - const clock_t time = clock() - startTime; - debugf("ethash_full test: %uns, %s\n", (unsigned)((time*1000000)/CLOCKS_PER_SEC), bytesToHexString(hash.result, 32).data()); + auto time = std::chrono::duration_cast<std::chrono::milliseconds>(high_resolution_clock::now() - startTime).count(); + debugf("ethash_full test: %uns, %s\n", (unsigned)time); } #endif @@ -186,10 +189,12 @@ extern "C" int main(void) } } } + + // ensure nothing else is going on + miner.finish(); #endif - - clock_t startTime = clock(); + auto startTime = high_resolution_clock::now(); unsigned hash_count = trials; #ifdef OPENCL @@ -201,7 +206,7 @@ extern "C" int main(void) virtual bool found(uint64_t const* nonces, uint32_t count) { - nonce_vec.assign(nonces, nonces + count); + nonce_vec.insert(nonce_vec.end(), nonces, nonces + count); return false; } @@ -241,15 +246,23 @@ extern "C" int main(void) } } #endif - - clock_t time = std::max((clock_t)1u, clock() - startTime); - + 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; - debugf( - "hashrate: %8u, bw: %6u MB/s\n", - (unsigned)(((uint64_t)hash_count*CLOCKS_PER_SEC)/time), - (unsigned)((((uint64_t)hash_count*read_size*CLOCKS_PER_SEC)/time) / (1024*1024)) +#if defined(OPENCL) || defined(FULL) + debugf( + "hashrate: %8.2f Mh/s, bw: %8.2f GB/s\n", + (double)hash_count * (1000*1000)/time / (1000*1000), + (double)hash_count*read_size * (1000*1000)/time / (1024*1024*1024) + ); +#else + debugf( + "hashrate: %8.2f Kh/s, bw: %8.2f MB/s\n", + (double)hash_count * (1000*1000)/time / (1000), + (double)hash_count*read_size * (1000*1000)/time / (1024*1024) ); +#endif free(cache_mem_buf); #ifdef FULL 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 f37471cf3..30fa7ed4b 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 @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 2.8) + set(LIBRARY ethash-cl) set(CMAKE_BUILD_TYPE Release) @@ -28,11 +30,16 @@ if (NOT MSVC) endif () endif() +set(OpenCL_FOUND TRUE) +set(OpenCL_INCLUDE_DIRS /usr/include/CL) +set(OpenCL_LIBRARIES -lOpenCL) + if (NOT OpenCL_FOUND) find_package(OpenCL) endif() if (OpenCL_FOUND) + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -Werror -pedantic -fPIC ${CMAKE_CXX_FLAGS}") include_directories(${OpenCL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(..) add_library(${LIBRARY} ethash_cl_miner.cpp ethash_cl_miner.h cl.hpp) 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 d3f0e9611..bf7bb2128 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 @@ -22,6 +22,8 @@ #define _CRT_SECURE_NO_WARNINGS +#include <cstdio> +#include <cstdlib> #include <assert.h> #include <queue> #include <vector> @@ -52,7 +54,7 @@ ethash_cl_miner::ethash_cl_miner() { } -bool ethash_cl_miner::init(ethash_params const& params, const uint8_t seed[32], unsigned workgroup_size) +bool ethash_cl_miner::init(ethash_params const& params, ethash_blockhash_t const *seed, unsigned workgroup_size) { // store params m_params = params; @@ -95,7 +97,7 @@ bool ethash_cl_miner::init(ethash_params const& params, const uint8_t seed[32], } // create context - m_context = cl::Context(std::vector<cl::Device>(&device, &device+1)); + m_context = cl::Context(std::vector<cl::Device>(&device, &device + 1)); m_queue = cl::CommandQueue(m_context, device); // use requested workgroup size, but we require multiple of 8 @@ -308,6 +310,10 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook if (exit) break; + // reset search buffer if we're still going + if (num_found) + m_queue.enqueueWriteBuffer(m_search_buf[batch.buf], true, 0, 4, &c_zero); + pending.pop(); } } 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 3fb98b5b7..af614b3e4 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 @@ -19,8 +19,9 @@ public: public: ethash_cl_miner(); - bool init(ethash_params const& params, const uint8_t seed[32], unsigned workgroup_size = 64); + bool init(ethash_params const& params, ethash_blockhash_t const *seed, unsigned workgroup_size = 64); + 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); @@ -41,4 +42,4 @@ private: cl::Buffer m_search_buf[c_num_buffers]; unsigned m_workgroup_size; bool m_opencl_1_1; -};
\ No newline at end of file +}; 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 38fc821c0..c92240086 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 @@ -12,6 +12,7 @@ endif() set(FILES util.c util.h + io.c internal.c ethash.h endian.h @@ -19,6 +20,12 @@ set(FILES util.c fnv.h data_sizes.h) +if (MSVC) + list(APPEND FILES io_win32.c) +else() + list(APPEND FILES io_posix.c) +endif() + if (NOT CRYPTOPP_FOUND) find_package(CryptoPP 5.6.2) 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 3b747b3ea..cf52ae4f8 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 @@ -48,7 +48,7 @@ extern "C" { // Sow[i*HashBytes]; j++]]]][[2]][[1]] -static const size_t dag_sizes[2048] = { +static const uint64_t dag_sizes[2048] = { 1073739904U, 1082130304U, 1090514816U, 1098906752U, 1107293056U, 1115684224U, 1124070016U, 1132461952U, 1140849536U, 1149232768U, 1157627776U, 1166013824U, 1174404736U, 1182786944U, 1191180416U, @@ -477,7 +477,7 @@ static const size_t dag_sizes[2048] = { // While[! PrimeQ[i], i--]; // Sow[i*HashBytes]; j++]]]][[2]][[1]] -const size_t cache_sizes[2048] = { +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, 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 a7159de65..fad964449 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 @@ -43,73 +43,107 @@ extern "C" { #endif typedef struct ethash_params { - size_t full_size; // Size of full data set (in bytes, multiple of mix size (128)). - size_t cache_size; // Size of compute cache (in bytes, multiple of node size (64)). + 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 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]; +} + +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); +} + typedef struct ethash_return_value { - uint8_t result[32]; - uint8_t mix_hash[32]; + ethash_blockhash_t result; + ethash_blockhash_t mix_hash; } ethash_return_value; -size_t ethash_get_datasize(const uint32_t block_number); -size_t ethash_get_cachesize(const uint32_t block_number); +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); + params->full_size = ethash_get_datasize(block_number); + params->cache_size = ethash_get_cachesize(block_number); } typedef struct ethash_cache { - void *mem; + void *mem; } ethash_cache; -void ethash_mkcache(ethash_cache *cache, ethash_params const *params, const uint8_t seed[32]); +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, const uint8_t header_hash[32], const uint64_t nonce); -void ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce); -void ethash_get_seedhash(uint8_t seedhash[32], const uint32_t block_number); - -static inline void ethash_prep_light(void *cache, ethash_params const *params, const uint8_t seed[32]) { +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, const uint8_t header_hash[32], const uint64_t nonce) { +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) { +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, const uint8_t header_hash[32], const uint64_t nonce) { +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( - const uint8_t hash[32], - const uint8_t difficulty[32]) { +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 (hash[i] == difficulty[i]) continue; - return hash[i] < difficulty[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( - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32], - const uint8_t difficulty[32]); +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); #ifdef __cplusplus } 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 0a7e767e7..5009d52f5 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 @@ -37,12 +37,12 @@ #include "sha3.h" #endif // WITH_CRYPTOPP -size_t ethash_get_datasize(const uint32_t block_number) { +uint64_t ethash_get_datasize(const uint32_t block_number) { assert(block_number / EPOCH_LENGTH < 2048); return dag_sizes[block_number / EPOCH_LENGTH]; } -size_t ethash_get_cachesize(const uint32_t block_number) { +uint64_t ethash_get_cachesize(const uint32_t block_number) { assert(block_number / EPOCH_LENGTH < 2048); return cache_sizes[block_number / EPOCH_LENGTH]; } @@ -50,14 +50,14 @@ size_t ethash_get_cachesize(const uint32_t block_number) { // 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, - const uint8_t seed[32]) { +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, seed, 32); + 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); @@ -84,20 +84,19 @@ void static ethash_compute_cache_nodes( #endif } -void ethash_mkcache( - ethash_cache *cache, - ethash_params const *params, - const uint8_t seed[32]) { +void ethash_mkcache(ethash_cache *cache, + ethash_params const *params, + ethash_blockhash_t const* seed) +{ node *nodes = (node *) cache->mem; ethash_compute_cache_nodes(nodes, params, seed); } -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, + const unsigned node_index, + const struct ethash_params *params, + const struct ethash_cache *cache) +{ 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]; @@ -161,13 +160,13 @@ void ethash_compute_full_data( } } -static void ethash_hash( - ethash_return_value *ret, - node const *full_nodes, - ethash_cache const *cache, - ethash_params const *params, - const uint8_t header_hash[32], - const uint64_t nonce) { +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) +{ assert((params->full_size % MIX_WORDS) == 0); @@ -251,16 +250,16 @@ static void ethash_hash( } #endif - memcpy(ret->mix_hash, mix->bytes, 32); + memcpy(&ret->mix_hash, mix->bytes, 32); // final Keccak hash - SHA3_256(ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix) + SHA3_256(&ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix) } -void ethash_quick_hash( - uint8_t return_hash[32], - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32]) { +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) +{ uint8_t buf[64 + 32]; memcpy(buf, header_hash, 32); @@ -273,28 +272,39 @@ void ethash_quick_hash( SHA3_256(return_hash, buf, 64 + 32); } -void ethash_get_seedhash(uint8_t seedhash[32], const uint32_t block_number) { - memset(seedhash, 0, 32); +void ethash_get_seedhash(ethash_blockhash_t *seedhash, const uint32_t block_number) +{ + ethash_blockhash_reset(seedhash); const uint32_t epochs = block_number / EPOCH_LENGTH; for (uint32_t i = 0; i < epochs; ++i) - SHA3_256(seedhash, seedhash, 32); + SHA3_256(seedhash, (uint8_t*)seedhash, 32); } -int ethash_quick_check_difficulty( - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32], - const uint8_t difficulty[32]) { +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) +{ - uint8_t return_hash[32]; - ethash_quick_hash(return_hash, header_hash, nonce, mix_hash); - return ethash_check_difficulty(return_hash, difficulty); + ethash_blockhash_t return_hash; + ethash_quick_hash(&return_hash, header_hash, nonce, mix_hash); + return ethash_check_difficulty(&return_hash, difficulty); } -void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { - ethash_hash(ret, (node const *) full_mem, NULL, params, previous_hash, nonce); +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) +{ + ethash_hash(ret, (node const *) full_mem, NULL, params, header_hash, nonce); } -void ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { - ethash_hash(ret, NULL, cache, params, previous_hash, nonce); -}
\ No newline at end of file +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) +{ + ethash_hash(ret, NULL, cache, params, header_hash, nonce); +} 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 ddd06e8f4..1e19cd1fd 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 @@ -30,19 +30,16 @@ typedef union node { } node; -void ethash_calculate_dag_item( - node *const ret, - const unsigned node_index, - ethash_params const *params, - ethash_cache const *cache -); - -void ethash_quick_hash( - uint8_t return_hash[32], - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32]); +void ethash_calculate_dag_item(node *const ret, + const unsigned node_index, + ethash_params const *params, + ethash_cache const *cache); + +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); #ifdef __cplusplus } -#endif
\ No newline at end of file +#endif 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 new file mode 100644 index 000000000..5a8eebae5 --- /dev/null +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.c @@ -0,0 +1,89 @@ +/* + 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 io.c + * @author Lefteris Karapetsas <lefteris@ethdev.com> + * @date 2015 + */ +#include "io.h" +#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) +{ + 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); + + if (!ethash_io_write_file(dirname, PASS_ARR(DAG_FILE_NAME), temp_data_ptr, (size_t)params->full_size)) { + goto fail_free; + } + + 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; + } + + *data = temp_data_ptr; + *data_size = params->full_size; + return true; + +fail_free: + free(temp_data_ptr); +end: + return false; +} + +#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 new file mode 100644 index 000000000..8cf8b69bf --- /dev/null +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h @@ -0,0 +1,115 @@ +/* + 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 io.h + * @author Lefteris Karapetsas <lefteris@ethdev.com> + * @date 2015 + */ +#pragma once +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.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 + +/// 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 +}; + +/** + * 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() + * + * @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 + */ +enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash); + +/** + * Fully computes data and writes it to the file on disk. + * + * 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. + * + * @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. + */ +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); + +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); +} + +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; + } + + name[0] = '\0'; + strcat(name, dirname); + strcat(name, filename); + return name; +} + + +#ifdef __cplusplus +} +#endif 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 new file mode 100644 index 000000000..693bdf750 --- /dev/null +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_posix.c @@ -0,0 +1,76 @@ +/* + 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 io_posix.c + * @author Lefteris Karapetsas <lefteris@ethdev.com> + * @date 2015 + */ + +#include "io.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <libgen.h> +#include <stdio.h> +#include <unistd.h> + +enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash) +{ + char read_buffer[DAG_MEMO_BYTESIZE]; + char expect_buffer[DAG_MEMO_BYTESIZE]; + enum ethash_io_rc ret = ETHASH_IO_FAIL; + + // 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 *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME)); + if (!memofile) { + goto end; + } + + // 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; + } + + if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) { + goto close; + } + + 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; + } + + ret = ETHASH_IO_MEMO_MATCH; + +close: + fclose(f); +free_memo: + free(memofile); +end: + return ret; +} 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 new file mode 100644 index 000000000..2cabc939a --- /dev/null +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c @@ -0,0 +1,73 @@ +/* + 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 io_win32.c + * @author Lefteris Karapetsas <lefteris@ethdev.com> + * @date 2015 + */ + +#include "io.h" +#include <direct.h> +#include <errno.h> +#include <stdio.h> + +enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash) +{ + char read_buffer[DAG_MEMO_BYTESIZE]; + char expect_buffer[DAG_MEMO_BYTESIZE]; + enum ethash_io_rc ret = ETHASH_IO_FAIL; + + // assert directory exists + int rc = _mkdir(dirname); + if (rc == -1 && errno != EEXIST) { + goto end; + } + + char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME)); + if (!memofile) { + goto end; + } + + // 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; + } + + if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) { + goto close; + } + + 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; + } + + ret = ETHASH_IO_MEMO_MATCH; + +close: + fclose(f); +free_memo: + free(memofile); +end: + return ret; +} 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 36a0a5301..84dca241b 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,20 +8,24 @@ extern "C" { #include <stdint.h> #include <stdlib.h> +struct ethash_blockhash; + #define decsha3(bits) \ int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); decsha3(256) decsha3(512) -static inline void SHA3_256(uint8_t * const ret, uint8_t const *data, const size_t size) { - sha3_256(ret, 32, data, size); +static inline void SHA3_256(struct ethash_blockhash const* ret, uint8_t const *data, const size_t size) +{ + sha3_256((uint8_t*)ret, 32, data, size); } -static inline void SHA3_512(uint8_t * const ret, uint8_t const *data, const size_t size) { +static inline void SHA3_512(uint8_t *ret, uint8_t const *data, const size_t size) +{ sha3_512(ret, 64, data, size); } #ifdef __cplusplus } -#endif
\ No newline at end of file +#endif 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 6cbbcad8f..e4d8b1855 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 @@ -19,16 +19,17 @@ * @author Tim Hughes <tim@twistedfury.com> * @date 2015 */ - #include <stdint.h> #include <cryptopp/sha3.h> extern "C" { -void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size) { - CryptoPP::SHA3_256().CalculateDigest(ret, data, size); +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); } void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size) { CryptoPP::SHA3_512().CalculateDigest(ret, data, size); } -}
\ No newline at end of file +} 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 f910960e1..6b257b87c 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 @@ -2,14 +2,18 @@ #include "compiler.h" #include <stdint.h> +#include <stdlib.h> #ifdef __cplusplus extern "C" { #endif -void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size); +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); void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size); #ifdef __cplusplus } -#endif
\ No newline at end of file +#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 359735998..9024bd584 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 @@ -5,6 +5,14 @@ #include <time.h> #include "../libethash/ethash.h" +#if PY_MAJOR_VERSION >= 3 +#define PY_STRING_FORMAT "y#" +#define PY_CONST_STRING_FORMAT "y" +#else +#define PY_STRING_FORMAT "s#" +#define PY_CONST_STRING_FORMAT "s" +#endif + #define MIX_WORDS (MIX_BYTES/4) static PyObject * @@ -46,7 +54,7 @@ mkcache_bytes(PyObject *self, PyObject *args) { unsigned long cache_size; int seed_len; - if (!PyArg_ParseTuple(args, "ks#", &cache_size, &seed, &seed_len)) + if (!PyArg_ParseTuple(args, "k" PY_STRING_FORMAT, &cache_size, &seed, &seed_len)) return 0; if (seed_len != 32) { @@ -61,8 +69,8 @@ mkcache_bytes(PyObject *self, PyObject *args) { params.cache_size = (size_t) cache_size; ethash_cache cache; cache.mem = malloc(cache_size); - ethash_mkcache(&cache, ¶ms, (uint8_t *) seed); - PyObject * val = Py_BuildValue("s#", cache.mem, cache_size); + ethash_mkcache(&cache, ¶ms, (ethash_blockhash_t *) seed); + PyObject * val = Py_BuildValue(PY_STRING_FORMAT, cache.mem, cache_size); free(cache.mem); return val; } @@ -74,7 +82,7 @@ calc_dataset_bytes(PyObject *self, PyObject *args) { unsigned long full_size; int cache_size; - if (!PyArg_ParseTuple(args, "ks#", &full_size, &cache_bytes, &cache_size)) + if (!PyArg_ParseTuple(args, "k" PY_STRING_FORMAT, &full_size, &cache_bytes, &cache_size)) return 0; if (full_size % MIX_WORDS != 0) { @@ -98,7 +106,7 @@ calc_dataset_bytes(PyObject *self, PyObject *args) { cache.mem = (void *) cache_bytes; void *mem = malloc(params.full_size); ethash_compute_full_data(mem, ¶ms, &cache); - PyObject * val = Py_BuildValue("s#", (char *) mem, full_size); + PyObject * val = Py_BuildValue(PY_STRING_FORMAT, (char *) mem, full_size); free(mem); return val; } @@ -106,28 +114,25 @@ calc_dataset_bytes(PyObject *self, PyObject *args) { // hashimoto_light(full_size, cache, header, nonce) static PyObject * hashimoto_light(PyObject *self, PyObject *args) { - char *cache_bytes, *header; + char *cache_bytes; + char *header; unsigned long full_size; unsigned long long nonce; int cache_size, header_size; - - if (!PyArg_ParseTuple(args, "ks#s#K", &full_size, &cache_bytes, &cache_size, &header, &header_size, &nonce)) + if (!PyArg_ParseTuple(args, "k" PY_STRING_FORMAT PY_STRING_FORMAT "K", &full_size, &cache_bytes, &cache_size, &header, &header_size, &nonce)) return 0; - if (full_size % MIX_WORDS != 0) { char error_message[1024]; sprintf(error_message, "The size of data set must be a multiple of %i bytes (was %lu)", MIX_WORDS, full_size); PyErr_SetString(PyExc_ValueError, error_message); return 0; } - if (cache_size % 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); PyErr_SetString(PyExc_ValueError, error_message); return 0; } - if (header_size != 32) { char error_message[1024]; sprintf(error_message, "Seed must be 32 bytes long (was %i)", header_size); @@ -135,27 +140,27 @@ hashimoto_light(PyObject *self, PyObject *args) { return 0; } - ethash_return_value out; ethash_params params; params.cache_size = (size_t) cache_size; params.full_size = (size_t) full_size; ethash_cache cache; cache.mem = (void *) cache_bytes; - ethash_light(&out, &cache, ¶ms, (uint8_t *) header, nonce); - return Py_BuildValue("{s:s#,s:s#}", - "mix digest", out.mix_hash, 32, - "result", out.result, 32); + ethash_light(&out, &cache, ¶ms, (ethash_blockhash_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); } // hashimoto_full(dataset, header, nonce) static PyObject * hashimoto_full(PyObject *self, PyObject *args) { - char *full_bytes, *header; + char *full_bytes; + char *header; unsigned long long nonce; int full_size, header_size; - if (!PyArg_ParseTuple(args, "s#s#K", &full_bytes, &full_size, &header, &header_size, &nonce)) + if (!PyArg_ParseTuple(args, PY_STRING_FORMAT PY_STRING_FORMAT "K", &full_bytes, &full_size, &header, &header_size, &nonce)) return 0; if (full_size % MIX_WORDS != 0) { @@ -176,21 +181,23 @@ 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, ¶ms, (uint8_t *) header, nonce); - return Py_BuildValue("{s:s#, s:s#}", - "mix digest", out.mix_hash, 32, - "result", out.result, 32); + ethash_full(&out, (void *) full_bytes, ¶ms, (ethash_blockhash_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); } // mine(dataset_bytes, header, difficulty_bytes) static PyObject * mine(PyObject *self, PyObject *args) { - char *full_bytes, *header, *difficulty; + char *full_bytes; + char *header; + char *difficulty; srand(time(0)); uint64_t nonce = ((uint64_t) rand()) << 32 | rand(); int full_size, header_size, difficulty_size; - if (!PyArg_ParseTuple(args, "s#s#s#", &full_bytes, &full_size, &header, &header_size, &difficulty, &difficulty_size)) + if (!PyArg_ParseTuple(args, PY_STRING_FORMAT PY_STRING_FORMAT PY_STRING_FORMAT, &full_bytes, &full_size, &header, &header_size, &difficulty, &difficulty_size)) return 0; if (full_size % MIX_WORDS != 0) { @@ -220,13 +227,13 @@ mine(PyObject *self, PyObject *args) { // TODO: Multi threading? do { - ethash_full(&out, (void *) full_bytes, ¶ms, (const uint8_t *) header, nonce++); + ethash_full(&out, (void *) full_bytes, ¶ms, (const ethash_blockhash_t *) header, nonce++); // TODO: disagrees with the spec https://github.com/ethereum/wiki/wiki/Ethash#mining - } while (!ethash_check_difficulty(out.result, (const uint8_t *) difficulty)); + } while (!ethash_check_difficulty(&out.result, (const ethash_blockhash_t *) difficulty)); - return Py_BuildValue("{s:s#, s:s#, s:K}", - "mix digest", out.mix_hash, 32, - "result", out.result, 32, + 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, + "result", &out.result, 32, "nonce", nonce); } @@ -243,9 +250,9 @@ get_seedhash(PyObject *self, PyObject *args) { PyErr_SetString(PyExc_ValueError, error_message); return 0; } - uint8_t seedhash[32]; - ethash_get_seedhash(seedhash, block_number); - return Py_BuildValue("s#", (char *) seedhash, 32); + ethash_blockhash_t seedhash; + ethash_get_seedhash(&seedhash, block_number); + return Py_BuildValue(PY_STRING_FORMAT, (char *) &seedhash, 32); } static PyMethodDef PyethashMethods[] = @@ -287,6 +294,32 @@ static PyMethodDef PyethashMethods[] = {NULL, NULL, 0, NULL} }; +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef PyethashModule = { + PyModuleDef_HEAD_INIT, + "pyethash", + "...", + -1, + PyethashMethods +}; + +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); + return module; +} +#else PyMODINIT_FUNC initpyethash(void) { PyObject *module = Py_InitModule("pyethash", PyethashMethods); @@ -303,3 +336,4 @@ initpyethash(void) { PyModule_AddIntConstant(module, "CACHE_ROUNDS", (long) CACHE_ROUNDS); PyModule_AddIntConstant(module, "ACCESSES", (long) 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 02e2aab91..dd91d8a92 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 @@ -1,5 +1,30 @@ +if (MSVC) + if (NOT BOOST_ROOT) + set (BOOST_ROOT "$ENV{BOOST_ROOT}") + endif() + set (CMAKE_PREFIX_PATH BOOST_ROOT) +endif() + IF( NOT Boost_FOUND ) - find_package(Boost COMPONENTS unit_test_framework) + # use multithreaded boost libraries, with -mt suffix + set(Boost_USE_MULTITHREADED ON) + + if (MSVC) + # TODO handle other msvc versions or it will fail find them + set(Boost_COMPILER -vc120) + # use static boost libraries *.lib + set(Boost_USE_STATIC_LIBS ON) + elseif (APPLE) + + # use static boost libraries *.a + set(Boost_USE_STATIC_LIBS ON) + + elseif (UNIX) + # use dynamic boost libraries .dll + set(Boost_USE_STATIC_LIBS OFF) + + endif() + find_package(Boost 1.48.0 COMPONENTS unit_test_framework system filesystem) ENDIF() IF( Boost_FOUND ) @@ -8,21 +33,29 @@ IF( Boost_FOUND ) link_directories ( ${Boost_LIBRARY_DIRS} ) file(GLOB HEADERS "*.h") - ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) - + if (NOT MSVC) + ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) + endif() if (NOT CRYPTOPP_FOUND) - find_package (CryptoPP) + find_package (CryptoPP) endif() if (CRYPTOPP_FOUND) - add_definitions(-DWITH_CRYPTOPP) + add_definitions(-DWITH_CRYPTOPP) endif() + if (NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") + endif() + add_executable (Test test.cpp ${HEADERS}) - target_link_libraries (Test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${ETHHASH_LIBS}) + 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}) if (CRYPTOPP_FOUND) - TARGET_LINK_LIBRARIES(Test ${CRYPTOPP_LIBRARIES}) + TARGET_LINK_LIBRARIES(Test ${CRYPTOPP_LIBRARIES}) endif() enable_testing () 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 21cb251fc..ffe8d53f3 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 @@ -2,6 +2,7 @@ #include <libethash/fnv.h> #include <libethash/ethash.h> #include <libethash/internal.h> +#include <libethash/io.h> #ifdef WITH_CRYPTOPP @@ -14,18 +15,32 @@ #define BOOST_TEST_MODULE Daggerhashimoto #define BOOST_TEST_MAIN -#include <boost/test/unit_test.hpp> #include <iostream> +#include <fstream> +#include <vector> +#include <boost/filesystem.hpp> +#include <boost/test/unit_test.hpp> + +using namespace std; +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 size_t s) { +std::string bytesToHexString(const uint8_t *str, const uint64_t s) { std::ostringstream ret; - for (int i = 0; i < s; ++i) + 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_blockhash_t *hash) { + return bytesToHexString((uint8_t*)hash, 32); +} + BOOST_AUTO_TEST_CASE(fnv_hash_check) { uint32_t x = 1235U; const uint32_t @@ -41,12 +56,13 @@ BOOST_AUTO_TEST_CASE(fnv_hash_check) { } BOOST_AUTO_TEST_CASE(SHA256_check) { - uint8_t input[32], out[32]; - memcpy(input, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32); - SHA3_256(out, input, 32); + 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(out, 32); + actual = bytesToHexString((uint8_t*)&out, 32); BOOST_REQUIRE_MESSAGE(expected == actual, "\nexpected: " << expected.c_str() << "\n" << "actual: " << actual.c_str() << "\n"); @@ -93,24 +109,27 @@ BOOST_AUTO_TEST_CASE(ethash_params_init_genesis_calcifide_check) { BOOST_AUTO_TEST_CASE(light_and_full_client_checks) { ethash_params params; - uint8_t seed[32], hash[32], difficulty[32]; - ethash_return_value light_out, full_out; - memcpy(seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32); - memcpy(hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32); + 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 - difficulty[0] = 197; - difficulty[1] = 90; + ethash_blockhash_set(&difficulty, 0, 197); + ethash_blockhash_set(&difficulty, 1, 90); for (int i = 2; i < 32; i++) - difficulty[i] = (uint8_t) 255; + ethash_blockhash_set(&difficulty, i, 255); ethash_params_init(¶ms, 0); params.cache_size = 1024; params.full_size = 1024 * 32; ethash_cache cache; - cache.mem = alloca(params.cache_size); - ethash_mkcache(&cache, ¶ms, seed); - node *full_mem = (node *) alloca(params.full_size); + cache.mem = our_alloca(params.cache_size); + ethash_mkcache(&cache, ¶ms, &seed); + node *full_mem = (node *) our_alloca(params.full_size); ethash_compute_full_data(full_mem, ¶ms, &cache); { @@ -153,76 +172,217 @@ BOOST_AUTO_TEST_CASE(light_and_full_client_checks) { { uint64_t nonce = 0x7c7c597c; - ethash_full(&full_out, full_mem, ¶ms, hash, nonce); - ethash_light(&light_out, &cache, ¶ms, hash, nonce); + ethash_full(&full_out, full_mem, ¶ms, &hash, nonce); + ethash_light(&light_out, &cache, ¶ms, &hash, nonce); const std::string - light_result_string = bytesToHexString(light_out.result, 32), - full_result_string = bytesToHexString(full_out.result, 32); + 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 = bytesToHexString(light_out.mix_hash, 32), - full_mix_hash_string = bytesToHexString(full_out.mix_hash, 32); + 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"); - uint8_t check_hash[32]; - ethash_quick_hash(check_hash, hash, nonce, full_out.mix_hash); - const std::string check_hash_string = bytesToHexString(check_hash, 32); + 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, ¶ms, hash, 5); + ethash_full(&full_out, full_mem, ¶ms, &hash, 5); std::string - light_result_string = bytesToHexString(light_out.result, 32), - full_result_string = bytesToHexString(full_out.result, 32); + 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, ¶ms, hash, 5); - light_result_string = bytesToHexString(light_out.result, 32); + ethash_light(&light_out, &cache, ¶ms, &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 = bytesToHexString(light_out.mix_hash, 32), - full_mix_hash_string = bytesToHexString(full_out.mix_hash, 32); + 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), + 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), + 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) { - uint8_t hash[32], target[32]; - memset(hash, 0, 32); - memset(target, 0, 32); - - memcpy(hash, "11111111111111111111111111111111", 32); - memcpy(target, "22222222222222222222222222222222", 32); + 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"); + 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); + 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); + 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"); -}
\ No newline at end of file + !ethash_check_difficulty(&hash, &target), ""); + // "\nexpected \"" << hash << "\" to have more difficulty than \"" << target << "\"\n"); +} + +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/"); +} + +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(¶ms, blockn); + params.cache_size = 1024; + params.full_size = 1024 * 32; + cache.mem = our_alloca(params.cache_size); + ethash_mkcache(&cache, ¶ms, &seedhash); + + BOOST_REQUIRE( + ethash_io_write("./test_ethash_directory/", ¶ms, 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_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(¶ms, blockn); + params.cache_size = 1024; + params.full_size = 1024 * 32; + cache.mem = our_alloca(params.cache_size); + ethash_mkcache(&cache, ¶ms, &seedhash); + + BOOST_REQUIRE( + ethash_io_write("./test_ethash_directory/", ¶ms, 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); +} + +// 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) +{ + ifstream ifs(filename, ios::binary|ios::ate); + ifstream::pos_type pos = ifs.tellg(); + + std::vector<char> result((unsigned int)pos); + + ifs.seekg(0, ios::beg); + ifs.read(&result[0], pos); + + return result; +} + +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(¶ms, blockn); + params.cache_size = 1024; + params.full_size = 1024 * 32; + cache.mem = our_alloca(params.cache_size); + ethash_mkcache(&cache, ¶ms, &seedhash); + + BOOST_REQUIRE( + ethash_io_write("./test_ethash_directory/", ¶ms, 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); +} diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/go/test.sh b/Godeps/_workspace/src/github.com/ethereum/ethash/test/go/test.sh deleted file mode 100644 index c6224858e..000000000 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/go/test.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# Strict mode -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" -done -TEST_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -export GOPATH=${HOME}/.go -export PATH=$PATH:$GOPATH/bin -echo "# getting go dependencies (can take some time)..." -cd ${TEST_DIR}/../.. && go get -cd ${GOPATH}/src/github.com/ethereum/go-ethereum -git checkout poc-9 -cd ${TEST_DIR} && go test diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/python/test.sh b/Godeps/_workspace/src/github.com/ethereum/ethash/test/python/test.sh index 95cea0215..05c66b550 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/python/test.sh +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/test/python/test.sh @@ -3,6 +3,15 @@ # Strict mode set -e +if [ -x "$(which virtualenv2)" ] ; then + VIRTUALENV_EXEC=virtualenv2 +elif [ -x "$(which virtualenv)" ] ; then + VIRTUALENV_EXEC=virtualenv +else + echo "Could not find a suitable version of virtualenv" + false +fi + SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" @@ -11,9 +20,11 @@ while [ -h "$SOURCE" ]; do done TEST_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -[ -d $TEST_DIR/python-virtual-env ] || virtualenv --system-site-packages $TEST_DIR/python-virtual-env +[ -d $TEST_DIR/python-virtual-env ] || $VIRTUALENV_EXEC --system-site-packages $TEST_DIR/python-virtual-env source $TEST_DIR/python-virtual-env/bin/activate pip install -r $TEST_DIR/requirements.txt > /dev/null +# force installation of nose in virtualenv even if existing in thereuser's system +pip install nose -I pip install --upgrade --no-deps --force-reinstall -e $TEST_DIR/../.. cd $TEST_DIR nosetests --with-doctest -v --nocapture |