def test_compute_merkle_tree_duplicated(): hash_0 = keccak(b'x') hash_1 = keccak(b'y') with pytest.raises(ValueError): compute_merkle_tree([hash_0, hash_0]) with pytest.raises(ValueError): compute_merkle_tree([hash_0, hash_1, hash_0])
def test_get_merkle_root_three(): hash_0 = b'a' * 32 hash_1 = b'b' * 32 hash_2 = b'c' * 32 leaves = [hash_0, hash_1, hash_2] merkle_tree = compute_merkle_tree(leaves) root = get_merkle_root(merkle_tree) hash_01 = (b'me\xef\x9c\xa9=5\x16\xa4\xd3\x8a\xb7\xd9\x89\xc2\xb5\x00' b'\xe2\xfc\x89\xcc\xdc\xf8x\xf9\xc4m\xaa\xf6\xad\r[') assert keccak(hash_0 + hash_1) == hash_01 calculated_root = keccak(hash_2 + hash_01) assert root == calculated_root proof0 = compute_merkle_proof(merkle_tree, hash_0) proof1 = compute_merkle_proof(merkle_tree, hash_1) proof2 = compute_merkle_proof(merkle_tree, hash_2) assert proof0 == [hash_1, hash_2] assert root == calculated_root assert validate_merkle_proof(proof0, root, hash_0) assert proof1 == [hash_0, hash_2] assert root == calculated_root assert validate_merkle_proof(proof1, root, hash_1) # with an odd number of values, the last value wont appear by itself in the # proof since it isn't hashed with another value assert proof2 == [keccak(hash_0 + hash_1)] assert root == calculated_root assert validate_merkle_proof(proof2, root, hash_2)
def test_get_merkle_root_many(tree_up_to=20): for number_of_leaves in range(1, tree_up_to): # skipping the empty tree leaves = [ keccak(str(value).encode()) for value in range(number_of_leaves) ] merkle_tree = compute_merkle_tree(leaves) root = get_merkle_root(merkle_tree) for value in leaves: proof = compute_merkle_proof(merkle_tree, value) assert validate_merkle_proof(proof, root, value) reversed_tree = compute_merkle_tree(reversed(leaves)) assert root == get_merkle_root(reversed_tree)
def test_get_merkle_root_one(): hash_0 = b'a' * 32 leaves = [hash_0] merkle_tree = compute_merkle_tree(leaves) root = get_merkle_root(merkle_tree) assert root == hash_0 proof = compute_merkle_proof(merkle_tree, hash_0) assert proof == [] assert root == hash_0 assert validate_merkle_proof(proof, root, hash_0) is True
def test_get_merkle_root_two(): hash_0 = b'a' * 32 hash_1 = b'b' * 32 leaves = [hash_0, hash_1] merkle_tree = compute_merkle_tree(leaves) root = get_merkle_root(merkle_tree) assert root == keccak(hash_0 + hash_1) proof0 = compute_merkle_proof(merkle_tree, hash_0) proof1 = compute_merkle_proof(merkle_tree, hash_1) assert proof0 == [hash_1] assert root == keccak(hash_0 + hash_1) assert validate_merkle_proof(proof0, root, hash_0) assert proof1 == [hash_0] assert root == keccak(hash_0 + hash_1) assert validate_merkle_proof(proof1, root, hash_1)
def update_balance(self, balance_proof: BalanceProof, locks: List[Lock]): """ Update the channel balance with the new balance proof. This needs to check that the balance proof is valid. Called by the public interface. """ participant1, participant2 = self.channel_id_to_addresses( balance_proof.channel_id) if is_same_address(participant1, balance_proof.sender): receiver = participant2 elif is_same_address(participant2, balance_proof.sender): receiver = participant1 else: raise ValueError( 'Balance proof signature does not match any of the participants.' ) view1: ChannelView = self.G[balance_proof.sender][receiver]['view'] view2: ChannelView = self.G[receiver][balance_proof.sender]['view'] if view1.transferred_amount >= balance_proof.transferred_amount: # FIXME: use nonce instead for this check? raise ValueError('Balance proof is outdated.') reconstructed_merkle_tree = compute_merkle_tree(lock.compute_hash() for lock in locks) reconstructed_merkle_root = get_merkle_root(reconstructed_merkle_tree) if not reconstructed_merkle_root == balance_proof.locksroot: raise ValueError( 'Supplied locks do not match the provided locksroot') view1.update_capacity( transferred_amount=balance_proof.transferred_amount, locked_amount=sum(lock.amount_locked for lock in locks)) view2.update_capacity(received_amount=balance_proof.transferred_amount)
def test_compute_merkle_tree_single_entry(): hash_0 = keccak(b'x') merkle_tree = compute_merkle_tree([hash_0]) assert merkle_tree.layers[-1][0] == hash_0 assert get_merkle_root(merkle_tree) == hash_0
def test_compute_merkle_tree_no_entry(): merkle_tree = compute_merkle_tree([]) assert is_empty_merkle_root(merkle_tree.layers[-1][0]) assert is_empty_merkle_root(get_merkle_root(merkle_tree))
def test_compute_merkle_tree_invalid_length(): with pytest.raises(ValueError): compute_merkle_tree([b'not32bytes', b'neither']) with pytest.raises(ValueError): compute_merkle_tree([b''])