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 ]
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
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
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() )
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, )
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
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, )
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, )
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
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)
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, )
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, )
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
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
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
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
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, )
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, )
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()
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
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
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
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()
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, )