('lock_time', StructType('<I')),
])
+merkle_branch_type = ListType(HashType())
+
merkle_tx_type = ComposedType([
('tx', tx_type),
('block_hash', HashType()),
- ('merkle_branch', ListType(HashType())),
+ ('merkle_branch', merkle_branch_type),
('index', StructType('<i')),
])
aux_pow_type = ComposedType([
('merkle_tx', merkle_tx_type),
- ('merkle_branch', ListType(HashType())),
+ ('merkle_branch', merkle_branch_type),
('index', StructType('<i')),
('parent_block_header', block_header_type),
])
for left, right in zip(hash_list[::2], hash_list[1::2] + [None])]
return hash_list[0]
+def calculate_merkle_branch(txs, index):
+ # XXX optimize this
+
+ hash_list = [(tx_type.hash256(tx), i == index, []) for i, tx in enumerate(txs)]
+
+ while len(hash_list) > 1:
+ hash_list = [
+ (
+ merkle_record_type.hash256(dict(left=left, right=right)),
+ left_f or right_f,
+ (left_l if left_f else right_l) + [dict(side=1, hash=right) if left_f else dict(side=0, hash=left)],
+ )
+ for (left, left_f, left_l), (right, right_f, right_l) in
+ zip(hash_list[::2], hash_list[1::2] + [hash_list[::2][-1]])
+ ]
+
+ res = [x['hash'] for x in hash_list[0][2]]
+
+ assert hash_list[0][1]
+ assert check_merkle_branch(txs[index], index, res) == hash_list[0][0]
+ assert index == sum(k*2**i for i, k in enumerate([1-x['side'] for x in hash_list[0][2]]))
+
+ return res
+
+def check_merkle_branch(tx, index, merkle_branch):
+ return reduce(lambda c, (i, h): merkle_record_type.hash256(
+ dict(left=h, right=c) if 2**i & index else
+ dict(left=c, right=h)
+ ), enumerate(merkle_branch), tx_type.hash256(tx))
+
def target_to_average_attempts(target):
return 2**256//(target + 1)
new_share1a_type = bitcoin_data.ComposedType([
('header', bitcoin_data.block_header_type),
('share_info', new_share_info_type),
- ('merkle_branch', merkle_branch_type),
+ ('merkle_branch', bitcoin_data.merkle_branch_type),
])
new_share1b_type = bitcoin_data.ComposedType([
if merkle_branch is None and other_txs is None:
raise ValueError('need either merkle_branch or other_txs')
if other_txs is not None:
- new_merkle_branch = calculate_merkle_branch([dict(version=0, tx_ins=[], tx_outs=[], lock_time=0)] + other_txs, 0)
+ new_merkle_branch = bitcoin_data.calculate_merkle_branch([dict(version=0, tx_ins=[], tx_outs=[], lock_time=0)] + other_txs, 0)
if merkle_branch is not None:
if merke_branch != new_merkle_branch:
raise ValueError('invalid merkle_branch and other_txs')
if len(gentx['tx_ins'][0]['script']) > 100:
raise ValueError('''coinbase too large! %i bytes''' % (len(gentx['tx_ins'][0]['script']),))
- if check_merkle_branch(gentx, self.merkle_branch) != self.header['merkle_root']:
+ if bitcoin_data.check_merkle_branch(gentx, 0, self.merkle_branch) != self.header['merkle_root']:
raise ValueError('''gentx doesn't match header via merkle_branch''')
if self.other_txs is not None: