Exemple #1
0
def test_cancel_transfer():
    deposit = 100
    asset = sha3('test_cancel_transfer')[:20]

    # pylint: disable=unbalanced-tuple-unpacking
    app0, app1, app2 = create_sequential_network(num_nodes=3, deposit=deposit, asset=asset)

    messages = setup_messages_cb()
    mlogger = MessageLogger()

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit, [],
        channel(app2, app1, asset), deposit, []
    )

    # drain the channel app1 -> app2
    amount = 80
    direct_transfer(app1, app2, asset, amount)

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit - amount, [],
        channel(app2, app1, asset), deposit + amount, []
    )

    # app1 -> app2 is the only available path and doens't have resource, app1
    # needs to send CancelTransfer to app0
    transfer(app0, app2, asset, 50)

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit - amount, [],
        channel(app2, app1, asset), deposit + amount, []
    )

    assert len(messages) == 6  # DirectTransfer + MediatedTransfer + CancelTransfer + a Ack for each

    app1_messages = mlogger.get_node_messages(pex(app1.raiden.address), only='sent')

    assert isinstance(app1_messages[-1], CancelTransfer)
Exemple #2
0
def raiden_chain(request, private_keys, asset, channels_per_node, deposit,
                 settle_timeout, poll_timeout, registry_address, blockchain_service,
                 transport_class):
    blockchain_service_class = BlockChainServiceMock
    blockchain_service.new_channel_manager_contract(asset)

    raiden_apps = create_sequential_network(
        private_keys,
        asset,
        registry_address,
        channels_per_node,
        deposit,
        settle_timeout,
        poll_timeout,
        transport_class,
        blockchain_service_class,
    )

    _raiden_cleanup(request, raiden_apps)

    return raiden_apps
Exemple #3
0
def raiden_chain(request, private_keys, asset, channels_per_node, deposit,
                 settle_timeout, poll_timeout, registry_address,
                 blockchain_service, transport_class):
    blockchain_service_class = BlockChainServiceMock
    blockchain_service.new_channel_manager_contract(asset)

    raiden_apps = create_sequential_network(
        private_keys,
        asset,
        registry_address,
        channels_per_node,
        deposit,
        settle_timeout,
        poll_timeout,
        transport_class,
        blockchain_service_class,
    )

    _raiden_cleanup(request, raiden_apps)

    return raiden_apps
def test_settled_lock():
    """ After a lock has it's secret revealed and a transfer happened, the lock
    cannot be used to net any value with the contract.
    """
    deposit = 100
    asset = sha3('test_settled_lock')[:20]
    amount = 30

    # pylint: disable=unbalanced-tuple-unpacking
    apps = create_sequential_network(num_nodes=4, deposit=deposit, asset=asset)

    # mediated transfer with the secret revealed
    transfer(apps[0], apps[3], asset, amount)

    # create the latest transfer
    direct_transfer(apps[0], apps[1], asset, amount)

    secret = ''  # need to get the secret
    attack_channel = channel(apps[2], apps[1], asset)
    secret_transfer = get_received_transfer(attack_channel, 0)
    last_transfer = get_received_transfer(attack_channel, 1)
    nettingcontract_address = attack_channel.nettingcontract_address

    # create a fake proof
    merkle_proof = attack_channel.our_state.locked.get_proof(secret_transfer)

    # call close giving the secret for a transfer that has being revealed
    apps[1].raiden.chain.close(
        asset,
        nettingcontract_address,
        apps[1].raiden.address,
        [last_transfer],
        [(merkle_proof, secret_transfer.lock, secret)],
    )

    # forward the block number to allow settle
    for _ in range(NettingChannelContract.locked_time):
        apps[2].raiden.chain.next_block()

    apps[1].raiden.chain.settle(asset, nettingcontract_address)
Exemple #5
0
def test_settled_lock():
    """ After a lock has it's secret revealed and a transfer happened, the lock
    cannot be used to net any value with the contract.
    """
    deposit = 100
    asset = sha3('test_settled_lock')[:20]
    amount = 30

    # pylint: disable=unbalanced-tuple-unpacking
    apps = create_sequential_network(num_nodes=4, deposit=deposit, asset=asset)

    # mediated transfer with the secret revealed
    transfer(apps[0], apps[3], asset, amount)

    # create the latest transfer
    direct_transfer(apps[0], apps[1], asset, amount)

    secret = ''  # need to get the secret
    attack_channel = channel(apps[2], apps[1], asset)
    secret_transfer = get_received_transfer(attack_channel, 0)
    last_transfer = get_received_transfer(attack_channel, 1)
    nettingcontract_address = attack_channel.nettingcontract_address

    # create a fake proof
    merkle_proof = attack_channel.our_state.locked.get_proof(secret_transfer)

    # call close giving the secret for a transfer that has being revealed
    apps[1].raiden.chain.close(
        asset,
        nettingcontract_address,
        apps[1].raiden.address,
        [last_transfer],
        [(merkle_proof, secret_transfer.lock, secret)],
    )

    # forward the block number to allow settle
    for _ in range(NettingChannelContract.settle_timeout):
        apps[2].raiden.chain.next_block()

    apps[1].raiden.chain.settle(asset, nettingcontract_address)
Exemple #6
0
def raiden_chain(request, assets_addresses, channels_per_node, deposit,
                 settle_timeout, blockchain_services, transport_class):
    if len(assets_addresses) > 1:
        raise ValueError('raiden_chain only works with a single asset')

    assert channels_per_node in (0, 1, 2, CHAIN), (
        'deployed_network uses create_sequential_network that can only work '
        'with 0, 1 or 2 channels')

    verbosity = request.config.option.verbose

    raiden_apps = create_sequential_network(
        blockchain_services,
        assets_addresses[0],
        channels_per_node,
        deposit,
        settle_timeout,
        transport_class,
        verbosity,
    )

    _raiden_cleanup(request, raiden_apps)

    return raiden_apps
def test_start_end_attack():
    """ An attacker can try to steal assets from a hub or the last node in a
    path.

    The attacker needs to use two addresses (A1 and A2) and connect both to the
    hub H, once connected a mediated transfer is initialized from A1 to A2
    through H, once the node A2 receives the mediated transfer the attacker
    uses the it's know secret and reveal to close and settles the channel H-A2,
    without revealing the secret to H's raiden node.

    The intention is to make the hub transfer the asset but for him to be
    unable to require the asset A1.
    """
    asset = sha3('test_two_attack')[:20]
    deposit = 100
    amount = 30
    apps = create_sequential_network(num_nodes=3, deposit=deposit, asset=asset)

    # The attacker creates a mediated transfer from it's account A1, to it's
    # account A2, throught the hub H
    secret = hidden_mediated_transfer(apps, asset, amount)

    attack_channel = channel(apps[2], apps[1], asset)
    attack_transfer = get_received_transfer(attack_channel, 0)
    attack_contract = attack_channel.nettingcontract_address
    hub_contract = channel(apps[1], apps[0], asset).nettingcontract_address

    # the attacker can create a merkle proof of the locked transfer
    merkle_proof = attack_channel.our_state.locked.get_proof(attack_transfer)

    # start the settle counter
    apps[2].raiden.chain.close(
        asset,
        attack_contract,
        apps[2].raiden.address,
        [attack_transfer],
        [],
    )

    # wait until the last block to reveal the secret
    for _ in range(attack_transfer.lock.expiration - 1):
        apps[2].raiden.chain.next_block()

    # since the attacker knows the secret he can net the lock
    apps[2].raiden.chain.close(
        asset,
        attack_contract,
        apps[2].raiden.address,
        [attack_transfer],
        [(merkle_proof, attack_transfer.lock, secret)],
    )
    # XXX: verify that the secret was publicized

    # at this point the hub might not know yet the secret, and won't be able to
    # claim the asset from the channel A1 - H

    # the attacker settle the contract
    apps[2].raiden.chain.next_block()
    apps[2].raiden.chain.settle(asset, attack_contract)

    # at this point the attack has the "stolen" funds
    attack_contract = apps[2].raiden.chain.asset_hashchannel[asset][attack_contract]
    assert attack_contract.participants[apps[2].raiden.address]['netted'] == deposit + amount
    assert attack_contract.participants[apps[1].raiden.address]['netted'] == deposit - amount

    # and the hub's channel A1-H doesn't
    hub_contract = apps[1].raiden.chain.asset_hashchannel[asset][hub_contract]
    assert hub_contract.participants[apps[0].raiden.address]['netted'] == deposit
    assert hub_contract.participants[apps[1].raiden.address]['netted'] == deposit

    # to mitigate the attack the Hub _needs_ to use a lower expiration for the
    # locked transfer between H-A2 than A1-H, since for A2 to acquire the asset
    # it needs to make the secret public in the block chain we publish the
    # secret through an event and the Hub will be able to require it's funds
    apps[1].raiden.chain.next_block()

    # XXX: verify that the Hub has found the secret, close and settle the channel

    # the hub has acquired it's asset
    hub_contract = apps[1].raiden.chain.asset_hashchannel[asset][hub_contract]
    assert hub_contract.participants[apps[0].raiden.address]['netted'] == deposit + amount
    assert hub_contract.participants[apps[1].raiden.address]['netted'] == deposit - amount
Exemple #8
0
def deployed_network(request, private_keys, channels_per_node, deposit,
                     number_of_assets, settle_timeout, poll_timeout,
                     transport_class, geth_cluster):

    gevent.sleep(2)
    assert channels_per_node in (0, 1, 2, CHAIN), (
        'deployed_network uses create_sequential_network that can only work '
        'with 0, 1 or 2 channels'
    )

    privatekey = private_keys[0]
    address = privtoaddr(privatekey)
    blockchain_service_class = BlockChainService

    jsonrpc_client = JSONRPCClient(
        host='0.0.0.0',
        privkey=privatekey,
        print_communication=False,
    )
    patch_send_transaction(jsonrpc_client)

    humantoken_path = get_contract_path('HumanStandardToken.sol')
    registry_path = get_contract_path('Registry.sol')

    humantoken_contracts = compile_file(humantoken_path, libraries=dict())
    registry_contracts = compile_file(registry_path, libraries=dict())

    registry_proxy = jsonrpc_client.deploy_solidity_contract(
        address,
        'Registry',
        registry_contracts,
        dict(),
        tuple(),
        timeout=poll_timeout,
    )
    registry_address = registry_proxy.address

    # Using 3 * deposit because we assume that is the maximum number of
    # channels that will be created.
    # `total_per_node = channels_per_node * deposit`
    total_per_node = 3 * deposit
    total_asset = total_per_node * len(private_keys)
    asset_addresses = []
    for _ in range(number_of_assets):
        token_proxy = jsonrpc_client.deploy_solidity_contract(
            address,
            'HumanStandardToken',
            humantoken_contracts,
            dict(),
            (total_asset, 'raiden', 2, 'Rd'),
            timeout=poll_timeout,
        )
        asset_address = token_proxy.address
        assert len(asset_address)
        asset_addresses.append(asset_address)

        transaction_hash = registry_proxy.addAsset(asset_address)  # pylint: disable=no-member
        jsonrpc_client.poll(transaction_hash.decode('hex'), timeout=poll_timeout)

        # only the creator of the token starts with a balance, transfer from
        # the creator to the other nodes
        for transfer_to in private_keys:
            if transfer_to != jsonrpc_client.privkey:
                transaction_hash = token_proxy.transfer(  # pylint: disable=no-member
                    privtoaddr(transfer_to),
                    total_per_node,
                    startgas=GAS_LIMIT,
                )
                jsonrpc_client.poll(transaction_hash.decode('hex'))

        for key in private_keys:
            assert token_proxy.balanceOf(privtoaddr(key)) == total_per_node  # pylint: disable=no-member

    raiden_apps = create_sequential_network(
        private_keys,
        asset_addresses[0],
        registry_address,
        channels_per_node,
        deposit,
        settle_timeout,
        poll_timeout,
        transport_class,
        blockchain_service_class,
    )

    _raiden_cleanup(request, raiden_apps)

    return raiden_apps
Exemple #9
0
def test_start_end_attack():
    """ An attacker can try to steal assets from a hub or the last node in a
    path.

    The attacker needs to use two addresses (A1 and A2) and connect both to the
    hub H, once connected a mediated transfer is initialized from A1 to A2
    through H, once the node A2 receives the mediated transfer the attacker
    uses the it's know secret and reveal to close and settles the channel H-A2,
    without revealing the secret to H's raiden node.

    The intention is to make the hub transfer the asset but for him to be
    unable to require the asset A1.
    """
    asset = sha3('test_two_attack')[:20]
    deposit = 100
    amount = 30
    apps = create_sequential_network(num_nodes=3, deposit=deposit, asset=asset)

    # The attacker creates a mediated transfer from it's account A1, to it's
    # account A2, throught the hub H
    secret = hidden_mediated_transfer(apps, asset, amount)

    attack_channel = channel(apps[2], apps[1], asset)
    attack_transfer = get_received_transfer(attack_channel, 0)
    attack_contract = attack_channel.nettingcontract_address
    hub_contract = channel(apps[1], apps[0], asset).nettingcontract_address

    # the attacker can create a merkle proof of the locked transfer
    merkle_proof = attack_channel.our_state.locked.get_proof(attack_transfer)

    # start the settle counter
    apps[2].raiden.chain.close(
        asset,
        attack_contract,
        apps[2].raiden.address,
        [attack_transfer],
        [],
    )

    # wait until the last block to reveal the secret
    for _ in range(attack_transfer.lock.expiration - 1):
        apps[2].raiden.chain.next_block()

    # since the attacker knows the secret he can net the lock
    apps[2].raiden.chain.close(
        asset,
        attack_contract,
        apps[2].raiden.address,
        [attack_transfer],
        [(merkle_proof, attack_transfer.lock, secret)],
    )
    # XXX: verify that the secret was publicized

    # at this point the hub might not know yet the secret, and won't be able to
    # claim the asset from the channel A1 - H

    # the attacker settle the contract
    apps[2].raiden.chain.next_block()
    apps[2].raiden.chain.settle(asset, attack_contract)

    # at this point the attack has the "stolen" funds
    attack_contract = apps[2].raiden.chain.asset_hashchannel[asset][
        attack_contract]
    assert attack_contract.participants[
        apps[2].raiden.address]['netted'] == deposit + amount
    assert attack_contract.participants[
        apps[1].raiden.address]['netted'] == deposit - amount

    # and the hub's channel A1-H doesn't
    hub_contract = apps[1].raiden.chain.asset_hashchannel[asset][hub_contract]
    assert hub_contract.participants[
        apps[0].raiden.address]['netted'] == deposit
    assert hub_contract.participants[
        apps[1].raiden.address]['netted'] == deposit

    # to mitigate the attack the Hub _needs_ to use a lower expiration for the
    # locked transfer between H-A2 than A1-H, since for A2 to acquire the asset
    # it needs to make the secret public in the block chain we publish the
    # secret through an event and the Hub will be able to require it's funds
    apps[1].raiden.chain.next_block()

    # XXX: verify that the Hub has found the secret, close and settle the channel

    # the hub has acquired it's asset
    hub_contract = apps[1].raiden.chain.asset_hashchannel[asset][hub_contract]
    assert hub_contract.participants[
        apps[0].raiden.address]['netted'] == deposit + amount
    assert hub_contract.participants[
        apps[1].raiden.address]['netted'] == deposit - amount
Exemple #10
0
def deployed_network(request, private_keys, channels_per_node, deposit,
                     number_of_assets, settle_timeout, poll_timeout,
                     transport_class, geth_cluster):

    gevent.sleep(2)
    assert channels_per_node in (0, 1, 2, CHAIN), (
        'deployed_network uses create_sequential_network that can only work '
        'with 0, 1 or 2 channels')

    privatekey = private_keys[0]
    address = privtoaddr(privatekey)
    blockchain_service_class = BlockChainService

    jsonrpc_client = JSONRPCClient(
        host='0.0.0.0',
        privkey=privatekey,
        print_communication=False,
    )
    patch_send_transaction(jsonrpc_client)

    humantoken_path = get_contract_path('HumanStandardToken.sol')
    registry_path = get_contract_path('Registry.sol')

    humantoken_contracts = compile_file(humantoken_path, libraries=dict())
    registry_contracts = compile_file(registry_path, libraries=dict())

    registry_proxy = jsonrpc_client.deploy_solidity_contract(
        address,
        'Registry',
        registry_contracts,
        dict(),
        tuple(),
        timeout=poll_timeout,
    )
    registry_address = registry_proxy.address

    # Using 3 * deposit because we assume that is the maximum number of
    # channels that will be created.
    # `total_per_node = channels_per_node * deposit`
    total_per_node = 3 * deposit
    total_asset = total_per_node * len(private_keys)
    asset_addresses = []
    for _ in range(number_of_assets):
        token_proxy = jsonrpc_client.deploy_solidity_contract(
            address,
            'HumanStandardToken',
            humantoken_contracts,
            dict(),
            (total_asset, 'raiden', 2, 'Rd'),
            timeout=poll_timeout,
        )
        asset_address = token_proxy.address
        assert len(asset_address)
        asset_addresses.append(asset_address)

        transaction_hash = registry_proxy.addAsset(asset_address)  # pylint: disable=no-member
        jsonrpc_client.poll(transaction_hash.decode('hex'),
                            timeout=poll_timeout)

        # only the creator of the token starts with a balance, transfer from
        # the creator to the other nodes
        for transfer_to in private_keys:
            if transfer_to != jsonrpc_client.privkey:
                transaction_hash = token_proxy.transfer(  # pylint: disable=no-member
                    privtoaddr(transfer_to),
                    total_per_node,
                    startgas=GAS_LIMIT,
                )
                jsonrpc_client.poll(transaction_hash.decode('hex'))

        for key in private_keys:
            assert token_proxy.balanceOf(privtoaddr(key)) == total_per_node  # pylint: disable=no-member

    raiden_apps = create_sequential_network(
        private_keys,
        asset_addresses[0],
        registry_address,
        channels_per_node,
        deposit,
        settle_timeout,
        poll_timeout,
        transport_class,
        blockchain_service_class,
    )

    _raiden_cleanup(request, raiden_apps)

    return raiden_apps