|
|
@ -142,13 +142,20 @@ class SPV(NetworkJobOnDefaultServer): |
|
|
|
try: |
|
|
|
h = hash_decode(tx_hash) |
|
|
|
merkle_branch_bytes = [hash_decode(item) for item in merkle_branch] |
|
|
|
int(leaf_pos_in_tree) # raise if invalid |
|
|
|
leaf_pos_in_tree = int(leaf_pos_in_tree) # raise if invalid |
|
|
|
except Exception as e: |
|
|
|
raise MerkleVerificationFailure(e) |
|
|
|
|
|
|
|
for i, item in enumerate(merkle_branch_bytes): |
|
|
|
h = sha256d(item + h) if ((leaf_pos_in_tree >> i) & 1) else sha256d(h + item) |
|
|
|
if leaf_pos_in_tree < 0: |
|
|
|
raise MerkleVerificationFailure('leaf_pos_in_tree must be non-negative') |
|
|
|
index = leaf_pos_in_tree |
|
|
|
for item in merkle_branch_bytes: |
|
|
|
if len(item) != 32: |
|
|
|
raise MerkleVerificationFailure('all merkle branch items have to 32 bytes long') |
|
|
|
h = sha256d(item + h) if (index & 1) else sha256d(h + item) |
|
|
|
index >>= 1 |
|
|
|
cls._raise_if_valid_tx(bh2u(h)) |
|
|
|
if index != 0: |
|
|
|
raise MerkleVerificationFailure(f'leaf_pos_in_tree too large for branch') |
|
|
|
return hash_encode(h) |
|
|
|
|
|
|
|
@classmethod |
|
|
@ -192,6 +199,8 @@ def verify_tx_is_in_block(tx_hash: str, merkle_branch: Sequence[str], |
|
|
|
if not block_header: |
|
|
|
raise MissingBlockHeader("merkle verification failed for {} (missing header {})" |
|
|
|
.format(tx_hash, block_height)) |
|
|
|
if len(merkle_branch) > 30: |
|
|
|
raise MerkleVerificationFailure(f"merkle branch too long: {len(merkle_branch)}") |
|
|
|
calc_merkle_root = SPV.hash_merkle_root(merkle_branch, tx_hash, leaf_pos_in_tree) |
|
|
|
if block_header.get('merkle_root') != calc_merkle_root: |
|
|
|
raise MerkleRootMismatch("merkle verification failed for {} ({} != {})".format( |
|
|
|