research/mining/hashimoto.py

129 lines
3.2 KiB
Python
Raw Normal View History

2014-10-24 07:56:42 +00:00
try:
shathree = __import__('sha3')
except:
shathree = __import__('python_sha3')
import random
import time
def sha3(x):
return decode_int(shathree.sha3_256(x).digest()) #
def decode_int(s):
o = 0
for i in range(len(s)):
o = o * 256 + ord(s[i])
return o
def encode_int(x):
o = ''
for _ in range(32):
o = chr(x % 256) + o
x //= 256
return o
P = 2**256 - 4294968273
def produce_dag(params, seed):
o = [sha3(seed)]
init = o[0]
picker = 1
for i in range(1, params["n"]):
x = 0
picker = (picker * init) % P
curpicker = picker
for j in range(params["k"]):
x |= o[curpicker % i]
curpicker >>= 10
o.append((x * x) % P) # use any "hash function" here
return o
def quick_calc(params, seed, pos):
init = sha3(seed)
known = {0: init}
def calc(p):
if p not in known:
picker = pow(init, p, P)
x = 0
for j in range(params["k"]):
x |= calc(picker % p)
picker >>= 10
known[p] = (x * x) % P
return known[p]
o = calc(pos)
print 'Calculated pos %d with %d accesses' % (pos, len(known))
return o
def hashimoto(daggerset, params, header, nonce):
rand = sha3(header+encode_int(nonce))
mix = 0
for i in range(40):
shifted_A = rand >> i
dag = daggerset[shifted_A % params["numdags"]]
mix ^= dag[(shifted_A // params["numdags"]) % params["n"]]
return mix ^ rand
def get_daggerset(params, block):
if block.number == 0:
return [produce_dag(params, i) for i in range(params["numdags"])]
elif block.number % params["epochtime"]:
return get_daggerset(block.parent)
else:
o = get_daggerset(block.parent)
o[sha3(block.parent.nonce) % params["numdags"]] = \
produce_dag(params, sha3(block.parent.nonce))
return o
def mine(daggerset, params, header):
nonce = random.randrange(2**50)
orignonce = nonce
origtime = time.time()
while 1:
h = hashimoto(daggerset, params, header, nonce)
if h <= 2**256 / params["diff"]:
noncediff = nonce - orignonce
timediff = time.time() - origtime
print 'Found nonce: %d, tested %d nonces in %f seconds (%f per sec)' % \
(nonce, noncediff, timediff, noncediff / timediff)
return nonce
nonce += 1
def verify(daggerset, params, header, nonce):
return hashimoto(daggerset, params, header, nonce) \
<= 2**256 / params["diff"]
def light_hashimoto(seedset, params, header, nonce):
rand = sha3(header+encode_int(nonce))
mix = 0
for i in range(40):
shifted_A = rand >> i
seed = seedset[shifted_A % params["numdags"]]
# can further optimize with cross-round memoization
mix ^= quick_calc(params, seed,
(shifted_A // params["numdags"]) % params["n"])
return mix ^ rand
def light_verify(seedset, params, header, nonce):
return light_hashimoto(seedset, params, header, nonce) \
<= 2**256 / params["diff"]
params = {
"numdags": 40,
"n": 250000,
"diff": 2**14,
"epochtime": 100,
"k": 3
}