Пример #1
0
def events_for_close(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: typing.BlockNumber,
):
    """ Emits the event for closing the netting channel if the transfer needs
    to be settled on-chain.
    """
    transfer = target_state.transfer

    safe_to_wait, _ = is_safe_to_wait(
        transfer.lock.expiration,
        channel_state.reveal_timeout,
        block_number,
    )
    secret_known = channel.is_secret_known(
        channel_state.partner_state,
        transfer.lock.secrethash,
    )

    if not safe_to_wait and secret_known:
        target_state.state = 'waiting_close'
        return channel.events_for_close(channel_state, block_number)

    return list()
Пример #2
0
def events_for_onchain_secretreveal(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: BlockNumber,
    block_hash: BlockHash,
) -> List[Event]:
    """ Emits the event for revealing the secret on-chain if the transfer
    can not be settled off-chain.
    """
    transfer = target_state.transfer
    expiration = transfer.lock.expiration

    safe_to_wait = is_safe_to_wait(expiration, channel_state.reveal_timeout, block_number)
    secret_known_offchain = channel.is_secret_known_offchain(
        channel_state.partner_state, transfer.lock.secrethash
    )
    has_onchain_reveal_started = target_state.state == TargetTransferState.ONCHAIN_SECRET_REVEAL

    if not safe_to_wait and secret_known_offchain and not has_onchain_reveal_started:
        target_state.state = TargetTransferState.ONCHAIN_SECRET_REVEAL
        secret = channel.get_secret(channel_state.partner_state, transfer.lock.secrethash)
        assert secret, "secret should be known at this point"
        return secret_registry.events_for_onchain_secretreveal(
            channel_state=channel_state,
            secret=secret,
            expiration=expiration,
            block_hash=block_hash,
        )

    return list()
Пример #3
0
def handle_block(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: typing.BlockNumber,
):
    """ After Raiden learns about a new block this function must be called to
    handle expiration of the hash time lock.
    """
    transfer = target_state.transfer
    events = list()

    secret_known = channel.is_secret_known(
        channel_state.partner_state,
        transfer.lock.secrethash,
    )
    is_lock_expired = (not secret_known
                       and block_number > transfer.lock.expiration)

    if secret_known:
        events = events_for_onchain_secretreveal(
            target_state,
            channel_state,
            block_number,
        )
    elif is_lock_expired and target_state.state != 'expired':
        failed = EventUnlockClaimFailed(
            identifier=transfer.payment_identifier,
            secrethash=transfer.lock.secrethash,
            reason='lock expired',
        )
        target_state.state = 'expired'
        events = [failed]

    return TransitionResult(target_state, events)
Пример #4
0
def handle_block(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: typing.BlockNumber,
    pseudo_random_generator: random.Random,
):
    """ After Raiden learns about a new block this function must be called to
    handle expiration of the hash time lock.
    """
    transfer = target_state.transfer
    secret_known = channel.is_secret_known(
        channel_state.partner_state,
        transfer.lock.secrethash,
    )

    if not secret_known and block_number > transfer.lock.expiration:
        if target_state.state != 'expired':
            failed = EventUnlockClaimFailed(
                identifier=transfer.payment_identifier,
                secrethash=transfer.lock.secrethash,
                reason='lock expired',
            )
            target_state.state = 'expired'
            events = [failed]
        else:
            events = list()
    elif target_state.state != 'waiting_close':  # only emit the close event once
        events = events_for_onchain_secretreveal(target_state, channel_state,
                                                 block_number)
    else:
        events = list()

    iteration = TransitionResult(target_state, events)
    return iteration
Пример #5
0
def handle_secretreveal(
    target_state: TargetTransferState,
    state_change: ReceiveSecretReveal,
    channel_state: NettingChannelState,
    pseudo_random_generator: random.Random,
):
    """ Validates and handles a ReceiveSecretReveal state change. """
    valid_secret = state_change.secrethash == target_state.transfer.lock.secrethash
    waiting_for_secret = target_state.state == 'secret_request'

    if valid_secret and waiting_for_secret:
        if isinstance(state_change, ReceiveSecretReveal):
            channel.register_secret(
                channel_state,
                state_change.secret,
                state_change.secrethash,
            )
        elif isinstance(state_change, ContractReceiveSecretReveal):
            channel.register_onchain_secret(
                channel_state=channel_state,
                secret=state_change.secret,
                secrethash=state_change.secrethash,
                secret_reveal_block_number=state_change.block_number,
            )
        else:
            assert False, 'Got unexpected StateChange'

        route = target_state.route
        message_identifier = message_identifier_from_prng(
            pseudo_random_generator)
        target_state.state = 'reveal_secret'
        target_state.secret = state_change.secret
        recipient = route.node_address

        # Send the secret reveal message only once, delivery is guaranteed by
        # the transport and not by the state machine
        reveal = SendSecretReveal(
            recipient=recipient,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=message_identifier,
            secret=target_state.secret,
        )

        iteration = TransitionResult(target_state, [reveal])

    else:
        # TODO: event for byzantine behavior
        iteration = TransitionResult(target_state, list())

    return iteration
Пример #6
0
def handle_offchain_secretreveal(
    target_state: TargetTransferState,
    state_change: ReceiveSecretReveal,
    channel_state: NettingChannelState,
    pseudo_random_generator: random.Random,
    block_number: BlockNumber,
):
    """ Validates and handles a ReceiveSecretReveal state change. """
    valid_secret = is_valid_secret_reveal(
        state_change=state_change,
        transfer_secrethash=target_state.transfer.lock.secrethash,
        secret=state_change.secret,
    )
    has_transfer_expired = channel.transfer_expired(
        transfer=target_state.transfer,
        affected_channel=channel_state,
        block_number=block_number,
    )

    if valid_secret and not has_transfer_expired:
        channel.register_offchain_secret(
            channel_state=channel_state,
            secret=state_change.secret,
            secrethash=state_change.secrethash,
        )

        route = target_state.route
        message_identifier = message_identifier_from_prng(
            pseudo_random_generator)
        target_state.state = TargetTransferState.OFFCHAIN_SECRET_REVEAL
        target_state.secret = state_change.secret
        recipient = route.node_address

        reveal = SendSecretReveal(
            recipient=recipient,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=message_identifier,
            secret=target_state.secret,
        )

        iteration = TransitionResult(target_state, [reveal])

    else:
        # TODO: event for byzantine behavior
        iteration = TransitionResult(target_state, list())

    return iteration
Пример #7
0
def handle_offchain_secretreveal(
        target_state: TargetTransferState,
        state_change: ReceiveSecretReveal,
        channel_state: NettingChannelState,
        pseudo_random_generator: random.Random,
        block_number: BlockNumber,
):
    """ Validates and handles a ReceiveSecretReveal state change. """
    valid_secret = is_valid_secret_reveal(
        state_change=state_change,
        transfer_secrethash=target_state.transfer.lock.secrethash,
        secret=state_change.secret,
    )
    has_transfer_expired = channel.transfer_expired(
        transfer=target_state.transfer,
        affected_channel=channel_state,
        block_number=block_number,
    )

    if valid_secret and not has_transfer_expired:
        channel.register_offchain_secret(
            channel_state=channel_state,
            secret=state_change.secret,
            secrethash=state_change.secrethash,
        )

        route = target_state.route
        message_identifier = message_identifier_from_prng(pseudo_random_generator)
        target_state.state = TargetTransferState.OFFCHAIN_SECRET_REVEAL
        target_state.secret = state_change.secret
        recipient = route.node_address

        reveal = SendSecretReveal(
            recipient=recipient,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=message_identifier,
            secret=target_state.secret,
        )

        iteration = TransitionResult(target_state, [reveal])

    else:
        # TODO: event for byzantine behavior
        iteration = TransitionResult(target_state, list())

    return iteration
Пример #8
0
def handle_block(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: BlockNumber,
    block_hash: BlockHash,
) -> TransitionResult[TargetTransferState]:
    """ After Raiden learns about a new block this function must be called to
    handle expiration of the hash time lock.
    """
    transfer = target_state.transfer
    events = list()
    lock = transfer.lock

    secret_known = channel.is_secret_known(
        channel_state.partner_state,
        lock.secrethash,
    )
    lock_has_expired, _ = channel.is_lock_expired(
        end_state=channel_state.our_state,
        lock=lock,
        block_number=block_number,
        lock_expiration_threshold=channel.get_receiver_expiration_threshold(
            lock),
    )

    if lock_has_expired and target_state.state != 'expired':
        failed = EventUnlockClaimFailed(
            identifier=transfer.payment_identifier,
            secrethash=transfer.lock.secrethash,
            reason=f'lock expired',
        )
        target_state.state = TargetTransferState.EXPIRED
        events = [failed]
    elif secret_known:
        events = events_for_onchain_secretreveal(
            target_state=target_state,
            channel_state=channel_state,
            block_number=block_number,
            block_hash=block_hash,
        )

    return TransitionResult(target_state, events)
Пример #9
0
def handle_onchain_secretreveal(
    target_state: TargetTransferState,
    state_change: ContractReceiveSecretReveal,
    channel_state: NettingChannelState,
):
    """ Validates and handles a ContractReceiveSecretReveal state change. """
    valid_secret = state_change.secrethash == target_state.transfer.lock.secrethash

    if valid_secret:
        channel.register_onchain_secret(
            channel_state=channel_state,
            secret=state_change.secret,
            secrethash=state_change.secrethash,
            secret_reveal_block_number=state_change.block_number,
        )

        target_state.state = 'reveal_secret'
        target_state.secret = state_change.secret

    return TransitionResult(target_state, list())
Пример #10
0
def handle_block(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: typing.BlockNumber,
):
    """ After Raiden learns about a new block this function must be called to
    handle expiration of the hash time lock.
    """
    transfer = target_state.transfer
    events = list()
    lock = transfer.lock

    secret_known = channel.is_secret_known(
        channel_state.partner_state,
        lock.secrethash,
    )
    lock_has_expired, _ = channel.is_lock_expired(
        end_state=channel_state.our_state,
        lock=lock,
        block_number=block_number,
        lock_expiration_threshold=typing.BlockNumber(
            lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, ),
    )

    if lock_has_expired and target_state.state != 'expired':
        failed = EventUnlockClaimFailed(
            identifier=transfer.payment_identifier,
            secrethash=transfer.lock.secrethash,
            reason=f'lock expired',
        )
        target_state.state = 'expired'
        events = [failed]
    elif secret_known:
        events = events_for_onchain_secretreveal(
            target_state,
            channel_state,
            block_number,
        )

    return TransitionResult(target_state, events)
Пример #11
0
def handle_block(
        target_state: TargetTransferState,
        channel_state: NettingChannelState,
        block_number: BlockNumber,
):
    """ After Raiden learns about a new block this function must be called to
    handle expiration of the hash time lock.
    """
    transfer = target_state.transfer
    events = list()
    lock = transfer.lock

    secret_known = channel.is_secret_known(
        channel_state.partner_state,
        lock.secrethash,
    )
    lock_has_expired, _ = channel.is_lock_expired(
        end_state=channel_state.our_state,
        lock=lock,
        block_number=block_number,
        lock_expiration_threshold=channel.get_receiver_expiration_threshold(lock),
    )

    if lock_has_expired and target_state.state != 'expired':
        failed = EventUnlockClaimFailed(
            identifier=transfer.payment_identifier,
            secrethash=transfer.lock.secrethash,
            reason=f'lock expired',
        )
        target_state.state = TargetTransferState.EXPIRED
        events = [failed]
    elif secret_known:
        events = events_for_onchain_secretreveal(
            target_state,
            channel_state,
            block_number,
        )

    return TransitionResult(target_state, events)
Пример #12
0
def events_for_onchain_secretreveal(
        target_state: TargetTransferState,
        channel_state: NettingChannelState,
        block_number: BlockNumber,
):
    """ Emits the event for revealing the secret on-chain if the transfer
    can not be settled off-chain.
    """
    transfer = target_state.transfer
    expiration = transfer.lock.expiration

    safe_to_wait, _ = is_safe_to_wait(
        expiration,
        channel_state.reveal_timeout,
        block_number,
    )
    secret_known_offchain = channel.is_secret_known_offchain(
        channel_state.partner_state,
        transfer.lock.secrethash,
    )
    has_onchain_reveal_started = (
        target_state.state == TargetTransferState.ONCHAIN_SECRET_REVEAL
    )

    if not safe_to_wait and secret_known_offchain and not has_onchain_reveal_started:
        target_state.state = TargetTransferState.ONCHAIN_SECRET_REVEAL
        secret = channel.get_secret(
            channel_state.partner_state,
            transfer.lock.secrethash,
        )
        return secret_registry.events_for_onchain_secretreveal(
            channel_state,
            secret,
            expiration,
        )

    return list()
Пример #13
0
def handle_offchain_secretreveal(
    target_state: TargetTransferState,
    state_change: ReceiveSecretReveal,
    channel_state: NettingChannelState,
    pseudo_random_generator: random.Random,
):
    """ Validates and handles a ReceiveSecretReveal state change. """
    valid_secret = state_change.secrethash == target_state.transfer.lock.secrethash

    if valid_secret:
        channel.register_offchain_secret(
            channel_state=channel_state,
            secret=state_change.secret,
            secrethash=state_change.secrethash,
        )

        route = target_state.route
        message_identifier = message_identifier_from_prng(
            pseudo_random_generator)
        target_state.state = 'reveal_secret'
        target_state.secret = state_change.secret
        recipient = route.node_address

        reveal = SendSecretReveal(
            recipient=recipient,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=message_identifier,
            secret=target_state.secret,
        )

        iteration = TransitionResult(target_state, [reveal])

    else:
        # TODO: event for byzantine behavior
        iteration = TransitionResult(target_state, list())

    return iteration
Пример #14
0
def events_for_onchain_secretreveal(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: BlockNumber,
):
    """ Emits the event for revealing the secret on-chain if the transfer
    can not be settled off-chain.
    """
    transfer = target_state.transfer
    expiration = transfer.lock.expiration

    safe_to_wait, _ = is_safe_to_wait(
        expiration,
        channel_state.reveal_timeout,
        block_number,
    )
    secret_known_offchain = channel.is_secret_known_offchain(
        channel_state.partner_state,
        transfer.lock.secrethash,
    )
    has_onchain_reveal_started = (
        target_state.state == TargetTransferState.ONCHAIN_SECRET_REVEAL)

    if not safe_to_wait and secret_known_offchain and not has_onchain_reveal_started:
        target_state.state = TargetTransferState.ONCHAIN_SECRET_REVEAL
        secret = channel.get_secret(
            channel_state.partner_state,
            transfer.lock.secrethash,
        )
        return secret_registry.events_for_onchain_secretreveal(
            channel_state,
            secret,
            expiration,
        )

    return list()
Пример #15
0
def handle_onchain_secretreveal(
        target_state: TargetTransferState,
        state_change: ContractReceiveSecretReveal,
        channel_state: NettingChannelState,
):
    """ Validates and handles a ContractReceiveSecretReveal state change. """
    valid_secret = is_valid_secret_reveal(
        state_change=state_change,
        transfer_secrethash=target_state.transfer.lock.secrethash,
        secret=state_change.secret,
    )

    if valid_secret:
        channel.register_onchain_secret(
            channel_state=channel_state,
            secret=state_change.secret,
            secrethash=state_change.secrethash,
            secret_reveal_block_number=state_change.block_number,
        )

        target_state.state = TargetTransferState.ONCHAIN_UNLOCK
        target_state.secret = state_change.secret

    return TransitionResult(target_state, list())
Пример #16
0
def handle_offchain_secretreveal_light(
    target_state: TargetTransferState,
    state_change: ReceiveSecretRevealLight,
    channel_state: NettingChannelState,
    pseudo_random_generator: random.Random,
    block_number: BlockNumber,
) -> TransitionResult[TargetTransferState]:
    """ Validates and handles a ReceiveSecretReveal state change. """
    valid_secret = is_valid_secret_reveal(
        state_change=state_change,
        transfer_secrethash=target_state.transfer.lock.secrethash,
        secret=state_change.secret,
    )
    has_transfer_expired = channel.is_transfer_expired(
        transfer=target_state.transfer, affected_channel=channel_state, block_number=block_number
    )

    if valid_secret and not has_transfer_expired:
        # TODO mmarcosmartinez7 this cannot be done without LC interaction
        # channel.register_offchain_secret(
        #     channel_state=channel_state,
        #     secret=state_change.secret,
        #     secrethash=state_change.secrethash,
        # )

        route = target_state.route
        message_identifier = message_identifier_from_prng(pseudo_random_generator)
        target_state.state = TargetTransferState.OFFCHAIN_SECRET_REVEAL
        target_state.secret = state_change.secret
        recipient = route.node_address

        # Store reveal secret 7, create reveal secret 9 and store it for LC signing.

        received_reveal_secret = state_change.secret_reveal_message
        reveal_secret_to_send_event = SendSecretReveal(
            recipient=recipient,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=message_identifier,
            secret=target_state.secret,
        )
        reveal_secret_to_send_msg = message_from_sendevent(reveal_secret_to_send_event)

        store_received_reveal = StoreMessageEvent(
            received_reveal_secret.message_identifier,
            target_state.transfer.payment_identifier,
            7,
            received_reveal_secret,
            True
        )

        store_reveal_to_send = StoreMessageEvent(
            message_identifier,
            target_state.transfer.payment_identifier,
            9,
            reveal_secret_to_send_msg,
            False
        )

        iteration = TransitionResult(target_state, [store_received_reveal, store_reveal_to_send])

    else:
        # TODO: event for byzantine behavior
        iteration = TransitionResult(target_state, list())

    return iteration