示例#1
0
def events_for_unlock_lock(
    initiator_state: InitiatorTransferState,
    channel_state: NettingChannelState,
    secret: typing.Secret,
    secrethash: typing.SecretHash,
    pseudo_random_generator: random.Random,
):
    # 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=channel_state.token_network_identifier,
        identifier=transfer_description.payment_identifier,
        amount=transfer_description.amount,
        target=transfer_description.target,
    )

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

    return [unlock_lock, payment_sent_success, unlock_success]
示例#2
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,
    )

    base_events = events_for_unlock_base(initiator_state, channel_state, secret)
    events = list()
    events.extend(base_events)
    events.append(unlock_lock)
    return events
示例#3
0
def claim_lock(app_chain, identifier, token, secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token)
        partner_channel = get_channelstate(to_, from_, token)

        unlock_lock = channel.send_unlock(
            from_channel,
            identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            unlock_lock.identifier,
            unlock_lock.balance_proof.nonce,
            unlock_lock.balance_proof.channel_address,
            unlock_lock.balance_proof.transferred_amount,
            unlock_lock.balance_proof.locksroot,
            unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            unlock_lock.secret,
            balance_proof,
        )

        is_valid, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
示例#4
0
def events_for_balanceproof(
    channelidentifiers_to_channels,
    transfers_pair,
    pseudo_random_generator,
    block_number,
    secret,
    secrethash,
):
    """ While it's safe do the off-chain unlock. """

    events = list()
    for pair in reversed(transfers_pair):
        payee_knows_secret = pair.payee_state in STATE_SECRET_KNOWN
        payee_payed = pair.payee_state in STATE_TRANSFER_PAID

        payee_channel = get_payee_channel(channelidentifiers_to_channels, pair)
        payee_channel_open = channel.get_status(
            payee_channel) == CHANNEL_STATE_OPENED

        payer_channel = get_payer_channel(channelidentifiers_to_channels, pair)

        # The mediator must not send to the payee a balance proof if the lock
        # is in the danger zone, because the payer may not do the same and the
        # on-chain unlock may fail. If the lock is nearing it's expiration
        # block, then on-chain unlock should be done, and if successfull it can
        # be unlocked off-chain.
        is_safe_to_send_balanceproof, _ = is_safe_to_wait(
            pair.payer_transfer.lock.expiration,
            payer_channel.reveal_timeout,
            block_number,
        )

        should_send_balanceproof_to_payee = (payee_channel_open
                                             and payee_knows_secret
                                             and not payee_payed
                                             and is_safe_to_send_balanceproof)

        if should_send_balanceproof_to_payee:
            pair.payee_state = 'payee_balance_proof'

            message_identifier = message_identifier_from_prng(
                pseudo_random_generator)
            unlock_lock = channel.send_unlock(
                payee_channel,
                pair.payee_transfer.payment_identifier,
                message_identifier,
                secret,
                secrethash,
            )

            unlock_success = EventUnlockSuccess(
                pair.payer_transfer.payment_identifier,
                pair.payer_transfer.lock.secrethash,
            )
            events.append(unlock_lock)
            events.append(unlock_success)

    return events
示例#5
0
def handle_offchain_secretreveal_light(
    initiator_state: InitiatorTransferState,
    state_change: ReceiveSecretRevealLight,
    channel_state: NettingChannelState,
    pseudo_random_generator: random.Random
) -> TransitionResult[InitiatorTransferState]:
    """ Once the next hop proves it knows the secret, the initiator can unlock
    the mediated transfer.

    This will validate the secret, and if valid a new balance proof is sent to
    the next hop with the current lock removed from the merkle tree and the
    transferred amount updated.
    """
    iteration: TransitionResult[InitiatorTransferState]
    valid_reveal = is_valid_secret_reveal(
        state_change=state_change,
        transfer_secrethash=initiator_state.transfer_description.secrethash,
        secret=state_change.secret,
    )
    sent_by_partner = state_change.sender == channel_state.partner_state.address
    is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED

    if valid_reveal and is_channel_open and sent_by_partner:
        unlock_events = events_for_unlock_base(
            initiator_state=initiator_state,
            channel_state=channel_state,
            secret=state_change.secret,
        )

        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=state_change.secret,
            secrethash=state_change.secrethash,
        )
        unlock_msg = Unlock.from_event(unlock_lock)

        store_received_secret_reveal_event = StoreMessageEvent(state_change.secret_reveal_message.message_identifier,
                                                               transfer_description.payment_identifier, 9,
                                                               state_change.secret_reveal_message,
                                                               True)
        store_created_unlock_event = StoreMessageEvent(message_identifier, transfer_description.payment_identifier, 11,
                                                       unlock_msg, False)

        events = list()
        events.append(store_received_secret_reveal_event)
        events.append(store_created_unlock_event)
        events.extend(unlock_events)
        iteration = TransitionResult(None, events)
    else:
        events = list()
        iteration = TransitionResult(initiator_state, events)

    return iteration
示例#6
0
def handle_secretreveal(
    initiator_state: InitiatorTransferState,
    state_change: ReceiveSecretReveal,
    channel_state: NettingChannelState,
    pseudo_random_generator: random.Random,
) -> TransitionResult:
    """ Send a balance proof to the next hop with the current mediated transfer
    lock removed and the balance updated.
    """
    is_valid_secret_reveal = (
        state_change.sender == channel_state.partner_state.address
        and state_change.secrethash
        == initiator_state.transfer_description.secrethash)

    # If the channel is closed the balance proof must not be sent
    is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED

    if is_valid_secret_reveal and is_channel_open:
        # 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,
            transfer_description.payment_identifier,
            message_identifier,
            state_change.secret,
            state_change.secrethash,
        )

        # TODO: Emit these events after on-chain unlock
        payment_sent_success = EventPaymentSentSuccess(
            payment_network_identifier=channel_state.
            payment_network_identifier,
            token_network_identifier=channel_state.token_network_identifier,
            identifier=transfer_description.payment_identifier,
            amount=transfer_description.amount,
            target=transfer_description.target,
        )

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

        iteration = TransitionResult(
            None, [payment_sent_success, unlock_success, unlock_lock])
    else:
        iteration = TransitionResult(initiator_state, list())

    return iteration
示例#7
0
def events_for_balanceproof(
    channelidentifiers_to_channels,
    transfers_pair,
    pseudo_random_generator,
    block_number,
    secret,
    secrethash,
):
    """ Send the balance proof to nodes that know the secret. """

    events = list()
    for pair in reversed(transfers_pair):
        payee_knows_secret = pair.payee_state in STATE_SECRET_KNOWN
        payee_payed = pair.payee_state in STATE_TRANSFER_PAID

        payee_channel = get_payee_channel(channelidentifiers_to_channels, pair)
        payee_channel_open = channel.get_status(
            payee_channel) == CHANNEL_STATE_OPENED

        # XXX: All nodes must close the channel and unlock on-chain if the
        # lock is nearing it's expiration block, what should be the strategy
        # for sending a balance proof to a node that knowns the secret but has
        # not gone on-chain while near the expiration? (The problem is how to
        # define the unsafe region, since that is a local configuration)
        lock_valid = is_lock_valid(pair.payee_transfer.lock.expiration,
                                   block_number)

        if payee_channel_open and payee_knows_secret and not payee_payed and lock_valid:
            pair.payee_state = 'payee_balance_proof'

            message_identifier = message_identifier_from_prng(
                pseudo_random_generator)
            unlock_lock = channel.send_unlock(
                payee_channel,
                pair.payee_transfer.payment_identifier,
                message_identifier,
                secret,
                secrethash,
            )

            unlock_success = EventUnlockSuccess(
                pair.payer_transfer.payment_identifier,
                pair.payer_transfer.lock.secrethash,
            )
            events.append(unlock_lock)
            events.append(unlock_success)

    return events
示例#8
0
def handle_secretreveal(
        initiator_state: InitiatorTransferState,
        state_change: ReceiveSecretReveal,
        channel_state: NettingChannelState,
        pseudo_random_generator: random.Random,
) -> TransitionResult:
    """ Send a balance proof to the next hop with the current mediated transfer
    lock removed and the balance updated.
    """
    is_valid_secret_reveal = (
        state_change.sender == channel_state.partner_state.address and
        state_change.secrethash == initiator_state.transfer_description.secrethash
    )

    # If the channel is closed the balance proof must not be sent
    is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED

    if is_valid_secret_reveal and is_channel_open:
        # 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,
            transfer_description.payment_identifier,
            message_identifier,
            state_change.secret,
            state_change.secrethash,
        )

        # TODO: Emit these events after on-chain unlock
        transfer_success = EventTransferSentSuccess(
            transfer_description.payment_identifier,
            transfer_description.amount,
            transfer_description.target,
        )

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

        iteration = TransitionResult(None, [transfer_success, unlock_success, unlock_lock])
    else:
        iteration = TransitionResult(initiator_state, list())

    return iteration
示例#9
0
def handle_secretreveal(
    initiator_state: InitiatorTransferState,
    state_change: ReceiveSecretReveal,
    channel_state: NettingChannelState,
) -> TransitionResult:
    """ Send a balance proof to the next hop with the current mediated transfer
    lock removed and the balance updated.
    """
    is_valid_secret_reveal = (state_change.sender
                              == channel_state.partner_state.address
                              and state_change.hashlock
                              == initiator_state.transfer_description.hashlock)

    # If the channel is closed the balance proof must not be sent
    is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED

    if is_valid_secret_reveal and is_channel_open:
        # next hop learned the secret, unlock the token locally and send the
        # withdraw message to next hop
        transfer_description = initiator_state.transfer_description

        unlock_lock = channel.send_unlock(
            channel_state,
            transfer_description.identifier,
            state_change.secret,
            state_change.hashlock,
        )

        # TODO: Emit these events after on-chain withdraw
        transfer_success = EventTransferSentSuccess(
            transfer_description.identifier,
            transfer_description.amount,
            transfer_description.target,
        )

        unlock_success = EventUnlockSuccess(
            transfer_description.identifier,
            transfer_description.hashlock,
        )

        iteration = TransitionResult(
            None, [transfer_success, unlock_success, unlock_lock])
    else:
        iteration = TransitionResult(initiator_state, list())

    return iteration
示例#10
0
def events_for_balanceproof(
        channelidentifiers_to_channels,
        transfers_pair,
        pseudo_random_generator,
        block_number,
        secret,
        secrethash,
):
    """ Send the balance proof to nodes that know the secret. """

    events = list()
    for pair in reversed(transfers_pair):
        payee_knows_secret = pair.payee_state in STATE_SECRET_KNOWN
        payee_payed = pair.payee_state in STATE_TRANSFER_PAID

        payee_channel = get_payee_channel(channelidentifiers_to_channels, pair)
        payee_channel_open = channel.get_status(payee_channel) == CHANNEL_STATE_OPENED

        # XXX: All nodes must close the channel and unlock on-chain if the
        # lock is nearing it's expiration block, what should be the strategy
        # for sending a balance proof to a node that knowns the secret but has
        # not gone on-chain while near the expiration? (The problem is how to
        # define the unsafe region, since that is a local configuration)
        lock_valid = is_lock_valid(pair.payee_transfer.lock.expiration, block_number)

        if payee_channel_open and payee_knows_secret and not payee_payed and lock_valid:
            pair.payee_state = 'payee_balance_proof'

            message_identifier = message_identifier_from_prng(pseudo_random_generator)
            unlock_lock = channel.send_unlock(
                payee_channel,
                pair.payee_transfer.payment_identifier,
                message_identifier,
                secret,
                secrethash,
            )

            unlock_success = EventUnlockSuccess(
                pair.payer_transfer.payment_identifier,
                pair.payer_transfer.lock.secrethash,
            )
            events.append(unlock_lock)
            events.append(unlock_success)

    return events
示例#11
0
def claim_lock(app_chain, payment_identifier, token_network_identifier,
               secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token_network_identifier)
        partner_channel = get_channelstate(to_, from_,
                                           token_network_identifier)

        unlock_lock = channel.send_unlock(
            from_channel,
            random.randint(0, UINT64_MAX),
            payment_identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            chain_id=unlock_lock.balance_proof.chain_id,
            message_identifier=unlock_lock.message_identifier,
            payment_identifier=unlock_lock.payment_identifier,
            nonce=unlock_lock.balance_proof.nonce,
            token_network_address=partner_channel.token_network_identifier,
            channel_identifier=unlock_lock.balance_proof.channel_identifier,
            transferred_amount=unlock_lock.balance_proof.transferred_amount,
            locked_amount=unlock_lock.balance_proof.locked_amount,
            locksroot=unlock_lock.balance_proof.locksroot,
            secret=unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            message_identifier=random.randint(0, UINT64_MAX),
            secret=unlock_lock.secret,
            balance_proof=balance_proof,
        )

        is_valid, _, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
示例#12
0
def claim_lock(app_chain, payment_identifier, token_network_identifier, secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token_network_identifier)
        partner_channel = get_channelstate(to_, from_, token_network_identifier)

        unlock_lock = channel.send_unlock(
            from_channel,
            random.randint(0, UINT64_MAX),
            payment_identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            unlock_lock.balance_proof.chain_id,
            unlock_lock.message_identifier,
            unlock_lock.payment_identifier,
            unlock_lock.balance_proof.nonce,
            partner_channel.token_network_identifier,
            unlock_lock.balance_proof.channel_address,
            unlock_lock.balance_proof.transferred_amount,
            unlock_lock.balance_proof.locked_amount,
            unlock_lock.balance_proof.locksroot,
            unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            message_identifier=random.randint(0, UINT64_MAX),
            secret=unlock_lock.secret,
            balance_proof=balance_proof,
        )

        is_valid, _, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
示例#13
0
def events_for_unlock_lock(
    initiator_state: InitiatorTransferState,
    channel_state: NettingChannelState,
    secret: Secret,
    secrethash: SecretHash,
    pseudo_random_generator: random.Random,
    block_number: BlockNumber,
) -> 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,
        block_number=block_number,
    )

    payment_sent_success = EventPaymentSentSuccess(
        token_network_registry_address=channel_state.
        token_network_registry_address,
        token_network_address=channel_state.token_network_address,
        identifier=transfer_description.payment_identifier,
        amount=transfer_description.amount,
        target=transfer_description.target,
        secret=secret,
        route=initiator_state.route.route,
    )

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

    return [unlock_lock, payment_sent_success, unlock_success]