예제 #1
0
def create_sendlockedtransfer(channel_state, initiator, target, amount,
                              identifier, expiration, secrethash):

    our_state = channel_state.our_state
    partner_state = channel_state.partner_state
    our_balance_proof = our_state.balance_proof

    msg = 'caller must make sure there is enough balance'
    assert amount <= get_distributable(our_state, partner_state), msg

    msg = 'caller must make sure the channel is open'
    assert get_status(channel_state) == CHANNEL_STATE_OPENED, msg

    lock = HashTimeLockState(
        amount,
        expiration,
        secrethash,
    )

    merkletree = compute_merkletree_with(
        channel_state.our_state.merkletree,
        lock.lockhash,
    )
    # The caller must ensure the same lock is not being used twice
    assert merkletree, 'lock is already registered'

    locksroot = merkleroot(merkletree)

    if our_balance_proof:
        transferred_amount = our_balance_proof.transferred_amount
    else:
        transferred_amount = 0

    token = channel_state.token_address
    nonce = get_next_nonce(channel_state.our_state)
    recipient = channel_state.partner_state.address

    balance_proof = BalanceProofUnsignedState(
        nonce,
        transferred_amount,
        locksroot,
        channel_state.identifier,
    )

    locked_transfer = LockedTransferUnsignedState(
        identifier,
        token,
        balance_proof,
        lock,
        initiator,
        target,
    )

    lockedtransfer = SendLockedTransfer(
        locked_transfer,
        recipient,
    )

    return lockedtransfer, merkletree
예제 #2
0
def test_get_event_with_balance_proof():
    """ All events which contain a balance proof must be found by when
    querying the database.
    """
    serializer = JSONSerializer
    storage = SQLiteStorage(':memory:', serializer)
    counter = itertools.count()

    lock_expired = SendLockExpired(
        recipient=factories.make_address(),
        message_identifier=next(counter),
        balance_proof=make_balance_proof_from_counter(counter),
        secrethash=sha3(factories.make_secret(next(counter))),
    )
    locked_transfer = SendLockedTransfer(
        recipient=factories.make_address(),
        channel_identifier=factories.make_channel_identifier(),
        message_identifier=next(counter),
        transfer=make_transfer_from_counter(counter),
    )
    balance_proof = SendBalanceProof(
        recipient=factories.make_address(),
        channel_identifier=factories.make_channel_identifier(),
        message_identifier=next(counter),
        payment_identifier=next(counter),
        token_address=factories.make_address(),
        secret=factories.make_secret(next(counter)),
        balance_proof=make_balance_proof_from_counter(counter),
    )
    refund_transfer = SendRefundTransfer(
        recipient=factories.make_address(),
        channel_identifier=factories.make_channel_identifier(),
        message_identifier=next(counter),
        transfer=make_transfer_from_counter(counter),
    )

    events_balanceproofs = [
        (lock_expired, lock_expired.balance_proof),
        (locked_transfer, locked_transfer.balance_proof),
        (balance_proof, balance_proof.balance_proof),
        (refund_transfer, refund_transfer.transfer.balance_proof),
    ]

    timestamp = datetime.utcnow().isoformat(timespec='milliseconds')
    state_change = ''
    for event, _ in events_balanceproofs:
        state_change_identifier = storage.write_state_change(
            state_change,
            timestamp,
        )
        storage.write_events(
            state_change_identifier=state_change_identifier,
            events=[event],
            log_time=timestamp,
        )

    for event, balance_proof in events_balanceproofs:
        event_record = get_event_with_balance_proof(
            storage=storage,
            chain_id=balance_proof.chain_id,
            token_network_identifier=balance_proof.token_network_identifier,
            channel_identifier=balance_proof.channel_identifier,
            balance_hash=balance_proof.balance_hash,
        )
        assert event_record.data == event
예제 #3
0
def create_sendlockedtransfer(
    channel_state: NettingChannelState,
    initiator: typing.InitiatorAddress,
    target: typing.TargetAddress,
    amount: typing.PaymentAmount,
    message_identifier: typing.MessageID,
    payment_identifier: typing.PaymentID,
    expiration: typing.BlockExpiration,
    secrethash: typing.SecretHash,
) -> SendLockedTransfer:
    our_state = channel_state.our_state
    partner_state = channel_state.partner_state
    our_balance_proof = our_state.balance_proof

    msg = 'caller must make sure there is enough balance'
    assert amount <= get_distributable(our_state, partner_state), msg

    msg = 'caller must make sure the channel is open'
    assert get_status(channel_state) == CHANNEL_STATE_OPENED, msg

    lock = HashTimeLockState(
        amount,
        expiration,
        secrethash,
    )

    merkletree = compute_merkletree_with(
        channel_state.our_state.merkletree,
        lock.lockhash,
    )
    # The caller must ensure the same lock is not being used twice
    assert merkletree, 'lock is already registered'

    locksroot = merkleroot(merkletree)

    if our_balance_proof:
        transferred_amount = our_balance_proof.transferred_amount
    else:
        transferred_amount = 0

    token = channel_state.token_address
    nonce = get_next_nonce(channel_state.our_state)
    recipient = channel_state.partner_state.address
    locked_amount = get_amount_locked(
        our_state) + amount  # the new lock is not registered yet

    balance_proof = BalanceProofUnsignedState(
        nonce,
        transferred_amount,
        locked_amount,
        locksroot,
        channel_state.token_network_identifier,
        channel_state.identifier,
    )

    locked_transfer = LockedTransferUnsignedState(
        payment_identifier,
        token,
        balance_proof,
        lock,
        initiator,
        target,
    )

    queue_name = channel_state.identifier
    lockedtransfer = SendLockedTransfer(
        recipient,
        queue_name,
        message_identifier,
        locked_transfer,
    )

    return lockedtransfer, merkletree
예제 #4
0
def test_get_event_with_balance_proof():
    """ All events which contain a balance proof must be found by when
    querying the database.
    """
    serializer = JSONSerializer()
    storage = SerializedSQLiteStorage(":memory:", serializer)
    counter = itertools.count(1)
    partner_address = factories.make_address()

    balance_proof = make_balance_proof_from_counter(counter)
    lock_expired = SendLockExpired(
        recipient=partner_address,
        message_identifier=MessageID(next(counter)),
        balance_proof=balance_proof,
        secrethash=factories.make_secret_hash(next(counter)),
        canonical_identifier=balance_proof.canonical_identifier,
    )
    locked_transfer = SendLockedTransfer(
        recipient=partner_address,
        message_identifier=MessageID(next(counter)),
        transfer=make_transfer_from_counter(counter),
        canonical_identifier=factories.make_canonical_identifier(),
    )
    send_balance_proof = SendBalanceProof(
        recipient=partner_address,
        message_identifier=MessageID(next(counter)),
        payment_identifier=factories.make_payment_id(),
        token_address=factories.make_token_address(),
        secret=factories.make_secret(next(counter)),
        balance_proof=make_balance_proof_from_counter(counter),
        canonical_identifier=factories.make_canonical_identifier(),
    )

    refund_transfer = SendRefundTransfer(
        recipient=partner_address,
        message_identifier=MessageID(next(counter)),
        transfer=make_transfer_from_counter(counter),
        canonical_identifier=factories.make_canonical_identifier(),
    )

    events_balanceproofs = [
        (lock_expired, lock_expired.balance_proof),
        (locked_transfer, locked_transfer.balance_proof),
        (send_balance_proof, send_balance_proof.balance_proof),
        (refund_transfer, refund_transfer.transfer.balance_proof),
    ]

    state_change = Block(BlockNumber(1), BlockGasLimit(1),
                         factories.make_block_hash())
    for event, _ in events_balanceproofs:
        state_change_identifiers = storage.write_state_changes([state_change])
        storage.write_events(events=[(state_change_identifiers[0], event)])

    for event, balance_proof in events_balanceproofs:
        event_record = get_event_with_balance_proof_by_balance_hash(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            balance_hash=balance_proof.balance_hash,
            recipient=partner_address,
        )
        assert event_record
        assert event_record.data == event

        event_record = get_event_with_balance_proof_by_locksroot(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            recipient=event.recipient,
            locksroot=balance_proof.locksroot,
        )
        assert event_record
        assert event_record.data == event

        # Checking that balance proof attribute can be accessed for all events.
        # Issue https://github.com/raiden-network/raiden/issues/3179
        assert event_record.data.balance_proof == event.balance_proof

    storage.close()
예제 #5
0
def test_pfs_global_messages(
    matrix_transports,
    monkeypatch,
):
    """
    Test that `update_pfs` from `RaidenEventHandler` sends balance proof updates to the global
    PATH_FINDING_BROADCASTING_ROOM room on Send($BalanceProof)* events, i.e. events, that send
    a new balance proof to the channel partner.
    """
    transport = matrix_transports[0]
    transport._client.api.retry_timeout = 0
    transport._send_raw = MagicMock()
    raiden_service = MockRaidenService(None)

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

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

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

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

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

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

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

    event_handler = raiden_event_handler.RaidenEventHandler()

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

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

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

    # ensure all events triggered a send for their respective balance_proof
    # matrix transport may concatenate multiple messages send in one interval
    assert pfs_room.send_text.call_count >= 1
    concatenated_call_args = ' '.join(
        str(arg) for arg in pfs_room.send_text.call_args_list)
    assert all(f'"nonce": {i + 1}' in concatenated_call_args
               for i in range(len(SEND_BALANCE_PROOF_EVENTS)))
    transport.stop()
    transport.get()
예제 #6
0
def test_get_event_with_balance_proof():
    """ All events which contain a balance proof must be found by when
    querying the database.
    """
    serializer = JSONSerializer
    storage = SerializedSQLiteStorage(":memory:", serializer)
    counter = itertools.count()

    lock_expired = SendLockExpired(
        recipient=factories.make_address(),
        message_identifier=next(counter),
        balance_proof=make_balance_proof_from_counter(counter),
        secrethash=sha3(factories.make_secret(next(counter))),
    )
    locked_transfer = SendLockedTransfer(
        recipient=factories.make_address(),
        channel_identifier=factories.make_channel_identifier(),
        message_identifier=next(counter),
        transfer=make_transfer_from_counter(counter),
    )
    balance_proof = SendBalanceProof(
        recipient=factories.make_address(),
        channel_identifier=factories.make_channel_identifier(),
        message_identifier=next(counter),
        payment_identifier=next(counter),
        token_address=factories.make_address(),
        secret=factories.make_secret(next(counter)),
        balance_proof=make_balance_proof_from_counter(counter),
    )
    refund_transfer = SendRefundTransfer(
        recipient=factories.make_address(),
        channel_identifier=factories.make_channel_identifier(),
        message_identifier=next(counter),
        transfer=make_transfer_from_counter(counter),
    )

    events_balanceproofs = [
        (lock_expired, lock_expired.balance_proof),
        (locked_transfer, locked_transfer.balance_proof),
        (balance_proof, balance_proof.balance_proof),
        (refund_transfer, refund_transfer.transfer.balance_proof),
    ]

    timestamp = datetime.utcnow().isoformat(timespec="milliseconds")
    state_change = ""
    for event, _ in events_balanceproofs:
        state_change_identifier = storage.write_state_change(
            state_change, timestamp)
        storage.write_events(state_change_identifier=state_change_identifier,
                             events=[event],
                             log_time=timestamp)

    for event, balance_proof in events_balanceproofs:
        event_record = get_event_with_balance_proof_by_balance_hash(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            balance_hash=balance_proof.balance_hash,
        )
        assert event_record.data == event
        # Checking that balance proof attribute can be accessed for all events.
        # Issue https://github.com/raiden-network/raiden/issues/3179
        assert event_record.data.balance_proof == event.balance_proof