def test_hash():
    ping = Ping(nonce=0, current_protocol_version=constants.PROTOCOL_VERSION)
    ping.sign(PRIVKEY)
    data = ping.encode()
    msghash = sha3(data)
    decoded_ping = decode(data)
    assert sha3(decoded_ping.encode()) == msghash
示例#2
0
def test_mediated_transfer(iterations=ITERATIONS):
    identifier = 1
    amount = 1
    expiration = 1
    hashlock = sha3(ADDRESS)
    lock = Lock(amount, expiration, hashlock)

    nonce = 1
    asset = ADDRESS
    balance = 1
    recipient = ADDRESS
    locksroot = sha3(ADDRESS)
    target = ADDRESS
    initiator = ADDRESS
    msg = MediatedTransfer(
        identifier,
        nonce,
        asset,
        balance,
        recipient,
        locksroot,
        lock,
        target,
        initiator,
        fee=0,
    )
    msg.sign(PRIVKEY, ADDRESS)

    run_timeit('MediatedTranfer', msg, iterations=iterations)
def test_three():
    hash_0 = b'a' * 32
    hash_1 = b'b' * 32
    hash_2 = b'c' * 32

    leaves = [hash_0, hash_1, hash_2]
    layers = compute_layers(leaves)
    tree = MerkleTreeState(layers)
    root = merkleroot(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 sha3(hash_0 + hash_1) == hash_01
    calculated_root = sha3(hash_2 + hash_01)

    proof0 = compute_merkleproof_for(tree, hash_0)
    proof1 = compute_merkleproof_for(tree, hash_1)
    proof2 = compute_merkleproof_for(tree, hash_2)

    assert proof0 == [hash_1, hash_2]
    assert root == calculated_root
    assert validate_proof(proof0, root, hash_0)

    assert proof1 == [hash_0, hash_2]
    assert root == calculated_root
    assert validate_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 == [sha3(hash_0 + hash_1)]
    assert root == calculated_root
    assert validate_proof(proof2, root, hash_2)
示例#4
0
def mediated_transfer(initiator_app, target_app, asset, amount):  # pylint: disable=too-many-arguments
    """ Nice to read shortcut to make a MediatedTransfer.

    The secret will be revealed and the apps will be synchronized.
    """
    has_channel = target_app.raiden.address in initiator_app.raiden.assetmanagers[asset].channel

    # api.transfer() would do a DirectTransfer
    if has_channel:
        initiator_channel = channel(initiator_app, target_app, asset)
        secret = sha3('{}{}'.format(
            initiator_channel.nettingcontract_address,
            str(initiator_channel.our_state.nonce),
        ))
        hashlock = sha3(secret)
        transfermanager = target_app.raiden.assetmanagers[asset].transfermanager

        task = MediatedTransferTask(
            transfermanager,
            amount,
            target_app.address,
            hashlock,
            expiration=None,
            originating_transfer=None,
            secret=secret,
        )
        task.start()
        task.join()
    else:
        initiator_app.raiden.api.transfer(asset, amount, target_app.raiden.address)
示例#5
0
def test_hash():
    ping = Ping(nonce=0)
    ping.sign(PRIVKEY)
    data = ping.encode()
    msghash = sha3(data)
    decoded_ping = decode(data)
    assert sha3(decoded_ping.encode()) == msghash
示例#6
0
    def unlock(self, ctx, locked_encoded, merkleproof_encoded, secret):
        if self.settled is not None:
            raise RuntimeError('Contract is settled.')

        if self.closed is None:
            raise RuntimeError('Contract is open.')

        if ctx['msg.sender'] not in self.participants:
            raise ValueError('Unknow address.')

        partner = self.partner(ctx['msg.sender'])
        state = self.participants[partner]
        transfer = state.transfer

        # if partner haven't made a single transfer
        if transfer is None:
            return

        merkle_proof = tuple32(merkleproof_encoded)
        lock = Lock.from_bytes(locked_encoded)

        hashlock = lock.hashlock
        if hashlock != sha3(secret):
            raise ValueError('Invalid secret')

        is_valid_proof = check_proof(
            merkle_proof,
            transfer.locksroot,
            sha3(transfer.lock.as_bytes),
        )

        if not is_valid_proof:
            raise ValueError('Invalid merkle proof')

        transfer.append(lock)
示例#7
0
文件: channel.py 项目: utzig/raiden
    def withdraw_lock(self, secret):
        """ A lock was released by the sender, withdraw it's funds and update
        the state.
        """
        hashlock = sha3(secret)

        if not self.our_state.balance_proof.is_known(hashlock):
            msg = 'The secret doesnt withdraw any hashlock. hashlock:{} asset:{}'.format(
                pex(hashlock),
                pex(self.asset_address),
            )
            raise ValueError(msg)

        lock = self.our_state.balance_proof.get_lock_by_hashlock(hashlock)

        if log.isEnabledFor(logging.DEBUG):
            log.debug(
                'ASSET WITHDRAWED %s < %s asset:%s hashlock:%s lockhash:%s amount:%s',
                pex(self.our_state.address),
                pex(self.partner_state.address),
                pex(self.asset_address),
                pex(hashlock),
                pex(sha3(lock.as_bytes)),
                lock.amount,
            )

        self.our_state.release_lock(self.partner_state, secret)
示例#8
0
def test_registry(state, registry, events):
    asset_address1 = sha3('asset')[:20]
    asset_address2 = sha3('address')[:20]
    unregistered_address = sha3('mainz')[:20]

    contract_address1 = registry.addAsset(asset_address1)
    contract_address2 = registry.addAsset(asset_address2)

    with pytest.raises(TransactionFailed):
        registry.addAsset(asset_address1)

    channel_manager_address = registry.channelManagerByAsset(asset_address1)
    assert channel_manager_address == contract_address1

    with pytest.raises(TransactionFailed):
        registry.channelManagerByAsset(unregistered_address)

    addresses = registry.assetAddresses()

    assert len(addresses) == 2
    assert addresses[0] == asset_address1.encode('hex')
    assert addresses[1] == asset_address2.encode('hex')

    assert len(events) == 2

    assert events[0]['_event_type'] == 'AssetAdded'
    assert events[0]['assetAddress'] == asset_address1.encode('hex')
    assert events[0]['channelManagerAddress'] == contract_address1

    assert events[1]['_event_type'] == 'AssetAdded'
    assert events[1]['assetAddress'] == asset_address2.encode('hex')
    assert events[1]['channelManagerAddress'] == contract_address2
示例#9
0
def make_signed_transfer_from_counter(counter):
    lock = Lock(
        amount=next(counter),
        expiration=next(counter),
        secrethash=sha3(factories.make_secret(next(counter))),
    )

    signed_transfer = factories.make_signed_transfer(
        amount=next(counter),
        initiator=factories.make_address(),
        target=factories.make_address(),
        expiration=next(counter),
        secret=factories.make_secret(next(counter)),
        payment_identifier=next(counter),
        message_identifier=next(counter),
        nonce=next(counter),
        transferred_amount=next(counter),
        locked_amount=next(counter),
        locksroot=sha3(lock.as_bytes),
        recipient=factories.make_address(),
        channel_identifier=next(counter),
        token_network_address=factories.make_address(),
        token=factories.make_address(),
        pkey=factories.HOP1_KEY,
        sender=factories.HOP1,
    )

    return signed_transfer
示例#10
0
 def secret_request_with_wrong_secrethash(self, previous_action, secret):
     assume(sha3(secret) != sha3(previous_action.transfer.secret))
     self._assume_channel_opened(previous_action)
     transfer = deepcopy(previous_action.transfer)
     transfer.secret = secret
     action = self._receive_secret_request(transfer)
     return self._unauthentic_secret_request(action)
示例#11
0
def test_settlement(raiden_network, settle_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    chain0 = app0.raiden.chain

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = 5
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.partneraddress_channel
    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert channel0.external_state.netting_channel.address == channel1.external_state.netting_channel.address

    transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock)
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0, balance0, [transfermessage.lock],
        channel1, balance1, []
    )

    # Bob learns the secret, but Alice did not send a signed updated balance to
    # reflect this Bob wants to settle

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    merkle_proof = channel1.our_state.locked.get_proof(transfermessage)
    root = channel1.our_state.locked.root
    assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes))

    channel0.external_state.netting_channel.close(
        app0.raiden.address,
        transfermessage,
        None,
    )

    unlocked = [(merkle_proof, transfermessage.lock.as_bytes, secret)]

    channel0.external_state.netting_channel.unlock(
        app0.raiden.address,
        unlocked,
    )

    for _ in range(settle_timeout):
        chain0.next_block()

    channel0.external_state.netting_channel.settle()
示例#12
0
def test_locked_transfer():
    apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1)
    a0, a1 = apps
    c0 = a0.raiden.assetmanagers.values()[0].channels.values()[0]
    c1 = a1.raiden.assetmanagers.values()[0].channels.values()[0]

    b0, b1 = c0.balance, c1.balance

    amount = 10
    secret = 'secret'
    expiration = a0.raiden.chain.block_number + 100
    hashlock = sha3(secret)
    t = c0.create_lockedtransfer(amount=amount, expiration=expiration, hashlock=hashlock)
    c0.raiden.sign(t)
    c0.register_transfer(t)
    c1.register_transfer(t)

    assert hashlock in c1.locked
    assert hashlock in c0.partner.locked
    assert len(c0.locked) == 0
    assert len(c0.partner.locked) == 1
    assert len(c1.locked) == 1
    assert len(c1.partner.locked) == 0

    assert c0.balance == b0
    assert c0.distributable == c0.balance - amount
    assert c1.balance == c1.distributable == b1
    assert c0.locked.outstanding == 0
    assert c0.partner.locked.outstanding == amount
    assert c1.locked.outstanding == amount
    assert c1.partner.locked.outstanding == 0

    assert c0.locked.root == ''
    assert c1.partner.locked.root == ''

    assert c1.locked.root == merkleroot(
        [sha3(tx.lock.asstring) for tx in c1.locked.locked.values()])
    assert c0.partner.locked.root == c1.locked.root

    # reveal secret

    c0.claim_locked(secret)
    c1.claim_locked(secret)

    assert c0.balance == b0 - amount
    assert c0.distributable == c0.balance
    assert c1.balance == c1.distributable == b1 + amount
    assert c0.locked.outstanding == 0
    assert c0.partner.locked.outstanding == 0
    assert c1.locked.outstanding == 0
    assert c1.partner.locked.outstanding == 0
    assert len(c0.locked) == 0
    assert len(c0.partner.locked) == 0
    assert len(c1.locked) == 0
    assert len(c1.partner.locked) == 0
    assert c0.locked.root == ''
    assert c1.partner.locked.root == ''
    assert c1.locked.root == ''
    assert c0.partner.locked.root == ''
def generate_accounts(seeds):
    """Create private keys and addresses for all seeds.
    """
    return {
        seed: dict(
            privatekey=encode_hex(sha3(seed)),
            address=encode_hex(privatekey_to_address(sha3(seed)))
        ) for seed in seeds}
def test_settle_with_locked_mediated_transfer_for_counterparty(
        deposit,
        settle_timeout,
        reveal_timeout,
        tester_chain,
        tester_channels,
        tester_token):

    """ Test settle with a locked mediated transfer for the counter party. """

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial0 = tester_token.balanceOf(address0, sender=pkey0)
    initial1 = tester_token.balanceOf(address1, sender=pkey0)

    transferred_amount0 = 30
    increase_transferred_amount(channel0, channel1, transferred_amount0)

    expiration0 = tester_chain.block.number + reveal_timeout + 5
    new_block = Block(tester_chain.block.number)
    channel0.state_transition(new_block)
    channel1.state_transition(new_block)
    lock0 = Lock(amount=29, expiration=expiration0, hashlock=sha3(b'lock1'))
    mediated0 = make_mediated_transfer(
        channel0,
        channel1,
        address0,
        address1,
        lock0,
        pkey0,
        tester_chain.block.number,
    )

    nettingchannel.close(sender=pkey0)

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.updateTransfer(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey1)

    # the balances only change by transferred_amount because the lock was /not/ unlocked
    balance0 = initial0 + deposit - transferred_amount0
    balance1 = initial1 + transferred_amount0

    assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey0) == balance1
示例#15
0
def make_signed_transfer(
        amount,
        initiator,
        target,
        expiration,
        secret,
        payment_identifier=1,
        message_identifier=None,
        nonce=1,
        transferred_amount=0,
        locked_amount=None,
        locksroot=EMPTY_MERKLE_ROOT,
        recipient=UNIT_TRANSFER_TARGET,
        channel_identifier=UNIT_CHANNEL_ID,
        token=UNIT_TOKEN_ADDRESS,
        pkey=UNIT_TRANSFER_PKEY,
        sender=UNIT_TRANSFER_SENDER,
):

    if message_identifier is None:
        message_identifier = random.randint(0, UINT64_MAX)

    secrethash = sha3(secret)
    lock = Lock(
        amount,
        expiration,
        secrethash,
    )

    if locksroot == EMPTY_MERKLE_ROOT:
        locksroot = sha3(lock.as_bytes)

    if locked_amount is None:
        locked_amount = amount
    else:
        assert locked_amount >= amount

    transfer = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=message_identifier,
        payment_identifier=payment_identifier,
        nonce=nonce,
        token_network_address=UNIT_TOKEN_NETWORK_ADDRESS,
        token=token,
        channel_identifier=channel_identifier,
        transferred_amount=transferred_amount,
        locked_amount=locked_amount,
        recipient=recipient,
        locksroot=locksroot,
        lock=lock,
        target=target,
        initiator=initiator,
    )
    transfer.sign(pkey)
    assert transfer.sender == sender

    return lockedtransfersigned_from_message(transfer)
def test_compute_layers_duplicated():
    hash_0 = sha3(b'x')
    hash_1 = sha3(b'y')

    with pytest.raises(ValueError):
        compute_layers([hash_0, hash_0])

    with pytest.raises(ValueError):
        compute_layers([hash_0, hash_1, hash_0])
示例#17
0
def transfer_speed(num_transfers=100, max_locked=100):  # pylint: disable=too-many-locals
    channels_per_node = 1
    deposit = 100
    num_nodes = 2
    num_assets = 1

    private_keys = [
        sha3('speed:{}'.format(position))
        for position in range(num_nodes)
    ]

    assets = [
        sha3('asset:{}'.format(number))[:20]
        for number in range(num_assets)
    ]

    apps = create_network(
        private_keys,
        assets,
        MOCK_REGISTRY_ADDRESS,
        channels_per_node,
        deposit,
        DEFAULT_SETTLE_TIMEOUT,
        UDPTransport,
        BlockChainServiceMock
    )

    app0, app1 = apps  # pylint: disable=unbalanced-tuple-unpacking
    channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0]
    channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0]

    amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)]
    secrets = [str(i) for i in range(num_transfers)]
    expiration = app0.raiden.chain.block_number + 100

    start = time.time()

    for i, amount in enumerate(amounts):
        hashlock = sha3(secrets[i])
        locked_transfer = channel0.create_lockedtransfer(
            amount=amount,
            expiration=expiration,
            hashlock=hashlock,
        )
        app0.raiden.sign(locked_transfer)
        channel0.register_transfer(locked_transfer)
        channel1.register_transfer(locked_transfer)

        if i > max_locked:
            idx = i - max_locked
            secret = secrets[idx]
            channel0.claim_locked(secret)
            channel1.claim_locked(secret)

    elapsed = time.time() - start
    print('%d transfers per second' % (num_transfers / elapsed))
示例#18
0
def generate_accounts(seeds):
    """Create private keys and addresses for all seeds.
    """
    return {
        seed: {
            'privatekey': encode_hex(sha3(seed)),
            'address': encode_hex(privatekey_to_address(sha3(seed))),
        }
        for seed in seeds
    }
示例#19
0
def test_ack():
    echo = sha3(privkey)
    msg = Ack(address, echo)
    assert msg.echo == echo
    d = msg.encode()
    msghash = sha3(d)
    msg2 = decode(d)
    assert msg2.echo == echo
    assert msg2.sender == address
    assert sha3(msg2.encode()) == msghash
示例#20
0
def test_ack():
    echo = sha3(PRIVKEY)
    ack = Ack(ADDRESS, echo)
    assert ack.echo == echo
    data = ack.encode()
    msghash = sha3(data)
    decoded_ack = decode(data)
    assert decoded_ack.echo == ack.echo
    assert decoded_ack.sender == ack.sender
    assert sha3(decoded_ack.encode()) == msghash
def pending_mediated_transfer(app_chain, token, amount, identifier, expiration):
    """ Nice to read shortcut to make a MediatedTransfer were the secret is
    _not_ revealed.

    While the secret is not revealed all apps will be synchronized, meaning
    they are all going to receive the MediatedTransfer message.

    Returns:
        The secret used to generate the MediatedTransfer
    """
    # pylint: disable=too-many-locals

    if len(app_chain) < 2:
        raise ValueError('Cannot make a MediatedTransfer with less than two apps')

    fee = 0
    secret = None
    hashlock = None
    initiator_app = app_chain[0]
    target_app = app_chain[0]

    for from_app, to_app in zip(app_chain[:-1], app_chain[1:]):
        from_channel = channel(from_app, to_app, token)
        to_channel = channel(to_app, from_app, token)

        # use the initiator channel to generate a secret
        if secret is None:
            address = from_channel.external_state.netting_channel.address
            nonce = str(from_channel.our_state.nonce)
            secret = sha3(address + nonce.encode())
            hashlock = sha3(secret)

        transfer_ = from_channel.create_mediatedtransfer(
            initiator_app.raiden.address,
            target_app.raiden.address,
            fee,
            amount,
            identifier,
            expiration,
            hashlock,
        )
        from_app.raiden.sign(transfer_)

        from_channel.register_transfer(
            from_app.raiden.get_block_number(),
            transfer_,
        )
        to_channel.register_transfer(
            to_app.raiden.get_block_number(),
            transfer_,
        )

    return secret
示例#22
0
def test_locked_transfer(iterations=ITERATIONS):
    amount = 1
    expiration = 1
    hashlock = sha3(ADDRESS)
    lock = Lock(amount, expiration, hashlock)

    nonce = 1
    asset = ADDRESS
    balance = 1
    recipient = ADDRESS
    locksroot = sha3(ADDRESS)
    msg = LockedTransfer(nonce, asset, balance, recipient, locksroot, lock).sign(PRIVKEY)
    run_timeit('LockedTransfer', msg, iterations=iterations)
示例#23
0
def test_event_operators():
    a = EventPaymentSentSuccess(1, 4, 2, 5, sha3(b'target'))
    b = EventPaymentSentSuccess(1, 4, 2, 5, sha3(b'target'))
    c = EventPaymentSentSuccess(2, 7, 3, 4, sha3(b'target'))
    d = EventPaymentSentSuccess(2, 7, 3, 4, sha3(b'differenttarget'))

    # pylint: disable=unneeded-not
    assert a == b
    assert not a != b
    assert a != c
    assert not a == c
    assert not c == d

    a = EventPaymentSentFailed(1, 7, 2, 'target', 'BECAUSE')
    b = EventPaymentSentFailed(1, 7, 2, 'target', 'BECAUSE')
    c = EventPaymentSentFailed(3, 3, 3, 'target', 'UNKNOWN')

    assert a == b
    assert not a != b
    assert a != c
    assert not a == c

    a = EventPaymentReceivedSuccess(4, 4, 2, 5, sha3(b'initiator'))
    b = EventPaymentReceivedSuccess(4, 4, 2, 5, sha3(b'initiator'))
    c = EventPaymentReceivedSuccess(1, 2, 3, 5, sha3(b'initiator'))
    d = EventPaymentReceivedSuccess(1, 2, 3, 5, sha3(b'other initiator'))

    assert a == b
    assert not a != b
    assert a != c
    assert not a == c
    assert c != d
    assert not c == d
def test_event_operators():
    a = EventTransferSentSuccess(2, 5, sha3(b'target'))
    b = EventTransferSentSuccess(2, 5, sha3(b'target'))
    c = EventTransferSentSuccess(3, 4, sha3(b'target'))
    d = EventTransferSentSuccess(3, 4, sha3(b'differenttarget'))

    assert a == b
    assert not a != b
    assert a != c
    assert not a == c
    assert not c == d

    a = EventTransferSentFailed(2, 'BECAUSE')
    b = EventTransferSentFailed(2, 'BECAUSE')
    c = EventTransferSentFailed(3, 'UNKNOWN')

    assert a == b
    assert not a != b
    assert a != c
    assert not a == c

    a = EventTransferReceivedSuccess(2, 5, sha3(b'initiator'))
    b = EventTransferReceivedSuccess(2, 5, sha3(b'initiator'))
    c = EventTransferReceivedSuccess(3, 5, sha3(b'initiator'))
    d = EventTransferReceivedSuccess(3, 5, sha3(b'other initiator'))

    assert a == b
    assert not a != b
    assert a != c
    assert not a == c
    assert c != d
    assert not c == d
def test_withdraw_twice(reveal_timeout, tester_channels, tester_chain):
    """ A lock can be withdrawn only once, the second try must fail. """
    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]

    lock_expiration = tester_chain.block.number + reveal_timeout + 5
    secret = b'secretsecretsecretsecretsecretse'
    new_block = Block(tester_chain.block.number)
    channel0.state_transition(new_block)
    channel1.state_transition(new_block)
    lock = Lock(17, lock_expiration, sha3(secret))

    mediated0 = make_mediated_transfer(
        channel1,
        channel0,
        privatekey_to_address(pkey1),
        privatekey_to_address(pkey0),
        lock,
        pkey1,
        tester_chain.block.number,
        secret,
    )

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.close(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey0,
    )

    unlock_proofs = list(channel0.partner_state.get_known_unlocks())
    proof = unlock_proofs[0]

    nettingchannel.withdraw(
        proof.lock_encoded,
        b''.join(proof.merkle_proof),
        proof.secret,
        sender=pkey0,
    )

    with pytest.raises(TransactionFailed):
        nettingchannel.withdraw(
            proof.lock_encoded,
            b''.join(proof.merkle_proof),
            proof.secret,
            sender=pkey0,
        )
示例#26
0
def test_automatic_secret_registration(raiden_chain, token_addresses):
    app0, app1 = raiden_chain
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    amount = 100
    identifier = 1

    hold_event_handler = HoldOffChainSecretRequest()
    app1.raiden.raiden_event_handler = hold_event_handler

    target = app1.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        amount,
        target,
        identifier,
        secret,
    )

    gevent.sleep(1)  # wait for the messages to be exchanged

    # Stop app0 to avoid sending the unlock
    app0.raiden.transport.stop()

    reveal_secret = RevealSecret(
        random.randint(0, UINT64_MAX),
        secret,
    )
    app0.raiden.sign(reveal_secret)
    message_handler.MessageHandler().on_message(app1.raiden, reveal_secret)

    chain_state = views.state_from_app(app1)

    secrethash = sha3(secret)
    target_task = chain_state.payment_mapping.secrethashes_to_task[secrethash]
    lock_expiration = target_task.target_state.transfer.lock.expiration
    wait_until_block(app1.raiden.chain, lock_expiration)

    assert app1.raiden.default_secret_registry.check_registered(secrethash)
示例#27
0
def test_processed():
    message_identifier = random.randint(0, constants.UINT64_MAX)
    processed_message = Processed(message_identifier)
    processed_message.sign(PRIVKEY)
    assert processed_message.sender == ADDRESS

    assert processed_message.message_identifier == message_identifier

    data = processed_message.encode()
    decoded_processed_message = decode(data)

    assert decoded_processed_message.message_identifier == message_identifier
    assert processed_message.message_identifier == message_identifier
    assert decoded_processed_message.sender == processed_message.sender
    assert sha3(decoded_processed_message.encode()) == sha3(data)
示例#28
0
def mk_app(chain, discovery, transport_class, port, host='127.0.0.1'):
    ''' Instantiates an Raiden app with the given configuration. '''
    config = copy.deepcopy(App.default_config)
    config['port'] = port
    config['host'] = host
    config['privkey'] = sha3('{}:{}'.format(host, config['port']))
    return App(config, chain, discovery, transport_class)
示例#29
0
def hostport_to_privkeyaddr(host, port):
    """ Return `(private key, address)` deterministically generated. """
    myip_port = '{}:{}'.format(host, port)
    privkey = sha3(myip_port.encode())
    addr = privatekey_to_address(privkey)

    return privkey, addr
    def register_secret(self, secret: bytes):
        """ Register the secret with any channel that has a hashlock on it.

        This must search through all channels registered for a given hashlock
        and ignoring the tokens. Useful for refund transfer, split transfer,
        and token swaps.

        Raises:
            TypeError: If secret is unicode data.
        """
        if not isinstance(secret, bytes):
            raise TypeError('secret must be bytes')

        hashlock = sha3(secret)
        revealsecret_message = RevealSecret(secret)
        self.sign(revealsecret_message)

        for hash_channel in self.token_to_hashlock_to_channels.values():
            for channel in hash_channel[hashlock]:
                channel.register_secret(secret)

                # The protocol ignores duplicated messages.
                self.send_async(
                    channel.partner_state.address,
                    revealsecret_message,
                )
示例#31
0
def test_end_state():
    netting_channel = NettingChannelMock()
    token_address = make_address()
    privkey1, address1 = make_privkey_address()
    address2 = make_address()

    balance1 = 70
    balance2 = 110

    lock_secret = sha3('test_end_state')
    lock_amount = 30
    lock_expiration = 10
    lock_hashlock = sha3(lock_secret)

    state1 = ChannelEndState(address1, balance1, netting_channel.opened())
    state2 = ChannelEndState(address2, balance2, netting_channel.opened())

    assert state1.contract_balance == balance1
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1
    assert state2.distributable(state1) == balance2

    assert state1.locked() == 0
    assert state2.locked() == 0

    assert state1.balance_proof.is_pending(lock_hashlock) is False
    assert state2.balance_proof.is_pending(lock_hashlock) is False

    assert state1.balance_proof.merkleroot_for_unclaimed() == ''
    assert state2.balance_proof.merkleroot_for_unclaimed() == ''

    lock = Lock(
        lock_amount,
        lock_expiration,
        lock_hashlock,
    )
    lock_hash = sha3(lock.as_bytes)

    transferred_amount = 0
    locksroot = state2.compute_merkleroot_with(lock)

    locked_transfer = LockedTransfer(
        1,  # TODO: fill in identifier
        nonce=state1.nonce,
        token=token_address,
        transferred_amount=transferred_amount,
        recipient=state2.address,
        locksroot=locksroot,
        lock=lock,
    )

    transfer_target = make_address()
    transfer_initiator = make_address()
    fee = 0
    mediated_transfer = locked_transfer.to_mediatedtransfer(
        transfer_target,
        transfer_initiator,
        fee,
    )
    mediated_transfer.sign(privkey1, address1)

    state2.register_locked_transfer(mediated_transfer)

    assert state1.contract_balance == balance1
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1 - lock_amount
    assert state2.distributable(state1) == balance2

    assert state1.locked() == 0
    assert state2.locked() == lock_amount

    assert state1.balance_proof.is_pending(lock_hashlock) is False
    assert state2.balance_proof.is_pending(lock_hashlock) is True

    assert state1.balance_proof.merkleroot_for_unclaimed() == ''
    assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash

    with pytest.raises(ValueError):
        state1.update_contract_balance(balance1 - 10)

    state1.update_contract_balance(balance1 + 10)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1 - lock_amount + 10
    assert state2.distributable(state1) == balance2

    assert state1.locked() == 0
    assert state2.locked() == lock_amount

    assert state1.balance_proof.is_pending(lock_hashlock) is False
    assert state2.balance_proof.is_pending(lock_hashlock) is True

    assert state1.balance_proof.merkleroot_for_unclaimed() == ''
    assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash

    # registering the secret should not change the locked amount
    state2.register_secret(lock_secret)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1 - lock_amount + 10
    assert state2.distributable(state1) == balance2

    assert state1.locked() == 0
    assert state2.locked() == lock_amount

    assert state1.balance_proof.is_pending(lock_hashlock) is False
    assert state2.balance_proof.is_pending(lock_hashlock) is False

    assert state1.balance_proof.merkleroot_for_unclaimed() == ''
    assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash

    state2.release_lock(state1, lock_secret)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10 - lock_amount
    assert state2.balance(state1) == balance2 + lock_amount

    assert state1.distributable(state2) == balance1 + 10 - lock_amount
    assert state2.distributable(state1) == balance2 + lock_amount

    assert state1.locked() == 0
    assert state2.locked() == 0

    assert state1.balance_proof.is_pending(lock_hashlock) is False
    assert state2.balance_proof.is_pending(lock_hashlock) is False

    assert state1.balance_proof.merkleroot_for_unclaimed() == ''
    assert state2.balance_proof.merkleroot_for_unclaimed() == ''
示例#32
0
    GenesisDescription,
    run_private_blockchain,
)
from raiden.utils import privatekey_to_address, sha3
from raiden_contracts.constants import NETWORKNAME_TO_ID

NUM_GETH_NODES = 3
NUM_RAIDEN_ACCOUNTS = 10
START_PORT = 30301
START_RPCPORT = 8101


DEFAULT_ACCOUNTS_SEEDS = [
    "127.0.0.1:{}".format(START_PORT + i).encode() for i in range(NUM_RAIDEN_ACCOUNTS)
]
DEFAULT_ACCOUNTS_KEYS = [sha3(seed) for seed in DEFAULT_ACCOUNTS_SEEDS]
DEFAULT_ACCOUNTS = [privatekey_to_address(key) for key in DEFAULT_ACCOUNTS_KEYS]


def main():
    tmpdir = tempfile.mkdtemp()

    geth_nodes = []
    for i in range(NUM_GETH_NODES):
        is_miner = i == 0
        node_key = sha3(f"node:{i}".encode())
        p2p_port = START_PORT + i
        rpc_port = START_RPCPORT + i

        description = EthNodeDescription(
            private_key=node_key,
示例#33
0
def main():
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('--transfers', default=100, type=int)
    parser.add_argument('--nodes', default=10, type=int)
    parser.add_argument('--tokens', default=1, type=int)
    parser.add_argument('--channels-per-node', default=2, type=int)
    parser.add_argument('-p', '--profile', default=False, action='store_true')
    parser.add_argument('--pdb', default=False, action='store_true')
    parser.add_argument('--throughput',
                        dest='throughput',
                        action='store_true',
                        default=True)
    parser.add_argument('--latency', dest='throughput', action='store_false')
    parser.add_argument('--log', action='store_true', default=False)
    args = parser.parse_args()

    if args.log:
        slogging.configure(':DEBUG')

    if args.profile:
        import GreenletProfiler
        GreenletProfiler.set_clock_type('cpu')
        GreenletProfiler.start()

    tokens = [
        sha3('token:{}'.format(number).encode())[:20]
        for number in range(args.tokens)
    ]

    amount = 10
    apps = setup_apps(
        amount,
        tokens,
        args.transfers,
        args.nodes,
        args.channels_per_node,
    )

    if args.pdb:
        from raiden.utils.debug import enable_greenlet_debugger
        enable_greenlet_debugger()

        try:
            if args.throughput:
                test_throughput(apps, tokens, args.transfers, amount)
            else:
                test_latency(apps, tokens, args.transfers, amount)
        except:  # noqa
            import pdb
            pdb.xpm()
    else:
        if args.throughput:
            test_throughput(apps, tokens, args.transfers, amount)
        else:
            test_latency(apps, tokens, args.transfers, amount)

    if args.profile:
        GreenletProfiler.stop()
        stats = GreenletProfiler.get_func_stats()
        pstats = GreenletProfiler.convert2pstats(stats)

        print_serialization(pstats)
        print_slow_path(pstats)
        print_slow_function(pstats)

        pstats.sort_stats('time').print_stats()
示例#34
0
def test_settled_lock(tokens_addresses, raiden_network, settle_timeout, reveal_timeout):
    """ Any transfer following a secret revealed must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    token = tokens_addresses[0]
    amount = 30

    app0, app1, app2, _ = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    address0 = app0.raiden.address
    address1 = app1.raiden.address

    # mediated transfer
    identifier = 1
    expiration = app0.raiden.chain.block_number() + settle_timeout - reveal_timeout
    secret = pending_mediated_transfer(
        raiden_network,
        token,
        amount,
        identifier,
        expiration,
    )
    hashlock = sha3(secret)

    # get a proof for the pending transfer
    back_channel = channel(app1, app0, token)
    secret_transfer = get_received_transfer(back_channel, 0)
    lock = back_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = back_channel.our_state.balance_proof.compute_proof_for_lock(secret, lock)

    # reveal the secret
    claim_lock(raiden_network, token, secret)

    # a new transfer to update the hashlock
    direct_transfer(app0, app1, token, amount)

    forward_channel = channel(app0, app1, token)
    last_transfer = get_sent_transfer(forward_channel, 1)

    # call close giving the secret for a transfer that has being revealed
    back_channel.external_state.netting_channel.close(
        app1.raiden.address,
        last_transfer,
    )

    # check that the double unlock will failed
    with pytest.raises(Exception):
        back_channel.external_state.netting_channel.unlock(
            app1.raiden.address,
            [(unlock_proof, secret_transfer.lock.as_bytes, secret)],
        )

    # forward the block number to allow settle
    settle_expiration = app2.raiden.chain.block_number() + settle_timeout
    wait_until_block(app2.raiden.chain, settle_expiration)

    back_channel.external_state.netting_channel.settle()

    participant0 = back_channel.external_state.netting_channel.contract.participants[address0]
    participant1 = back_channel.external_state.netting_channel.contract.participants[address1]

    assert participant0.netted == participant0.deposit - amount * 2
    assert participant1.netted == participant1.deposit + amount * 2
示例#35
0
def test_start_end_attack(token_addresses, raiden_chain, deposit,
                          reveal_timeout):
    """ An attacker can try to steal tokens 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 known 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 token but for him to be
    unable to require the token A1.
    """
    amount = 30

    token = token_addresses[0]
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    # the attacker owns app0 and app2 and creates a transfer through app1
    identifier = 1
    expiration = reveal_timeout + 5
    secret = pending_mediated_transfer(raiden_chain, token, amount, identifier,
                                       expiration)
    hashlock = sha3(secret)

    attack_channel = channel(app2, app1, token)
    attack_transfer = get_received_transfer(attack_channel, 0)
    attack_contract = attack_channel.external_state.netting_channel.address
    hub_contract = channel(app1, app0,
                           token).external_state.netting_channel.address

    # the attacker can create a merkle proof of the locked transfer
    lock = attack_channel.partner_state.get_lock_by_hashlock(hashlock)
    unlock_proof = attack_channel.partner_state.compute_proof_for_lock(
        secret, lock)

    # start the settle counter
    attack_balance_proof = attack_transfer.to_balanceproof()
    attack_channel.netting_channel.close(attack_balance_proof)

    # wait until the last block to reveal the secret, hopefully we are not
    # missing a block during the test
    wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1)

    # since the attacker knows the secret he can net the lock
    attack_channel.netting_channel.withdraw(
        [(unlock_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 token from the channel A1 - H

    # the attacker settle the contract
    app2.raiden.chain.next_block()

    attack_channel.netting_channel.settle(token, attack_contract)

    # at this point the attack has the "stolen" funds
    attack_contract = app2.raiden.chain.token_hashchannel[token][
        attack_contract]
    assert attack_contract.participants[
        app2.raiden.address]['netted'] == deposit + amount
    assert attack_contract.participants[
        app1.raiden.address]['netted'] == deposit - amount

    # and the hub's channel A1-H doesn't
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[app0.raiden.address]['netted'] == deposit
    assert hub_contract.participants[app1.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 token
    # 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
    app1.raiden.chain.next_block()

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

    # the hub has acquired its token
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[
        app0.raiden.address]['netted'] == deposit + amount
    assert hub_contract.participants[
        app1.raiden.address]['netted'] == deposit - amount
示例#36
0
def test_interwoven_transfers(number_of_transfers, raiden_network,
                              settle_timeout):
    """ Can keep doing transactions even if not all secrets have been released. """
    def log_state():
        unclaimed = [
            transfer.lock.amount for pos, transfer in enumerate(transfers_list)
            if not transfers_claimed[pos]
        ]

        claimed = [
            transfer.lock.amount for pos, transfer in enumerate(transfers_list)
            if transfers_claimed[pos]
        ]
        log.info(
            'interwoven',
            claimed_amount=claimed_amount,
            distributed_amount=distributed_amount,
            claimed=claimed,
            unclaimed=unclaimed,
        )

    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    graph0 = app0.raiden.channelgraphs.values()[0]
    graph1 = app1.raiden.channelgraphs.values()[0]

    channel0 = graph0.partneraddress_channel.values()[0]
    channel1 = graph1.partneraddress_channel.values()[0]

    contract_balance0 = channel0.contract_balance
    contract_balance1 = channel1.contract_balance

    unclaimed_locks = []
    transfers_list = []
    transfers_claimed = []

    # start at 1 because we can't use amount=0
    transfers_amount = [i for i in range(1, number_of_transfers + 1)]
    transfers_secret = [str(i) for i in range(number_of_transfers)]

    claimed_amount = 0
    distributed_amount = 0

    for i, (amount,
            secret) in enumerate(zip(transfers_amount, transfers_secret)):
        block_number = app0.raiden.chain.block_number()
        expiration = block_number + settle_timeout - 1
        mediated_transfer = channel0.create_mediatedtransfer(
            transfer_initiator=app0.raiden.address,
            transfer_target=app1.raiden.address,
            fee=0,
            amount=amount,
            identifier=1,
            expiration=expiration,
            hashlock=sha3(secret),
        )

        # synchronized registration
        app0.raiden.sign(mediated_transfer)
        channel0.register_transfer(mediated_transfer)
        channel1.register_transfer(mediated_transfer)

        # update test state
        distributed_amount += amount
        transfers_claimed.append(False)
        transfers_list.append(mediated_transfer)
        unclaimed_locks.append(mediated_transfer.lock)

        log_state()

        # test the synchronization and values
        assert_synched_channels(
            channel0,
            contract_balance0 - claimed_amount,
            [],
            channel1,
            contract_balance1 + claimed_amount,
            unclaimed_locks,
        )
        assert channel0.distributable == contract_balance0 - distributed_amount

        # claim a transaction at every other iteration, leaving the current one
        # in place
        if i > 0 and i % 2 == 0:
            transfer = transfers_list[i - 1]
            secret = transfers_secret[i - 1]

            # synchronized clamining
            channel0.release_lock(secret)
            channel1.withdraw_lock(secret)

            # update test state
            claimed_amount += transfer.lock.amount
            transfers_claimed[i - 1] = True
            unclaimed_locks = [
                unclaimed_transfer.lock
                for pos, unclaimed_transfer in enumerate(transfers_list)
                if not transfers_claimed[pos]
            ]

            log_state()

            # test the state of the channels after the claim
            assert_synched_channels(
                channel0,
                contract_balance0 - claimed_amount,
                [],
                channel1,
                contract_balance1 + claimed_amount,
                unclaimed_locks,
            )
            assert channel0.distributable == contract_balance0 - distributed_amount
示例#37
0
 def secrethash(self):
     return sha3(self.secret)
示例#38
0
def run_test_start_end_attack(token_addresses, raiden_chain, deposit):
    """ An attacker can try to steal tokens 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 known secret and reveal to close and settle the channel H-A2,
    without revealing the secret to H's raiden node.

    The intention is to make the hub transfer the token but for him to be
    unable to require the token A1."""
    amount = 30

    token = token_addresses[0]
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address, token
    )
    hold_event_handler = app2.raiden.raiden_event_handler

    # the attacker owns app0 and app2 and creates a transfer through app1
    identifier = 1
    target = app2.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=amount,
        fee=0,
        target=target,
        identifier=identifier,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=secret,
    )

    gevent.sleep(1)  # wait for the messages to be exchanged

    attack_channel = get_channelstate(app2, app1, token_network_identifier)
    attack_transfer = None  # TODO
    attack_contract = attack_channel.external_state.netting_channel.address
    hub_contract = get_channelstate(
        app1, app0, token_network_identifier
    ).external_state.netting_channel.address

    # the attacker can create a merkle proof of the locked transfer
    # <the commented code below is left for documentation purposes>
    # lock = attack_channel.partner_state.get_lock_by_secrethash(secrethash)
    # unlock_proof = attack_channel.partner_state.compute_proof_for_lock(secret, lock)

    # start the settle counter
    attack_balance_proof = attack_transfer.to_balanceproof()
    attack_channel.netting_channel.channel_close(attack_balance_proof)

    # wait until the last block to reveal the secret, hopefully we are not
    # missing a block during the test
    app2.raiden.chain.wait_until_block(target_block_number=attack_transfer.lock.expiration - 1)

    # since the attacker knows the secret he can net the lock
    # <the commented code below is left for documentation purposes>
    # attack_channel.netting_channel.unlock(
    #     UnlockProofState(unlock_proof, attack_transfer.lock, secret)
    # )
    # XXX: verify that the secret was publicized

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

    # the attacker settles the contract
    app2.raiden.chain.next_block()

    attack_channel.netting_channel.settle(token, attack_contract)

    # at this point the attacker has the "stolen" funds
    attack_contract = app2.raiden.chain.token_hashchannel[token][attack_contract]
    assert attack_contract.participants[app2.raiden.address]["netted"] == deposit + amount
    assert attack_contract.participants[app1.raiden.address]["netted"] == deposit - amount

    # and the hub's channel A1-H doesn't
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[app0.raiden.address]["netted"] == deposit
    assert hub_contract.participants[app1.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. For A2 to acquire the token
    # it needs to make the secret public in the blockchain so it publishes the
    # secret through an event and the Hub is able to require its funds
    app1.raiden.chain.next_block()

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

    # the hub has acquired its token
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[app0.raiden.address]["netted"] == deposit + amount
    assert hub_contract.participants[app1.raiden.address]["netted"] == deposit - amount
示例#39
0
def run_test_batch_unlock_after_restart(raiden_network, token_addresses, deposit):
    """Simulate the case where:
    - A sends B a transfer
    - B sends A a transfer
    - Secrets were never revealed
    - B closes channel
    - A crashes
    - Wait for settle
    - Wait for unlock from B
    - Restart A
    At this point, the current unlock logic will try to unlock
    iff the node gains from unlocking. Which means that the node will try to unlock
    either side. In the above scenario, each node will unlock its side.
    This test makes sure that we do NOT invalidate A's unlock transaction based
    on the ContractReceiveChannelBatchUnlock caused by B's unlock.
    """
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=views.state_from_app(alice_app),
        payment_network_id=alice_app.raiden.default_registry.address,
        token_address=token_address,
    )
    timeout = 10

    token_network = views.get_token_network_by_identifier(
        chain_state=views.state_from_app(alice_app), token_network_id=token_network_identifier
    )

    channel_identifier = get_channelstate(alice_app, bob_app, token_network_identifier).identifier

    assert (
        channel_identifier
        in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address]
    )

    alice_to_bob_amount = 10
    identifier = 1

    alice_transfer_secret = sha3(alice_app.raiden.address)
    alice_transfer_secrethash = sha3(alice_transfer_secret)

    bob_transfer_secret = sha3(bob_app.raiden.address)
    bob_transfer_secrethash = sha3(bob_transfer_secret)

    alice_transfer_hold = bob_app.raiden.raiden_event_handler.hold_secretrequest_for(
        secrethash=alice_transfer_secrethash
    )
    bob_transfer_hold = alice_app.raiden.raiden_event_handler.hold_secretrequest_for(
        secrethash=bob_transfer_secrethash
    )

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=bob_app.raiden.address,
        identifier=identifier,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=alice_transfer_secret,
    )

    bob_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=alice_app.raiden.address,
        identifier=identifier + 1,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=bob_transfer_secret,
    )

    alice_transfer_hold.wait(timeout=timeout)
    bob_transfer_hold.wait(timeout=timeout)

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    alice_lock = channel.get_lock(alice_bob_channel_state.our_state, alice_transfer_secrethash)
    bob_lock = channel.get_lock(alice_bob_channel_state.partner_state, bob_transfer_secrethash)

    # This is the current state of protocol:
    #
    #    A -> B LockedTransfer
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier=token_network_identifier,
        app0=alice_app,
        balance0=deposit,
        pending_locks0=[alice_lock],
        app1=bob_app,
        balance1=deposit,
        pending_locks1=[bob_lock],
    )

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=alice_app.raiden.address,
    )

    # wait for the close transaction to be mined, this is necessary to compute
    # the timeout for the settle
    with gevent.Timeout(timeout):
        waiting.wait_for_close(
            raiden=alice_app.raiden,
            payment_network_id=registry_address,
            token_address=token_address,
            channel_ids=[alice_bob_channel_state.identifier],
            retry_timeout=alice_app.raiden.alarm.sleep_time,
        )

    channel_closed = raiden_state_changes_search_for_item(
        bob_app.raiden,
        ContractReceiveChannelClosed,
        {
            "canonical_identifier": {
                "token_network_address": token_network_identifier,
                "channel_identifier": alice_bob_channel_state.identifier,
            }
        },
    )
    settle_max_wait_block = (
        channel_closed.block_number + alice_bob_channel_state.settle_timeout * 2
    )

    settle_timeout = BlockTimeout(
        RuntimeError("settle did not happen"),
        bob_app.raiden,
        settle_max_wait_block,
        alice_app.raiden.alarm.sleep_time,
    )
    with settle_timeout:
        waiting.wait_for_settle(
            raiden=alice_app.raiden,
            payment_network_id=registry_address,
            token_address=token_address,
            channel_ids=[alice_bob_channel_state.identifier],
            retry_timeout=alice_app.raiden.alarm.sleep_time,
        )

    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            app=bob_app,
            token_network_id=token_network_identifier,
            participant=alice_bob_channel_state.partner_state.address,
            partner=alice_bob_channel_state.our_state.address,
        )

    alice_app.start()

    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            app=alice_app,
            token_network_id=token_network_identifier,
            participant=alice_bob_channel_state.partner_state.address,
            partner=alice_bob_channel_state.our_state.address,
        )
示例#40
0
def run_test_settled_lock(token_addresses, raiden_network, deposit):
    """ Any transfer following a secret reveal must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = 30
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address, token_address
    )
    hold_event_handler = app1.raiden.raiden_event_handler

    address0 = app0.raiden.address
    address1 = app1.raiden.address

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)
    identifier = 1
    target = app1.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    secret_available = hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=amount,
        fee=0,
        target=target,
        identifier=identifier,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=secret,
    )

    secret_available.wait()  # wait for the messages to be exchanged

    # Save the merkle tree leaves from the pending transfer, used to test the unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)
    batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state)
    assert batch_unlock

    hold_event_handler.release_secretrequest_for(app1.raiden, secrethash)

    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount,
        identifier=2,
    )

    RaidenAPI(app1.raiden).channel_close(registry_address, token_address, app0.raiden.address)

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.sleep_time,
    )

    netting_channel = app1.raiden.chain.payment_channel(
        canonical_identifier=channelstate_0_1.canonical_identifier
    )

    # The transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    with pytest.raises(RaidenUnrecoverableError):
        netting_channel.unlock(
            merkle_tree_leaves=batch_unlock,
            participant=channelstate_0_1.our_state.address,
            partner=channelstate_0_1.partner_state.address,
        )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
示例#41
0
def run_test_batch_unlock(
    raiden_network, token_addresses, secret_registry_address, deposit, blockchain_type
):
    """Batch unlock can be called after the channel is settled."""
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_proxy = alice_app.raiden.chain.token(token_address)
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address
    )

    hold_event_handler = bob_app.raiden.raiden_event_handler

    # Take a snapshot early on
    alice_app.raiden.wal.snapshot()

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(alice_app), token_network_identifier
    )

    channel_identifier = get_channelstate(alice_app, bob_app, token_network_identifier).identifier

    assert (
        channel_identifier
        in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address]
    )

    alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    # Take snapshot before transfer
    alice_app.raiden.wal.snapshot()

    alice_to_bob_amount = 10
    identifier = 1
    target = bob_app.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    secret_request_event = hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=target,
        identifier=identifier,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=secret,
    )

    secret_request_event.get()  # wait for the messages to be exchanged

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier, alice_app, deposit, [lock], bob_app, deposit, []
    )

    # Take a snapshot early on
    alice_app.raiden.wal.snapshot()

    our_balance_proof = alice_bob_channel_state.our_state.balance_proof

    # Test WAL restore to return the latest channel state
    restored_channel_state = channel_state_until_state_change(
        raiden=alice_app.raiden,
        canonical_identifier=alice_bob_channel_state.canonical_identifier,
        state_change_identifier="latest",
    )

    our_restored_balance_proof = restored_channel_state.our_state.balance_proof
    assert our_balance_proof == our_restored_balance_proof

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address, token_address, alice_app.raiden.address
    )

    secret_registry_proxy = alice_app.raiden.chain.secret_registry(secret_registry_address)
    secret_registry_proxy.register_secret(secret=secret)

    assert lock, "the lock must still be part of the node state"
    msg = "the secret must be registered before the lock expires"
    assert lock.expiration > alice_app.raiden.get_block_number(), msg
    assert lock.secrethash == sha3(secret)

    waiting.wait_for_settle(
        alice_app.raiden,
        registry_address,
        token_address,
        [alice_bob_channel_state.identifier],
        alice_app.raiden.alarm.sleep_time,
    )

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(bob_app), token_network_identifier
    )

    assert (
        channel_identifier
        in token_network.partneraddresses_to_channelidentifiers[alice_app.raiden.address]
    )

    # Wait for both nodes to call batch unlock
    timeout = 30 if blockchain_type == "parity" else 10
    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            app=bob_app,
            token_network_id=token_network_identifier,
            participant=alice_bob_channel_state.partner_state.address,
            partner=alice_bob_channel_state.our_state.address,
        )

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(bob_app), token_network_identifier
    )

    assert (
        channel_identifier
        not in token_network.partneraddresses_to_channelidentifiers[alice_app.raiden.address]
    )

    alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount
    bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount

    assert token_proxy.balance_of(alice_app.raiden.address) == alice_new_balance
    assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
示例#42
0
def test_regression_multiple_revealsecret(raiden_network, token_addresses):
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Secret handling followed these steps:

        The Secret message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given hashlock

    The step marked with an asterisk above introduced a context-switch, this
    allowed a second Reveal Secret message to be handled before the channel was
    unregistered, because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = token_addresses[0]

    identifier = 1
    secret = sha3('test_regression_multiple_revealsecret')
    hashlock = sha3(secret)
    expiration = app0.raiden.get_block_number() + 100
    amount = 10

    mediated_transfer = channel(app0, app1, token).create_mediatedtransfer(
        transfer_initiator=app0.raiden.address,
        transfer_target=app1.raiden.address,
        fee=0,
        amount=amount,
        identifier=identifier,
        expiration=expiration,
        hashlock=hashlock,
    )
    app0.raiden.sign(mediated_transfer)

    message_data = mediated_transfer.encode()
    app1.raiden.protocol.receive(message_data)

    reveal_secret = RevealSecret(secret)
    app0.raiden.sign(reveal_secret)
    reveal_secret_data = reveal_secret.encode()

    secret = Secret(
        identifier=identifier,
        nonce=mediated_transfer.nonce + 1,
        channel=channel(app0, app1, token).channel_address,
        transferred_amount=amount,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=secret,
    )
    app0.raiden.sign(secret)
    secret_data = secret.encode()

    messages = [
        secret_data,
        reveal_secret_data,
    ]

    wait = [
        gevent.spawn_later(
            .1,
            app1.raiden.protocol.receive,
            data,
        ) for data in messages
    ]

    gevent.joinall(wait)
示例#43
0
 def hashlock(self):
     if self._hashlock is None:
         self._hashlock = sha3(self.secret)
     return self._hashlock
示例#44
0
 def hash(self):
     packed = self.packed()
     return sha3(packed.data)
示例#45
0
def test_settlement(raiden_network, settle_timeout, reveal_timeout):
    alice_app, bob_app = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    alice_graph = alice_app.raiden.token_to_channelgraph.values()[0]
    bob_graph = bob_app.raiden.token_to_channelgraph.values()[0]
    assert alice_graph.token_address == bob_graph.token_address

    alice_bob_channel = alice_graph.partneraddress_to_channel[
        bob_app.raiden.address]
    bob_alice_channel = bob_graph.partneraddress_to_channel[
        alice_app.raiden.address]

    alice_deposit = alice_bob_channel.balance
    bob_deposit = bob_alice_channel.balance

    token = alice_app.raiden.chain.token(alice_bob_channel.token_address)

    alice_balance = token.balance_of(alice_app.raiden.address)
    bob_balance = token.balance_of(bob_app.raiden.address)

    alice_chain = alice_app.raiden.chain

    alice_to_bob_amount = 10
    expiration = alice_app.raiden.chain.block_number() + reveal_timeout + 1
    secret = 'secretsecretsecretsecretsecretse'
    hashlock = sha3(secret)

    assert bob_app.raiden.address in alice_graph.partneraddress_to_channel

    nettingaddress0 = alice_bob_channel.external_state.netting_channel.address
    nettingaddress1 = bob_alice_channel.external_state.netting_channel.address
    assert nettingaddress0 == nettingaddress1

    identifier = 1
    fee = 0
    transfermessage = alice_bob_channel.create_mediatedtransfer(
        alice_app.raiden.address,
        bob_app.raiden.address,
        fee,
        alice_to_bob_amount,
        identifier,
        expiration,
        hashlock,
    )
    alice_app.raiden.sign(transfermessage)
    alice_bob_channel.register_transfer(
        alice_app.raiden.get_block_number(),
        transfermessage,
    )
    bob_alice_channel.register_transfer(
        bob_app.raiden.get_block_number(),
        transfermessage,
    )

    assert_synched_channels(
        alice_bob_channel,
        alice_deposit,
        [],
        bob_alice_channel,
        bob_deposit,
        [transfermessage.lock],
    )

    # At this point we are assuming the following:
    #
    #    A -> B MediatedTransfer
    #    B -> A SecretRequest
    #    A -> B RevealSecret
    #    - protocol didn't continue
    #
    # B knowns the secret but doesn't have an updated balance proof, B needs to
    # call settle.

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = bob_alice_channel.partner_state.get_lock_by_hashlock(hashlock)
    assert sha3(secret) == hashlock
    unlock_proof = bob_alice_channel.partner_state.compute_proof_for_lock(
        secret, lock)

    root = merkleroot(bob_alice_channel.partner_state.merkletree)

    assert validate_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    # a ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    balance_proof = transfermessage.to_balanceproof()
    bob_alice_channel.external_state.close(balance_proof)
    wait_until_block(alice_chain, alice_chain.block_number() + 1)

    assert alice_bob_channel.external_state.close_event.wait(timeout=15)
    assert bob_alice_channel.external_state.close_event.wait(timeout=15)

    assert alice_bob_channel.external_state.closed_block != 0
    assert bob_alice_channel.external_state.closed_block != 0
    assert alice_bob_channel.external_state.settled_block == 0
    assert bob_alice_channel.external_state.settled_block == 0

    # unlock will not be called by Channel.channel_closed because we did not
    # register the secret
    assert lock.expiration > alice_app.raiden.chain.block_number()
    assert lock.hashlock == sha3(secret)

    bob_alice_channel.external_state.netting_channel.withdraw([unlock_proof])

    settle_expiration = alice_chain.block_number() + settle_timeout + 2
    wait_until_block(alice_chain, settle_expiration)

    assert alice_bob_channel.external_state.settle_event.wait(timeout=15)
    assert bob_alice_channel.external_state.settle_event.wait(timeout=15)
    # settle must be called by the apps triggered by the ChannelClose event,
    # and the channels must update it's state based on the ChannelSettled event
    assert alice_bob_channel.external_state.settled_block != 0
    assert bob_alice_channel.external_state.settled_block != 0

    address0 = alice_app.raiden.address
    address1 = bob_app.raiden.address

    alice_netted_balance = alice_balance + alice_deposit - alice_to_bob_amount
    bob_netted_balance = bob_balance + bob_deposit + alice_to_bob_amount

    assert token.balance_of(address0) == alice_netted_balance
    assert token.balance_of(address1) == bob_netted_balance

    # Now let's query the WAL to see if the state changes were logged as expected
    state_changes = [
        change[1]
        for change in get_all_state_changes(alice_app.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]

    assert must_contain_entry(
        state_changes, ContractReceiveClosed, {
            'channel_address': nettingaddress0,
            'closing_address': bob_app.raiden.address,
            'block_number': alice_bob_channel.external_state.closed_block,
        })

    assert must_contain_entry(state_changes, ReceiveSecretReveal, {
        'secret': secret,
        'sender': bob_app.raiden.address,
    })

    assert must_contain_entry(
        state_changes, ContractReceiveWithdraw, {
            'channel_address': nettingaddress0,
            'secret': secret,
            'receiver': bob_app.raiden.address,
        })

    assert must_contain_entry(
        state_changes, ContractReceiveSettled, {
            'channel_address': nettingaddress0,
            'block_number': bob_alice_channel.external_state.settled_block,
        })
示例#46
0
def address_from_key(key):
    return sha3(key[1:])[-20:]
示例#47
0
def test_python_channel():
    netting_channel = NettingChannelMock()
    token_address = make_address()
    privkey1, address1 = make_privkey_address()
    address2 = make_address()

    balance1 = 70
    balance2 = 110

    reveal_timeout = 5
    settle_timeout = 15
    block_number = 10

    our_state = ChannelEndState(address1, balance1, netting_channel.opened())
    partner_state = ChannelEndState(address2, balance2,
                                    netting_channel.opened())
    external_state = make_external_state()

    test_channel = Channel(
        our_state,
        partner_state,
        external_state,
        token_address,
        reveal_timeout,
        settle_timeout,
        block_number,
    )

    assert test_channel.contract_balance == our_state.contract_balance
    assert test_channel.balance == our_state.balance(partner_state)
    assert test_channel.transferred_amount == our_state.transferred_amount
    assert test_channel.distributable == our_state.distributable(partner_state)
    assert test_channel.outstanding == our_state.locked()
    assert test_channel.outstanding == 0
    assert test_channel.locked == partner_state.locked()
    assert test_channel.our_state.locked() == 0
    assert test_channel.partner_state.locked() == 0

    with pytest.raises(ValueError):
        test_channel.create_directtransfer(
            -10,
            identifier=1,
        )

    with pytest.raises(ValueError):
        test_channel.create_directtransfer(
            balance1 + 10,
            identifier=1,
        )

    amount1 = 10
    directtransfer = test_channel.create_directtransfer(
        amount1,
        identifier=1,
    )
    directtransfer.sign(privkey1, address1)
    test_channel.register_transfer(directtransfer)

    assert test_channel.contract_balance == balance1
    assert test_channel.balance == balance1 - amount1
    assert test_channel.transferred_amount == amount1
    assert test_channel.distributable == balance1 - amount1
    assert test_channel.outstanding == 0
    assert test_channel.locked == 0
    assert test_channel.our_state.locked() == 0
    assert test_channel.partner_state.locked() == 0

    secret = sha3('test_channel')
    hashlock = sha3(secret)
    amount2 = 10
    fee = 0
    expiration = block_number + settle_timeout - 5
    identifier = 1
    mediatedtransfer = test_channel.create_mediatedtransfer(
        address1,
        address2,
        fee,
        amount2,
        identifier,
        expiration,
        hashlock,
    )
    mediatedtransfer.sign(privkey1, address1)

    test_channel.register_transfer(mediatedtransfer)

    assert test_channel.contract_balance == balance1
    assert test_channel.balance == balance1 - amount1
    assert test_channel.transferred_amount == amount1
    assert test_channel.distributable == balance1 - amount1 - amount2
    assert test_channel.outstanding == 0
    assert test_channel.locked == amount2
    assert test_channel.our_state.locked() == 0
    assert test_channel.partner_state.locked() == amount2

    test_channel.release_lock(secret)

    assert test_channel.contract_balance == balance1
    assert test_channel.balance == balance1 - amount1 - amount2
    assert test_channel.transferred_amount == amount1 + amount2
    assert test_channel.distributable == balance1 - amount1 - amount2
    assert test_channel.outstanding == 0
    assert test_channel.locked == 0
    assert test_channel.our_state.locked() == 0
    assert test_channel.partner_state.locked() == 0
示例#48
0
def test_register_invalid_transfer(raiden_network, settle_timeout):
    """ Regression test for registration of invalid transfer.

    The bug occurred if a transfer with an invalid allowance but a valid secret
    was registered, when the local end registered the transfer it would
    "unlock" the partners' token, but the transfer wouldn't be sent because the
    allowance check failed, leaving the channel in an inconsistent state.
    """
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    graph0 = app0.raiden.channelgraphs.values()[0]
    graph1 = app1.raiden.channelgraphs.values()[0]

    channel0 = graph0.partneraddress_channel.values()[0]
    channel1 = graph1.partneraddress_channel.values()[0]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    block_number = app0.raiden.chain.block_number()
    expiration = block_number + settle_timeout - 1

    secret = 'secret'
    hashlock = sha3(secret)

    transfer1 = channel0.create_mediatedtransfer(
        transfer_initiator=app0.raiden.address,
        transfer_target=app1.raiden.address,
        fee=0,
        amount=amount,
        identifier=1,
        expiration=expiration,
        hashlock=hashlock,
    )

    # register a locked transfer
    app0.raiden.sign(transfer1)
    channel0.register_transfer(transfer1)
    channel1.register_transfer(transfer1)

    # assert the locked transfer is registered
    assert_synched_channels(
        channel0,
        balance0,
        [],
        channel1,
        balance1,
        [transfer1.lock],
    )

    # handcrafted transfer because channel.create_transfer won't create it
    transfer2 = DirectTransfer(
        1,  # TODO: fill in identifier
        nonce=channel0.our_state.nonce,
        token=channel0.token_address,
        transferred_amount=channel1.balance + balance0 + amount,
        recipient=channel0.partner_state.address,
        locksroot=channel0.partner_state.balance_proof.
        merkleroot_for_unclaimed(),
    )
    app0.raiden.sign(transfer2)

    # this need to fail because the allowance is incorrect
    with pytest.raises(Exception):
        channel0.register_transfer(transfer2)

    with pytest.raises(Exception):
        channel1.register_transfer(transfer2)

    # the registration of a bad transfer need fail equaly on both channels
    assert_synched_channels(
        channel0,
        balance0,
        [],
        channel1,
        balance1,
        [transfer1.lock],
    )
示例#49
0
def test_settled_lock(token_addresses, raiden_network, settle_timeout,
                      reveal_timeout):
    """ Any transfer following a secret revealed must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    token = token_addresses[0]
    amount = 30

    app0, app1, app2, _ = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    address0 = app0.raiden.address
    address1 = app1.raiden.address

    forward_channel = channel(app0, app1, token)
    back_channel = channel(app1, app0, token)

    deposit0 = forward_channel.contract_balance
    deposit1 = back_channel.contract_balance

    token_contract = app0.raiden.chain.token(token)
    balance0 = token_contract.balance_of(address0)
    balance1 = token_contract.balance_of(address1)

    # A pending mediated transfer
    identifier = 1
    expiration = app0.raiden.chain.block_number(
    ) + settle_timeout - reveal_timeout
    secret = pending_mediated_transfer(
        raiden_network,
        token,
        amount,
        identifier,
        expiration,
    )
    hashlock = sha3(secret)

    # Get the proof to unlock the pending lock
    secret_transfer = get_received_transfer(back_channel, 0)
    lock = back_channel.partner_state.get_lock_by_hashlock(hashlock)
    unlock_proof = back_channel.partner_state.compute_proof_for_lock(
        secret, lock)

    # Update the hashlock
    claim_lock(raiden_network, identifier, token, secret)
    direct_transfer(app0, app1, token, amount, identifier=1)

    # The direct transfer locksroot must remove the unlocked lock and update
    # the transferred amount, the withdraw must fail.
    balance_proof = back_channel.partner_state.balance_proof
    back_channel.external_state.close(balance_proof)
    with pytest.raises(Exception):
        back_channel.external_state.netting_channel.withdraw(
            [(unlock_proof, secret_transfer.lock.as_bytes, secret)], )

    settle_expiration = app2.raiden.chain.block_number() + settle_timeout
    wait_until_block(app2.raiden.chain, settle_expiration)
    back_channel.external_state.netting_channel.settle()

    assert token_contract.balance_of(
        address0) == balance0 + deposit0 - amount * 2
    assert token_contract.balance_of(
        address1) == balance1 + deposit1 + amount * 2
示例#50
0
def pending_mediated_transfer(app_chain, token_network_identifier, amount,
                              identifier):
    """ Nice to read shortcut to make a LockedTransfer where the secret is _not_ revealed.

    While the secret is not revealed all apps will be synchronized, meaning
    they are all going to receive the LockedTransfer message.
    Returns:
        The secret used to generate the LockedTransfer
    """
    # pylint: disable=too-many-locals

    if len(app_chain) < 2:
        raise ValueError(
            'Cannot make a LockedTransfer with less than two apps')

    target = app_chain[-1].raiden.address

    # Generate a secret
    initiator_channel = views.get_channelstate_by_token_network_and_partner(
        views.state_from_app(app_chain[0]),
        token_network_identifier,
        app_chain[1].raiden.address,
    )
    address = initiator_channel.identifier
    nonce_int = channel.get_next_nonce(initiator_channel.our_state)
    nonce_bytes = nonce_int.to_bytes(2, 'big')
    secret = sha3(address + nonce_bytes)

    initiator_app = app_chain[0]
    init_initiator_statechange = initiator_init(
        initiator_app.raiden,
        identifier,
        amount,
        secret,
        token_network_identifier,
        target,
    )
    events = initiator_app.raiden.wal.log_and_dispatch(
        init_initiator_statechange,
        initiator_app.raiden.get_block_number(),
    )
    send_transfermessage = must_contain_entry(events, SendLockedTransfer, {})
    transfermessage = LockedTransfer.from_event(send_transfermessage)
    initiator_app.raiden.sign(transfermessage)

    for mediator_app in app_chain[1:-1]:
        mediator_init_statechange = mediator_init(mediator_app.raiden,
                                                  transfermessage)
        events = mediator_app.raiden.wal.log_and_dispatch(
            mediator_init_statechange,
            mediator_app.raiden.get_block_number(),
        )
        send_transfermessage = must_contain_entry(events, SendLockedTransfer,
                                                  {})
        transfermessage = LockedTransfer.from_event(send_transfermessage)
        mediator_app.raiden.sign(transfermessage)

    target_app = app_chain[-1]
    mediator_init_statechange = target_init(transfermessage)
    events = target_app.raiden.wal.log_and_dispatch(
        mediator_init_statechange,
        target_app.raiden.get_block_number(),
    )
    return secret
示例#51
0
    def send_and_wait_valid(self, raiden, mediated_transfer, maker_payer_hop):
        """ Start the second half of the exchange and wait for the SecretReveal
        for it.

        This will send the taker mediated transfer with the maker as a target,
        once the maker receives the transfer he is expected to send a
        RevealSecret backwards.
        """

        # the taker cannot discard the transfer since the secret is controlled
        # by another node (the maker), so we have no option but to wait for a
        # valid response until the lock expires
        response_iterator = self._send_and_wait_block(
            raiden,
            mediated_transfer.recipient,
            mediated_transfer,
            mediated_transfer.lock.expiration,
        )

        # Usually the RevealSecret for the MediatedTransfer from this node to
        # the maker should arrive first, but depending on the number of hops
        # and if the maker-path is optimistically revealing the Secret, then
        # the Secret message might arrive first.
        secret = None

        for response in response_iterator:
            valid_reveal = (
                isinstance(response, RevealSecret) and
                response.hashlock == mediated_transfer.lock.hashlock and
                response.sender == maker_payer_hop
            )

            valid_refund = (
                isinstance(response, RefundTransfer) and
                response.sender == maker_payer_hop and
                response.lock.amount == mediated_transfer.lock.amount and
                response.lock.expiration <= mediated_transfer.lock.expiration and
                response.token == mediated_transfer.token
            )

            if response is None:
                log.error(
                    'TAKER SWAP TIMED OUT node:%s hashlock:%s',
                    pex(raiden.address),
                    pex(mediated_transfer.lock.hashlock),
                )
                return (response, secret)

            elif isinstance(response, Secret):
                if sha3(response.secret) != mediated_transfer.lock.hashlock:
                    log.error("Secret doesn't match the hashlock, ignoring.")
                    continue

                secret = response

            elif valid_reveal:
                return (response, secret)

            elif valid_refund:
                return (response, secret)

            elif log.isEnabledFor(logging.ERROR):
                log.error(
                    'Invalid message [%s] supplied to the task, ignoring.',
                    repr(response),
                )

        return (None, secret)
示例#52
0
import gevent
import networkx

from raiden.settings import DEFAULT_SETTLE_TIMEOUT
from raiden.app import App
from raiden.network.blockchain_service import BlockChainService
from raiden.network.discovery import Discovery
from raiden.network.rpc import JSONRPCClient
from raiden.utils import sha3, privatekey_to_address
from raiden.settings import (
    GAS_LIMIT,
    GAS_PRICE,
)

TRANSFER_AMOUNT = 1
TOKEN_ADDRESS = sha3('tps')[:20]


def hostport_to_privkeyaddr(host, port):
    """ Return `(private key, address)` deterministically generated. """
    myip_port = '{}:{}'.format(host, port)
    privkey = sha3(myip_port)
    addr = privatekey_to_address(privkey)

    return privkey, addr


def random_raiden_network(token_address, blockchain_service, node_addresses,
                          deposit, settle_timeout):
    """ Creates random channels among the test nodes until we have a connected graph. """
    graph = networkx.Graph()
示例#53
0
def transfer_speed(num_transfers=100, max_locked=100):  # pylint: disable=too-many-locals
    channels_per_node = 1
    num_nodes = 2
    num_tokens = 1

    private_keys = [
        sha3('speed:{}'.format(position)) for position in range(num_nodes)
    ]

    tokens = [
        sha3('token:{}'.format(number))[:20] for number in range(num_tokens)
    ]

    amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)]

    deposit = sum(amounts)

    secrets = [str(i) for i in range(num_transfers)]

    BlockChainServiceMock._instance = True
    blockchain_service = BlockChainServiceMock(None, MOCK_REGISTRY_ADDRESS)
    BlockChainServiceMock._instance = blockchain_service  # pylint: disable=redefined-variable-type

    registry = blockchain_service.registry(MOCK_REGISTRY_ADDRESS)
    for token in tokens:
        registry.add_token(token)

    apps = create_network(private_keys, tokens, MOCK_REGISTRY_ADDRESS,
                          channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT,
                          DEFAULT_POLL_TIMEOUT, UDPTransport,
                          BlockChainServiceMock)

    app0, app1 = apps  # pylint: disable=unbalanced-tuple-unpacking
    channel0 = app0.raiden.get_manager_by_token_address(
        tokens[0]).address_channel.values()[0]
    channel1 = app1.raiden.get_manager_by_token_address(
        tokens[0]).address_channel.values()[0]

    expiration = app0.raiden.chain.block_number() + DEFAULT_REVEAL_TIMEOUT + 3

    start = time.time()

    for i, amount in enumerate(amounts):
        hashlock = sha3(secrets[i])
        locked_transfer = channel0.create_lockedtransfer(
            amount=amount,
            identifier=1,  # TODO: fill in identifier
            expiration=expiration,
            hashlock=hashlock,
        )
        app0.raiden.sign(locked_transfer)
        channel0.register_transfer(locked_transfer)
        channel1.register_transfer(locked_transfer)

        if i > max_locked:
            idx = i - max_locked
            secret = secrets[idx]
            channel0.register_secret(secret)
            channel1.register_secret(secret)

    elapsed = time.time() - start
    print('%d transfers per second' % (num_transfers / elapsed))
示例#54
0
 def hash(self):
     warnings.warn('Expensive comparison called')
     packed = self.packed()
     return sha3(packed.data)
    merkleroot,
    compute_merkleproof_for,
)
from raiden.utils import get_project_root, sha3

# The computeMerkleRoot function only computes the proof regardless of what the
# hashes are encoding, so just use some arbitrary data to produce a merkle tree.
ARBITRARY_DATA = [letter * 32 for letter in string.ascii_uppercase[:7]]
FAKE_TREE = [
    ARBITRARY_DATA[:1],
    ARBITRARY_DATA[:2],
    ARBITRARY_DATA[:3],
    ARBITRARY_DATA[:7],
]

HASH = sha3('muchcodingsuchwow_______________')


def deploy_auxiliary_tester(tester_state,
                            tester_nettingchannel_library_address):
    contracts_path = os.path.join(get_project_root(), 'smart_contracts')
    raiden_remap = 'raiden={}'.format(contracts_path)

    auxiliary = tester_state.abi_contract(
        None,
        path=get_relative_contract(__file__, 'AuxiliaryTester.sol'),
        language='solidity',
        libraries={
            'NettingChannelLibrary':
            tester_nettingchannel_library_address.encode('hex')
        },
示例#56
0
 def lockhash(self):
     return sha3(self.as_bytes)
def run_test_mediated_transfer_messages_out_of_order(raiden_network, deposit,
                                                     token_addresses,
                                                     network_wait):
    """Raiden must properly handle repeated locked transfer messages."""
    app0, app1, app2 = raiden_network

    app1_wait_for_message = WaitForMessage()
    app2_wait_for_message = WaitForMessage()

    app1.raiden.message_handler = app1_wait_for_message
    app2.raiden.message_handler = app2_wait_for_message

    secret = factories.make_secret(0)
    secrethash = sha3(secret)

    # Save the messages, these will be processed again
    app1_mediatedtransfer = app1_wait_for_message.wait_for_message(
        LockedTransfer, {"lock": {
            "secrethash": secrethash
        }})
    app2_mediatedtransfer = app2_wait_for_message.wait_for_message(
        LockedTransfer, {"lock": {
            "secrethash": secrethash
        }})
    # Wait until the node receives a reveal secret to redispatch the locked
    # transfer message
    app1_revealsecret = app1_wait_for_message.wait_for_message(
        RevealSecret, {"secret": secret})
    app2_revealsecret = app2_wait_for_message.wait_for_message(
        RevealSecret, {"secret": secret})

    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state, payment_network_id, token_address)

    amount = 10
    identifier = 1
    transfer_received = app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=amount,
        fee=0,
        target=app2.raiden.address,
        identifier=identifier,
        secret=secret,
    )

    # - Wait until reveal secret is received to replay the message
    # - The secret is revealed backwards, app2 should be first
    # - The locked transfer is sent before the secret reveal, so the mediated
    #   transfers async results must be set and `get_nowait` can be used
    app2_revealsecret.get(timeout=network_wait)
    mediated_transfer_msg = app2_mediatedtransfer.get_nowait()
    app2.raiden.message_handler.handle_message_lockedtransfer(
        app2.raiden, mediated_transfer_msg)

    app1_revealsecret.get(timeout=network_wait)
    app1.raiden.message_handler.handle_message_lockedtransfer(
        app1.raiden, app1_mediatedtransfer.get_nowait())

    transfer_received.payment_done.wait()
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app1,
            deposit - amount,
            [],
            app2,
            deposit + amount,
            [],
        )
def run_test_mediated_transfer_with_node_consuming_more_than_allocated_fee(
        raiden_network, number_of_nodes, deposit, token_addresses,
        network_wait):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state, payment_network_id, token_address)
    fee = 5
    amount = 10

    app1_app2_channel_state = views.get_channelstate_by_token_network_and_partner(
        chain_state=views.state_from_raiden(app1.raiden),
        token_network_id=token_network_identifier,
        partner_address=app2.raiden.address,
    )

    # Let app1 consume all of the allocated mediation fee
    action_set_fee = ActionChannelSetFee(
        canonical_identifier=app1_app2_channel_state.canonical_identifier,
        mediation_fee=fee * 2)

    app1.raiden.handle_state_change(state_change=action_set_fee)

    secret = factories.make_secret(0)
    secrethash = sha3(secret)

    wait_message_handler = WaitForMessage()
    app0.raiden.message_handler = wait_message_handler
    secret_request_received = wait_message_handler.wait_for_message(
        SecretRequest, {"secrethash": secrethash})

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=amount,
        fee=fee,
        target=app2.raiden.address,
        identifier=1,
        secret=secret,
    )

    app0_app1_channel_state = views.get_channelstate_by_token_network_and_partner(
        chain_state=views.state_from_raiden(app0.raiden),
        token_network_id=token_network_identifier,
        partner_address=app1.raiden.address,
    )

    msg = "App0 should have the transfer in secrethashes_to_lockedlocks"
    assert secrethash in app0_app1_channel_state.our_state.secrethashes_to_lockedlocks, msg

    msg = "App0 should have locked the amount + fee"
    lock_amount = app0_app1_channel_state.our_state.secrethashes_to_lockedlocks[
        secrethash].amount
    assert lock_amount == amount + fee, msg

    secret_request_received.wait()

    app0_chain_state = views.state_from_app(app0)
    initiator_task = app0_chain_state.payment_mapping.secrethashes_to_task[
        secrethash]

    msg = "App0 should have never revealed the secret"
    assert initiator_task.manager_state.initiator_transfers[
        secrethash].revealsecret is None
示例#59
0
def run_test_lock_expiry(raiden_network, token_addresses, deposit):
    alice_app, bob_app = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address
    )

    hold_event_handler = bob_app.raiden.raiden_event_handler
    wait_message_handler = bob_app.raiden.message_handler

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(alice_app), token_network_identifier
    )

    channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    channel_identifier = channel_state.identifier

    assert (
        channel_identifier
        in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address]
    )

    alice_to_bob_amount = 10
    identifier = 1
    target = bob_app.raiden.address
    transfer_1_secret = factories.make_secret(0)
    transfer_1_secrethash = sha3(transfer_1_secret)
    transfer_2_secret = factories.make_secret(1)
    transfer_2_secrethash = sha3(transfer_2_secret)

    hold_event_handler.hold_secretrequest_for(secrethash=transfer_1_secrethash)
    transfer1_received = wait_message_handler.wait_for_message(
        LockedTransfer, {"lock": {"secrethash": transfer_1_secrethash}}
    )
    transfer2_received = wait_message_handler.wait_for_message(
        LockedTransfer, {"lock": {"secrethash": transfer_2_secrethash}}
    )
    remove_expired_lock_received = wait_message_handler.wait_for_message(
        LockExpired, {"secrethash": transfer_1_secrethash}
    )

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=target,
        identifier=identifier,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=transfer_1_secret,
    )
    transfer1_received.wait()

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state, transfer_1_secrethash)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier, alice_app, deposit, [lock], bob_app, deposit, []
    )

    # Verify lock is registered in both channel states
    alice_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    assert transfer_1_secrethash in alice_channel_state.our_state.secrethashes_to_lockedlocks

    bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier)
    assert transfer_1_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks

    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_1_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task

    remove_expired_lock_received.wait()

    alice_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    assert transfer_1_secrethash not in alice_channel_state.our_state.secrethashes_to_lockedlocks

    # Verify Bob received the message and processed the LockExpired message
    bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier)
    assert transfer_1_secrethash not in bob_channel_state.partner_state.secrethashes_to_lockedlocks

    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_1_secrethash not in alice_chain_state.payment_mapping.secrethashes_to_task

    # Make another transfer
    alice_to_bob_amount = 10
    identifier = 2

    hold_event_handler.hold_secretrequest_for(secrethash=transfer_2_secrethash)

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=target,
        identifier=identifier,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=transfer_2_secret,
    )
    transfer2_received.wait()

    # Make sure the other transfer still exists
    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_2_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task

    bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier)
    assert transfer_2_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks
示例#60
0
from raiden.messages import Processed
from raiden.tests.utils import factories
from raiden.transfer.events import (
    EventPaymentReceivedSuccess,
    EventPaymentSentFailed,
    EventPaymentSentSuccess,
)
from raiden.transfer.state_change import ActionCancelPayment, Block
from raiden.utils import sha3

ADDRESS = sha3(b'foo')[:20]
ADDRESS2 = sha3(b'boo')[:20]
ADDRESS3 = sha3(b'coo')[:20]
ADDRESS4 = sha3(b'goo')[:20]
SECRET = b'secret'
HASH = sha3(SECRET)
HASH2 = sha3(b'joo')


def test_transfer_statechange_operators():
    # pylint: disable=unneeded-not
    block_hash = factories.make_transaction_hash()
    a = Block(
        block_number=2,
        gas_limit=1,
        block_hash=block_hash,
    )
    b = Block(
        block_number=2,
        gas_limit=1,
        block_hash=block_hash,