Exemple #1
0
def test_events_for_close():
    """ Channel must be closed when the unsafe region is reached and the secret is known. """
    amount = 3
    expire = 10
    initiator = factories.HOP1
    our_address = factories.ADDR
    secret = factories.UNIT_SECRET

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
        secret=secret,
    )

    safe_to_wait = expire - from_route.reveal_timeout - 1
    unsafe_to_wait = expire - from_route.reveal_timeout

    state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=safe_to_wait,
    )
    events = target.events_for_close(state)
    assert not events

    state.block_number = unsafe_to_wait
    events = target.events_for_close(state)
    assert events
    assert isinstance(events[0], ContractSendChannelClose)
    assert from_transfer.secret is not None
    assert events[0].channel_address == from_route.channel_address
def test_events_for_close_secret_unknown():
    """ Channel must not be closed when the unsafe region is reached and the
    secret is not known.
    """
    amount = 3
    expire = 10
    initiator = factories.HOP1
    our_address = factories.ADDR

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )

    state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=expire,
    )

    events = target.events_for_close(state)
    assert not events

    events = target.events_for_close(state)
    assert not events
    assert from_transfer.secret is None
def test_no_valid_routes():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT - 1),
        factories.make_route(factories.HOP3, available_balance=1),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(
        init_state_change,
    )

    assert mediator_state_machine.current_state is None

    assert len(events) == 1
    assert isinstance(events[0], SendRefundTransfer)
def test_no_valid_routes():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT - 1),
        factories.make_route(factories.HOP3, available_balance=1),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(
        init_state_change,
    )

    assert mediator_state_machine.current_state is None

    assert len(events) == 1
    assert isinstance(events[0], SendRefundTransfer)
def test_handle_inittarget():
    """ Init transfer must send a secret request if the expiration is valid. """
    block_number = 1
    amount = 3
    expire = factories.UNIT_REVEAL_TIMEOUT + block_number + 1
    initiator = factories.HOP1

    from_route, from_transfer = factories.make_from(
        amount,
        factories.ADDR,
        expire,
        initiator,
    )
    state_change = ActionInitTarget(
        factories.ADDR,
        from_route,
        from_transfer,
        block_number,
    )

    iteration = target.handle_inittarget(state_change)

    events = iteration.events
    assert isinstance(events[0], SendSecretRequest)

    assert events[0].identifier == from_transfer.identifier
    assert events[0].amount == from_transfer.amount
    assert events[0].hashlock == from_transfer.hashlock
    assert events[0].receiver == initiator
def test_events_for_close():
    """ Channel must be closed when the unsafe region is reached and the secret is known. """
    amount = 3
    expire = 10
    initiator = factories.HOP1
    our_address = factories.ADDR
    secret = factories.UNIT_SECRET

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
        secret=secret,
    )

    safe_to_wait = expire - from_route.reveal_timeout - 1
    unsafe_to_wait = expire - from_route.reveal_timeout

    state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=safe_to_wait,
    )
    events = target.events_for_close(state)
    assert not events

    state.block_number = unsafe_to_wait
    events = target.events_for_close(state)
    assert events
    assert isinstance(events[0], ContractSendChannelClose)
    assert from_transfer.secret is not None
    assert events[0].channel_address == from_route.channel_address
Exemple #7
0
def test_handle_inittarget():
    """ Init transfer must send a secret request if the expiration is valid. """
    block_number = 1
    amount = 3
    expire = factories.UNIT_REVEAL_TIMEOUT + block_number + 1
    initiator = factories.HOP1

    from_route, from_transfer = factories.make_from(
        amount,
        factories.ADDR,
        expire,
        initiator,
    )
    state_change = ActionInitTarget(
        factories.ADDR,
        from_route,
        from_transfer,
        block_number,
    )

    iteration = target.handle_inittarget(state_change)

    events = iteration.events
    assert isinstance(events[0], SendSecretRequest)

    assert events[0].identifier == from_transfer.identifier
    assert events[0].amount == from_transfer.amount
    assert events[0].hashlock == from_transfer.hashlock
    assert events[0].receiver == initiator
Exemple #8
0
def test_events_for_close_secret_unknown():
    """ Channel must not be closed when the unsafe region is reached and the
    secret is not known.
    """
    amount = 3
    expire = 10
    initiator = factories.HOP1
    our_address = factories.ADDR

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )

    state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=expire,
    )

    events = target.events_for_close(state)
    assert not events

    events = target.events_for_close(state)
    assert not events
    assert from_transfer.secret is None
Exemple #9
0
def test_state_transition():
    """ Happy case testing. """
    amount = 7
    block_number = 1
    initiator = factories.HOP6
    expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        factories.ADDR,
        expire,
        initiator,
    )
    init = ActionInitTarget(
        factories.ADDR,
        from_route,
        from_transfer,
        block_number,
    )

    init_transition = target.state_transition(None, init)
    assert init_transition.new_state is not None
    assert init_transition.new_state.from_route == from_route
    assert init_transition.new_state.from_transfer == from_transfer

    first_new_block = Block(block_number + 1)
    first_block_iteration = target.state_transition(init_transition.new_state,
                                                    first_new_block)
    assert first_block_iteration.new_state.block_number == block_number + 1

    secret_reveal = ReceiveSecretReveal(factories.UNIT_SECRET, initiator)
    reveal_iteration = target.state_transition(first_block_iteration.new_state,
                                               secret_reveal)
    assert reveal_iteration.new_state.from_transfer.secret == factories.UNIT_SECRET

    second_new_block = Block(block_number + 2)
    second_block_iteration = target.state_transition(init_transition.new_state,
                                                     second_new_block)
    assert second_block_iteration.new_state.block_number == block_number + 2

    nonce = 11
    transferred_amount = 13
    locksroot = ''
    message_hash = ''
    balance_proof = ReceiveBalanceProof(
        from_transfer.identifier,
        from_route.node_address,
        nonce,
        transferred_amount,
        locksroot,
        from_route.channel_address,
        message_hash,
    )
    proof_iteration = target.state_transition(init_transition.new_state,
                                              balance_proof)
    assert proof_iteration.new_state is None
Exemple #10
0
def test_secret_learned():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2,
                             available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    state = make_mediator_state(
        from_transfer,
        from_route,
        list(routes),
    )

    secret = factories.UNIT_SECRET
    payee_address = factories.HOP2

    iteration = mediator.secret_learned(
        state,
        secret,
        payee_address,
        'payee_secret_revealed',
    )
    transfer_pair = iteration.new_state.transfers_pair[0]

    assert from_transfer.expiration > transfer_pair.payee_transfer.expiration
    assert transfer_pair.payee_transfer.almost_equal(from_transfer)
    assert transfer_pair.payee_route == routes[0]

    assert transfer_pair.payer_route == from_route
    assert transfer_pair.payer_transfer == from_transfer

    assert iteration.new_state.secret == secret
    assert transfer_pair.payee_transfer.secret == secret
    assert transfer_pair.payer_transfer.secret == secret

    assert transfer_pair.payee_state == 'payee_balance_proof'
    assert transfer_pair.payer_state == 'payer_secret_revealed'

    reveal_events = [
        e for e in iteration.events if isinstance(e, SendRevealSecret)
    ]
    assert len(reveal_events) == 1

    balance_events = [
        e for e in iteration.events if isinstance(e, SendBalanceProof)
    ]
    assert len(balance_events) == 1
Exemple #11
0
def test_init_mediator():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2,
                             available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(init_state_change, )

    mediator_state = mediator_state_machine.current_state
    assert isinstance(mediator_state, MediatorState)
    assert mediator_state.our_address == factories.ADDR
    assert mediator_state.block_number == init_state_change.block_number
    assert mediator_state.transfers_pair[0].payer_transfer == from_transfer
    assert mediator_state.transfers_pair[0].payer_route == from_route

    assert len(
        events
    ), 'we have a valid route, the mediated transfer event must be emited'

    mediated_transfers = [
        e for e in events if isinstance(e, SendMediatedTransfer)
    ]
    assert len(mediated_transfers
               ) == 1, 'mediated_transfer should /not/ split the transfer'
    mediated_transfer = mediated_transfers[0]

    assert mediated_transfer.token == from_transfer.token, 'transfer token address mismatch'
    assert mediated_transfer.amount == from_transfer.amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration < from_transfer.expiration, 'transfer expiration mismatch'
    assert mediated_transfer.hashlock == from_transfer.hashlock, 'wrong hashlock'
def test_init_mediator():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(
        init_state_change,
    )

    mediator_state = mediator_state_machine.current_state
    assert isinstance(mediator_state, MediatorState)
    assert mediator_state.our_address == factories.ADDR
    assert mediator_state.block_number == init_state_change.block_number
    assert mediator_state.transfers_pair[0].payer_transfer == from_transfer
    assert mediator_state.transfers_pair[0].payer_route == from_route

    assert len(events), 'we have a valid route, the mediated transfer event must be emited'

    mediated_transfers = [
        e for e in events
        if isinstance(e, SendMediatedTransfer)
    ]
    assert len(mediated_transfers) == 1, 'mediated_transfer should /not/ split the transfer'
    mediated_transfer = mediated_transfers[0]

    assert mediated_transfer.token == from_transfer.token, 'transfer token address mismatch'
    assert mediated_transfer.amount == from_transfer.amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration < from_transfer.expiration, 'transfer expiration mismatch'
    assert mediated_transfer.hashlock == from_transfer.hashlock, 'wrong hashlock'
def test_secret_learned():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    state = make_mediator_state(
        from_transfer,
        from_route,
        list(routes),
    )

    secret = factories.UNIT_SECRET
    payee_address = factories.HOP2

    iteration = mediator.secret_learned(
        state,
        secret,
        payee_address,
        'payee_secret_revealed',
    )
    transfer_pair = iteration.new_state.transfers_pair[0]

    assert from_transfer.expiration > transfer_pair.payee_transfer.expiration
    assert transfer_pair.payee_transfer.almost_equal(from_transfer)
    assert transfer_pair.payee_route == routes[0]

    assert transfer_pair.payer_route == from_route
    assert transfer_pair.payer_transfer == from_transfer

    assert iteration.new_state.secret == secret
    assert transfer_pair.payee_transfer.secret == secret
    assert transfer_pair.payer_transfer.secret == secret

    assert transfer_pair.payee_state == 'payee_balance_proof'
    assert transfer_pair.payer_state == 'payer_secret_revealed'

    reveal_events = [e for e in iteration.events if isinstance(e, SendRevealSecret)]
    assert len(reveal_events) == 1

    balance_events = [e for e in iteration.events if isinstance(e, SendBalanceProof)]
    assert len(balance_events) == 1
def make_init_state_change(our_address, amount, block_number, initiator, expire=None):
    if expire is None:
        expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )
    init = ActionInitTarget(
        our_address,
        from_route,
        from_transfer,
        block_number,
    )

    return init
def make_target_state(our_address, amount, block_number, initiator, expire=None):
    if expire is None:
        expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )

    state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number,
    )

    return state
def test_mediate_transfer():
    amount = 10
    block_number = 5
    expiration = 30

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    routes_state = RoutesState(routes)
    state = MediatorState(
        factories.ADDR,
        routes_state,
        block_number,
        factories.UNIT_HASHLOCK,
    )

    payer_route, payer_transfer = factories.make_from(amount, factories.HOP6, expiration)

    iteration = mediator.mediate_transfer(
        state,
        payer_route,
        payer_transfer,
    )

    events_mediated = [
        e
        for e in iteration.events
        if isinstance(e, SendMediatedTransfer)
    ]

    assert len(events_mediated) == 1
    transfer = events_mediated[0]
    assert transfer.identifier == payer_transfer.identifier
    assert transfer.token == payer_transfer.token
    assert transfer.amount == payer_transfer.amount
    assert transfer.hashlock == payer_transfer.hashlock
    assert transfer.target == payer_transfer.target
    assert payer_transfer.expiration > transfer.expiration
    assert transfer.receiver == routes[0].node_address
def test_mediate_transfer():
    amount = 10
    block_number = 5
    expiration = 30

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    routes_state = RoutesState(routes)
    state = MediatorState(
        factories.ADDR,
        routes_state,
        block_number,
        factories.UNIT_HASHLOCK,
    )

    payer_route, payer_transfer = factories.make_from(amount, factories.HOP6, expiration)

    iteration = mediator.mediate_transfer(
        state,
        payer_route,
        payer_transfer,
    )

    events_mediated = [
        e
        for e in iteration.events
        if isinstance(e, SendMediatedTransfer)
    ]

    assert len(events_mediated) == 1
    transfer = events_mediated[0]
    assert transfer.identifier == payer_transfer.identifier
    assert transfer.token == payer_transfer.token
    assert transfer.amount == payer_transfer.amount
    assert transfer.hashlock == payer_transfer.hashlock
    assert transfer.target == payer_transfer.target
    assert payer_transfer.expiration > transfer.expiration
    assert transfer.receiver == routes[0].node_address
Exemple #18
0
def make_init_state_change(our_address,
                           amount,
                           block_number,
                           initiator,
                           expire=None):
    if expire is None:
        expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )
    init = ActionInitTarget(
        our_address,
        from_route,
        from_transfer,
        block_number,
    )

    return init
def test_handle_inittarget_bad_expiration():
    """ Init transfer must do nothing if the expiration is bad. """
    block_number = 1
    amount = 3
    expire = block_number + factories.UNIT_REVEAL_TIMEOUT
    initiator = factories.HOP1

    from_route, from_transfer = factories.make_from(
        amount,
        factories.ADDR,
        expire,
        initiator,
    )
    state_change = ActionInitTarget(
        factories.ADDR,
        from_route,
        from_transfer,
        block_number,
    )

    iteration = target.handle_inittarget(state_change)
    assert len(iteration.events) == 0
Exemple #20
0
def test_handle_inittarget_bad_expiration():
    """ Init transfer must do nothing if the expiration is bad. """
    block_number = 1
    amount = 3
    expire = block_number + factories.UNIT_REVEAL_TIMEOUT
    initiator = factories.HOP1

    from_route, from_transfer = factories.make_from(
        amount,
        factories.ADDR,
        expire,
        initiator,
    )
    state_change = ActionInitTarget(
        factories.ADDR,
        from_route,
        from_transfer,
        block_number,
    )

    iteration = target.handle_inittarget(state_change)
    assert len(iteration.events) == 0
Exemple #21
0
def make_target_state(our_address,
                      amount,
                      block_number,
                      initiator,
                      expire=None):
    if expire is None:
        expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )

    state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number,
    )

    return state
def test_clear_if_finalized_expired():
    """ Clear expired locks that we don't know the secret for. """
    initiator = factories.HOP6
    our_address = factories.ADDR
    amount = 3
    block_number = 10
    expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )

    before_state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=expire,
    )
    before_iteration = TransitionResult(before_state, list())
    before_iteration = target.clear_if_finalized(before_iteration)

    assert before_iteration.new_state.from_transfer.secret is None
    assert before_iteration.new_state is not None

    expired_state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=expire + 1,
    )
    expired_iteration = TransitionResult(expired_state, list())
    expired_iteration = target.clear_if_finalized(expired_iteration)

    assert expired_iteration.new_state is None
Exemple #23
0
def test_clear_if_finalized_expired():
    """ Clear expired locks that we don't know the secret for. """
    initiator = factories.HOP6
    our_address = factories.ADDR
    amount = 3
    block_number = 10
    expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        our_address,
        expire,
        initiator,
    )

    before_state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=expire,
    )
    before_iteration = TransitionResult(before_state, list())
    before_iteration = target.clear_if_finalized(before_iteration)

    assert before_iteration.new_state.from_transfer.secret is None
    assert before_iteration.new_state is not None

    expired_state = TargetState(
        our_address,
        from_route,
        from_transfer,
        block_number=expire + 1,
    )
    expired_iteration = TransitionResult(expired_state, list())
    expired_iteration = target.clear_if_finalized(expired_iteration)

    assert expired_iteration.new_state is None
def test_state_transition():
    """ Happy case testing. """
    amount = 7
    block_number = 1
    initiator = factories.HOP6
    expire = block_number + factories.UNIT_REVEAL_TIMEOUT

    from_route, from_transfer = factories.make_from(
        amount,
        factories.ADDR,
        expire,
        initiator,
    )
    init = ActionInitTarget(
        factories.ADDR,
        from_route,
        from_transfer,
        block_number,
    )

    init_transition = target.state_transition(None, init)
    assert init_transition.new_state is not None
    assert init_transition.new_state.from_route == from_route
    assert init_transition.new_state.from_transfer == from_transfer

    first_new_block = Block(block_number + 1)
    first_block_iteration = target.state_transition(init_transition.new_state, first_new_block)
    assert first_block_iteration.new_state.block_number == block_number + 1

    secret_reveal = ReceiveSecretReveal(factories.UNIT_SECRET, initiator)
    reveal_iteration = target.state_transition(first_block_iteration.new_state, secret_reveal)
    assert reveal_iteration.new_state.from_transfer.secret == factories.UNIT_SECRET

    second_new_block = Block(block_number + 2)
    second_block_iteration = target.state_transition(init_transition.new_state, second_new_block)
    assert second_block_iteration.new_state.block_number == block_number + 2

    nonce = 11
    transferred_amount = 13
    locksroot = ''
    message_hash = ''
    signature = None

    balance_proof = BalanceProofState(
        nonce,
        transferred_amount,
        locksroot,
        from_route.channel_address,
        message_hash,
        signature,
    )

    balance_proof_state_change = ReceiveBalanceProof(
        from_transfer.identifier,
        from_route.node_address,
        balance_proof,
    )
    proof_iteration = target.state_transition(
        init_transition.new_state,
        balance_proof_state_change,
    )
    assert proof_iteration.new_state is None