示例#1
0
def test_three():
    def sort_join(first, second):
        return ''.join(sorted([first, second]))

    hash_0 = 'a' * 32
    hash_1 = 'b' * 32
    hash_2 = 'c' * 32

    leaves = [hash_0, hash_1, hash_2]
    tree = Merkletree(leaves)
    merkle_root = tree.merkleroot

    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)

    merkle_proof0 = tree.make_proof(hash_0)
    assert merkle_proof0 == [hash_1, hash_2]
    assert merkle_root == calculated_root
    assert check_proof(merkle_proof0, merkle_root, hash_0)

    merkle_proof1 = tree.make_proof(hash_1)
    assert merkle_proof1 == [hash_0, hash_2]
    assert merkle_root == calculated_root
    assert check_proof(merkle_proof1, merkle_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
    merkle_proof2 = tree.make_proof(hash_2)
    assert merkle_proof2 == [keccak(hash_0 + hash_1)]
    assert merkle_root == calculated_root
    assert check_proof(merkle_proof2, merkle_root, hash_2)
def test_merkle_proof_missing_byte(tree, tester_state,
                                   tester_nettingchannel_library_address):
    """ computeMerkleRoot must fail if the proof is missing a byte. """

    auxiliary = deploy_auxiliary_tester(tester_state,
                                        tester_nettingchannel_library_address)

    hashes = [sha3(element) for element in tree]
    merkle_tree = Merkletree(hashes)

    element = hashes[-1]
    merkle_proof = merkle_tree.make_proof(element)

    # for each element of the proof, remove a byte from the start and the end and test it
    for element_to_tamper in range(len(merkle_proof)):
        tampered_proof = list(merkle_proof)
        tampered_proof[element_to_tamper] = tampered_proof[
            element_to_tamper][:-1]

        with pytest.raises(TransactionFailed):
            auxiliary.computeMerkleRoot(
                element,
                ''.join(tampered_proof),
            )

        tampered_proof = list(merkle_proof)
        tampered_proof[element_to_tamper] = tampered_proof[element_to_tamper][
            1:]

        with pytest.raises(TransactionFailed):
            auxiliary.computeMerkleRoot(
                element,
                ''.join(tampered_proof),
            )
示例#3
0
def test_withdraw_tampered_lock_amount(tree, tester_channels, tester_state,
                                       tester_token, settle_timeout):
    """ withdraw must fail if the lock amonut is tampered. """
    pkey0, pkey1, nettingchannel, channel0, _ = tester_channels[0]

    current_block = tester_state.block.number
    expiration = current_block + settle_timeout - 1
    locks = [
        make_lock(
            hashlock=hashlock,
            expiration=expiration,
        ) for hashlock in tree
    ]

    merkle_tree = Merkletree(sha3(lock.as_bytes) for lock in locks)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2**32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        channel=channel0.channel_address,
        locksroot=merkle_tree.merkleroot,
        token=tester_token.address,
        recipient=privatekey_to_address(pkey1))

    address = privatekey_to_address(pkey0)
    sign_key = PrivateKey(pkey0)
    direct_transfer.sign(sign_key, address)

    direct_transfer_hash = sha3(direct_transfer.packed().data[:-65])
    nettingchannel.close(
        direct_transfer.nonce,
        direct_transfer.transferred_amount,
        direct_transfer.locksroot,
        direct_transfer_hash,
        direct_transfer.signature,
        sender=pkey1,
    )

    for lock in locks:
        secret = HASHLOCKS_SECRESTS[lock.hashlock]

        lock_encoded = lock.as_bytes
        merkle_proof = merkle_tree.make_proof(sha3(lock_encoded))

        tampered_lock = make_lock(
            amount=lock.amount * 100,
            hashlock=lock.hashlock,
            expiration=lock.expiration,
        )
        tampered_lock_encoded = sha3(tampered_lock.as_bytes)

        with pytest.raises(TransactionFailed):
            nettingchannel.withdraw(
                tampered_lock_encoded,
                ''.join(merkle_proof),
                secret,
                sender=pkey1,
            )
示例#4
0
def test_withdraw_fails_with_partial_merkle_proof(tree, tester_channels,
                                                  tester_state,
                                                  settle_timeout):
    """ withdraw must fail if informed proof is not complete. """
    pkey0, pkey1, nettingchannel, channel0, _ = tester_channels[0]

    current_block = tester_state.block.number
    expiration = current_block + settle_timeout - 1
    locks = [
        make_lock(
            hashlock=hashlock,
            expiration=expiration,
        ) for hashlock in tree
    ]

    merkle_tree = Merkletree(sha3(lock.as_bytes) for lock in locks)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2**32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        channel=channel0.channel_address,
        locksroot=merkle_tree.merkleroot,
        recipient=privatekey_to_address(pkey1))

    address = privatekey_to_address(pkey0)
    sign_key = PrivateKey(pkey0)
    direct_transfer.sign(sign_key, address)

    direct_transfer_hash = sha3(direct_transfer.packed().data[:-65])
    nettingchannel.close(
        direct_transfer.nonce,
        direct_transfer.transferred_amount,
        direct_transfer.locksroot,
        direct_transfer_hash,
        direct_transfer.signature,
        sender=pkey1,
    )

    for lock in locks:
        secret = HASHLOCKS_SECRESTS[lock.hashlock]
        lock_encoded = lock.as_bytes
        merkle_proof = merkle_tree.make_proof(sha3(lock_encoded))

        # withdraw must fail regardless of which part of the proof is removed
        for hash_ in merkle_proof:
            tampered_proof = list(merkle_proof)
            tampered_proof.remove(hash_)

            with pytest.raises(TransactionFailed):
                nettingchannel.withdraw(
                    lock_encoded,
                    ''.join(tampered_proof),
                    secret,
                    sender=pkey1,
                )
示例#5
0
def test_two():
    hash_0 = 'a' * 32
    hash_1 = 'b' * 32

    leaves = [hash_0, hash_1]

    tree = Merkletree(leaves)
    merkle_root = tree.merkleroot
    merkle_proof0 = tree.make_proof(hash_0)

    assert merkle_proof0 == [hash_1]
    assert merkle_root == keccak(hash_0 + hash_1)
    assert check_proof(merkle_proof0, merkle_root, hash_0)

    merkle_proof1 = tree.make_proof(hash_1)

    assert merkle_proof1 == [hash_0]
    assert merkle_root == keccak(hash_0 + hash_1)
    assert check_proof(merkle_proof1, merkle_root, hash_1)
示例#6
0
def test_one():
    hash_0 = 'a' * 32

    leaves = [hash_0]
    tree = Merkletree(leaves)
    merkle_root = tree.merkleroot
    merkle_proof = tree.make_proof(hash_0)

    assert merkle_proof == []
    assert merkle_root == hash_0
    assert check_proof(merkle_proof, merkle_root, hash_0) is True
示例#7
0
def test_many(tree_up_to=10):
    for number_of_leaves in range(tree_up_to):
        leaves = [sha3(str(value)) for value in range(number_of_leaves)]
        tree = Merkletree(leaves)
        merkleroot = tree.merkleroot

        for value in leaves:
            merkle_proof = tree.make_proof(value)
            assert check_proof(merkle_proof, merkleroot, value)

        assert merkleroot == Merkletree(reversed(leaves)).merkleroot
示例#8
0
def test_withdraw_tampered_merkle_proof(tree, tester_channels, tester_state,
                                        settle_timeout):
    """ withdraw must fail if the proof is tampered. """
    pkey0, pkey1, nettingchannel, _, _ = tester_channels[0]

    current_block = tester_state.block.number
    expiration = current_block + settle_timeout - 1
    locks = [
        make_lock(
            hashlock=hashlock,
            expiration=expiration,
        ) for hashlock in tree
    ]

    merkle_tree = Merkletree(sha3(lock.as_bytes) for lock in locks)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2**32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        locksroot=merkle_tree.merkleroot,
        recipient=privatekey_to_address(pkey1))

    address = privatekey_to_address(pkey0)
    sign_key = PrivateKey(pkey0)
    direct_transfer.sign(sign_key, address)

    direct_transfer_data = str(direct_transfer.packed().data)
    nettingchannel.close(direct_transfer_data, sender=pkey1)

    for lock in locks:
        secret = HASHLOCKS_SECRESTS[lock.hashlock]

        lock_encoded = lock.as_bytes
        merkle_proof = merkle_tree.make_proof(sha3(lock_encoded))

        # withdraw must fail regardless of which part of the proof is tampered
        for pos, hash_ in enumerate(merkle_proof):
            # changing arbitrary bytes from the proof
            tampered_hash = bytearray(hash_)
            tampered_hash[5], tampered_hash[6] = tampered_hash[
                6], tampered_hash[5]

            tampered_proof = list(merkle_proof)
            tampered_proof[pos] = str(tampered_hash)

            with pytest.raises(TransactionFailed):
                nettingchannel.withdraw(
                    lock_encoded,
                    ''.join(tampered_proof),
                    secret,
                    sender=pkey1,
                )
示例#9
0
    def compute_proof_for_lock(self, secret, lock):
        alllocks = chain(self.hashlock_pendinglocks.values(),
                         self.hashlock_unclaimedlocks.values(),
                         self.hashlock_unlockedlocks.values())

        # forcing bytes because ethereum.abi doesnt work with bytearray
        lock_encoded = bytes(lock.as_bytes)
        lock_hash = sha3(lock_encoded)

        tree = Merkletree(lock.lockhashed for lock in alllocks)
        merkle_proof = tree.make_proof(lock_hash)

        return UnlockProof(
            merkle_proof,
            lock_encoded,
            secret,
        )
def test_merkle_proof(tree, tester_state,
                      tester_nettingchannel_library_address):
    """ computeMerkleRoot and the python implementation must compute the same value. """

    auxiliary = deploy_auxiliary_tester(tester_state,
                                        tester_nettingchannel_library_address)

    hashes = [sha3(element) for element in tree]
    merkle_tree = Merkletree(hashes)

    for element in tree:
        proof = merkle_tree.make_proof(sha3(element))

        smart_contact_root = auxiliary.computeMerkleRoot(
            element,
            ''.join(proof),
        )

        assert smart_contact_root == merkle_tree.merkleroot