Esempio n. 1
0
def test_events_for_onchain_secretreveal():
    """ Secret must be registered on-chain when the unsafe region is reached and
    the secret is known.
    """
    block_number = 10
    expiration = block_number + 30

    channels = make_channel_set([channel_properties])
    from_transfer = make_target_transfer(channels[0], expiration=expiration)

    channel.handle_receive_lockedtransfer(channels[0], from_transfer)

    channel.register_offchain_secret(channels[0], UNIT_SECRET, UNIT_SECRETHASH)

    safe_to_wait = expiration - channels[0].reveal_timeout - 1
    unsafe_to_wait = expiration - channels[0].reveal_timeout

    state = TargetTransferState(channels.get_route(0), from_transfer)
    events = target.events_for_onchain_secretreveal(state, channels[0], safe_to_wait)
    assert not events

    events = target.events_for_onchain_secretreveal(state, channels[0], unsafe_to_wait)

    msg = 'when its not safe to wait, the contract send must be emitted'
    assert must_contain_entry(events, ContractSendSecretReveal, {'secret': UNIT_SECRET}), msg

    msg = 'second call must not emit ContractSendSecretReveal again'
    assert not target.events_for_onchain_secretreveal(state, channels[0], unsafe_to_wait), msg
Esempio n. 2
0
def make_mediated_transfer(
    from_channel,
    partner_channel,
    initiator,
    target,
    lock,
    pkey,
    secret=None,
):
    """ Helper to create and register a mediated transfer from `from_channel` to
    `partner_channel`."""
    payment_identifier = channel.get_next_nonce(from_channel.our_state)
    message_identifier = random.randint(0, UINT64_MAX)

    lockedtransfer = channel.send_lockedtransfer(
        from_channel,
        initiator,
        target,
        lock.amount,
        message_identifier,
        payment_identifier,
        lock.expiration,
        lock.secrethash,
    )
    mediated_transfer_msg = LockedTransfer.from_event(lockedtransfer)

    mediated_transfer_msg.sign(LocalSigner(pkey))

    # compute the signature
    balance_proof = balanceproof_from_envelope(mediated_transfer_msg)
    lockedtransfer.balance_proof = balance_proof

    # if this fails it's not the right key for the current `from_channel`
    assert mediated_transfer_msg.sender == from_channel.our_state.address
    receive_lockedtransfer = lockedtransfersigned_from_message(
        mediated_transfer_msg)

    channel.handle_receive_lockedtransfer(
        partner_channel,
        receive_lockedtransfer,
    )

    if secret is not None:
        secrethash = sha3(secret)

        channel.register_offchain_secret(from_channel, secret, secrethash)
        channel.register_offchain_secret(partner_channel, secret, secrethash)

    return mediated_transfer_msg
Esempio n. 3
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
Esempio n. 4
0
def test_events_for_onchain_secretreveal():
    """ Secret must be registered on-chain when the unsafe region is reached and
    the secret is known.
    """
    amount = 3
    block_number = 10
    expiration = block_number + 30
    initiator = HOP1
    target_address = UNIT_TRANSFER_TARGET

    from_channel = factories.make_channel(
        our_address=target_address,
        partner_address=UNIT_TRANSFER_SENDER,
        partner_balance=amount,
    )
    from_route = factories.route_from_channel(from_channel)

    from_transfer = factories.make_signed_transfer_for(
        from_channel,
        amount,
        initiator,
        target_address,
        expiration,
        UNIT_SECRET,
    )

    channel.handle_receive_lockedtransfer(
        from_channel,
        from_transfer,
    )

    channel.register_offchain_secret(from_channel, UNIT_SECRET,
                                     UNIT_SECRETHASH)

    safe_to_wait = expiration - from_channel.reveal_timeout - 1
    unsafe_to_wait = expiration - from_channel.reveal_timeout

    state = TargetTransferState(from_route, from_transfer)
    events = target.events_for_onchain_secretreveal(state, from_channel,
                                                    safe_to_wait)
    assert not events

    events = target.events_for_onchain_secretreveal(state, from_channel,
                                                    unsafe_to_wait)
    assert events
    assert isinstance(events[0], ContractSendSecretReveal)
    assert events[0].secret == UNIT_SECRET
Esempio n. 5
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
Esempio n. 6
0
def test_events_for_onchain_secretreveal():
    """ Secret must be registered on-chain when the unsafe region is reached and
    the secret is known.
    """
    block_number = 10
    expiration = block_number + 30

    channels = make_channel_set([channel_properties])
    from_transfer = make_target_transfer(channels[0], expiration=expiration)

    channel.handle_receive_lockedtransfer(channels[0], from_transfer)

    channel.register_offchain_secret(channels[0], UNIT_SECRET, UNIT_SECRETHASH)

    safe_to_wait = expiration - channels[0].reveal_timeout - 1
    unsafe_to_wait = expiration - channels[0].reveal_timeout

    state = TargetTransferState(channels.get_route(0), from_transfer)
    events = target.events_for_onchain_secretreveal(
        target_state=state,
        channel_state=channels[0],
        block_number=safe_to_wait,
        block_hash=factories.make_block_hash(),
    )
    assert not events

    events = target.events_for_onchain_secretreveal(
        target_state=state,
        channel_state=channels[0],
        block_number=unsafe_to_wait,
        block_hash=factories.make_block_hash(),
    )

    msg = "when its not safe to wait, the contract send must be emitted"
    assert search_for_item(events, ContractSendSecretReveal,
                           {"secret": UNIT_SECRET}), msg

    msg = "second call must not emit ContractSendSecretReveal again"
    assert not target.events_for_onchain_secretreveal(
        target_state=state,
        channel_state=channels[0],
        block_number=unsafe_to_wait,
        block_hash=factories.make_block_hash(),
    ), msg
Esempio n. 7
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
Esempio n. 8
0
def set_offchain_secret(
        state: MediatorTransferState,
        channelidentifiers_to_channels: typing.ChannelMap,
        secret: typing.Secret,
        secrethash: typing.SecretHash,
) -> typing.List[Event]:
    """ Set the secret to all mediated transfers. """
    state.secret = secret

    for pair in state.transfers_pair:
        payer_channel = channelidentifiers_to_channels[
            pair.payer_transfer.balance_proof.channel_identifier
        ]
        channel.register_offchain_secret(
            payer_channel,
            secret,
            secrethash,
        )

        payee_channel = channelidentifiers_to_channels[
            pair.payee_transfer.balance_proof.channel_identifier
        ]
        channel.register_offchain_secret(
            payee_channel,
            secret,
            secrethash,
        )

    # The secret should never be revealed if `waiting_transfer` is not None.
    # For this to happen this node must have received a transfer, which it did
    # *not* mediate, and neverthless the secret was revealed.
    #
    # This can only be possible if the initiator reveals the secret without the
    # target's secret request, or if the node which sent the `waiting_transfer`
    # has sent another transfer which reached the target (meaning someone along
    # the path will lose tokens).
    if state.waiting_transfer:
        payer_channel = channelidentifiers_to_channels[
            state.waiting_transfer.transfer.balance_proof.channel_identifier
        ]
        channel.register_offchain_secret(
            payer_channel,
            secret,
            secrethash,
        )

        unexpected_reveal = EventUnexpectedSecretReveal(
            secrethash=secrethash,
            reason='The mediator has a waiting transfer.',
        )
        return [unexpected_reveal]

    return list()
Esempio n. 9
0
def test_secret_revealed(raiden_chain, deposit, settle_timeout, token_addresses):
    app0, app1, app2 = raiden_chain
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    app2.raiden.raiden_event_handler = hold_event_handler

    amount = 10
    identifier = 1
    target = app2.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    hold_event_handler.hold_secretrequest_for(secret)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        amount,
        target,
        identifier,
        secret,
    )

    gevent.sleep(.1)  # wait for the messages

    # The secret hasn't been revealed yet
    channel_state2_1 = get_channelstate(app2, app1, token_network_identifier)
    assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1

    channel.register_offchain_secret(channel_state2_1, secret, secrethash)

    # Close the channel
    # This needs to register the secrets on chain
    netting_channel_proxy = app2.raiden.chain.payment_channel(
        token_network_identifier,
        channel_state2_1.identifier,
    )
    netting_channel_proxy.channel_close(
        registry_address,
        channel_state2_1.partner_state.balance_proof,
    )

    settle_expiration = (
        app0.raiden.chain.block_number() +
        settle_timeout +
        DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS
    )
    wait_until_block(app0.raiden.chain, settle_expiration)

    assert_synced_channel_state(
        token_address,
        app1, deposit - amount, [],
        app2, deposit + amount, [],
    )

    assert_synced_channel_state(
        token_address,
        app0, deposit - amount, [],
        app1, deposit + amount, [],
    )