Пример #1
0
def geth_generate_poa_genesis(
        genesis_path: str,
        accounts_addresses: typing.List[str],
        seal_address: str,
        random_marker,
):
    """Writes a bare genesis to `genesis_path`.

    Args:
        genesis_path: the path in which the genesis block is written.
        accounts_addresses: iterable list of privatekeys whose
            corresponding accounts will have a premined balance available.
        seal_address: Address of the ethereum account that can seal
            blocks in the PoA chain
    """

    alloc = {
        to_normalized_address(address): {
            'balance': DEFAULT_BALANCE_BIN,
        }
        for address in accounts_addresses
    }
    genesis = GENESIS_STUB.copy()
    genesis['alloc'].update(alloc)

    genesis['config']['clique'] = {'period': 1, 'epoch': 30000}

    genesis['extraData'] = geth_clique_extradata(
        random_marker,
        to_normalized_address(seal_address)[2:],
    )

    with open(genesis_path, 'w') as handler:
        json.dump(genesis, handler)
Пример #2
0
    def request_blocking(self, method, params):
        if method == 'eth_sendTransaction':
            base_transaction = params[0]
            # create a fully signed transaction and send through the
            # `eth_sendRawTransaction` endpoint instead.
            full_transaction = self.construct_full_transaction(base_transaction)
            raw_transaction_bytes = self.sign_and_serialize_transaction(
                full_transaction,
            )
            raw_transaction_bytes_as_hex = encode_hex(raw_transaction_bytes)
            return self.request_blocking(
                'eth_sendRawTransaction', [raw_transaction_bytes_as_hex],
            )

        result = super(BaseSendRawTransactionMixin, self).request_blocking(
            method, params,
        )
        if method in self.TXN_SENDING_METHODS:
            if method == 'eth_sendRawTransaction':
                txn = rlp.decode(decode_hex(params[0]), Transaction)
                self._known_transactions[to_normalized_address(txn.sender)].add(result)
                self._known_nonces[to_normalized_address(txn.sender)].add(txn.nonce)
            else:
                txn = params[0]
                self._known_transactions[to_normalized_address(txn['from'])].add(result)
                if 'nonce' in txn:
                    self._known_nonces[to_normalized_address(txn['from'])].add(
                        to_decimal(txn['nonce'])
                    )
        return result
Пример #3
0
def verify_state_db(expected_state, state_db):
    diff = diff_state_db(expected_state, state_db)
    if diff:
        error_messages = []
        for account, field, actual_value, expected_value in diff:
            if field == 'balance':
                error_messages.append(
                    "{0}({1}) | Actual: {2} | Expected: {3} | Delta: {4}".format(
                        to_normalized_address(account),
                        'balance',
                        actual_value,
                        expected_value,
                        expected_value - actual_value,
                    )
                )
            else:
                error_messages.append(
                    "{0}({1}) | Actual: {2} | Expected: {3}".format(
                        to_normalized_address(account),
                        field,
                        actual_value,
                        expected_value,
                    )
                )
        raise AssertionError(
            "State DB did not match expected state on {0} values:\n"
            "{1}".format(
                len(error_messages),
                "\n - ".join(error_messages),
            )
        )
Пример #4
0
    def _get_room_for_address(
        self,
        address: Address,
        allow_missing_peers=False,
    ) -> Optional[Room]:
        if not self._running:
            return
        address_hex = to_normalized_address(address)
        assert address and address in self._address_to_userids,\
            f'address not health checked: me: {self._client.user_id}, peer: {address_hex}'
        room_id = self._get_room_id_for_address(address)
        if room_id:
            return self._client.rooms[room_id]

        # The addresses are being sorted to ensure the same channel is used for both directions
        # of communication.
        # e.g.: raiden_ropsten_0xaaaa_0xbbbb
        address_pair = sorted([
            to_normalized_address(address)
            for address in [address, self._raiden_service.address]
        ])
        room_name = self._make_room_alias(*address_pair)

        # no room with expected name => create one and invite peer
        candidates = [
            self._get_user(user)
            for user in self._client.search_user_directory(address_hex)
        ]

        # filter candidates
        peers = [
            user
            for user in candidates
            if self._validate_userid_signature(user) == address
        ]
        if not peers and not allow_missing_peers:
            self.log.error('No valid peer found', peer_address=address_hex)
            return

        self._address_to_userids[address].update({user.user_id for user in peers})

        room = self._get_unlisted_room(room_name, invitees=peers)
        self._set_room_id_for_address(address, room.room_id)

        for user in peers:
            self._maybe_invite_user(user)

        if not room.listeners:
            room.add_listener(self._handle_message, 'm.room.message')

        self.log.info(
            'CHANNEL ROOM',
            peer_address=to_normalized_address(address),
            room=room,
        )
        return room
Пример #5
0
 def sign_and_serialize_transaction(self, transaction):
     txn_from = to_normalized_address(transaction['from'])
     if txn_from not in self.keys:
         raise KeyError("No signing key registered for from address: {0}".format(txn_from))
     transaction = Transaction(
         nonce=to_decimal(transaction['nonce']),
         gasprice=to_decimal(transaction['gasPrice']),
         startgas=to_decimal(transaction['gas']),
         to=transaction['to'],
         value=to_decimal(transaction['value']),
         data=decode_hex(transaction['data']),
     )
     transaction.sign(self.keys[txn_from])
     assert to_normalized_address(transaction.sender) == txn_from
     return rlp.encode(transaction, Transaction)
Пример #6
0
 def to_dict(self):
     return {
         'type': self.__class__.__name__,
         'chain_id': self.chain_id,
         'nonce': self.nonce,
         'token_network_address': to_normalized_address(self.token_network_address),
         'message_identifier': self.message_identifier,
         'channel_identifier': self.channel_identifier,
         'secrethash': encode_hex(self.secrethash),
         'transferred_amount': self.transferred_amount,
         'locked_amount': self.locked_amount,
         'recipient': to_normalized_address(self.recipient),
         'locksroot': encode_hex(self.locksroot),
         'signature': encode_hex(self.signature),
     }
Пример #7
0
    def __init__(
            self,
            jsonrpc_client,
            registry_address,
    ):
        if not is_binary_address(registry_address):
            raise InvalidAddress('Expected binary address format for token network registry')

        check_address_has_code(jsonrpc_client, registry_address, CONTRACT_TOKEN_NETWORK_REGISTRY)

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_TOKEN_NETWORK_REGISTRY),
            to_normalized_address(registry_address),
        )

        is_valid_version = compare_versions(
            proxy.contract.functions.contract_version().call(),
            EXPECTED_CONTRACTS_VERSION,
        )
        if not is_valid_version:
            raise ContractVersionMismatch('Incompatible ABI for TokenNetworkRegistry')

        self.address = registry_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(self.client.privkey)
Пример #8
0
    def __init__(
            self,
            jsonrpc_client,
            secret_registry_address,
    ):
        if not is_binary_address(secret_registry_address):
            raise InvalidAddress('Expected binary address format for secret registry')

        check_address_has_code(jsonrpc_client, secret_registry_address, CONTRACT_SECRET_REGISTRY)

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_SECRET_REGISTRY),
            to_normalized_address(secret_registry_address),
        )

        if not compare_versions(
            proxy.contract.functions.contract_version().call(),
            EXPECTED_CONTRACTS_VERSION,
        ):
            raise ContractVersionMismatch('Incompatible ABI for SecretRegistry')

        self.address = secret_registry_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(self.client.privkey)
        self.open_secret_transactions = dict()
Пример #9
0
    def __init__(
            self,
            jsonrpc_client,
            discovery_address,
            contract_manager: ContractManager,
    ):
        contract = jsonrpc_client.new_contract(
            contract_manager.get_contract_abi(CONTRACT_ENDPOINT_REGISTRY),
            to_normalized_address(discovery_address),
        )
        proxy = ContractProxy(jsonrpc_client, contract)

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

        check_address_has_code(jsonrpc_client, discovery_address, 'Discovery')

        compare_contract_versions(
            proxy=proxy,
            expected_version=contract_manager.contracts_version,
            contract_name=CONTRACT_ENDPOINT_REGISTRY,
            address=discovery_address,
        )

        self.address = discovery_address
        self.node_address = privatekey_to_address(jsonrpc_client.privkey)
        self.client = jsonrpc_client
        self.not_found_address = NULL_ADDRESS
        self.proxy = proxy
Пример #10
0
    def sign(self, key):
        """Sign this transaction with a private key.

        A potentially already existing signature would be overridden.
        """
        if not is_bitcoin_available() or not is_secp256k1_available():
            raise ImportError(
                "In order to sign transactions the "
                "`bitcoin` and `secp256k1` packages must be installed."
            )
        from bitcoin import privtopub
        from secp256k1 import PrivateKey

        if key in (0, b'', b'\x00' * 32, b'0' * 64):
            raise ValueError("Zero privkey cannot sign")

        rawhash = keccak(rlp.encode(self, UnsignedTransaction))

        if len(key) in {64, 66}:
            # we need a binary key
            key = decode_hex(key)

        pk = PrivateKey(key, raw=True)
        sig_bytes, rec_id = pk.ecdsa_recoverable_serialize(
            pk.ecdsa_sign_recoverable(rawhash, raw=True)
        )
        signature = sig_bytes + force_bytes(chr(rec_id))
        self.v = (ord(signature[64]) if is_string(signature[64]) else signature[64]) + 27
        self.r = decode_big_endian_int(signature[0:32])
        self.s = decode_big_endian_int(signature[32:64])

        self.sender = to_normalized_address(keccak(privtopub(key)[1:])[-20:])
        return self
Пример #11
0
    def __init__(
            self,
            jsonrpc_client,
            secret_registry_address,
            contract_manager: ContractManager,
    ):
        if not is_binary_address(secret_registry_address):
            raise InvalidAddress('Expected binary address format for secret registry')

        self.contract_manager = contract_manager
        check_address_has_code(jsonrpc_client, secret_registry_address, CONTRACT_SECRET_REGISTRY)

        proxy = jsonrpc_client.new_contract_proxy(
            self.contract_manager.get_contract_abi(CONTRACT_SECRET_REGISTRY),
            to_normalized_address(secret_registry_address),
        )

        compare_contract_versions(
            proxy=proxy,
            expected_version=contract_manager.contracts_version,
            contract_name=CONTRACT_SECRET_REGISTRY,
            address=secret_registry_address,
        )

        self.address = secret_registry_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(self.client.privkey)
        self.open_secret_transactions = dict()
def test_decode_address(address_bytes, padding_size, data_byte_size):
    stream_bytes = b'\x00' * padding_size + address_bytes
    if data_byte_size < 20:
        with pytest.raises(ValueError):
            AddressDecoder(
                data_byte_size=data_byte_size,
            )
        return
    else:
        decoder = AddressDecoder(
            data_byte_size=data_byte_size,
        )

    stream = ContextFramesBytesIO(stream_bytes)
    padding_bytes = stream_bytes[:data_byte_size][:-20]

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return
    elif is_non_empty_non_null_byte_string(padding_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return
    else:
        decoded_value = decoder(stream)

    actual_value = to_normalized_address(stream_bytes[:data_byte_size][-20:])

    assert decoded_value == actual_value
Пример #13
0
    def __init__(
            self,
            jsonrpc_client,
            discovery_address,
    ):
        contract = jsonrpc_client.new_contract(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_ENDPOINT_REGISTRY),
            to_normalized_address(discovery_address),
        )
        proxy = ContractProxy(jsonrpc_client, contract)

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

        check_address_has_code(jsonrpc_client, discovery_address, 'Discovery')

        is_valid_version = compare_versions(
            proxy.contract.functions.contract_version().call(),
            EXPECTED_CONTRACTS_VERSION,
        )
        if not is_valid_version:
            raise ContractVersionMismatch('Incompatible ABI for Discovery')

        self.address = discovery_address
        self.client = jsonrpc_client
        self.not_found_address = NULL_ADDRESS
        self.proxy = proxy
Пример #14
0
    def __init__(
            self,
            jsonrpc_client,
            registry_address: PaymentNetworkID,
            contract_manager: ContractManager,
    ):
        if not is_binary_address(registry_address):
            raise InvalidAddress('Expected binary address format for token network registry')

        check_address_has_code(
            client=jsonrpc_client,
            address=Address(registry_address),
            contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY,
        )

        self.contract_manager = contract_manager
        proxy = jsonrpc_client.new_contract_proxy(
            self.contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK_REGISTRY),
            to_normalized_address(registry_address),
        )

        compare_contract_versions(
            proxy=proxy,
            expected_version=contract_manager.contracts_version,
            contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY,
            address=Address(registry_address),
        )

        self.address = registry_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(self.client.privkey)
Пример #15
0
    def send_async(
        self,
        receiver_address: Address,
        queue_name: bytes,
        message: Message,
    ):
        if not self._running:
            return
        self.log.info(
            'SEND ASYNC',
            receiver_address=to_normalized_address(receiver_address),
            message=message,
            queue_name=queue_name,
        )
        if not is_binary_address(receiver_address):
            raise ValueError('Invalid address {}'.format(pex(receiver_address)))

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

        message_id = message.message_identifier
        async_result = AsyncResult()
        if isinstance(message, Processed):
            async_result.set(True)  # processed messages shouldn't get a Delivered reply
            self._send_immediate(receiver_address, json.dumps(message.to_dict()))
        else:
            self._messageids_to_asyncresult[message_id] = async_result
            self._send_with_retry(receiver_address, async_result, json.dumps(message.to_dict()))
Пример #16
0
    def __init__(
            self,
            jsonrpc_client,
            manager_address,
    ):
        if not is_binary_address(manager_address):
            raise InvalidAddress('Expected binary address format for token nework')

        check_address_has_code(jsonrpc_client, manager_address, CONTRACT_TOKEN_NETWORK)

        proxy = jsonrpc_client.new_contract_proxy(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_TOKEN_NETWORK),
            to_normalized_address(manager_address),
        )

        is_good_version = compare_versions(
            proxy.contract.functions.contract_version().call(),
            EXPECTED_CONTRACTS_VERSION,
        )
        if not is_good_version:
            raise ContractVersionMismatch('Incompatible ABI for TokenNetwork')

        self.address = manager_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(self.client.privkey)
        self.open_channel_transactions = dict()

        # Forbids concurrent operations on the same channel
        self.channel_operations_lock = defaultdict(RLock)

        # Serializes concurent deposits on this token network. This must be an
        # exclusive lock, since we need to coordinate the approve and
        # setTotalDeposit calls.
        self.deposit_lock = Semaphore()
Пример #17
0
def input_address_formatter(addr):
    iban = Iban(addr)
    if iban.isValid() and iban.isDirect():
        return add_0x_prefix(iban.address())
    elif is_address(addr):
        return to_normalized_address(addr)

    raise ValueError("invalid address")
Пример #18
0
    def sender(self):
        if not self._sender:
            if not is_bitcoin_available() or not is_secp256k1_available():
                raise ImportError(
                    "In order to derive the sender for transactions the "
                    "`bitcoin` and `secp256k1` packages must be installed."
                )
            from bitcoin import N
            from secp256k1 import PublicKey, ALL_FLAGS

            # Determine sender
            if self.v:
                has_invalid_signature_values = (
                    self.r >= N or
                    self.s >= N or
                    self.v < 27 or
                    self.v > 28 or
                    self.r == 0 or
                    self.s == 0
                )
                if has_invalid_signature_values:
                    raise ValueError("Invalid signature values!")
                rlpdata = rlp.encode(self, UnsignedTransaction)
                rawhash = keccak(rlpdata)

                pk = PublicKey(flags=ALL_FLAGS)
                try:
                    pk.public_key = pk.ecdsa_recover(
                        rawhash,
                        pk.ecdsa_recoverable_deserialize(
                            pad_left(
                                int_to_big_endian(self.r),
                                32,
                                b'\x00',
                            ) + pad_left(
                                int_to_big_endian(self.s),
                                32,
                                b'\x00',
                            ),
                            self.v - 27
                        ),
                        raw=True
                    )
                    pub = pk.serialize(compressed=False)
                except Exception:
                    raise ValueError("Invalid signature values (x^3+7 is non-residue)")

                if pub[1:] == b"\x00" * (len(pub) - 1):
                    raise ValueError("Invalid signature (zero privkey cannot sign)")

                self._sender = to_normalized_address(keccak(pub[1:])[-20:])
                assert self.sender == self._sender
            else:
                self._sender = 0
        return self._sender
Пример #19
0
 def to_dict(self):
     return {
         'type': self.__class__.__name__,
         'chain_id': self.chain_id,
         'message_identifier': self.message_identifier,
         'payment_identifier': self.payment_identifier,
         'nonce': self.nonce,
         'token_network_address': to_normalized_address(self.token_network_address),
         'token': to_normalized_address(self.token),
         'channel': encode_hex(self.channel),
         'transferred_amount': self.transferred_amount,
         'locked_amount': self.locked_amount,
         'recipient': to_normalized_address(self.recipient),
         'locksroot': encode_hex(self.locksroot),
         'lock': self.lock.to_dict(),
         'target': to_normalized_address(self.target),
         'initiator': to_normalized_address(self.initiator),
         'fee': self.fee,
         'signature': encode_hex(self.signature),
     }
Пример #20
0
def database_paths(tmpdir, private_keys):
    """ Sqlite database paths for each app. """
    database_paths = list()
    for pkey in private_keys:
        app_dir = os.path.join(
            tmpdir.strpath,
            to_normalized_address(privatekey_to_address(pkey))[2:8],
        )
        if not os.path.exists(app_dir):
            os.makedirs(app_dir)
        database_paths.append(os.path.join(app_dir, 'log.db'))

    return database_paths
Пример #21
0
    def __init__(
            self,
            config: typing.Dict,
            chain: BlockChainService,
            query_start_block: typing.BlockNumber,
            default_registry: TokenNetworkRegistry,
            default_secret_registry: SecretRegistry,
            transport,
            discovery: Discovery = None,
    ):
        self.config = config
        self.discovery = discovery

        # check that the settlement timeout fits the limits of the contract
        invalid_timeout = (
            config['settle_timeout'] < default_registry.settlement_timeout_min() or
            config['settle_timeout'] > default_registry.settlement_timeout_max()
        )
        if invalid_timeout:
            raise InvalidSettleTimeout(
                (
                    'Settlement timeout for Registry contract {} must '
                    'be in range [{}, {}], is {}'
                ).format(
                    to_checksum_address(default_registry.address),
                    default_registry.settlement_timeout_min(),
                    default_registry.settlement_timeout_max(),
                    config['settle_timeout'],
                ),
            )

        try:
            self.raiden = RaidenService(
                chain=chain,
                query_start_block=query_start_block,
                default_registry=default_registry,
                default_secret_registry=default_secret_registry,
                private_key_bin=unhexlify(config['privatekey_hex']),
                transport=transport,
                config=config,
                discovery=discovery,
            )
        except filelock.Timeout:
            pubkey = to_normalized_address(
                privatekey_to_address(unhexlify(self.config['privatekey_hex'])),
            )
            print(
                f'FATAL: Another Raiden instance already running for account {pubkey} on '
                f'network id {chain.network_id}',
            )
            sys.exit(1)
Пример #22
0
    def _login_or_register(self):
        # password is signed server address
        password = encode_hex(self._sign(self._server_name.encode()))
        seed = int.from_bytes(self._sign(b'seed')[-32:], 'big')
        rand = Random()  # deterministic, random secret for username suffixes
        rand.seed(seed)
        # try login and register on first 5 possible accounts
        for i in range(5):
            base_username = to_normalized_address(self._raiden_service.address)
            username = base_username
            if i:
                username = f'{username}.{rand.randint(0, 0xffffffff):08x}'

            try:
                self._client.sync_token = None
                self._client.login(username, password)
                self.log.info(
                    'LOGIN',
                    homeserver=self._server_name,
                    server_url=self._server_url,
                    username=username,
                )
                break
            except MatrixRequestError as ex:
                if ex.code != 403:
                    raise
                self.log.debug(
                    'Could not login. Trying register',
                    homeserver=self._server_name,
                    server_url=self._server_url,
                    username=username,
                )
                try:
                    self._client.register_with_password(username, password)
                    self.log.info(
                        'REGISTER',
                        homeserver=self._server_name,
                        server_url=self._server_url,
                        username=username,
                    )
                    break
                except MatrixRequestError as ex:
                    if ex.code != 400:
                        raise
                    self.log.debug('Username taken. Continuing')
                    continue
        else:
            raise ValueError('Could not register or login!')
        # TODO: persist access_token, to avoid generating a new login every time
        name = encode_hex(self._sign(self._client.user_id.encode()))
        self._get_user(self._client.user_id).set_display_name(name)
Пример #23
0
def removedb(ctx):
    """Delete local cache and database of this address or all if none is specified."""

    datadir = ctx.obj['datadir']
    address = ctx.obj['address']
    address_hex = to_normalized_address(address) if address else None

    result = False
    for f in os.listdir(datadir):
        netdir = os.path.join(datadir, f)
        if os.path.isdir(netdir):
            if _removedb(netdir, address_hex):
                result = True

    if not result:
        print('No raiden databases found for {}'.format(address_hex))
        print('Nothing to delete.')
Пример #24
0
 def get_filter_events(
         self,
         contract_address: Address,
         topics: List[str] = None,
         from_block: typing.BlockSpecification = 0,
         to_block: typing.BlockSpecification = 'latest',
 ) -> List[Dict]:
     """ Get events for the given query. """
     try:
         return self.web3.eth.getLogs({
             'fromBlock': from_block,
             'toBlock': to_block,
             'address': to_normalized_address(contract_address),
             'topics': topics,
         })
     except BlockNotFound:
         return []
Пример #25
0
 def new_filter(
         self,
         contract_address: Address,
         topics: List[str] = None,
         from_block: typing.BlockSpecification = 0,
         to_block: typing.BlockSpecification = 'latest',
 ) -> Filter:
     """ Create a filter in the ethereum node. """
     return StatelessFilter(
         self.web3,
         {
             'fromBlock': from_block,
             'toBlock': to_block,
             'address': to_normalized_address(contract_address),
             'topics': topics,
         },
     )
Пример #26
0
def check_address_has_code(
        client: 'JSONRPCClient',
        address: Address,
        contract_name: str = '',
):
    """ Checks that the given address contains code. """
    result = client.web3.eth.getCode(to_checksum_address(address), 'latest')

    if not result:
        if contract_name:
            formated_contract_name = '[{}]: '.format(contract_name)
        else:
            formated_contract_name = ''

        raise AddressWithoutCode('{}Address {} does not contain code'.format(
            formated_contract_name,
            to_normalized_address(address),
        ))
Пример #27
0
    def __init__(
            self,
            jsonrpc_client,
            token_address,
    ):
        contract = jsonrpc_client.new_contract(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_HUMAN_STANDARD_TOKEN),
            to_normalized_address(token_address),
        )
        proxy = ContractProxy(jsonrpc_client, contract)

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

        check_address_has_code(jsonrpc_client, token_address, 'Token')

        self.address = token_address
        self.client = jsonrpc_client
        self.proxy = proxy
Пример #28
0
 def get(self, ethAddress, redis_conn=None):
     ethAddress = eth_utils.to_normalized_address(ethAddress)
     u = redis_conn.hget(REDIS_ADABDHA_USERS, ethAddress)
     if not u:
         return {}, 404
     details = json.loads(u)
     if 'isAdmin' not in details:
         details['isAdmin'] = False
     _u_v = redis_conn.get(REDIS_ADABDHA_USER_VI_TOKEN.format(ethAddress))
     if not _u_v:
         # no waiting verificaion intents found
         pass
     else:
         # check VI status
         v_s = redis_conn.get(
             REDIS_ADABDHA_VI_STATUS.format(_u_v.decode('utf-8')))
         if v_s and int(v_s) == -1:
             # set kyc verified status to requested
             details['kycVerified'] = 'requested'
     return details, 200
Пример #29
0
    async def _unlock_account_with_duration(self,
                                            wallet_address: bytes,
                                            password: str,
                                            duration: int = 300):
        normalized_wallet_address = to_normalized_address(wallet_address)
        account = await self._unlock_account(wallet_address, password)

        self._unlocked_accounts[normalized_wallet_address] = account

        if duration == 0:
            if normalized_wallet_address in self._account_lock_cancel_events:
                print("Cancelling previous lock event")
                self._account_lock_cancel_events[
                    normalized_wallet_address].set()
                del (self.
                     _account_lock_cancel_events[normalized_wallet_address])

        else:
            asyncio.ensure_future(
                self._lock_account_after_time(account.address, duration))
Пример #30
0
    def start_health_check(self, node_address):
        if not self._running:
            return
        node_address_hex = to_normalized_address(node_address)
        self.log.debug('HEALTHCHECK', peer_address=node_address_hex)
        with self._health_semaphore:
            candidates = [
                self._get_user(user)
                for user in self._client.search_user_directory(node_address_hex)
            ]
            user_ids = {
                user.user_id
                for user in candidates
                if self._validate_userid_signature(user) == node_address
            }
            self._address_to_userids[node_address].update(user_ids)

            # Ensure network state is updated in case we already know about the user presences
            # representing the target node
            self._update_address_presence(node_address)
Пример #31
0
    def __init__(
        self,
        jsonrpc_client,
        token_address,
    ):
        contract = jsonrpc_client.new_contract(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_HUMAN_STANDARD_TOKEN),
            to_normalized_address(token_address),
        )
        proxy = ContractProxy(jsonrpc_client, contract)

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

        check_address_has_code(jsonrpc_client, token_address, 'Token')

        self.address = token_address
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(jsonrpc_client.privkey)
        self.proxy = proxy
Пример #32
0
def database_paths(tmpdir, private_keys, in_memory_database):
    """ Sqlite database paths for each app.
    """
    # According to http://www.sqlite.org/inmemorydb.html each memory connection will
    # create a unique in-memory DB, which is exactly what we need in this case for
    # each different Raiden app
    if in_memory_database:
        return [':memory:' for position in range(len(private_keys))]

    database_paths = list()
    for pkey in private_keys:
        app_dir = os.path.join(
            tmpdir.strpath,
            to_normalized_address(privatekey_to_address(pkey))[2:8],
        )
        if not os.path.exists(app_dir):
            os.makedirs(app_dir)
        database_paths.append(os.path.join(app_dir, 'log.db'))

    return database_paths
Пример #33
0
    def start_health_check(self, node_address):
        if not self._running:
            return
        node_address_hex = to_normalized_address(node_address)
        self.log.debug('HEALTHCHECK', peer_address=node_address_hex)
        with self._health_semaphore:
            candidates = [
                self._get_user(user) for user in
                self._client.search_user_directory(node_address_hex)
            ]
            user_ids = {
                user.user_id
                for user in candidates
                if self._validate_userid_signature(user) == node_address
            }
            self._address_to_userids[node_address].update(user_ids)

            # Ensure network state is updated in case we already know about the user presences
            # representing the target node
            self._update_address_presence(node_address)
Пример #34
0
    def __init__(
        self,
        jsonrpc_client,
        token_address,
        poll_timeout=DEFAULT_POLL_TIMEOUT,
    ):
        contract = jsonrpc_client.new_contract(
            CONTRACT_MANAGER.get_contract_abi(CONTRACT_HUMAN_STANDARD_TOKEN),
            to_normalized_address(token_address),
        )
        self.proxy = ContractProxy(jsonrpc_client, contract)

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

        check_address_has_code(jsonrpc_client, token_address, 'Token')

        self.address = token_address
        self.client = jsonrpc_client
        self.poll_timeout = poll_timeout
Пример #35
0
def login(
    client: GMatrixClient,
    signer: Signer,
    prev_auth_data: Optional[str] = None,
    capabilities: Dict[str, Any] = None,
) -> User:
    """Login with a matrix server.

    Params:
        client: GMatrixClient instance configured with desired homeserver.
        signer: Signer used to sign the password and displayname.
        prev_auth_data: Previously persisted authentication using the format "{user}/{password}".
    """
    if capabilities is None:
        capabilities = {}
    server_url = client.api.base_url
    server_name = urlparse(server_url).netloc

    username = str(to_normalized_address(signer.address))

    if prev_auth_data and prev_auth_data.count("/") == 1:
        user_id, _, access_token = prev_auth_data.partition("/")

        if is_valid_username(username, server_name, user_id):
            user = login_with_token(client, user_id, access_token)

            if user is not None:
                return user
        else:
            log.debug(
                "Auth data is invalid, discarding",
                node=username,
                user_id=user_id,
                server_name=server_name,
            )

    try:
        capstr = serialize_capabilities(capabilities)
    except ValueError:
        raise Exception("error serializing")
    return first_login(client, signer, username, capstr)
Пример #36
0
    def start_health_check(self, node_address):
        if not self._running:
            return
        self.log.debug('HEALTHCHECK', peer_address=pex(node_address))
        node_address_hex = to_normalized_address(node_address)
        with self._health_semaphore:
            user_ids = {
                user.user_id
                for user in self._client.search_user_directory(
                    node_address_hex) if self._validate_userid_signature(user)
            }
            self._address_to_userids[node_address].update(user_ids)

            # Ensure network state is updated in case we already know about the user presences
            # representing the target node
            self._update_address_presence(node_address)
            room = self._get_room_for_address(node_address,
                                              allow_missing_peers=True)
            if not room:
                self.log.warning('No room found or created for peer',
                                 peer=node_address_hex)
Пример #37
0
 def get_filter_events(
     self,
     contract_address: Address,
     topics: List[str] = None,
     from_block: typing.BlockSpecification = 0,
     to_block: typing.BlockSpecification = 'latest',
 ) -> List[Dict]:
     """ Get events for the given query. """
     try:
         return self.web3.eth.getLogs({
             'fromBlock':
             from_block,
             'toBlock':
             to_block,
             'address':
             to_normalized_address(contract_address),
             'topics':
             topics,
         })
     except BlockNotFound:
         return []
Пример #38
0
def decrypt_account(keystore_dir: PS,
                    address: StrOrBytes,
                    passphrase: Optional[str] = None) -> bytes:
    """ Decrypt the keyfile and return the private key """
    global PRIVATE_KEY

    address = str(to_normalized_address(address))

    if PRIVATE_KEY is not None and PRIVATE_KEY[0] == address:
        return PRIVATE_KEY[1]

    if not passphrase:
        if not passphrase:
            passphrase = getpass(
                "Enter password to decrypt account ({}):".format(address))

    account_json = read_account_json(keystore_dir, address)

    eth_account = Account()
    PRIVATE_KEY = (address, eth_account.decrypt(account_json, passphrase))
    return PRIVATE_KEY[1]
Пример #39
0
    def _update_address_presence(self, address):
        """ Update synthesized address presence state from user presence state """
        self.log.debug('Address to userids',
                       address_to_userids=self._address_to_userids)

        composite_presence = {
            self._get_user_presence(uid)
            for uid in self._address_to_userids.get(address, set())
        }

        # Iterate over UserPresence in definition order and pick first matching state
        new_state = UserPresence.UNKNOWN
        for presence in UserPresence.__members__.values():
            if presence in composite_presence:
                new_state = presence
                break

        if new_state == self._address_to_presence.get(address):
            return
        self.log.debug(
            'Changing address presence state',
            address=to_normalized_address(address),
            prev_state=self._address_to_presence.get(address),
            state=new_state,
        )
        self._address_to_presence[address] = new_state
        if new_state is None:
            return

        if new_state is UserPresence.UNKNOWN:
            reachability = NODE_NETWORK_UNKNOWN
        elif new_state is UserPresence.OFFLINE:
            reachability = NODE_NETWORK_UNREACHABLE
        else:
            reachability = NODE_NETWORK_REACHABLE
            # The Matrix presence status 'unavailable' just means that the user has been inactive
            # for a while. So a user with UserPresence.UNAVAILABLE is still 'reachable' to us.

        state_change = ActionChangeNodeNetworkState(address, reachability)
        self._raiden_service.handle_state_change(state_change)
Пример #40
0
def sign_create_order(order_params, private_key):
    """
    Function to sign the create order parameters and send to the Switcheo API.
    Execution of this function is as follows::

        sign_create_order(order_params=signable_params, private_key=eth_private_key)

    The expected return result for this function is as follows::

        {
            'blockchain': 'eth',
            'pair': 'JRC_ETH',
            'side': 'buy',
            'price': '0.00000003',
            'want_amount': '3350000000000000000000000',
            'use_native_tokens': False,
            'order_type': 'limit',
            'timestamp': 1542089785915,
            'contract_hash': '0x607af5164d95bd293dbe2b994c7d8aef6bec03bf',
            'signature': '536306a2f2aee499ffd6584027029ee585293b3686....',
            'address': '0x32c46323b51c977814e05ef5e258ee4da0e4c3c3'
        }

    :param order_params: Parameters to create an order to be submitted to the Switcheo Order Book.
    :type order_params: dict
    :param private_key: The Ethereum private key to sign the deposit parameters.
    :type private_key: str
    :return: Dictionary of signed message to send to the Switcheo API.
    """
    hash_message = defunct_hash_message(text=stringify_message(order_params))
    hex_message = binascii.hexlify(hash_message).decode()
    create_params = order_params.copy()
    signed_message = binascii.hexlify(
        Account.signHash(hex_message,
                         private_key=private_key)['signature']).decode()
    create_params['signature'] = signed_message
    create_params['address'] = to_normalized_address(
        Account.privateKeyToAccount(private_key=private_key).address)
    return create_params
Пример #41
0
    def __init__(
        self,
        jsonrpc_client,
        manager_address,
        contract_manager: ContractManager,
    ):
        if not is_binary_address(manager_address):
            raise InvalidAddress(
                'Expected binary address format for token nework')

        check_address_has_code(jsonrpc_client, manager_address,
                               CONTRACT_TOKEN_NETWORK)

        self.contract_manager = contract_manager
        proxy = jsonrpc_client.new_contract_proxy(
            self.contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK),
            to_normalized_address(manager_address),
        )

        compare_contract_versions(
            proxy=proxy,
            expected_version=contract_manager.contracts_version,
            contract_name=CONTRACT_TOKEN_NETWORK,
            address=manager_address,
        )

        self.address = manager_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(self.client.privkey)
        self.open_channel_transactions = dict()

        # Forbids concurrent operations on the same channel
        self.channel_operations_lock = defaultdict(RLock)

        # Serializes concurent deposits on this token network. This must be an
        # exclusive lock, since we need to coordinate the approve and
        # setTotalDeposit calls.
        self.deposit_lock = Semaphore()
Пример #42
0
    def refresh_address_presence(self, address: Address):
        """
        Update synthesized address presence state from cached user presence states.

        Triggers callback (if any) in case the state has changed.

        This method is only provided to cover an edge case in our use of the Matrix protocol and
        should **not** generally be used.
        """
        composite_presence = {
            self._fetch_user_presence(uid)
            for uid in self._address_to_userids[address]
        }

        # Iterate over UserPresence in definition order (most to least online) and pick
        # first matching state
        new_presence = UserPresence.UNKNOWN
        for presence in UserPresence.__members__.values():
            if presence in composite_presence:
                new_presence = presence
                break

        new_address_reachability = USER_PRESENCE_TO_ADDRESS_REACHABILITY[
            new_presence]

        if new_address_reachability == self._address_to_reachability.get(
                address):
            # Cached address reachability matches new state, do nothing
            return
        log.debug(
            "Changing address presence state",
            current_user=self._user_id,
            address=to_normalized_address(address),
            prev_state=self._address_to_reachability.get(address),
            state=new_address_reachability,
        )
        self._address_to_reachability[address] = new_address_reachability
        self._address_reachability_changed_callback(address,
                                                    new_address_reachability)
Пример #43
0
    def __init__(
        self,
        jsonrpc_client,
        manager_address,
    ):
        if not is_binary_address(manager_address):
            raise InvalidAddress(
                'Expected binary address format for token nework')

        check_address_has_code(jsonrpc_client, manager_address,
                               CONTRACT_TOKEN_NETWORK)

        contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH)
        proxy = jsonrpc_client.new_contract_proxy(
            contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK),
            to_normalized_address(manager_address),
        )

        is_good_version = compare_versions(
            proxy.contract.functions.contract_version().call(),
            EXPECTED_CONTRACTS_VERSION,
        )
        if not is_good_version:
            raise ContractVersionMismatch('Incompatible ABI for TokenNetwork')

        self.address = manager_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = privatekey_to_address(self.client.privkey)
        self.open_channel_transactions = dict()

        # Forbids concurrent operations on the same channel
        self.channel_operations_lock = defaultdict(RLock)

        # Serializes concurent deposits on this token network. This must be an
        # exclusive lock, since we need to coordinate the approve and
        # setTotalDeposit calls.
        self.deposit_lock = Semaphore()
Пример #44
0
    def __init__(
        self,
        jsonrpc_client,
        secret_registry_address,
        contract_manager: ContractManager,
    ):
        if not is_binary_address(secret_registry_address):
            raise InvalidAddress(
                'Expected binary address format for secret registry')

        self.contract_manager = contract_manager
        check_address_has_code(jsonrpc_client, secret_registry_address,
                               CONTRACT_SECRET_REGISTRY)

        proxy = jsonrpc_client.new_contract_proxy(
            self.contract_manager.get_contract_abi(CONTRACT_SECRET_REGISTRY),
            to_normalized_address(secret_registry_address),
        )

        # There should be only one smart contract deployed, to avoid race
        # conditions for on-chain unlocks.
        compare_contract_versions(
            proxy=proxy,
            expected_version=contract_manager.contracts_version,
            contract_name=CONTRACT_SECRET_REGISTRY,
            address=secret_registry_address,
        )

        self.address = secret_registry_address
        self.proxy = proxy
        self.client = jsonrpc_client
        self.node_address = self.client.address

        # The dictionary of open transactions is used to avoid sending a
        # transaction for the same secret more than once. This requires
        # synchronization for the local threads.
        self.open_secret_transactions = dict()
        self._open_secret_transactions_lock = Semaphore()
Пример #45
0
def geth_generate_poa_genesis(genesis_path: str,
                              genesis_description: GenesisDescription,
                              seal_account: Address) -> None:
    """Writes a bare genesis to `genesis_path`."""

    alloc = {
        to_normalized_address(account.address): {
            "balance": str(account.balance)
        }
        for account in genesis_description.prefunded_accounts
    }
    seal_address_normalized = remove_0x_prefix(encode_hex(seal_account))
    extra_data = geth_clique_extradata(genesis_description.random_marker,
                                       seal_address_normalized)

    genesis = GENESIS_STUB.copy()
    genesis["alloc"].update(alloc)
    genesis["config"]["ChainID"] = genesis_description.chain_id
    genesis["config"]["clique"] = {"period": 1, "epoch": 30000}
    genesis["extraData"] = extra_data

    with open(genesis_path, "w") as handler:
        json.dump(genesis, handler)
Пример #46
0
def sign_create_withdrawal(withdrawal_params, private_key):
    """
    Function to create a withdrawal from the Switcheo Smart Contract.
    Execution of this function is as follows::

        sign_create_withdrawal(withdrawal_params=signable_params, private_key=eth_private_key)

    The expected return result for this function is as follows::

        {
            'blockchain': 'eth',
            'asset_id': 'ETH',
            'amount': '10000000000000000',
            'timestamp': 1542090476102,
            'contract_hash': '0x607af5164d95bd293dbe2b994c7d8aef6bec03bf',
            'address': '0x32c46323b51c977814e05ef5e258ee4da0e4c3c3',
            'signature': '375ddce62e5b3676d5e94ebb9f9a8af5963b....'
        }

    :param withdrawal_params: The parameters to be signed and create a withdraw from Switcheo.
    :type withdrawal_params: dict
    :param private_key: The Ethereum private key to sign the deposit parameters.
    :type private_key: str
    :return: Dictionary of the signed transaction to initiate the withdrawal of ETH via the Switcheo API.
    """
    hash_message = defunct_hash_message(
        text=stringify_message(withdrawal_params))
    hex_message = binascii.hexlify(hash_message).decode()
    signed_message = binascii.hexlify(
        Account.signHash(hex_message,
                         private_key=private_key)['signature']).decode()
    create_params = withdrawal_params.copy()
    create_params['address'] = to_normalized_address(
        Account.privateKeyToAccount(private_key=private_key).address)
    create_params['signature'] = signed_message
    return create_params
Пример #47
0
    def _update_address_presence(self, address):
        """ Update synthesized address presence state from user presence state """
        composite_presence = {
            self._get_user_presence(uid)
            for uid
            in self._address_to_userids.get(address, set())
        }

        # Iterate over UserPresence in definition order and pick first matching state
        new_state = UserPresence.UNKNOWN
        for presence in UserPresence.__members__.values():
            if presence in composite_presence:
                new_state = presence
                break

        if new_state == self._address_to_presence.get(address):
            return
        self.log.debug(
            'Changing address presence state',
            address=to_normalized_address(address),
            prev_state=self._address_to_presence.get(address),
            state=new_state,
        )
        self._address_to_presence[address] = new_state

        if new_state is UserPresence.UNKNOWN:
            reachability = NODE_NETWORK_UNKNOWN
        elif new_state is UserPresence.OFFLINE:
            reachability = NODE_NETWORK_UNREACHABLE
        else:
            reachability = NODE_NETWORK_REACHABLE
            # The Matrix presence status 'unavailable' just means that the user has been inactive
            # for a while. So a user with UserPresence.UNAVAILABLE is still 'reachable' to us.

        state_change = ActionChangeNodeNetworkState(address, reachability)
        self._raiden_service.handle_state_change(state_change)
Пример #48
0
 def to_dict(self):
     return {
         'type': self.__class__.__name__,
         'message_identifier': self.message_identifier,
         'payment_identifier': self.payment_identifier,
         'nonce': self.nonce,
         'token_network_address': to_normalized_address(self.token_network_address),
         'token': to_normalized_address(self.token),
         'channel': to_normalized_address(self.channel),
         'transferred_amount': self.transferred_amount,
         'locked_amount': self.locked_amount,
         'recipient': to_normalized_address(self.recipient),
         'locksroot': encode_hex(self.locksroot),
         'lock': self.lock.to_dict(),
         'target': to_normalized_address(self.target),
         'initiator': to_normalized_address(self.initiator),
         'fee': self.fee,
         'signature': encode_hex(self.signature),
     }
Пример #49
0
def address_to_reverse_domain(address: ChecksumAddress) -> str:
    lower_unprefixed_address = remove_0x_prefix(
        HexStr(to_normalized_address(address)))
    return lower_unprefixed_address + '.' + REVERSE_REGISTRAR_DOMAIN
Пример #50
0
    def __init__(self, *args, **kwargs):
        """Create a new smart contract proxy object.

        :param address: Contract address as 0x hex string
        """
        code = kwargs.pop('code', empty)
        code_runtime = kwargs.pop('code_runtime', empty)
        source = kwargs.pop('source', empty)
        abi = kwargs.pop('abi', empty)
        address = kwargs.pop('address', empty)

        if self.web3 is None:
            raise AttributeError(
                'The `Contract` class has not been initialized.  Please use the '
                '`web3.contract` interface to create your contract class.')

        arg_0, arg_1, arg_2, arg_3, arg_4 = tuple(
            itertools.chain(
                args,
                itertools.repeat(empty, 5),
            ))[:5]

        if is_list_like(arg_0):
            if abi:
                raise TypeError("The 'abi' argument was found twice")
            abi = arg_0
        elif is_address(arg_0):
            if address:
                raise TypeError("The 'address' argument was found twice")
            address = arg_0

        if arg_1 is not empty:
            if address:
                raise TypeError("The 'address' argument was found twice")
            address = arg_1

        if arg_2 is not empty:
            if code:
                raise TypeError("The 'code' argument was found twice")
            code = arg_2

        if arg_3 is not empty:
            if code_runtime:
                raise TypeError("The 'code_runtime' argument was found twice")
            code_runtime = arg_3

        if arg_4 is not empty:
            if source:
                raise TypeError("The 'source' argument was found twice")
            source = arg_4

        if any((abi, code, code_runtime, source)):
            warnings.warn(
                DeprecationWarning(
                    "The arguments abi, code, code_runtime, and source have been "
                    "deprecated and will be removed from the Contract class "
                    "constructor in future releases.  Update your code to use the "
                    "Contract.factory method."))

        if abi is not empty:
            validate_abi(abi)
            self.abi = abi
        if code is not empty:
            self.bytecode = code
        if code_runtime is not empty:
            self.bytecode_runtime = code_runtime
        if source is not empty:
            self._source = source

        if address is not empty:
            validate_address(address)
            self.address = to_normalized_address(address)
        else:
            warnings.warn(
                DeprecationWarning(
                    "The address argument is now required for contract class "
                    "instantiation.  Please update your code to reflect this change"
                ))
Пример #51
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit, transport_config):
    node1, node2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(node1),
        node1.raiden.default_registry.address,
        token_address,
    )

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    registry_address = node1.raiden.default_registry.address

    # nodes don't have a channel, so they are not healthchecking
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN
    assert not api1.get_channel_list(registry_address, token_address, api2.address)

    # open is a synchronous api
    api1.channel_open(node1.raiden.default_registry.address, token_address, api2.address)
    channels = api1.get_channel_list(registry_address, token_address, api2.address)
    assert len(channels) == 1

    channel12 = get_channelstate(node1, node2, token_network_identifier)
    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED

    event_list1 = api1.get_channel_events(
        token_address,
        channel12.partner_state.address,
        channel12.open_transaction.finished_block_number,
    )
    assert any(
        (
            event['event'] == EVENT_CHANNEL_OPENED and
            is_same_address(
                event['args']['participant1'],
                to_normalized_address(api1.address),
            ) and
            is_same_address(
                event['args']['participant2'],
                to_normalized_address(api2.address),
            )
        )
        for event in event_list1
    )

    token_events = api1.get_token_network_events(
        token_address,
        channel12.open_transaction.finished_block_number,
    )
    assert token_events[0]['event'] == EVENT_CHANNEL_OPENED

    registry_address = api1.raiden.default_registry.address
    # Load the new state with the deposit
    api1.set_total_channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )

    # let's make sure it's idempotent
    api1.set_total_channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )

    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED
    assert channel.get_balance(channel12.our_state, channel12.partner_state) == deposit
    assert channel12.our_state.contract_balance == deposit
    assert api1.get_channel_list(registry_address, token_address, api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_channel_events(
        token_address,
        channel12.partner_state.address,
        channel12.open_transaction.finished_block_number,
    )
    assert any(
        (
            event['event'] == EVENT_CHANNEL_DEPOSIT and
            is_same_address(
                event['args']['participant'],
                to_normalized_address(api1.address),
            ) and
            event['args']['total_deposit'] == deposit
        )
        for event in event_list2
    )

    api1.channel_close(registry_address, token_address, api2.address)

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    event_list3 = api1.get_channel_events(
        token_address,
        channel12.partner_state.address,
        channel12.open_transaction.finished_block_number,
    )
    assert len(event_list3) > len(event_list2)
    assert any(
        (
            event['event'] == EVENT_CHANNEL_CLOSED and
            is_same_address(
                event['args']['closing_participant'],
                to_normalized_address(api1.address),
            )
        )
        for event in event_list3
    )
    assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.close_transaction.finished_block_number +
        channel12.settle_timeout +
        10  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    # Load the new state with the channel settled
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_SETTLED
Пример #52
0
 def __init__(self, address):
     if isinstance(address, Address):
         self.address = address.address
     else:
         self.address = eth_utils.to_normalized_address(address)
Пример #53
0
def run_app(
    address,
    keystore_path,
    gas_price,
    eth_rpc_endpoint,
    tokennetwork_registry_contract_address,
    secret_registry_contract_address,
    endpoint_registry_contract_address,
    listen_address,
    mapped_socket,
    max_unresponsive_time,
    api_address,
    rpc,
    sync_check,
    console,
    password_file,
    web_ui,
    datadir,
    transport,
    matrix_server,
    network_id,
    environment_type,
    unrecoverable_error_should_crash,
    pathfinding_service_address,
    config=None,
    extra_config=None,
    **kwargs,
):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    from raiden.app import App

    _assert_sql_version()

    if transport == 'udp' and not mapped_socket:
        raise RuntimeError('Missing socket')

    if datadir is None:
        datadir = os.path.join(os.path.expanduser('~'), '.raiden')

    address_hex = to_normalized_address(address) if address else None
    address_hex, privatekey_bin = prompt_account(address_hex, keystore_path,
                                                 password_file)
    address = to_canonical_address(address_hex)

    (listen_host, listen_port) = split_endpoint(listen_address)
    (api_host, api_port) = split_endpoint(api_address)

    config['transport']['udp']['host'] = listen_host
    config['transport']['udp']['port'] = listen_port
    config['console'] = console
    config['rpc'] = rpc
    config['web_ui'] = rpc and web_ui
    config['api_host'] = api_host
    config['api_port'] = api_port
    if mapped_socket:
        config['socket'] = mapped_socket.socket
        config['transport']['udp']['external_ip'] = mapped_socket.external_ip
        config['transport']['udp'][
            'external_port'] = mapped_socket.external_port
    config['transport_type'] = transport
    config['transport']['matrix']['server'] = matrix_server
    config['transport']['udp'][
        'nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES
    timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES
    config['transport']['udp']['nat_keepalive_timeout'] = timeout
    config['privatekey_hex'] = encode_hex(privatekey_bin)
    config[
        'unrecoverable_error_should_crash'] = unrecoverable_error_should_crash
    config['services'][
        'pathfinding_service_address'] = pathfinding_service_address

    parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint)
    if not parsed_eth_rpc_endpoint.scheme:
        eth_rpc_endpoint = f'http://{eth_rpc_endpoint}'

    web3 = _setup_web3(eth_rpc_endpoint)

    rpc_client = JSONRPCClient(
        web3,
        privatekey_bin,
        gas_price_strategy=gas_price,
        block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
        uses_infura='infura.io' in eth_rpc_endpoint,
    )

    blockchain_service = BlockChainService(
        privatekey_bin=privatekey_bin,
        jsonrpc_client=rpc_client,
        # Not giving the contract manager here, but injecting it later
        # since we first need blockchain service to calculate the network id
    )

    given_network_id = network_id
    node_network_id = blockchain_service.network_id
    known_given_network_id = given_network_id in ID_TO_NETWORKNAME
    known_node_network_id = node_network_id in ID_TO_NETWORKNAME

    if node_network_id != given_network_id:
        if known_given_network_id and known_node_network_id:
            click.secho(
                f"The chosen ethereum network '{ID_TO_NETWORKNAME[given_network_id]}' "
                f"differs from the ethereum client '{ID_TO_NETWORKNAME[node_network_id]}'. "
                "Please update your settings.",
                fg='red',
            )
        else:
            click.secho(
                f"The chosen ethereum network id '{given_network_id}' differs "
                f"from the ethereum client '{node_network_id}'. "
                "Please update your settings.",
                fg='red',
            )
        sys.exit(1)

    config['chain_id'] = given_network_id

    # interpret the provided string argument
    if environment_type == Environment.PRODUCTION:
        # Safe configuration: restrictions for mainnet apply and matrix rooms have to be private
        config['environment_type'] = Environment.PRODUCTION
        config['transport']['matrix']['private_rooms'] = True
    else:
        config['environment_type'] = Environment.DEVELOPMENT

    environment_type = config['environment_type']
    print(f'Raiden is running in {environment_type.value.lower()} mode')

    chain_config = {}
    contract_addresses_known = False
    contracts = dict()
    contracts_version = 'pre_limits' if environment_type == Environment.DEVELOPMENT else None
    config['contracts_path'] = contracts_precompiled_path(contracts_version)
    if node_network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[
            node_network_id] != 'smoketest':
        deployment_data = get_contracts_deployed(node_network_id,
                                                 contracts_version)
        not_allowed = (  # for now we only disallow mainnet with test configuration
            network_id == 1 and environment_type == Environment.DEVELOPMENT)
        if not_allowed:
            click.secho(
                f'The chosen network ({ID_TO_NETWORKNAME[node_network_id]}) is not a testnet, '
                'but the "development" environment was selected.\n'
                'This is not allowed. Please start again with a safe environment setting '
                '(--environment production).',
                fg='red',
            )
            sys.exit(1)

        contracts = deployment_data['contracts']
        contract_addresses_known = True

    blockchain_service.inject_contract_manager(
        ContractManager(config['contracts_path']))

    if sync_check:
        check_synced(blockchain_service, known_node_network_id)

    contract_addresses_given = (
        tokennetwork_registry_contract_address is not None
        and secret_registry_contract_address is not None
        and endpoint_registry_contract_address is not None)

    if not contract_addresses_given and not contract_addresses_known:
        click.secho(
            f"There are no known contract addresses for network id '{given_network_id}'. "
            "Please provide them on the command line or in the configuration file.",
            fg='red',
        )
        sys.exit(1)

    try:
        token_network_registry = blockchain_service.token_network_registry(
            tokennetwork_registry_contract_address or to_canonical_address(
                contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address'], ), )
    except ContractVersionMismatch as e:
        handle_contract_version_mismatch(e)
    except AddressWithoutCode:
        handle_contract_no_code('token network registry',
                                tokennetwork_registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address(
            'token network registry',
            tokennetwork_registry_contract_address,
        )

    try:
        secret_registry = blockchain_service.secret_registry(
            secret_registry_contract_address or to_canonical_address(
                contracts[CONTRACT_SECRET_REGISTRY]['address'], ), )
    except ContractVersionMismatch as e:
        handle_contract_version_mismatch(e)
    except AddressWithoutCode:
        handle_contract_no_code('secret registry',
                                secret_registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address('secret registry',
                                      secret_registry_contract_address)

    database_path = os.path.join(
        datadir,
        f'node_{pex(address)}',
        f'netid_{given_network_id}',
        f'network_{pex(token_network_registry.address)}',
        f'v{RAIDEN_DB_VERSION}_log.db',
    )
    config['database_path'] = database_path

    print(
        '\nYou are connected to the \'{}\' network and the DB path is: {}'.
        format(
            ID_TO_NETWORKNAME.get(given_network_id, given_network_id),
            database_path,
        ), )

    discovery = None
    if transport == 'udp':
        transport, discovery = _setup_udp(
            config,
            blockchain_service,
            address,
            contracts,
            endpoint_registry_contract_address,
        )
    elif transport == 'matrix':
        transport = _setup_matrix(config)
    else:
        raise RuntimeError(f'Unknown transport type "{transport}" given')

    raiden_event_handler = RaidenEventHandler()
    message_handler = MessageHandler()

    try:
        if 'contracts' in chain_config:
            start_block = chain_config['contracts']['TokenNetworkRegistry'][
                'block_number']
        else:
            start_block = 0

        raiden_app = App(
            config=config,
            chain=blockchain_service,
            query_start_block=start_block,
            default_registry=token_network_registry,
            default_secret_registry=secret_registry,
            transport=transport,
            raiden_event_handler=raiden_event_handler,
            message_handler=message_handler,
            discovery=discovery,
        )
    except RaidenError as e:
        click.secho(f'FATAL: {e}', fg='red')
        sys.exit(1)

    try:
        raiden_app.start()
    except RuntimeError as e:
        click.secho(f'FATAL: {e}', fg='red')
        sys.exit(1)
    except filelock.Timeout:
        name_or_id = ID_TO_NETWORKNAME.get(given_network_id, given_network_id)
        click.secho(
            f'FATAL: Another Raiden instance already running for account {address_hex} on '
            f'network id {name_or_id}',
            fg='red',
        )
        sys.exit(1)

    return raiden_app
Пример #54
0
def pubkey_as_address(umbral_pubkey):
    """
    Returns the public key as b'0x' + keccak(uncompressed_bytes)[-20:]
    """
    return to_normalized_address(
        canonical_address_from_umbral_key(umbral_pubkey).hex())
Пример #55
0
def test_query_events(raiden_chain, token_addresses, deposit, settle_timeout,
                      events_poll_timeout):
    app0, app1 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )

    manager0 = app0.raiden.default_registry.manager_by_token(token_address)

    channelcount0 = views.total_token_network_channels(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )

    events = get_all_registry_events(
        app0.raiden.chain,
        registry_address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert events[0]['event'] == EVENT_TOKEN_ADDED
    assert event_dicts_are_equal(
        events[0]['args'], {
            'registry_address': to_normalized_address(registry_address),
            'channel_manager_address': to_normalized_address(manager0.address),
            'token_address': to_normalized_address(token_address),
            'block_number': 'ignore',
        })

    events = get_all_registry_events(
        app0.raiden.chain,
        app0.raiden.default_registry.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    channel_address = RaidenAPI(app0.raiden).channel_open(
        registry_address,
        token_address,
        app1.raiden.address,
    )

    gevent.sleep(events_poll_timeout * 2)

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert events[0]['event'] == EVENT_CHANNEL_NEW
    assert event_dicts_are_equal(
        events[0]['args'], {
            'registry_address': to_normalized_address(registry_address),
            'settle_timeout': settle_timeout,
            'netting_channel': to_normalized_address(channel_address),
            'participant1': to_normalized_address(app0.raiden.address),
            'participant2': to_normalized_address(app1.raiden.address),
            'block_number': 'ignore',
        })

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    # channel is created but not opened and without funds
    channelcount1 = views.total_token_network_channels(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )
    assert channelcount0 + 1 == channelcount1

    assert_synched_channel_state(
        token_network_identifier,
        app0,
        0,
        [],
        app1,
        0,
        [],
    )

    RaidenAPI(app0.raiden).set_total_channel_deposit(
        registry_address,
        token_address,
        app1.raiden.address,
        deposit,
    )

    gevent.sleep(events_poll_timeout * 2)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_NEW_BALANCE)],
    )

    assert len(all_netting_channel_events) == 1
    assert len(events) == 1

    assert events[0]['event'] == EVENT_CHANNEL_NEW_BALANCE
    new_balance_event = {
        'registry_address': to_normalized_address(registry_address),
        'token_address': to_normalized_address(token_address),
        'participant': to_normalized_address(app0.raiden.address),
        'balance': deposit,
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1]['args'],
                                 new_balance_event)
    assert event_dicts_are_equal(events[0]['args'], new_balance_event)

    RaidenAPI(app0.raiden).channel_close(
        registry_address,
        token_address,
        app1.raiden.address,
    )

    gevent.sleep(events_poll_timeout * 2)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=channel_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_CLOSED)],
    )

    assert len(all_netting_channel_events) == 2
    assert len(events) == 1

    assert events[0]['event'] == EVENT_CHANNEL_CLOSED
    closed_event = {
        'registry_address': to_normalized_address(registry_address),
        'closing_address': to_normalized_address(app0.raiden.address),
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1]['args'],
                                 closed_event)
    assert event_dicts_are_equal(events[0]['args'], closed_event)

    settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 5
    wait_until_block(app0.raiden.chain, settle_expiration)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=channel_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_SETTLED)],
    )

    assert len(all_netting_channel_events) == 3
    assert len(events) == 1

    assert events[0]['event'] == EVENT_CHANNEL_SETTLED
    settled_event = {
        'registry_address': to_normalized_address(registry_address),
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1]['args'],
                                 settled_event)
    assert event_dicts_are_equal(events[0]['args'], settled_event)
Пример #56
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit,
                           transport_config):
    node1, node2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(node1),
        node1.raiden.default_registry.address,
        token_address,
    )

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    registry_address = node1.raiden.default_registry.address

    if transport_config.protocol == TransportProtocol.UDP:
        # nodes don't have a channel, so they are not healthchecking
        assert api1.get_node_network_state(
            api2.address) == NODE_NETWORK_UNKNOWN
        assert api2.get_node_network_state(
            api1.address) == NODE_NETWORK_UNKNOWN
    elif transport_config.protocol == TransportProtocol.MATRIX:
        # with Matrix nodes do not need a health check to know each others reachability
        assert api1.get_node_network_state(
            api2.address) == NODE_NETWORK_UNREACHABLE
        assert api2.get_node_network_state(
            api1.address) == NODE_NETWORK_UNREACHABLE
    assert not api1.get_channel_list(registry_address, token_address,
                                     api2.address)

    # open is a synchronous api
    api1.channel_open(node1.raiden.default_registry.address, token_address,
                      api2.address)
    channels = api1.get_channel_list(registry_address, token_address,
                                     api2.address)
    assert len(channels) == 1

    channel12 = get_channelstate(node1, node2, token_network_identifier)
    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED

    event_list1 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert event_list1 == []

    token_events = api1.get_token_network_events(
        token_address,
        channel12.open_transaction.finished_block_number,
    )
    assert token_events[0]['event'] == EVENT_CHANNEL_NEW

    registry_address = api1.raiden.default_registry.address
    # Load the new state with the deposit
    api1.channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )

    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED
    assert channel.get_balance(channel12.our_state,
                               channel12.partner_state) == deposit
    assert channel12.our_state.contract_balance == deposit
    assert api1.get_channel_list(registry_address, token_address,
                                 api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert any(
        (event['event'] == EVENT_CHANNEL_NEW_BALANCE and is_same_address(
            event['args']['registry_address'],
            to_normalized_address(registry_address),
        ) and is_same_address(
            event['args']['participant'],
            to_normalized_address(api1.address),
        )) for event in event_list2)

    api1.channel_close(registry_address, token_address, api2.address)

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    event_list3 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['event'] == EVENT_CHANNEL_CLOSED and is_same_address(
        event['args']['registry_address'],
        to_normalized_address(registry_address),
    ) and is_same_address(
        event['args']['closing_address'],
        to_normalized_address(api1.address),
    )) for event in event_list3)
    assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.close_transaction.finished_block_number +
        channel12.settle_timeout +
        10  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    # Load the new state with the channel settled
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_SETTLED
Пример #57
0
Файл: app.py Проект: onyb/raiden
def run_app(
        address,
        keystore_path,
        gas_price,
        eth_rpc_endpoint,
        registry_contract_address,
        secret_registry_contract_address,
        discovery_contract_address,
        listen_address,
        mapped_socket,
        max_unresponsive_time,
        api_address,
        rpc,
        sync_check,
        console,
        password_file,
        web_ui,
        datadir,
        transport,
        matrix_server,
        network_id,
        network_type,
        config=None,
        extra_config=None,
        **kwargs,
):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    from raiden.app import App

    _assert_sql_version()

    if transport == 'udp' and not mapped_socket:
        raise RuntimeError('Missing socket')

    if datadir is None:
        datadir = os.path.join(os.path.expanduser('~'), '.raiden')

    address_hex = to_normalized_address(address) if address else None
    address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file)
    address = to_canonical_address(address_hex)

    (listen_host, listen_port) = split_endpoint(listen_address)
    (api_host, api_port) = split_endpoint(api_address)

    config['transport']['udp']['host'] = listen_host
    config['transport']['udp']['port'] = listen_port
    config['console'] = console
    config['rpc'] = rpc
    config['web_ui'] = rpc and web_ui
    config['api_host'] = api_host
    config['api_port'] = api_port
    if mapped_socket:
        config['socket'] = mapped_socket.socket
        config['transport']['udp']['external_ip'] = mapped_socket.external_ip
        config['transport']['udp']['external_port'] = mapped_socket.external_port
    config['transport_type'] = transport
    config['transport']['matrix']['server'] = matrix_server
    config['transport']['udp']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES
    timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES
    config['transport']['udp']['nat_keepalive_timeout'] = timeout

    privatekey_hex = hexlify(privatekey_bin)
    config['privatekey_hex'] = privatekey_hex

    parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint)
    if not parsed_eth_rpc_endpoint.scheme:
        eth_rpc_endpoint = f'http://{eth_rpc_endpoint}'

    web3 = _setup_web3(eth_rpc_endpoint)

    rpc_client = JSONRPCClient(
        web3,
        privatekey_bin,
        gas_price_strategy=gas_price,
    )

    blockchain_service = BlockChainService(privatekey_bin, rpc_client)

    given_numeric_network_id = network_id.value if isinstance(network_id, ChainId) else network_id
    node_numeric_network_id = blockchain_service.network_id
    known_given_network_id = networkid_is_known(given_numeric_network_id)
    known_node_network_id = networkid_is_known(node_numeric_network_id)
    if known_given_network_id:
        given_network_id = ChainId(given_numeric_network_id)
    if known_node_network_id:
        node_network_id = ChainId(node_numeric_network_id)

    if node_numeric_network_id != given_numeric_network_id:
        if known_given_network_id and known_node_network_id:
            click.secho(
                f"The chosen ethereum network '{given_network_id.name.lower()}' "
                f"differs from the ethereum client '{node_network_id.name.lower()}'. "
                "Please update your settings.",
                fg='red',
            )
        else:
            click.secho(
                f"The chosen ethereum network id '{given_numeric_network_id}' differs "
                f"from the ethereum client '{node_numeric_network_id}'. "
                "Please update your settings.",
                fg='red',
            )
        sys.exit(1)

    config['chain_id'] = given_numeric_network_id

    log.debug('Network type', type=network_type)
    if network_type == 'main':
        config['network_type'] = NetworkType.MAIN
        # Forcing private rooms to true for the mainnet
        config['transport']['matrix']['private_rooms'] = True
    else:
        config['network_type'] = NetworkType.TEST

    network_type = config['network_type']
    chain_config = {}
    contract_addresses_known = False
    contract_addresses = dict()
    if node_network_id in ID_TO_NETWORK_CONFIG:
        network_config = ID_TO_NETWORK_CONFIG[node_network_id]
        not_allowed = (
            NetworkType.TEST not in network_config and
            network_type == NetworkType.TEST
        )
        if not_allowed:
            click.secho(
                'The chosen network {} has no test configuration but a test network type '
                'was given. This is not allowed.'.format(
                    ID_TO_NETWORKNAME[node_network_id],
                ),
                fg='red',
            )
            sys.exit(1)

        if network_type in network_config:
            chain_config = network_config[network_type]
            contract_addresses = chain_config['contract_addresses']
            contract_addresses_known = True

    if sync_check:
        check_synced(blockchain_service, known_node_network_id)

    contract_addresses_given = (
        registry_contract_address is not None and
        secret_registry_contract_address is not None and
        discovery_contract_address is not None
    )

    if not contract_addresses_given and not contract_addresses_known:
        click.secho(
            f"There are no known contract addresses for network id '{given_numeric_network_id}'. "
            "Please provide them on the command line or in the configuration file.",
            fg='red',
        )
        sys.exit(1)

    try:
        token_network_registry = blockchain_service.token_network_registry(
            registry_contract_address or contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY],
        )
    except ContractVersionMismatch:
        handle_contract_version_mismatch('token network registry', registry_contract_address)
    except AddressWithoutCode:
        handle_contract_no_code('token network registry', registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address('token network registry', registry_contract_address)

    try:
        secret_registry = blockchain_service.secret_registry(
            secret_registry_contract_address or contract_addresses[CONTRACT_SECRET_REGISTRY],
        )
    except ContractVersionMismatch:
        handle_contract_version_mismatch('secret registry', secret_registry_contract_address)
    except AddressWithoutCode:
        handle_contract_no_code('secret registry', secret_registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address('secret registry', secret_registry_contract_address)

    database_path = os.path.join(
        datadir,
        f'node_{pex(address)}',
        f'netid_{given_numeric_network_id}',
        f'network_{pex(token_network_registry.address)}',
        f'v{RAIDEN_DB_VERSION}_log.db',
    )
    config['database_path'] = database_path

    print(
        '\nYou are connected to the \'{}\' network and the DB path is: {}'.format(
            ID_TO_NETWORKNAME.get(given_network_id, given_numeric_network_id),
            database_path,
        ),
    )

    discovery = None
    if transport == 'udp':
        transport, discovery = _setup_udp(
            config,
            blockchain_service,
            address,
            contract_addresses,
            discovery_contract_address,
        )
    elif transport == 'matrix':
        transport = _setup_matrix(config)
    else:
        raise RuntimeError(f'Unknown transport type "{transport}" given')

    raiden_event_handler = RaidenEventHandler()
    message_handler = MessageHandler()

    try:
        start_block = chain_config.get(START_QUERY_BLOCK_KEY, 0)
        raiden_app = App(
            config=config,
            chain=blockchain_service,
            query_start_block=start_block,
            default_registry=token_network_registry,
            default_secret_registry=secret_registry,
            transport=transport,
            raiden_event_handler=raiden_event_handler,
            message_handler=message_handler,
            discovery=discovery,
        )
    except RaidenError as e:
        click.secho(f'FATAL: {e}', fg='red')
        sys.exit(1)

    try:
        raiden_app.start()
    except RuntimeError as e:
        click.secho(f'FATAL: {e}', fg='red')
        sys.exit(1)
    except filelock.Timeout:
        name_or_id = ID_TO_NETWORKNAME.get(given_network_id, given_numeric_network_id)
        click.secho(
            f'FATAL: Another Raiden instance already running for account {address_hex} on '
            f'network id {name_or_id}',
            fg='red',
        )
        sys.exit(1)

    return raiden_app
Пример #58
0
def run_app(
    address,
    keystore_path,
    gas_price,
    eth_rpc_endpoint,
    tokennetwork_registry_contract_address,
    secret_registry_contract_address,
    service_registry_contract_address,
    endpoint_registry_contract_address,
    user_deposit_contract_address,
    listen_address,
    mapped_socket,
    max_unresponsive_time,
    api_address,
    rpc,
    sync_check,
    console,
    password_file,
    web_ui,
    datadir,
    transport,
    matrix_server,
    network_id,
    environment_type,
    unrecoverable_error_should_crash,
    pathfinding_service_address,
    pathfinding_eth_address,
    pathfinding_max_paths,
    enable_monitoring,
    resolver_endpoint,
    routing_mode,
    config=None,
    extra_config=None,
    **kwargs,
):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    from raiden.app import App

    check_sql_version()

    if transport == "udp" and not mapped_socket:
        raise RuntimeError("Missing socket")

    if datadir is None:
        datadir = os.path.join(os.path.expanduser("~"), ".raiden")

    account_manager = AccountManager(keystore_path)
    check_has_accounts(account_manager)

    if not address:
        address_hex = prompt_account(account_manager)
    else:
        address_hex = to_normalized_address(address)

    if password_file:
        privatekey_bin = unlock_account_with_passwordfile(
            account_manager=account_manager,
            address_hex=address_hex,
            password_file=password_file)
    else:
        privatekey_bin = unlock_account_with_passwordprompt(
            account_manager=account_manager, address_hex=address_hex)

    address = to_canonical_address(address_hex)

    (listen_host, listen_port) = split_endpoint(listen_address)
    (api_host, api_port) = split_endpoint(api_address)

    config["transport"]["udp"]["host"] = listen_host
    config["transport"]["udp"]["port"] = listen_port
    config["console"] = console
    config["rpc"] = rpc
    config["web_ui"] = rpc and web_ui
    config["api_host"] = api_host
    config["api_port"] = api_port
    config["resolver_endpoint"] = resolver_endpoint
    if mapped_socket:
        config["socket"] = mapped_socket.socket
        config["transport"]["udp"]["external_ip"] = mapped_socket.external_ip
        config["transport"]["udp"][
            "external_port"] = mapped_socket.external_port
    config["transport_type"] = transport
    config["transport"]["matrix"]["server"] = matrix_server
    config["transport"]["udp"][
        "nat_keepalive_retries"] = DEFAULT_NAT_KEEPALIVE_RETRIES
    timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES
    config["transport"]["udp"]["nat_keepalive_timeout"] = timeout
    config[
        "unrecoverable_error_should_crash"] = unrecoverable_error_should_crash
    config["services"]["pathfinding_max_paths"] = pathfinding_max_paths
    config["services"]["monitoring_enabled"] = enable_monitoring

    parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint)
    if not parsed_eth_rpc_endpoint.scheme:
        eth_rpc_endpoint = f"http://{eth_rpc_endpoint}"

    web3 = Web3(HTTPProvider(eth_rpc_endpoint))
    check_ethereum_version(web3)
    check_network_id(network_id, web3)
    config["chain_id"] = network_id

    setup_environment(config, environment_type)

    contracts = setup_contracts_or_exit(config, network_id)

    rpc_client = JSONRPCClient(
        web3,
        privatekey_bin,
        gas_price_strategy=gas_price,
        block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
        uses_infura="infura.io" in eth_rpc_endpoint,
    )

    blockchain_service = BlockChainService(jsonrpc_client=rpc_client,
                                           contract_manager=ContractManager(
                                               config["contracts_path"]))

    if sync_check:
        check_synced(blockchain_service)

    proxies = setup_proxies_or_exit(
        config=config,
        tokennetwork_registry_contract_address=
        tokennetwork_registry_contract_address,
        secret_registry_contract_address=secret_registry_contract_address,
        endpoint_registry_contract_address=endpoint_registry_contract_address,
        user_deposit_contract_address=user_deposit_contract_address,
        service_registry_contract_address=service_registry_contract_address,
        blockchain_service=blockchain_service,
        contracts=contracts,
        routing_mode=routing_mode,
        pathfinding_service_address=pathfinding_service_address,
        pathfinding_eth_address=pathfinding_eth_address,
    )

    database_path = os.path.join(
        datadir,
        f"node_{pex(address)}",
        f"netid_{network_id}",
        f"network_{pex(proxies.token_network_registry.address)}",
        f"v{RAIDEN_DB_VERSION}_log.db",
    )
    config["database_path"] = database_path

    print("\nYou are connected to the '{}' network and the DB path is: {}".
          format(ID_TO_NETWORKNAME.get(network_id, network_id), database_path))

    discovery = None
    if transport == "udp":
        transport, discovery = setup_udp_or_exit(
            config, blockchain_service, address, contracts,
            endpoint_registry_contract_address)
    elif transport == "matrix":
        transport = _setup_matrix(config)
    else:
        raise RuntimeError(f'Unknown transport type "{transport}" given')

    raiden_event_handler = RaidenEventHandler()

    message_handler = MessageHandler()

    try:
        start_block = 0
        if "TokenNetworkRegistry" in contracts:
            start_block = contracts["TokenNetworkRegistry"]["block_number"]

        raiden_app = App(
            config=config,
            chain=blockchain_service,
            query_start_block=start_block,
            default_registry=proxies.token_network_registry,
            default_secret_registry=proxies.secret_registry,
            default_service_registry=proxies.service_registry,
            transport=transport,
            raiden_event_handler=raiden_event_handler,
            message_handler=message_handler,
            discovery=discovery,
            user_deposit=proxies.user_deposit,
        )
    except RaidenError as e:
        click.secho(f"FATAL: {e}", fg="red")
        sys.exit(1)

    try:
        raiden_app.start()
    except RuntimeError as e:
        click.secho(f"FATAL: {e}", fg="red")
        sys.exit(1)
    except filelock.Timeout:
        name_or_id = ID_TO_NETWORKNAME.get(network_id, network_id)
        click.secho(
            f"FATAL: Another Raiden instance already running for account {address_hex} on "
            f"network id {name_or_id}",
            fg="red",
        )
        sys.exit(1)

    return raiden_app
Пример #59
0
def login_or_register(
    client: GMatrixClient,
    signer: Signer,
    prev_user_id: str = None,
    prev_access_token: str = None,
) -> User:
    """Login to a Raiden matrix server with password and displayname proof-of-keys

    - Username is in the format: 0x<eth_address>(.<suffix>)?, where the suffix is not required,
    but a deterministic (per-account) random 8-hex string to prevent DoS by other users registering
    our address
    - Password is the signature of the server hostname, verified by the server to prevent account
    creation spam
    - Displayname currently is the signature of the whole user_id (including homeserver), to be
    verified by other peers. May include in the future other metadata such as protocol version

    Params:
        client: GMatrixClient instance configured with desired homeserver
        signer: raiden.utils.signer.Signer instance for signing password and displayname
        prev_user_id: (optional) previous persisted client.user_id. Must match signer's account
        prev_access_token: (optional) previous persistend client.access_token for prev_user_id
    Returns:
        Own matrix_client.User
    """
    server_url = client.api.base_url
    server_name = urlparse(server_url).netloc

    base_username = to_normalized_address(signer.address)
    _match_user = re.match(
        f'^@{re.escape(base_username)}.*:{re.escape(server_name)}$',
        prev_user_id or '',
    )
    if _match_user:  # same user as before
        log.debug('Trying previous user login', user_id=prev_user_id)
        client.set_access_token(user_id=prev_user_id, token=prev_access_token)

        try:
            client.api.get_devices()
        except MatrixRequestError as ex:
            log.debug(
                'Couldn\'t use previous login credentials, discarding',
                prev_user_id=prev_user_id,
                _exception=ex,
            )
        else:
            prev_sync_limit = client.set_sync_limit(0)
            client._sync()  # initial_sync
            client.set_sync_limit(prev_sync_limit)
            log.debug('Success. Valid previous credentials',
                      user_id=prev_user_id)
            return client.get_user(client.user_id)
    elif prev_user_id:
        log.debug(
            'Different server or account, discarding',
            prev_user_id=prev_user_id,
            current_address=base_username,
            current_server=server_name,
        )

    # password is signed server address
    password = encode_hex(signer.sign(server_name.encode()))
    rand = None
    # try login and register on first 5 possible accounts
    for i in range(JOIN_RETRIES):
        username = base_username
        if i:
            if not rand:
                rand = Random(
                )  # deterministic, random secret for username suffixes
                # initialize rand for seed (which requires a signature) only if/when needed
                rand.seed(int.from_bytes(signer.sign(b'seed')[-32:], 'big'))
            username = f'{username}.{rand.randint(0, 0xffffffff):08x}'

        try:
            client.login(username, password, sync=False)
            prev_sync_limit = client.set_sync_limit(0)
            client._sync()  # when logging, do initial_sync with limit=0
            client.set_sync_limit(prev_sync_limit)
            log.debug(
                'Login',
                homeserver=server_name,
                server_url=server_url,
                username=username,
            )
            break
        except MatrixRequestError as ex:
            if ex.code != 403:
                raise
            log.debug(
                'Could not login. Trying register',
                homeserver=server_name,
                server_url=server_url,
                username=username,
            )
            try:
                client.register_with_password(username, password)
                log.debug(
                    'Register',
                    homeserver=server_name,
                    server_url=server_url,
                    username=username,
                )
                break
            except MatrixRequestError as ex:
                if ex.code != 400:
                    raise
                log.debug('Username taken. Continuing')
                continue
    else:
        raise ValueError('Could not register or login!')

    name = encode_hex(signer.sign(client.user_id.encode()))
    user = client.get_user(client.user_id)
    user.set_display_name(name)
    return user
Пример #60
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit,
                           transport_config):
    node1, node2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(node1),
        node1.raiden.default_registry.address,
        token_address,
    )

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    registry_address = node1.raiden.default_registry.address

    # nodes don't have a channel, so they are not healthchecking
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN
    assert not api1.get_channel_list(registry_address, token_address,
                                     api2.address)

    # open is a synchronous api
    api1.channel_open(node1.raiden.default_registry.address, token_address,
                      api2.address)
    channels = api1.get_channel_list(registry_address, token_address,
                                     api2.address)
    assert len(channels) == 1

    channel12 = get_channelstate(node1, node2, token_network_identifier)
    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED

    event_list1 = api1.get_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any((event['event'] == ChannelEvent.OPENED and is_same_address(
        event['args']['participant1'],
        to_normalized_address(api1.address),
    ) and is_same_address(
        event['args']['participant2'],
        to_normalized_address(api2.address),
    )) for event in event_list1)

    token_events = api1.get_blockchain_events_token_network(token_address, )
    assert token_events[0]['event'] == ChannelEvent.OPENED

    registry_address = api1.raiden.default_registry.address
    # Load the new state with the deposit
    api1.set_total_channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )

    # let's make sure it's idempotent. Same deposit should raise deposit mismatch limit
    with pytest.raises(DepositMismatch):
        api1.set_total_channel_deposit(
            registry_address,
            token_address,
            api2.address,
            deposit,
        )

    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED
    assert channel.get_balance(channel12.our_state,
                               channel12.partner_state) == deposit
    assert channel12.our_state.contract_balance == deposit
    assert api1.get_channel_list(registry_address, token_address,
                                 api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any((event['event'] == ChannelEvent.DEPOSIT and is_same_address(
        event['args']['participant'],
        to_normalized_address(api1.address),
    ) and event['args']['total_deposit'] == deposit) for event in event_list2)

    api1.channel_close(registry_address, token_address, api2.address)

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    event_list3 = api1.get_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['event'] == ChannelEvent.CLOSED and is_same_address(
        event['args']['closing_participant'],
        to_normalized_address(api1.address),
    )) for event in event_list3)
    assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.close_transaction.finished_block_number +
        channel12.settle_timeout +
        10  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    state_changes = node1.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    assert must_contain_entry(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel12.identifier,
        })