From b24f16fa532483e0714700d687f134fb373f2487 Mon Sep 17 00:00:00 2001
From: Gustav Simonsson <gustav.simonsson@gmail.com>
Date: Thu, 14 May 2015 03:39:07 +0200
Subject: Make read of ethash hashrate atomic and update ethash godep

---
 .../src/github.com/ethereum/ethash/ethash.go       |  22 ++--
 .../github.com/ethereum/ethash/src/python/core.c   | 127 +++++----------------
 2 files changed, 43 insertions(+), 106 deletions(-)

(limited to 'Godeps/_workspace')

diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
index 5b94711c4..ce450d461 100644
--- a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
+++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
@@ -18,6 +18,7 @@ import (
 	"path/filepath"
 	"runtime"
 	"sync"
+	"sync/atomic"
 	"time"
 	"unsafe"
 
@@ -235,7 +236,7 @@ type Full struct {
 
 	test     bool // if set use a smaller DAG size
 	turbo    bool
-	hashRate int64
+	hashRate int32
 
 	mu      sync.Mutex // protects dag
 	current *dag       // current full DAG
@@ -265,6 +266,7 @@ func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mi
 	i := int64(0)
 	starti := i
 	start := time.Now().UnixNano()
+	previousHashrate := int32(0)
 
 	nonce = uint64(r.Int63())
 	hash := hashToH256(block.HashNoNonce())
@@ -272,14 +274,20 @@ func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mi
 	for {
 		select {
 		case <-stop:
-			pow.hashRate = 0
+			atomic.AddInt32(&pow.hashRate, -previousHashrate)
 			return 0, nil
 		default:
 			i++
 
-			elapsed := time.Now().UnixNano() - start
-			hashes := ((float64(1e9) / float64(elapsed)) * float64(i-starti)) / 1000
-			pow.hashRate = int64(hashes)
+			// we don't have to update hash rate on every nonce, so update after
+			// first nonce check and then after 2^X nonces
+			if i == 2 || ((i % (1 << 16)) == 0) {
+				elapsed := time.Now().UnixNano() - start
+				hashes := (float64(1e9) / float64(elapsed)) * float64(i-starti)
+				hashrateDiff := int32(hashes) - previousHashrate
+				previousHashrate = int32(hashes)
+				atomic.AddInt32(&pow.hashRate, hashrateDiff)
+			}
 
 			ret := C.ethash_full_compute(dag.ptr, hash, C.uint64_t(nonce))
 			result := h256ToHash(ret.result).Big()
@@ -287,6 +295,7 @@ func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mi
 			// TODO: disagrees with the spec https://github.com/ethereum/wiki/wiki/Ethash#mining
 			if ret.success && result.Cmp(target) <= 0 {
 				mixDigest = C.GoBytes(unsafe.Pointer(&ret.mix_hash), C.int(32))
+				atomic.AddInt32(&pow.hashRate, -previousHashrate)
 				return nonce, mixDigest
 			}
 			nonce += 1
@@ -299,8 +308,7 @@ func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mi
 }
 
 func (pow *Full) GetHashrate() int64 {
-	// TODO: this needs to use an atomic operation.
-	return pow.hashRate
+	return int64(atomic.LoadInt32(&pow.hashRate))
 }
 
 func (pow *Full) Turbo(on bool) {
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 d77b9761b..c66e03c54 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
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include "../libethash/ethash.h"
+#include "../libethash/internal.h"
 
 #if PY_MAJOR_VERSION >= 3
 #define PY_STRING_FORMAT "y#"
@@ -15,67 +16,21 @@
 
 #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 >= ETHASH_EPOCH_LENGTH * 2048) {
-        char error_message[1024];
-        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;
-    }
-
-    return Py_BuildValue("i", ethash_get_cachesize(block_number));
-}
-
-static PyObject *
-get_full_size(PyObject *self, PyObject *args) {
-    unsigned long block_number;
-    if (!PyArg_ParseTuple(args, "k", &block_number))
-        return 0;
-    if (block_number >= ETHASH_EPOCH_LENGTH * 2048) {
-        char error_message[1024];
-        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;
-    }
-
-    return Py_BuildValue("i", ethash_get_datasize(block_number));
-}
-
-
 static PyObject *
 mkcache_bytes(PyObject *self, PyObject *args) {
-    char *seed;
+    unsigned long block_number;
     unsigned long cache_size;
-    int seed_len;
-
-    if (!PyArg_ParseTuple(args, "k" PY_STRING_FORMAT, &cache_size, &seed, &seed_len))
-        return 0;
 
-    if (seed_len != 32) {
-        char error_message[1024];
-        sprintf(error_message, "Seed must be 32 bytes long (was %i)", seed_len);
-
-        PyErr_SetString(PyExc_ValueError, error_message);
+    if (!PyArg_ParseTuple(args, "k", &block_number))
         return 0;
-    }
 
-    ethash_params params;
-    params.cache_size = (size_t) cache_size;
-    ethash_cache cache;
-    cache.mem = malloc(cache_size);
-    ethash_mkcache(&cache, &params, (ethash_h256_t *) seed);
-    PyObject * val = Py_BuildValue(PY_STRING_FORMAT, cache.mem, cache_size);
-    free(cache.mem);
+    ethash_light_t L = ethash_light_new(block_number);
+    PyObject * val = Py_BuildValue(PY_STRING_FORMAT, L->cache, L->cache_size);
+    free(L->cache);
     return val;
 }
 
-
+/*
 static PyObject *
 calc_dataset_bytes(PyObject *self, PyObject *args) {
     char *cache_bytes;
@@ -109,49 +64,38 @@ calc_dataset_bytes(PyObject *self, PyObject *args) {
     PyObject * val = Py_BuildValue(PY_STRING_FORMAT, (char *) mem, full_size);
     free(mem);
     return val;
-}
+}*/
 
 // hashimoto_light(full_size, cache, header, nonce)
 static PyObject *
 hashimoto_light(PyObject *self, PyObject *args) {
     char *cache_bytes;
     char *header;
-    unsigned long full_size;
+    unsigned long block_number;
     unsigned long long nonce;
     int cache_size, header_size;
-    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 % 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)", ETHASH_HASH_BYTES, cache_size);
-        PyErr_SetString(PyExc_ValueError, error_message);
+    if (!PyArg_ParseTuple(args, "k" PY_STRING_FORMAT PY_STRING_FORMAT "K", &block_number, &cache_bytes, &cache_size, &header, &header_size, &nonce))
         return 0;
-    }
     if (header_size != 32) {
         char error_message[1024];
         sprintf(error_message, "Seed must be 32 bytes long (was %i)", header_size);
         PyErr_SetString(PyExc_ValueError, error_message);
         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, &params, (ethash_h256_t *) header, nonce);
+    struct ethash_light *s;
+    s = calloc(sizeof(*s), 1);
+    s->cache = cache_bytes;
+    s->cache_size = cache_size;
+    s->block_number = block_number;
+    struct ethash_h256 *h;
+    h = calloc(sizeof(*h), 1);
+    for (int i = 0; i < 32; i++) h->b[i] = header[i];
+    struct ethash_return_value out = ethash_light_compute(s, *h, 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) {
@@ -236,6 +180,7 @@ mine(PyObject *self, PyObject *args) {
             "result", &out.result, 32,
             "nonce", nonce);
 }
+*/
 
 //get_seedhash(block_number)
 static PyObject *
@@ -256,40 +201,24 @@ get_seedhash(PyObject *self, PyObject *args) {
 
 static PyMethodDef PyethashMethods[] =
         {
-                {"get_cache_size", get_cache_size, METH_VARARGS,
-                        "get_cache_size(block_number)\n\n"
-                                "Get the cache size for a given block number\n"
-                                "\nExample:\n"
-                                ">>> get_cache_size(0)\n"
-                                "1048384"},
-                {"get_full_size", get_full_size, METH_VARARGS,
-                        "get_full_size(block_number)\n\n"
-                                "Get the full size for a given block number\n"
-                                "\nExample:\n"
-                                ">>> get_full_size(0)\n"
-                                "1073739904"
-                },
                 {"get_seedhash", get_seedhash, METH_VARARGS,
                         "get_seedhash(block_number)\n\n"
                                 "Gets the seedhash for a block."},
                 {"mkcache_bytes", mkcache_bytes, METH_VARARGS,
-                        "mkcache_bytes(size, header)\n\n"
-                                "Makes a byte array for the cache for given cache size and seed hash\n"
-                                "\nExample:\n"
-                                ">>> pyethash.mkcache_bytes( 1024, \"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\").encode('hex')"
-                                "\"2da2b506f21070e1143d908e867962486d6b0a02e31d468fd5e3a7143aafa76a14201f63374314e2a6aaf84ad2eb57105dea3378378965a1b3873453bb2b78f9a8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995c259440b89fa3481c2c33171477c305c8e1e421f8d8f6d59585449d0034f3e421808d8da6bbd0b6378f567647cc6c4ba6c434592b198ad444e7284905b7c6adaf70bf43ec2daa7bd5e8951aa609ab472c124cf9eba3d38cff5091dc3f58409edcc386c743c3bd66f92408796ee1e82dd149eaefbf52b00ce33014a6eb3e50625413b072a58bc01da28262f42cbe4f87d4abc2bf287d15618405a1fe4e386fcdafbb171064bd99901d8f81dd6789396ce5e364ac944bbbd75a7827291c70b42d26385910cd53ca535ab29433dd5c5714d26e0dce95514c5ef866329c12e958097e84462197c2b32087849dab33e88b11da61d52f9dbc0b92cc61f742c07dbbf751c49d7678624ee60dfbe62e5e8c47a03d8247643f3d16ad8c8e663953bcda1f59d7e2d4a9bf0768e789432212621967a8f41121ad1df6ae1fa78782530695414c6213942865b2730375019105cae91a4c17a558d4b63059661d9f108362143107babe0b848de412e4da59168cce82bfbff3c99e022dd6ac1e559db991f2e3f7bb910cefd173e65ed00a8d5d416534e2c8416ff23977dbf3eb7180b75c71580d08ce95efeb9b0afe904ea12285a392aff0c8561ff79fca67f694a62b9e52377485c57cc3598d84cac0a9d27960de0cc31ff9bbfe455acaa62c8aa5d2cce96f345da9afe843d258a99c4eaf3650fc62efd81c7b81cd0d534d2d71eeda7a6e315d540b4473c80f8730037dc2ae3e47b986240cfc65ccc565f0d8cde0bc68a57e39a271dda57440b3598bee19f799611d25731a96b5dbbbefdff6f4f656161462633030d62560ea4e9c161cf78fc96a2ca5aaa32453a6c5dea206f766244e8c9d9a8dc61185ce37f1fc804459c5f07434f8ecb34141b8dcae7eae704c950b55556c5f40140c3714b45eddb02637513268778cbf937a33e4e33183685f9deb31ef54e90161e76d969587dd782eaa94e289420e7c2ee908517f5893a26fdb5873d68f92d118d4bcf98d7a4916794d6ab290045e30f9ea00ca547c584b8482b0331ba1539a0f2714fddc3a0b06b0cfbb6a607b8339c39bcfd6640b1f653e9d70ef6c985b\""},
-                {"calc_dataset_bytes", calc_dataset_bytes, METH_VARARGS,
+                        "mkcache_bytes(block_number)\n\n"
+                                "Makes a byte array for the cache for given block number\n"},
+                /*{"calc_dataset_bytes", calc_dataset_bytes, METH_VARARGS,
                         "calc_dataset_bytes(full_size, cache_bytes)\n\n"
-                                "Makes a byte array for the dataset for a given size given cache bytes"},
+                                "Makes a byte array for the dataset for a given size given cache bytes"},*/
                 {"hashimoto_light", hashimoto_light, METH_VARARGS,
-                        "hashimoto_light(full_size, cache_bytes, header, nonce)\n\n"
+                        "hashimoto_light(block_number, cache_bytes, header, nonce)\n\n"
                                 "Runs the hashimoto hashing function just using cache bytes. Takes an int (full_size), byte array (cache_bytes), another byte array (header), and an int (nonce). Returns an object containing the mix digest, and hash result."},
-                {"hashimoto_full", hashimoto_full, METH_VARARGS,
+                /*{"hashimoto_full", hashimoto_full, METH_VARARGS,
                         "hashimoto_full(dataset_bytes, header, nonce)\n\n"
                                 "Runs the hashimoto hashing function using the dataset bytes. Useful for testing. Returns an object containing the mix digest (byte array), and hash result (another byte array)."},
                 {"mine", mine, METH_VARARGS,
                         "mine(dataset_bytes, header, difficulty_bytes)\n\n"
-                                "Mine for an adequate header. Returns an object containing the mix digest (byte array), hash result (another byte array) and nonce (an int)."},
+                                "Mine for an adequate header. Returns an object containing the mix digest (byte array), hash result (another byte array) and nonce (an int)."},*/
                 {NULL, NULL, 0, NULL}
         };
 
-- 
cgit v1.2.3