research/mining/arpow_miner.py

105 lines
2.7 KiB
Python

from pyethereum import utils
import random
def sha3(x):
return utils.decode_int(utils.zunpad(utils.sha3(x)))
class SeedObj():
def __init__(self, seed):
self.seed = seed
self.a = 3**160
self.c = 7**80
self.n = 2**256 - 4294968273 # secp256k1n, why not
def rand(self, r):
self.seed = (self.seed * self.a + self.c) % self.n
return self.seed % r
def encode_int(x):
o = ''
for _ in range(8):
o = chr(x % 256) + o
x //= 256
return o
ops = {
"plus": lambda x, y: (x + y) % 2**64,
"times": lambda x, y: (x * y) % 2**64,
"xor": lambda x, y: x ^ y,
"and": lambda x, y: x & y,
"or": lambda x, y: x | y,
"not": lambda x, y: 2**64-1-x,
"nxor": lambda x, y: (2**64-1-x) ^ y,
"rshift": lambda x, y: x >> (y % 64)
}
def gentape(W, H, SEED):
s = SeedObj(SEED)
tape = []
for i in range(H):
op = ops.keys()[s.rand(len(ops))]
r = s.rand(100)
if r < 20 and i > 20:
x1 = tape[-r]["x1"]
else:
x1 = s.rand(W)
x2 = s.rand(W)
tape.append({"op": op, "x1": x1, "x2": x2})
return tape
def runtape(TAPE, SEED, params):
s = SeedObj(SEED)
# Fill up tape inputs
mem = [0] * params["w"]
for i in range(params["w"]):
mem[i] = s.rand(2**64)
# Direction variable (run forwards or backwards)
dir = 1
# Run the tape on the inputs
for i in range(params["h"] // 100):
for j in (range(100) if dir == 1 else range(99, -1, -1)):
t = TAPE[i * 100 + j]
mem[t["x1"]] = ops[t["op"]](mem[t["x1"]], mem[t["x2"]])
# 16% of the time, we flip the order of the next 100 ops;
# this adds in conditional branching
if 2 < mem[t["x1"]] % 37 < 9:
dir *= -1
return sha3(''.join(encode_int(x) for x in mem))
def PoWVerify(header, nonce, params):
tape = gentape(params["w"], params["h"],
sha3(header + encode_int(nonce // params["n"])))
h = runtape(tape, sha3(header + encode_int(nonce)), params)
print h
return h < 2**256 / params["diff"]
def PoWRun(header, params):
# actual randomness, so that miners don't overlap
nonce = random.randrange(2**50) * params["n"]
tape = None
while 1:
print nonce
if nonce % params["n"] == 0:
tape = gentape(params["w"], params["h"],
sha3(header + encode_int(nonce // params["n"])))
h = runtape(tape, sha3(header + encode_int(nonce)), params)
if h < 2**256 / params["diff"]:
return nonce
else:
nonce += 1
params = {
"w": 100,
"h": 15000, # generally, w*log(w) at least
"diff": 2**24, # initial
"n": 1000
}