def test_get_status(): failed_status = TransactionExecutionStatus( finished_block_number=10, result=TransactionExecutionStatus.FAILURE) close_failed = factories.create( factories.NettingChannelStateProperties( close_transaction=failed_status)) assert get_status(close_failed) == ChannelState.STATE_UNUSABLE settle_failed = factories.create( factories.NettingChannelStateProperties( settle_transaction=failed_status)) assert get_status(settle_failed) == ChannelState.STATE_UNUSABLE
def test_handle_block_closed_channel(): channel_state = factories.create( factories.NettingChannelStateProperties( close_transaction=TransactionExecutionStatus( finished_block_number=50, result=TransactionExecutionStatus.SUCCESS), settle_timeout=50, )) pseudo_random_generator = random.Random() block = Block(block_number=90, gas_limit=100000, block_hash=factories.make_block_hash()) before_settle = handle_block( channel_state=channel_state, state_change=block, block_number=block.block_number, pseudo_random_generator=pseudo_random_generator, ) assert get_status(before_settle.new_state) == ChannelState.STATE_CLOSED assert not before_settle.events block = Block(block_number=102, gas_limit=100000, block_hash=factories.make_block_hash()) after_settle = handle_block( channel_state=before_settle.new_state, state_change=block, block_number=block.block_number, pseudo_random_generator=pseudo_random_generator, ) assert get_status(after_settle.new_state) == ChannelState.STATE_SETTLING assert after_settle.events
def test_get_batch_unlock_gain(): channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state = replace( channel_state.our_state, secrethashes_to_lockedlocks={ factories.make_keccak_hash(): make_hash_time_lock_state(1), factories.make_keccak_hash(): make_hash_time_lock_state(2), }, secrethashes_to_unlockedlocks={ factories.make_keccak_hash(): make_unlock_partial_proof_state(4) }, secrethashes_to_onchain_unlockedlocks={ factories.make_keccak_hash(): make_unlock_partial_proof_state(8) }, ) channel_state.partner_state = replace( channel_state.partner_state, secrethashes_to_lockedlocks={ factories.make_keccak_hash(): make_hash_time_lock_state(16) }, secrethashes_to_unlockedlocks={ factories.make_keccak_hash(): make_unlock_partial_proof_state(32) }, secrethashes_to_onchain_unlockedlocks={ factories.make_keccak_hash(): make_unlock_partial_proof_state(64), factories.make_keccak_hash(): make_unlock_partial_proof_state(128), }, ) unlock_gain = get_batch_unlock_gain(channel_state) assert unlock_gain.from_partner_locks == 192 assert unlock_gain.from_our_locks == 7
def make_from_route_from_counter(counter): from_channel = factories.create( factories.NettingChannelStateProperties( canonical_identifier=factories.make_canonical_identifier(), token_address=factories.make_token_address(), partner_state=factories.NettingChannelEndStateProperties( balance=next(counter), address=factories.HOP1), )) from_hop = factories.make_hop_from_channel(from_channel) expiration = BlockExpiration(factories.UNIT_REVEAL_TIMEOUT + 1) from_transfer = factories.make_signed_transfer_for( from_channel, factories.LockedTransferSignedStateProperties( transferred_amount=TokenAmount(0), canonical_identifier=factories.make_canonical_identifier( token_network_address=from_channel.token_network_address), amount=TokenAmount(1), expiration=expiration, secret=sha3(factories.make_secret(next(counter))), initiator=factories.make_initiator_address(), target=factories.make_target_address(), payment_identifier=next(counter), sender=factories.HOP1, pkey=factories.HOP1_KEY, ), ) return from_hop, from_transfer
def test_target_task_view(): """Same as above for target tasks.""" secret = factories.make_secret() transfer = factories.create( factories.LockedTransferSignedStateProperties(secret=secret)) secrethash = transfer.lock.secrethash mediator = factories.make_address() mediator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=mediator, balance=TokenAmount(100)))) transfer_state = TargetTransferState( from_hop=HopState( channel_identifier=mediator_channel.canonical_identifier. channel_identifier, node_address=mediator, ), transfer=transfer, secret=secret, ) task = TargetTask( canonical_identifier=mediator_channel.canonical_identifier, target_state=transfer_state) payment_mapping = {secrethash: cast(TransferTask, task)} view = transfer_tasks_view(payment_mapping) assert len(view) == 1 pending_transfer = view[0] assert pending_transfer.get("role") == "target" # pylint: disable=no-member assert pending_transfer.get("locked_amount") == str( transfer.balance_proof.locked_amount) assert pending_transfer.get("payment_identifier") == str( transfer.payment_identifier)
def netting_channel_state(chain_state, token_network_state, token_network_registry_state, partner): if partner is None: partner = factories.make_address() canonical_identifier = factories.make_canonical_identifier( token_network_address=token_network_state.address) channel_state = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=TokenAmount(10), address=chain_state.our_address), partner_state=factories.NettingChannelEndStateProperties( balance=TokenAmount(10), address=partner), token_address=token_network_state.token_address, token_network_registry_address=token_network_registry_state. address, canonical_identifier=canonical_identifier, )) channel_id = canonical_identifier.channel_identifier token_network_state.partneraddresses_to_channelidentifiers[partner].append( channel_id) token_network_state.channelidentifiers_to_channels[ channel_id] = channel_state return channel_state
def test_fee_update(): channel_state = factories.create(factories.NettingChannelStateProperties()) message = PFSFeeUpdate.from_channel_state(channel_state) message.sign(signer) assert message == DictSerializer.deserialize( DictSerializer.serialize(message))
def test_mediator_task_view(): """Same as above for mediator tasks.""" secret1 = factories.make_secret(1) locked_amount1 = 11 payee_transfer = factories.create( factories.LockedTransferUnsignedStateProperties(secret=secret1)) payer_transfer = factories.create( factories.LockedTransferSignedStateProperties( secret=secret1, payment_identifier=1, locked_amount=locked_amount1)) secrethash1 = payee_transfer.lock.secrethash initiator = payee_transfer.initiator initiator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=initiator, balance=100))) routes = [factories.make_route_from_channel(initiator_channel)] transfer_state1 = MediatorTransferState(secrethash=secrethash1, routes=routes) transfer_state1.transfers_pair.append( MediationPairState( payer_transfer=payer_transfer, payee_transfer=payee_transfer, payee_address=payee_transfer.target, )) task1 = MediatorTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state1, ) secret2 = factories.make_secret(2) locked_amount2 = 13 transfer2 = factories.create( factories.LockedTransferSignedStateProperties( secret=secret2, payment_identifier=2, locked_amount=locked_amount2)) secrethash2 = transfer2.lock.secrethash transfer_state2 = MediatorTransferState(secrethash=secrethash2, routes=routes) transfer_state2.waiting_transfer = WaitingTransferState(transfer=transfer2) task2 = MediatorTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state2, ) payment_mapping = {secrethash1: task1, secrethash2: task2} view = transfer_tasks_view(payment_mapping) assert len(view) == 2 if view[0].get("payment_identifier") == "1": pending_transfer, waiting_transfer = view else: waiting_transfer, pending_transfer = view assert pending_transfer.get("role") == waiting_transfer.get( "role") == "mediator" assert pending_transfer.get("payment_identifier") == "1" assert waiting_transfer.get("payment_identifier") == "2" assert pending_transfer.get("locked_amount") == str(locked_amount1) assert waiting_transfer.get("locked_amount") == str(locked_amount2)
def test_target_task_view(): """Same as above for target tasks.""" secret = factories.make_secret() transfer = factories.create( factories.LockedTransferSignedStateProperties(secret=secret)) secrethash = transfer.lock.secrethash mediator = factories.make_address() mediator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=mediator, balance=100))) transfer_state = TargetTransferState(route=None, transfer=transfer, secret=secret) task = TargetTask( canonical_identifier=mediator_channel.canonical_identifier, target_state=transfer_state) payment_mapping = {secrethash: task} view = transfer_tasks_view(payment_mapping) assert len(view) == 1 pending_transfer = view[0] assert pending_transfer.get("role") == "target" assert pending_transfer.get("locked_amount") == str( transfer.balance_proof.locked_amount) assert pending_transfer.get("payment_identifier") == str( transfer.payment_identifier)
def test_target_task_view(): """Same as above for target tasks.""" secret = factories.make_secret() transfer = factories.create( factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties(secret=secret), )) secrethash = transfer.lock.secrethash mediator = factories.make_address() mediator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=mediator, balance=100), )) transfer_state = TargetTransferState(route=None, transfer=transfer, secret=secret) task = TargetTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, channel_identifier=mediator_channel.identifier, target_state=transfer_state, ) payment_mapping = {secrethash: task} view = transfer_tasks_view(payment_mapping) assert len(view) == 1 pending_transfer = view[0] assert pending_transfer.get('role') == 'target' assert pending_transfer.get('locked_amount') == str( transfer.balance_proof.locked_amount) assert pending_transfer.get('payment_identifier') == str( transfer.payment_identifier)
def test_events_for_onchain_secretreveal_with_unfit_channels(): settle = factories.TransactionExecutionStatusProperties() settled = factories.create( factories.NettingChannelStateProperties(settle_transaction=settle)) secret = factories.UNIT_SECRET block_hash = factories.make_block_hash() events = events_for_onchain_secretreveal(settled, secret, 10, block_hash) assert not events, "Secret reveal event should not be generated for settled channel" settle = factories.replace(settle, result=TransactionExecutionStatus.FAILURE) unusable = factories.create( factories.NettingChannelStateProperties(settle_transaction=settle)) events = events_for_onchain_secretreveal(unusable, secret, 10, block_hash) assert not events, "Secret reveal event should not be generated for unusable channel."
def test_pfs_global_messages( local_matrix_servers, private_rooms, retry_interval, retries_before_backoff, monkeypatch, global_rooms, ): """ Test that RaidenService sends UpdatePFS messages to global PATH_FINDING_BROADCASTING_ROOM room on newly received balance proofs. """ transport = MatrixTransport({ "global_rooms": global_rooms, # FIXME: #3735 "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) pfs_room_name = make_room_alias(transport.network_id, PATH_FINDING_BROADCASTING_ROOM) pfs_room = transport._global_rooms.get(pfs_room_name) assert isinstance(pfs_room, Room) pfs_room.send_text = MagicMock(spec=pfs_room.send_text) raiden_service.transport = transport transport.log = MagicMock() balance_proof = factories.create(HOP1_BALANCE_PROOF) channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof monkeypatch.setattr( raiden.transfer.views, "get_channelstate_by_canonical_identifier", lambda *a, **kw: channel_state, ) update_path_finding_service_from_balance_proof( raiden=raiden_service, chain_state=None, new_balance_proof=balance_proof) gevent.idle() with gevent.Timeout(2): while pfs_room.send_text.call_count < 1: gevent.idle() assert pfs_room.send_text.call_count == 1 transport.stop() transport.get()
def test_set_settled(): channel = factories.create( factories.NettingChannelStateProperties( settle_transaction=TransactionExecutionStatus( finished_block_number=None, result=None))) assert get_status(channel) == ChannelState.STATE_SETTLING set_settled(channel, block_number=100) assert get_status(channel) == ChannelState.STATE_SETTLED
def channel_properties(our_address, token_network_state): partner_privkey, address = factories.make_privkey_address() properties = factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties(balance=80, address=our_address), partner_state=factories.NettingChannelEndStateProperties(balance=80, address=address), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address ), ) return properties, partner_privkey
def test_get_state_change_with_transfer_by_secrethash(): serializer = JSONSerializer() storage = SerializedSQLiteStorage(":memory:", serializer) mediator_secret, mediator_secrethash = factories.make_secret_with_hash() channels = factories.mediator_make_channel_pair() mediator_transfer = factories.create( factories.LockedTransferSignedStateProperties( secret=mediator_secret, target=channels.partner_address(1), initiator=channels.partner_address(0), ) ) mediator_state_change = factories.mediator_make_init_action(channels, mediator_transfer) target_secret, target_secrethash = factories.make_secret_with_hash() from_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( balance=100, address=factories.make_address() ) ) ) target_transfer = factories.create( factories.LockedTransferSignedStateProperties( secret=target_secret, target=channels.our_address(0), initiator=channels.partner_address(1), ) ) target_state_change = ActionInitTarget( from_hop=HopState( node_address=from_channel.partner_state.address, channel_identifier=from_channel.canonical_identifier.channel_identifier, ), transfer=target_transfer, balance_proof=target_transfer.balance_proof, sender=target_transfer.balance_proof.sender, # pylint: disable=no-member ) assert storage.count_state_changes() == 0 storage.write_state_changes([mediator_state_change, target_state_change]) assert storage.count_state_changes() == 2 restored = get_state_change_with_transfer_by_secrethash(storage, mediator_secrethash) assert isinstance(restored.data, ActionInitMediator) assert restored.data.from_transfer == mediator_transfer restored = get_state_change_with_transfer_by_secrethash(storage, target_secrethash) assert isinstance(restored.data, ActionInitTarget) assert restored.data.transfer == target_transfer
def test_get_capacity(): our_state = factories.create( factories.NettingChannelEndStateProperties(balance=TokenAmount(100))) channel_state = factories.create( factories.NettingChannelStateProperties( our_state=our_state, partner_state=factories.NettingChannelEndStateProperties( balance=TokenAmount(50)), )) assert channel.get_capacity(channel_state) == 150 channel_state.our_state = replace(our_state, onchain_total_withdraw=50) assert channel.get_capacity(channel_state) == 100
def test_update_pfs(): properties = factories.BalanceProofSignedStateProperties(pkey=PRIVKEY) balance_proof = factories.create(properties) channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof message = UpdatePFS.from_channel_state(channel_state=channel_state) assert message.signature == b"" privkey2, address2 = factories.make_privkey_address() signer2 = LocalSigner(privkey2) message.sign(signer2) assert recover(message._data_to_sign(), message.signature) == address2 assert message == UpdatePFS.from_dict(message.to_dict())
def test_update_pfs(): properties = factories.BalanceProofSignedStateProperties(pkey=PRIVKEY) balance_proof = factories.create(properties) channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof message = PFSCapacityUpdate.from_channel_state(channel_state=channel_state) assert message.signature == EMPTY_SIGNATURE privkey2, address2 = factories.make_privkey_address() signer2 = LocalSigner(privkey2) message.sign(signer2) assert recover(message._data_to_sign(), message.signature) == address2 assert message == DictSerializer.deserialize(DictSerializer.serialize(message))
def test_update_fee_schedule_after_balance_change(): channel_state = factories.create( factories.NettingChannelStateProperties( our_state=NettingChannelEndStateProperties(balance=100), partner_state=NettingChannelEndStateProperties(balance=0), ) ) fee_config = prepare_mediation_fee_config( cli_token_to_flat_fee=(), cli_token_to_proportional_fee=(), cli_token_to_proportional_imbalance_fee=((channel_state.token_address, 50_000),), # 5% cli_cap_mediation_fees=True, ) update_fee_schedule_after_balance_change(channel_state, fee_config) assert channel_state.fee_schedule.imbalance_penalty[0] == (0, 5)
def new_channel(self): """Create a new partner address with private key and channel. The private key and channels are listed in the instance's dictionaries, the address is returned and should be added to the partners Bundle. """ partner_privkey, partner_address = factories.make_privkey_address() self.address_to_privkey[partner_address] = partner_privkey self.address_to_channel[partner_address] = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=1000, address=self.address), partner_state=factories.NettingChannelEndStateProperties( balance=1000, address=partner_address), canonical_identifier=factories.make_canonical_identifier( token_network_address=self.token_network_address), )) return partner_address
def test_update_channel_reveal_timeout(): pseudo_random_generator = random.Random() channel_state = factories.create( factories.NettingChannelStateProperties(settle_timeout=500, reveal_timeout=50)) invalid_reveal_timeout = 260 valid_reveal_timeout = 250 set_reveal_timeout = ActionChannelSetRevealTimeout( canonical_identifier=channel_state.canonical_identifier, reveal_timeout=invalid_reveal_timeout, ) iteration = channel.state_transition( channel_state=channel_state, state_change=set_reveal_timeout, block_number=1, block_hash=make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) assert iteration.new_state == channel_state assert isinstance(iteration.events[0], EventInvalidActionSetRevealTimeout) set_reveal_timeout = ActionChannelSetRevealTimeout( canonical_identifier=channel_state.canonical_identifier, reveal_timeout=250) iteration = channel.state_transition( channel_state=channel_state, state_change=set_reveal_timeout, block_number=1, block_hash=make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) assert iteration.new_state.reveal_timeout == valid_reveal_timeout
def test_pfs_broadcast_messages( local_matrix_servers, retry_interval_initial, retry_interval_max, retries_before_backoff, monkeypatch, broadcast_rooms, route_mode, ): """ Test that RaidenService broadcasts PFSCapacityUpdate messages to PATH_FINDING_BROADCASTING_ROOM room on newly received balance proofs. """ transport = MatrixTransport( config=MatrixTransportConfig( broadcast_rooms=broadcast_rooms, retries_before_backoff=retries_before_backoff, retry_interval_initial=retry_interval_initial, retry_interval_max=retry_interval_max, server=local_matrix_servers[0], available_servers=[local_matrix_servers[0]], ), environment=Environment.DEVELOPMENT, ) transport._client.api.retry_timeout = 0 transport._send_raw = MagicMock() raiden_service = MockRaidenService(None) raiden_service.config.services.monitoring_enabled = True raiden_service.routing_mode = route_mode transport.start(raiden_service, [], None) pfs_room_name = make_room_alias(transport.chain_id, PATH_FINDING_BROADCASTING_ROOM) pfs_room = transport._broadcast_rooms.get(pfs_room_name) assert isinstance(pfs_room, Room) pfs_room.send_text = MagicMock(spec=pfs_room.send_text) raiden_service.transport = transport transport.log = MagicMock() # send PFSCapacityUpdate balance_proof = factories.create(HOP1_BALANCE_PROOF) channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof monkeypatch.setattr( raiden.transfer.views, "get_channelstate_by_canonical_identifier", lambda *a, **kw: channel_state, ) send_pfs_update(raiden=raiden_service, canonical_identifier=balance_proof.canonical_identifier) gevent.idle() with gevent.Timeout(2): while pfs_room.send_text.call_count < 1: gevent.idle() assert pfs_room.send_text.call_count == 1 # send PFSFeeUpdate channel_state = factories.create(factories.NettingChannelStateProperties()) fee_update = PFSFeeUpdate.from_channel_state(channel_state) fee_update.sign(raiden_service.signer) raiden_service.transport.broadcast(PATH_FINDING_BROADCASTING_ROOM, fee_update) with gevent.Timeout(2): while pfs_room.send_text.call_count < 2: gevent.idle() assert pfs_room.send_text.call_count == 2 msg_data = json.loads(pfs_room.send_text.call_args[0][0]) assert msg_data["type"] == "PFSFeeUpdate" transport.stop() transport.greenlet.get()
def test_monitoring_broadcast_messages( local_matrix_servers, retry_interval_initial, retry_interval_max, retries_before_backoff, monkeypatch, broadcast_rooms, ): """ Test that RaidenService broadcast RequestMonitoring messages to MONITORING_BROADCASTING_ROOM room on newly received balance proofs. """ transport = MatrixTransport( config=MatrixTransportConfig( broadcast_rooms=broadcast_rooms + [MONITORING_BROADCASTING_ROOM], retries_before_backoff=retries_before_backoff, retry_interval_initial=retry_interval_initial, retry_interval_max=retry_interval_max, server=local_matrix_servers[0], available_servers=[local_matrix_servers[0]], ), environment=Environment.DEVELOPMENT, ) transport._client.api.retry_timeout = 0 transport._send_raw = MagicMock() raiden_service = MockRaidenService(None) raiden_service.config = RaidenConfig( chain_id=1234, environment_type=Environment.DEVELOPMENT, services=ServiceConfig(monitoring_enabled=True), ) transport.start(raiden_service, [], None) ms_room_name = make_room_alias(transport.chain_id, MONITORING_BROADCASTING_ROOM) ms_room = transport._broadcast_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 = factories.create(HOP1_BALANCE_PROOF) channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof monkeypatch.setattr( raiden.transfer.views, "get_channelstate_by_canonical_identifier", lambda *a, **kw: channel_state, ) monkeypatch.setattr(raiden.transfer.channel, "get_balance", lambda *a, **kw: 123) raiden_service.user_deposit.effective_balance.return_value = MONITORING_REWARD update_monitoring_service_from_balance_proof( raiden=raiden_service, chain_state=None, new_balance_proof=balance_proof, non_closing_participant=HOP1, ) gevent.idle() with gevent.Timeout(2): while ms_room.send_text.call_count < 1: gevent.idle() assert ms_room.send_text.call_count == 1 transport.stop() transport.greenlet.get()
def test_mediator_task_view(): """Same as above for mediator tasks.""" secret1 = factories.make_secret(1) locked_amount1 = TokenAmount(11) payee_transfer = factories.create( factories.LockedTransferUnsignedStateProperties(secret=secret1)) payer_transfer = factories.create( factories.LockedTransferSignedStateProperties( secret=secret1, payment_identifier=PaymentID(1), locked_amount=locked_amount1)) secrethash1 = payee_transfer.lock.secrethash initiator = payee_transfer.initiator initiator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=initiator, balance=TokenAmount(100)))) route_state = RouteState( route=[payee_transfer.target], forward_channel_id=initiator_channel.canonical_identifier. channel_identifier, ) transfer_state1 = MediatorTransferState(secrethash=secrethash1, routes=[route_state]) # pylint: disable=E1101 transfer_state1.transfers_pair.append( MediationPairState( payer_transfer=payer_transfer, payee_transfer=payee_transfer, payee_address=payee_transfer.target, )) task1 = MediatorTask( token_network_address=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state1) secret2 = factories.make_secret(2) locked_amount2 = TokenAmount(13) transfer2 = factories.create( factories.LockedTransferSignedStateProperties( secret=secret2, payment_identifier=PaymentID(2), locked_amount=locked_amount2)) secrethash2 = transfer2.lock.secrethash transfer_state2 = MediatorTransferState(secrethash=secrethash2, routes=[route_state]) transfer_state2.waiting_transfer = WaitingTransferState(transfer=transfer2) task2 = MediatorTask( token_network_address=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state2) payment_mapping = { secrethash1: cast(TransferTask, task1), secrethash2: cast(TransferTask, task2), } view = transfer_tasks_view(payment_mapping) assert len(view) == 2 if view[0].get("payment_identifier") == "1": pending_transfer, waiting_transfer = view else: waiting_transfer, pending_transfer = view assert pending_transfer.get("role") == waiting_transfer.get( "role") == "mediator" assert pending_transfer.get("payment_identifier") == "1" assert waiting_transfer.get("payment_identifier") == "2" assert pending_transfer.get("locked_amount") == str(locked_amount1) assert waiting_transfer.get("locked_amount") == str(locked_amount2)
def test_events_for_onchain_secretreveal_typechecks_secret(): channel = factories.create(factories.NettingChannelStateProperties()) block_hash = factories.make_block_hash() with pytest.raises(ValueError): events_for_onchain_secretreveal(channel, "This is an invalid secret", 10, block_hash)
def test_routing_priority(chain_state, token_network_state, one_to_n_address, our_address): open_block_number = factories.make_block_number() open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() pseudo_random_generator = random.Random() # Create a network with the following topology # # our ----- 1/1 ----> (1) # | | # | | # 2/0 x # | | # v v # (2) ----- x -----> (3) # | | # | | # x x # | | # v v # (4) (4) channel_state1 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=1, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=1, address=address1), )) channel_state2 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=2, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address2), )) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change1, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) channel_new_iteration2 = token_network.state_transition( token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=3), participant1=address2, participant2=address3, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration3 = token_network.state_transition( token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration4 = token_network.state_transition( token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration5 = token_network.state_transition( token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change6 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address2, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) token_network.state_transition( token_network_state=channel_new_iteration5.new_state, state_change=channel_new_state_change6, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) # test routing priority with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, } error_msg, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address3, amount=1, previous_address=None, pfs_config=None, privkey=b"", ) assert routes, error_msg assert routes[0].next_hop_address == address1, error_msg assert routes[1].next_hop_address == address2, error_msg # number of hops overwrites refunding capacity (route over node 2 involves less hops) chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } _, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=1, previous_address=None, pfs_config=None, privkey=b"", ) assert routes[0].next_hop_address == address2 assert routes[1].next_hop_address == address1
def test_routing_issue2663(chain_state, token_network_state, one_to_n_address, our_address): open_block_number = 10 open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() pseudo_random_generator = random.Random() # Create a network with the following topology # # our ----- 50 ----> (1) <------50------ # | | # | | # 100 (4) # | ^ # v | # (2) ----- 100 ---> (3) <-------100--- channel_state1 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=50, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address1), )) channel_state2 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=100, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address2), )) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change1, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) channel_new_iteration2 = token_network.state_transition( token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration2.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=3), participant1=address2, participant2=address3, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration3 = token_network.state_transition( token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration3.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 3 assert len(graph_state.network.edges()) == 3 channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration4 = token_network.state_transition( token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration4.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 4 assert len(graph_state.network.edges()) == 4 channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=5), participant1=address1, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration5 = token_network.state_transition( token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration5.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 5 assert len(graph_state.network.edges()) == 5 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } error_msg, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes1, error_msg assert routes1[0].next_hop_address == address1, error_msg assert routes1[1].next_hop_address == address2, error_msg # test routing with node 2 offline chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.UNREACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } _, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, pfs_config=None, privkey=b"", ) assert routes1[0].next_hop_address == address1 # test routing with node 3 offline # the routing doesn't care as node 3 is not directly connected chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.UNREACHABLE, address4: NetworkState.REACHABLE, } _, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, pfs_config=None, privkey=b"", ) assert routes1[0].next_hop_address == address1 assert routes1[1].next_hop_address == address2 # test routing with node 1 offline chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.UNREACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } _, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address3, amount=50, previous_address=None, pfs_config=None, privkey=b"", ) # right now the channel to 1 gets filtered out as it is offline assert routes1[0].next_hop_address == address2
def test_multiple_channel_states(chain_state, token_network_state, channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() properties, pkey = channel_properties channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = keccak(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) from_hop = factories.make_hop_from_channel(channel_state) init_target = ActionInitTarget( from_hop=from_hop, transfer=mediated_transfer, balance_proof=mediated_transfer.balance_proof, sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 closed_block_hash = factories.make_block_hash() channel_close_state_change = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=factories.make_32bytes(), partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels # Create new channel while the previous one is pending unlock new_channel_properties = factories.create_properties( factories.NettingChannelStateProperties( canonical_identifier=factories.make_canonical_identifier()), defaults=properties, ) new_channel_state = factories.create(new_channel_properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=new_channel_state, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_new_open = channel_new_iteration.new_state ids_to_channels = token_network_state_after_new_open.channelidentifiers_to_channels assert len(ids_to_channels) == 2 assert channel_state.identifier in ids_to_channels
def test_internal_routing_mediation_fees(chain_state, token_network_state, one_to_n_address, our_address): """ Checks that requesting a route for a single-hop transfer will return the route with estimated_fee of zero. """ open_block_number = 10 open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() pseudo_random_generator = random.Random() direct_channel_state = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=50, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address1), )) # create new channels as participant direct_channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=direct_channel_state, block_number=open_block_number, block_hash=open_block_number_hash, ) direct_channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=direct_channel_new_state_change, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) route_new_state_change = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address1, participant2=address2, block_number=open_block_number, block_hash=open_block_number_hash, ) route_new_iteration = token_network.state_transition( token_network_state=direct_channel_new_iteration.new_state, state_change=route_new_state_change, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = route_new_iteration.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, } # Routing to our direct partner would require 0 mediation fees.x _, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address1, amount=50, previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes[0].estimated_fee == 0 # Routing to our address2 through address1 would charge 2% error_msg, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address2, amount=50, previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes, error_msg assert routes[0].estimated_fee == round(INTERNAL_ROUTING_DEFAULT_FEE_PERC * 50), error_msg
def test_mediator_skips_used_routes(): prng = random.Random() block_number = 3 defaults = factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties.OUR_STATE, partner_state=factories.NettingChannelEndStateProperties( balance=UNIT_TRANSFER_AMOUNT), open_transaction=factories.TransactionExecutionStatusProperties( started_block_number=1, finished_block_number=2, result="success"), ) properties = [ factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( privatekey=factories.HOP1_KEY, address=factories.HOP1)), factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( privatekey=factories.HOP2_KEY, address=factories.HOP2)), factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( privatekey=factories.HOP3_KEY, address=factories.HOP3)), ] channels = factories.make_channel_set(properties=properties, number_of_channels=3, defaults=defaults) bob = channels.channels[1].partner_state.address charlie = channels.channels[2].partner_state.address dave = factories.make_address() eric = factories.make_address() locked_transfer = factories.create( factories.LockedTransferSignedStateProperties( expiration=10, routes=[ [ factories.UNIT_OUR_ADDRESS, bob, dave, factories.UNIT_TRANSFER_TARGET ], [ factories.UNIT_OUR_ADDRESS, bob, eric, factories.UNIT_TRANSFER_TARGET ], [ factories.UNIT_OUR_ADDRESS, charlie, eric, factories.UNIT_TRANSFER_TARGET ], ], canonical_identifier=channels.channels[0].canonical_identifier, pkey=factories.HOP1_KEY, sender=factories.HOP1, )) init_action = factories.mediator_make_init_action(channels=channels, transfer=locked_transfer) nodeaddresses_to_networkstates = { channel.partner_state.address: NetworkState.REACHABLE for channel in channels.channels } transition_result = mediator.handle_init( state_change=init_action, channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=nodeaddresses_to_networkstates, pseudo_random_generator=prng, block_number=block_number, ) mediator_state = transition_result.new_state events = transition_result.events assert mediator_state is not None assert events assert len(mediator_state.routes) == 3 assert mediator_state.routes[0].route[1] == bob assert mediator_state.routes[1].route[1] == bob assert mediator_state.routes[2].route[1] == charlie # now we receive a refund from whoever we forwarded to (should be HOP2) assert isinstance(events[-1], SendLockedTransfer) assert events[-1].recipient == factories.HOP2 last_pair = mediator_state.transfers_pair[-1] canonical_identifier = last_pair.payee_transfer.balance_proof.canonical_identifier lock_expiration = last_pair.payee_transfer.lock.expiration payment_identifier = last_pair.payee_transfer.payment_identifier received_transfer = factories.create( factories.LockedTransferSignedStateProperties( expiration=lock_expiration, payment_identifier=payment_identifier, canonical_identifier=canonical_identifier, sender=factories.HOP2, pkey=factories.HOP2_KEY, message_identifier=factories.make_message_identifier(), )) refund_state_change = ReceiveTransferRefund( transfer=received_transfer, balance_proof=received_transfer.balance_proof, sender=received_transfer.balance_proof.sender, # pylint: disable=no-member ) transition_result = mediator.handle_refundtransfer( mediator_state=mediator_state, mediator_state_change=refund_state_change, channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=nodeaddresses_to_networkstates, pseudo_random_generator=prng, block_number=block_number, ) mediator_state = transition_result.new_state events = transition_result.events assert mediator_state is not None assert events assert mediator_state.transfers_pair[-1].payee_address == charlie # now we should have a forward transfer to HOP3 assert isinstance(events[-1], SendLockedTransfer) assert events[-1].recipient == factories.HOP3 # now we will receive a refund from HOP3 last_pair = mediator_state.transfers_pair[-1] canonical_identifier = last_pair.payee_transfer.balance_proof.canonical_identifier lock_expiration = last_pair.payee_transfer.lock.expiration payment_identifier = last_pair.payee_transfer.payment_identifier received_transfer = factories.create( factories.LockedTransferSignedStateProperties( expiration=lock_expiration, payment_identifier=payment_identifier, canonical_identifier=canonical_identifier, sender=factories.HOP3, pkey=factories.HOP3_KEY, message_identifier=factories.make_message_identifier(), )) refund_state_change = ReceiveTransferRefund( transfer=received_transfer, balance_proof=received_transfer.balance_proof, sender=received_transfer.balance_proof.sender, # pylint: disable=no-member ) transition_result = mediator.handle_refundtransfer( mediator_state=mediator_state, mediator_state_change=refund_state_change, channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=nodeaddresses_to_networkstates, pseudo_random_generator=prng, block_number=block_number, ) mediator_state = transition_result.new_state events = transition_result.events assert mediator_state is not None assert events # no other routes available, so refund HOP1 assert isinstance(events[-1], SendRefundTransfer) assert events[-1].recipient == factories.HOP1