Beispiel #1
0
def populate_token_network_random(token_network_model: TokenNetwork,
                                  private_keys: List[str]) -> None:
    # seed for pseudo-randomness from config constant, that changes from time to time
    random.seed(NUMBER_OF_CHANNELS)

    for channel_id_int in range(NUMBER_OF_CHANNELS):
        channel_id = ChannelID(channel_id_int)

        private_key1, private_key2 = random.sample(private_keys, 2)
        address1 = Address(private_key_to_address(private_key1))
        address2 = Address(private_key_to_address(private_key2))
        settle_timeout = 15
        token_network_model.handle_channel_opened_event(
            channel_id, address1, address2, settle_timeout)

        # deposit to channels
        deposit1 = TokenAmount(random.randint(0, 1000))
        deposit2 = TokenAmount(random.randint(0, 1000))
        address1, address2 = token_network_model.channel_id_to_addresses[
            channel_id]
        token_network_model.handle_channel_new_deposit_event(
            channel_id, address1, deposit1)
        token_network_model.handle_channel_new_deposit_event(
            channel_id, address2, deposit2)
        token_network_model.handle_channel_balance_update_message(
            UpdatePFS(
                canonical_identifier=CanonicalIdentifier(
                    chain_identifier=ChainID(1),
                    channel_identifier=channel_id,
                    token_network_address=TokenNetworkAddressBytes(
                        decode_hex(token_network_model.address)),
                ),
                updating_participant=decode_hex(address1),
                other_participant=decode_hex(address2),
                updating_nonce=Nonce(1),
                other_nonce=Nonce(1),
                updating_capacity=deposit1,
                other_capacity=deposit2,
                reveal_timeout=2,
                mediation_fee=FeeAmount(0),
            ))
        token_network_model.handle_channel_balance_update_message(
            UpdatePFS(
                canonical_identifier=CanonicalIdentifier(
                    chain_identifier=ChainID(1),
                    channel_identifier=channel_id,
                    token_network_address=TokenNetworkAddressBytes(
                        decode_hex(token_network_model.address)),
                ),
                updating_participant=decode_hex(address2),
                other_participant=decode_hex(address1),
                updating_nonce=Nonce(2),
                other_nonce=Nonce(1),
                updating_capacity=deposit2,
                other_capacity=deposit1,
                reveal_timeout=2,
                mediation_fee=FeeAmount(0),
            ))
Beispiel #2
0
def make_signed_balance_proof(
    nonce: typing.Nonce = EMPTY,
    transferred_amount: typing.TokenAmount = EMPTY,
    locked_amount: typing.TokenAmount = EMPTY,
    token_network_address: typing.TokenNetworkID = EMPTY,
    channel_identifier: typing.ChannelID = EMPTY,
    locksroot: typing.Locksroot = EMPTY,
    extra_hash: typing.Keccak256 = EMPTY,
    private_key: bytes = EMPTY,
    sender_address: typing.Address = EMPTY,
) -> BalanceProofSignedState:

    nonce = if_empty(nonce, make_uint256())
    transferred_amount = if_empty(transferred_amount, make_uint256())
    locked_amount = if_empty(locked_amount, make_uint256())
    token_network_address = if_empty(token_network_address, make_address())
    channel_identifier = if_empty(channel_identifier, make_uint256())
    locksroot = if_empty(locksroot, make_32bytes())
    extra_hash = if_empty(extra_hash, make_keccak_hash())
    private_key = if_empty(private_key, make_privatekey())
    sender_address = if_empty(sender_address, make_address())
    signer = LocalSigner(private_key)

    balance_hash = hash_balance_data(
        transferred_amount=transferred_amount,
        locked_amount=locked_amount,
        locksroot=locksroot,
    )
    data_to_sign = balance_proof.pack_balance_proof(
        nonce=nonce,
        balance_hash=balance_hash,
        additional_hash=extra_hash,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=UNIT_CHAIN_ID,
            token_network_address=token_network_address,
            channel_identifier=channel_identifier,
        ),
    )

    signature = signer.sign(data=data_to_sign)

    return BalanceProofSignedState(
        nonce=nonce,
        transferred_amount=transferred_amount,
        locked_amount=locked_amount,
        locksroot=locksroot,
        message_hash=extra_hash,
        signature=signature,
        sender=sender_address,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=UNIT_CHAIN_ID,
            token_network_address=token_network_address,
            channel_identifier=channel_identifier,
        ),
    )
Beispiel #3
0
def _get_onchain_locksroots(
    raiden: RaidenService,
    storage: SQLiteStorage,
    token_network: Dict[str, Any],
    channel: Dict[str, Any],
) -> Tuple[Locksroot, Locksroot]:
    channel_new_state_change = _find_channel_new_state_change(
        storage=storage,
        token_network_address=token_network['address'],
        channel_identifier=channel['identifier'],
    )

    if not channel_new_state_change:
        raise RaidenUnrecoverableError(
            f'Could not find the state change for channel {channel["identifier"]}, '
            f'token network address: {token_network["address"]} being created. ',
        )

    canonical_identifier = CanonicalIdentifier(
        chain_identifier=CHAIN_ID_UNSPECIFIED,
        token_network_address=to_canonical_address(token_network['address']),
        channel_identifier=int(channel['identifier']),
    )

    our_locksroot, partner_locksroot = get_onchain_locksroots(
        chain=raiden.chain,
        canonical_identifier=canonical_identifier,
        participant1=to_canonical_address(channel['our_state']['address']),
        participant2=to_canonical_address(channel['partner_state']['address']),
        block_identifier='latest',
    )
    return our_locksroot, partner_locksroot
Beispiel #4
0
def get_updatepfs_message(
    updating_participant: Address,
    other_participant: Address,
    chain_identifier=ChainID(1),
    channel_identifier=ChannelID(0),
    token_network_address:
    TokenNetworkAddressBytes = DEFAULT_TOKEN_NETWORK_ADDRESS_BYTES,
    updating_nonce=Nonce(1),
    other_nonce=Nonce(0),
    updating_capacity=TokenAmount(90),
    other_capacity=TokenAmount(110),
    reveal_timeout: int = 2,
    mediation_fee: FeeAmount = FeeAmount(0),
    privkey_signer: bytes = PRIVAT_KEY_EXAMPLE_1,
) -> UpdatePFS:
    updatepfs_message = UpdatePFS(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_identifier,
            channel_identifier=channel_identifier,
            token_network_address=token_network_address,
        ),
        updating_participant=decode_hex(updating_participant),
        other_participant=decode_hex(other_participant),
        updating_nonce=updating_nonce,
        other_nonce=other_nonce,
        updating_capacity=updating_capacity,
        other_capacity=other_capacity,
        reveal_timeout=reveal_timeout,
        mediation_fee=mediation_fee,
    )

    updatepfs_message.sign(LocalSigner(privkey_signer))

    return updatepfs_message
Beispiel #5
0
def _(properties, defaults=None) -> LockedTransferUnsignedState:
    defaults = defaults or LOCKED_TRANSFER_DEFAULTS
    parameters = _properties_to_dict(properties, defaults)

    lock = HashTimeLockState(
        amount=parameters.pop('amount'),
        expiration=parameters.pop('expiration'),
        secrethash=sha3(parameters.pop('secret')),
    )

    balance_proof_parameters = _properties_to_dict(
        parameters.pop('balance_proof'),
        defaults.balance_proof,
    )
    balance_proof_parameters['canonical_identifier'] = CanonicalIdentifier(
        chain_identifier=balance_proof_parameters.pop('chain_id'),
        token_network_address=balance_proof_parameters.pop(
            'token_network_identifier'),
        channel_identifier=balance_proof_parameters.pop('channel_identifier'),
    )
    if balance_proof_parameters['locksroot'] == EMPTY_MERKLE_ROOT:
        balance_proof_parameters['locksroot'] = lock.lockhash
    balance_proof = BalanceProofUnsignedState(**balance_proof_parameters)

    return LockedTransferUnsignedState(balance_proof=balance_proof,
                                       lock=lock,
                                       **parameters)
def handle_channel_batch_unlock(raiden: 'RaidenService', event: Event):
    token_network_identifier = event.originating_contract
    data = event.event_data
    args = data['args']
    block_number = data['block_number']
    block_hash = data['block_hash']
    transaction_hash = data['transaction_hash']

    chain_state = views.state_from_raiden(raiden)
    unlock_state_change = ContractReceiveChannelBatchUnlock(
        transaction_hash=transaction_hash,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_state.chain_id,
            token_network_address=token_network_identifier,
            # FIXME: we will resolve the channel identifier only further down in
            # raiden.transfer.token_network::handle_batch_unlock
            # can/should we do it here already?
            channel_identifier=CHANNEL_ID_UNSPECIFIED,
        ),
        participant=args['participant'],
        partner=args['partner'],
        locksroot=args['locksroot'],
        unlocked_amount=args['unlocked_amount'],
        returned_tokens=args['returned_tokens'],
        block_number=block_number,
        block_hash=block_hash,
    )

    raiden.handle_and_track_state_change(unlock_state_change)
def handle_channel_update_transfer(raiden: 'RaidenService', event: Event):
    token_network_identifier = event.originating_contract
    data = event.event_data
    args = data['args']
    channel_identifier = args['channel_identifier']
    transaction_hash = data['transaction_hash']
    block_number = data['block_number']
    block_hash = data['block_hash']

    chain_state = views.state_from_raiden(raiden)
    channel_state = views.get_channelstate_by_canonical_identifier(
        chain_state=chain_state,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_state.chain_id,
            token_network_address=token_network_identifier,
            channel_identifier=channel_identifier,
        ),
    )

    if channel_state:
        channel_transfer_updated = ContractReceiveUpdateTransfer(
            transaction_hash=transaction_hash,
            canonical_identifier=channel_state.canonical_identifier,
            nonce=args['nonce'],
            block_number=block_number,
            block_hash=block_hash,
        )
        raiden.handle_and_track_state_change(channel_transfer_updated)
    def handle_contract_send_channelclose(
        raiden: 'RaidenService',
        channel_close_event: ContractSendChannelClose,
    ):
        balance_proof = channel_close_event.balance_proof

        if balance_proof:
            nonce = balance_proof.nonce
            balance_hash = balance_proof.balance_hash
            signature = balance_proof.signature
            message_hash = balance_proof.message_hash

        else:
            nonce = 0
            balance_hash = EMPTY_HASH
            signature = EMPTY_SIGNATURE
            message_hash = EMPTY_HASH

        channel_proxy = raiden.chain.payment_channel(
            canonical_identifier=CanonicalIdentifier(
                chain_identifier=state_from_raiden(raiden).chain_id,
                token_network_address=channel_close_event.
                token_network_identifier,
                channel_identifier=channel_close_event.channel_identifier,
            ), )

        channel_proxy.close(
            nonce=nonce,
            balance_hash=balance_hash,
            additional_hash=message_hash,
            signature=signature,
            block_identifier=channel_close_event.triggered_by_block_hash,
        )
Beispiel #9
0
def get_updatepfs_message(
    chain_identifier: ChainID = 1,
    channel_identifier: ChannelID = 0,
    token_network_address:
    TokenNetworkAddress = DEFAULT_TOKEN_NETWORK_ADDRESS_BYTES,
    updating_participant: Address = None,
    other_participant: Address = None,
    updating_nonce: Nonce = 1,
    other_nonce: Nonce = 0,
    updating_capacity: TokenAmount = 90,
    other_capacity: TokenAmount = 110,
    reveal_timeout: int = 2,
    signature: Signature = '',
) -> UpdatePFS:
    return UpdatePFS(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_identifier,
            channel_identifier=channel_identifier,
            token_network_address=token_network_address,
        ),
        updating_participant=updating_participant,
        other_participant=other_participant,
        updating_nonce=updating_nonce,
        other_nonce=other_nonce,
        updating_capacity=updating_capacity,
        other_capacity=other_capacity,
        reveal_timeout=reveal_timeout,
        signature=signature,
    )
Beispiel #10
0
def _(properties: BalanceProofSignedStateProperties,
      defaults=None) -> BalanceProofSignedState:
    defaults = defaults or BALANCE_PROOF_SIGNED_STATE_DEFAULTS
    params = _properties_to_dict(properties, defaults)
    params.update(
        _properties_to_dict(params.pop('balance_proof'),
                            defaults.balance_proof), )
    signer = LocalSigner(params.pop('pkey'))

    if params['signature'] is EMPTY:
        keys = ('transferred_amount', 'locked_amount', 'locksroot')
        balance_hash = hash_balance_data(**_partial_dict(params, *keys))

        canonical_identifier = CanonicalIdentifier(
            chain_identifier=params.pop('chain_id'),
            token_network_address=params.pop('token_network_identifier'),
            channel_identifier=params.pop('channel_identifier'),
        )
        params['canonical_identifier'] = canonical_identifier

        data_to_sign = balance_proof.pack_balance_proof(
            balance_hash=balance_hash,
            additional_hash=params['message_hash'],
            canonical_identifier=canonical_identifier,
            nonce=params.get('nonce'),
        )

        params['signature'] = signer.sign(data=data_to_sign)

    return BalanceProofSignedState(**params)
Beispiel #11
0
 def from_dict(cls, data):
     return cls(
         canonical_identifier=CanonicalIdentifier(
             chain_identifier=CHAIN_ID_UNSPECIFIED,
             token_network_address=to_canonical_address(data['token_network_identifier']),
             channel_identifier=int(data['channel_identifier']),
         ),
     )
Beispiel #12
0
def subdispatch_targettask(
    chain_state: ChainState,
    state_change: StateChange,
    token_network_identifier: TokenNetworkID,
    channel_identifier: ChannelID,
    secrethash: SecretHash,
) -> TransitionResult[ChainState]:

    block_number = chain_state.block_number
    sub_task = chain_state.payment_mapping.secrethashes_to_task.get(secrethash)

    if not sub_task:
        is_valid_subtask = True
        target_state = None

    elif sub_task and isinstance(sub_task, TargetTask):
        is_valid_subtask = (
            token_network_identifier == sub_task.token_network_identifier)
        target_state = sub_task.target_state
    else:
        is_valid_subtask = False

    events = list()
    channel_state = None
    if is_valid_subtask:
        channel_state = views.get_channelstate_by_canonical_identifier(
            chain_state=chain_state,
            canonical_identifier=CanonicalIdentifier(
                chain_identifier=chain_state.chain_id,
                token_network_address=token_network_identifier,
                channel_identifier=channel_identifier,
            ),
        )

    if channel_state:
        pseudo_random_generator = chain_state.pseudo_random_generator

        iteration = target.state_transition(
            target_state,
            state_change,
            channel_state,
            pseudo_random_generator,
            block_number,
        )
        events = iteration.events

        if iteration.new_state:
            sub_task = TargetTask(
                token_network_identifier,
                channel_identifier,
                iteration.new_state,
            )
            chain_state.payment_mapping.secrethashes_to_task[
                secrethash] = sub_task
        elif secrethash in chain_state.payment_mapping.secrethashes_to_task:
            del chain_state.payment_mapping.secrethashes_to_task[secrethash]

    return TransitionResult(chain_state, events)
def handle_channel_closed(raiden: 'RaidenService', event: Event):
    token_network_identifier = event.originating_contract
    data = event.event_data
    block_number = data['block_number']
    args = data['args']
    channel_identifier = args['channel_identifier']
    transaction_hash = data['transaction_hash']
    block_hash = data['block_hash']

    chain_state = views.state_from_raiden(raiden)
    channel_state = views.get_channelstate_by_canonical_identifier(
        chain_state=chain_state,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_state.chain_id,
            token_network_address=token_network_identifier,
            channel_identifier=channel_identifier,
        ),
    )

    channel_closed: StateChange
    if channel_state:
        # The from address is included in the ChannelClosed event as the
        # closing_participant field
        channel_closed = ContractReceiveChannelClosed(
            transaction_hash=transaction_hash,
            transaction_from=args['closing_participant'],
            canonical_identifier=channel_state.canonical_identifier,
            block_number=block_number,
            block_hash=block_hash,
        )
        raiden.handle_and_track_state_change(channel_closed)
    else:
        # This is a channel close event of a channel we're not a participant of
        route_closed = ContractReceiveRouteClosed(
            transaction_hash=transaction_hash,
            canonical_identifier=CanonicalIdentifier(
                chain_identifier=chain_state.chain_id,
                token_network_address=token_network_identifier,
                channel_identifier=channel_identifier,
            ),
            block_number=block_number,
            block_hash=block_hash,
        )
        raiden.handle_and_track_state_change(route_closed)
Beispiel #14
0
def wait_for_channel_in_states(
    raiden: RaidenService,
    payment_network_id: typing.PaymentNetworkID,
    token_address: typing.TokenAddress,
    channel_ids: typing.List[typing.ChannelID],
    retry_timeout: float,
    target_states: typing.Tuple[str],
) -> None:
    """Wait until all channels are in `target_states`.

    Raises:
        ValueError: If the token_address is not registered in the
            payment_network.

    Note:
        This does not time out, use gevent.Timeout.
    """
    chain_state = views.state_from_raiden(raiden)
    token_network = views.get_token_network_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )

    if token_network is None:
        raise ValueError(
            f'The token {token_address} is not registered on the network {payment_network_id}.',
        )

    token_network_address = token_network.address

    list_cannonical_ids = [
        CanonicalIdentifier(
            chain_identifier=chain_state.chain_id,
            token_network_address=token_network_address,
            channel_identifier=channel_identifier,
        ) for channel_identifier in channel_ids
    ]

    while list_cannonical_ids:
        canonical_id = list_cannonical_ids[-1]
        chain_state = views.state_from_raiden(raiden)

        channel_state = views.get_channelstate_by_canonical_identifier(
            chain_state=chain_state,
            canonical_identifier=canonical_id,
        )

        channel_is_settled = (channel_state is None
                              or channel.get_status(channel_state)
                              in target_states)

        if channel_is_settled:
            list_cannonical_ids.pop()
        else:
            gevent.sleep(retry_timeout)
Beispiel #15
0
def make_canonical_identifier(
        chain_identifier=UNIT_CHAIN_ID,
        token_network_address=UNIT_TOKEN_NETWORK_ADDRESS,
        channel_identifier=UNIT_CHANNEL_ID,
) -> CanonicalIdentifier:
    return CanonicalIdentifier(
        chain_identifier=chain_identifier,
        token_network_address=token_network_address,
        channel_identifier=channel_identifier,
    )
Beispiel #16
0
    def from_dict(cls, data: Dict[str, Any]) -> 'ContractSendChannelSettle':
        restored = cls(
            canonical_identifier=CanonicalIdentifier(
                chain_identifier=CHAIN_ID_UNSPECIFIED,
                token_network_address=to_canonical_address(data['token_network_identifier']),
                channel_identifier=ChannelID(int(data['channel_identifier'])),
            ),
            triggered_by_block_hash=BlockHash(deserialize_bytes(data['triggered_by_block_hash'])),
        )

        return restored
Beispiel #17
0
 def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveRouteClosed':
     return cls(
         transaction_hash=deserialize_transactionhash(data['transaction_hash']),
         canonical_identifier=CanonicalIdentifier(
             chain_identifier=CHAIN_ID_UNSPECIFIED,
             token_network_address=to_canonical_address(data['token_network_identifier']),
             channel_identifier=ChannelID(int(data['channel_identifier'])),
         ),
         block_number=BlockNumber(int(data['block_number'])),
         block_hash=BlockHash(deserialize_bytes(data['block_hash'])),
     )
Beispiel #18
0
def make_balance_proof_from_counter(counter) -> BalanceProofUnsignedState:
    return BalanceProofUnsignedState(
        nonce=next(counter),
        transferred_amount=next(counter),
        locked_amount=next(counter),
        locksroot=sha3(next(counter).to_bytes(1, 'big')),
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=next(counter),
            token_network_address=factories.make_address(),
            channel_identifier=next(counter),
        ),
    )
def handle_channel_new_balance(raiden: 'RaidenService', event: Event):
    data = event.event_data
    args = data['args']
    block_number = data['block_number']
    block_hash = data['block_hash']
    channel_identifier = args['channel_identifier']
    token_network_identifier = event.originating_contract
    participant_address = args['participant']
    total_deposit = args['total_deposit']
    transaction_hash = data['transaction_hash']

    chain_state = views.state_from_raiden(raiden)
    previous_channel_state = views.get_channelstate_by_canonical_identifier(
        chain_state=chain_state,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_state.chain_id,
            token_network_address=token_network_identifier,
            channel_identifier=channel_identifier,
        ),
    )

    # Channels will only be registered if this node is a participant
    if previous_channel_state is not None:
        previous_balance = previous_channel_state.our_state.contract_balance
        balance_was_zero = previous_balance == 0

        deposit_transaction = TransactionChannelNewBalance(
            participant_address,
            total_deposit,
            block_number,
        )

        newbalance_statechange = ContractReceiveChannelNewBalance(
            transaction_hash=transaction_hash,
            canonical_identifier=previous_channel_state.canonical_identifier,
            deposit_transaction=deposit_transaction,
            block_number=block_number,
            block_hash=block_hash,
        )
        raiden.handle_and_track_state_change(newbalance_statechange)

        if balance_was_zero and participant_address != raiden.address:
            connection_manager = raiden.connection_manager_for_token_network(
                token_network_identifier, )

            join_channel = gevent.spawn(
                connection_manager.join_channel,
                participant_address,
                total_deposit,
            )

            raiden.add_pending_greenlet(join_channel)
Beispiel #20
0
def payment_channel_open_and_deposit(app0, app1, token_address, deposit,
                                     settle_timeout):
    """ Open a new channel with app0 and app1 as participants """
    assert token_address

    token_network_address = app0.raiden.default_registry.get_token_network(
        token_address)
    token_network_proxy = app0.raiden.chain.token_network(
        token_network_address)

    channel_identifier = token_network_proxy.new_netting_channel(
        partner=app1.raiden.address,
        settle_timeout=settle_timeout,
        given_block_identifier='latest',
    )
    assert channel_identifier
    canonical_identifier = CanonicalIdentifier(
        chain_identifier=state_from_raiden(app0.raiden).chain_id,
        token_network_address=token_network_proxy.address,
        channel_identifier=channel_identifier,
    )

    for app in [app0, app1]:
        # Use each app's own chain because of the private key / local signing
        token = app.raiden.chain.token(token_address)
        payment_channel_proxy = app.raiden.chain.payment_channel(
            canonical_identifier=canonical_identifier, )

        # This check can succeed and the deposit still fail, if channels are
        # openned in parallel
        previous_balance = token.balance_of(app.raiden.address)
        assert previous_balance >= deposit

        # the payment channel proxy will call approve
        # token.approve(token_network_proxy.address, deposit)
        payment_channel_proxy.set_total_deposit(total_deposit=deposit,
                                                block_identifier='latest')

        # Balance must decrease by at least but not exactly `deposit` amount,
        # because channels can be openned in parallel
        new_balance = token.balance_of(app.raiden.address)
        assert new_balance <= previous_balance - deposit

    check_channel(
        app0,
        app1,
        token_network_proxy.address,
        channel_identifier,
        settle_timeout,
        deposit,
    )
Beispiel #21
0
 def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveChannelBatchUnlock':
     return cls(
         transaction_hash=deserialize_transactionhash(data['transaction_hash']),
         canonical_identifier=CanonicalIdentifier(
             chain_identifier=CHAIN_ID_UNSPECIFIED,
             token_network_address=to_canonical_address(data['token_network_identifier']),
             channel_identifier=CHANNEL_ID_UNSPECIFIED,
         ),
         participant=to_canonical_address(data['participant']),
         partner=to_canonical_address(data['partner']),
         locksroot=deserialize_locksroot(data['locksroot']),
         unlocked_amount=TokenAmount(int(data['unlocked_amount'])),
         returned_tokens=TokenAmount(int(data['returned_tokens'])),
         block_number=BlockNumber(int(data['block_number'])),
         block_hash=deserialize_blockhash(data['block_hash']),
     )
Beispiel #22
0
def check_channel(
    app1,
    app2,
    token_network_identifier,
    channel_identifier,
    settle_timeout,
    deposit_amount,
):
    canonical_identifier = CanonicalIdentifier(
        chain_identifier=state_from_raiden(app1.raiden).chain_id,
        token_network_address=token_network_identifier,
        channel_identifier=channel_identifier,
    )
    netcontract1 = app1.raiden.chain.payment_channel(
        canonical_identifier=canonical_identifier, )
    netcontract2 = app2.raiden.chain.payment_channel(
        canonical_identifier=canonical_identifier, )

    # Check a valid settle timeout was used, the netting contract has an
    # enforced minimum and maximum
    assert settle_timeout == netcontract1.settle_timeout()
    assert settle_timeout == netcontract2.settle_timeout()

    if deposit_amount > 0:
        assert netcontract1.can_transfer('latest')
        assert netcontract2.can_transfer('latest')

    app1_details = netcontract1.detail('latest')
    app2_details = netcontract2.detail('latest')

    assert (app1_details.participants_data.our_details.address ==
            app2_details.participants_data.partner_details.address)
    assert (app1_details.participants_data.partner_details.address ==
            app2_details.participants_data.our_details.address)

    assert (app1_details.participants_data.our_details.deposit ==
            app2_details.participants_data.partner_details.deposit)
    assert (app1_details.participants_data.partner_details.deposit ==
            app2_details.participants_data.our_details.deposit)
    assert app1_details.chain_id == app2_details.chain_id

    assert app1_details.participants_data.our_details.deposit == deposit_amount
    assert app1_details.participants_data.partner_details.deposit == deposit_amount
    assert app2_details.participants_data.our_details.deposit == deposit_amount
    assert app2_details.participants_data.partner_details.deposit == deposit_amount
    assert app2_details.chain_id == UNIT_CHAIN_ID
Beispiel #23
0
def channel_state_until_state_change(
    raiden,
    payment_network_identifier: typing.PaymentNetworkID,
    token_address: typing.TokenAddress,
    channel_identifier: typing.ChannelID,
    state_change_identifier: int,
) -> typing.Optional[NettingChannelState]:
    """ Go through WAL state changes until a certain balance hash is found. """
    wal = restore_to_state_change(
        transition_function=node.state_transition,
        storage=raiden.wal.storage,
        state_change_identifier=state_change_identifier,
    )

    msg = 'There is a state change, therefore the state must not be None'
    assert wal.state_manager.current_state is not None, msg

    chain_state = wal.state_manager.current_state
    token_network = views.get_token_network_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_identifier,
        token_address=token_address,
    )

    if not token_network:
        return None

    token_network_address = token_network.address

    canonical_identifier = CanonicalIdentifier(
        chain_identifier=chain_state.chain_id,
        token_network_address=token_network_address,
        channel_identifier=channel_identifier,
    )
    channel_state = views.get_channelstate_by_canonical_identifier(
        chain_state=wal.state_manager.current_state,
        canonical_identifier=canonical_identifier,
    )

    if not channel_state:
        raise RaidenUnrecoverableError(
            f"Channel was not found before state_change {state_change_identifier}",
        )

    return channel_state
    def handle_contract_send_channelupdate(
        raiden: RaidenService,
        channel_update_event: ContractSendChannelUpdateTransfer,
    ):
        balance_proof = channel_update_event.balance_proof

        if balance_proof:
            channel = raiden.chain.payment_channel(
                token_network_address=channel_update_event.
                token_network_identifier,
                channel_id=channel_update_event.channel_identifier,
            )

            non_closing_data = pack_balance_proof_update(
                nonce=balance_proof.nonce,
                balance_hash=balance_proof.balance_hash,
                additional_hash=balance_proof.message_hash,
                canonical_identifier=CanonicalIdentifier(
                    chain_identifier=balance_proof.chain_id,
                    token_network_address=balance_proof.
                    token_network_identifier,
                    channel_identifier=balance_proof.channel_identifier,
                ),
                partner_signature=balance_proof.signature,
            )
            our_signature = raiden.signer.sign(data=non_closing_data)

            try:
                channel.update_transfer(
                    nonce=balance_proof.nonce,
                    balance_hash=balance_proof.balance_hash,
                    additional_hash=balance_proof.message_hash,
                    partner_signature=balance_proof.signature,
                    signature=our_signature,
                    block_identifier=channel_update_event.
                    triggered_by_block_hash,
                )
            except ChannelOutdatedError as e:
                log.error(
                    str(e),
                    node=pex(raiden.address),
                )
Beispiel #25
0
def handle_contract_receive_channel_closed(
    chain_state: ChainState,
    state_change: ContractReceiveChannelClosed,
) -> TransitionResult[ChainState]:
    # cleanup queue for channel
    channel_state = views.get_channelstate_by_canonical_identifier(
        chain_state=chain_state,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_state.chain_id,
            token_network_address=state_change.token_network_identifier,
            channel_identifier=state_change.channel_identifier,
        ),
    )
    if channel_state:
        queue_id = QueueIdentifier(
            recipient=channel_state.partner_state.address,
            channel_identifier=state_change.channel_identifier,
        )
        if queue_id in chain_state.queueids_to_queues:
            chain_state.queueids_to_queues.pop(queue_id)

    return handle_token_network_action(chain_state=chain_state,
                                       state_change=state_change)
Beispiel #26
0
def test_request_monitoring():
    partner_signer = LocalSigner(PARTNER_PRIVKEY)
    balance_proof = make_balance_proof(signer=partner_signer, amount=1)
    partner_signed_balance_proof = SignedBlindedBalanceProof.from_balance_proof_signed_state(
        balance_proof, )
    request_monitoring = RequestMonitoring(
        onchain_balance_proof=partner_signed_balance_proof,
        reward_amount=55,
    )
    assert request_monitoring
    with pytest.raises(ValueError):
        request_monitoring.to_dict()
    request_monitoring.sign(signer)
    as_dict = request_monitoring.to_dict()
    assert RequestMonitoring.from_dict(as_dict) == request_monitoring
    packed = request_monitoring.pack(request_monitoring.packed())
    assert RequestMonitoring.unpack(packed) == request_monitoring
    # RequestMonitoring can be created directly from BalanceProofSignedState
    direct_created = RequestMonitoring.from_balance_proof_signed_state(
        balance_proof,
        reward_amount=55,
    )
    with pytest.raises(ValueError):
        # equality test uses `validated` packed format
        assert direct_created == request_monitoring

    direct_created.sign(signer)
    # Instances created from same balance proof are equal
    assert direct_created == request_monitoring
    other_balance_proof = make_balance_proof(signer=partner_signer, amount=2)
    other_instance = RequestMonitoring.from_balance_proof_signed_state(
        other_balance_proof,
        reward_amount=55,
    )
    other_instance.sign(signer)
    # different balance proof ==> non-equality
    assert other_instance != request_monitoring

    # test signature verification
    reward_proof_data = pack_reward_proof(
        request_monitoring.balance_proof.channel_identifier,
        request_monitoring.reward_amount,
        request_monitoring.balance_proof.token_network_address,
        request_monitoring.balance_proof.chain_id,
        request_monitoring.balance_proof.nonce,
    )

    assert recover(reward_proof_data,
                   request_monitoring.reward_proof_signature) == ADDRESS

    blinded_data = pack_balance_proof_update(
        nonce=request_monitoring.balance_proof.nonce,
        balance_hash=request_monitoring.balance_proof.balance_hash,
        additional_hash=request_monitoring.balance_proof.additional_hash,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=request_monitoring.balance_proof.chain_id,
            token_network_address=request_monitoring.balance_proof.
            token_network_address,
            channel_identifier=request_monitoring.balance_proof.
            channel_identifier,
        ),
        partner_signature=request_monitoring.balance_proof.signature,
    )
    assert recover(blinded_data,
                   request_monitoring.non_closing_signature) == ADDRESS

    balance_proof_data = pack_balance_proof(
        nonce=request_monitoring.balance_proof.nonce,
        balance_hash=request_monitoring.balance_proof.balance_hash,
        additional_hash=request_monitoring.balance_proof.additional_hash,
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=request_monitoring.balance_proof.chain_id,
            token_network_address=request_monitoring.balance_proof.
            token_network_address,
            channel_identifier=request_monitoring.balance_proof.
            channel_identifier,
        ),
    )
    assert recover(
        balance_proof_data,
        request_monitoring.balance_proof.signature,
    ) == PARTNER_ADDRESS

    assert request_monitoring.verify_request_monitoring(
        PARTNER_ADDRESS, ADDRESS)
def run_test_secret_revealed_on_chain(
    raiden_chain,
    deposit,
    settle_timeout,
    token_addresses,
    retry_interval,
):
    """ A node must reveal the secret on-chain if it's known and the channel is closed. """
    app0, app1, app2 = raiden_chain
    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,
    )

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

    # Reveal the secret, but do not unlock it off-chain
    app1_hold_event_handler = HoldOffChainSecretRequest()
    app1.raiden.raiden_event_handler = app1_hold_event_handler
    app1_hold_event_handler.hold_unlock_for(secrethash=secrethash)

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

    with gevent.Timeout(10):
        wait_for_state_change(
            app2.raiden,
            ReceiveSecretReveal,
            {'secrethash': secrethash},
            retry_interval,
        )

    channel_state2_1 = get_channelstate(app2, app1, token_network_identifier)
    pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get(
        secrethash)
    msg = "The lock must be registered in unlocked locks since the secret is known"
    assert pending_lock is not None, msg

    # The channels are out-of-sync. app1 has sent the unlock, however we are
    # intercepting it and app2 has not received the updated balance proof

    # Close the channel. This must register the secret on chain
    channel_close_event = ContractSendChannelClose(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=channel_state2_1.chain_id,
            token_network_address=token_network_identifier,
            channel_identifier=channel_state2_1.identifier,
        ),
        token_address=channel_state2_1.token_address,
        balance_proof=channel_state2_1.partner_state.balance_proof,
        triggered_by_block_hash=app0.raiden.chain.block_hash(),
    )
    app2.raiden.raiden_event_handler.on_raiden_event(app2.raiden,
                                                     channel_close_event)

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

    # TODO:
    # - assert on the transferred amounts on-chain (for settle and unlock)

    # The channel app0-app1 should continue with the protocol off-chain, once
    # the secret is released on-chain by app2
    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount,
        [],
        app1,
        deposit + amount,
        [],
    )

    with gevent.Timeout(10):
        wait_for_state_change(
            app2.raiden,
            ContractReceiveSecretReveal,
            {'secrethash': secrethash},
            retry_interval,
        )
Beispiel #28
0
    def populate_token_network(token_network: TokenNetwork,
                               addresses: List[Address],
                               channel_descriptions: List):
        for (
                channel_id,
            (
                p1_index,
                p1_deposit,
                p1_capacity,
                _p1_fee,
                p1_reveal_timeout,
                p2_index,
                p2_deposit,
                p2_capacity,
                _p2_fee,
                p2_reveal_timeout,
                settle_timeout,
            ),
        ) in enumerate(channel_descriptions):
            token_network.handle_channel_opened_event(
                ChannelID(channel_id),
                addresses[p1_index],
                addresses[p2_index],
                settle_timeout=settle_timeout,
            )

            token_network.handle_channel_new_deposit_event(
                ChannelID(channel_id), addresses[p1_index], p1_deposit)
            token_network.handle_channel_new_deposit_event(
                ChannelID(channel_id), addresses[p2_index], p2_deposit)

            token_network.handle_channel_balance_update_message(
                UpdatePFS(
                    canonical_identifier=CanonicalIdentifier(
                        chain_identifier=ChainID(1),
                        channel_identifier=ChannelID(channel_id),
                        token_network_address=TokenNetworkAddressBytes(
                            decode_hex(token_network.address)),
                    ),
                    updating_participant=decode_hex(addresses[p1_index]),
                    other_participant=decode_hex(addresses[p2_index]),
                    updating_nonce=Nonce(1),
                    other_nonce=Nonce(1),
                    updating_capacity=p1_capacity,
                    other_capacity=p2_capacity,
                    reveal_timeout=p1_reveal_timeout,
                    mediation_fee=FeeAmount(0),
                ))
            token_network.handle_channel_balance_update_message(
                UpdatePFS(
                    canonical_identifier=CanonicalIdentifier(
                        chain_identifier=ChainID(1),
                        channel_identifier=ChannelID(channel_id),
                        token_network_address=TokenNetworkAddressBytes(
                            decode_hex(token_network.address)),
                    ),
                    updating_participant=decode_hex(addresses[p2_index]),
                    other_participant=decode_hex(addresses[p1_index]),
                    updating_nonce=Nonce(2),
                    other_nonce=Nonce(1),
                    updating_capacity=p2_capacity,
                    other_capacity=p1_capacity,
                    reveal_timeout=p2_reveal_timeout,
                    mediation_fee=FeeAmount(0),
                ))
    def handle_contract_send_channelunlock(
        raiden: 'RaidenService',
        channel_unlock_event: ContractSendChannelBatchUnlock,
    ):
        token_network_identifier = channel_unlock_event.token_network_identifier
        channel_identifier = channel_unlock_event.channel_identifier
        canonical_identifier = CanonicalIdentifier(
            chain_identifier=raiden.chain.network_id,
            token_network_address=token_network_identifier,
            channel_identifier=channel_identifier,
        )
        participant = channel_unlock_event.participant
        token_address = channel_unlock_event.token_address

        payment_channel: PaymentChannel = raiden.chain.payment_channel(
            canonical_identifier=canonical_identifier, )

        channel_state = get_channelstate_by_token_network_and_partner(
            chain_state=state_from_raiden(raiden),
            token_network_id=token_network_identifier,
            partner_address=participant,
        )

        if not channel_state:
            # channel was cleaned up already due to an unlock
            raise RaidenUnrecoverableError(
                f'Failed to find channel state with partner '
                f'{participant}, token_network:pex(token_network_identifier)',
            )

        our_address = channel_state.our_state.address
        our_locksroot = channel_state.our_state.onchain_locksroot

        partner_address = channel_state.partner_state.address
        partner_locksroot = channel_state.partner_state.onchain_locksroot

        # we want to unlock because there are on-chain unlocked locks
        search_events = our_locksroot != EMPTY_HASH
        # we want to unlock, because there are unlocked/unclaimed locks
        search_state_changes = partner_locksroot != EMPTY_HASH

        if not search_events and not search_state_changes:
            # In the case that someone else sent the unlock we do nothing
            # Check https://github.com/raiden-network/raiden/issues/3152
            # for more details
            log.warning(
                'Onchain unlock already mined',
                token_address=token_address,
                channel_identifier=canonical_identifier.channel_identifier,
                participant=participant,
            )
            return

        if search_state_changes:
            state_change_record = get_state_change_with_balance_proof_by_locksroot(
                storage=raiden.wal.storage,
                canonical_identifier=canonical_identifier,
                locksroot=partner_locksroot,
                sender=partner_address,
            )
            state_change_identifier = state_change_record.state_change_identifier

            if not state_change_identifier:
                raise RaidenUnrecoverableError(
                    f'Failed to find state that matches the current channel locksroots. '
                    f'chain_id:{raiden.chain.network_id} '
                    f'token:{to_checksum_address(token_address)} '
                    f'token_network:{to_checksum_address(token_network_identifier)} '
                    f'channel:{channel_identifier} '
                    f'participant:{to_checksum_address(participant)} '
                    f'our_locksroot:{to_hex(our_locksroot)} '
                    f'partner_locksroot:{to_hex(partner_locksroot)} ', )

            restored_channel_state = channel_state_until_state_change(
                raiden=raiden,
                payment_network_identifier=raiden.default_registry.address,
                token_address=token_address,
                channel_identifier=channel_identifier,
                state_change_identifier=state_change_identifier,
            )

            gain = get_batch_unlock_gain(restored_channel_state, )

            skip_unlock = (restored_channel_state.partner_state.address
                           == participant and gain.from_partner_locks == 0)
            if not skip_unlock:
                unlock(
                    raiden=raiden,
                    payment_channel=payment_channel,
                    end_state=restored_channel_state.partner_state,
                    participant=our_address,
                    partner=partner_address,
                )

        if search_events:
            event_record = get_event_with_balance_proof_by_locksroot(
                storage=raiden.wal.storage,
                canonical_identifier=canonical_identifier,
                locksroot=our_locksroot,
                recipient=partner_address,
            )
            state_change_identifier = event_record.state_change_identifier

            if not state_change_identifier:
                raise RaidenUnrecoverableError(
                    f'Failed to find event that match current channel locksroots. '
                    f'chain_id:{raiden.chain.network_id} '
                    f'token:{to_checksum_address(token_address)} '
                    f'token_network:{to_checksum_address(token_network_identifier)} '
                    f'channel:{channel_identifier} '
                    f'participant:{to_checksum_address(participant)} '
                    f'our_locksroot:{to_hex(our_locksroot)} '
                    f'partner_locksroot:{to_hex(partner_locksroot)} ', )

            restored_channel_state = channel_state_until_state_change(
                raiden=raiden,
                payment_network_identifier=raiden.default_registry.address,
                token_address=token_address,
                channel_identifier=canonical_identifier.channel_identifier,
                state_change_identifier=state_change_identifier,
            )

            gain = get_batch_unlock_gain(restored_channel_state, )

            skip_unlock = (restored_channel_state.our_state.address
                           == participant and gain.from_our_locks == 0)
            if not skip_unlock:
                unlock(
                    raiden=raiden,
                    payment_channel=payment_channel,
                    end_state=restored_channel_state.our_state,
                    participant=partner_address,
                    partner=our_address,
                )
    def handle_contract_send_channelsettle(
        raiden: 'RaidenService',
        channel_settle_event: ContractSendChannelSettle,
    ):
        canonical_identifier = CanonicalIdentifier(
            chain_identifier=raiden.chain.network_id,
            token_network_address=channel_settle_event.
            token_network_identifier,
            channel_identifier=channel_settle_event.channel_identifier,
        )
        triggered_by_block_hash = channel_settle_event.triggered_by_block_hash

        payment_channel: PaymentChannel = raiden.chain.payment_channel(
            canonical_identifier=canonical_identifier, )
        token_network_proxy: TokenNetwork = payment_channel.token_network

        if not token_network_proxy.client.can_query_state_for_block(
                triggered_by_block_hash):
            # The only time this can happen is during restarts after a long time
            # when the triggered block ends up getting pruned
            # In that case it's safe to just use the latest view of the chain to
            # query the on-chain participant/channel details
            triggered_by_block_hash = token_network_proxy.client.blockhash_from_blocknumber(
                'latest', )

        participants_details = token_network_proxy.detail_participants(
            participant1=payment_channel.participant1,
            participant2=payment_channel.participant2,
            block_identifier=triggered_by_block_hash,
            channel_identifier=channel_settle_event.channel_identifier,
        )

        our_details = participants_details.our_details
        partner_details = participants_details.partner_details

        log_details = {
            'chain_id': canonical_identifier.chain_identifier,
            'token_network_identifier':
            canonical_identifier.token_network_address,
            'channel_identifier': canonical_identifier.channel_identifier,
            'node': pex(raiden.address),
            'partner': to_checksum_address(partner_details.address),
            'our_deposit': our_details.deposit,
            'our_withdrawn': our_details.withdrawn,
            'our_is_closer': our_details.is_closer,
            'our_balance_hash': to_hex(our_details.balance_hash),
            'our_nonce': our_details.nonce,
            'our_locksroot': to_hex(our_details.locksroot),
            'our_locked_amount': our_details.locked_amount,
            'partner_deposit': partner_details.deposit,
            'partner_withdrawn': partner_details.withdrawn,
            'partner_is_closer': partner_details.is_closer,
            'partner_balance_hash': to_hex(partner_details.balance_hash),
            'partner_nonce': partner_details.nonce,
            'partner_locksroot': to_hex(partner_details.locksroot),
            'partner_locked_amount': partner_details.locked_amount,
        }

        if our_details.balance_hash != EMPTY_HASH:
            event_record = get_event_with_balance_proof_by_balance_hash(
                storage=raiden.wal.storage,
                canonical_identifier=canonical_identifier,
                balance_hash=our_details.balance_hash,
            )

            if event_record.data is None:
                log.critical(
                    'our balance proof not found',
                    **log_details,
                )
                raise RaidenUnrecoverableError(
                    'Our balance proof could not be found in the database', )

            our_balance_proof = event_record.data.balance_proof
            our_transferred_amount = our_balance_proof.transferred_amount
            our_locked_amount = our_balance_proof.locked_amount
            our_locksroot = our_balance_proof.locksroot
        else:
            our_transferred_amount = 0
            our_locked_amount = 0
            our_locksroot = EMPTY_HASH

        if partner_details.balance_hash != EMPTY_HASH:
            state_change_record = get_state_change_with_balance_proof_by_balance_hash(
                storage=raiden.wal.storage,
                canonical_identifier=canonical_identifier,
                balance_hash=partner_details.balance_hash,
                sender=participants_details.partner_details.address,
            )
            if state_change_record.data is None:
                log.critical(
                    'partner balance proof not found',
                    **log_details,
                )
                raise RaidenUnrecoverableError(
                    'Partner balance proof could not be found in the database',
                )

            partner_balance_proof = state_change_record.data.balance_proof
            partner_transferred_amount = partner_balance_proof.transferred_amount
            partner_locked_amount = partner_balance_proof.locked_amount
            partner_locksroot = partner_balance_proof.locksroot
        else:
            partner_transferred_amount = 0
            partner_locked_amount = 0
            partner_locksroot = EMPTY_HASH

        payment_channel.settle(
            transferred_amount=our_transferred_amount,
            locked_amount=our_locked_amount,
            locksroot=our_locksroot,
            partner_transferred_amount=partner_transferred_amount,
            partner_locked_amount=partner_locked_amount,
            partner_locksroot=partner_locksroot,
            block_identifier=triggered_by_block_hash,
        )