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 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_network_addresses_for( 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, ) token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state=views.state_from_raiden(self.raiden), payment_network_id=registry_address, token_address=token_address, ) for channel_state in channels_to_close: channel_close = ActionChannelClose( token_network_identifier=token_network_identifier, channel_identifier=channel_state.identifier, ) self.raiden.handle_state_change(channel_close) 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 channel_batch_close(self, token_address, partner_addresses, poll_timeout=DEFAULT_POLL_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 isaddress(token_address): raise InvalidAddress( 'Expected binary address format for token in channel close') if not all(map(isaddress, partner_addresses)): raise InvalidAddress( 'Expected binary address format for partner in channel close') valid_tokens = views.get_token_network_addresses_for( views.state_from_raiden(self.raiden), self.raiden.default_registry.address, ) if token_address not in valid_tokens: raise UnknownTokenAddress('Token address is not known.') registry_address = self.raiden.default_registry.address node_state = views.state_from_raiden(self.raiden) channels_to_close = views.filter_channels_by_partneraddress( node_state, registry_address, token_address, partner_addresses, ) for channel_state in channels_to_close: channel_close = ActionChannelClose(channel_state.identifier) state_change = ActionForTokenNetwork( registry_address, token_address, channel_close, ) self.raiden.handle_state_change(state_change) msg = 'After {} seconds the deposit was not properly processed.'.format( poll_timeout) channel_ids = [ channel_state.identifier for channel_state in channels_to_close ] with gevent.Timeout(poll_timeout, EthNodeCommunicationError(msg)): waiting.wait_for_close( self.raiden, registry_address, token_address, channel_ids, self.raiden.alarm.wait_time, )
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_network_addresses_for( 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, ) token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state=views.state_from_raiden(self.raiden), payment_network_id=registry_address, token_address=token_address, ) for channel_state in channels_to_close: channel_close = ActionChannelClose( token_network_identifier=token_network_identifier, channel_identifier=channel_state.identifier, ) self.raiden.handle_state_change(channel_close) 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 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 test_filter_channels_by_partneraddress_empty(chain_state): token_network_registry_address = factories.make_address() token_address = factories.make_address() partner_addresses = [factories.make_address(), factories.make_address()] assert (filter_channels_by_partneraddress( chain_state=chain_state, token_network_registry_address=token_network_registry_address, token_address=token_address, partner_addresses=partner_addresses, ) == [])
def test_filter_channels_by_partneraddress(): test_state = factories.make_chain_state(number_of_channels=3) partner_addresses = [c.partner_state.address for c in test_state.channels[1:]] assert ( views.filter_channels_by_partneraddress( chain_state=test_state.chain_state, token_network_registry_address=test_state.token_network_registry_address, token_address=test_state.token_address, partner_addresses=partner_addresses, ) == test_state.channels[1:] )
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_network_addresses_for( views.state_from_raiden(self.raiden), 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, registry_address, token_address, partner_addresses, ) token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_raiden(self.raiden), registry_address, token_address, ) # If concurrent operations are happening on one of the channels, fail entire # request. with ExitStack() as stack: # Put all the locks in this outer context so that the netting channel functions # don't release the locks when their context goes out of scope for channel_state in channels_to_close: channel = self.raiden.chain.payment_channel( token_network_identifier, channel_state.identifier, ) stack.enter_context(channel.lock_or_raise()) for channel_state in channels_to_close: channel_close = ActionChannelClose( token_network_identifier, channel_state.identifier, ) self.raiden.handle_state_change(channel_close) channel_ids = [ channel_state.identifier for channel_state in channels_to_close ] waiting.wait_for_close( self.raiden, registry_address, token_address, channel_ids, retry_timeout, )
def channel_batch_close(self, token_address, partner_addresses, poll_timeout=DEFAULT_POLL_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 isaddress(token_address): raise InvalidAddress( 'Expected binary address format for token in channel close') if not all(map(isaddress, partner_addresses)): raise InvalidAddress( 'Expected binary address format for partner in channel close') valid_tokens = views.get_token_network_addresses_for( views.state_from_raiden(self.raiden), self.raiden.default_registry.address, ) if token_address not in valid_tokens: raise UnknownTokenAddress('Token address is not known.') registry_address = self.raiden.default_registry.address node_state = views.state_from_raiden(self.raiden) channels_to_close = views.filter_channels_by_partneraddress( node_state, registry_address, token_address, partner_addresses, ) # If concurrent operations are happening on one of the channels, fail entire # request. with ExitStack() as stack: # Put all the locks in this outer context so that the netting channel functions # don't release the locks when their context goes out of scope for channel_state in channels_to_close: channel = self.raiden.chain.netting_channel( channel_state.identifier) # Check if we can acquire the lock. If we can't raise an exception, which # will cause the ExitStack to exit, releasing all locks acquired so far if not channel.channel_operations_lock.acquire(blocking=False): raise ChannelBusyError( f'Channel with id {channel_state.identifier} is ' f'busy with another ongoing operation.') stack.push(channel.channel_operations_lock) for channel_state in channels_to_close: channel_close = ActionChannelClose( registry_address, token_address, channel_state.identifier, ) self.raiden.handle_state_change(channel_close) msg = 'After {} seconds the deposit was not properly processed.'.format( poll_timeout) channel_ids = [ channel_state.identifier for channel_state in channels_to_close ] with gevent.Timeout(poll_timeout, EthNodeCommunicationError(msg)): waiting.wait_for_close( self.raiden, registry_address, token_address, channel_ids, self.raiden.alarm.wait_time, )
def channel_batch_close( self, registry_address, token_address, partner_addresses, poll_timeout=DEFAULT_POLL_TIMEOUT, retry_timeout=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_network_addresses_for( views.state_from_raiden(self.raiden), 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, registry_address, token_address, partner_addresses, ) token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_raiden(self.raiden), registry_address, token_address, ) # If concurrent operations are happening on one of the channels, fail entire # request. with ExitStack() as stack: # Put all the locks in this outer context so that the netting channel functions # don't release the locks when their context goes out of scope for channel_state in channels_to_close: channel = self.raiden.chain.payment_channel( token_network_identifier, channel_state.identifier, ) stack.enter_context(channel.lock_or_raise()) for channel_state in channels_to_close: channel_close = ActionChannelClose( token_network_identifier, channel_state.identifier, ) self.raiden.handle_state_change(channel_close) msg = 'After {} seconds the closing transactions were not properly processed.'.format( poll_timeout, ) channel_ids = [channel_state.identifier for channel_state in channels_to_close] with gevent.Timeout(poll_timeout, EthNodeCommunicationError(msg)): waiting.wait_for_close( self.raiden, registry_address, token_address, channel_ids, retry_timeout, )