示例#1
0
文件: target.py 项目: wx7063/raiden
def events_for_onchain_secretreveal(
    target_state: TargetTransferState,
    channel_state: NettingChannelState,
    block_number: typing.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,
    )

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

    return list()
示例#2
0
def events_for_onchain_secretreveal(target_state, channel_state, block_number):
    """ Emits the event for revealing the secret on-chain if the transfer cannot
    to be settled off-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:
        secret = channel.get_secret(
            channel_state.partner_state,
            transfer.lock.secrethash,
        )
        return secret_registry.events_for_onchain_secretreveal(
            channel_state,
            block_number,
            secret,
        )

    return list()
示例#3
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()
示例#4
0
def events_for_onchain_secretreveal(target_state, channel_state, block_number):
    """ Emits the event for revealing the secret on-chain if the transfer cannot
    to be settled off-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:
        secret = channel.get_secret(
            channel_state.partner_state,
            transfer.lock.secrethash,
        )
        return secret_registry.events_for_onchain_secretreveal(
            channel_state,
            block_number,
            secret,
        )

    return list()
示例#5
0
def test_events_for_onchain_secretreveal_with_unfit_channels():
    settle = factories.TransactionExecutionStatusProperties()
    settled = factories.create(
        factories.NettingChannelStateProperties(settle_transaction=settle))
    secret = factories.UNIT_SECRET
    block_hash = factories.make_block_hash()

    events = events_for_onchain_secretreveal(settled, secret, 10, block_hash)
    assert not events, "Secret reveal event should not be generated for settled channel"

    settle = factories.replace(settle,
                               result=TransactionExecutionStatus.FAILURE)
    unusable = factories.create(
        factories.NettingChannelStateProperties(settle_transaction=settle))

    events = events_for_onchain_secretreveal(unusable, secret, 10, block_hash)
    assert not events, "Secret reveal event should not be generated for unusable channel."
示例#6
0
def events_for_onchain_secretreveal_if_closed(
        channelmap: typing.ChannelMap,
        transfers_pair: typing.List[MediationPairState],
        secret: typing.Secret,
        secrethash: typing.SecretHash,
) -> typing.List[ContractSendSecretReveal]:
    """ Register the secret on-chain if the payer channel is already closed and
    the mediator learned the secret off-chain.

    Balance proofs are not exchanged for closed channels, so there is no reason
    to wait for the unsafe region to register secret.

    Note:

        If the secret is learned before the channel is closed, then the channel
        will register the secrets in bulk, not the transfer.
    """
    events = list()

    all_payer_channels = [
        get_payer_channel(channelmap, pair)
        for pair in transfers_pair
    ]
    transaction_sent = has_secret_registration_started(
        all_payer_channels,
        transfers_pair,
        secrethash,
    )

    # Just like the case for entering the danger zone, this will only consider
    # the transfers which have a pair.

    for pending_pair in get_pending_transfer_pairs(transfers_pair):
        payer_channel = get_payer_channel(channelmap, pending_pair)
        # Don't register the secret on-chain if the channel is open or settled
        if channel.get_status(payer_channel) == CHANNEL_STATE_CLOSED:
            pending_pair.payer_state = 'payer_waiting_secret_reveal'

            if not transaction_sent:
                partner_state = payer_channel.partner_state
                lock = channel.get_lock(partner_state, secrethash)
                reveal_events = secret_registry.events_for_onchain_secretreveal(
                    payer_channel,
                    secret,
                    lock.expiration,
                )
                events.extend(reveal_events)
                transaction_sent = True

    return events
示例#7
0
def events_for_onchain_secretreveal(
    channelidentifiers_to_channels,
    transfers_pair,
    block_number,
):
    """ Reveal the secret if a locks is in the unsafe region. """
    events = list()
    pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair)

    for pair in reversed(pending_transfers_pairs):
        payer_channel = get_payer_channel(channelidentifiers_to_channels, pair)
        expiration = pair.payer_transfer.lock.expiration

        safe_to_wait, _ = is_safe_to_wait(
            expiration,
            payer_channel.reveal_timeout,
            block_number,
        )

        # We check if the secret is already known by receiving a ReceiveSecretReveal state change
        secret_known = channel.is_secret_known(
            payer_channel.partner_state,
            pair.payer_transfer.lock.secrethash,
        )

        if not safe_to_wait and secret_known:
            secret = channel.get_secret(
                payer_channel.partner_state,
                pair.payer_transfer.lock.secrethash,
            )
            reveal_events = secret_registry.events_for_onchain_secretreveal(
                payer_channel,
                secret,
                expiration,
            )
            # short circuit because the secret needs to be revealed on-chain
            # only once
            return reveal_events

    return events
示例#8
0
def events_for_onchain_secretreveal(
    channelidentifiers_to_channels,
    transfers_pair,
    block_number,
):
    """ Reveal secrets for transfer locks that are in the unsafe region.
    """
    events = list()
    pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair)

    for pair in reversed(pending_transfers_pairs):
        payer_channel = get_payer_channel(channelidentifiers_to_channels, pair)

        safe_to_wait = is_safe_to_wait(
            pair.payer_transfer.lock.expiration,
            payer_channel.reveal_timeout,
            block_number,
        )

        # We check if the secret is already known by receiving a  ReceiveSecretReveal state change
        secret_known = channel.is_secret_known(
            payer_channel.partner_state,
            pair.payer_transfer.lock.secrethash,
        )

        if not safe_to_wait and secret_known:
            secret = channel.get_secret(
                payer_channel.partner_state,
                pair.payer_transfer.lock.secrethash,
            )
            reveal_events = secret_registry.events_for_onchain_secretreveal(
                payer_channel,
                block_number,
                secret,
            )
            events.extend(reveal_events)

    return events
示例#9
0
def events_for_onchain_secretreveal(
        channelidentifiers_to_channels,
        transfers_pair,
        block_number,
):
    """ Reveal secrets for transfer locks that are in the unsafe region.
    """
    events = list()
    pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair)

    for pair in reversed(pending_transfers_pairs):
        payer_channel = get_payer_channel(channelidentifiers_to_channels, pair)

        safe_to_wait = is_safe_to_wait(
            pair.payer_transfer.lock.expiration,
            payer_channel.reveal_timeout,
            block_number,
        )

        # We check if the secret is already known by receiving a  ReceiveSecretReveal state change
        secret_known = channel.is_secret_known(
            payer_channel.partner_state,
            pair.payer_transfer.lock.secrethash,
        )

        if not safe_to_wait and secret_known:
            secret = channel.get_secret(
                payer_channel.partner_state,
                pair.payer_transfer.lock.secrethash,
            )
            reveal_events = secret_registry.events_for_onchain_secretreveal(
                payer_channel,
                block_number,
                secret,
            )
            events.extend(reveal_events)

    return events
示例#10
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()
示例#11
0
def test_events_for_onchain_secretreveal_typechecks_secret():
    channel = factories.create(factories.NettingChannelStateProperties())
    block_hash = factories.make_block_hash()
    with pytest.raises(ValueError):
        events_for_onchain_secretreveal(channel, "This is an invalid secret",
                                        10, block_hash)
示例#12
0
def events_for_onchain_secretreveal_if_dangerzone(
        channelmap: typing.ChannelMap,
        secrethash: typing.SecretHash,
        transfers_pair: typing.List[MediationPairState],
        block_number: typing.BlockNumber,
) -> typing.List[Event]:
    """ Reveal the secret on-chain if the lock enters the unsafe region and the
    secret is not yet on-chain.
    """
    events = list()

    all_payer_channels = [
        get_payer_channel(channelmap, pair)
        for pair in transfers_pair
    ]
    transaction_sent = has_secret_registration_started(
        all_payer_channels,
        transfers_pair,
        secrethash,
    )

    # Only consider the transfers which have a pair. This means if we have a
    # waiting transfer and for some reason the node knows the secret, it will
    # not try to register it. Otherwise it would be possible for an attacker to
    # reveal the secret late, just to force the node to send an unecessary
    # transaction.

    for pair in get_pending_transfer_pairs(transfers_pair):
        payer_channel = get_payer_channel(channelmap, pair)
        lock = pair.payer_transfer.lock

        safe_to_wait, _ = is_safe_to_wait(
            lock.expiration,
            payer_channel.reveal_timeout,
            block_number,
        )

        secret_known = channel.is_secret_known(
            payer_channel.partner_state,
            pair.payer_transfer.lock.secrethash,
        )

        if not safe_to_wait and secret_known:
            pair.payer_state = 'payer_waiting_secret_reveal'

            if not transaction_sent:
                secret = channel.get_secret(
                    payer_channel.partner_state,
                    lock.secrethash,
                )

                reveal_events = secret_registry.events_for_onchain_secretreveal(
                    payer_channel,
                    secret,
                    lock.expiration,
                )
                events.extend(reveal_events)

                transaction_sent = True

    return events