tverifier: further sanity checks for SPV verification. - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit 9b82321fc083f3fb4728d9f3785a04861a617011
 (DIR) parent 5bf854edcb15906fd6eb6bb707eb5a89f349b73d
 (HTM) Author: SomberNight <somber.night@protonmail.com>
       Date:   Fri,  5 Jul 2019 18:39:40 +0200
       
       verifier: further sanity checks for SPV verification.
       
       Thanks to @JeremyRand
       
       Diffstat:
         M electrum/verifier.py                |      17 +++++++++++++----
       
       1 file changed, 13 insertions(+), 4 deletions(-)
       ---
 (DIR) diff --git a/electrum/verifier.py b/electrum/verifier.py
       t@@ -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
       t@@ -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(