Exemple #1
0
def test_listings():
    test_state = factories.make_chain_state(number_of_channels=3)
    assert (
        views.get_token_network_addresses(
            chain_state=test_state.chain_state,
            token_network_registry_address=factories.make_address(),
        )
        == []
    )
    assert views.get_token_network_addresses(
        chain_state=test_state.chain_state,
        token_network_registry_address=test_state.token_network_registry_address,
    ) == [test_state.token_network_address]
    assert (
        views.get_token_identifiers(
            chain_state=test_state.chain_state,
            token_network_registry_address=factories.make_address(),
        )
        == []
    )
    assert views.get_token_identifiers(
        chain_state=test_state.chain_state,
        token_network_registry_address=test_state.token_network_registry_address,
    ) == [test_state.token_address]
    assert views.get_token_network_registry_address(chain_state=test_state.chain_state) == [
        test_state.token_network_registry_address
    ]
Exemple #2
0
 def get_tokens_list(self, registry_address: typing.PaymentNetworkID):
     """Returns a list of tokens the node knows about"""
     tokens_list = views.get_token_identifiers(
         chain_state=views.state_from_raiden(self.raiden),
         payment_network_id=registry_address,
     )
     return tokens_list
Exemple #3
0
    def can_close_channel(token_address, partner_addresses, registry_address,
                          raiden):

        if not is_binary_address(token_address):
            raise InvalidAddress(
                "Expected binary address format for token in channel close")

        if not all(map(is_binary_address, partner_addresses)):
            raise InvalidAddress(
                "Expected binary address format for partner in channel close")

        valid_tokens = views.get_token_identifiers(
            chain_state=views.state_from_raiden(raiden),
            payment_network_id=registry_address)
        if token_address not in valid_tokens:
            raise UnknownTokenAddress("Token address is not known.")

        chain_state = views.state_from_raiden(raiden)
        channels_to_close = views.filter_channels_by_partneraddress(
            chain_state=chain_state,
            payment_network_id=registry_address,
            token_address=token_address,
            partner_addresses=partner_addresses,
        )

        return channels_to_close
Exemple #4
0
def test_token_identifiers_empty_list_for_token_network_registry_none(chain_state):
    assert (
        get_token_identifiers(
            chain_state=chain_state, token_network_registry_address=factories.make_address()
        )
        == list()
    )
Exemple #5
0
 def get_tokens_list(
         self, registry_address: TokenNetworkRegistryAddress
 ) -> List[TokenAddress]:
     """Returns a list of tokens the node knows about"""
     return views.get_token_identifiers(
         chain_state=views.state_from_raiden(self.raiden),
         token_network_registry_address=registry_address,
     )
Exemple #6
0
def _get_required_gas_estimate_for_state(raiden) -> int:
    chain_state = views.state_from_raiden(raiden)
    registry_address = raiden.default_registry.address
    token_addresses = views.get_token_identifiers(chain_state,
                                                  registry_address)

    gas_estimate = 0

    for token_address in token_addresses:
        token_network_address = views.get_token_network_identifier_by_token_address(
            chain_state=chain_state,
            payment_network_id=registry_address,
            token_address=token_address,
        )
        num_opening_channels = len(
            raiden.chain.token_network(
                token_network_address).open_channel_transactions, )
        num_opened_channels = len(
            views.get_channelstate_open(
                chain_state,
                registry_address,
                token_address,
            ))
        num_closing_channels = len(
            views.get_channelstate_closing(
                chain_state,
                registry_address,
                token_address,
            ))
        num_closed_channels = len(
            views.get_channelstate_closed(
                chain_state,
                registry_address,
                token_address,
            ))
        num_settling_channels = len(
            views.get_channelstate_settling(
                chain_state,
                registry_address,
                token_address,
            ))
        num_settled_channels = len(
            views.get_channelstate_settled(
                chain_state,
                registry_address,
                token_address,
            ))

        gas_estimate += _get_required_gas_estimate(
            opening_channels=num_opening_channels,
            opened_channels=num_opened_channels,
            closing_channels=num_closing_channels,
            closed_channels=num_closed_channels,
            settling_channels=num_settling_channels,
            settled_channels=num_settled_channels,
        )

    return gas_estimate
Exemple #7
0
    def channel_batch_close(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        partner_addresses: List[Address],
        retry_timeout: NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ) -> None:
        """Close a channel opened with `partner_address` for the given
        `token_address`.

        Race condition, this can fail if channel was closed externally.
        """

        if not is_binary_address(token_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for token in channel close")

        if not all(map(is_binary_address, partner_addresses)):
            raise InvalidBinaryAddress(
                "Expected binary address format for partner in channel close")

        valid_tokens = views.get_token_identifiers(
            chain_state=views.state_from_raiden(self.raiden),
            token_network_registry_address=registry_address,
        )
        if token_address not in valid_tokens:
            raise UnknownTokenAddress("Token address is not known.")

        chain_state = views.state_from_raiden(self.raiden)
        channels_to_close = views.filter_channels_by_partneraddress(
            chain_state=chain_state,
            token_network_registry_address=registry_address,
            token_address=token_address,
            partner_addresses=partner_addresses,
        )

        close_state_changes: List[StateChange] = [
            ActionChannelClose(
                canonical_identifier=channel_state.canonical_identifier)
            for channel_state in channels_to_close
        ]

        greenlets = set(self.raiden.handle_state_changes(close_state_changes))
        gevent.joinall(greenlets, raise_error=True)

        channel_ids = [
            channel_state.identifier for channel_state in channels_to_close
        ]

        waiting.wait_for_close(
            raiden=self.raiden,
            token_network_registry_address=registry_address,
            token_address=token_address,
            channel_ids=channel_ids,
            retry_timeout=retry_timeout,
        )
Exemple #8
0
    def channel_batch_close(
        self,
        registry_address: typing.PaymentNetworkID,
        token_address: typing.TokenAddress,
        partner_addresses: typing.List[typing.Address],
        retry_timeout: typing.NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ):
        """Close a channel opened with `partner_address` for the given
        `token_address`.

        Race condition, this can fail if channel was closed externally.
        """

        if not is_binary_address(token_address):
            raise InvalidAddress(
                'Expected binary address format for token in channel close')

        if not all(map(is_binary_address, partner_addresses)):
            raise InvalidAddress(
                'Expected binary address format for partner in channel close')

        valid_tokens = views.get_token_identifiers(
            chain_state=views.state_from_raiden(self.raiden),
            payment_network_id=registry_address,
        )
        if token_address not in valid_tokens:
            raise UnknownTokenAddress('Token address is not known.')

        chain_state = views.state_from_raiden(self.raiden)
        channels_to_close = views.filter_channels_by_partneraddress(
            chain_state=chain_state,
            payment_network_id=registry_address,
            token_address=token_address,
            partner_addresses=partner_addresses,
        )

        greenlets: typing.Set[Greenlet] = set()
        for channel_state in channels_to_close:
            channel_close = ActionChannelClose(
                canonical_identifier=channel_state.canonical_identifier, )

            greenlets.update(self.raiden.handle_state_change(channel_close), )

        gevent.joinall(greenlets, raise_error=True)

        channel_ids = [
            channel_state.identifier for channel_state in channels_to_close
        ]

        waiting.wait_for_close(
            raiden=self.raiden,
            payment_network_id=registry_address,
            token_address=token_address,
            channel_ids=channel_ids,
            retry_timeout=retry_timeout,
        )
Exemple #9
0
def smoketest_perform_tests(
    raiden_service: RaidenService,
    transport: str,
    token_addresses,
    discovery_address,
):
    """ Perform high level tests designed to quickly discover broken functionality. """
    try:
        chain = raiden_service.chain
        token_network_added_events = raiden_service.default_registry.filter_token_added_events(
        )
        events_token_addresses = [
            event['args']['token_address']
            for event in token_network_added_events
        ]

        assert events_token_addresses == token_addresses

        if transport == 'udp':
            discovery_addresses = list(chain.address_to_discovery.keys())
            assert len(discovery_addresses) == 1, repr(
                chain.address_to_discovery)
            assert discovery_addresses[0] == discovery_address
            discovery = chain.address_to_discovery[discovery_addresses[0]]
            assert discovery.endpoint_by_address(
                raiden_service.address) != TEST_ENDPOINT

        token_networks = views.get_token_identifiers(
            views.state_from_raiden(raiden_service),
            raiden_service.default_registry.address,
        )
        assert len(token_networks) == 1

        channel_state = views.get_channelstate_for(
            views.state_from_raiden(raiden_service),
            raiden_service.default_registry.address,
            token_networks[0],
            decode_hex(TEST_PARTNER_ADDRESS),
        )

        distributable = channel.get_distributable(
            channel_state.our_state,
            channel_state.partner_state,
        )
        assert distributable == TEST_DEPOSIT_AMOUNT
        assert distributable == channel_state.our_state.contract_balance
        assert channel.get_status(channel_state) == CHANNEL_STATE_OPENED

        # Run API test
        run_restapi_smoketests()
    except:  # NOQA pylint: disable=bare-except
        error = traceback.format_exc()
        return error

    return None
Exemple #10
0
    def set_reveal_timeout(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        partner_address: Address,
        reveal_timeout: BlockTimeout,
    ) -> None:
        """ Set the `reveal_timeout` in the channel with the peer at `partner_address` and the
        given `token_address`.

        Raises:
            InvalidBinaryAddress: If either token_address or partner_address is not
                20 bytes long.
            InvalidRevealTimeout: If reveal_timeout has an invalid value.
        """
        chain_state = views.state_from_raiden(self.raiden)

        token_addresses = views.get_token_identifiers(chain_state,
                                                      registry_address)
        channel_state = views.get_channelstate_for(
            chain_state=chain_state,
            token_network_registry_address=registry_address,
            token_address=token_address,
            partner_address=partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for token in channel deposit")

        if not is_binary_address(partner_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for partner in channel deposit"
            )

        if token_address not in token_addresses:
            raise UnknownTokenAddress("Unknown token address")

        if channel_state is None:
            raise NonexistingChannel(
                "No channel with partner_address for the given token")

        if reveal_timeout <= 0:
            raise InvalidRevealTimeout(
                "reveal_timeout should be larger than zero.")

        if channel_state.settle_timeout < reveal_timeout * 2:
            raise InvalidRevealTimeout(
                "`settle_timeout` should be at least double the "
                "provided `reveal_timeout`.")

        self.raiden.set_channel_reveal_timeout(
            canonical_identifier=channel_state.canonical_identifier,
            reveal_timeout=reveal_timeout)
Exemple #11
0
def get_required_gas_estimate(raiden: "RaidenService",
                              channels_to_open: int = 0) -> int:
    num_opening_channels = 0
    num_opened_channels = 0
    num_closing_channels = 0
    num_closed_channels = 0
    num_settling_channels = 0
    num_settled_channels = 0

    # Only use the token networks that have been instantiated. Instantiating
    # the token networks here has a very high performance impact for a registry
    # with lots of tokens.
    #
    # The lock is being acquired to prevent chnages to the dictionary while
    # iterating over it.
    with raiden.proxy_manager.token_network_creation_lock:
        num_opening_channels = sum(
            token_network.opening_channels_count for token_network in
            raiden.proxy_manager.address_to_token_network.values())

    chain_state = views.state_from_raiden(raiden)
    registry_address = raiden.default_registry.address
    token_addresses = views.get_token_identifiers(chain_state,
                                                  registry_address)

    for token_address in token_addresses:
        num_opened_channels += len(
            views.get_channelstate_open(chain_state, registry_address,
                                        token_address))
        num_closing_channels += len(
            views.get_channelstate_closing(chain_state, registry_address,
                                           token_address))
        num_closed_channels += len(
            views.get_channelstate_closed(chain_state, registry_address,
                                          token_address))
        num_settling_channels += len(
            views.get_channelstate_settling(chain_state, registry_address,
                                            token_address))
        num_settled_channels += len(
            views.get_channelstate_settled(chain_state, registry_address,
                                           token_address))

    return _get_required_gas_estimate(
        gas_measurements=gas_measurements(
            raiden.contract_manager.contracts_version),
        opening_channels=num_opening_channels + channels_to_open,
        opened_channels=num_opened_channels,
        closing_channels=num_closing_channels,
        closed_channels=num_closed_channels,
        settling_channels=num_settling_channels,
        settled_channels=num_settled_channels,
    )
Exemple #12
0
def _get_required_gas_estimate_for_state(raiden: "RaidenService") -> int:
    num_opening_channels = 0
    num_opened_channels = 0
    num_closing_channels = 0
    num_closed_channels = 0
    num_settling_channels = 0
    num_settled_channels = 0

    # Only use the token networks that have been instantiated. Instantiating
    # the token networks here can have a high performance impacet for a token
    # network registry with lots of registeres tokens.
    with raiden.proxy_manager.token_network_creation_lock:
        num_opening_channels = sum(
            token_network.opening_channels_count for token_network in
            raiden.proxy_manager.address_to_token_network.values())

    chain_state = views.state_from_raiden(raiden)
    registry_address = raiden.default_registry.address
    token_addresses = views.get_token_identifiers(chain_state,
                                                  registry_address)

    for token_address in token_addresses:
        num_opened_channels += len(
            views.get_channelstate_open(chain_state, registry_address,
                                        token_address))
        num_closing_channels += len(
            views.get_channelstate_closing(chain_state, registry_address,
                                           token_address))
        num_closed_channels += len(
            views.get_channelstate_closed(chain_state, registry_address,
                                          token_address))
        num_settling_channels += len(
            views.get_channelstate_settling(chain_state, registry_address,
                                            token_address))
        num_settled_channels += len(
            views.get_channelstate_settled(chain_state, registry_address,
                                           token_address))

    return _get_required_gas_estimate(
        gas_measurements=gas_measurements(
            raiden.contract_manager.contracts_version),
        opening_channels=num_opening_channels,
        opened_channels=num_opened_channels,
        closing_channels=num_closing_channels,
        closed_channels=num_closed_channels,
        settling_channels=num_settling_channels,
        settled_channels=num_settled_channels,
    )
Exemple #13
0
def _get_required_gas_estimate_for_state(raiden) -> int:
    chain_state = views.state_from_raiden(raiden)
    token_addresses = views.get_token_identifiers(
        chain_state, raiden.default_registry.address)

    gas_estimate = 0

    for token_address in token_addresses:
        num_opened_channels = len(
            views.get_channelstate_open(
                chain_state,
                raiden.default_registry.address,
                token_address,
            ))
        num_closing_channels = len(
            views.get_channelstate_closing(
                chain_state,
                raiden.default_registry.address,
                token_address,
            ))
        num_closed_channels = len(
            views.get_channelstate_closed(
                chain_state,
                raiden.default_registry.address,
                token_address,
            ))
        num_settling_channels = len(
            views.get_channelstate_settling(
                chain_state,
                raiden.default_registry.address,
                token_address,
            ))
        num_settled_channels = len(
            views.get_channelstate_settled(
                chain_state,
                raiden.default_registry.address,
                token_address,
            ))

        gas_estimate += _get_required_gas_estimate(
            opened_channels=num_opened_channels,
            closing_channels=num_closing_channels,
            closed_channels=num_closed_channels,
            settling_channels=num_settling_channels,
            settled_channels=num_settled_channels,
        )

    return gas_estimate
Exemple #14
0
def _get_required_gas_estimate_for_state(raiden: "RaidenService") -> int:
    chain_state = views.state_from_raiden(raiden)
    registry_address = raiden.default_registry.address
    token_addresses = views.get_token_identifiers(chain_state,
                                                  registry_address)
    measurements = gas_measurements(raiden.contract_manager.contracts_version)

    gas_estimate = 0

    for token_address in token_addresses:
        token_network_address = views.get_token_network_address_by_token_address(
            chain_state=chain_state,
            token_network_registry_address=registry_address,
            token_address=token_address,
        )
        if token_network_address is None:
            continue

        num_opening_channels = raiden.proxy_manager.token_network(
            token_network_address).opening_channels_count
        num_opened_channels = len(
            views.get_channelstate_open(chain_state, registry_address,
                                        token_address))
        num_closing_channels = len(
            views.get_channelstate_closing(chain_state, registry_address,
                                           token_address))
        num_closed_channels = len(
            views.get_channelstate_closed(chain_state, registry_address,
                                          token_address))
        num_settling_channels = len(
            views.get_channelstate_settling(chain_state, registry_address,
                                            token_address))
        num_settled_channels = len(
            views.get_channelstate_settled(chain_state, registry_address,
                                           token_address))

        gas_estimate += _get_required_gas_estimate(
            gas_measurements=measurements,
            opening_channels=num_opening_channels,
            opened_channels=num_opened_channels,
            closing_channels=num_closing_channels,
            closed_channels=num_closed_channels,
            settling_channels=num_settling_channels,
            settled_channels=num_settled_channels,
        )

    return gas_estimate
Exemple #15
0
def run_smoketests(
    raiden_service: RaidenService,
    transport: str,
    token_addresses,
    discovery_address,
    orig_stdout: IO[str],
    debug: bool = False,
):
    """ Test that the assembled raiden_service correctly reflects the configuration from the
    smoketest_genesis. """
    try:
        chain = raiden_service.chain
        token_network_added_events = raiden_service.default_registry.filter_token_added_events(
        )
        events_token_addresses = [
            event['args']['token_address']
            for event in token_network_added_events
        ]

        assert events_token_addresses == token_addresses

        if transport == 'udp':
            discovery_addresses = list(chain.address_to_discovery.keys())
            assert len(discovery_addresses) == 1, repr(
                chain.address_to_discovery)
            assert discovery_addresses[0] == discovery_address
            discovery = chain.address_to_discovery[discovery_addresses[0]]
            assert discovery.endpoint_by_address(
                raiden_service.address) != TEST_ENDPOINT

        token_networks = views.get_token_identifiers(
            views.state_from_raiden(raiden_service),
            raiden_service.default_registry.address,
        )
        assert len(token_networks) == 1

        channel_state = views.get_channelstate_for(
            views.state_from_raiden(raiden_service),
            raiden_service.default_registry.address,
            token_networks[0],
            decode_hex(TEST_PARTNER_ADDRESS),
        )

        distributable = channel.get_distributable(
            channel_state.our_state,
            channel_state.partner_state,
        )
        assert distributable == TEST_DEPOSIT_AMOUNT
        assert distributable == channel_state.our_state.contract_balance
        assert channel.get_status(channel_state) == CHANNEL_STATE_OPENED

        # Run API test
        run_restapi_smoketests()
    except:  # NOQA pylint: disable=bare-except
        error = traceback.format_exc()
        if debug:
            with contextlib.redirect_stdout(orig_stdout):
                import pdb
                pdb.post_mortem()  # pylint: disable=no-member
        return error

    return None
Exemple #16
0
    def transfer_async(
        self,
        registry_address: typing.PaymentNetworkID,
        token_address: typing.TokenAddress,
        amount: typing.TokenAmount,
        target: typing.Address,
        identifier: typing.PaymentID = None,
        secret: typing.Secret = None,
        secret_hash: typing.SecretHash = None,
    ):

        if not isinstance(amount, int):
            raise InvalidAmount('Amount not a number')

        if amount <= 0:
            raise InvalidAmount('Amount negative')

        if not is_binary_address(token_address):
            raise InvalidAddress('token address is not valid.')

        if not is_binary_address(target):
            raise InvalidAddress('target address is not valid.')

        if secret is not None:
            if len(secret) != SECRET_HEXSTRING_LENGTH:
                raise InvalidSecretOrSecretHash(
                    'secret length should be ' + str(SECRET_HEXSTRING_LENGTH) +
                    '.', )
            if not is_hex(secret):
                raise InvalidSecretOrSecretHash(
                    'provided secret is not an hexadecimal string.')
            secret = to_bytes(hexstr=secret)

        if secret_hash is not None:
            if len(secret_hash) != SECRET_HASH_HEXSTRING_LENGTH:
                raise InvalidSecretOrSecretHash(
                    'secret_hash length should be ' +
                    str(SECRET_HASH_HEXSTRING_LENGTH) + '.', )
            if not is_hex(secret_hash):
                raise InvalidSecretOrSecretHash(
                    'secret_hash is not an hexadecimal string.')
            secret_hash = to_bytes(hexstr=secret_hash)

        if secret is None and secret_hash is not None:
            raise InvalidSecretOrSecretHash(
                'secret_hash without a secret is not supported yet.')

        if secret is not None and secret_hash is not None and secret_hash != sha3(
                secret):
            raise InvalidSecretOrSecretHash(
                'provided secret and secret_hash do not match.')

        valid_tokens = views.get_token_identifiers(
            views.state_from_raiden(self.raiden),
            registry_address,
        )
        if token_address not in valid_tokens:
            raise UnknownTokenAddress('Token address is not known.')

        log.debug(
            'Initiating transfer',
            initiator=pex(self.raiden.address),
            target=pex(target),
            token=pex(token_address),
            amount=amount,
            identifier=identifier,
        )

        payment_network_identifier = self.raiden.default_registry.address
        token_network_identifier = views.get_token_network_identifier_by_token_address(
            chain_state=views.state_from_raiden(self.raiden),
            payment_network_id=payment_network_identifier,
            token_address=token_address,
        )
        payment_status = self.raiden.mediated_transfer_async(
            token_network_identifier=token_network_identifier,
            amount=amount,
            target=target,
            identifier=identifier,
            secret=secret,
            secret_hash=secret_hash,
        )
        return payment_status
Exemple #17
0
    def set_total_channel_deposit(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        partner_address: Address,
        total_deposit: TokenAmount,
        retry_timeout: NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ) -> None:
        """ Set the `total_deposit` in the channel with the peer at `partner_address` and the
        given `token_address` in order to be able to do transfers.

        Raises:
            InvalidBinaryAddress: If either token_address or partner_address is not
                20 bytes long.
            RaidenRecoverableError: May happen for multiple reasons:
                - If the token approval fails, e.g. the token may validate if
                account has enough balance for the allowance.
                - The deposit failed, e.g. the allowance did not set the token
                aside for use and the user spent it before deposit was called.
                - The channel was closed/settled between the allowance call and
                the deposit call.
            AddressWithoutCode: The channel was settled during the deposit
                execution.
            DepositOverLimit: The total deposit amount is higher than the limit.
            UnexpectedChannelState: The channel is no longer in an open state.
        """
        chain_state = views.state_from_raiden(self.raiden)

        token_addresses = views.get_token_identifiers(chain_state,
                                                      registry_address)
        channel_state = views.get_channelstate_for(
            chain_state=chain_state,
            token_network_registry_address=registry_address,
            token_address=token_address,
            partner_address=partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for token in channel deposit")

        if not is_binary_address(partner_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for partner in channel deposit"
            )

        if token_address not in token_addresses:
            raise UnknownTokenAddress("Unknown token address")

        if channel_state is None:
            raise NonexistingChannel(
                "No channel with partner_address for the given token")

        confirmed_block_identifier = chain_state.block_hash
        token = self.raiden.proxy_manager.token(
            token_address, block_identifier=confirmed_block_identifier)
        token_network_registry = self.raiden.proxy_manager.token_network_registry(
            registry_address, block_identifier=confirmed_block_identifier)
        token_network_address = token_network_registry.get_token_network(
            token_address=token_address,
            block_identifier=confirmed_block_identifier)

        if token_network_address is None:
            raise UnknownTokenAddress(
                f"Token {to_checksum_address(token_address)} is not registered "
                f"with the network {to_checksum_address(registry_address)}.")

        token_network_proxy = self.raiden.proxy_manager.token_network(
            address=token_network_address,
            block_identifier=confirmed_block_identifier)
        channel_proxy = self.raiden.proxy_manager.payment_channel(
            channel_state=channel_state,
            block_identifier=confirmed_block_identifier)

        blockhash = chain_state.block_hash
        token_network_proxy = channel_proxy.token_network

        safety_deprecation_switch = token_network_proxy.safety_deprecation_switch(
            block_identifier=blockhash)

        balance = token.balance_of(self.raiden.address,
                                   block_identifier=blockhash)

        network_balance = token.balance_of(
            address=Address(token_network_address), block_identifier=blockhash)
        token_network_deposit_limit = token_network_proxy.token_network_deposit_limit(
            block_identifier=blockhash)

        addendum = total_deposit - channel_state.our_state.contract_balance

        channel_participant_deposit_limit = token_network_proxy.channel_participant_deposit_limit(
            block_identifier=blockhash)
        total_channel_deposit = total_deposit + channel_state.partner_state.contract_balance

        is_channel_open = channel.get_status(
            channel_state) == ChannelState.STATE_OPENED

        if not is_channel_open:
            raise UnexpectedChannelState("Channel is not in an open state.")

        if safety_deprecation_switch:
            msg = ("This token_network has been deprecated. "
                   "All channels in this network should be closed and "
                   "the usage of the newly deployed token network contract "
                   "is highly encouraged.")
            raise TokenNetworkDeprecated(msg)

        if total_deposit <= channel_state.our_state.contract_balance:
            raise DepositMismatch("Total deposit did not increase.")

        # If this check succeeds it does not imply the `deposit` will
        # succeed, since the `deposit` transaction may race with another
        # transaction.
        if not (balance >= addendum):
            msg = "Not enough balance to deposit. {} Available={} Needed={}".format(
                to_checksum_address(token_address), balance, addendum)
            raise InsufficientFunds(msg)

        if network_balance + addendum > token_network_deposit_limit:
            msg = f"Deposit of {addendum} would have exceeded the token network deposit limit."
            raise DepositOverLimit(msg)

        if total_deposit > channel_participant_deposit_limit:
            msg = (f"Deposit of {total_deposit} is larger than the "
                   f"channel participant deposit limit")
            raise DepositOverLimit(msg)

        if total_channel_deposit >= UINT256_MAX:
            raise DepositOverLimit("Deposit overflow")

        try:
            channel_proxy.approve_and_set_total_deposit(
                total_deposit=total_deposit, block_identifier=blockhash)
        except RaidenRecoverableError as e:
            log.info(f"Deposit failed. {str(e)}")

        target_address = self.raiden.address
        waiting.wait_for_participant_deposit(
            raiden=self.raiden,
            token_network_registry_address=registry_address,
            token_address=token_address,
            partner_address=partner_address,
            target_address=target_address,
            target_balance=total_deposit,
            retry_timeout=retry_timeout,
        )
Exemple #18
0
    def set_total_channel_deposit(
        self,
        registry_address: typing.PaymentNetworkID,
        token_address: typing.TokenAddress,
        partner_address: typing.Address,
        total_deposit: typing.TokenAmount,
        retry_timeout: typing.NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ):
        """ Set the `total_deposit` in the channel with the peer at `partner_address` and the
        given `token_address` in order to be able to do transfers.

        Raises:
            InvalidAddress: If either token_address or partner_address is not
                20 bytes long.
            TransactionThrew: May happen for multiple reasons:
                - If the token approval fails, e.g. the token may validate if
                account has enough balance for the allowance.
                - The deposit failed, e.g. the allowance did not set the token
                aside for use and the user spent it before deposit was called.
                - The channel was closed/settled between the allowance call and
                the deposit call.
            AddressWithoutCode: The channel was settled during the deposit
                execution.
            DepositOverLimit: The total deposit amount is higher than the limit.
        """
        chain_state = views.state_from_raiden(self.raiden)

        token_addresses = views.get_token_identifiers(
            chain_state,
            registry_address,
        )
        channel_state = views.get_channelstate_for(
            chain_state=chain_state,
            payment_network_id=registry_address,
            token_address=token_address,
            partner_address=partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidAddress(
                'Expected binary address format for token in channel deposit')

        if not is_binary_address(partner_address):
            raise InvalidAddress(
                'Expected binary address format for partner in channel deposit'
            )

        if token_address not in token_addresses:
            raise UnknownTokenAddress('Unknown token address')

        if channel_state is None:
            raise InvalidAddress(
                'No channel with partner_address for the given token')

        if self.raiden.config['environment_type'] == Environment.PRODUCTION:
            per_token_network_deposit_limit = RED_EYES_PER_TOKEN_NETWORK_LIMIT
        else:
            per_token_network_deposit_limit = UINT256_MAX

        token = self.raiden.chain.token(token_address)
        token_network_registry = self.raiden.chain.token_network_registry(
            registry_address)
        token_network_address = token_network_registry.get_token_network(
            token_address)
        token_network_proxy = self.raiden.chain.token_network(
            token_network_address)
        channel_proxy = self.raiden.chain.payment_channel(
            canonical_identifier=channel_state.canonical_identifier, )

        if total_deposit == 0:
            raise DepositMismatch(
                'Attempted to deposit with total deposit being 0')

        addendum = total_deposit - channel_state.our_state.contract_balance

        total_network_balance = token.balance_of(registry_address)

        if total_network_balance + addendum > per_token_network_deposit_limit:
            raise DepositOverLimit(
                f'The deposit of {addendum} will exceed the '
                f'token network limit of {per_token_network_deposit_limit}', )

        balance = token.balance_of(self.raiden.address)

        functions = token_network_proxy.proxy.contract.functions
        deposit_limit = functions.channel_participant_deposit_limit().call()

        if total_deposit > deposit_limit:
            raise DepositOverLimit(
                f'The additional deposit of {addendum} will exceed the '
                f'channel participant limit of {deposit_limit}', )

        # If this check succeeds it does not imply the the `deposit` will
        # succeed, since the `deposit` transaction may race with another
        # transaction.
        if not balance >= addendum:
            msg = 'Not enough balance to deposit. {} Available={} Needed={}'.format(
                pex(token_address),
                balance,
                addendum,
            )
            raise InsufficientFunds(msg)

        # set_total_deposit calls approve
        # token.approve(netcontract_address, addendum)
        channel_proxy.set_total_deposit(
            total_deposit=total_deposit,
            block_identifier=views.state_from_raiden(self.raiden).block_hash,
        )

        target_address = self.raiden.address
        waiting.wait_for_participant_newbalance(
            raiden=self.raiden,
            payment_network_id=registry_address,
            token_address=token_address,
            partner_address=partner_address,
            target_address=target_address,
            target_balance=total_deposit,
            retry_timeout=retry_timeout,
        )
Exemple #19
0
def run_smoketest(print_step: StepPrinter, setup: RaidenTestSetup) -> None:
    print_step("Starting Raiden")

    app = None
    try:
        app = run_raiden_service(**setup.args)
        raiden_api = app.raiden_api
        assert raiden_api is not None  # for mypy
        partner_address = Address(b"1" * 20)

        block = BlockNumber(app.get_block_number() +
                            DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS)
        # Proxies now use the confirmed block hash to query the chain for
        # prerequisite checks. Wait a bit here to make sure that the confirmed
        # block hash contains the deployed token network or else things break
        wait_for_block(raiden=app, block_number=block, retry_timeout=1.0)

        raiden_api.channel_open(
            registry_address=TokenNetworkRegistryAddress(
                setup.contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]),
            token_address=TokenAddress(
                to_canonical_address(setup.token.address)),
            partner_address=partner_address,
        )
        raiden_api.set_total_channel_deposit(
            registry_address=TokenNetworkRegistryAddress(
                setup.contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]),
            token_address=TokenAddress(
                to_canonical_address(setup.token.address)),
            partner_address=partner_address,
            total_deposit=TEST_DEPOSIT_AMOUNT,
        )
        token_addresses = [to_checksum_address(setup.token.address)
                           ]  # type: ignore

        print_step("Running smoketest")

        raiden_service = app
        token_network_added_events = raiden_service.default_registry.filter_token_added_events(
        )
        events_token_addresses = [
            event["args"]["token_address"]
            for event in token_network_added_events
        ]

        assert events_token_addresses == token_addresses

        token_networks = views.get_token_identifiers(
            views.state_from_raiden(raiden_service),
            raiden_service.default_registry.address)
        assert len(token_networks) == 1

        channel_state = views.get_channelstate_for(
            chain_state=views.state_from_raiden(raiden_service),
            token_network_registry_address=raiden_service.default_registry.
            address,
            token_address=token_networks[0],
            partner_address=partner_address,
        )
        assert channel_state

        distributable = channel.get_distributable(channel_state.our_state,
                                                  channel_state.partner_state)
        assert distributable == TEST_DEPOSIT_AMOUNT
        assert Balance(
            distributable) == channel_state.our_state.contract_balance
        assert channel.get_status(channel_state) == ChannelState.STATE_OPENED

        port_number = raiden_service.config.rest_api.port
        response = requests.get(
            f"http://localhost:{port_number}/api/v1/channels")

        assert response.status_code == HTTPStatus.OK

        response_json = json.loads(response.content)
        assert response_json[0]["partner_address"] == to_checksum_address(
            partner_address)
        assert response_json[0]["state"] == "opened"
        assert int(response_json[0]["balance"]) > 0
    finally:
        if app is not None:
            app.stop()
            app.greenlet.get()
Exemple #20
0
    def transfer_async(
        self,
        registry_address: PaymentNetworkID,
        token_address: TokenAddress,
        amount: TokenAmount,
        target: Address,
        identifier: PaymentID = None,
        secret: Secret = None,
        secrethash: SecretHash = None,
    ):

        if not isinstance(amount, int):
            raise InvalidAmount("Amount not a number")

        if amount <= 0:
            raise InvalidAmount("Amount negative")

        if not is_binary_address(token_address):
            raise InvalidAddress("token address is not valid.")

        if not is_binary_address(target):
            raise InvalidAddress("target address is not valid.")

        if secret is not None:
            if len(secret) != SECRET_HEXSTRING_LENGTH:
                raise InvalidSecretOrSecretHash(
                    "secret length should be " + str(SECRET_HEXSTRING_LENGTH) + "."
                )
            if not is_hex(secret):
                raise InvalidSecretOrSecretHash("provided secret is not an hexadecimal string.")
            secret = to_bytes(hexstr=secret)

        if secrethash is not None:
            if len(secrethash) != SECRETHASH_HEXSTRING_LENGTH:
                raise InvalidSecretOrSecretHash(
                    "secret_hash length should be " + str(SECRETHASH_HEXSTRING_LENGTH) + "."
                )
            if not is_hex(secrethash):
                raise InvalidSecretOrSecretHash("secret_hash is not an hexadecimal string.")
            secrethash = to_bytes(hexstr=secrethash)

        # if both secret and secrethash were provided we check that sha3(secret)
        # matches the secerthash. Note that it is valid to provide a secert_hash
        # without providing a secret
        if secret is not None and secrethash is not None and secrethash != sha3(secret):
            raise InvalidSecretOrSecretHash("provided secret and secret_hash do not match.")

        valid_tokens = views.get_token_identifiers(
            views.state_from_raiden(self.raiden), registry_address
        )
        if token_address not in valid_tokens:
            raise UnknownTokenAddress("Token address is not known.")

        log.debug(
            "Initiating transfer",
            initiator=pex(self.raiden.address),
            target=pex(target),
            token=pex(token_address),
            amount=amount,
            identifier=identifier,
        )

        payment_network_identifier = self.raiden.default_registry.address
        token_network_identifier = views.get_token_network_identifier_by_token_address(
            chain_state=views.state_from_raiden(self.raiden),
            payment_network_id=payment_network_identifier,
            token_address=token_address,
        )
        payment_status = self.raiden.mediated_transfer_async(
            token_network_identifier=token_network_identifier,
            amount=amount,
            target=target,
            identifier=identifier,
            secret=secret,
            secrethash=secrethash,
        )
        return payment_status
Exemple #21
0
    def transfer_async(
        self,
        registry_address: PaymentNetworkID,
        token_address: TokenAddress,
        amount: TokenAmount,
        target: Address,
        identifier: PaymentID = None,
        secret: Secret = None,
        secrethash: SecretHash = None,
    ):
        current_state = views.state_from_raiden(self.raiden)
        payment_network_identifier = self.raiden.default_registry.address

        if not isinstance(amount, int):
            raise InvalidAmount("Amount not a number")

        if amount <= 0:
            raise InvalidAmount("Amount negative")

        if amount > UINT256_MAX:
            raise InvalidAmount("Amount too large")

        if not is_binary_address(token_address):
            raise InvalidAddress("token address is not valid.")

        if token_address not in views.get_token_identifiers(current_state, registry_address):
            raise UnknownTokenAddress("Token address is not known.")

        if not is_binary_address(target):
            raise InvalidAddress("target address is not valid.")

        valid_tokens = views.get_token_identifiers(
            views.state_from_raiden(self.raiden), registry_address
        )
        if token_address not in valid_tokens:
            raise UnknownTokenAddress("Token address is not known.")

        if secret is not None and not isinstance(secret, typing.T_Secret):
            raise InvalidSecret("secret is not valid.")

        if secrethash is not None and not isinstance(secrethash, typing.T_SecretHash):
            raise InvalidSecretHash("secrethash is not valid.")

        log.debug(
            "Initiating transfer",
            initiator=pex(self.raiden.address),
            target=pex(target),
            token=pex(token_address),
            amount=amount,
            identifier=identifier,
        )

        token_network_identifier = views.get_token_network_identifier_by_token_address(
            chain_state=current_state,
            payment_network_id=payment_network_identifier,
            token_address=token_address,
        )
        payment_status = self.raiden.mediated_transfer_async(
            token_network_identifier=token_network_identifier,
            amount=amount,
            target=target,
            identifier=identifier,
            secret=secret,
            secrethash=secrethash,
        )
        return payment_status
Exemple #22
0
    def transfer_async(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        amount: PaymentAmount,
        target: TargetAddress,
        identifier: PaymentID = None,
        secret: Secret = None,
        secrethash: SecretHash = None,
        lock_timeout: BlockTimeout = None,
    ) -> "PaymentStatus":
        current_state = views.state_from_raiden(self.raiden)
        token_network_registry_address = self.raiden.default_registry.address

        if not isinstance(amount, int):  # pragma: no unittest
            raise InvalidAmount("Amount not a number")

        if Address(target) == self.address:
            raise SamePeerAddress("Address must be different than ours")

        if amount <= 0:
            raise InvalidAmount("Amount negative")

        if amount > UINT256_MAX:
            raise InvalidAmount("Amount too large")

        if not is_binary_address(token_address):
            raise InvalidBinaryAddress("token address is not valid.")

        if token_address not in views.get_token_identifiers(
                current_state, registry_address):
            raise UnknownTokenAddress("Token address is not known.")

        if not is_binary_address(target):
            raise InvalidBinaryAddress("target address is not valid.")

        valid_tokens = views.get_token_identifiers(
            views.state_from_raiden(self.raiden), registry_address)
        if token_address not in valid_tokens:
            raise UnknownTokenAddress("Token address is not known.")

        if secret is not None and not isinstance(secret, T_Secret):
            raise InvalidSecret("secret is not valid.")

        if secrethash is not None and not isinstance(secrethash, T_SecretHash):
            raise InvalidSecretHash("secrethash is not valid.")

        if identifier is None:
            identifier = create_default_identifier()

        if identifier <= 0:
            raise InvalidPaymentIdentifier(
                "Payment identifier cannot be 0 or negative")

        if identifier > UINT64_MAX:
            raise InvalidPaymentIdentifier("Payment identifier is too large")

        log.debug(
            "Initiating transfer",
            initiator=to_checksum_address(self.raiden.address),
            target=to_checksum_address(target),
            token=to_checksum_address(token_address),
            amount=amount,
            identifier=identifier,
        )

        token_network_address = views.get_token_network_address_by_token_address(
            chain_state=current_state,
            token_network_registry_address=token_network_registry_address,
            token_address=token_address,
        )

        if token_network_address is None:
            raise UnknownTokenAddress(
                f"Token {to_checksum_address(token_address)} is not registered "
                f"with the network {to_checksum_address(registry_address)}.")

        payment_status = self.raiden.mediated_transfer_async(
            token_network_address=token_network_address,
            amount=amount,
            target=target,
            identifier=identifier,
            secret=secret,
            secrethash=secrethash,
            lock_timeout=lock_timeout,
        )
        return payment_status
Exemple #23
0
def run_smoketest(
    print_step: Callable,
    args: Dict[str, Any],
    contract_addresses: Dict[str, Address],
    token: ContractProxy,
):
    print_step("Starting Raiden")

    app = None
    api_server = None
    try:
        app = run_app(**args)
        raiden_api = RaidenAPI(app.raiden)
        rest_api = RestAPI(raiden_api)
        (api_host, api_port) = split_endpoint(args["api_address"])
        api_server = APIServer(rest_api, config={"host": api_host, "port": api_port})
        api_server.start()

        block = BlockNumber(app.raiden.get_block_number() + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS)
        # Proxies now use the confirmed block hash to query the chain for
        # prerequisite checks. Wait a bit here to make sure that the confirmed
        # block hash contains the deployed token network or else things break
        wait_for_block(raiden=app.raiden, block_number=block, retry_timeout=1.0)

        raiden_api.channel_open(
            registry_address=TokenNetworkRegistryAddress(
                contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]
            ),
            token_address=TokenAddress(to_canonical_address(token.contract.address)),
            partner_address=ConnectionManager.BOOTSTRAP_ADDR,
        )
        raiden_api.set_total_channel_deposit(
            registry_address=TokenNetworkRegistryAddress(
                contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]
            ),
            token_address=TokenAddress(to_canonical_address(token.contract.address)),
            partner_address=ConnectionManager.BOOTSTRAP_ADDR,
            total_deposit=TEST_DEPOSIT_AMOUNT,
        )
        token_addresses = [to_checksum_address(token.contract.address)]

        print_step("Running smoketest")

        raiden_service = app.raiden
        token_network_added_events = raiden_service.default_registry.filter_token_added_events()
        events_token_addresses = [
            event["args"]["token_address"] for event in token_network_added_events
        ]

        assert events_token_addresses == token_addresses

        token_networks = views.get_token_identifiers(
            views.state_from_raiden(raiden_service), raiden_service.default_registry.address
        )
        assert len(token_networks) == 1

        channel_state = views.get_channelstate_for(
            chain_state=views.state_from_raiden(raiden_service),
            token_network_registry_address=raiden_service.default_registry.address,
            token_address=token_networks[0],
            partner_address=ConnectionManager.BOOTSTRAP_ADDR,
        )
        assert channel_state

        distributable = channel.get_distributable(
            channel_state.our_state, channel_state.partner_state
        )
        assert distributable == TEST_DEPOSIT_AMOUNT
        assert distributable == channel_state.our_state.contract_balance
        assert channel.get_status(channel_state) == ChannelState.STATE_OPENED

        port_number = raiden_service.config.api_port
        response = requests.get(f"http://localhost:{port_number}/api/v1/channels")

        assert response.status_code == HTTPStatus.OK

        response_json = json.loads(response.content)
        assert response_json[0]["partner_address"] == to_checksum_address(
            ConnectionManager.BOOTSTRAP_ADDR
        )
        assert response_json[0]["state"] == "opened"
        assert int(response_json[0]["balance"]) > 0
    finally:
        if api_server is not None:
            api_server.stop()
            api_server.greenlet.get()

        if app is not None:
            app.stop()
            app.raiden.greenlet.get()
Exemple #24
0
    def set_total_channel_withdraw(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        partner_address: Address,
        total_withdraw: WithdrawAmount,
        retry_timeout: NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ) -> None:
        """ Set the `total_withdraw` in the channel with the peer at `partner_address` and the
        given `token_address`.

        Raises:
            InvalidBinaryAddress: If either token_address or partner_address is not
                20 bytes long.
            RaidenUnrecoverableError: May happen for multiple reasons:
                - During preconditions checks, if the channel was not open
                  at the time of the approve_and_set_total_deposit call.
                - If the transaction fails during gas estimation or
                  if a previous withdraw transaction with the same value
                   was already mined.
            DepositMismatch: The total withdraw amount did not increase.
        """
        chain_state = views.state_from_raiden(self.raiden)

        token_addresses = views.get_token_identifiers(chain_state,
                                                      registry_address)
        channel_state = views.get_channelstate_for(
            chain_state=chain_state,
            token_network_registry_address=registry_address,
            token_address=token_address,
            partner_address=partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for token in channel deposit")

        if not is_binary_address(partner_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for partner in channel deposit"
            )

        if token_address not in token_addresses:
            raise UnknownTokenAddress("Unknown token address")

        if channel_state is None:
            raise NonexistingChannel(
                "No channel with partner_address for the given token")

        if total_withdraw <= channel_state.our_total_withdraw:
            raise WithdrawMismatch(
                f"Total withdraw {total_withdraw} did not increase")

        current_balance = channel.get_balance(
            sender=channel_state.our_state,
            receiver=channel_state.partner_state)
        amount_to_withdraw = total_withdraw - channel_state.our_total_withdraw
        if amount_to_withdraw > current_balance:
            raise InsufficientFunds(
                "The withdraw of {} is bigger than the current balance of {}".
                format(amount_to_withdraw, current_balance))

        self.raiden.withdraw(
            canonical_identifier=channel_state.canonical_identifier,
            total_withdraw=total_withdraw)

        waiting.wait_for_withdraw_complete(
            raiden=self.raiden,
            canonical_identifier=channel_state.canonical_identifier,
            total_withdraw=total_withdraw,
            retry_timeout=retry_timeout,
        )