예제 #1
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,
            )
예제 #2
0
def test_withdraw_fails_with_partial_merkle_proof(tree, tester_channels,
                                                  tester_chain,
                                                  settle_timeout):
    """ withdraw must fail if informed proof is not complete. """
    pkey0, pkey1, nettingchannel, channel0, _ = tester_channels[0]

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

    leaves = [sha3(lock.as_bytes) for lock in locks]
    layers = compute_layers(leaves)
    merkle_tree = MerkleTreeState(layers)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2**32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        channel=channel0.identifier,
        locksroot=merkleroot(merkle_tree),
        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 = compute_merkleproof_for(merkle_tree, 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,
                    b''.join(tampered_proof),
                    secret,
                    sender=pkey1,
                )
예제 #3
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,
                )
예제 #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, _, _ = 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,
    )

    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 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_withdraw_tampered_lock_amount(
        tree,
        tester_channels,
        tester_chain,
        tester_token,
        settle_timeout,
):

    """ withdraw must fail if the lock amonut is tampered. """
    pkey0, pkey1, nettingchannel, channel0, _ = tester_channels[0]

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

    leaves = [sha3(lock.as_bytes) for lock in locks]
    layers = compute_layers(leaves)
    merkle_tree = MerkleTreeState(layers)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2 ** 32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        channel=channel0.identifier,
        locksroot=merkleroot(merkle_tree),
        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 = SECRETHASHES_SECRESTS[lock.secrethash]

        lock_encoded = lock.as_bytes
        merkle_proof = compute_merkleproof_for(merkle_tree, sha3(lock_encoded))

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

        with pytest.raises(TransactionFailed):
            nettingchannel.withdraw(
                tampered_lock_encoded,
                b''.join(merkle_proof),
                secret,
                sender=pkey1,
            )
예제 #6
0
def test_withdraw_tampered_merkle_proof(tree, tester_channels, tester_chain, settle_timeout):
    """ withdraw must fail if the proof is tampered. """
    pkey0, pkey1, nettingchannel, channel0, _ = tester_channels[0]

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

    leaves = [sha3(lock.as_bytes) for lock in locks]
    layers = compute_layers(leaves)
    merkle_tree = MerkleTreeState(layers)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2 ** 32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        channel=channel0.identifier,
        locksroot=merkleroot(merkle_tree),
        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 = SECRETHASHES_SECRESTS[lock.secrethash]

        lock_encoded = lock.as_bytes
        merkle_proof = compute_merkleproof_for(merkle_tree, 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[6], tampered_hash[7] = tampered_hash[7], tampered_hash[6]

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

            joiner = b''
            with pytest.raises(TransactionFailed):
                nettingchannel.withdraw(
                    lock_encoded,
                    joiner.join(tampered_proof),
                    secret,
                    sender=pkey1,
                )
def test_withdraw_tampered_lock_amount(
        tree,
        tester_channels,
        tester_chain,
        tester_token,
        settle_timeout):

    """ withdraw must fail if the lock amonut is tampered. """
    pkey0, pkey1, nettingchannel, channel0, _ = tester_channels[0]

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

    leaves = [sha3(lock.as_bytes) for lock in locks]
    layers = compute_layers(leaves)
    merkle_tree = MerkleTreeState(layers)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2 ** 32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        channel=channel0.channel_address,
        locksroot=merkleroot(merkle_tree),
        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 = compute_merkleproof_for(merkle_tree, 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,
                b''.join(merkle_proof),
                secret,
                sender=pkey1,
            )
def test_withdraw_tampered_merkle_proof(tree, tester_channels, tester_chain, settle_timeout):
    """ withdraw must fail if the proof is tampered. """
    pkey0, pkey1, nettingchannel, channel0, _ = tester_channels[0]

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

    leaves = [sha3(lock.as_bytes) for lock in locks]
    layers = compute_layers(leaves)
    merkle_tree = MerkleTreeState(layers)

    opened_block = nettingchannel.opened(sender=pkey0)
    nonce = 1 + (opened_block * (2 ** 32))
    direct_transfer = make_direct_transfer(
        nonce=nonce,
        channel=channel0.channel_address,
        locksroot=merkleroot(merkle_tree),
        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 = compute_merkleproof_for(merkle_tree, 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[6], tampered_hash[7] = tampered_hash[7], tampered_hash[6]

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

            joiner = b''
            with pytest.raises(TransactionFailed):
                nettingchannel.withdraw(
                    lock_encoded,
                    joiner.join(tampered_proof),
                    secret,
                    sender=pkey1,
                )
예제 #9
0
def test_pfs_global_messages(
    matrix_transports,
    monkeypatch,
):
    """
    Test that `update_pfs` from `RaidenEventHandler` sends balance proof updates to the global
    PATH_FINDING_BROADCASTING_ROOM room on Send($BalanceProof)* events, i.e. events, that send
    a new balance proof to the channel partner.
    """
    transport = matrix_transports[0]
    transport._client.api.retry_timeout = 0
    transport._send_raw = MagicMock()
    raiden_service = MockRaidenService(None)

    transport.start(
        raiden_service,
        raiden_service.message_handler,
        None,
    )

    pfs_room_name = make_room_alias(transport.network_id,
                                    PATH_FINDING_BROADCASTING_ROOM)
    pfs_room = transport._global_rooms.get(pfs_room_name)
    assert isinstance(pfs_room, Room)
    pfs_room.send_text = MagicMock(spec=pfs_room.send_text)

    raiden_service.transport = transport
    transport.log = MagicMock()

    # create mock events that should trigger a send
    lock = make_lock()
    hash_time_lock = HashTimeLockState(lock.amount, lock.expiration,
                                       lock.secrethash)

    def make_unsigned_balance_proof(nonce):
        return BalanceProofUnsignedState.from_dict(
            make_balance_proof(nonce=nonce,
                               signer=LocalSigner(HOP1_KEY),
                               amount=1).to_dict(), )

    transfer1 = LockedTransferUnsignedState(
        balance_proof=make_unsigned_balance_proof(nonce=1),
        payment_identifier=1,
        token=b'1',
        lock=hash_time_lock,
        target=HOP1,
        initiator=HOP1,
    )
    transfer2 = LockedTransferUnsignedState(
        balance_proof=make_unsigned_balance_proof(nonce=2),
        payment_identifier=1,
        token=b'1',
        lock=hash_time_lock,
        target=HOP1,
        initiator=HOP1,
    )

    send_balance_proof_events = [
        SendLockedTransfer(HOP1, 1, 1, transfer1),
        SendRefundTransfer(HOP1, 1, 1, transfer2),
        SendBalanceProof(HOP1, 1, 1, 1, b'1', b'x' * 32,
                         make_unsigned_balance_proof(nonce=3)),
        SendLockExpired(HOP1, 1, make_unsigned_balance_proof(nonce=4),
                        b'x' * 32),
    ]
    for num, event in enumerate(send_balance_proof_events):
        assert event.balance_proof.nonce == num + 1
    # make sure we cover all configured event types
    assert all(event in [type(event) for event in send_balance_proof_events]
               for event in SEND_BALANCE_PROOF_EVENTS)

    event_handler = raiden_event_handler.RaidenEventHandler()

    # let our mock objects pass validation
    channelstate_mock = Mock()
    channelstate_mock.reveal_timeout = 1

    monkeypatch.setattr(
        raiden_event_handler,
        'get_channelstate_by_token_network_and_partner',
        lambda *args, **kwargs: channelstate_mock,
    )
    monkeypatch.setattr(raiden_event_handler, 'state_from_raiden',
                        lambda *args, **kwargs: 1)
    monkeypatch.setattr(event_handler, 'handle_send_lockedtransfer',
                        lambda *args, **kwargs: 1)
    monkeypatch.setattr(event_handler, 'handle_send_refundtransfer',
                        lambda *args, **kwargs: 1)

    # handle the events
    for event in send_balance_proof_events:
        event_handler.on_raiden_event(
            raiden_service,
            event,
        )
    gevent.idle()

    # ensure all events triggered a send for their respective balance_proof
    # matrix transport may concatenate multiple messages send in one interval
    assert pfs_room.send_text.call_count >= 1
    concatenated_call_args = ' '.join(
        str(arg) for arg in pfs_room.send_text.call_args_list)
    assert all(f'"nonce": {i + 1}' in concatenated_call_args
               for i in range(len(SEND_BALANCE_PROOF_EVENTS)))
    transport.stop()
    transport.get()