def new_netting_channel(self, peer1, peer2, settle_timeout):
        """ Creates a new netting contract between peer1 and peer2.

        Raises:
            ValueError: If peer1 or peer2 is not a valid address.
        """
        if not isaddress(peer1):
            raise ValueError('The pee1 must be a valid address')

        if not isaddress(peer2):
            raise ValueError('The peer2 must be a valid address')

        if privatekey_to_address(self.private_key) == peer1:
            other = peer2
        else:
            other = peer1

        netting_channel_address_hex = self.proxy.newChannel(other, settle_timeout)
        self.tester_state.mine(number_of_blocks=1)

        channel = NettingChannelTesterMock(
            self.tester_state,
            self.private_key,
            netting_channel_address_hex,
        )

        return decode_hex(channel.address)
    def open_channel(
            self,
            token_address,
            partner_address,
            settle_timeout=None,
            reveal_timeout=None):

        invalid_timeout = (
            settle_timeout < NETTINGCHANNEL_SETTLE_TIMEOUT_MIN or
            settle_timeout > NETTINGCHANNEL_SETTLE_TIMEOUT_MAX
        )
        if invalid_timeout:
            raise InvalidSettleTimeout('`settle_timeout` should be in range [{}, {}].'.format(
                NETTINGCHANNEL_SETTLE_TIMEOUT_MIN, NETTINGCHANNEL_SETTLE_TIMEOUT_MAX
            ))

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

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

        reveal_value = reveal_timeout if reveal_timeout is not None else self.reveal_timeout
        channel = self.make_channel(
            token_address=token_address,
            partner_address=partner_address,
            settle_timeout=settle_timeout,
            reveal_timeout=reveal_value
        )
        self.channels.append(channel)
        return channel
    def transfer_async(self, asset_address, amount, target, identifier=None,
                       callback=None):
        # pylint: disable=too-many-arguments

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

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

        asset_address_bin = safe_address_decode(asset_address)
        target_bin = safe_address_decode(target)

        if not isaddress(asset_address_bin) or asset_address_bin not in self.assets:
            raise InvalidAddress('asset address is not valid.')

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

        asset_manager = self.raiden.get_manager_by_asset_address(asset_address_bin)

        if not asset_manager.has_path(self.raiden.address, target_bin):
            raise NoPathError('No path to address found')

        transfer_manager = asset_manager.transfermanager
        async_result = transfer_manager.transfer_async(
            amount,
            target_bin,
            identifier=identifier,
            callback=callback,
        )
        return async_result
    def settle(self, asset_address, partner_address):
        """ Settle a closed channel with `partner_address` for the given `asset_address`. """
        asset_address_bin = safe_address_decode(asset_address)
        partner_address_bin = safe_address_decode(partner_address)

        if not isaddress(asset_address_bin) or asset_address_bin not in self.assets:
            raise InvalidAddress('asset address is not valid.')

        if not isaddress(partner_address_bin):
            raise InvalidAddress('partner_address is not valid.')

        manager = self.raiden.get_manager_by_asset_address(asset_address_bin)
        channel = manager.get_channel_by_partner_address(partner_address_bin)

        if channel.isopen:
            raise InvalidState('channel is still open.')

        netting_channel = channel.external_state.netting_channel

        if not (self.raiden.chain.client.blocknumber() >=
                (channel.external_state.closed_block +
                 netting_channel.detail(self.raiden.address)['settle_timeout'])):
            raise InvalidState('settlement period not over.')

        netting_channel.settle()
        return netting_channel
Exemple #5
0
    def transfer(self, asset_address, amount, target, callback=None):
        """ Do a transfer with `target` with the given `amount` of `asset_address`. """
        if not isinstance(amount, (int, long)):
            raise InvalidAmount('Amount not a number')

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

        asset_address_bin = safe_address_decode(asset_address)
        target_bin = safe_address_decode(target)

        asset_manager = self.raiden.get_manager_by_asset_address(asset_address_bin)

        if not isaddress(asset_address_bin) or asset_address_bin not in self.assets:
            raise InvalidAddress('asset address is not valid.')

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

        if not asset_manager.has_path(self.raiden.address, target_bin):
            raise NoPathError('No path to address found')

        transfer_manager = self.raiden.managers_by_asset_address[asset_address_bin].transfermanager
        task = transfer_manager.transfer(amount, target_bin, callback=callback)
        task.join()
Exemple #6
0
    def close(self, asset_address, partner_address):
        """ Close a channel opened with `partner_address` for the given `asset_address`. """
        asset_address_bin = safe_address_decode(asset_address)
        partner_address_bin = safe_address_decode(partner_address)

        if not isaddress(asset_address_bin) or asset_address_bin not in self.assets:
            raise InvalidAddress('asset address is not valid.')

        if not isaddress(partner_address_bin):
            raise InvalidAddress('partner_address is not valid.')

        manager = self.raiden.get_manager_by_asset_address(asset_address_bin)
        channel = manager.get_channel_by_partner_address(partner_address_bin)

        first_transfer = None
        if channel.received_transfers:
            first_transfer = channel.received_transfers[-1]

        second_transfer = None
        if channel.sent_transfers:
            second_transfer = channel.sent_transfers[-1]

        netting_channel = channel.external_state.netting_channel
        netting_channel.close(
            self.raiden.address,
            first_transfer,
            second_transfer,
        )
def make_graph(edge_list):
    """ Return a graph that represents the connections among the netting
    contracts.

    Args:
        edge_list (List[(address1, address2)]): All the channels that compose
            the graph.

    Returns:
        Graph A networkx.Graph instance were the graph nodes are nodes in the
            network and the edges are nodes that have a channel between them.
    """

    for edge in edge_list:
        if len(edge) != 2:
            raise ValueError('All values in edge_list must be of length two (origin, destination)')

        origin, destination = edge

        if not isaddress(origin) or not isaddress(destination):
            raise ValueError('All values in edge_list must be valid addresses')

    graph = networkx.Graph()  # undirected graph, for bidirectional channels

    for first, second in edge_list:
        graph.add_edge(first, second)

    return graph
    def settle(self, token_address, partner_address):
        """ Settle a closed channel with `partner_address` for the given `token_address`. """

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

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

        if not isaddress(token_address) or token_address not in self.tokens:
            raise InvalidAddress('token address is not valid.')

        if not isaddress(partner_address):
            raise InvalidAddress('partner_address is not valid.')

        graph = self.raiden.token_to_channelgraph[token_address]
        channel = graph.partneraddress_to_channel[partner_address]

        if channel.can_transfer:
            raise InvalidState('channel is still open.')

        netting_channel = channel.external_state.netting_channel

        current_block = self.raiden.chain.block_number()
        settle_timeout = netting_channel.detail()['settle_timeout']
        settle_expiration = channel.external_state.closed_block + settle_timeout

        if current_block <= settle_expiration:
            raise InvalidState('settlement period is not yet over.')

        netting_channel.settle()
        return channel
Exemple #9
0
    def request_transfer(self, asset_address, amount, target):
        if not isaddress(asset_address) or asset_address not in self.assets:
            raise InvalidAddress('asset address is not valid.')

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

        transfer_manager = self.raiden.assetmanagers[asset_address].transfermanager
        transfer_manager.request_transfer(amount, target)
    def get_channel_list(self, token_address=None, partner_address=None):
        """Returns a list of channels associated with the optionally given
           `token_address` and/or `partner_address`.

        Args:
            token_address (bin): an optionally provided token address
            partner_address (bin): an optionally provided partner address

        Return:
            A list containing all channels the node participates. Optionally
            filtered by a token address and/or partner address.

        Raises:
            KeyError: An error occurred when the token address is unknown to the node.
        """

        if token_address and not isaddress(token_address):
            raise InvalidAddress('Expected binary address format for token in get_channel_list')

        if partner_address and not isaddress(partner_address):
            raise InvalidAddress('Expected binary address format for partner in get_channel_list')

        result = list()

        if token_address and partner_address:
            graph = self.raiden.token_to_channelgraph[token_address]

            channel = graph.partneraddress_to_channel.get(partner_address)

            if channel:
                result = [channel]

        elif token_address:
            graph = self.raiden.token_to_channelgraph.get(token_address)

            if graph:
                result = list(graph.address_to_channel.values())

        elif partner_address:
            partner_channels = [
                graph.partneraddress_to_channel[partner_address]
                for graph in self.raiden.token_to_channelgraph.values()
                if partner_address in graph.partneraddress_to_channel
            ]

            result = partner_channels

        else:
            all_channels = list()
            for graph in self.raiden.token_to_channelgraph.values():
                all_channels.extend(graph.address_to_channel.values())

            result = all_channels

        return result
    def get_shortest_paths(self, source, target):
        """Compute all shortest paths in the graph.

        Returns:
            generator of lists: A generator of all paths between source and
            target.
        """
        if not isaddress(source) or not isaddress(target):
            raise ValueError('both source and target must be valid addresses')

        return networkx.all_shortest_paths(self.graph, source, target)
    def __init__(
            self,
            jsonrpc_client,
            discovery_address,
            startgas,
            gasprice,
            poll_timeout=DEFAULT_POLL_TIMEOUT):

        if not isaddress(discovery_address):
            raise ValueError('discovery_address must be a valid address')

        check_address_has_code(jsonrpc_client, discovery_address, 'Discovery')

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_abi(CONTRACT_ENDPOINT_REGISTRY),
            address_encoder(discovery_address),
        )

        self.address = discovery_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.startgas = startgas
        self.gasprice = gasprice
        self.poll_timeout = poll_timeout
        self.not_found_address = '0x' + '0' * 40
Exemple #13
0
    def send_async(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(pex(receiver_address)))

        if isinstance(message, Ack):
            raise ValueError('Do not use send for Ack messages or Errors')

        if len(message.encode()) > self.max_message_size:
            raise ValueError('message size exceeds the maximum {}'.format(self.max_message_size))

        messagedata = message.encode()

        # Adding the receiver address into the echohash to avoid collisions
        # among different receivers.
        # (Messages that are not unique per receiver
        # can result in hash colision, eg. Secret message sent to more than one
        # node, this hash collision has the undesired effect of aborting
        # message resubmission once a single node replied with an Ack)
        echohash = sha3(messagedata + receiver_address)

        # Don't add the same message twice into the queue
        if echohash not in self.echohash_asyncresult:
            ack_result = AsyncResult()
            self.echohash_asyncresult[echohash] = WaitAck(ack_result, receiver_address)

            # state changes are local to each channel/asset
            queue_name = getattr(message, 'asset', '')

            self._send(receiver_address, queue_name, message, messagedata, echohash)
        else:
            waitack = self.echohash_asyncresult[echohash]
            ack_result = waitack.ack_result

        return ack_result
    def get_channel_events(self, channel_address, from_block, to_block=None):
        if not isaddress(channel_address):
            raise InvalidAddress(
                'Expected binary address format for channel in get_channel_events'
            )
        returned_events = get_all_netting_channel_events(
            self.raiden.chain,
            channel_address,
            events=ALL_EVENTS,
            from_block=from_block,
            to_block=to_block,
        )
        raiden_events = self.raiden.transaction_log.get_events_in_block_range(
            from_block=from_block,
            to_block=to_block
        )
        # Here choose which raiden internal events we want to expose to the end user
        for event in raiden_events:
            is_user_transfer_event = isinstance(event.event_object, (
                EventTransferSentSuccess,
                EventTransferSentFailed,
                EventTransferReceivedSuccess
            ))

            if is_user_transfer_event:
                new_event = {
                    'block_number': event.block_number,
                    '_event_type': type(event.event_object).__name__,
                }
                new_event.update(event.event_object.__dict__)
                returned_events.append(new_event)

        return returned_events
    def add_token(self, token_address):
        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        transaction_hash = estimate_and_transact(
            self.proxy,
            'addToken',
            self.startgas,
            self.gasprice,
            token_address,
        )

        self.client.poll(unhexlify(transaction_hash), timeout=self.poll_timeout)
        receipt_or_none = check_transaction_threw(self.client, transaction_hash)
        if receipt_or_none:
            raise TransactionThrew('AddToken', receipt_or_none)

        manager_address = self.manager_address_by_token(token_address)

        if manager_address is None:
            log.error('Transaction failed and check_transaction_threw didnt detect it')
            raise RuntimeError('channelManagerByToken failed')

        if log.isEnabledFor(logging.INFO):
            log.info(
                'add_token called',
                token_address=pex(token_address),
                registry_address=pex(self.address),
                manager_address=pex(manager_address),
            )

        return manager_address
    def __init__(
            self,
            our_address,
            channelmanager_address,
            token_address,
            edge_list,
            channels_details):

        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        graph = make_graph(edge_list)
        self.address_to_channel = dict()
        self.graph = graph
        self.our_address = our_address
        self.partneraddress_to_channel = dict()
        self.token_address = token_address
        self.channelmanager_address = channelmanager_address

        for details in channels_details:
            try:
                self.add_channel(details)
            except ValueError as e:
                log.warn(
                    'Error at registering opened channel contract. Perhaps contract is invalid?',
                    error=str(e),
                    channel_address=pex(details.channel_address)
                )
Exemple #17
0
    def send_ping(self, receiver_address):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(pex(receiver_address)))

        nonce = self._ping_nonces[receiver_address]
        self._ping_nonces[receiver_address] += 1

        message = Ping(nonce)
        self.raiden.sign(message)

        if log.isEnabledFor(logging.INFO):
            log.info(
                'SENDING PING %s > %s',
                pex(self.raiden.address),
                pex(receiver_address)
            )

        message_data = message.encode()
        echohash = sha3(message_data + receiver_address)
        async_result = AsyncResult()
        if echohash not in self.echohash_asyncresult:
            self.echohash_asyncresult[echohash] = WaitAck(async_result, receiver_address)
        # Just like ACK, a PING message is sent directly. No need for queuing
        self.transport.send(
            self.raiden,
            self.discovery.get(receiver_address),
            message_data
        )
        return async_result
Exemple #18
0
    def __init__(self, raiden, asset_address, channel_manager_address, channel_graph):
        """
        Args:
            raiden (RaidenService): a node's service
            asset_address (bin): the asset address managed by this instance
            channel_manager_address (bin): The channel manager address.
            channelgraph (networkx.Graph): a graph representing the raiden network
        """
        if not isaddress(asset_address):
            raise ValueError("asset_address must be a valid address")

        self.partneraddress_channel = dict()  #: maps the partner address to the channel instance
        self.address_channel = dict()  #: maps the channel address to the channel instance

        # This is a map from a hashlock to a list of channels, the same
        # hashlock can be used in more than one AssetManager (for exchanges), a
        # channel should be removed from this list only when the lock is
        # released/withdrawed but not when the secret is registered.
        self.hashlock_channel = defaultdict(list)  #: channels waiting on the conditional lock

        self.asset_address = asset_address
        self.channel_manager_address = channel_manager_address
        self.channelgraph = channel_graph
        self.raiden = raiden

        transfermanager = TransferManager(self)
        self.transfermanager = transfermanager
    def __init__(
            self,
            jsonrpc_client,
            registry_address,
            startgas,
            gasprice,
            poll_timeout=DEFAULT_POLL_TIMEOUT):
        # pylint: disable=too-many-arguments

        if not isaddress(registry_address):
            raise ValueError('registry_address must be a valid address')

        check_address_has_code(jsonrpc_client, registry_address, 'Registry')

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_abi(CONTRACT_REGISTRY),
            address_encoder(registry_address),
        )

        self.address = registry_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.startgas = startgas
        self.gasprice = gasprice
        self.poll_timeout = poll_timeout

        self.address_to_channelmanager = dict()
        self.token_to_channelmanager = dict()
    def manager_by_token(self, token_address):
        """ Find the channel manager for `token_address` and return a proxy to
        interact with it.

        If the token is not already registered it raises `EthNodeCommunicationError`,
        since we try to instantiate a Channel manager with an empty address.
        """
        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        if token_address not in self.token_to_channelmanager:
            check_address_has_code(self.client, token_address)  # check that the token exists
            manager_address = self.manager_address_by_token(token_address)

            if manager_address is None:
                raise NoTokenManager(
                    'Manager for token 0x{} does not exist'.format(hexlify(token_address))
                )

            manager = ChannelManager(
                self.client,
                manager_address,
                self.startgas,
                self.gasprice,
                self.poll_timeout,
            )

            self.token_to_channelmanager[token_address] = manager
            self.address_to_channelmanager[manager_address] = manager

        return self.token_to_channelmanager[token_address]
Exemple #21
0
    def new_netting_channel(self, peer1, peer2, settle_timeout):
        """ Creates a new netting contract between peer1 and peer2.

        Raises:
            ValueError: If peer1 or peer2 is not a valid address.
        """
        if not isaddress(peer1):
            raise ValueError('The pee1 must be a valid address')

        if not isaddress(peer2):
            raise ValueError('The peer2 must be a valid address')

        if peer1 == peer2:
            raise ValueError('Cannot open a channel with itself')

        pair = tuple(sorted((peer1, peer2)))
        if pair in self.pair_channel:
            raise ValueError('({}, {}) already have a channel'.format(
                encode_hex(peer1),
                encode_hex(peer2)
            ))

        channel = NettingChannelMock(
            self.asset_address(),
            peer1,
            peer2,
            settle_timeout,
        )
        self.pair_channel[pair] = channel
        self.participant_channels[peer1].append(channel)
        self.participant_channels[peer2].append(channel)

        BlockChainServiceMock.address_contract[channel.address] = channel

        data = {
            '_event_type': 'ChannelNew',
            'netting_channel': channel.address,
            'participant1': peer1,
            'participant2': peer2,
            'settle_timeout': settle_timeout,
        }
        event = ethereum_event(CHANNELNEW_EVENTID, CHANNELNEW_EVENT, data, self.address)

        for filter_ in BlockChainServiceMock.filters[self.address]:
            filter_.event(event)

        return channel.address
 def connection_manager_for_token(self, token_address):
     if not isaddress(token_address):
         raise InvalidAddress('token address is not valid.')
     if token_address in self.tokens_to_connectionmanagers.keys():
         manager = self.tokens_to_connectionmanagers[token_address]
     else:
         raise InvalidAddress('token is not registered.')
     return manager
    def get_channel(self, channel_address):
        if not isaddress(channel_address):
            raise InvalidAddress('Expected binary address format for channel in get_channel')

        channel_list = self.get_channel_list()
        for channel in channel_list:
            if channel.channel_address == channel_address:
                return channel

        raise ChannelNotFound()
Exemple #24
0
    def new_netting_channel(self, peer1, peer2, settle_timeout):
        if not isaddress(peer1):
            raise ValueError('The pee1 must be a valid address')

        if not isaddress(peer2):
            raise ValueError('The peer2 must be a valid address')

        if privatekey_to_address(self.client.privkey) == peer1:
            other = peer2
        else:
            other = peer1

        transaction_hash = self.proxy.newChannel.transact(
            other,
            settle_timeout,
            startgas=self.startgas,
            gasprice=self.gasprice,
        )
        self.client.poll(transaction_hash.decode('hex'), timeout=self.poll_timeout)

        # TODO: raise if the transaction failed because there is an existing
        # channel in place

        netting_channel_address_encoded = self.proxy.getChannelWith.call(
            other,
            startgas=self.startgas,
        )

        if not netting_channel_address_encoded:
            log.error('netting_channel_address failed', peer1=pex(peer1), peer2=pex(peer2))
            raise RuntimeError('netting_channel_address failed')

        netting_channel_address_bin = address_decoder(netting_channel_address_encoded)

        log.info(
            'new_netting_channel called',
            peer1=pex(peer1),
            peer2=pex(peer2),
            netting_channel=pex(netting_channel_address_bin),
        )

        return netting_channel_address_bin
    def maybe_send_ack(self, receiver_address, ack_message):
        """ Send ack_message to receiver_address if the transport is running. """
        if not isaddress(receiver_address):
            raise InvalidAddress('Invalid address {}'.format(pex(receiver_address)))

        if not isinstance(ack_message, Ack):
            raise ValueError('Use maybe_send_ack only for Ack messages')

        messagedata = ack_message.encode()
        self.receivedhashes_to_acks[ack_message.echo] = (receiver_address, messagedata)
        self._maybe_send_ack(*self.receivedhashes_to_acks[ack_message.echo])
Exemple #26
0
    def send(self, receiver_address, msg):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(pex(receiver_address)))

        if isinstance(msg, (Ack, BaseError)):
            raise ValueError('Do not use send for Ack messages or Erorrs')

        if len(msg.encode()) > self.max_message_size:
            raise ValueError('message size excedes the maximum {}'.format(self.max_message_size))

        return gevent.spawn(self._repeat_until_ack, receiver_address, msg)
    def open(
            self,
            token_address,
            partner_address,
            settle_timeout=None,
            reveal_timeout=None):
        """ Open a channel with the peer at `partner_address`
        with the given `token_address`.
        """
        if reveal_timeout is None:
            reveal_timeout = self.raiden.config['reveal_timeout']

        if settle_timeout is None:
            settle_timeout = self.raiden.config['settle_timeout']

        if settle_timeout <= reveal_timeout:
            raise InvalidSettleTimeout(
                'reveal_timeout can not be larger-or-equal to settle_timeout'
            )

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

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

        channel_manager = self.raiden.default_registry.manager_by_token(token_address)
        assert token_address in self.raiden.token_to_channelgraph

        netcontract_address = channel_manager.new_netting_channel(
            partner_address,
            settle_timeout,
        )
        while netcontract_address not in self.raiden.chain.address_to_nettingchannel:
            gevent.sleep(self.raiden.alarm.wait_time)

        graph = self.raiden.token_to_channelgraph[token_address]
        while partner_address not in graph.partneraddress_to_channel:
            gevent.sleep(self.raiden.alarm.wait_time)
        channel = graph.partneraddress_to_channel[partner_address]
        return channel
Exemple #28
0
    def send(self, recipient, message):
        """ Send `message` to `recipient` using the raiden protocol.

        The protocol will take care of resending the message on a given
        interval until an Acknowledgment is received or a given number of
        tries.
        """

        if not isaddress(recipient):
            raise ValueError('recipient is not a valid address.')

        self.protocol.send(recipient, message)
Exemple #29
0
    def transfer(self, asset_address, amount, target, callback=None):
        if not isinstance(amount, (int, long)):
            raise InvalidAmount('Amount not a number')

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

        asset_address = safe_address_decode(asset_address)
        target = safe_address_decode(target)

        if not isaddress(asset_address) or asset_address not in self.assets:
            raise InvalidAddress('asset address is not valid.')

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

        if not self.raiden.has_path(asset_address, target):
            raise NoPathError('No path to address found')

        transfer_manager = self.raiden.assetmanagers[asset_address].transfermanager
        transfer_manager.transfer(amount, target, callback=callback)
Exemple #30
0
    def new_netting_contract(self, asset_address, peer1, peer2):
        """ Creates a new netting contract between peer1 and peer2.

        Raises:
            ValueError: If peer1 or peer2 is not a valid address.
        """
        if not isaddress(peer1):
            raise ValueError('The pee1 must be a valid address')

        if not isaddress(peer2):
            raise ValueError('The peer2 must be a valid address')

        netcontract_address = bytes(sha3(peer1 + peer2)[:20])
        hash_channel = self.asset_hashchannel[asset_address]

        if netcontract_address in hash_channel:
            raise ValueError('netting contract already exists')

        channel = NettingChannelContract(asset_address, netcontract_address, peer1, peer2)
        hash_channel[netcontract_address] = channel
        return netcontract_address
Exemple #31
0
    def register_token(self, token_address):
        """ Will register the token at `token_address` with raiden. If it's already
        registered, will throw an exception.
        """

        if not isaddress(token_address):
            raise InvalidAddress('token_address must be a valid address in binary')

        try:
            self.raiden.default_registry.manager_by_token(token_address)
        except NoTokenManager:
            channel_manager_address = self.raiden.default_registry.add_token(token_address)
            self.raiden.register_channel_manager(channel_manager_address)
            return channel_manager_address

        raise ValueError('Token already registered')
Exemple #32
0
    def __init__(self, raiden, asset_address, channel_graph):
        """
        Args:
            raiden (RaidenService): a node's service
            asset_address (address): the asset address managed by this instance
            channelgraph (networkx.Graph): a graph representing the raiden network
        """
        if not isaddress(asset_address):
            raise ValueError('asset_address must be a valid address')

        self.asset_address = asset_address
        self.channelgraph = channel_graph

        transfermanager = TransferManager(self, raiden)
        self.channels = dict()  #: mapping form partner_address -> channel object
        self.transfermanager = transfermanager  #: handle's raiden transfers
Exemple #33
0
    def __init__(self, our_address, channelmanager_address, token_address,
                 edge_list, channels_details, block_number):

        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        graph = make_graph(edge_list)
        self.address_channel = dict()
        self.graph = graph
        self.our_address = our_address
        self.partneraddress_channel = dict()
        self.token_address = token_address
        self.channelmanager_address = channelmanager_address

        for details in channels_details:
            self.add_channel(details, block_number)
    def netting_channel(self, netting_channel_address):
        """ Return a proxy to interact with a NettingChannelContract. """
        if not isaddress(netting_channel_address):
            raise ValueError('netting_channel_address must be a valid address')

        if netting_channel_address not in self.address_to_nettingchannel:
            channel = NettingChannel(
                self.client,
                netting_channel_address,
                self.startgas,
                self.gasprice,
                self.poll_timeout,
            )
            self.address_to_nettingchannel[netting_channel_address] = channel

        return self.address_to_nettingchannel[netting_channel_address]
Exemple #35
0
    def send_async(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(
                pex(receiver_address)))

        if isinstance(message, (Processed, Ping)):
            raise ValueError(
                'Do not use send for `Processed` or `Ping` messages')

        messagedata = message.encode()
        if len(messagedata) > UDP_MAX_MESSAGE_SIZE:
            raise ValueError('message size exceeds the maximum {}'.format(
                UDP_MAX_MESSAGE_SIZE))

        message_id = messageid_from_data(messagedata, receiver_address)

        # All messages must be ordered, but only on a per channel basis.
        token_address = getattr(message, 'token', b'')

        # Ignore duplicated messages
        if message_id not in self.messageids_to_states:
            async_result = AsyncResult()
            self.messageids_to_states[message_id] = SentMessageState(
                async_result,
                receiver_address,
            )

            queue = self.get_channel_queue(
                receiver_address,
                token_address,
            )

            if log.isEnabledFor(logging.DEBUG):
                log.debug(
                    'SENDING MESSAGE',
                    to=pex(receiver_address),
                    node=pex(self.raiden.address),
                    message=message,
                    message_id=message_id,
                )

            queue.put(messagedata)
        else:
            wait_processed = self.messageids_to_states[message_id]
            async_result = wait_processed.async_result

        return async_result
Exemple #36
0
    def register(self, node_address, host, port):
        if node_address != self.node_address:
            raise ValueError('You can only register your own endpoint.')

        if not isaddress(node_address):
            raise ValueError('node_address must be a valid address')

        try:
            socket.inet_pton(socket.AF_INET, host)
        except OSError:
            raise ValueError('invalid ip address provided: {}'.format(host))

        if not isinstance(port, (int, long)):
            raise ValueError('port must be a valid number')

        endpoint = host_port_to_endpoint(host, port)
        self.discovery_proxy.register_endpoint(node_address, endpoint)
Exemple #37
0
    def new_channel_manager_contract(self, asset_address):
        """ The equivalent of instatiating a new `ChannelManagerContract`
        contract that will manage channels for a given asset in the blockchain.

        Raises:
            ValueError: If asset_address is not a valid address or is already registered.
        """
        if not isaddress(asset_address):
            raise ValueError('The asset must be a valid address')

        if asset_address in self.asset_hashchannel:
            raise ValueError('This asset already has a registered contract')

        manager_address = make_address()
        self.asset_hashchannel[asset_address] = dict()
        self.asset_address[asset_address] = manager_address
        return manager_address
    def connect(
            self,
            token_address,
            funds,
            initial_channel_target,
            joinable_funds_target):

        if not isaddress(token_address):
            raise InvalidAddress('not an address %s' % pex(token_address))

        funding = int((funds * joinable_funds_target) / initial_channel_target)
        for i in range(0, initial_channel_target):
            channel = self.make_channel(token_address=token_address, balance=funding)
            self.channels.append(channel)

        connection_manager = ConnectionManagerMock(token_address, funds)
        self.connection_managers.append(connection_manager)
Exemple #39
0
    def send_and_wait(self, recipient, message, timeout):
        """ Send `message` to `recipient` and wait for the response or `timeout`.

        Args:
            recipient (address): The address of the node that will receive the
                message.
            message: The transfer message.
            timeout (float): How long should we wait for a response from `recipient`.

        Returns:
            None: If the wait timed out
            object: The result from the event
        """
        if not isaddress(recipient):
            raise ValueError('recipient is not a valid address.')

        self.protocol.send_and_wait(recipient, message, timeout)
Exemple #40
0
    def manager_address_if_token_registered(self, token_address):
        """
        If the token is registered then, return the channel manager address.
        Also make sure that the channel manager is registered with the node.

        Returns None otherwise.
        """
        if not isaddress(token_address):
            raise InvalidAddress('token_address must be a valid address in binary')

        try:
            manager = self.raiden.default_registry.manager_by_token(token_address)
            if not self.raiden.channel_manager_is_registered(manager.address):
                self.raiden.register_channel_manager(manager.address)
            return manager.address
        except (EthNodeCommunicationError, TransactionFailed, NoTokenManager):
            return None
Exemple #41
0
    def maybe_send_processed(self, receiver_address, processed_message):
        """ Send processed_message to receiver_address if the transport is running. """
        if not isaddress(receiver_address):
            raise InvalidAddress('Invalid address {}'.format(
                pex(receiver_address)))

        if not isinstance(processed_message, Processed):
            raise ValueError(
                'Use _maybe_send_processed only for `Processed` messages')

        messagedata = processed_message.encode()

        self.receivedhashes_to_processedmessages[processed_message.echo] = (
            receiver_address, messagedata)

        self._maybe_send_processed(
            *self.receivedhashes_to_processedmessages[processed_message.echo])
Exemple #42
0
    def token_network_leave(self,
                            registry_address,
                            token_address,
                            only_receiving=True):
        """Close all channels and wait for settlement."""
        if not isaddress(token_address):
            raise InvalidAddress(
                'token_address must be a valid address in binary')

        if token_address not in self.get_tokens_list(registry_address):
            raise UnknownTokenAddress('token_address unknown')

        connection_manager = self.raiden.connection_manager_for_token(
            registry_address,
            token_address,
        )

        return connection_manager.leave(only_receiving)
Exemple #43
0
    def manager(self, manager_address):
        """ Return a proxy to interact with a ChannelManagerContract. """
        if not isaddress(manager_address):
            raise ValueError('manager_address must be a valid address')

        if manager_address not in self.address_to_channelmanager:
            manager = ChannelManager(
                self.client,
                manager_address,
                poll_timeout=self.poll_timeout,
            )

            token_address = manager.token_address()

            self.token_to_channelmanager[token_address] = manager
            self.address_to_channelmanager[manager_address] = manager

        return self.address_to_channelmanager[manager_address]
Exemple #44
0
    def send_ack(self, receiver_address, msg):
        assert isinstance(msg, (Ack, BaseError))
        assert isaddress(receiver_address)

        host_port = self.discovery.get(receiver_address)
        data = msg.encode()
        msghash = sha3(data)

        log.info('SENDING ACK {} > {} : [{}] [echo={}] {}'.format(
            pex(self.raiden.address),
            pex(receiver_address),
            pex(msghash),
            pex(msg.echo),
            msg,
        ))

        self.transport.send(self.raiden, host_port, msg.encode())
        self.sent_acks[msg.echo] = (receiver_address, msg)
Exemple #45
0
    def get_token_network_events(self, token_address, from_block, to_block):
        if not isaddress(token_address):
            raise InvalidAddress(
                'Expected binary address format for token in get_token_network_events'
            )

        try:
            graph = self.raiden.token_to_channelgraph[token_address]

            return get_all_channel_manager_events(
                self.raiden.chain,
                graph.channelmanager_address,
                events=ALL_EVENTS,
                from_block=from_block,
                to_block=to_block,
            )
        except KeyError:
            raise UnknownTokenAddress('The token address is not registered.')
Exemple #46
0
    def send_async(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(pex(receiver_address)))

        if isinstance(message, Ack):
            raise ValueError('Do not use send for Ack messages or Errors')

        if len(message.encode()) > self.max_message_size:
            raise ValueError('message size exceeds the maximum {}'.format(self.max_message_size))

        messagedata = message.encode()
        messagehash = sha3(messagedata + receiver_address)
        ack_result = AsyncResult()
        self.msghash_asyncresult[messagehash] = ack_result

        self._send(receiver_address, message, messagedata, messagehash)

        return ack_result
Exemple #47
0
    def __init__(self,
                 jsonrpc_client,
                 token_address,
                 poll_timeout=DEFAULT_POLL_TIMEOUT):

        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        check_address_has_code(jsonrpc_client, token_address, 'Token')

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_HUMAN_STANDARD_TOKEN),
            address_encoder(token_address),
        )

        self.address = token_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.poll_timeout = poll_timeout
Exemple #48
0
    def connection_manager_for_token(self, registry_address, token_address):
        if not isaddress(token_address):
            raise InvalidAddress('token address is not valid.')

        known_token_networks = views.get_token_network_addresses_for(
            self.wal.state_manager.current_state,
            registry_address,
        )

        if token_address not in known_token_networks:
            raise InvalidAddress('token is not registered.')

        manager = self.tokens_to_connectionmanagers.get(token_address)

        if manager is None:
            manager = ConnectionManager(self, registry_address, token_address)
            self.tokens_to_connectionmanagers[token_address] = manager

        return manager
    def token_network(self, token_network_address: typing.TokenNetworkAddress):
        """ Return a proxy to interact with a TokenNetwork. """
        if not isaddress(token_network_address):
            raise InvalidAddress(
                'Expected binary address format for token network')

        if token_network_address not in self.address_to_tokennetwork:
            token_network = TokenNetwork(
                self.client,
                token_network_address,
                self.poll_timeout,
            )

            token_address = token_network.token_address()

            self.token_to_tokennetwork[token_address] = token_network
            self.address_to_tokennetwork[token_network_address] = token_network

        return self.address_to_tokennetwork[token_network_address]
Exemple #50
0
    def send_async(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(
                pex(receiver_address)))

        if isinstance(message, (Ack, Ping)):
            raise ValueError('Do not use send for Ack or Ping messages')

        # Messages that are not unique per receiver can result in hash
        # collision, e.g. Secret messages. The hash collision has the undesired
        # effect of aborting message resubmission once /one/ of the nodes
        # replied with an Ack, adding the receiver address into the echohash to
        # avoid these collisions.
        messagedata = message.encode()
        echohash = sha3(messagedata + receiver_address)

        if len(messagedata) > UDP_MAX_MESSAGE_SIZE:
            raise ValueError('message size exceeds the maximum {}'.format(
                UDP_MAX_MESSAGE_SIZE))

        # All messages must be ordered, but only on a per channel basis.
        token_address = getattr(message, 'token', '')

        # Ignore duplicated messages
        if echohash not in self.senthashes_to_states:
            async_result = AsyncResult()
            self.senthashes_to_states[echohash] = SentMessageState(
                async_result,
                receiver_address,
            )

            queue = self.get_channel_queue(
                receiver_address,
                token_address,
            )

            queue.put(messagedata)
        else:
            waitack = self.senthashes_to_states[echohash]
            async_result = waitack.async_result

        return async_result
Exemple #51
0
    def send_ack(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(pex(receiver_address)))

        if not isinstance(message, Ack):
            raise ValueError('Use send_Ack only for Ack messages or Erorrs')

        if log.isEnabledFor(logging.INFO):
            log.info(
                'SENDING ACK %s > %s %s',
                pex(self.raiden.address),
                pex(receiver_address),
                message,
            )

        messagedata = message.encode()
        host_port = self.get_host_port(receiver_address)
        self.receivedhashes_to_acks[message.echo] = (host_port, messagedata)

        self._send_ack(*self.receivedhashes_to_acks[message.echo])
Exemple #52
0
    def __init__(self,
                 jsonrpc_client,
                 discovery_address,
                 poll_timeout=DEFAULT_POLL_TIMEOUT):

        if not isaddress(discovery_address):
            raise ValueError('discovery_address must be a valid address')

        check_address_has_code(jsonrpc_client, discovery_address, 'Discovery')

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_abi(CONTRACT_ENDPOINT_REGISTRY),
            address_encoder(discovery_address),
        )

        self.address = discovery_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.poll_timeout = poll_timeout
        self.not_found_address = NULL_ADDRESS
Exemple #53
0
    def send_async(
        self,
        recipient: typing.Address,
        queue_name: bytes,
        message: 'Message',
    ):
        """ Send a new ordered message to recipient.

        Messages that use the same `queue_name` are ordered.
        """

        if not isaddress(recipient):
            raise ValueError('Invalid address {}'.format(pex(recipient)))

        # These are not protocol messages, but transport specific messages
        if isinstance(message, (Delivered, Ping, Pong)):
            raise ValueError('Do not use send for {} messages'.format(
                message.__class__.__name__))

        messagedata = message.encode()
        if len(messagedata) > UDP_MAX_MESSAGE_SIZE:
            raise ValueError('message size exceeds the maximum {}'.format(
                UDP_MAX_MESSAGE_SIZE))

        # message identifiers must be unique
        message_id = message.message_identifier

        # ignore duplicates
        if message_id not in self.messageids_to_asyncresults:
            self.messageids_to_asyncresults[message_id] = AsyncResult()

            queue = self.get_queue_for(recipient, queue_name)
            queue.put((messagedata, message_id))

            log.debug(
                'MESSAGE QUEUED',
                node=pex(self.raiden.address),
                queue_name=queue_name,
                to=pex(recipient),
                message=message,
            )
Exemple #54
0
    def __init__(self,
                 jsonrpc_client,
                 manager_address,
                 poll_timeout=DEFAULT_POLL_TIMEOUT):
        # pylint: disable=too-many-arguments

        if not isaddress(manager_address):
            raise ValueError('manager_address must be a valid address')

        check_address_has_code(jsonrpc_client, manager_address,
                               'Channel Manager')

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_abi(CONTRACT_CHANNEL_MANAGER),
            address_encoder(manager_address),
        )

        self.address = manager_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.poll_timeout = poll_timeout
Exemple #55
0
    def send_ack(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(
                pex(receiver_address)))

        if not isinstance(message, (Ack, BaseError)):
            raise ValueError('Use send_Ack only for Ack messages or Erorrs')

        host_port = self.discovery.get(receiver_address)
        data = message.encode()
        msghash = sha3(data)

        log.info('SENDING ACK {} > {} : [{}] [echo={}] {}'.format(
            pex(self.raiden.address),
            pex(receiver_address),
            pex(msghash),
            pex(message.echo),
            message,
        ))

        self.transport.send(self.raiden, host_port, data)
        self.sent_acks[message.echo] = (receiver_address, message)
Exemple #56
0
    def __init__(self, raiden, asset_address, channel_manager_address, channel_graph):
        """
        Args:
            raiden (RaidenService): a node's service
            asset_address (address): the asset address managed by this instance
            channelgraph (networkx.Graph): a graph representing the raiden network
        """
        if not isaddress(asset_address):
            raise ValueError('asset_address must be a valid address')

        self.partneraddress_channel = dict()  #: maps the partner address to the channel instance
        self.address_channel = dict()  #: maps the channel address to the channel instance
        self.hashlock_channel = defaultdict(list)
        ''' A list of channels that are waiting on the conditional lock. '''

        self.asset_address = asset_address
        self.channel_manager_address = channel_manager_address
        self.channelgraph = channel_graph
        self.raiden = raiden

        transfermanager = TransferManager(self)
        self.transfermanager = transfermanager
Exemple #57
0
    def connect_token_network(self,
                              token_address,
                              funds,
                              initial_channel_target=3,
                              joinable_funds_target=.4):
        """Instruct the ConnectionManager to establish and maintain a connection to the token
        network.

        If the `token_address` is not already part of the raiden network, this will also register
        the token.

        Args:
            token_address (bin): the ERC20 token network to connect to.
            funds (int): the amount of funds that can be used by the ConnectionMananger.
            initial_channel_target (int): number of channels to open proactively.
            joinable_funds_target (float): fraction of the funds that will be used to join
                channels opened by other participants.
        """
        if not isaddress(token_address):
            raise InvalidAddress(
                'token_address must be a valid address in binary')

        try:
            connection_manager = self.raiden.connection_manager_for_token(
                token_address)
        except InvalidAddress:
            # token is not yet registered
            self.raiden.default_registry.add_token(token_address)

            # wait for registration
            while token_address not in self.raiden.tokens_to_connectionmanagers:
                gevent.sleep(self.raiden.alarm.wait_time)
            connection_manager = self.raiden.connection_manager_for_token(
                token_address)

        connection_manager.connect(
            funds,
            initial_channel_target=initial_channel_target,
            joinable_funds_target=joinable_funds_target)
Exemple #58
0
    def __init__(self, our_address, channelmanager_address, token_address,
                 edge_list, channels_details):

        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        graph = make_graph(edge_list)
        self.address_to_channel = dict()
        self.graph = graph
        self.our_address = our_address
        self.partneraddress_to_channel = dict()
        self.token_address = token_address
        self.channelmanager_address = channelmanager_address

        for details in channels_details:
            try:
                self.add_channel(details)
            except ValueError as e:
                log.warn(
                    'Error at registering opened channel contract. Perhaps contract is invalid?',
                    error=str(e),
                    channel_address=pex(details.channel_address))
Exemple #59
0
    def send_ack(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(
                pex(receiver_address)))

        if not isinstance(message, Ack):
            raise ValueError('Use send_Ack only for Ack messages or Erorrs')

        host_port = self.discovery.get(receiver_address)
        messagedata = message.encode()
        messagehash = sha3(messagedata)

        log.info('SENDING ACK {} > {} : [{}] [echo={}] {}'.format(
            pex(self.raiden.address),
            pex(receiver_address),
            pex(messagehash),
            pex(message.echo),
            message,
        ))

        self.msghash_acks[message.echo] = (host_port, messagedata, messagehash)
        self._send_ack(*self.msghash_acks[message.echo])
Exemple #60
0
    def send_async(self, receiver_address, message):
        if not isaddress(receiver_address):
            raise ValueError('Invalid address {}'.format(
                pex(receiver_address)))

        if isinstance(message, Ack):
            raise ValueError('Do not use send for Ack messages or Errors')

        if len(message.encode()) > self.max_message_size:
            raise ValueError('message size exceeds the maximum {}'.format(
                self.max_message_size))

        messagedata = message.encode()

        # Adding the receiver address into the echohash to avoid collisions
        # among different receivers.
        # (Messages that are not unique per receiver
        # can result in hash colision, eg. Secret message sent to more than one
        # node, this hash collision has the undesired effect of aborting
        # message resubmission once a single node replied with an Ack)
        echohash = sha3(messagedata + receiver_address)

        # Don't add the same message twice into the queue
        if echohash not in self.echohash_asyncresult:
            ack_result = AsyncResult()
            self.echohash_asyncresult[echohash] = WaitAck(
                ack_result, receiver_address)

            # state changes are local to each channel/token
            queue_name = getattr(message, 'token', '')

            self._send(receiver_address, queue_name, message, messagedata,
                       echohash)
        else:
            waitack = self.echohash_asyncresult[echohash]
            ack_result = waitack.ack_result

        return ack_result