Пример #1
0
    def _initialize_payment_statuses(self, chain_state: ChainState):
        """ Re-initialize targets_to_identifiers_to_statuses.

        Restore the PaymentStatus for any pending payment. This is not tied to
        a specific protocol message but to the lifecycle of a payment, i.e.
        the status is re-created if a payment itself has not completed.
        """

        with self.payment_identifier_lock:
            for task in chain_state.payment_mapping.secrethashes_to_task.values(
            ):
                if not isinstance(task, InitiatorTask):
                    continue

                # Every transfer in the transfers_list must have the same target
                # and payment_identifier, so using the first transfer is
                # sufficient.
                initiator = next(
                    iter(task.manager_state.initiator_transfers.values()))
                transfer = initiator.transfer
                transfer_description = initiator.transfer_description
                target = transfer.target
                identifier = transfer.payment_identifier
                balance_proof = transfer.balance_proof
                self.targets_to_identifiers_to_statuses[target][
                    identifier] = PaymentStatus(
                        payment_identifier=identifier,
                        amount=transfer_description.amount,
                        token_network_identifier=TokenNetworkID(
                            balance_proof.token_network_identifier),
                        payment_done=AsyncResult(),
                    )
Пример #2
0
def handle_unlock(
    target_state: TargetTransferState,
    state_change: ReceiveUnlock,
    channel_state: NettingChannelState,
) -> TransitionResult[TargetTransferState]:
    """ Handles a ReceiveUnlock state change. """
    balance_proof_sender = state_change.balance_proof.sender

    is_valid, events, _ = channel.handle_unlock(channel_state, state_change)
    next_target_state: Optional[TargetTransferState] = target_state

    if is_valid:
        transfer = target_state.transfer
        payment_received_success = EventPaymentReceivedSuccess(
            payment_network_identifier=channel_state.payment_network_identifier,
            token_network_identifier=TokenNetworkID(channel_state.token_network_identifier),
            identifier=transfer.payment_identifier,
            amount=TokenAmount(transfer.lock.amount),
            initiator=transfer.initiator,
        )

        unlock_success = EventUnlockClaimSuccess(
            transfer.payment_identifier, transfer.lock.secrethash
        )

        send_processed = SendProcessed(
            recipient=balance_proof_sender,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=state_change.message_identifier,
        )

        events.extend([payment_received_success, unlock_success, send_processed])
        next_target_state = None

    return TransitionResult(next_target_state, events)
Пример #3
0
    def handle_message_refundtransfer(raiden: RaidenService,
                                      message: RefundTransfer):
        token_network_address = message.token_network_address
        from_transfer = lockedtransfersigned_from_message(message)
        chain_state = views.state_from_raiden(raiden)

        routes = get_best_routes(
            chain_state=chain_state,
            token_network_id=TokenNetworkID(token_network_address),
            from_address=InitiatorAddress(raiden.address),
            to_address=from_transfer.target,
            amount=from_transfer.lock.amount,
            previous_address=message.sender,
            config=raiden.config,
        )

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

        if role == 'initiator':
            secret = random_secret()
            state_change = ReceiveTransferRefundCancelRoute(
                routes=routes,
                transfer=from_transfer,
                secret=secret,
            )
        else:
            state_change = ReceiveTransferRefund(
                transfer=from_transfer,
                routes=routes,
            )

        raiden.handle_state_change(state_change)
Пример #4
0
def handle_cancelpayment(
    payment_state: InitiatorPaymentState,
    channelidentifiers_to_channels: ChannelMap
) -> TransitionResult[InitiatorPaymentState]:
    """ Cancel the payment and all related transfers. """
    # Cannot cancel a transfer after the secret is revealed
    events = list()
    for initiator_state in payment_state.initiator_transfers.values():
        channel_identifier = initiator_state.channel_identifier
        channel_state = channelidentifiers_to_channels.get(channel_identifier)

        if not channel_state:
            continue

        if can_cancel(initiator_state):
            transfer_description = initiator_state.transfer_description
            cancel_events = cancel_current_route(payment_state,
                                                 initiator_state)

            initiator_state.transfer_state = "transfer_cancelled"

            cancel = EventPaymentSentFailed(
                payment_network_identifier=channel_state.
                payment_network_identifier,
                token_network_identifier=TokenNetworkID(
                    channel_state.token_network_identifier),
                identifier=transfer_description.payment_identifier,
                target=transfer_description.target,
                reason="user canceled payment",
            )
            cancel_events.append(cancel)

            events.extend(cancel_events)

    return TransitionResult(payment_state, events)
Пример #5
0
def handle_init_mediator(
        chain_state: ChainState,
        state_change: ActionInitMediator) -> TransitionResult[ChainState]:
    transfer = state_change.from_transfer
    secrethash = transfer.lock.secrethash
    token_network_identifier = transfer.balance_proof.token_network_identifier

    return subdispatch_mediatortask(chain_state, state_change,
                                    TokenNetworkID(token_network_identifier),
                                    secrethash)
Пример #6
0
def get_channelstate_by_canonical_identifier(
    chain_state: ChainState, canonical_identifier: CanonicalIdentifier
) -> Optional[NettingChannelState]:
    """ Return the NettingChannelState if it exists, None otherwise. """
    token_network = get_token_network_by_identifier(
        chain_state,
        TokenNetworkID(canonical_identifier.token_network_address))

    channel_state = None
    if token_network:
        channel_state = token_network.channelidentifiers_to_channels.get(
            canonical_identifier.channel_identifier)

    return channel_state
Пример #7
0
def handle_init_target(
        chain_state: ChainState,
        state_change: ActionInitTarget) -> TransitionResult[ChainState]:
    transfer = state_change.transfer
    secrethash = transfer.lock.secrethash
    channel_identifier = transfer.balance_proof.channel_identifier
    token_network_identifier = transfer.balance_proof.token_network_identifier

    return subdispatch_targettask(
        chain_state,
        state_change,
        TokenNetworkID(token_network_identifier),
        channel_identifier,
        secrethash,
    )
Пример #8
0
def get_token_network_by_address(
    chain_state: ChainState, token_network_address: Union[TokenNetworkID,
                                                          TokenNetworkAddress]
) -> Optional[TokenNetworkState]:
    payment_network_identifier = chain_state.tokennetworkaddresses_to_paymentnetworkaddresses.get(
        TokenNetworkAddress(token_network_address))

    payment_network_state = None
    if payment_network_identifier:
        payment_network_state = chain_state.identifiers_to_paymentnetworks.get(
            payment_network_identifier)

    token_network_state = None
    if payment_network_state:
        token_network_state = payment_network_state.tokenidentifiers_to_tokennetworks.get(
            TokenNetworkID(token_network_address))

    return token_network_state
Пример #9
0
def mediator_init(raiden, transfer: LockedTransfer) -> ActionInitMediator:
    from_transfer = lockedtransfersigned_from_message(transfer)
    # Feedback token not used here, will be removed with source routing
    routes, _ = routing.get_best_routes(
        chain_state=views.state_from_raiden(raiden),
        token_network_id=TokenNetworkID(
            from_transfer.balance_proof.token_network_identifier),
        one_to_n_address=raiden.default_one_to_n_address,
        from_address=raiden.address,
        to_address=from_transfer.target,
        amount=PaymentAmount(from_transfer.lock.amount
                             ),  # FIXME: mypy; deprecated through #3863
        previous_address=transfer.sender,
        config=raiden.config,
        privkey=raiden.privkey,
    )
    from_route = RouteState(transfer.sender,
                            from_transfer.balance_proof.channel_identifier)
    return ActionInitMediator(routes, from_route, from_transfer)
Пример #10
0
def mediator_init(raiden, transfer: LockedTransfer):
    from_transfer = lockedtransfersigned_from_message(transfer)
    routes = routing.get_best_routes(
        chain_state=views.state_from_raiden(raiden),
        token_network_id=TokenNetworkID(
            from_transfer.balance_proof.token_network_identifier),
        from_address=raiden.address,
        to_address=from_transfer.target,
        amount=PaymentAmount(from_transfer.lock.amount
                             ),  # FIXME: mypy; deprecated through #3863
        previous_address=transfer.sender,
        config=raiden.config,
        privkey=raiden.privkey,
    )
    from_route = RouteState(transfer.sender,
                            from_transfer.balance_proof.channel_identifier)
    init_mediator_statechange = ActionInitMediator(routes, from_route,
                                                   from_transfer)
    return init_mediator_statechange
Пример #11
0
def get_channelstate_by_canonical_identifier_and_address(
        chain_state: ChainState, canonical_identifier: CanonicalIdentifier,
        address: AddressHex) -> Optional[NettingChannelState]:
    """ Return the NettingChannelState if it exists, None otherwise. """
    token_network = get_token_network_by_identifier(
        chain_state,
        TokenNetworkID(canonical_identifier.token_network_address))

    channel_state = None
    if token_network and address in token_network.channelidentifiers_to_channels:
        channel_state = token_network.channelidentifiers_to_channels[
            address].get(canonical_identifier.channel_identifier)
    else:
        # Get the channel by the light client associated with the participant and the canonical id
        lc_address = get_lc_address_by_channel_id_and_partner(
            token_network, address, canonical_identifier)
        if lc_address in token_network.channelidentifiers_to_channels:
            channel_state = token_network.channelidentifiers_to_channels[
                lc_address].get(canonical_identifier.channel_identifier)
    return channel_state
Пример #12
0
def events_for_unlock_base(
    initiator_state: InitiatorTransferState,
    channel_state: NettingChannelState,
    secret: Secret
) -> List[Event]:
    transfer_description = initiator_state.transfer_description
    payment_sent_success = EventPaymentSentSuccess(
        payment_network_identifier=channel_state.payment_network_identifier,
        token_network_identifier=TokenNetworkID(channel_state.token_network_identifier),
        identifier=transfer_description.payment_identifier,
        amount=transfer_description.amount,
        target=transfer_description.target,
        secret=secret,
    )

    unlock_success = EventUnlockSuccess(
        transfer_description.payment_identifier, transfer_description.secrethash
    )

    return [payment_sent_success, unlock_success]
Пример #13
0
    def handle_message_refundtransfer(raiden: RaidenService,
                                      message: RefundTransfer) -> None:
        token_network_address = message.token_network_address
        from_transfer = lockedtransfersigned_from_message(message)
        chain_state = views.state_from_raiden(raiden)

        # FIXME: Shouldn't request routes here
        routes, _ = get_best_routes(
            chain_state=chain_state,
            token_network_id=TokenNetworkID(token_network_address),
            one_to_n_address=raiden.default_one_to_n_address,
            from_address=InitiatorAddress(raiden.address),
            to_address=from_transfer.target,
            amount=PaymentAmount(
                from_transfer.lock.amount),  # FIXME: mypy; deprecated by #3863
            previous_address=message.sender,
            config=raiden.config,
            privkey=raiden.privkey,
        )

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

        state_change: StateChange
        if role == "initiator":
            old_secret = views.get_transfer_secret(
                chain_state, from_transfer.lock.secrethash)
            # We currently don't allow multi routes if the initiator does not
            # hold the secret. In such case we remove all other possible routes
            # which allow the API call to return with with an error message.
            if old_secret == EMPTY_SECRET:
                routes = list()

            secret = random_secret()
            state_change = ReceiveTransferRefundCancelRoute(
                routes=routes, transfer=from_transfer, secret=secret)
        else:
            state_change = ReceiveTransferRefund(transfer=from_transfer,
                                                 routes=routes)

        raiden.handle_and_track_state_change(state_change)
Пример #14
0
def handle_unlock_light(
    target_state: TargetTransferState,
    state_change: ReceiveUnlockLight,
    channel_state: NettingChannelState,
) -> TransitionResult[TargetTransferState]:
    """ Handles a ReceiveUnlockLight state change. """

    is_valid, events, _ = channel.handle_unlock_light(channel_state, state_change)
    next_target_state: Optional[TargetTransferState] = target_state

    if is_valid:
        transfer = target_state.transfer
        payment_received_success = EventPaymentReceivedSuccess(
            payment_network_identifier=channel_state.payment_network_identifier,
            token_network_identifier=TokenNetworkID(channel_state.token_network_identifier),
            identifier=transfer.payment_identifier,
            amount=TokenAmount(transfer.lock.amount),
            initiator=transfer.initiator,
        )

        unlock_success = EventUnlockClaimSuccess(
            transfer.payment_identifier, transfer.lock.secrethash
        )

        store_unlock_message = StoreMessageEvent(
            state_change.signed_unlock.message_identifier,
            state_change.signed_unlock.payment_identifier,
            11,
            state_change.signed_unlock,
            True
        )

        events.extend([payment_received_success, unlock_success, store_unlock_message])
        next_target_state = None

    return TransitionResult(next_target_state, events)
Пример #15
0
def events_for_unlock_lock(
    initiator_state: InitiatorTransferState,
    channel_state: NettingChannelState,
    secret: Secret,
    secrethash: SecretHash,
    pseudo_random_generator: random.Random,
) -> List[Event]:
    """ Unlocks the lock offchain, and emits the events for the successful payment. """
    # next hop learned the secret, unlock the token locally and send the
    # lock claim message to next hop
    transfer_description = initiator_state.transfer_description

    message_identifier = message_identifier_from_prng(pseudo_random_generator)
    unlock_lock = channel.send_unlock(
        channel_state=channel_state,
        message_identifier=message_identifier,
        payment_identifier=transfer_description.payment_identifier,
        secret=secret,
        secrethash=secrethash,
    )

    payment_sent_success = EventPaymentSentSuccess(
        payment_network_identifier=channel_state.payment_network_identifier,
        token_network_identifier=TokenNetworkID(
            channel_state.token_network_identifier),
        identifier=transfer_description.payment_identifier,
        amount=transfer_description.amount,
        target=transfer_description.target,
        secret=secret,
    )

    unlock_success = EventUnlockSuccess(
        transfer_description.payment_identifier,
        transfer_description.secrethash)

    return [unlock_lock, payment_sent_success, unlock_success]
Пример #16
0
    def handle_contract_send_channelunlock(
        raiden: "RaidenService",
        chain_state: ChainState,
        channel_unlock_event: ContractSendChannelBatchUnlock,
    ):
        assert raiden.wal, "The Raiden Service must be initialize to handle events"

        canonical_identifier = channel_unlock_event.canonical_identifier
        token_network_identifier = canonical_identifier.token_network_address
        channel_identifier = canonical_identifier.channel_identifier
        participant = channel_unlock_event.participant

        payment_channel: PaymentChannel = raiden.chain.payment_channel(
            canonical_identifier=canonical_identifier
        )

        channel_state = get_channelstate_by_token_network_and_partner(
            chain_state=chain_state,
            token_network_id=TokenNetworkID(token_network_identifier),
            partner_address=participant,
        )

        if not channel_state:
            # channel was cleaned up already due to an unlock
            raise RaidenUnrecoverableError(
                f"Failed to find channel state with partner:"
                f"{to_checksum_address(participant)}, token_network:pex(token_network_identifier)"
            )

        our_address = channel_state.our_state.address
        our_locksroot = channel_state.our_state.onchain_locksroot

        partner_address = channel_state.partner_state.address
        partner_locksroot = channel_state.partner_state.onchain_locksroot

        # we want to unlock because there are on-chain unlocked locks
        search_events = our_locksroot != EMPTY_HASH
        # we want to unlock, because there are unlocked/unclaimed locks
        search_state_changes = partner_locksroot != EMPTY_HASH

        if not search_events and not search_state_changes:
            # In the case that someone else sent the unlock we do nothing
            # Check https://github.com/raiden-network/raiden/issues/3152
            # for more details
            log.warning(
                "Onchain unlock already mined",
                canonical_identifier=canonical_identifier,
                channel_identifier=canonical_identifier.channel_identifier,
                participant=to_checksum_address(participant),
            )
            return

        if search_state_changes:
            state_change_record = get_state_change_with_balance_proof_by_locksroot(
                storage=raiden.wal.storage,
                canonical_identifier=canonical_identifier,
                locksroot=partner_locksroot,
                sender=partner_address,
            )
            state_change_identifier = state_change_record.state_change_identifier

            if not state_change_identifier:
                raise RaidenUnrecoverableError(
                    f"Failed to find state that matches the current channel locksroots. "
                    f"chain_id:{raiden.chain.network_id} "
                    f"token_network:{to_checksum_address(token_network_identifier)} "
                    f"channel:{channel_identifier} "
                    f"participant:{to_checksum_address(participant)} "
                    f"our_locksroot:{to_hex(our_locksroot)} "
                    f"partner_locksroot:{to_hex(partner_locksroot)} "
                )

            restored_channel_state = channel_state_until_state_change(
                raiden=raiden,
                canonical_identifier=canonical_identifier,
                state_change_identifier=state_change_identifier,
            )
            assert restored_channel_state is not None

            gain = get_batch_unlock_gain(restored_channel_state)

            skip_unlock = (
                restored_channel_state.partner_state.address == participant
                and gain.from_partner_locks == 0
            )
            if not skip_unlock:
                unlock(
                    raiden=raiden,
                    payment_channel=payment_channel,
                    end_state=restored_channel_state.partner_state,
                    participant=our_address,
                    partner=partner_address,
                )

        if search_events:
            event_record = get_event_with_balance_proof_by_locksroot(
                storage=raiden.wal.storage,
                canonical_identifier=canonical_identifier,
                locksroot=our_locksroot,
                recipient=partner_address,
            )
            state_change_identifier = event_record.state_change_identifier

            if not state_change_identifier:
                raise RaidenUnrecoverableError(
                    f"Failed to find event that match current channel locksroots. "
                    f"chain_id:{raiden.chain.network_id} "
                    f"token_network:{to_checksum_address(token_network_identifier)} "
                    f"channel:{channel_identifier} "
                    f"participant:{to_checksum_address(participant)} "
                    f"our_locksroot:{to_hex(our_locksroot)} "
                    f"partner_locksroot:{to_hex(partner_locksroot)} "
                )

            restored_channel_state = channel_state_until_state_change(
                raiden=raiden,
                canonical_identifier=canonical_identifier,
                state_change_identifier=state_change_identifier,
            )
            assert restored_channel_state is not None

            gain = get_batch_unlock_gain(restored_channel_state)

            skip_unlock = (
                restored_channel_state.our_state.address == participant
                and gain.from_our_locks == 0
            )
            if not skip_unlock:
                unlock(
                    raiden=raiden,
                    payment_channel=payment_channel,
                    end_state=restored_channel_state.our_state,
                    participant=partner_address,
                    partner=our_address,
                )
Пример #17
0
 def token_network_identifier(self) -> TokenNetworkID:
     return TokenNetworkID(self.canonical_identifier.token_network_address)
Пример #18
0
def get_channel_state(
    token_address: TokenAddress,
    payment_network_identifier: PaymentNetworkID,
    token_network_address: TokenNetworkAddress,
    reveal_timeout: BlockTimeout,
    payment_channel_proxy,
    opened_block_number: BlockNumber,
    opened_block_hash: BlockHash,
):
    channel_details = payment_channel_proxy.detail(opened_block_hash)

    our_state = NettingChannelEndState(
        channel_details.participants_data.our_details.address,
        channel_details.participants_data.our_details.deposit,
    )
    partner_state = NettingChannelEndState(
        channel_details.participants_data.partner_details.address,
        channel_details.participants_data.partner_details.deposit,
    )

    identifier = payment_channel_proxy.channel_identifier
    settle_timeout = payment_channel_proxy.settle_timeout()
    closed_block_number = payment_channel_proxy.close_block_number()

    # ignore bad open block numbers
    if opened_block_number <= 0:
        return None

    open_transaction = TransactionExecutionStatus(
        None,
        opened_block_number,
        TransactionExecutionStatus.SUCCESS,
    )

    if closed_block_number:
        close_transaction = TransactionExecutionStatus(
            None,
            closed_block_number,
            TransactionExecutionStatus.SUCCESS,
        )
    else:
        close_transaction = None

    # For the current implementation the channel is a smart contract that
    # will be killed on settle.
    settle_transaction = None

    channel = NettingChannelState(
        identifier=identifier,
        chain_id=channel_details.chain_id,
        token_address=token_address,
        payment_network_identifier=payment_network_identifier,
        token_network_identifier=TokenNetworkID(token_network_address),
        reveal_timeout=reveal_timeout,
        settle_timeout=settle_timeout,
        our_state=our_state,
        partner_state=partner_state,
        open_transaction=open_transaction,
        close_transaction=close_transaction,
        settle_transaction=settle_transaction,
    )

    return channel
Пример #19
0
def is_transaction_effect_satisfied(chain_state: ChainState,
                                    transaction: ContractSendEvent,
                                    state_change: StateChange) -> bool:
    """ True if the side-effect of `transaction` is satisfied by
    `state_change`.

    This predicate is used to clear the transaction queue. This should only be
    done once the expected side effect of a transaction is achieved. This
    doesn't necessarily mean that the transaction sent by *this* node was
    mined, but only that *some* transaction which achieves the same side-effect
    was successfully executed and mined. This distinction is important for
    restarts and to reduce the number of state changes.

    On restarts: The state of the on-chain channel could have changed while the
    node was offline. Once the node learns about the change (e.g. the channel
    was settled), new transactions can be dispatched by Raiden as a side effect for the
    on-chain *event* (e.g. do the batch unlock with the latest merkle tree),
    but the dispatched transaction could have been completed by another agent (e.g.
    the partner node). For these cases, the transaction from a different
    address which achieves the same side-effect is sufficient, otherwise
    unnecessary transactions would be sent by the node.

    NOTE: The above is not important for transactions sent as a side-effect for
    a new *block*. On restart the node first synchronizes its state by querying
    for new events, only after the off-chain state is up-to-date, a Block state
    change is dispatched. At this point some transactions are not required
    anymore and therefore are not dispatched.

    On the number of state changes: Accepting a transaction from another
    address removes the need for clearing state changes, e.g. when our
    node's close transaction fails but its partner's close transaction
    succeeds.
    """
    # These transactions are not made atomic through the WAL. They are sent
    # exclusively through the external APIs.
    #
    #  - ContractReceiveChannelNew
    #  - ContractReceiveChannelNewBalance
    #  - ContractReceiveNewPaymentNetwork
    #  - ContractReceiveNewTokenNetwork
    #  - ContractReceiveRouteNew
    #
    # Note: Deposits and Withdraws must consider a transaction with a higher
    # value as sufficient, because the values are monotonically increasing and
    # the transaction with a lower value will never be executed.

    # Transactions are used to change the on-chain state of a channel. It
    # doesn't matter if the sender of the transaction is the local node or
    # another node authorized to perform the operation. So, for the following
    # transactions, as long as the side-effects are the same, the local
    # transaction can be removed from the queue.
    #
    # - An update transfer can be done by a trusted third party (i.e. monitoring service)
    # - A close transaction can be sent by our partner
    # - A settle transaction can be sent by anyone
    # - A secret reveal can be done by anyone

    # - A lower nonce is not a valid replacement, since that is an older balance
    #   proof
    # - A larger raiden state change nonce is impossible.
    #   That would require the partner node to produce an invalid balance proof,
    #   and this node to accept the invalid balance proof and sign it
    is_valid_update_transfer = (
        isinstance(state_change, ContractReceiveUpdateTransfer)
        and isinstance(transaction, ContractSendChannelUpdateTransfer)
        and state_change.token_network_identifier
        == transaction.token_network_identifier
        and state_change.channel_identifier == transaction.channel_identifier
        and state_change.nonce == transaction.balance_proof.nonce)
    if is_valid_update_transfer:
        return True

    # The balance proof data cannot be verified, the local close could have
    # lost a race against a remote close, and the balance proof data would be
    # the one provided by this node's partner
    is_valid_close = (isinstance(state_change, ContractReceiveChannelClosed)
                      and isinstance(transaction, ContractSendChannelClose)
                      and state_change.token_network_identifier
                      == transaction.token_network_identifier
                      and state_change.channel_identifier
                      == transaction.channel_identifier)
    if is_valid_close:
        return True

    is_valid_settle = (isinstance(state_change, ContractReceiveChannelSettled)
                       and isinstance(transaction, ContractSendChannelSettle)
                       and state_change.token_network_identifier
                       == transaction.token_network_identifier
                       and state_change.channel_identifier
                       == transaction.channel_identifier)
    if is_valid_settle:
        return True

    is_valid_secret_reveal = (
        isinstance(state_change, ContractReceiveSecretReveal)
        and isinstance(transaction, ContractSendSecretReveal)
        and state_change.secret == transaction.secret)
    if is_valid_secret_reveal:
        return True

    is_batch_unlock = isinstance(
        state_change, ContractReceiveChannelBatchUnlock) and isinstance(
            transaction, ContractSendChannelBatchUnlock)
    if is_batch_unlock:
        assert isinstance(state_change,
                          ContractReceiveChannelBatchUnlock), MYPY_ANNOTATION
        assert isinstance(transaction,
                          ContractSendChannelBatchUnlock), MYPY_ANNOTATION

        our_address = chain_state.our_address

        # Don't assume that because we sent the transaction, we are a
        # participant
        partner_address = None
        if state_change.participant == our_address:
            partner_address = state_change.partner
        elif state_change.partner == our_address:
            partner_address = state_change.participant

        # Use the second address as the partner address, but check that a
        # channel exists for our_address and partner_address
        if partner_address:
            channel_state = views.get_channelstate_by_token_network_and_partner(
                chain_state,
                TokenNetworkID(state_change.token_network_identifier),
                partner_address)
            # If the channel was cleared, that means that both
            # sides of the channel were successfully unlocked.
            # In this case, we clear the batch unlock
            # transaction from the queue only in case there
            # were no more locked funds to unlock.
            if channel_state is None:
                return True

    return False
Пример #20
0
 def __init__(
         self,
         canonical_identifier: CanonicalIdentifier,
 ) -> None:
     self.token_network_identifier = TokenNetworkID(canonical_identifier.token_network_address)
     self.channel_identifier = canonical_identifier.channel_identifier