예제 #1
0
def test_no_valid_routes():
    from_route, from_transfer = 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)
예제 #3
0
def test_cancel_transfer():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]

    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    state_change = ActionCancelTransfer(identifier=identifier)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert isinstance(events[0], EventTransferSentFailed)
    assert initiator_state_machine.current_state is None
예제 #4
0
def test_state_wait_secretrequest_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    hashlock = current_state.transfer.hashlock

    state_change = ReceiveSecretRequest(
        identifier=identifier,
        amount=amount,
        hashlock=hashlock,
        sender=target_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    events = initiator_state_machine.dispatch(state_change)
    assert all(isinstance(event, SendRevealSecret) for event in events)
    assert len(events) == 1
def test_state_wait_secretrequest_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    hashlock = current_state.transfer.hashlock

    state_change = ReceiveSecretRequest(
        identifier=identifier,
        amount=amount,
        hashlock=hashlock,
        sender=target_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    events = initiator_state_machine.dispatch(state_change)
    assert all(isinstance(event, SendRevealSecret) for event in events)
    assert len(events) == 1
예제 #6
0
def test_init_without_routes():
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    our_address, target_address = factories.HOP1, factories.HOP3
    routes = []

    transfer = factories.make_transfer(
        amount,
        initiator=our_address,
        target=target_address,
        secret=None,
        hashlock=None,
        expiration=None,
    )
    init_state_change = ActionInitInitiator(
        our_address,
        transfer,
        RoutesState(routes),
        SequenceGenerator(),
        block_number,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        None,
    )

    assert initiator_state_machine.current_state is None

    events = initiator_state_machine.dispatch(init_state_change, )

    assert len(events) == 1
    assert any(isinstance(e, EventTransferSentFailed) for e in events)
    assert initiator_state_machine.current_state is None
def test_cancel_transfer():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]

    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    state_change = ActionCancelTransfer(
        identifier=identifier
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert isinstance(events[0], EventTransferSentFailed)
    assert initiator_state_machine.current_state is None
예제 #8
0
파일: wal.py 프로젝트: tokenbase/raiden
def restore_from_latest_snapshot(transition_function, storage):
    snapshot = storage.get_latest_state_snapshot()

    if snapshot:
        log.debug('Restoring from snapshot')
        last_applied_state_change_id, state = snapshot
        unapplied_state_changes = storage.get_statechanges_by_identifier(
            from_identifier=last_applied_state_change_id,
            to_identifier='latest',
        )
    else:
        log.debug('No snapshot found, replaying all state changes')
        state = None
        unapplied_state_changes = storage.get_statechanges_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )

    state_manager = StateManager(transition_function, state)
    wal = WriteAheadLog(state_manager, storage)

    log.debug('Replaying state changes',
              num_state_changes=len(unapplied_state_changes))
    for state_change in unapplied_state_changes:
        state_manager.dispatch(state_change)

    return wal
예제 #9
0
def test_state_wait_unlock_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        identifier=identifier,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    # setup the state for the wait unlock
    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=mediator_address,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 3

    assert any(isinstance(e, SendBalanceProof) for e in events)
    assert any(isinstance(e, EventTransferSentSuccess) for e in events)
    assert any(isinstance(e, EventUnlockSuccess) for e in events)

    balance_proof = next(e for e in events if isinstance(e, SendBalanceProof))
    complete = next(e for e in events
                    if isinstance(e, EventTransferSentSuccess))

    assert balance_proof.receiver == mediator_address
    assert complete.identifier == identifier
    assert initiator_state_machine.current_state is None, 'state must be cleaned'
def test_state_wait_unlock_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        identifier=identifier,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    # setup the state for the wait unlock
    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=mediator_address,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 3

    assert any(isinstance(e, SendBalanceProof) for e in events)
    assert any(isinstance(e, EventTransferSentSuccess) for e in events)
    assert any(isinstance(e, EventUnlockSuccess) for e in events)

    balance_proof = next(e for e in events if isinstance(e, SendBalanceProof))
    complete = next(e for e in events if isinstance(e, EventTransferSentSuccess))

    assert balance_proof.receiver == mediator_address
    assert complete.identifier == identifier
    assert initiator_state_machine.current_state is None, 'state must be cleaned'
예제 #11
0
def test_refund_transfer_next_route():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
        factories.make_route(factories.HOP2, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=mediator_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert any(
        isinstance(e, SendMediatedTransfer) for e in events
    ), 'No mediated transfer event emitted, should have tried a new route'

    assert initiator_state_machine.current_state is not None
    assert initiator_state_machine.current_state.routes.canceled_routes[
        0] == prior_state.route
예제 #12
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_refund_transfer_next_route():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
        factories.make_route(factories.HOP2, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=mediator_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert any(
        isinstance(e, SendMediatedTransfer) for e in events
    ), 'No mediated transfer event emitted, should have tried a new route'

    assert initiator_state_machine.current_state is not None
    assert initiator_state_machine.current_state.routes.canceled_routes[0] == prior_state.route
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'
예제 #15
0
def new_wal(state_transition: Callable, state: State = None) -> WriteAheadLog:
    serializer = JSONSerializer()

    state_manager = StateManager(state_transition, state)
    storage = SerializedSQLiteStorage(":memory:", serializer)
    wal = WriteAheadLog(state_manager, storage)
    return wal
예제 #16
0
def restore_to_state_change(transition_function, storage,
                            state_change_identifier):
    snapshot = storage.get_snapshot_closest_to_state_change(
        state_change_identifier)

    from_state_change_id = 0
    chain_state = None
    if snapshot:
        log.debug('Restoring from snapshot')
        from_state_change_id, chain_state = snapshot
    else:
        log.debug('No snapshot found, replaying all state changes')

    unapplied_state_changes = storage.get_statechanges_by_identifier(
        from_identifier=from_state_change_id,
        to_identifier=state_change_identifier,
    )

    state_manager = StateManager(transition_function, chain_state)
    wal = WriteAheadLog(state_manager, storage)

    log.debug('Replaying state changes',
              num_state_changes=len(unapplied_state_changes))
    for state_change in unapplied_state_changes:
        wal.state_manager.dispatch(state_change)

    return wal
예제 #17
0
    def __init__(self,
                 message_handler=None,
                 state_transition=None,
                 private_key=None):
        if private_key is None:
            self.private_key, self.address = factories.make_privkey_address()
        else:
            self.private_key = private_key
            self.address = privatekey_to_address(private_key)

        self.chain = MockChain(network_id=17, node_address=self.address)
        self.signer = LocalSigner(self.private_key)

        self.message_handler = message_handler

        self.user_deposit = Mock()

        if state_transition is None:
            state_transition = node.state_transition

        serializer = JSONSerializer
        state_manager = StateManager(state_transition, None)
        storage = SerializedSQLiteStorage(":memory:", serializer)
        self.wal = WriteAheadLog(state_manager, storage)

        state_change = ActionInitChain(
            pseudo_random_generator=random.Random(),
            block_number=0,
            block_hash=factories.make_block_hash(),
            our_address=self.chain.node_address,
            chain_id=self.chain.network_id,
        )

        self.wal.log_and_dispatch(state_change)
예제 #18
0
def replay_wal(storage, token_network_identifier, partner_address):
    all_state_changes = storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    state_manager = StateManager(state_transition=node.state_transition,
                                 current_state=None)
    wal = WriteAheadLog(state_manager, storage)

    for _, state_change in enumerate(all_state_changes):
        events = wal.state_manager.dispatch(state_change)

        chain_state = wal.state_manager.current_state

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state,
            to_canonical_address(token_network_identifier),
            to_canonical_address(partner_address),
        )

        if not channel_state:
            continue

        ###
        # Customize this to filter things further somewhere around here.
        # An example would be to add `import pdb; pdb.set_trace()`
        # and inspect the state.
        ###

        print_state_change(state_change)
        print_events(events)
예제 #19
0
def restore_to_state_change(transition_function: Callable,
                            storage: SerializedSQLiteStorage,
                            state_change_identifier: int) -> "WriteAheadLog":
    msg = "state change identifier 'latest' or an integer greater than zero"
    assert state_change_identifier == "latest" or state_change_identifier > 0, msg

    from_state_change_id, chain_state = storage.get_snapshot_closest_to_state_change(
        state_change_identifier=state_change_identifier)

    if chain_state is not None:
        log.debug(
            "Restoring from snapshot",
            from_state_change_id=from_state_change_id,
            to_state_change_id=state_change_identifier,
        )
    else:
        log.debug(
            "No snapshot found, replaying all state changes",
            to_state_change_id=state_change_identifier,
        )

    unapplied_state_changes = storage.get_statechanges_by_identifier(
        from_identifier=from_state_change_id,
        to_identifier=state_change_identifier)

    state_manager = StateManager(transition_function, chain_state)
    wal = WriteAheadLog(state_manager, storage)

    log.debug("Replaying state changes",
              num_state_changes=len(unapplied_state_changes))
    for state_change in unapplied_state_changes:
        wal.state_manager.dispatch(state_change, storage)

    return wal
def test_state_wait_unlock_invalid():
    identifier = identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    before_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=factories.ADDR,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state.revealsecret is not None
    assert_state_equal(initiator_state_machine.current_state, current_state)
    assert_state_equal(current_state, before_state)
예제 #21
0
def test_state_wait_unlock_invalid():
    identifier = identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    before_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=factories.ADDR,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state.revealsecret is not None
    assert_state_equal(initiator_state_machine.current_state, current_state)
    assert_state_equal(current_state, before_state)
예제 #22
0
def new_wal():
    state = None
    serializer = JSONSerializer

    state_manager = StateManager(state_transition_noop, state)
    storage = SQLiteStorage(':memory:', serializer)
    wal = WriteAheadLog(state_manager, storage)
    return wal
예제 #23
0
def test_state_wait_unlock_valid():
    identifier = identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    # setup the state for the wait unlock
    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        target_address,
        our_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        identifier=identifier,
        secret=secret,
        target=our_address,
        sender=mediator_address,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert isinstance(events[0], SendRevealSecret)
    assert events[0].target == mediator_address
    assert initiator_state_machine.current_state is None, 'state must be cleaned'
예제 #24
0
def test_wal():
    state = None
    serializer = PickleSerializer

    state_manager = StateManager(state_transition_noop, state)
    ###storage = SQLiteStorage('/home/wk/work/Raiden/test.txt', serializer)
    storage = SQLiteStorage('/Users/vincent/Downloads/test.txt', serializer)
    wal = WriteAheadLog(state_manager, storage)
    return wal
def test_refund_transfer_invalid_sender():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=our_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state is not None
    assert_state_equal(initiator_state_machine.current_state, prior_state)
예제 #26
0
def test_refund_transfer_invalid_sender():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=our_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state is not None
    assert_state_equal(initiator_state_machine.current_state, prior_state)
예제 #27
0
    def __init__(self, transition_function, storage):
        # TODO:
        # - reapply missing state changes
        # - clear existing events for the unapplied state changes
        snapshot = storage.get_state_snapshot()
        state_manager = StateManager(transition_function, snapshot)

        self.state_manager = state_manager
        self.state_change_id = None
        self.storage = storage
예제 #28
0
    def mediate_mediated_transfer(self, message):
        # pylint: disable=too-many-locals
        identifier = message.identifier
        amount = message.lock.amount
        target = message.target
        token = message.token
        graph = self.channelgraphs[token]
        routes = graph.get_best_routes(
            self.address,
            target,
            amount,
            lock_timeout=None,
        )

        available_routes = [
            route
            for route in map(route_to_routestate, routes)
            if route.state == CHANNEL_STATE_OPENED
        ]

        from_channel = graph.partneraddress_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

        our_address = self.address
        from_transfer = lockedtransfer_from_message(message)
        route_state = RoutesState(available_routes)
        block_number = self.get_block_number()

        init_mediator = ActionInitMediator(
            our_address,
            from_transfer,
            route_state,
            from_route,
            block_number,
        )

        state_manager = StateManager(mediator.state_transition, None)
        all_events = state_manager.dispatch(init_mediator)

        for event in all_events:
            self.state_machine_event_handler.on_event(event)

        self.identifier_statemanager[identifier].append(state_manager)
예제 #29
0
def restore_from_latest_snapshot(transition_function, storage):
    events = list()
    snapshot = storage.get_state_snapshot()

    if snapshot:
        last_applied_state_change_id, state = snapshot
        unapplied_state_changes = storage.get_statechanges_by_identifier(
            from_identifier=last_applied_state_change_id,
            to_identifier='latest',
        )
    else:
        state = None
        unapplied_state_changes = list()

    state_manager = StateManager(transition_function, state)
    wal = WriteAheadLog(state_manager, storage)

    for state_change in unapplied_state_changes:
        events.extend(state_manager.dispatch(state_change))

    return wal, events
예제 #30
0
def restore_to_state_change(
    transition_function: Callable,
    storage: SerializedSQLiteStorage,
    state_change_identifier: StateChangeID,
    node_address: Address,
) -> Tuple[int, int, "WriteAheadLog"]:
    chain_state: Optional[State]
    from_identifier: StateChangeID

    snapshot = storage.get_snapshot_before_state_change(
        state_change_identifier=state_change_identifier)

    if snapshot is not None:
        log.debug(
            "Restoring from snapshot",
            from_state_change_id=snapshot.state_change_identifier,
            to_state_change_id=state_change_identifier,
            node=to_checksum_address(node_address),
        )
        from_identifier = snapshot.state_change_identifier
        chain_state = snapshot.data
        state_change_qty = snapshot.state_change_qty
    else:
        log.debug(
            "No snapshot found, replaying all state changes",
            to_state_change_id=state_change_identifier,
            node=to_checksum_address(node_address),
        )
        from_identifier = LOW_STATECHANGE_ULID
        chain_state = None
        state_change_qty = 0

    state_manager = StateManager(transition_function, chain_state)
    wal = WriteAheadLog(state_manager, storage)

    unapplied_state_changes = storage.get_statechanges_by_range(
        Range(from_identifier, state_change_identifier))
    if unapplied_state_changes:
        log.debug(
            "Replaying state changes",
            replayed_state_changes=[
                redact_secret(DictSerializer.serialize(state_change))
                for state_change in unapplied_state_changes
            ],
            node=to_checksum_address(node_address),
        )
        for state_change in unapplied_state_changes:
            wal.state_manager.dispatch(state_change)

    return state_change_qty, len(unapplied_state_changes), wal
def test_init_without_routes():
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    our_address, target_address = factories.HOP1, factories.HOP3
    routes = []

    transfer = factories.make_transfer(
        amount,
        initiator=our_address,
        target=target_address,
        secret=None,
        hashlock=None,
        expiration=None,
    )
    init_state_change = ActionInitInitiator(
        our_address,
        transfer,
        RoutesState(routes),
        SequenceGenerator(),
        block_number,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        None,
    )

    assert initiator_state_machine.current_state is None

    events = initiator_state_machine.dispatch(
        init_state_change,
    )

    assert len(events) == 1
    assert any(isinstance(e, EventTransferSentFailed) for e in events)
    assert initiator_state_machine.current_state is None
예제 #32
0
    def target_mediated_transfer(self, message):
        graph = self.channelgraphs[message.token]
        from_channel = graph.partneraddress_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

        from_transfer = lockedtransfer_from_message(message)
        our_address = self.address
        block_number = self.get_block_number()

        init_target = ActionInitTarget(
            our_address,
            from_route,
            from_transfer,
            block_number,
        )

        state_manager = StateManager(target_task.state_transition, None)
        all_events = state_manager.dispatch(init_target)

        for event in all_events:
            self.state_machine_event_handler.on_event(event)

        identifier = message.identifier
        self.identifier_statemanager[identifier].append(state_manager)
예제 #33
0
    def __init__(self,
                 message_handler=None,
                 state_transition=None,
                 private_key=None):
        if private_key is None:
            self.privkey, self.address = factories.make_privkey_address()
        else:
            self.privkey = private_key
            self.address = privatekey_to_address(private_key)

        self.rpc_client = MockJSONRPCClient(self.address)
        self.proxy_manager = MockProxyManager(node_address=self.address)
        self.signer = LocalSigner(self.privkey)

        self.message_handler = message_handler
        self.routing_mode = RoutingMode.PRIVATE
        self.config = RaidenConfig(chain_id=self.rpc_client.chain_id,
                                   environment_type=Environment.DEVELOPMENT)

        self.default_user_deposit = Mock()
        self.default_registry = Mock()
        self.default_registry.address = factories.make_address()
        self.default_one_to_n_address = factories.make_address()
        self.default_msc_address = factories.make_address()

        self.targets_to_identifiers_to_statuses: Dict[Address,
                                                      dict] = defaultdict(dict)
        self.route_to_feedback_token: dict = {}

        if state_transition is None:
            state_transition = node.state_transition

        serializer = JSONSerializer()
        state_manager = StateManager(state_transition, None)
        storage = SerializedSQLiteStorage(":memory:", serializer)
        self.wal = WriteAheadLog(state_manager, storage)

        state_change = ActionInitChain(
            pseudo_random_generator=random.Random(),
            block_number=BlockNumber(0),
            block_hash=factories.make_block_hash(),
            our_address=self.rpc_client.address,
            chain_id=self.rpc_client.chain_id,
        )
        with self.wal.process_state_change_atomically() as dispatcher:
            dispatcher.dispatch(state_change)

        self.transport = Mock()
예제 #34
0
def replay_wal(
    storage: SerializedSQLiteStorage,
    token_network_address: TokenNetworkAddress,
    partner_address: Address,
    translator: Optional[Translator] = None,
) -> None:
    all_state_changes = storage.get_statechanges_by_range(
        RANGE_ALL_STATE_CHANGES)

    state_manager = StateManager(state_transition=node.state_transition,
                                 current_state=None)
    wal = WriteAheadLog(state_manager, storage)

    for _, state_change in enumerate(all_state_changes):
        # Dispatching the state changes one-by-one to easy debugging
        _, events = wal.state_manager.dispatch([state_change])

        chain_state = wal.state_manager.current_state
        msg = "Chain state must never be cleared up."
        assert chain_state, msg

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state,
            to_canonical_address(token_network_address),
            to_canonical_address(partner_address),
        )

        if channel_state is None:
            continue

        ###
        # Customize this to filter things further somewhere around here.
        # An example would be to add `breakpoint()`
        # and inspect the state.
        ###
        print_state_change(state_change, translator=translator)
        print_events(chain.from_iterable(events), translator=translator)

        # Enable to print color coded presence state of channel partners
        # print_presence_view(chain_state, translator)

        # Enable to print balances & balance sum with all channel partners
        # print_node_balances(chain_state, token_network_address, translator)

        print_nl()
예제 #35
0
    def __init__(self,
                 message_handler=None,
                 state_transition=None,
                 private_key=None,
                 config=None):
        if private_key is None:
            self.privkey, self.address = factories.make_privkey_address()
        else:
            self.privkey = private_key
            self.address = privatekey_to_address(private_key)

        self.rpc_client = MockJSONRPCClient(self.address)
        self.proxy_manager = MockProxyManager(node_address=self.address)
        self.signer = LocalSigner(self.privkey)

        self.message_handler = message_handler
        self.routing_mode = RoutingMode.PRIVATE
        self.config = config

        self.user_deposit = Mock()
        self.default_registry = Mock()
        self.default_registry.address = factories.make_address()
        self.default_one_to_n_address = factories.make_address()
        self.default_msc_address = factories.make_address()

        self.targets_to_identifiers_to_statuses = defaultdict(dict)
        self.route_to_feedback_token = {}

        if state_transition is None:
            state_transition = node.state_transition

        serializer = JSONSerializer
        state_manager = StateManager(state_transition, None)
        storage = SerializedSQLiteStorage(":memory:", serializer)
        self.wal = WriteAheadLog(state_manager, storage)

        state_change = ActionInitChain(
            pseudo_random_generator=random.Random(),
            block_number=0,
            block_hash=factories.make_block_hash(),
            our_address=self.rpc_client.address,
            chain_id=self.rpc_client.chain_id,
        )

        self.wal.log_and_dispatch([state_change])
예제 #36
0
    def mediate_mediated_transfer(self, message):
        # pylint: disable=too-many-locals
        identifier = message.identifier
        amount = message.lock.amount
        target = message.target
        token = message.token
        graph = self.token_to_channelgraph[token]

        available_routes = get_best_routes(
            graph,
            self.protocol.nodeaddresses_networkstatuses,
            self.address,
            target,
            amount,
            message.sender,
        )

        from_channel = graph.partneraddress_to_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

        our_address = self.address
        from_transfer = lockedtransfer_from_message(message)
        route_state = RoutesState(available_routes)
        block_number = self.get_block_number()

        init_mediator = ActionInitMediator(
            our_address,
            from_transfer,
            route_state,
            from_route,
            block_number,
        )

        state_manager = StateManager(mediator.state_transition, None)

        self.state_machine_event_handler.log_and_dispatch(
            state_manager, init_mediator)

        self.identifier_to_statemanagers[identifier].append(state_manager)
예제 #37
0
    def __init__(self, message_handler=None, state_transition=None):
        self.chain = MockChain()
        self.private_key, self.address = factories.make_privatekey_address()

        self.chain.node_address = self.address
        self.message_handler = message_handler

        if state_transition is None:
            state_transition = node.state_transition

        serializer = JSONSerializer
        state_manager = StateManager(state_transition, None)
        storage = SQLiteStorage(':memory:', serializer)
        self.wal = WriteAheadLog(state_manager, storage)

        state_change = ActionInitChain(
            random.Random(),
            0,
            self.chain.node_address,
            self.chain.network_id,
        )

        self.wal.log_and_dispatch(state_change)
예제 #38
0
    def start_mediated_transfer(self, token_address, amount, identifier,
                                target):
        # pylint: disable=too-many-locals

        async_result = AsyncResult()
        graph = self.token_to_channelgraph[token_address]

        available_routes = get_best_routes(
            graph,
            self.protocol.nodeaddresses_networkstatuses,
            self.address,
            target,
            amount,
            None,
        )

        if not available_routes:
            async_result.set(False)
            return async_result

        self.protocol.start_health_check(target)

        if identifier is None:
            identifier = create_default_identifier()

        route_state = RoutesState(available_routes)
        our_address = self.address
        block_number = self.get_block_number()

        transfer_state = LockedTransferState(
            identifier=identifier,
            amount=amount,
            token=token_address,
            initiator=self.address,
            target=target,
            expiration=None,
            hashlock=None,
            secret=None,
        )

        # Issue #489
        #
        # Raiden may fail after a state change using the random generator is
        # handled but right before the snapshot is taken. If that happens on
        # the next initialization when raiden is recovering and applying the
        # pending state changes a new secret will be generated and the
        # resulting events won't match, this breaks the architecture model,
        # since it's assumed the re-execution of a state change will always
        # produce the same events.
        #
        # TODO: Removed the secret generator from the InitiatorState and add
        # the secret into all state changes that require one, this way the
        # secret will be serialized with the state change and the recovery will
        # use the same /random/ secret.
        random_generator = RandomSecretGenerator()

        init_initiator = ActionInitInitiator(
            our_address=our_address,
            transfer=transfer_state,
            routes=route_state,
            random_generator=random_generator,
            block_number=block_number,
        )

        state_manager = StateManager(initiator.state_transition, None)
        self.state_machine_event_handler.log_and_dispatch(
            state_manager, init_initiator)

        # TODO: implement the network timeout raiden.config['msg_timeout'] and
        # cancel the current transfer if it hapens (issue #374)
        self.identifier_to_statemanagers[identifier].append(state_manager)
        self.identifier_to_results[identifier].append(async_result)

        return async_result
def test_init_with_usable_routes():
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    init_state_change = make_init_statechange(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
    )

    expiration = block_number + factories.HOP1_TIMEOUT

    initiator_state_machine = StateManager(
        initiator.state_transition,
        None,
    )

    assert initiator_state_machine.current_state is None

    events = initiator_state_machine.dispatch(
        init_state_change,
    )

    initiator_state = initiator_state_machine.current_state
    assert isinstance(initiator_state, InitiatorState)
    assert initiator_state.our_address == our_address

    transfer = initiator_state.transfer
    assert isinstance(transfer, LockedTransferState)
    assert transfer.amount == amount
    assert transfer.target == target_address
    assert transfer.secret == secret_generator.secrets[0]
    assert transfer.hashlock == sha3(transfer.secret)

    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 == factories.UNIT_TOKEN_ADDRESS
    assert mediated_transfer.amount == amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration == expiration, 'transfer expiration mismatch'

    secret_hash = sha3(secret_generator.secrets[0])
    assert mediated_transfer.hashlock == secret_hash, 'wrong hashlock'
    assert mediated_transfer.receiver == mediator_address, 'wrong mediator address'

    assert initiator_state.route == routes[0]
    assert len(initiator_state.routes.available_routes) == 0
    assert len(initiator_state.routes.ignored_routes) == 0
    assert len(initiator_state.routes.refunded_routes) == 0
    assert len(initiator_state.routes.canceled_routes) == 0
예제 #40
0
def test_init_with_usable_routes():
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    init_state_change = make_init_statechange(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
    )

    expiration = block_number + factories.HOP1_TIMEOUT

    initiator_state_machine = StateManager(
        initiator.state_transition,
        None,
    )

    assert initiator_state_machine.current_state is None

    events = initiator_state_machine.dispatch(init_state_change, )

    initiator_state = initiator_state_machine.current_state
    assert isinstance(initiator_state, InitiatorState)
    assert initiator_state.our_address == our_address

    transfer = initiator_state.transfer
    assert isinstance(transfer, LockedTransferState)
    assert transfer.amount == amount
    assert transfer.target == target_address
    assert transfer.secret == secret_generator.secrets[0]
    assert transfer.hashlock == sha3(transfer.secret)

    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 == factories.UNIT_TOKEN_ADDRESS
    assert mediated_transfer.amount == amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration == expiration, 'transfer expiration mismatch'
    assert mediated_transfer.hashlock == sha3(
        secret_generator.secrets[0]), 'wrong hashlock'
    assert mediated_transfer.receiver == mediator_address, 'wrong mediator address'

    assert initiator_state.route == routes[0]
    assert len(initiator_state.routes.available_routes) == 0
    assert len(initiator_state.routes.ignored_routes) == 0
    assert len(initiator_state.routes.refunded_routes) == 0
    assert len(initiator_state.routes.canceled_routes) == 0