def get_capacity_update_message( # pylint: disable=too-many-arguments updating_participant: Address, other_participant: Address, chain_identifier=ChainID(1), channel_identifier=DEFAULT_CHANNEL_ID, token_network_address: TokenNetworkAddress = DEFAULT_TOKEN_NETWORK_ADDRESS, updating_nonce=Nonce(1), other_nonce=Nonce(0), updating_capacity=TA(90), other_capacity=TA(110), reveal_timeout: int = 2, privkey_signer: bytes = PRIVATE_KEY_1, ) -> PFSCapacityUpdate: updatepfs_message = PFSCapacityUpdate( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_identifier, channel_identifier=channel_identifier, token_network_address=token_network_address, ), updating_participant=updating_participant, other_participant=other_participant, updating_nonce=updating_nonce, other_nonce=other_nonce, updating_capacity=updating_capacity, other_capacity=other_capacity, reveal_timeout=reveal_timeout, signature=EMPTY_SIGNATURE, ) updatepfs_message.sign(LocalSigner(privkey_signer)) return updatepfs_message
def test_update_fee(order, pathfinding_service_mock, token_network_model): pathfinding_service_mock.database.insert( "token_network", dict(address=token_network_model.address)) if order == "normal": setup_channel(pathfinding_service_mock, token_network_model) fee_schedule = FeeScheduleState( flat=FeeAmount(1), proportional=int(0.1e9), imbalance_penalty=[(TokenAmount(0), FeeAmount(0)), (TokenAmount(10), FeeAmount(10))], ) fee_update = PFSFeeUpdate( canonical_identifier=CanonicalIdentifier( chain_identifier=ChainID(1), token_network_address=token_network_model.address, channel_identifier=ChannelID(1), ), updating_participant=PARTICIPANT1, fee_schedule=fee_schedule, timestamp=datetime.now(timezone.utc), signature=EMPTY_SIGNATURE, ) fee_update.sign(LocalSigner(PARTICIPANT1_PRIVKEY)) pathfinding_service_mock.handle_message(fee_update) if order == "fee_update_befor_channel_open": setup_channel(pathfinding_service_mock, token_network_model) cv = token_network_model.G[PARTICIPANT1][PARTICIPANT2]["view"] for key in ("flat", "proportional", "imbalance_penalty"): assert getattr(cv.fee_schedule_sender, key) == getattr(fee_schedule, key)
def make_params(timestamp: datetime): params = { "sender": sender, "receiver": api_sut.pathfinding_service.address, "timestamp": timestamp.isoformat(), } local_signer = LocalSigner(private_key=decode_hex(privkey)) params["signature"] = encode_hex( local_signer.sign( pack_data( ["address", "address", "string"], [params["sender"], params["receiver"], params["timestamp"]], ) ) ) return params
def make_message(convert_to_hex: bool = False, overwrite_data=None): from matrix_client.room import Room room = Room(None, '!roomID:server') if not overwrite_data: message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=UNIT_SECRETHASH, amount=1, expiration=10, ) message.sign(LocalSigner(HOP1_KEY)) data = message.encode() if convert_to_hex: data = '0x' + data.hex() else: data = json.dumps(message.to_dict()) else: data = overwrite_data event = dict( type='m.room.message', sender=USERID1, content={ 'msgtype': 'm.text', 'body': data, }, ) return room, event
def get_updatepfs_message( updating_participant: Address, other_participant: Address, chain_identifier=ChainID(1), channel_identifier=DEFAULT_CHANNEL_ID, token_network_address: TokenNetworkAddressBytes = DEFAULT_TOKEN_NETWORK_ADDRESS_BYTES, updating_nonce=Nonce(1), other_nonce=Nonce(0), updating_capacity=TokenAmount(90), other_capacity=TokenAmount(110), reveal_timeout: int = 2, mediation_fee: FeeAmount = FeeAmount(0), privkey_signer: bytes = PRIVATE_KEY_1, ) -> UpdatePFS: updatepfs_message = UpdatePFS( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_identifier, channel_identifier=channel_identifier, token_network_address=token_network_address, ), updating_participant=decode_hex(updating_participant), other_participant=decode_hex(other_participant), updating_nonce=updating_nonce, other_nonce=other_nonce, updating_capacity=updating_capacity, other_capacity=other_capacity, reveal_timeout=reveal_timeout, mediation_fee=mediation_fee, ) updatepfs_message.sign(LocalSigner(privkey_signer)) return updatepfs_message
def test_message_identical() -> None: """ Will fail if the messages changed since the committed version If you intend to change the serialized messages, then update the messages on disc (see comment inside test). This test exists only to prevent accidental breaking of compatibility. If many values change in unexpected ways, that might have to do with the pseudo-random initialization of the messages (see random.seed() above). """ signer = LocalSigner(bytes(range(32))) for message in messages: # The messages contain only random signatures. We don't want to test # only the serialization itself, but also prevent accidental changes of # the signature. To do this, we have to create proper signatures. message.sign(signer) filename = os.path.join( os.path.dirname(__file__), "serialized_messages", message.__class__.__name__ + ".json" ) # Uncomment this for one run if you intentionally changed the message # with open(filename, "w") as f: # json_msg = MessageSerializer.serialize(message) # # pretty print for more readable diffs # json_msg = json.dumps(json.loads(json_msg), indent=4, sort_keys=True) # f.write(json_msg) with open(filename) as f: saved_message_dict = JSONSerializer.deserialize(f.read()) # The assert output is more readable when we used dicts than with plain JSON message_dict = JSONSerializer.deserialize(MessageSerializer.serialize(message)) assert message_dict == saved_message_dict
def get_last_iou( url: str, token_network_address: Union[TokenNetworkAddress, TokenNetworkID], sender: Address, receiver: Address, privkey: bytes, ) -> Optional[Dict]: timestamp = datetime.utcnow().isoformat(timespec="seconds") signature_data = sender + receiver + Web3.toBytes(text=timestamp) signature = to_hex(LocalSigner(privkey).sign(signature_data)) try: return (requests.get( f"{url}/api/v1/{to_checksum_address(token_network_address)}/payment/iou", params=dict( sender=to_checksum_address(sender), receiver=to_checksum_address(receiver), timestamp=timestamp, signature=signature, ), timeout=DEFAULT_HTTP_REQUEST_TIMEOUT, ).json().get("last_iou")) except (requests.exceptions.RequestException, ValueError) as e: raise ServiceRequestFailed(str(e))
def _(properties, defaults=None) -> LockedTransferSignedState: defaults = defaults or LOCKED_TRANSFER_SIGNED_STATE_DEFAULTS params = _properties_to_dict(properties, defaults) transfer_params = _properties_to_dict(params.pop('transfer'), defaults.transfer) balance_proof_params = _properties_to_dict( transfer_params.pop('balance_proof'), defaults.transfer.balance_proof, ) lock = Lock( amount=transfer_params.pop('amount'), expiration=transfer_params.pop('expiration'), secrethash=sha3(transfer_params.pop('secret')), ) pkey = params.pop('pkey') signer = LocalSigner(pkey) sender = params.pop('sender') params.update(transfer_params) params.update(balance_proof_params) params['token_network_address'] = params.pop('token_network_identifier') if params['locksroot'] == EMPTY_MERKLE_ROOT: params['locksroot'] = lock.lockhash locked_transfer = LockedTransfer(lock=lock, **params) locked_transfer.sign(signer) assert locked_transfer.sender == sender return lockedtransfersigned_from_message(locked_transfer)
def setup_matrix(self, service_room_suffix: str) -> Tuple[GMatrixClient, Room]: available_servers_url = DEFAULT_MATRIX_KNOWN_SERVERS[Environment.DEVELOPMENT] available_servers = get_matrix_servers(available_servers_url) def _http_retry_delay() -> Iterable[float]: # below constants are defined in raiden.app.App.DEFAULT_CONFIG return udp_utils.timeout_exponential_backoff( DEFAULT_TRANSPORT_RETRIES_BEFORE_BACKOFF, int(DEFAULT_TRANSPORT_MATRIX_RETRY_INTERVAL / 5), int(DEFAULT_TRANSPORT_MATRIX_RETRY_INTERVAL), ) client = make_client( servers=available_servers, http_pool_maxsize=4, http_retry_timeout=40, http_retry_delay=_http_retry_delay, ) try: login_or_register(client, signer=LocalSigner(private_key=decode_hex(self.private_key))) except (MatrixRequestError, ValueError): raise ConnectionError("Could not login/register to matrix.") try: room_name = make_room_alias(self.chain_id, service_room_suffix) monitoring_room = join_global_room( client=client, name=room_name, servers=available_servers ) except (MatrixRequestError, TransportError): raise ConnectionError("Could not join monitoring broadcasting room.") return client, monitoring_room
def make_params(timestamp: datetime): params = { "sender": to_checksum_address(sender), "receiver": to_checksum_address(api_sut.pathfinding_service.address), "timestamp": timestamp.isoformat(), } local_signer = LocalSigner(private_key=decode_hex(privkey)) params["signature"] = encode_hex( local_signer.sign( pack_data( (params["sender"], "address"), (params["receiver"], "address"), (params["timestamp"], "string"), ))) return params
def _(properties, defaults=None) -> LockedTransferSignedState: transfer: LockedTransferSignedStateProperties = create_properties( properties, defaults) params = {key: value for key, value in transfer.__dict__.items()} lock = Lock(amount=transfer.amount, expiration=transfer.expiration, secrethash=sha3(transfer.secret)) pkey = params.pop("pkey") signer = LocalSigner(pkey) sender = params.pop("sender") canonical_identifier = params.pop("canonical_identifier") params["chain_id"] = int(canonical_identifier.chain_identifier) params["channel_identifier"] = int(canonical_identifier.channel_identifier) params[ "token_network_address"] = canonical_identifier.token_network_address if params["locksroot"] == EMPTY_MERKLE_ROOT: params["locksroot"] = lock.lockhash locked_transfer = LockedTransfer(lock=lock, **params) locked_transfer.sign(signer) assert locked_transfer.sender == sender return lockedtransfersigned_from_message(locked_transfer)
def get_fee_update_message( # pylint: disable=too-many-arguments updating_participant: Address, chain_id=ChainID(61), channel_identifier=DEFAULT_CHANNEL_ID, token_network_address: TokenNetworkAddress = DEFAULT_TOKEN_NETWORK_ADDRESS, fee_schedule: FeeScheduleState = FeeScheduleState( cap_fees=True, flat=FeeAmount(1), proportional=ProportionalFeeAmount(1)), timestamp: datetime = datetime.utcnow(), privkey_signer: bytes = PRIVATE_KEY_1, ) -> PFSFeeUpdate: fee_message = PFSFeeUpdate( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, channel_identifier=channel_identifier, token_network_address=token_network_address, ), updating_participant=updating_participant, fee_schedule=fee_schedule, timestamp=timestamp, signature=EMPTY_SIGNATURE, ) fee_message.sign(LocalSigner(privkey_signer)) return fee_message
def get_request_monitoring( self, privkey: str, reward_amount: TokenAmount, monitoring_service_contract_address: Address, ) -> RequestMonitoring: """Returns raiden client's RequestMonitoring object""" non_closing_signer = LocalSigner(decode_hex(privkey)) partner_signed_self = SignedBlindedBalanceProof( channel_identifier=self.channel_identifier, token_network_address=self.token_network_address, nonce=self.nonce, additional_hash=decode_hex(self.additional_hash), chain_id=self.chain_id, signature=self.signature, balance_hash=decode_hex(self.balance_hash), ) request_monitoring = RequestMonitoring( balance_proof=partner_signed_self, reward_amount=reward_amount, signature=EMPTY_SIGNATURE, monitoring_service_contract_address= monitoring_service_contract_address, ) request_monitoring.sign(non_closing_signer) return request_monitoring
def __init__(self, message_handler=None, state_transition=None): self.chain = MockChain(network_id=17, node_address=factories.make_address()) self.private_key, self.address = factories.make_privatekey_address() self.signer = LocalSigner(self.private_key) self.chain.node_address = self.address self.message_handler = message_handler self.user_deposit = Mock() if state_transition is None: state_transition = node.state_transition serializer = JSONSerializer state_manager = StateManager(state_transition, None) storage = SerializedSQLiteStorage(':memory:', serializer) self.wal = WriteAheadLog(state_manager, storage) state_change = ActionInitChain( pseudo_random_generator=random.Random(), block_number=0, block_hash=factories.make_block_hash(), our_address=self.chain.node_address, chain_id=self.chain.network_id, ) self.wal.log_and_dispatch(state_change)
def sign(self, priv_key: str) -> "MonitorRequest": local_signer = LocalSigner(private_key=decode_hex(priv_key)) return MonitorRequest( channel_identifier=self.channel_identifier, token_network_address=self.token_network_address, chain_id=self.chain_id, balance_hash=self.balance_hash, nonce=self.nonce, additional_hash=self.additional_hash, closing_signature=self.closing_signature, reward_amount=self.reward_amount, reward_proof_signature=encode_hex( local_signer.sign(self.packed_reward_proof_data())), non_closing_signature=encode_hex( local_signer.sign(self.packed_non_closing_data())), )
def make_params(timestamp: datetime): params = { 'sender': sender, 'receiver': api_sut.pathfinding_service.address, 'timestamp': timestamp.isoformat(), } local_signer = LocalSigner(private_key=decode_hex(privkey)) params['signature'] = encode_hex( local_signer.sign( pack_data( ['address', 'address', 'string'], [ params['sender'], params['receiver'], params['timestamp'] ], ), )) return params
def get_login(address, password) -> None: path = os.path.expanduser("~/.ethereum/keystore") if sys.platform.startswith("darwin"): path = os.path.expanduser("~/Library/Ethereum/keystore") am = AccountManager(path) signer = LocalSigner(am.get_privkey(to_checksum_address(address), password)) print(f"Username: {to_normalized_address(address)}") print(f"Password:"******"\ttransport {i:02d}:", encode_hex(signer.sign( f"transport{i:02d}.raiden.network".encode())), )
def run_test_receive_secrethashtransfer_unknown(raiden_network, token_addresses): app0 = raiden_network[0] token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) other_key = HOP1_KEY other_signer = LocalSigner(other_key) channel_identifier = make_channel_identifier() amount = 10 refund_transfer_message = make_refund_transfer( payment_identifier=1, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel_identifier, transferred_amount=amount, recipient=app0.raiden.address, locksroot=UNIT_SECRETHASH, amount=amount, secrethash=UNIT_SECRETHASH, ) sign_and_inject(refund_transfer_message, other_signer, app0) unlock = Unlock( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, nonce=1, channel_identifier=channel_identifier, token_network_address=token_network_identifier, transferred_amount=amount, locked_amount=0, locksroot=UNIT_SECRETHASH, secret=UNIT_SECRET, ) sign_and_inject(unlock, other_signer, app0) secret_request_message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=UNIT_SECRETHASH, amount=1, expiration=refund_transfer_message.lock.expiration, ) sign_and_inject(secret_request_message, other_signer, app0) reveal_secret_message = RevealSecret( message_identifier=random.randint(0, UINT64_MAX), secret=UNIT_SECRET, ) sign_and_inject(reveal_secret_message, other_signer, app0)
def update_transfer(self, partner_address: Address, balance_proof: HashedBalanceProof): """Given a valid signed balance proof, this method calls `updateNonClosingBalanceProof` for an open channel """ local_signer = LocalSigner(decode_hex(self.privkey)) serialized = balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) non_closing_data = serialized + decode_hex(balance_proof.signature) non_closing_signature = encode_hex(local_signer.sign(non_closing_data)) self.contract.functions.updateNonClosingBalanceProof( self.partner_to_channel_id[partner_address], partner_address, self.address, balance_proof.balance_hash, balance_proof.nonce, balance_proof.additional_hash, balance_proof.signature, non_closing_signature, ).transact({'from': self.address})
def test_signer_sign_seed_retry(): # Rsk Address 0x6d369723521B4080A19457D5Fdd2194d633B0c3A privkey = decode_hex( '0x51dd3591fb7ce95b0bd77ca14a5236a4989d399c80b8150d3799dd0afcb14282') message = 'seed' # generated with Metamask's web3.personal.sign signature = decode_hex( "0xd5adc7e384a8e080e187a4de4d0a51820a3585f7c44ddf39f32f94ea58a6611b") signer = LocalSigner(privkey) # signer: Signer = LocalSigner(privkey) print(f'SEED SIGNATURE: {encode_hex(signer.sign(message.encode()))}') result = signer.sign(message.encode())[-32:] assert result == signature
def sign(self, priv_key: PrivateKey) -> "MonitorRequest": local_signer = LocalSigner(private_key=priv_key) non_closing_signature = local_signer.sign( self.packed_non_closing_data()) return MonitorRequest( channel_identifier=self.channel_identifier, token_network_address=self.token_network_address, chain_id=self.chain_id, balance_hash=self.balance_hash, nonce=self.nonce, additional_hash=self.additional_hash, closing_signature=self.closing_signature, non_closing_signature=non_closing_signature, reward_amount=self.reward_amount, non_closing_participant=self.non_closing_participant, reward_proof_signature=local_signer.sign( self.packed_reward_proof_data(non_closing_signature)), msc_address=self.msc_address, )
def test_receive_lockedtransfer_invalidsender( raiden_network, token_addresses, deposit, reveal_timeout, ): app0, app1 = raiden_network token_address = token_addresses[0] other_key, other_address = make_privkey_address() token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) lock_amount = 10 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=app0.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(amount=lock_amount, expiration=expiration, secrethash=UNIT_SECRETHASH), target=app0.raiden.address, initiator=other_address, fee=0, ) sign_and_inject( mediated_transfer_message, LocalSigner(other_key), app0, ) assert_synced_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def build_request_monitoring(): signer = LocalSigner(decode_hex(get_random_privkey())) non_closing_signer = LocalSigner(decode_hex(get_random_privkey())) def f(chain_id=1, **kwargs): balance_proof = make_balance_proof(signer=signer, **kwargs) balance_proof.chain_id = chain_id partner_signed_balance_proof = SignedBlindedBalanceProof.from_balance_proof_signed_state( balance_proof) request_monitoring = RequestMonitoring( onchain_balance_proof=partner_signed_balance_proof, reward_amount=TokenAmount(55)) request_monitoring.sign(non_closing_signer) # usually not a property of RequestMonitoring, but added for convenience in these tests request_monitoring.non_closing_signer = to_checksum_address( # type: ignore non_closing_signer.address) return request_monitoring return f
def _(properties: BalanceProofSignedStateProperties, defaults=None) -> BalanceProofSignedState: defaults = defaults or BalanceProofSignedStateProperties.DEFAULTS params = create_properties(properties, defaults).__dict__ signer = LocalSigner(params.pop("pkey")) if params["signature"] is GENERATE: keys = ("transferred_amount", "locked_amount", "locksroot") balance_hash = hash_balance_data(**_partial_dict(params, *keys)) data_to_sign = balance_proof.pack_balance_proof( balance_hash=balance_hash, additional_hash=params["message_hash"], canonical_identifier=params["canonical_identifier"], nonce=params.get("nonce"), ) params["signature"] = signer.sign(data=data_to_sign) return BalanceProofSignedState(**params)
def build_request_monitoring(): signer = LocalSigner(decode_hex(get_random_privkey())) non_closing_signer = LocalSigner(decode_hex(get_random_privkey())) def f(amount=1, nonce=1): balance_proof = make_balance_proof(signer=signer, amount=amount, nonce=nonce) partner_signed_balance_proof = SignedBlindedBalanceProof.from_balance_proof_signed_state( balance_proof, ) request_monitoring = RequestMonitoring( onchain_balance_proof=partner_signed_balance_proof, reward_amount=55, ) request_monitoring.sign(non_closing_signer) request_monitoring.non_closing_signer = to_checksum_address( non_closing_signer.address) return request_monitoring return f
def test_signer_sign(): privkey = sha3(b"secret") # 0x38e959391dD8598aE80d5d6D114a7822A09d313A message = b"message" # generated with Metamask's web3.personal.sign signature = decode_hex( "0x1eff8317c59ab169037f5063a5129bb1bab0299fef0b5621d866b07be59e2c0a" "6a404e88d3360fb58bd13daf577807c2cf9b6b26d80fc929c52e952769a460981c") signer: Signer = LocalSigner(privkey) assert signer.sign(message) == signature
def __init__( self, channel_identifier: ChannelID, token_network_address: TokenNetworkAddress, chain_id: ChainID, nonce: Nonce, additional_hash: AdditionalHash, balance_hash: BalanceHash = None, signature: Signature = None, # these three parameters can be passed instead of `balance_hash` transferred_amount: int = None, locked_amount: int = None, locksroot: str = None, # can be used instead of passing `signature` priv_key: str = None, ) -> None: self.channel_identifier = channel_identifier self.token_network_address = token_network_address self.chain_id = chain_id self.nonce = nonce self.additional_hash = additional_hash if balance_hash is None: assert signature is None balance_hash_data = (transferred_amount, locked_amount, locksroot) assert all(x is not None for x in balance_hash_data) self.balance_hash = encode_hex( Web3.soliditySha3( ['uint256', 'uint256', 'bytes32'], balance_hash_data, )) else: self.balance_hash = balance_hash if signature is None: assert priv_key local_signer = LocalSigner(private_key=decode_hex(priv_key)) self.signature = encode_hex(local_signer.sign( self.serialize_bin())) else: self.signature = signature
def make_message(sign: bool = True) -> Message: message = SecretRequest( message_identifier=make_message_identifier(), payment_identifier=PaymentID(1), secrethash=factories.UNIT_SECRETHASH, amount=PaymentAmount(1), expiration=BlockExpiration(10), signature=EMPTY_SIGNATURE, ) if sign: message.sign(LocalSigner(factories.HOP1_KEY)) return message
def make_message(sign=True): message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=factories.UNIT_SECRETHASH, amount=1, expiration=10, signature=EMPTY_SIGNATURE, ) if sign: message.sign(LocalSigner(factories.HOP1_KEY)) return message
def test_monitoring_global_messages( local_matrix_servers, private_rooms, retry_interval, retries_before_backoff, ): """ Test that RaidenService sends RequestMonitoring messages to global MONITORING_BROADCASTING_ROOM room on newly received balance proofs. """ transport = MatrixTransport({ 'global_rooms': ['discovery', MONITORING_BROADCASTING_ROOM], 'retries_before_backoff': retries_before_backoff, 'retry_interval': retry_interval, 'server': local_matrix_servers[0], 'server_name': local_matrix_servers[0].netloc, 'available_servers': [local_matrix_servers[0]], 'private_rooms': private_rooms, }) transport._client.api.retry_timeout = 0 transport._send_raw = MagicMock() raiden_service = MockRaidenService(None) raiden_service.config = dict(services=dict(monitoring_enabled=True)) transport.start( raiden_service, raiden_service.message_handler, None, ) ms_room_name = make_room_alias(transport.network_id, MONITORING_BROADCASTING_ROOM) ms_room = transport._global_rooms.get(ms_room_name) assert isinstance(ms_room, Room) ms_room.send_text = MagicMock(spec=ms_room.send_text) raiden_service.transport = transport transport.log = MagicMock() balance_proof = make_balance_proof(signer=LocalSigner(HOP1_KEY), amount=1) update_monitoring_service_from_balance_proof( raiden_service, balance_proof, ) gevent.idle() assert ms_room.send_text.call_count == 1 transport.stop() transport.get()