diff --git a/electrum/verifier.py b/electrum/verifier.py index 9fef9fc98..d73dcb96d 100644 --- a/electrum/verifier.py +++ b/electrum/verifier.py @@ -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(