Beispiel #1
0
def test_events_for_onchain_secretreveal_with_unfit_channels():
    settle = factories.TransactionExecutionStatusProperties()
    settled = factories.create(
        factories.NettingChannelStateProperties(settle_transaction=settle))
    secret = factories.UNIT_SECRET
    block_hash = factories.make_block_hash()

    events = events_for_onchain_secretreveal(settled, secret, 10, block_hash)
    assert not events, "Secret reveal event should not be generated for settled channel"

    settle = factories.replace(settle,
                               result=TransactionExecutionStatus.FAILURE)
    unusable = factories.create(
        factories.NettingChannelStateProperties(settle_transaction=settle))

    events = events_for_onchain_secretreveal(unusable, secret, 10, block_hash)
    assert not events, "Secret reveal event should not be generated for unusable channel."
def test_mediator_skips_used_routes():
    prng = random.Random()
    block_number = 3
    defaults = factories.NettingChannelStateProperties(
        our_state=factories.NettingChannelEndStateProperties.OUR_STATE,
        partner_state=factories.NettingChannelEndStateProperties(
            balance=UNIT_TRANSFER_AMOUNT),
        open_transaction=factories.TransactionExecutionStatusProperties(
            started_block_number=1, finished_block_number=2, result="success"),
    )
    properties = [
        factories.NettingChannelStateProperties(
            partner_state=factories.NettingChannelEndStateProperties(
                privatekey=factories.HOP1_KEY, address=factories.HOP1)),
        factories.NettingChannelStateProperties(
            partner_state=factories.NettingChannelEndStateProperties(
                privatekey=factories.HOP2_KEY, address=factories.HOP2)),
        factories.NettingChannelStateProperties(
            partner_state=factories.NettingChannelEndStateProperties(
                privatekey=factories.HOP3_KEY, address=factories.HOP3)),
    ]
    channels = factories.make_channel_set(properties=properties,
                                          number_of_channels=3,
                                          defaults=defaults)
    bob = channels.channels[1].partner_state.address
    charlie = channels.channels[2].partner_state.address
    dave = factories.make_address()
    eric = factories.make_address()
    locked_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            expiration=10,
            routes=[
                [
                    factories.UNIT_OUR_ADDRESS, bob, dave,
                    factories.UNIT_TRANSFER_TARGET
                ],
                [
                    factories.UNIT_OUR_ADDRESS, bob, eric,
                    factories.UNIT_TRANSFER_TARGET
                ],
                [
                    factories.UNIT_OUR_ADDRESS, charlie, eric,
                    factories.UNIT_TRANSFER_TARGET
                ],
            ],
            canonical_identifier=channels.channels[0].canonical_identifier,
            pkey=factories.HOP1_KEY,
            sender=factories.HOP1,
        ))
    init_action = factories.mediator_make_init_action(channels=channels,
                                                      transfer=locked_transfer)
    nodeaddresses_to_networkstates = {
        channel.partner_state.address: NetworkState.REACHABLE
        for channel in channels.channels
    }

    transition_result = mediator.handle_init(
        state_change=init_action,
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=nodeaddresses_to_networkstates,
        pseudo_random_generator=prng,
        block_number=block_number,
    )
    mediator_state = transition_result.new_state
    events = transition_result.events
    assert mediator_state is not None
    assert events

    assert len(mediator_state.routes) == 3
    assert mediator_state.routes[0].route[1] == bob
    assert mediator_state.routes[1].route[1] == bob
    assert mediator_state.routes[2].route[1] == charlie
    # now we receive a refund from whoever we forwarded to (should be HOP2)
    assert isinstance(events[-1], SendLockedTransfer)
    assert events[-1].recipient == factories.HOP2

    last_pair = mediator_state.transfers_pair[-1]
    canonical_identifier = last_pair.payee_transfer.balance_proof.canonical_identifier
    lock_expiration = last_pair.payee_transfer.lock.expiration
    payment_identifier = last_pair.payee_transfer.payment_identifier

    received_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            expiration=lock_expiration,
            payment_identifier=payment_identifier,
            canonical_identifier=canonical_identifier,
            sender=factories.HOP2,
            pkey=factories.HOP2_KEY,
            message_identifier=factories.make_message_identifier(),
        ))

    refund_state_change = ReceiveTransferRefund(
        transfer=received_transfer,
        balance_proof=received_transfer.balance_proof,
        sender=received_transfer.balance_proof.sender,  # pylint: disable=no-member
    )
    transition_result = mediator.handle_refundtransfer(
        mediator_state=mediator_state,
        mediator_state_change=refund_state_change,
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=nodeaddresses_to_networkstates,
        pseudo_random_generator=prng,
        block_number=block_number,
    )

    mediator_state = transition_result.new_state
    events = transition_result.events
    assert mediator_state is not None
    assert events
    assert mediator_state.transfers_pair[-1].payee_address == charlie

    # now we should have a forward transfer to HOP3
    assert isinstance(events[-1], SendLockedTransfer)
    assert events[-1].recipient == factories.HOP3

    # now we will receive a refund from HOP3

    last_pair = mediator_state.transfers_pair[-1]
    canonical_identifier = last_pair.payee_transfer.balance_proof.canonical_identifier
    lock_expiration = last_pair.payee_transfer.lock.expiration
    payment_identifier = last_pair.payee_transfer.payment_identifier

    received_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            expiration=lock_expiration,
            payment_identifier=payment_identifier,
            canonical_identifier=canonical_identifier,
            sender=factories.HOP3,
            pkey=factories.HOP3_KEY,
            message_identifier=factories.make_message_identifier(),
        ))

    refund_state_change = ReceiveTransferRefund(
        transfer=received_transfer,
        balance_proof=received_transfer.balance_proof,
        sender=received_transfer.balance_proof.sender,  # pylint: disable=no-member
    )

    transition_result = mediator.handle_refundtransfer(
        mediator_state=mediator_state,
        mediator_state_change=refund_state_change,
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=nodeaddresses_to_networkstates,
        pseudo_random_generator=prng,
        block_number=block_number,
    )

    mediator_state = transition_result.new_state
    events = transition_result.events
    assert mediator_state is not None
    assert events

    # no other routes available, so refund HOP1
    assert isinstance(events[-1], SendRefundTransfer)
    assert events[-1].recipient == factories.HOP1
def test_initiator_skips_used_routes():
    defaults = factories.NettingChannelStateProperties(
        our_state=factories.NettingChannelEndStateProperties.OUR_STATE,
        partner_state=factories.NettingChannelEndStateProperties(balance=10),
        open_transaction=factories.TransactionExecutionStatusProperties(
            started_block_number=1, finished_block_number=2, result="success"),
    )
    properties = [
        factories.NettingChannelStateProperties(
            partner_state=factories.NettingChannelEndStateProperties(
                privatekey=factories.HOP1_KEY, address=factories.HOP1))
    ]
    test_chain_state = factories.make_chain_state(number_of_channels=1,
                                                  properties=properties,
                                                  defaults=defaults)
    channels = test_chain_state.channel_set

    bob = channels.channels[0].partner_state.address

    routes = [[
        factories.UNIT_OUR_ADDRESS, bob, factories.UNIT_TRANSFER_TARGET
    ]]

    transfer = factories.create(
        factories.TransferDescriptionProperties(
            initiator=factories.UNIT_OUR_ADDRESS,
            target=factories.UNIT_TRANSFER_TARGET))
    init_action = factories.initiator_make_init_action(
        channels=channels,
        routes=routes,
        transfer=transfer,
        estimated_fee=FeeAmount(0))
    transition_result = handle_action_init_initiator(
        chain_state=test_chain_state.chain_state, state_change=init_action)

    chain_state = transition_result.new_state

    assert transfer.secrethash in chain_state.payment_mapping.secrethashes_to_task

    initiator_task = chain_state.payment_mapping.secrethashes_to_task[
        transfer.secrethash]
    initiator_state = initiator_task.manager_state

    assert len(initiator_state.routes) == 1, "Should have one route"
    assert len(
        initiator_state.routes[0].route) == 3, "Route should not be pruned"
    assert initiator_state.routes[0].route == routes[
        0], "Should have test route"

    events = transition_result.events

    assert isinstance(events[-1], SendLockedTransfer)

    locked_transfer = initiator_state.initiator_transfers[
        transfer.secrethash].transfer

    received_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            expiration=locked_transfer.lock.expiration,
            payment_identifier=locked_transfer.payment_identifier,
            canonical_identifier=locked_transfer.balance_proof.
            canonical_identifier,
            initiator=factories.UNIT_OUR_ADDRESS,
            sender=bob,
            pkey=factories.HOP1_KEY,
            message_identifier=factories.make_message_identifier(),
            routes=[],
            secret=transfer.secret,
        ))

    role = views.get_transfer_role(chain_state=chain_state,
                                   secrethash=locked_transfer.lock.secrethash)

    assert role == "initiator", "Should keep initiator role"

    failed_route_state_change = ReceiveTransferCancelRoute(
        transfer=received_transfer,
        balance_proof=received_transfer.balance_proof,
        sender=received_transfer.balance_proof.sender,  # pylint: disable=no-member
    )

    state_transition(chain_state=chain_state,
                     state_change=failed_route_state_change)

    reroute_state_change = ActionTransferReroute(
        transfer=received_transfer,
        balance_proof=received_transfer.balance_proof,
        sender=received_transfer.balance_proof.sender,  # pylint: disable=no-member
        secret=factories.make_secret(),
    )

    iteration = state_transition(chain_state=chain_state,
                                 state_change=reroute_state_change)

    assert search_for_item(iteration.events, SendLockedTransfer, {}) is None