Exemple #1
0
def test_get_secret():
    secret1 = factories.make_secret()
    secret2 = factories.make_secret()
    secrethash3 = factories.make_keccak_hash()
    secrethash4 = factories.make_keccak_hash()

    lock_state = HashTimeLockState(amount=10,
                                   expiration=10,
                                   secrethash=factories.UNIT_SECRETHASH)
    end_state = factories.create(factories.NettingChannelEndStateProperties())
    end_state = factories.replace(
        end_state,
        secrethashes_to_lockedlocks={secrethash3: lock_state},
        secrethashes_to_unlockedlocks={
            sha3(secret1): UnlockPartialProofState(lock=lock_state,
                                                   secret=secret1)
        },
        secrethashes_to_onchain_unlockedlocks={
            sha3(secret2): UnlockPartialProofState(lock=lock_state,
                                                   secret=secret2)
        },
    )

    assert get_secret(
        end_state,
        sha3(secret1)) == secret1  # known secret from offchain unlock
    assert get_secret(
        end_state,
        sha3(secret2)) == secret2  # known secret from offchain unlock
    assert get_secret(end_state,
                      secrethash3) is None  # known lock but not unlocked yet
    assert get_secret(end_state, secrethash4) is None  # unknown secrethash
Exemple #2
0
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()
Exemple #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()
Exemple #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()
Exemple #5
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()
Exemple #6
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
Exemple #7
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
Exemple #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
Exemple #9
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()
Exemple #10
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