From 59ff88444aea9a8ff92e7f30ccba4e0de0894c76 Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Wed, 13 May 2015 17:39:31 +0200 Subject: [PATCH 1/4] Improve ethash hash rate update * Add hash rate tracking for each mining thread * Do not use pow.GetHashrate but track it in each agent instead --- core/chain_makers.go | 2 +- miner/agent.go | 16 +++++++++------- miner/miner.go | 3 ++- miner/remote_agent.go | 2 +- miner/worker.go | 6 +++--- pow/dagger/dagger.go | 2 +- pow/ezp/pow.go | 2 +- pow/pow.go | 2 +- xeth/xeth.go | 2 +- 9 files changed, 20 insertions(+), 17 deletions(-) diff --git a/core/chain_makers.go b/core/chain_makers.go index 5cd7ab4abb..385786bc17 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -14,7 +14,7 @@ import ( // So we can generate blocks easily type FakePow struct{} -func (f FakePow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte) { +func (f FakePow) Search(block pow.Block, stop <-chan struct{}, prevHashRate *uint64) (uint64, []byte) { return 0, nil } func (f FakePow) Verify(block pow.Block) bool { return true } diff --git a/miner/agent.go b/miner/agent.go index 939f63fef0..3aaceacfc0 100644 --- a/miner/agent.go +++ b/miner/agent.go @@ -17,14 +17,16 @@ type CpuAgent struct { quitCurrentOp chan struct{} returnCh chan<- *types.Block - index int - pow pow.PoW + index int + prevHashRate *uint64 + pow pow.PoW } func NewCpuAgent(index int, pow pow.PoW) *CpuAgent { miner := &CpuAgent{ - pow: pow, - index: index, + pow: pow, + index: index, + prevHashRate: new(uint64), } return miner @@ -85,7 +87,7 @@ func (self *CpuAgent) mine(block *types.Block) { self.chMu.Unlock() // Mine - nonce, mixDigest := self.pow.Search(block, self.quitCurrentOp) + nonce, mixDigest := self.pow.Search(block, self.quitCurrentOp, self.prevHashRate) if nonce != 0 { block.SetNonce(nonce) block.Header().MixDigest = common.BytesToHash(mixDigest) @@ -95,6 +97,6 @@ func (self *CpuAgent) mine(block *types.Block) { } } -func (self *CpuAgent) GetHashRate() int64 { - return self.pow.GetHashrate() +func (self *CpuAgent) GetHashRate() uint64 { + return *self.prevHashRate } diff --git a/miner/miner.go b/miner/miner.go index 09342e2501..c1bfa86ca7 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -54,6 +54,7 @@ func (self *Miner) Start(coinbase common.Address, threads int) { self.worker.coinbase = coinbase self.worker.start() self.worker.commitNewWork() + } func (self *Miner) Stop() { @@ -69,7 +70,7 @@ func (self *Miner) Register(agent Agent) { self.worker.register(agent) } -func (self *Miner) HashRate() int64 { +func (self *Miner) HashRate() uint64 { return self.worker.HashRate() } diff --git a/miner/remote_agent.go b/miner/remote_agent.go index 80cc9053e1..486bc55a72 100644 --- a/miner/remote_agent.go +++ b/miner/remote_agent.go @@ -42,7 +42,7 @@ func (a *RemoteAgent) Stop() { close(a.workCh) } -func (a *RemoteAgent) GetHashRate() int64 { return 0 } +func (a *RemoteAgent) GetHashRate() uint64 { return 0 } func (a *RemoteAgent) run() { out: diff --git a/miner/worker.go b/miner/worker.go index f737be507e..6670ef2074 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -35,7 +35,7 @@ type Agent interface { SetReturnCh(chan<- *types.Block) Stop() Start() - GetHashRate() int64 + GetHashRate() uint64 } // environment is the workers current environment and holds @@ -453,8 +453,8 @@ func (self *worker) commitTransaction(tx *types.Transaction) error { return nil } -func (self *worker) HashRate() int64 { - var tot int64 +func (self *worker) HashRate() uint64 { + var tot uint64 for _, agent := range self.agents { tot += agent.GetHashRate() } diff --git a/pow/dagger/dagger.go b/pow/dagger/dagger.go index b941c0eeb5..c5834cae2e 100644 --- a/pow/dagger/dagger.go +++ b/pow/dagger/dagger.go @@ -44,7 +44,7 @@ func (dag *Dagger) Find(obj *big.Int, resChan chan int64) { resChan <- 0 } -func (dag *Dagger) Search(hash, diff *big.Int) (uint64, []byte) { +func (dag *Dagger) Search(hash, diff *big.Int, prevHashRate *uint64) (uint64, []byte) { // TODO fix multi threading. Somehow it results in the wrong nonce amountOfRoutines := 1 diff --git a/pow/ezp/pow.go b/pow/ezp/pow.go index c838dd5ecc..8f1ebc219b 100644 --- a/pow/ezp/pow.go +++ b/pow/ezp/pow.go @@ -32,7 +32,7 @@ func (pow *EasyPow) Turbo(on bool) { pow.turbo = on } -func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte) { +func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}, prevHashRate *uint64) (uint64, []byte) { r := rand.New(rand.NewSource(time.Now().UnixNano())) hash := block.HashNoNonce() diff := block.Difficulty() diff --git a/pow/pow.go b/pow/pow.go index 73984a4aee..e9217adb9d 100644 --- a/pow/pow.go +++ b/pow/pow.go @@ -1,7 +1,7 @@ package pow type PoW interface { - Search(block Block, stop <-chan struct{}) (uint64, []byte) + Search(block Block, stop <-chan struct{}, prevHashRate *uint64) (uint64, []byte) Verify(block Block) bool GetHashrate() int64 Turbo(bool) diff --git a/xeth/xeth.go b/xeth/xeth.go index 0fe68d1753..163ec25b6a 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -405,7 +405,7 @@ func (self *XEth) IsMining() bool { return self.backend.IsMining() } -func (self *XEth) HashRate() int64 { +func (self *XEth) HashRate() uint64 { return self.backend.Miner().HashRate() } From 7a25ecfa1f144d5295485da5124dbbe7452f0181 Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Wed, 13 May 2015 18:09:30 +0200 Subject: [PATCH 2/4] Update ethash godeps --- Godeps/Godeps.json | 4 +- .../src/github.com/ethereum/ethash/ethash.go | 13 +- .../github.com/ethereum/ethash/ethash_test.go | 6 +- .../ethereum/ethash/src/python/core.c | 127 ++++-------------- 4 files changed, 41 insertions(+), 109 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index d64fd157a6..22da157861 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -17,8 +17,8 @@ }, { "ImportPath": "github.com/ethereum/ethash", - "Comment": "v23.1-204-g0401fdf", - "Rev": "0401fdf56a3bc8679f9560e542c3d1cf83020efe" + "Comment": "v23.1-206-gec7e3ba", + "Rev": "ec7e3ba99c7236902722b64aa89bc752fc67ba72" }, { "ImportPath": "github.com/howeyc/fsnotify", diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go index 5b94711c4b..6c4d33095b 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go @@ -256,7 +256,7 @@ func (pow *Full) getDAG(blockNum uint64) (d *dag) { return d } -func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mixDigest []byte) { +func (pow *Full) Search(block pow.Block, stop <-chan struct{}, prevHashRate *uint64) (nonce uint64, mixDigest []byte) { dag := pow.getDAG(block.NumberU64()) r := rand.New(rand.NewSource(time.Now().UnixNano())) @@ -277,9 +277,11 @@ func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mi default: i++ - elapsed := time.Now().UnixNano() - start - hashes := ((float64(1e9) / float64(elapsed)) * float64(i-starti)) / 1000 - pow.hashRate = int64(hashes) + if (i % (1 << 14)) == 0 { // we don't have to update hash rate on every nonce + elapsed := time.Now().UnixNano() - start + hashes := (float64(1e9) / float64(elapsed)) * float64(i-starti) + *prevHashRate = uint64(hashes) + } ret := C.ethash_full_compute(dag.ptr, hash, C.uint64_t(nonce)) result := h256ToHash(ret.result).Big() @@ -298,9 +300,10 @@ func (pow *Full) Search(block pow.Block, stop <-chan struct{}) (nonce uint64, mi } } +// TODO: remove? for ethash we do not call this anymore func (pow *Full) GetHashrate() int64 { // TODO: this needs to use an atomic operation. - return pow.hashRate + return 0 } func (pow *Full) Turbo(on bool) { diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go index 42be77b94b..acec8ded4e 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go @@ -73,7 +73,7 @@ func TestEthashConcurrentVerify(t *testing.T) { defer os.RemoveAll(eth.Full.Dir) block := &testBlock{difficulty: big.NewInt(10)} - nonce, _ := eth.Search(block, nil) + nonce, _ := eth.Search(block, nil, new(uint64)) block.nonce = nonce // Verify the block concurrently to check for data races. @@ -110,7 +110,7 @@ func TestEthashConcurrentSearch(t *testing.T) { wg.Add(nsearch) for i := 0; i < nsearch; i++ { go func() { - nonce, _ := eth.Search(block, stop) + nonce, _ := eth.Search(block, stop, new(uint64)) select { case found <- nonce: case <-stop: @@ -140,7 +140,7 @@ func TestEthashSearchAcrossEpoch(t *testing.T) { for i := epochLength - 40; i < epochLength+40; i++ { block := &testBlock{number: i, difficulty: big.NewInt(90)} rand.Read(block.hashNoNonce[:]) - nonce, _ := eth.Search(block, nil) + nonce, _ := eth.Search(block, nil, new(uint64)) block.nonce = nonce if !eth.Verify(block) { t.Fatalf("Block could not be verified") 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 d77b9761be..c66e03c549 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 #include #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)) + if (!PyArg_ParseTuple(args, "k", &block_number)) 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); - return 0; - } - - ethash_params params; - params.cache_size = (size_t) cache_size; - ethash_cache cache; - cache.mem = malloc(cache_size); - ethash_mkcache(&cache, ¶ms, (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)) + 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 (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); - 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, ¶ms, (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} }; From 773fcd801c782645996693e0924319f6d6da0163 Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Wed, 13 May 2015 21:59:46 +0200 Subject: [PATCH 3/4] Use atomic load for CPU agent's hash rate --- miner/agent.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miner/agent.go b/miner/agent.go index 3aaceacfc0..e2838d20e1 100644 --- a/miner/agent.go +++ b/miner/agent.go @@ -2,6 +2,7 @@ package miner import ( "sync" + "sync/atomic" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -98,5 +99,5 @@ func (self *CpuAgent) mine(block *types.Block) { } func (self *CpuAgent) GetHashRate() uint64 { - return *self.prevHashRate + return atomic.LoadUint64(self.prevHashRate) } From 960a2b2d82ae2f22fb746a06624433d79aa013f0 Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Wed, 13 May 2015 22:05:01 +0200 Subject: [PATCH 4/4] Update ethash godep --- Godeps/Godeps.json | 4 ++-- Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 22da157861..9a4a5d3013 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -17,8 +17,8 @@ }, { "ImportPath": "github.com/ethereum/ethash", - "Comment": "v23.1-206-gec7e3ba", - "Rev": "ec7e3ba99c7236902722b64aa89bc752fc67ba72" + "Comment": "v23.1-207-gac7a2d1", + "Rev": "ac7a2d1d57e7fd655636496b6df3c517d18e8734" }, { "ImportPath": "github.com/howeyc/fsnotify", diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go index 6c4d33095b..2d0c024c9d 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" @@ -280,7 +281,7 @@ func (pow *Full) Search(block pow.Block, stop <-chan struct{}, prevHashRate *uin if (i % (1 << 14)) == 0 { // we don't have to update hash rate on every nonce elapsed := time.Now().UnixNano() - start hashes := (float64(1e9) / float64(elapsed)) * float64(i-starti) - *prevHashRate = uint64(hashes) + atomic.StoreUint64(prevHashRate, uint64(hashes)) } ret := C.ethash_full_compute(dag.ptr, hash, C.uint64_t(nonce))