stratum-mining/lib/merkletree.py
2013-11-20 11:31:07 +00:00

104 lines
3.6 KiB
Python

# Eloipool - Python Bitcoin pool server
# Copyright (C) 2011-2012 Luke Dashjr <luke-jr+eloipool@utopios.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from hashlib import sha256
from util import doublesha
class MerkleTree:
def __init__(self, data, detailed=False):
self.data = data
self.recalculate(detailed)
self._hash_steps = None
def recalculate(self, detailed=False):
L = self.data
steps = []
if detailed:
detail = []
PreL = []
StartL = 0
else:
detail = None
PreL = [None]
StartL = 2
Ll = len(L)
if detailed or Ll > 1:
while True:
if detailed:
detail += L
if Ll == 1:
break
steps.append(L[1])
if Ll % 2:
L += [L[-1]]
L = PreL + [doublesha(L[i] + L[i + 1]) for i in range(StartL, Ll, 2)]
Ll = len(L)
self._steps = steps
self.detail = detail
def hash_steps(self):
if self._hash_steps == None:
self._hash_steps = doublesha(''.join(self._steps))
return self._hash_steps
def withFirst(self, f):
steps = self._steps
for s in steps:
f = doublesha(f + s)
return f
def merkleRoot(self):
return self.withFirst(self.data[0])
# MerkleTree tests
def _test():
import binascii
import time
mt = MerkleTree([None] + [binascii.unhexlify(a) for a in [
'999d2c8bb6bda0bf784d9ebeb631d711dbbbfe1bc006ea13d6ad0d6a2649a971',
'3f92594d5a3d7b4df29d7dd7c46a0dac39a96e751ba0fc9bab5435ea5e22a19d',
'a5633f03855f541d8e60a6340fc491d49709dc821f3acb571956a856637adcb6',
'28d97c850eaf917a4c76c02474b05b70a197eaefb468d21c22ed110afe8ec9e0',
]])
assert(
b'82293f182d5db07d08acf334a5a907012bbb9990851557ac0ec028116081bd5a' ==
binascii.b2a_hex(mt.withFirst(binascii.unhexlify('d43b669fb42cfa84695b844c0402d410213faa4f3e66cb7248f688ff19d5e5f7')))
)
print '82293f182d5db07d08acf334a5a907012bbb9990851557ac0ec028116081bd5a'
txes = [binascii.unhexlify(a) for a in [
'd43b669fb42cfa84695b844c0402d410213faa4f3e66cb7248f688ff19d5e5f7',
'999d2c8bb6bda0bf784d9ebeb631d711dbbbfe1bc006ea13d6ad0d6a2649a971',
'3f92594d5a3d7b4df29d7dd7c46a0dac39a96e751ba0fc9bab5435ea5e22a19d',
'a5633f03855f541d8e60a6340fc491d49709dc821f3acb571956a856637adcb6',
'28d97c850eaf917a4c76c02474b05b70a197eaefb468d21c22ed110afe8ec9e0',
]]
s = time.time()
mt = MerkleTree(txes)
for x in range(100):
y = int('d43b669fb42cfa84695b844c0402d410213faa4f3e66cb7248f688ff19d5e5f7', 16)
#y += x
coinbasehash = binascii.unhexlify("%x" % y)
x = binascii.b2a_hex(mt.withFirst(coinbasehash))
print x
print time.time() - s
if __name__ == '__main__':
_test()