Esempio n. 1
0
def restore_state(
    transition_function: Callable,
    storage: SerializedSQLiteStorage,
    state_change_identifier: StateChangeID,
    node_address: Address,
) -> Optional[State]:
    snapshot = storage.get_snapshot_before_state_change(
        state_change_identifier=state_change_identifier)

    if snapshot is None:
        return None

    log.debug(
        "Snapshot found",
        from_state_change_id=snapshot.state_change_identifier,
        to_state_change_id=state_change_identifier,
        node=to_checksum_address(node_address),
    )
    state, _ = replay_state_changes(
        node_address=node_address,
        state=snapshot.data,
        state_change_range=Range(snapshot.state_change_identifier,
                                 state_change_identifier),
        storage=storage,
        transition_function=transition_function,
    )
    return state
Esempio n. 2
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
Esempio n. 3
0
def test_get_state_change_with_balance_proof():
    """ All state changes which contain a balance proof must be found when
    querying the database.
    """
    serializer = JSONSerializer()
    storage = SerializedSQLiteStorage(":memory:", serializer)
    counter = itertools.count()

    balance_proof = make_signed_balance_proof_from_counter(counter)

    lock_expired = ReceiveLockExpired(
        sender=balance_proof.sender,
        balance_proof=balance_proof,
        secrethash=factories.make_secret_hash(next(counter)),
        message_identifier=MessageID(next(counter)),
    )

    received_balance_proof = make_signed_balance_proof_from_counter(counter)
    unlock = ReceiveUnlock(
        sender=received_balance_proof.sender,
        message_identifier=MessageID(next(counter)),
        secret=factories.make_secret(next(counter)),
        balance_proof=received_balance_proof,
    )
    transfer = make_signed_transfer_from_counter(counter)
    transfer_refund = ReceiveTransferRefund(
        transfer=transfer,
        balance_proof=transfer.balance_proof,
        sender=transfer.balance_proof.sender,  # pylint: disable=no-member
    )
    transfer = make_signed_transfer_from_counter(counter)
    transfer_reroute = ActionTransferReroute(
        transfer=transfer,
        balance_proof=transfer.balance_proof,
        sender=transfer.balance_proof.sender,  # pylint: disable=no-member
        secret=sha3(factories.make_secret(next(counter))),
    )
    mediator_from_route, mediator_signed_transfer = make_from_route_from_counter(
        counter)

    action_init_mediator = ActionInitMediator(
        route_states=[
            RouteState(
                route=[factories.make_address(),
                       factories.make_address()],
                forward_channel_id=factories.make_channel_identifier(),
            )
        ],
        from_hop=mediator_from_route,
        from_transfer=mediator_signed_transfer,
        balance_proof=mediator_signed_transfer.balance_proof,
        sender=mediator_signed_transfer.balance_proof.sender,  # pylint: disable=no-member
    )
    target_from_route, target_signed_transfer = make_from_route_from_counter(
        counter)
    action_init_target = ActionInitTarget(
        from_hop=target_from_route,
        transfer=target_signed_transfer,
        balance_proof=target_signed_transfer.balance_proof,
        sender=target_signed_transfer.balance_proof.sender,  # pylint: disable=no-member
    )

    statechanges_balanceproofs = [
        (lock_expired, lock_expired.balance_proof),
        (unlock, unlock.balance_proof),
        (transfer_refund, transfer_refund.transfer.balance_proof),
        (transfer_reroute, transfer_reroute.transfer.balance_proof),
        (action_init_mediator,
         action_init_mediator.from_transfer.balance_proof),
        (action_init_target, action_init_target.transfer.balance_proof),
    ]

    assert storage.count_state_changes() == 0

    state_change_ids = storage.write_state_changes(
        [state_change for state_change, _ in statechanges_balanceproofs])
    assert storage.count_state_changes() == len(statechanges_balanceproofs)

    msg_in_order = "Querying must return state changes in order"
    stored_statechanges_records = storage.get_statechanges_records_by_range(
        RANGE_ALL_STATE_CHANGES)
    assert len(stored_statechanges_records) == 6, msg_in_order

    pair_elements = zip(statechanges_balanceproofs, state_change_ids,
                        stored_statechanges_records)
    for statechange_balanceproof, statechange_id, record in pair_elements:
        assert record.data == statechange_balanceproof[0], msg_in_order
        assert record.state_change_identifier == statechange_id, msg_in_order

    # Make sure state changes are returned in the correct order in which they were stored
    stored_statechanges = storage.get_statechanges_by_range(
        Range(
            stored_statechanges_records[1].state_change_identifier,
            stored_statechanges_records[2].state_change_identifier,
        ))

    assert len(stored_statechanges) == 2
    assert isinstance(stored_statechanges[0], ReceiveUnlock)
    assert isinstance(stored_statechanges[1], ReceiveTransferRefund)

    for state_change, balance_proof in statechanges_balanceproofs:
        state_change_record = get_state_change_with_balance_proof_by_balance_hash(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            sender=balance_proof.sender,
            balance_hash=balance_proof.balance_hash,
        )
        assert state_change_record
        assert state_change_record.data == state_change

        state_change_record = get_state_change_with_balance_proof_by_locksroot(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            sender=balance_proof.sender,
            locksroot=balance_proof.locksroot,
        )
        assert state_change_record
        assert state_change_record.data == state_change

    storage.close()