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)
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
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), ) )
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
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)
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), }
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)
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()
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
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
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
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
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)
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()))
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()
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")
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
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), }
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
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)
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)
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.')
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 []
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, }, )
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), ))
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
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
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))
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)
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
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
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)
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
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)
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)
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 []
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]
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)
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
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()
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)
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()
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()
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)
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
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)
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), }
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
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" ))
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
def __init__(self, address): if isinstance(address, Address): self.address = address.address else: self.address = eth_utils.to_normalized_address(address)
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
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())
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)
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
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
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
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
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, })